Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2016-01-12 18:09:12 +0300
committerJan Kotas <jkotas@microsoft.com>2016-01-13 02:34:47 +0300
commitc4232511ff688be60494042599eafa259a88b2aa (patch)
treef05d9ee10373e0ea6b4bbfc7d8466c501be1f44e /src/ILCompiler.Compiler
parent53935c508390f886bf54ff2444be3323bf394ce9 (diff)
Proper implementations of JIT helpers
Cleanup C++ glue code related to JIT helpers
Diffstat (limited to 'src/ILCompiler.Compiler')
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs25
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs95
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/JitHelper.cs117
-rw-r--r--src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs2
4 files changed, 159 insertions, 80 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index 7d13484c8..767f00aaa 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -239,29 +239,6 @@ namespace ILCompiler.DependencyAnalysis
objData.EmitShort((short)flags);
}
- private static bool ComputeRequiresAlign8(TypeDesc type)
- {
- if (type.Context.Target.Architecture != TargetArchitecture.ARM)
- {
- return false;
- }
-
- if (type.IsArray)
- {
- var elementType = ((ArrayType)type).ElementType;
- if ((elementType.IsValueType) && ((DefType)elementType).InstanceByteAlignment > 4)
- {
- return true;
- }
- }
- else if (type is DefType && ((DefType)type).InstanceByteAlignment > 4)
- {
- return true;
- }
-
- return false;
- }
-
private void OutputBaseSize(ref ObjectDataBuilder objData)
{
int pointerSize = _type.Context.Target.PointerSize;
@@ -440,7 +417,7 @@ namespace ILCompiler.DependencyAnalysis
flags |= (uint)EETypeRareFlags.HasCctorFlag;
}
- if (ComputeRequiresAlign8(_type))
+ if (EETypeBuilderHelpers.ComputeRequiresAlign8(_type))
{
flags |= (uint)EETypeRareFlags.RequiresAlign8Flag;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
index 02608fbe0..7149a9097 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
@@ -20,8 +20,11 @@ namespace ILCompiler.DependencyAnalysis
switch (Id)
{
case ReadyToRunHelperId.NewHelper:
- encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol((TypeDesc)Target));
- encoder.EmitJMP(factory.ExternSymbol("__allocate_object"));
+ {
+ TypeDesc target = (TypeDesc)Target;
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.ConstructedTypeSymbol(target));
+ encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewObjectHelperForType(target)));
+ }
break;
case ReadyToRunHelperId.VirtualCall:
@@ -40,33 +43,52 @@ namespace ILCompiler.DependencyAnalysis
break;
case ReadyToRunHelperId.IsInstanceOf:
- encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
- encoder.EmitJMP(factory.ExternSymbol("__isinst_class"));
+ {
+ TypeDesc target = (TypeDesc)Target;
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target));
+ encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, false)));
+ }
break;
case ReadyToRunHelperId.CastClass:
- encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
- encoder.EmitJMP(factory.ExternSymbol("__castclass_class"));
+ {
+ TypeDesc target = (TypeDesc)Target;
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol(target));
+ encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetCastingHelperNameForType(target, true)));
+ }
break;
case ReadyToRunHelperId.NewArr1:
- encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.NecessaryTypeSymbol((TypeDesc)Target));
- encoder.EmitJMP(factory.ExternSymbol("__allocate_array"));
+ {
+ TypeDesc target = (TypeDesc)Target;
+
+
+ // TODO: Swap argument order instead
+ // mov arg1, arg0
+ encoder.Builder.EmitByte(0x48);
+ encoder.Builder.EmitShort((short)((encoder.TargetRegister.Arg0 == Register.RCX) ? 0xD18B : 0xF78B));
+
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.NecessaryTypeSymbol(target));
+ encoder.EmitJMP(factory.ExternSymbol(JitHelper.GetNewArrayHelperForType(target)));
+ }
break;
case ReadyToRunHelperId.GetNonGCStaticBase:
- if (!((MetadataType)Target).HasStaticConstructor)
{
- Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase);
- encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol((MetadataType)Target));
- encoder.EmitRET();
- }
- else
- {
- // We need to trigger the cctor before returning the base
- encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target));
- encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol((MetadataType)Target));
- encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
+ MetadataType target = (MetadataType)Target;
+ if (!target.HasStaticConstructor)
+ {
+ Debug.Assert(Id == ReadyToRunHelperId.GetNonGCStaticBase);
+ encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeNonGCStaticsSymbol(target));
+ encoder.EmitRET();
+ }
+ else
+ {
+ // We need to trigger the cctor before returning the base
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target));
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeNonGCStaticsSymbol(target));
+ encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnNonGCStaticBase));
+ }
}
break;
@@ -75,23 +97,26 @@ namespace ILCompiler.DependencyAnalysis
break;
case ReadyToRunHelperId.GetGCStaticBase:
- if (!((MetadataType)Target).HasStaticConstructor)
- {
- encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol((MetadataType)Target));
- AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64);
- encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
- encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
- encoder.EmitRET();
- }
- else
{
- // We need to trigger the cctor before returning the base
- encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol((MetadataType)Target));
- encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol((MetadataType)Target));
- AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64);
- encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
- encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
- encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
+ MetadataType target = (MetadataType)Target;
+ if (!target.HasStaticConstructor)
+ {
+ encoder.EmitLEAQ(encoder.TargetRegister.Result, factory.TypeGCStaticsSymbol(target));
+ AddrMode loadFromRax = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64);
+ encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
+ encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromRax);
+ encoder.EmitRET();
+ }
+ else
+ {
+ // We need to trigger the cctor before returning the base
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg0, factory.TypeCctorContextSymbol(target));
+ encoder.EmitLEAQ(encoder.TargetRegister.Arg1, factory.TypeGCStaticsSymbol(target));
+ AddrMode loadFromRdx = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64);
+ encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
+ encoder.EmitMOV(encoder.TargetRegister.Arg1, ref loadFromRdx);
+ encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnGCStaticBase));
+ }
}
break;
diff --git a/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs b/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
index 4bc8e9515..19cc14483 100644
--- a/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/JitHelper.cs
@@ -9,6 +9,9 @@ using System.Threading.Tasks;
using Internal.TypeSystem;
+using Internal.IL;
+using Internal.Runtime;
+
namespace ILCompiler
{
public enum JitHelperId
@@ -91,44 +94,118 @@ namespace ILCompiler
internal class JitHelper
{
- static public string GetMangledName(JitHelperId id)
+ /// <summary>
+ /// Returns JIT helper entrypoint. JIT helpers can be either implemented by entrypoint with given mangled name or
+ /// by a method in class library.
+ /// </summary>
+ static public void GetEntryPoint(TypeSystemContext context, JitHelperId id, out string mangledName, out MethodDesc methodDesc)
{
+ mangledName = null;
+ methodDesc = null;
+
switch (id)
{
+ case JitHelperId.Throw:
+ mangledName = "RhpThrowEx";
+ break;
+ case JitHelperId.Rethrow:
+ mangledName = "RhpRethrow";
+ break;
+
+ case JitHelperId.Overflow:
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowOverflowException");
+ break;
case JitHelperId.RngChkFail:
- return "__range_check_fail";
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException");
+ break;
+ case JitHelperId.FailFast:
+ mangledName = "__fail_fast"; // TODO: Report stack buffer overrun
+ break;
+ case JitHelperId.ThrowNullRef:
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowNullReferenceException");
+ break;
+ case JitHelperId.ThrowDivZero:
+ methodDesc = context.GetHelperEntryPoint("ThrowHelpers", "ThrowDivideByZeroException");
+ break;
case JitHelperId.WriteBarrier:
- return "RhpAssignRef";
-
+ mangledName = "RhpAssignRef";
+ break;
case JitHelperId.CheckedWriteBarrier:
- return "RhpCheckedAssignRef";
-
+ mangledName = "RhpCheckedAssignRef";
+ break;
case JitHelperId.ByRefWriteBarrier:
- return "RhpByRefAssignRef";
-
- case JitHelperId.Throw:
- return "__throw_exception";
-
- case JitHelperId.FailFast:
- return "__fail_fast";
+ mangledName = "RhpByRefAssignRef";
+ break;
case JitHelperId.NewMultiDimArr:
- return "RhNewMDArray";
+ mangledName = "RhNewMDArray";
+ break;
case JitHelperId.Stelem_Ref:
- return "__stelem_ref";
+ mangledName = "__stelem_ref";
+ break;
case JitHelperId.Ldelema_Ref:
- return "__ldelema_ref";
+ mangledName = "__ldelema_ref";
+ break;
case JitHelperId.MemCpy:
- return "memcpy";
+ mangledName = "memcpy"; // TODO: Null reference handling
+ break;
+ case JitHelperId.MemSet:
+ mangledName = "memset"; // TODO: Null reference handling
+ break;
+
+ case JitHelperId.GetRuntimeTypeHandle: // TODO: Reflection
+ case JitHelperId.GetRuntimeMethodHandle:
+ case JitHelperId.GetRuntimeFieldHandle:
+ mangledName = "__fail_fast";
+ break;
default:
- // TODO: Uncomment once all helpers are implemented
- // throw new NotImplementedException();
- return "__fail_fast";
+ throw new NotImplementedException(id.ToString());
+ }
+ }
+
+ //
+ // These methods are static compiler equivalent of RhGetRuntimeHelperForType
+ //
+ static public string GetNewObjectHelperForType(TypeDesc type)
+ {
+ if (EETypeBuilderHelpers.ComputeRequiresAlign8(type))
+ {
+ if (type.HasFinalizer)
+ return "RhpNewFinalizableAlign8";
+
+ if (type.IsValueType)
+ return "RhpNewFastMisalign";
+
+ return "RhpNewFastAlign8";
}
+
+ if (type.HasFinalizer)
+ return "RhpNewFinalizable";
+
+ return "RhpNewFast";
+ }
+
+ static public string GetNewArrayHelperForType(TypeDesc type)
+ {
+ if (EETypeBuilderHelpers.ComputeRequiresAlign8(type))
+ return "RhpNewArrayAlign8";
+
+ return "RhpNewArray";
+ }
+
+ static public string GetCastingHelperNameForType(TypeDesc type, bool throwing)
+ {
+ if (type.IsSzArray)
+ return throwing ? "RhTypeCast_CheckCastArray" : "RhTypeCast_IsInstanceOfArray";
+
+ if (type.IsInterface)
+ return throwing ? "RhTypeCast_CheckCastInterface" : "RhTypeCast_IsInstanceOfInterface";
+
+ return throwing ? "RhTypeCast_CheckCastClass" : "RhTypeCast_IsInstanceOfClass";
}
}
}
diff --git a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs
index 8a7694787..3d19be767 100644
--- a/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs
+++ b/src/ILCompiler.Compiler/src/CppCodeGen/ILToCppImporter.cs
@@ -611,7 +611,7 @@ namespace Internal.IL
AddTypeReference(type, false);
- Append(opcode == ILOpcode.isinst ? "__isinst_class" : "__castclass_class");
+ Append(opcode == ILOpcode.isinst ? "__isinst" : "__castclass");
Append("(");
Append(value.Value.Name);
Append(", ");