diff --git a/src/Common/src/TypeSystem/Common/TypeSystemHelpers.cs b/src/Common/src/TypeSystem/Common/TypeSystemHelpers.cs index 8da2f8d71aa..bfe3aa03925 100644 --- a/src/Common/src/TypeSystem/Common/TypeSystemHelpers.cs +++ b/src/Common/src/TypeSystem/Common/TypeSystemHelpers.cs @@ -40,6 +40,17 @@ static public MetadataType GetClosestDefType(this TypeDesc type) return type.BaseType; } + static public int GetElementSize(this TypeDesc type) + { + if (type.IsValueType) + { + return ((MetadataType)type).InstanceFieldSize; + } + else + { + return type.Context.Target.PointerSize; + } + } static private MethodDesc FindMethodOnExactTypeWithMatchingTypicalMethod(this TypeDesc type, MethodDesc method) { diff --git a/src/ILToNative/reproNative/common.h b/src/ILToNative/reproNative/common.h index 38e8d08e483..accea2ecaa3 100644 --- a/src/ILToNative/reproNative/common.h +++ b/src/ILToNative/reproNative/common.h @@ -40,7 +40,7 @@ int __initialize_runtime(); void __shutdown_runtime(); extern "C" Object * __allocate_object(MethodTable * pMT); -extern "C" Object * __allocate_array(MethodTable * pMT, size_t elements); +extern "C" Object * __allocate_array(size_t elements, MethodTable * pMT); Object * __allocate_string(int32_t len); __declspec(noreturn) void __throw_exception(void * pEx); Object * __load_string_literal(const char * string); @@ -48,6 +48,7 @@ Object * __load_string_literal(const char * string); extern "C" Object * __castclass_class(void * p, MethodTable * pMT); extern "C" Object * __isinst_class(void * p, MethodTable * pMT); +extern "C" void __range_check_fail(); void __range_check(void * a, size_t elem); Object * __get_commandline_args(int argc, char * argv[]); diff --git a/src/ILToNative/reproNative/main.cpp b/src/ILToNative/reproNative/main.cpp index c1567c9ea1c..e643b29c723 100644 --- a/src/ILToNative/reproNative/main.cpp +++ b/src/ILToNative/reproNative/main.cpp @@ -196,7 +196,7 @@ Object * __allocate_string(int32_t len) #endif } -extern "C" Object * __allocate_array(MethodTable * pMT, size_t elements) +extern "C" Object * __allocate_array(size_t elements, MethodTable * pMT) { #if !USE_MRT alloc_context * acontext = GetThread()->GetAllocContext(); @@ -301,6 +301,11 @@ void ThrowRangeOverflowException() throw 0; } +void __range_check_fail() +{ + ThrowRangeOverflowException(); +} + void __range_check(void * a, size_t elem) { if (elem >= *((size_t*)a + 1)) @@ -310,7 +315,7 @@ void __range_check(void * a, size_t elem) #ifdef CPPCODEGEN Object * __get_commandline_args(int argc, char * argv[]) { - System::Array * p = (System::Array *)__allocate_array(System::String__Array::__getMethodTable(), argc); + System::Array * p = (System::Array *)__allocate_array(argc, System::String__Array::__getMethodTable()); for (int i = 0; i < argc; i++) { diff --git a/src/ILToNative/src/Compiler/AsmWriter.cs b/src/ILToNative/src/Compiler/AsmWriter.cs index 1a80bb48552..7c64a7ec2a5 100644 --- a/src/ILToNative/src/Compiler/AsmWriter.cs +++ b/src/ILToNative/src/Compiler/AsmWriter.cs @@ -91,6 +91,11 @@ void OutputMethodCode(RegisteredMethod m) targetName = ((ReadyToRunHelper)target).MangledName; } else + if (target is JitHelper) + { + targetName = ((JitHelper)target).MangledName; + } + else { // TODO: throw new NotImplementedException(); @@ -228,6 +233,14 @@ void OutputReadyToHelpers() Out.WriteLine("jmp __castclass_class"); break; + case ReadyToRunHelperId.NewArr1: + Out.Write("leaq __EEType_"); + Out.Write(NameMangler.GetMangledTypeName((TypeDesc)helper.Target)); + Out.WriteLine("(%rip), %rdx"); + + Out.WriteLine("jmp __allocate_array"); + break; + case ReadyToRunHelperId.GetNonGCStaticBase: Out.Write("leaq __NonGCStaticBase_"); Out.Write(NameMangler.GetMangledTypeName((TypeDesc)helper.Target)); @@ -254,7 +267,17 @@ void OutputEETypes() Out.Write(NameMangler.GetMangledTypeName(t.Type)); Out.WriteLine(":"); - Out.WriteLine(".int 0, 24"); + if (t.Type.IsArray && ((ArrayType)t.Type).Rank == 1) + { + Out.Write(".word "); + Out.WriteLine(t.Type.GetElementSize()); // m_ComponentSize + Out.WriteLine(".word 4"); // m_flags: IsArray(0x4) + Out.WriteLine(".int 24"); + } + else + { + Out.WriteLine(".int 0, 24"); + } if (t.Type.BaseType != null) { @@ -321,4 +344,4 @@ void OutputVirtualSlots(TypeDesc implType, TypeDesc declType) } } } -} \ No newline at end of file +} diff --git a/src/ILToNative/src/Compiler/Compilation.cs b/src/ILToNative/src/Compiler/Compilation.cs index b4b25e2b50c..f5b87e0808c 100644 --- a/src/ILToNative/src/Compiler/Compilation.cs +++ b/src/ILToNative/src/Compiler/Compilation.cs @@ -403,5 +403,16 @@ public Object GetReadyToRunHelper(ReadyToRunHelperId id, Object target) return helper; } + + Dictionary _jitHelpers = new Dictionary(); + public Object GetJitHelper(JitHelperId id) + { + JitHelper helper; + + if (!_jitHelpers.TryGetValue(id, out helper)) + _jitHelpers.Add(id, helper = new JitHelper(this, id)); + + return helper; + } } } diff --git a/src/ILToNative/src/Compiler/JitHelper.cs b/src/ILToNative/src/Compiler/JitHelper.cs new file mode 100644 index 00000000000..7c86f0815b8 --- /dev/null +++ b/src/ILToNative/src/Compiler/JitHelper.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Internal.TypeSystem; + +namespace ILToNative +{ + public enum JitHelperId + { + RngChkFail, + } + + class JitHelper + { + Compilation _compilation; + + public JitHelper(Compilation compilation, JitHelperId id) + { + _compilation = compilation; + + this.Id = id; + } + + public JitHelperId Id { get; private set; } + + public string MangledName + { + get + { + switch (this.Id) + { + case JitHelperId.RngChkFail: + return "__range_check_fail"; + + default: + throw new NotImplementedException(); + } + } + } + } + +} + diff --git a/src/ILToNative/src/Compiler/ReadyToRunHelper.cs b/src/ILToNative/src/Compiler/ReadyToRunHelper.cs index 9cb87e5aec9..55ace677b0b 100644 --- a/src/ILToNative/src/Compiler/ReadyToRunHelper.cs +++ b/src/ILToNative/src/Compiler/ReadyToRunHelper.cs @@ -14,6 +14,7 @@ namespace ILToNative public enum ReadyToRunHelperId { NewHelper, + NewArr1, VirtualCall, IsInstanceOf, CastClass, @@ -43,6 +44,8 @@ public string MangledName { case ReadyToRunHelperId.NewHelper: return "__NewHelper_" + _compilation.NameMangler.GetMangledTypeName((TypeDesc)this.Target); + case ReadyToRunHelperId.NewArr1: + return "__NewArr1_" + _compilation.NameMangler.GetMangledTypeName((TypeDesc)this.Target); case ReadyToRunHelperId.VirtualCall: return "__VirtualCall_" + _compilation.NameMangler.GetMangledMethodName((MethodDesc)this.Target); case ReadyToRunHelperId.IsInstanceOf: diff --git a/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs b/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs index e9b433d476f..815138fcb9d 100644 --- a/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs +++ b/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs @@ -1779,9 +1779,10 @@ void ImportNewArray(int token) _compilation.MarkAsConstructed(arrayType); Append("__allocate_array("); - Append(_writer.GetCppTypeName(arrayType)); - Append("::__getMethodTable(), "); Append(numElements.Value.Name); + Append(", "); + Append(_writer.GetCppTypeName(arrayType)); + Append("::__getMethodTable()"); Append(")"); Finish(); } diff --git a/src/ILToNative/src/ILToNative.csproj b/src/ILToNative/src/ILToNative.csproj index 1d43710024b..4903746e276 100644 --- a/src/ILToNative/src/ILToNative.csproj +++ b/src/ILToNative/src/ILToNative.csproj @@ -44,6 +44,7 @@ + diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs index a43e18a20f6..02da6b20f70 100644 --- a/src/JitInterface/src/CorInfoImpl.cs +++ b/src/JitInterface/src/CorInfoImpl.cs @@ -203,7 +203,7 @@ void Get_CORINFO_SIG_INFO(MethodDesc method, out CORINFO_SIG_INFO sig) sig.numArgs = (ushort)signature.Length; - sig.args = (CORINFO_ARG_LIST_STRUCT_ * )0; // CORINFO_ARG_LIST_STRUCT_ is argument index + sig.args = (CORINFO_ARG_LIST_STRUCT_*)0; // CORINFO_ARG_LIST_STRUCT_ is argument index // TODO: Shared generic sig.sigInst.classInst = null; @@ -211,7 +211,7 @@ void Get_CORINFO_SIG_INFO(MethodDesc method, out CORINFO_SIG_INFO sig) sig.sigInst.methInst = null; sig.sigInst.methInstCount = 0; - sig.pSig = (byte * )ObjectToHandle(signature); + sig.pSig = (byte*)ObjectToHandle(signature); sig.cbSig = 0; // Not used by the JIT sig.scope = null; // Not used by the JIT sig.token = 0; // Not used by the JIT @@ -246,7 +246,7 @@ void Get_CORINFO_SIG_INFO(TypeDesc[] locals, out CORINFO_SIG_INFO sig) sig.token = 0; // Not used by the JIT } - CorInfoType asCorInfoType(TypeDesc type, out CORINFO_CLASS_STRUCT_* structType) + CorInfoType asCorInfoType(TypeDesc type) { if (type.IsEnum) { @@ -258,20 +258,29 @@ CorInfoType asCorInfoType(TypeDesc type, out CORINFO_CLASS_STRUCT_* structType) Debug.Assert((CorInfoType)TypeFlags.Void == CorInfoType.CORINFO_TYPE_VOID); Debug.Assert((CorInfoType)TypeFlags.Double == CorInfoType.CORINFO_TYPE_DOUBLE); - structType = null; return (CorInfoType)type.Category; } + if (type.IsByRef) + { + return CorInfoType.CORINFO_TYPE_BYREF; + } + if (type.IsValueType) { - structType = ObjectToHandle(type); return CorInfoType.CORINFO_TYPE_VALUECLASS; } - structType = null; return CorInfoType.CORINFO_TYPE_CLASS; } + CorInfoType asCorInfoType(TypeDesc type, out CORINFO_CLASS_STRUCT_* structType) + { + var corInfoType = asCorInfoType(type); + structType = (corInfoType == CorInfoType.CORINFO_TYPE_VALUECLASS) ? ObjectToHandle(type) : null; + return corInfoType; + } + uint getMethodAttribsInternal(MethodDesc method) { CorInfoFlag result = 0; @@ -501,8 +510,12 @@ bool isValidStringRef(IntPtr _this, CORINFO_MODULE_STRUCT_* module, uint metaTOK [return: MarshalAs(UnmanagedType.Bool)] bool shouldEnforceCallvirtRestriction(IntPtr _this, CORINFO_MODULE_STRUCT_* scope) { throw new NotImplementedException(); } + CorInfoType asCorInfoType(IntPtr _this, CORINFO_CLASS_STRUCT_* cls) - { throw new NotImplementedException(); } + { + var type = HandleToObject(cls); + return asCorInfoType(type); + } byte* getClassName(IntPtr _this, CORINFO_CLASS_STRUCT_* cls) { @@ -598,14 +611,7 @@ void LongLifetimeFree(IntPtr _this, void* obj) uint getClassSize(IntPtr _this, CORINFO_CLASS_STRUCT_* cls) { TypeDesc type = HandleToObject(cls); - if (type.IsValueType) - { - return (uint)((MetadataType)type).InstanceFieldSize; - } - else - { - return (uint)type.Context.Target.PointerSize; - } + return (uint)type.GetElementSize(); } uint getClassAlignmentRequirement(IntPtr _this, CORINFO_CLASS_STRUCT_* cls, [MarshalAs(UnmanagedType.Bool)]bool fDoubleAlignHint) @@ -704,6 +710,16 @@ void getReadyToRunHelper(IntPtr _this, ref CORINFO_RESOLVED_TOKEN pResolvedToken pLookup.addr = (void*)ObjectToHandle(_compilation.GetReadyToRunHelper(ReadyToRunHelperId.NewHelper, type)); } break; + case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_NEWARR_1: + { + var type = HandleToObject(pResolvedToken.hClass); + var arrayType = type.Context.GetArrayType(type); + _compilation.AddType(arrayType); + _compilation.MarkAsConstructed(arrayType); + + pLookup.addr = (void*)ObjectToHandle(_compilation.GetReadyToRunHelper(ReadyToRunHelperId.NewArr1, arrayType)); + } + break; case CorInfoHelpFunc.CORINFO_HELP_READYTORUN_ISINSTANCEOF: { var type = HandleToObject(pResolvedToken.hClass); @@ -740,8 +756,12 @@ void classMustBeLoadedBeforeCodeIsRun(IntPtr _this, CORINFO_CLASS_STRUCT_* cls) CORINFO_CLASS_STRUCT_* getBuiltinClass(IntPtr _this, CorInfoClassId classId) { throw new NotImplementedException(); } + CorInfoType getTypeForPrimitiveValueClass(IntPtr _this, CORINFO_CLASS_STRUCT_* cls) - { throw new NotImplementedException(); } + { + return asCorInfoType(HandleToObject(cls)); + } + [return: MarshalAs(UnmanagedType.Bool)] bool canCast(IntPtr _this, CORINFO_CLASS_STRUCT_* child, CORINFO_CLASS_STRUCT_* parent) { throw new NotImplementedException(); } @@ -1036,7 +1056,15 @@ uint getThreadTLSIndex(IntPtr _this, ref void* ppIndirection) SIZE_T* getAddrModuleDomainID(IntPtr _this, CORINFO_MODULE_STRUCT_* module) { throw new NotImplementedException(); } void* getHelperFtn(IntPtr _this, CorInfoHelpFunc ftnNum, ref void* ppIndirection) - { throw new NotImplementedException(); } + { + switch (ftnNum) + { + case CorInfoHelpFunc.CORINFO_HELP_RNGCHKFAIL: + return (void*)ObjectToHandle(_compilation.GetJitHelper(JitHelperId.RngChkFail)); + default: + throw new NotImplementedException(); + } + } void getFunctionEntryPoint(IntPtr _this, CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult, CORINFO_ACCESS_FLAGS accessFlags) { throw new NotImplementedException(); } void getFunctionFixedEntryPoint(IntPtr _this, CORINFO_METHOD_STRUCT_* ftn, ref CORINFO_CONST_LOOKUP pResult)