diff options
author | Jan Kotas <jkotas@microsoft.com> | 2016-01-12 18:09:12 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2016-01-13 02:34:47 +0300 |
commit | c4232511ff688be60494042599eafa259a88b2aa (patch) | |
tree | f05d9ee10373e0ea6b4bbfc7d8466c501be1f44e /src/ILCompiler.Compiler | |
parent | 53935c508390f886bf54ff2444be3323bf394ce9 (diff) |
Proper implementations of JIT helpers
Cleanup C++ glue code related to JIT helpers
Diffstat (limited to 'src/ILCompiler.Compiler')
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(", "); |