From 9b80c26d0aff5d0fcd5ce2e6eddd2c46423a1854 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 19 Dec 2020 14:19:33 -0800 Subject: [PATCH] More const eval progress --- BeefLibs/corlib/src/Compiler.bf | 9 + BeefLibs/corlib/src/Event.bf | 24 +- .../corlib/src/Globalization/CultureInfo.bf | 2 + BeefLibs/corlib/src/Internal.bf | 2 + BeefLibs/corlib/src/NumberFormatter.bf | 27 +- BeefLibs/corlib/src/Object.bf | 7 + BeefLibs/corlib/src/Text/UTF8.bf | 14 +- BeefySysLib/util/Hash.h | 14 +- BeefySysLib/util/Heap.cpp | 2 + IDEHelper/Backend/BeContext.cpp | 5 + IDEHelper/Backend/BeContext.h | 1 + IDEHelper/Backend/BeIRCodeGen.cpp | 31 +- IDEHelper/Backend/BeModule.cpp | 5 +- IDEHelper/Backend/BeModule.h | 26 +- IDEHelper/Compiler/BfCompiler.cpp | 76 +- IDEHelper/Compiler/BfCompiler.h | 9 +- IDEHelper/Compiler/BfContext.cpp | 43 +- IDEHelper/Compiler/BfContext.h | 1 + IDEHelper/Compiler/BfIRBuilder.cpp | 40 +- IDEHelper/Compiler/BfIRBuilder.h | 12 +- IDEHelper/Compiler/BfModule.cpp | 119 +- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 23 + IDEHelper/Compiler/BfResolvedTypeUtils.h | 16 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 10 +- IDEHelper/Compiler/CeMachine.cpp | 1489 +++++++++++++---- IDEHelper/Compiler/CeMachine.h | 126 +- 26 files changed, 1673 insertions(+), 460 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 4d921117..f40ab63a 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -23,7 +23,16 @@ namespace System [LinkName("#CallerExpression")] public static extern String[Int32.MaxValue] CallerExpression; + [LinkName("#ProjectName")] + public static extern String ProjectName; + + [LinkName("#ModuleName")] + public static extern String ModuleName; + [LinkName("#TimeLocal")] public static extern String TimeLocal; + + [LinkName("#IsConstEval")] + public static extern bool IsConstEval; } } diff --git a/BeefLibs/corlib/src/Event.bf b/BeefLibs/corlib/src/Event.bf index 248919d2..dc59fae9 100644 --- a/BeefLibs/corlib/src/Event.bf +++ b/BeefLibs/corlib/src/Event.bf @@ -35,10 +35,8 @@ namespace System if (data == null) return true; - var type = data.GetType(); - if (type == typeof(List)) + if (var list = data as List) { - var list = (List)data; return list.Count == 0; } return false; @@ -54,10 +52,8 @@ namespace System if (data == null) return 0; - var type = data.GetType(); - if (type == typeof(List)) + if (var list = data as List) { - var list = (List)data; return list.Count; } return 1; @@ -105,11 +101,8 @@ namespace System return; } - var type = data.GetType(); - - if (type == typeof(List)) + if (var list = data as List) { - var list = (List)data; list.Add(ownDelegate); } else @@ -125,10 +118,8 @@ namespace System { Object data = Target; - var type = data.GetType(); - if (type == typeof(List)) + if (var list = data as List) { - var list = (List)data; int32 idx = -1; for (int32 i = 0; i < list.Count; i++) if (Delegate.Equals(list[i], compareDelegate)) @@ -193,9 +184,8 @@ namespace System if (mData == 0) return; var data = Target; - if (data.GetType() == typeof(List)) + if (var list = data as List) { - var list = (List)data; for (var dlg in list) delete dlg; } @@ -282,10 +272,8 @@ namespace System if (data == null) return false; - var type = data.GetType(); - if (type == typeof(List)) + if (var list = data as List) { - var list = (List)data; repeat { mIdx++; diff --git a/BeefLibs/corlib/src/Globalization/CultureInfo.bf b/BeefLibs/corlib/src/Globalization/CultureInfo.bf index 21ee0e0d..9e6b9ca0 100644 --- a/BeefLibs/corlib/src/Globalization/CultureInfo.bf +++ b/BeefLibs/corlib/src/Globalization/CultureInfo.bf @@ -83,6 +83,8 @@ namespace System.Globalization { get { + if (Compiler.IsConstEval) + return InitUserDefaultCulture(); if (tlCurrentCulture == null) tlCurrentCulture = CultureInfo.DefaultThreadCurrentCulture ?? CultureInfo.UserDefaultCulture; return tlCurrentCulture; diff --git a/BeefLibs/corlib/src/Internal.bf b/BeefLibs/corlib/src/Internal.bf index 8c7f842e..8255a3e3 100644 --- a/BeefLibs/corlib/src/Internal.bf +++ b/BeefLibs/corlib/src/Internal.bf @@ -127,6 +127,8 @@ namespace System public static T* AllocRawArrayUnmarked(int size) { #if BF_ENABLE_REALTIME_LEAK_CHECK + if (Compiler.IsConstEval) + return new T[size]*(?); // We don't want to use the default mark function because the GC will mark the entire array, // whereas we have a custom marking routine because we only want to mark up to mSize return (T*)Internal.Dbg_RawAlloc(size * strideof(T), &DbgRawAllocData.Unmarked.sRawAllocData); diff --git a/BeefLibs/corlib/src/NumberFormatter.bf b/BeefLibs/corlib/src/NumberFormatter.bf index bd12c457..9b03a7e3 100644 --- a/BeefLibs/corlib/src/NumberFormatter.bf +++ b/BeefLibs/corlib/src/NumberFormatter.bf @@ -109,7 +109,7 @@ namespace System 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 };*/ - private static uint64[2048] MantissaBitsTable = .( + private const uint64[2048] MantissaBitsTable = .( 4556951262222748432UL, 9113902524445496865UL, 1822780504889099373UL, 3645561009778198746UL, 7291122019556397492UL, 14582244039112794984UL, 2916448807822558996UL, 5832897615645117993UL, 11665795231290235987UL, @@ -794,7 +794,7 @@ namespace System 4602094425247528723UL, 9204188850495057447UL, 1840837770099011489UL, 3681675540198022979UL, 7363351080396045958UL); - private static int32[2048] TensExponentTable = .( + private const int32[2048] TensExponentTable = .( -323, -323, -322, -322, -322, -322, -321, -321, -321, -320, -320, -320, -319, -319, -319, -319, -318, -318, -318, -317, -317, -317, -316, -316, -316, -316, -315, -315, -315, -314, -314, -314, -313, -313, -313, -313, @@ -966,9 +966,9 @@ namespace System 284, 284, 284, 285, 285, 285, 286, 286, 286, 286, 287, 287, 287, 288, 288, 288, 289, 289, 289, 289, 290, 290, 290, 291, 291, 291, 292, 292, 292, 293, 293, 293 ); - private static char8[16] DigitLowerTable = .('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - private static char8[16] DigitUpperTable = .('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); - private static int64[19] TenPowersList = .( + private const char8[16] DigitLowerTable = .('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); + private const char8[16] DigitUpperTable = .('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); + private const int64[19] TenPowersList = .( 1L, 10L, 100L, @@ -991,7 +991,7 @@ namespace System // DecHexDigits s a translation table from a decimal number to its // digits hexadecimal representation (e.g. DecHexDigits [34] = 0x34). - private static int32[100] DecHexDigits = .( + private const int32[100] DecHexDigits = .( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, @@ -1235,8 +1235,10 @@ namespace System // _isCustomFormat, _specifierIsUpper, _specifier & _precision. this(CultureInfo cultureInfo) { - //_cbuf = EmptyArray.Value; - _cbuf = sEmtpyBuf; + if (Compiler.IsConstEval) + _cbuf = new char8[0]; + else + _cbuf = sEmtpyBuf; if (cultureInfo != null) CurrentCulture = cultureInfo; } @@ -2032,13 +2034,12 @@ namespace System private void FormatHexadecimal (int32 precision, String outString) { int32 size = Math.Max (precision, _decPointPos); - char8* digits = _specifierIsUpper ? &DigitUpperTable : &DigitLowerTable; - + ResetCharBuf (size); _ind = size; uint64 val = _val1 | ((uint64)_val2 << 32); while (size > 0) { - _cbuf [--size] = digits [val & 0xf]; + _cbuf [--size] = _specifierIsUpper ? DigitUpperTable[val & 0xf] : DigitLowerTable[val & 0xf]; val >>= 4; } outString.Append(_cbuf, 0, _ind); @@ -2046,8 +2047,6 @@ namespace System private void FormatAddress(String outString) { - char8* digits = _specifierIsUpper ? &DigitUpperTable : &DigitLowerTable; - const int bufLen = 18; char8* strChars = scope:: char8[bufLen]* (?); int32 curLen = 0; @@ -2056,7 +2055,7 @@ namespace System { if (curLen == 8) strChars[bufLen - curLen++ - 1] = '\''; - strChars[bufLen - curLen++ - 1] = digits[(int)(valLeft & 0xF)]; + strChars[bufLen - curLen++ - 1] = _specifierIsUpper ? DigitUpperTable[(int)(valLeft & 0xF)] : DigitLowerTable[(int)(valLeft & 0xF)]; valLeft >>= 4; } diff --git a/BeefLibs/corlib/src/Object.bf b/BeefLibs/corlib/src/Object.bf index ec0e4aca..a664e084 100644 --- a/BeefLibs/corlib/src/Object.bf +++ b/BeefLibs/corlib/src/Object.bf @@ -40,9 +40,13 @@ namespace System return false; } #endif + extern Type ConstEval_GetType(); public Type GetType() { + if (Compiler.IsConstEval) + return ConstEval_GetType(); + Type type; #if BF_ENABLE_OBJECT_DEBUG_FLAGS ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); @@ -61,6 +65,9 @@ namespace System [NoShow] Type RawGetType() { + if (Compiler.IsConstEval) + return ConstEval_GetType(); + Type type; #if BF_ENABLE_OBJECT_DEBUG_FLAGS ClassVData* maskedVData = (ClassVData*)(void*)(mClassVData & ~(int)0xFF); diff --git a/BeefLibs/corlib/src/Text/UTF8.bf b/BeefLibs/corlib/src/Text/UTF8.bf index 031ec57f..4df4c7f9 100644 --- a/BeefLibs/corlib/src/Text/UTF8.bf +++ b/BeefLibs/corlib/src/Text/UTF8.bf @@ -1,9 +1,10 @@ +using System.Diagnostics; namespace System.Text { class UTF8 { - public static int8* sTrailingBytesForUTF8 = new int8[]* - ( + public const int8[256] sTrailingBytesForUTF8 = + .( 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -12,13 +13,13 @@ namespace System.Text 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 - ) ~ delete _; + ); - public static uint32* sOffsetsFromUTF8 = new uint32[]* - ( + public const uint32[6] sOffsetsFromUTF8 = + .( 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080 - ) ~ delete _; + ); public static int GetEncodedLength(char32 c) { @@ -58,6 +59,7 @@ namespace System.Text case 2: c <<= 6; c += (int32)buf[bufIdx++]; fallthrough; case 1: c <<= 6; c += (int32)buf[bufIdx++]; fallthrough; } + c -= (int32)UTF8.sOffsetsFromUTF8[trailingBytes]; return (c, trailingBytes + 1); } diff --git a/BeefySysLib/util/Hash.h b/BeefySysLib/util/Hash.h index 0a22de32..46eb44cb 100644 --- a/BeefySysLib/util/Hash.h +++ b/BeefySysLib/util/Hash.h @@ -146,4 +146,16 @@ public: uint64 Finish64(); }; -NS_BF_END \ No newline at end of file +NS_BF_END + +namespace std +{ + template<> + struct hash + { + size_t operator()(const Beefy::Val128& val) const + { + return val.mLow; + } + }; +} diff --git a/BeefySysLib/util/Heap.cpp b/BeefySysLib/util/Heap.cpp index 2410a9d5..d6e8e306 100644 --- a/BeefySysLib/util/Heap.cpp +++ b/BeefySysLib/util/Heap.cpp @@ -151,6 +151,8 @@ void ContiguousHeap::Clear(int maxAllocSize) while (block != NULL) { block->mKind = ChBlockKind_Bad; + if (block->mNext == -1) + break; block = CH_REL_TO_ABS(block->mNext); } } diff --git a/IDEHelper/Backend/BeContext.cpp b/IDEHelper/Backend/BeContext.cpp index 1b71b9cc..0e78b879 100644 --- a/IDEHelper/Backend/BeContext.cpp +++ b/IDEHelper/Backend/BeContext.cpp @@ -70,6 +70,11 @@ BeType* BeContext::GetPrimitiveType(BeTypeCode typeCode) return primType; } +BeType* BeContext::GetVoidPtrType() +{ + return GetPointerTo(GetPrimitiveType(BeTypeCode_None)); +} + BeStructType* BeContext::CreateStruct(const StringImpl& name) { BeStructType* structType = mTypes.Alloc(); diff --git a/IDEHelper/Backend/BeContext.h b/IDEHelper/Backend/BeContext.h index d08db01d..467f6a98 100644 --- a/IDEHelper/Backend/BeContext.h +++ b/IDEHelper/Backend/BeContext.h @@ -275,6 +275,7 @@ public: public: BeContext(); BeType* GetPrimitiveType(BeTypeCode typeCode); + BeType* GetVoidPtrType(); BeStructType* CreateStruct(const StringImpl& name); BeStructType* CreateStruct(const SizedArrayImpl& types); BePointerType* GetPointerTo(BeType* beType); diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 240e0c5c..59b8604a 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -765,6 +765,22 @@ void BeIRCodeGen::Read(BeValue*& beValue) BE_MEM_END("ParamType_Const_PtrToInt"); return; } + else if (constType == BfConstType_IntToPtr) + { + CMD_PARAM(BeConstant*, target); + CMD_PARAM(BeType*, toType); + + auto castedVal = mBeModule->mAlloc.Alloc(); + castedVal->mInt64 = target->mInt64; + castedVal->mType = toType; + castedVal->mTarget = target; + BF_ASSERT(target->GetType() != NULL); + BF_ASSERT(!target->GetType()->IsComposite()); + BF_ASSERT(toType->IsPointer()); + beValue = castedVal; + BE_MEM_END("ParamType_Const_IntToPtr"); + return; + } else if (constType == BfConstType_AggZero) { CMD_PARAM(BeType*, type); @@ -2545,6 +2561,17 @@ void BeIRCodeGen::HandleNextCmd() SetResult(curId, inst); } break; + case BfIRCmd_ConstEval_GetReflectType: + { + CMD_PARAM(int32, typeId); + CMD_PARAM(BeType*, resultType); + + auto inst = mBeModule->AllocInst(); + inst->mTypeId = typeId; + inst->mResultType = resultType; + SetResult(curId, inst); + } + break; case BfIRCmd_ConstEval_DynamicCastCheck: { CMD_PARAM(BeValue*, value); @@ -2575,13 +2602,13 @@ void BeIRCodeGen::HandleNextCmd() { CMD_PARAM(BeValue*, value); CMD_PARAM(int32, ifaceTypeId); - CMD_PARAM(int32, virtualTableIdx); + CMD_PARAM(int32, methodIdx); CMD_PARAM(BeType*, resultType); auto inst = mBeModule->AllocInst(); inst->mValue = value; inst->mIFaceTypeId = ifaceTypeId; - inst->mVirtualTableIdx = virtualTableIdx; + inst->mMethodIdx = methodIdx; inst->mResultType = resultType; SetResult(curId, inst); } diff --git a/IDEHelper/Backend/BeModule.cpp b/IDEHelper/Backend/BeModule.cpp index 2f337cc8..49099e83 100644 --- a/IDEHelper/Backend/BeModule.cpp +++ b/IDEHelper/Backend/BeModule.cpp @@ -1282,7 +1282,7 @@ void BeDumpContext::ToString(StringImpl& str, BeValue* value, bool showType, boo str += StrFormat(" %d %d", constantGEP->mIdx0, constantGEP->mIdx1); return; } - + if (auto constantExtract = BeValueDynCast(value)) { str += "ConstExtract "; @@ -2450,9 +2450,10 @@ String BeModule::ToString(BeFunction* wantFunc) } break; DISPLAY_INST1(BeConstEvalGetType, "ConstEvalGetType", mTypeId); + DISPLAY_INST1(BeConstEvalGetReflectType, "ConstEvalGetReflectType", mTypeId); DISPLAY_INST2(BeConstEvalDynamicCastCheck, "ConstEvalDynamicCastCheck", mValue, mTypeId); DISPLAY_INST2(BeConstEvalGetVirtualFunc, "ConstEvalGetVirtualFunc", mValue, mVirtualTableIdx); - DISPLAY_INST3(BeConstEvalGetInterfaceFunc, "ConstEvalGetInterfaceFunc", mValue, mIFaceTypeId, mVirtualTableIdx); + DISPLAY_INST3(BeConstEvalGetInterfaceFunc, "ConstEvalGetInterfaceFunc", mValue, mIFaceTypeId, mMethodIdx); default: BF_FATAL("Notimpl"); str += ""; diff --git a/IDEHelper/Backend/BeModule.h b/IDEHelper/Backend/BeModule.h index 42663301..605c7f27 100644 --- a/IDEHelper/Backend/BeModule.h +++ b/IDEHelper/Backend/BeModule.h @@ -1361,6 +1361,28 @@ public: } }; +class BeConstEvalGetReflectType : public BeInst +{ +public: + BE_VALUE_TYPE(BeConstEvalGetReflectType, BeInst); + +public: + int mTypeId; + BeType* mResultType; + +public: + virtual BeType* GetType() override + { + return mResultType; + } + + virtual void HashInst(BeHashContext& hashCtx) override + { + hashCtx.Mixin(TypeId); + hashCtx.Mixin(mTypeId); + } +}; + class BeConstEvalDynamicCastCheck : public BeInst { public: @@ -1417,7 +1439,7 @@ public: public: BeValue* mValue; int mIFaceTypeId; - int mVirtualTableIdx; + int mMethodIdx; BeType* mResultType; public: @@ -1431,7 +1453,7 @@ public: hashCtx.Mixin(TypeId); mValue->HashReference(hashCtx); hashCtx.Mixin(mIFaceTypeId); - hashCtx.Mixin(mVirtualTableIdx); + hashCtx.Mixin(mMethodIdx); } }; diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index cc4d6def..aa1d41fc 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -371,14 +371,15 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mHotState = NULL; mHotResolveData = NULL; + mBfObjectTypeDef = NULL; + mChar32TypeDef = NULL; mArray1TypeDef = NULL; mArray2TypeDef = NULL; mArray3TypeDef = NULL; mArray4TypeDef = NULL; mSpanTypeDef = NULL; mAttributeTypeDef = NULL; - mAttributeUsageAttributeTypeDef = NULL; - mBfObjectTypeDef = NULL; + mAttributeUsageAttributeTypeDef = NULL; mClassVDataTypeDef = NULL; mCLinkAttributeTypeDef = NULL; mImportAttributeTypeDef = NULL; @@ -1043,26 +1044,28 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) ////////////////////////////////////////////////////////////////////////// + mContext->ReflectInit(); + // Create types we'll need for vdata, so we won't change the vdata hash afterward - bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)); - - /// - - auto typeDefType = bfModule->ResolveTypeDef(mTypeTypeDef)->ToTypeInstance(); - if (!typeDefType) - return; - BF_ASSERT(typeDefType != NULL); - vdataContext->mBfTypeType = typeDefType->ToTypeInstance(); - - auto typeInstanceDefType = bfModule->ResolveTypeDef(mReflectTypeInstanceTypeDef); - if (!typeInstanceDefType) - return; - auto typeInstanceDefTypeInstance = typeInstanceDefType->ToTypeInstance(); - - auto typeDef = mSystem->FindTypeDef("System.ClassVData"); - BF_ASSERT(typeDef != NULL); - auto bfClassVDataType = bfModule->ResolveTypeDef(typeDef)->ToTypeInstance(); - vdataContext->mBfClassVDataPtrType = bfModule->CreatePointerType(bfClassVDataType); +// bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)); +// +// /// +// +// auto typeDefType = bfModule->ResolveTypeDef(mTypeTypeDef)->ToTypeInstance(); +// if (!typeDefType) +// return; +// BF_ASSERT(typeDefType != NULL); +// vdataContext->mBfTypeType = typeDefType->ToTypeInstance(); +// +// auto typeInstanceDefType = bfModule->ResolveTypeDef(mReflectTypeInstanceTypeDef); +// if (!typeInstanceDefType) +// return; +// auto typeInstanceDefTypeInstance = typeInstanceDefType->ToTypeInstance(); +// +// auto typeDef = mSystem->FindTypeDef("System.ClassVData"); +// BF_ASSERT(typeDef != NULL); +// auto bfClassVDataType = bfModule->ResolveTypeDef(typeDef)->ToTypeInstance(); +// vdataContext->mBfClassVDataPtrType = bfModule->CreatePointerType(bfClassVDataType); ////////////////////////////////////////////////////////////////////////// @@ -1278,6 +1281,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) bool madeBfTypeData = false; + auto typeDefType = mContext->mBfTypeType; bool needsTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType"); bool needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType"); bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName") || bfModule->IsMethodImplementedAndReified(typeDefType, "GetFullName"); @@ -1801,7 +1805,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) bool hadRet = false; String entryClassName = project->mStartupObject; - typeDef = mSystem->FindTypeDef(entryClassName, 0, bfModule->mProject, {}, NULL, BfFindTypeDefFlag_AllowGlobal); + auto typeDef = mSystem->FindTypeDef(entryClassName, 0, bfModule->mProject, {}, NULL, BfFindTypeDefFlag_AllowGlobal); if (typeDef != NULL) { @@ -6546,14 +6550,33 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) return typeDef; }; + + _GetRequiredType("System.Void"); + _GetRequiredType("System.Boolean"); + _GetRequiredType("System.Int"); + _GetRequiredType("System.Int8"); + _GetRequiredType("System.Int16"); + _GetRequiredType("System.Int32"); + _GetRequiredType("System.Int64"); + _GetRequiredType("System.UInt"); + _GetRequiredType("System.UInt8"); + _GetRequiredType("System.UInt16"); + _GetRequiredType("System.UInt32"); + _GetRequiredType("System.UInt64"); + _GetRequiredType("System.Float"); + _GetRequiredType("System.Double"); + _GetRequiredType("System.Char8"); + _GetRequiredType("System.Char16"); + mChar32TypeDef = _GetRequiredType("System.Char32"); + + mBfObjectTypeDef = _GetRequiredType("System.Object"); mArray1TypeDef = _GetRequiredType("System.Array1", 1); mArray2TypeDef = _GetRequiredType("System.Array2", 1); mArray3TypeDef = _GetRequiredType("System.Array3", 1); mArray4TypeDef = _GetRequiredType("System.Array4", 1); - mSpanTypeDef = _GetRequiredType("System.Span", 1); + mSpanTypeDef = _GetRequiredType("System.Span", 1); mAttributeTypeDef = _GetRequiredType("System.Attribute"); - mAttributeUsageAttributeTypeDef = _GetRequiredType("System.AttributeUsageAttribute"); - mBfObjectTypeDef = _GetRequiredType("System.Object"); + mAttributeUsageAttributeTypeDef = _GetRequiredType("System.AttributeUsageAttribute"); mClassVDataTypeDef = _GetRequiredType("System.ClassVData"); mCLinkAttributeTypeDef = _GetRequiredType("System.CLinkAttribute"); mImportAttributeTypeDef = _GetRequiredType("System.ImportAttribute"); @@ -6623,6 +6646,9 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) for (int i = 0; i < BfTypeCode_Length; i++) mContext->mPrimitiveStructTypes[i] = NULL; + mContext->mBfTypeType = NULL; + mContext->mBfClassVDataPtrType = NULL; + if (!hasRequiredTypes) { // Force rebuilding diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 24bd2211..ae5ba550 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -331,13 +331,16 @@ public: CompileState mCompileState; Array mVDataModules; + + BfTypeDef* mChar32TypeDef; + BfTypeDef* mBfObjectTypeDef; + BfTypeDef* mArray1TypeDef; BfTypeDef* mArray2TypeDef; BfTypeDef* mArray3TypeDef; BfTypeDef* mArray4TypeDef; - BfTypeDef* mSpanTypeDef; - - BfTypeDef* mBfObjectTypeDef; + BfTypeDef* mSpanTypeDef; + BfTypeDef* mClassVDataTypeDef; BfTypeDef* mDbgRawAllocDataTypeDef; diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 9c4f7454..2827f30c 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -631,20 +631,10 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods) BfLogSysM("Module %p inlining method %p into func:%p\n", module, methodInstance, workItem.mFunc); - BfMethodInstance dupMethodInstance = *methodInstance; - if (dupMethodInstance.mMethodInfoEx != NULL) - { - dupMethodInstance.mMethodInfoEx = new BfMethodInfoEx(); - *dupMethodInstance.mMethodInfoEx = *(methodInstance->mMethodInfoEx); - for (auto genericParam : dupMethodInstance.mMethodInfoEx->mGenericParams) - genericParam->AddRef(); - dupMethodInstance.mMethodInfoEx->mMethodCustomAttributes = NULL; - } - dupMethodInstance.mHasBeenProcessed = false; - dupMethodInstance.mIRFunction = workItem.mFunc; - dupMethodInstance.mMethodProcessRequest = NULL; - dupMethodInstance.mIsReified = true; - dupMethodInstance.mHotMethod = NULL; + BfMethodInstance dupMethodInstance; + dupMethodInstance.CopyFrom(methodInstance); + dupMethodInstance.mIRFunction = workItem.mFunc; + dupMethodInstance.mIsReified = true; dupMethodInstance.mInCEMachine = false; // Only have the original one BF_ASSERT(module->mIsReified); // We should only bother inlining in reified modules @@ -1437,6 +1427,31 @@ BfHotTypeData* BfContext::GetHotTypeData(int typeId) return NULL; } +void BfContext::ReflectInit() +{ + auto bfModule = mScratchModule; + + bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)); + + /// + + auto typeDefType = bfModule->ResolveTypeDef(mCompiler->mTypeTypeDef)->ToTypeInstance(); + if (!typeDefType) + return; + BF_ASSERT(typeDefType != NULL); + mBfTypeType = typeDefType->ToTypeInstance(); + + auto typeInstanceDefType = bfModule->ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef); + if (!typeInstanceDefType) + return; + auto typeInstanceDefTypeInstance = typeInstanceDefType->ToTypeInstance(); + + auto typeDef = mSystem->FindTypeDef("System.ClassVData"); + BF_ASSERT(typeDef != NULL); + auto bfClassVDataType = bfModule->ResolveTypeDef(typeDef)->ToTypeInstance(); + mBfClassVDataPtrType = bfModule->CreatePointerType(bfClassVDataType); +} + void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) { if (type == mBfObjectType) diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index bdd6db61..4fbc3616 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -412,6 +412,7 @@ public: BfType* FindType(const StringImpl& typeName); String TypeIdToString(int typeId); BfHotTypeData* GetHotTypeData(int typeId); + void ReflectInit(); public: BfContext(BfCompiler* compiler); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index c575b170..ba076e33 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -1280,6 +1280,12 @@ String BfIRBuilder::ToString(BfIRValue irValue) BfIRValue targetConst(BfIRValueFlags_Const, ptrToIntConst->mTarget); return ToString(targetConst) + StrFormat(" PtrToInt TypeCode:%d", ptrToIntConst->mToTypeCode); } + else if (constant->mConstType == BfConstType_IntToPtr) + { + auto bitcast = (BfConstantIntToPtr*)constant; + BfIRValue targetConst(BfIRValueFlags_Const, bitcast->mTarget); + return ToString(targetConst) + " IntToPtr " + ToString(bitcast->mToType); + } else if (constant->mConstType == BfConstType_Array) { auto constArray = (BfConstantArray*)constant; @@ -1896,6 +1902,14 @@ void BfIRBuilder::Write(const BfIRValue& irValue) Write(ptrToIntConst->mToTypeCode); } break; + case (int)BfConstType_IntToPtr: + { + auto intToPtrConst = (BfConstantIntToPtr*)constant; + BfIRValue targetConst(BfIRValueFlags_Const, intToPtrConst->mTarget); + Write(targetConst); + Write(intToPtrConst->mToType); + } + break; case (int)BfConstType_AggZero: { Write(constant->mIRType); @@ -4074,6 +4088,20 @@ BfIRValue BfIRBuilder::CreatePtrToInt(BfIRValue val, BfTypeCode typeCode) BfIRValue BfIRBuilder::CreateIntToPtr(BfIRValue val, BfIRType type) { + if (val.IsConst()) + { + auto ptrToInt = mTempAlloc.Alloc(); + ptrToInt->mConstType = BfConstType_IntToPtr; + ptrToInt->mTarget = val.mId; + ptrToInt->mToType = type; + + BfIRValue castedVal(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(ptrToInt)); +#ifdef CHECK_CONSTHOLDER + castedVal.mHolder = this; +#endif + return castedVal; + } + BfIRValue retVal = WriteCmd(BfIRCmd_IntToPtr, val, type); NEW_CMD_INSERTED_IRVALUE; return retVal; @@ -4806,6 +4834,13 @@ BfIRValue BfIRBuilder::ConstEval_GetBfType(int typeId, BfIRType resultType) return retVal; } +BfIRValue BfIRBuilder::ConstEval_GetReflectType(int typeId, BfIRType resultType) +{ + BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetReflectType, typeId, resultType); + NEW_CMD_INSERTED; + return retVal; +} + BfIRValue BfIRBuilder::ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType) { BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_DynamicCastCheck, value, typeId, resultType); @@ -4820,9 +4855,9 @@ BfIRValue BfIRBuilder::ConstEval_GetVirtualFunc(BfIRValue value, int virtualTabl return retVal; } -BfIRValue BfIRBuilder::ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType) +BfIRValue BfIRBuilder::ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int methodIdx, BfIRType resultType) { - BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetInterfaceFunc, value, typeId, virtualTableId, resultType); + BfIRValue retVal = WriteCmd(BfIRCmd_ConstEval_GetInterfaceFunc, value, typeId, methodIdx, resultType); NEW_CMD_INSERTED; return retVal; } @@ -4920,6 +4955,7 @@ void BfIRBuilder::CreateObjectAccessCheck(BfIRValue value, bool useAsm) NEW_CMD_INSERTED_IRBLOCK; if (!mIgnoreWrites) { + BF_ASSERT(!value.IsConst()); BF_ASSERT(!retBlock.IsFake()); mActualInsertBlock = retBlock; } diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index 93d6b732..25e5d61b 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -118,6 +118,7 @@ enum BfConstType BfConstType_GEP32_2, BfConstType_ExtractValue, BfConstType_PtrToInt, + BfConstType_IntToPtr, BfConstType_TypeOf, BfConstType_AggZero, BfConstType_Array, @@ -282,6 +283,7 @@ enum BfIRCmd : uint8 BfIRCmd_Func_SetLinkage, BfIRCmd_ConstEval_GetBfType, + BfIRCmd_ConstEval_GetReflectType, BfIRCmd_ConstEval_DynamicCastCheck, BfIRCmd_ConstEval_GetVirtualFunc, BfIRCmd_ConstEval_GetInterfaceFunc, @@ -831,6 +833,13 @@ struct BfConstantPtrToInt BfTypeCode mToTypeCode; }; +struct BfConstantIntToPtr +{ + BfConstType mConstType; + int mTarget; + BfIRType mToType; +}; + struct BfConstantGEP32_2 { BfConstType mConstType; @@ -1230,9 +1239,10 @@ public: void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage); BfIRValue ConstEval_GetBfType(int typeId, BfIRType resultType); + BfIRValue ConstEval_GetReflectType(int typeId, BfIRType resultType); BfIRValue ConstEval_DynamicCastCheck(BfIRValue value, int typeId, BfIRType resultType); BfIRValue ConstEval_GetVirtualFunc(BfIRValue value, int virtualTableId, BfIRType resultType); - BfIRValue ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int virtualTableId, BfIRType resultType); + BfIRValue ConstEval_GetInterfaceFunc(BfIRValue value, int typeId, int methodIdx, BfIRType resultType); void SaveDebugLocation(); void RestoreDebugLocation(); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 137503dc..007ba8fb 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1338,13 +1338,15 @@ void BfModule::StartExtension() void BfModule::GetConstClassValueParam(BfIRValue classVData, SizedArrayImpl& typeValueParams) { + auto hasObjectDebugFlags = mContext->mBfObjectType->mFieldInstances[0].mResolvedType->IsInteger(); + BfIRValue vDataValue; - if (mCompiler->mOptions.mObjectHasDebugFlags) + if (hasObjectDebugFlags) vDataValue = mBfIRBuilder->CreatePtrToInt(classVData, BfTypeCode_IntPtr); else vDataValue = mBfIRBuilder->CreateBitCast(classVData, mBfIRBuilder->MapType(mContext->mBfClassVDataPtrType)); typeValueParams.push_back(vDataValue); - if (mCompiler->mOptions.mObjectHasDebugFlags) + if (hasObjectDebugFlags) { auto primType = GetPrimitiveType(BfTypeCode_IntPtr); typeValueParams.push_back(GetDefaultValue(primType)); @@ -4640,6 +4642,12 @@ BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* ou PopulateType(typeInstance, BfPopulateType_DataAndMethods); BfType* classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); + + if (mIsConstModule) + { + auto idVal = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, typeInstance->mTypeId); + return mBfIRBuilder->CreateIntToPtr(idVal, mBfIRBuilder->MapType(CreatePointerType(classVDataType))); + } BfIRValue* globalVariablePtr = NULL; mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr); @@ -4828,6 +4836,13 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type) { return mBfIRBuilder->CreateTypeOf(type); } + + if (mIsConstModule) + { + auto typeTypeDef = ResolveTypeDef(mCompiler->mTypeTypeDef); + auto typeTypeInst = typeTypeDef->ToTypeInstance(); + return mBfIRBuilder->ConstEval_GetReflectType(type->mTypeId, mBfIRBuilder->MapType(typeTypeInst)); + } BfIRValue globalVariable; @@ -4883,6 +4898,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin return BfIRValue(); } + if (mContext->mBfTypeType == NULL) + { + + } + BfIRValue typeTypeData; int typeFlags = 0; if (needsTypeData) @@ -5141,29 +5161,32 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin StringT<128> mangledName; BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), typeInstance, typeInstance->mModule); - for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++) + if (!mIsConstModule) { - auto methodDef = typeDef->mMethods[methodIdx]; - auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault; - if (methodInstance == NULL) - continue; - if (typeInstance->IsUnspecializedType()) - continue; - if (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject)) + for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++) { - if (methodInstance->mChainType == BfMethodChainType_ChainMember) + auto methodDef = typeDef->mMethods[methodIdx]; + auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault; + if (methodInstance == NULL) + continue; + if (typeInstance->IsUnspecializedType()) + continue; + if (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject)) { - BF_ASSERT(!methodInstance->GetOwner()->IsUnspecializedType()); + if (methodInstance->mChainType == BfMethodChainType_ChainMember) + { + BF_ASSERT(!methodInstance->GetOwner()->IsUnspecializedType()); - // We need to create an empty thunk for this chained method - BfIRFunction func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline); - mBfIRBuilder->SetActiveFunction(func); - auto block = mBfIRBuilder->CreateBlock("entry", true); - mBfIRBuilder->SetInsertPoint(block); - mBfIRBuilder->CreateRetVoid(); - mBfIRBuilder->SetActiveFunction(BfIRFunction()); + // We need to create an empty thunk for this chained method + BfIRFunction func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline); + mBfIRBuilder->SetActiveFunction(func); + auto block = mBfIRBuilder->CreateBlock("entry", true); + mBfIRBuilder->SetInsertPoint(block); + mBfIRBuilder->CreateRetVoid(); + mBfIRBuilder->SetActiveFunction(BfIRFunction()); + } } - } + } } SizedArray vData; @@ -5292,7 +5315,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin { highestIFaceVirtIdx = BF_MAX(highestIFaceVirtIdx, interfaceEntry.mStartVirtualIdx + interfaceEntry.mInterfaceType->mVirtualMethodTableSize); - if (!typeInstance->IsTypeMemberAccessible(interfaceEntry.mDeclaringType, mProject)) + if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry.mDeclaringType, mProject))) continue; _InterfaceMatchEntry* matchEntry = NULL; @@ -5391,13 +5414,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (entry.mDeclaringMethod.mMethodNum == -1) continue; BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod; - if ((methodInstance == NULL) || (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject))) + if ((methodInstance == NULL) || + ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)))) { if (origVTable.empty()) origVTable = typeInstance->mVirtualMethodTable; BfMethodInstance* declMethodInstance = entry.mDeclaringMethod; - if (typeInstance->IsTypeMemberAccessible(declMethodInstance->mMethodDef->mDeclaringType, mProject)) + if ((mIsConstModule) || (typeInstance->IsTypeMemberAccessible(declMethodInstance->mMethodDef->mDeclaringType, mProject))) { // Prepare to reslot... entry.mImplementingMethod = entry.mDeclaringMethod; @@ -5429,7 +5453,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (!reslotNames.Contains(methodInstance->mMethodDef->mName)) continue; - if (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)) + if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject))) continue; if ((methodInstance->mChainType != BfMethodChainType_None) && (methodInstance->mChainType != BfMethodChainType_ChainHead)) continue; @@ -5465,7 +5489,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod; if ((methodInstance != NULL) && (!methodInstance->mMethodDef->mIsAbstract)) { - BF_ASSERT(typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)); + BF_ASSERT((mIsConstModule) || typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)); moduleMethodInst = GetMethodInstanceAtIdx(methodInstance->mMethodInstanceGroup->mOwner, methodInstance->mMethodInstanceGroup->mMethodIdx, NULL, BfGetMethodInstanceFlag_NoInline); auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType); vValue = funcPtr; @@ -5531,7 +5555,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin auto interfaceEntry = interfacePair.mValue.mEntry; bool makeEmpty = false; - if (!typeInstance->IsTypeMemberAccessible(interfaceEntry->mDeclaringType, mProject)) + if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry->mDeclaringType, mProject))) makeEmpty = true; int endVirtualIdx = interfaceEntry->mStartVirtualIdx + interfaceEntry->mInterfaceType->mVirtualMethodTableSize; @@ -5627,10 +5651,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic)) + if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic) && (!mIsConstModule)) { BfIRValue ifaceMethodExtVar; - if (!ifaceMethodExtData.IsEmpty()) + if ((!ifaceMethodExtData.IsEmpty()) && (!mIsConstModule)) { StringT<128> classVDataName; BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), typeInstance, "bf_hs_replace_IFaceExt"); @@ -6228,6 +6252,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (!needsTypeData) break; + // Disable const method reflection info for now + if (mIsConstModule) + break; + auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx]; if (!methodInstanceGroup->IsImplemented()) continue; @@ -6270,9 +6298,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - if (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject)) + if ((!mIsConstModule) && (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject))) continue; - // { @@ -6709,7 +6736,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin mTypeDataRefs[typeInstance] = typeDataVar; - if (classVDataVar) + if ((!mIsConstModule) && (classVDataVar)) { BF_ASSERT(!classVDataName.IsEmpty()); @@ -6751,6 +6778,8 @@ void BfModule::CheckStaticAccess(BfTypeInstance* typeInstance) // Note: this is not just for perf, it fixes a field var-type resolution issue if (mBfIRBuilder->mIgnoreWrites) return; + if (mIsConstModule) + return; PopulateType(typeInstance, BfPopulateType_DataAndMethods); @@ -6891,7 +6920,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) break; case BfBuiltInFuncType_Malloc: { - if (mCompiler->mOptions.mDebugAlloc) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) { func = GetInternalMethod("Dbg_RawAlloc", 1).mFunc; } @@ -6914,7 +6943,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) break; case BfBuiltInFuncType_Free: { - if (mCompiler->mOptions.mDebugAlloc) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) { func = GetInternalMethod("Dbg_RawFree").mFunc; } @@ -8142,7 +8171,7 @@ BfIRValue BfModule::AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTar if ((allocFlags & BfAllocFlags_NoDefaultToMalloc) != 0) return result; - if (mCompiler->mOptions.mDebugAlloc) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) { BfIRValue allocData = GetDbgRawAllocData(type); BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_RawAlloc", 2); @@ -8838,13 +8867,14 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget } else { - if ((mBfIRBuilder->mIgnoreWrites) || (mCompiler->mIsResolveOnly)) + if ((mBfIRBuilder->mIgnoreWrites) || + ((mCompiler->mIsResolveOnly) && (!mIsConstModule))) return GetDefaultValue(typeInstance); auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance())); - if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) + if (mCompiler->mOptions.mObjectHasDebugFlags) { SizedArray llvmArgs; llvmArgs.push_back(vData); @@ -8870,6 +8900,12 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget BfIRValue objectVal = mBfIRBuilder->CreateCall(irFunc, llvmArgs); auto objResult = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(mContext->mBfObjectType, BfIRPopulateType_Full)); auto vdataPtr = mBfIRBuilder->CreateInBoundsGEP(objResult, 0, 0); + + if (mIsConstModule) + { + vdataPtr = mBfIRBuilder->CreateBitCast(vdataPtr, mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()))); + } + mBfIRBuilder->CreateStore(vData, vdataPtr); result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance)); } @@ -9136,7 +9172,7 @@ bool BfModule::WantsLifetimes() bool BfModule::HasCompiledOutput() { - return (!mSystem->mIsResolveOnly) && (mIsReified); + return (!mSystem->mIsResolveOnly) && (mIsReified) && (!mIsConstModule); } // We will skip the object access check for any occurances of this value @@ -13114,6 +13150,11 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) typeType = typeType->GetUnderlyingType(); } + if (mIsConstModule) + { + mCompiler->mCEMachine->QueueStaticField(fieldInstance, staticVarName); + } + PopulateType(typeType); if ((typeType != NULL) && (!typeType->IsValuelessType())) { @@ -17487,7 +17528,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } int dependentGenericStartIdx = 0; - if (methodDef->mIsLocalMethod) // See DoMethodDeclaration for an explaination of dependentGenericStartIdx + if ((methodDef->mIsLocalMethod) && (mCurMethodState != NULL)) // See DoMethodDeclaration for an explaination of dependentGenericStartIdx dependentGenericStartIdx = (int)mCurMethodState->GetRootMethodState()->mMethodInstance->GetNumGenericArguments(); SetAndRestoreValue prevMethodInstance(mCurMethodInstance, methodInstance); @@ -17495,7 +17536,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) SetAndRestoreValue prevFilePos(mCurFilePosition); SetAndRestoreValue prevHadBuildError(mHadBuildError, false); SetAndRestoreValue prevHadWarning(mHadBuildWarning, false); - SetAndRestoreValue prevIgnoreWarnings(mIgnoreWarnings, false); + SetAndRestoreValue prevIgnoreWarnings(mIgnoreWarnings, mIsConstModule); if ((methodInstance->mIsReified) && ((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorNoBody))) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 330b2700..0c499d70 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -567,6 +567,29 @@ BfMethodInstance::~BfMethodInstance() delete mMethodInfoEx; } +void BfMethodInstance::CopyFrom(BfMethodInstance* methodInstance) +{ + *this = *methodInstance; + if (mMethodInfoEx != NULL) + { + mMethodInfoEx = new BfMethodInfoEx(); + *mMethodInfoEx = *(methodInstance->mMethodInfoEx); + for (auto genericParam : mMethodInfoEx->mGenericParams) + genericParam->AddRef(); + mMethodInfoEx->mMethodCustomAttributes = NULL; + + if (mMethodInfoEx->mClosureInstanceInfo != NULL) + { + mMethodInfoEx->mClosureInstanceInfo = new BfClosureInstanceInfo(); + *mMethodInfoEx->mClosureInstanceInfo = *methodInstance->mMethodInfoEx->mClosureInstanceInfo; + } + } + mHasBeenProcessed = false; + mIRFunction = BfIRValue(); + mMethodProcessRequest = NULL; + mHotMethod = NULL; +} + BfImportKind BfMethodInstance::GetImportKind() { if (mMethodDef->mImportKind != BfImportKind_Import_Unknown) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 005e28cb..c38ad295 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -771,7 +771,7 @@ public: BfTypeVector mMethodGenericArguments; Dictionary mGenericTypeBindings; BfMethodCustomAttributes* mMethodCustomAttributes; - int mMinDependDepth; + int mMinDependDepth; BfMethodInfoEx() { @@ -779,10 +779,10 @@ public: mForeignType = NULL; mClosureInstanceInfo = NULL; mMethodCustomAttributes = NULL; - mMinDependDepth = -1; + mMinDependDepth = -1; } - - ~BfMethodInfoEx(); + + ~BfMethodInfoEx(); }; enum BfImportCallKind @@ -872,6 +872,8 @@ public: ~BfMethodInstance(); + void CopyFrom(BfMethodInstance* methodInstance); + bool IsMixin() { return mMethodDef->mMethodType == BfMethodType_Mixin; @@ -923,7 +925,7 @@ public: int GetIRFunctionParamCount(BfModule* module); bool IsExactMatch(BfMethodInstance* other, bool ignoreImplicitParams = false, bool checkThis = false); - bool IsReifiedAndImplemented(); + bool IsReifiedAndImplemented(); BfMethodInfoEx* GetMethodInfoEx(); BfCustomAttributes* GetCustomAttributes() @@ -1292,7 +1294,7 @@ public: bool mFieldIncluded; bool mIsEnumPayloadCase; bool mIsThreadLocal; - bool mIsInferredType; + bool mIsInferredType; int mLastRevisionReferenced; public: @@ -1314,7 +1316,7 @@ public: mFieldIncluded = copyFrom.mFieldIncluded; mIsEnumPayloadCase = copyFrom.mIsEnumPayloadCase; mIsThreadLocal = copyFrom.mIsThreadLocal; - mIsInferredType = copyFrom.mIsInferredType; + mIsInferredType = copyFrom.mIsInferredType; mLastRevisionReferenced = copyFrom.mLastRevisionReferenced; } diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 9399849e..24a3a79b 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3933,7 +3933,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) allowPrivate = false; } - if (mCompiler->mOptions.mObjectHasDebugFlags) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) { auto preDelete = GetInternalMethod((deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete"); SizedArray llvmArgs; @@ -3990,7 +3990,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) } else { - if (mCompiler->mOptions.mEnableRealtimeLeakCheck) + if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule)) { SizedArray llvmArgs; llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType))); @@ -6784,7 +6784,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) if (!customAllocator) { - if (mCompiler->mOptions.mEnableRealtimeLeakCheck) + if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsConstModule)) { auto moduleMethodInstance = GetInternalMethod("Dbg_MarkObjectDeleted"); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); @@ -6801,7 +6801,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) auto moduleMethodInstance = GetMethodInstance(objectType, methodInstance->mMethodDef, BfTypeVector()); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); - if (mCompiler->mOptions.mObjectHasDebugFlags) + if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule)) { auto moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), (deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete"); AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true); @@ -6813,7 +6813,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt) { val = LoadValue(val); BfModuleMethodInstance moduleMethodInstance; - if (mCompiler->mOptions.mEnableRealtimeLeakCheck) + if ((mCompiler->mOptions.mDebugAlloc) && (!mIsConstModule)) moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Dbg_RawFree"); else moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Free"); diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index a07dad96..21cbd873 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -3,6 +3,10 @@ #include "BfCompiler.h" #include "BfIRBuilder.h" #include "../Backend/BeIRCodeGen.h" +extern "C" +{ +#include "BeefySysLib/third_party/utf8proc/utf8proc.h" +} #define CE_ENABLE_HEAP @@ -77,6 +81,7 @@ static CeOpInfo gOpInfo[] = {"JmpIfNot", CEOI_None, CEOI_JMPREL, CEOI_FrameRef}, {"Error", CEOI_None, CEOI_IMM32}, {"DynamicCastCheck", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32}, + {"GetReflectType", CEOI_FrameRef, CEOI_IMM32}, {"GetString", CEOI_FrameRef, CEOI_IMM32}, {"Malloc", CEOI_FrameRef, CEOI_FrameRef}, {"Free", CEOI_None, CEOI_FrameRef}, @@ -86,7 +91,9 @@ static CeOpInfo gOpInfo[] = {"MemCpy", CEOI_None, CEOI_FrameRef, CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr_32", CEOI_FrameRef, CEOI_FrameRef}, {"FrameAddr_64", CEOI_FrameRef, CEOI_FrameRef}, - {"Zero", CEOI_None, CEOI_FrameRef, CEOI_IMM32}, + {"FrameAddrOfs_32", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32}, + {"CeOp_ConstDataRef", CEOI_FrameRef, CEOI_IMM32}, + {"Zero", CEOI_None, CEOI_FrameRef, CEOI_IMM32}, {"Const_8", CEOI_FrameRef, CEOI_IMM8}, {"Const_16", CEOI_FrameRef, CEOI_IMM16}, @@ -105,9 +112,12 @@ static CeOpInfo gOpInfo[] = {"AdjustSPConst", CEOI_None, CEOI_IMM32}, {"CeOp_GetSP", CEOI_FrameRef}, {"CeOp_SetSP", CEOI_None, CEOI_FrameRef}, - {"Call", CEOI_None, CEOI_IMM32}, - {"Call_Virt", CEOI_None, CEOI_FrameRef, CEOI_IMM32}, - {"CeOp_Call_IFace", CEOI_None, CEOI_FrameRef, CEOI_IMM32, CEOI_IMM32}, + {"GetStaticField", CEOI_FrameRef, CEOI_IMM32}, + {"GetMethod", CEOI_FrameRef, CEOI_IMM32}, + {"GetMethod_Inner", CEOI_FrameRef, CEOI_IMM32}, + {"GetMethod_Virt", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32}, + {"GetMethod_IFace", CEOI_FrameRef, CEOI_FrameRef, CEOI_IMM32, CEOI_IMM32}, + {"Call", CEOI_None, CEOI_FrameRef}, {"CeOp_Conv_I8_I16", CEOI_FrameRef, CEOI_FrameRef}, {"CeOp_Conv_I8_I32", CEOI_FrameRef, CEOI_FrameRef}, @@ -190,7 +200,8 @@ static_assert(BF_ARRAY_COUNT(gOpInfo) == (int)CeOp_COUNT, "gOpName incorrect siz CeFunction::~CeFunction() { - + for (auto innerFunc : mInnerFunctions) + delete innerFunc; } ////////////////////////////////////////////////////////////////////////// @@ -361,7 +372,10 @@ void CeBuilder::Emit(CeOp val) void CeBuilder::EmitSizedOp(CeOp val, int size) { - Emit((CeOp)(val + GetSizeClass(size))); + CeSizeClass sizeClass = GetSizeClass(size); + Emit((CeOp)(val + sizeClass)); + if (sizeClass == CeSizeClass_X) + Emit((int32)size); } void CeBuilder::Emit(int32 val) @@ -384,6 +398,12 @@ void CeBuilder::Emit(void* ptr, int size) memcpy(mCeFunction->mCode.GrowUninitialized(size), ptr, size); } +void CeBuilder::EmitZeroes(int size) +{ + for (int i = 0; i < size; i++) + Emit((uint8)0); +} + void CeBuilder::EmitJump(CeOp op, const CeOperand& block) { BF_ASSERT(block.mKind == CeOperandKind_Block); @@ -494,7 +514,8 @@ void CeBuilder::EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeO Fail("Invalid binary operand"); Emit(op); - result = FrameAlloc(lhs.mType); + if (!result) + result = FrameAlloc(lhs.mType); EmitFrameOffset(result); EmitFrameOffset(lhs); EmitFrameOffset(rhs); @@ -672,6 +693,35 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme return result; } + + CeStaticFieldInfo* staticFieldInfoPtr = NULL; + if (mCeMachine->mStaticFieldMap.TryGetValue(globalVar->mName, &staticFieldInfoPtr)) + { + CeStaticFieldInfo* staticFieldInfo = staticFieldInfoPtr; + + int* staticFieldTableIdxPtr = NULL; + if (mStaticFieldMap.TryAdd(globalVar, NULL, &staticFieldTableIdxPtr)) + { + CeStaticFieldEntry staticFieldEntry; + staticFieldEntry.mTypeId = staticFieldInfo->mFieldInstance->mOwner->mTypeId; + staticFieldEntry.mName = globalVar->mName; + staticFieldEntry.mSize = globalVar->mType->mSize; + *staticFieldTableIdxPtr = (int)mCeFunction->mStaticFieldTable.size(); + mCeFunction->mStaticFieldTable.Add(staticFieldEntry); + } + + auto result = FrameAlloc(mCeMachine->GetBeContext()->GetPointerTo(globalVar->mType)); + + Emit(CeOp_GetStaticField); + EmitFrameOffset(result); + Emit((int32)*staticFieldTableIdxPtr); + + return result; + } + + if (globalVar->mInitializer != NULL) + return GetOperand(globalVar->mInitializer); + errorKind = CeErrorKind_GlobalVariable; errorType = mCeMachine->GetBeContext()->GetPointerTo(globalVar->mType); } @@ -729,22 +779,28 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme } else { -// auto relTo = GetOperand(constant->mTarget); -// -// if (relTo.mKind == CeOperandKind_Immediate_Null) -// { -// mcOperand.mKind = CeOperandKind_Immediate_Null; -// mcOperand.mType = constant->mType; -// return mcOperand; -// } -// -// mcOperand = AllocVirtualReg(constant->mType); -// auto vregInfo = GetVRegInfo(mcOperand); -// vregInfo->mDefOnFirstUse = true; -// vregInfo->mRelTo = relTo; -// vregInfo->mIsExpr = true; -// -// return mcOperand; + auto relTo = GetOperand(constant->mTarget); + if (relTo) + { + auto result = relTo; + result.mType = constant->mType; + return result; + } + +// if (relTo.mKind == CeOperandKind_Immediate_Null) +// { +// mcOperand.mKind = CeOperandKind_Immediate_Null; +// mcOperand.mType = constant->mType; +// return mcOperand; +// } +// +// mcOperand = AllocVirtualReg(constant->mType); +// auto vregInfo = GetVRegInfo(mcOperand); +// vregInfo->mDefOnFirstUse = true; +// vregInfo->mRelTo = relTo; +// vregInfo->mIsExpr = true; +// + //return mcOperand; } } break; @@ -790,14 +846,38 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme break; case BeStructConstant::TypeId: { -// auto structConstant = (BeStructConstant*)value; -// -// CeOperand mcOperand; -// mcOperand.mKind = CeOperandKind_ConstAgg; -// mcOperand.mConstant = structConstant; -// -// return mcOperand; + int* constDataPtr = NULL; + auto structConstant = (BeStructConstant*)value; + if (mConstDataMap.TryAdd(structConstant, NULL, &constDataPtr)) + { + CeConstStructData constStructData; + errorKind = mCeMachine->WriteConstant(constStructData.mData, structConstant); + if (errorKind == CeErrorKind_None) + { + *constDataPtr = (int)mCeFunction->mConstStructTable.size(); + mCeFunction->mConstStructTable.Add(constStructData); + } + else + { + *constDataPtr = -1; + } + } + + if (*constDataPtr != -1) + { + auto ptrResult = mCeMachine->GetBeContext()->GetPointerTo(structConstant->mType); + auto result = FrameAlloc(ptrResult); + Emit(CeOp_ConstDataRef); + EmitFrameOffset(result); + Emit((int32)*constDataPtr); + return result; + } + else + { + errorKind = CeErrorKind_GlobalVariable; + } } + break; case BeGEPConstant::TypeId: { auto gepConstant = (BeGEPConstant*)value; @@ -848,29 +928,70 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme case BeExtractValueConstant::TypeId: { // Note: this only handles zero-aggregates -// auto extractConstant = (BeExtractValueConstant*)value; -// auto elementType = extractConstant->GetType(); -// -// auto mcVal = GetOperand(extractConstant->mTarget); -// auto valType = GetType(mcVal); -// -// BeConstant beConstant; -// beConstant.mType = elementType; -// beConstant.mUInt64 = 0; -// return GetOperand(&beConstant); + auto extractConstant = (BeExtractValueConstant*)value; + auto elementType = extractConstant->GetType(); + + auto mcVal = GetOperand(extractConstant->mTarget); + + BeConstant beConstant; + beConstant.mType = elementType; + beConstant.mUInt64 = 0; + return GetOperand(&beConstant); } break; - case BeFunction::TypeId: - { -// auto sym = mCOFFObject->GetSymbol(value); -// BEMC_ASSERT(sym != NULL); -// if (sym != NULL) -// { -// CeOperand mcOperand; -// mcOperand.mKind = CeOperandKind_SymbolAddr; -// mcOperand.mSymbolIdx = sym->mIdx; -// return mcOperand; -// } + case BeFunction::TypeId: + { + auto beFunction = (BeFunction*)value; + + int* callIdxPtr = NULL; + if (mFunctionMap.TryAdd(beFunction, NULL, &callIdxPtr)) + { + CeFunctionInfo* ceFunctionInfo = NULL; + mCeMachine->mNamedFunctionMap.TryGetValue(beFunction->mName, &ceFunctionInfo); + if (ceFunctionInfo != NULL) + ceFunctionInfo->mRefCount++; + else + { + auto checkBuilder = this; + if (checkBuilder->mParentBuilder != NULL) + checkBuilder = checkBuilder->mParentBuilder; + + int innerFunctionIdx = 0; + if (checkBuilder->mInnerFunctionMap.TryGetValue(beFunction, &innerFunctionIdx)) + { + auto innerFunction = checkBuilder->mCeFunction->mInnerFunctions[innerFunctionIdx]; + if (!innerFunction->mInitialized) + mCeMachine->PrepareFunction(innerFunction, checkBuilder); + + CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32)); + Emit(CeOp_GetMethod_Inner); + EmitFrameOffset(result); + Emit((int32)innerFunctionIdx); + return result; + } + + Fail(StrFormat("Unable to locate method %s", beFunction->mName.c_str())); + } + + CeCallEntry callEntry; + callEntry.mFunctionInfo = ceFunctionInfo; + *callIdxPtr = (int)mCeFunction->mCallTable.size(); + mCeFunction->mCallTable.Add(callEntry); + } + + if (allowImmediate) + { + CeOperand result; + result.mKind = CeOperandKind_CallTableIdx; + result.mCallTableIdx = *callIdxPtr; + return result; + } + + CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32)); + Emit(CeOp_GetMethod); + EmitFrameOffset(result); + Emit((int32)*callIdxPtr); + return result; } break; case BeCallInst::TypeId: @@ -981,61 +1102,91 @@ void CeBuilder::HandleParams() void CeBuilder::Build() { + auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen; + auto beModule = irCodeGen->mBeModule; + mCeFunction->mFailed = true; auto methodInstance = mCeFunction->mMethodInstance; - auto methodDef = methodInstance->mMethodDef; + + if (methodInstance != NULL) + { + auto methodDef = methodInstance->mMethodDef; - BfMethodInstance dupMethodInstance = *methodInstance; - if (dupMethodInstance.mMethodInfoEx != NULL) - { - dupMethodInstance.mMethodInfoEx = new BfMethodInfoEx(); - *dupMethodInstance.mMethodInfoEx = *(methodInstance->mMethodInfoEx); - for (auto genericParam : dupMethodInstance.mMethodInfoEx->mGenericParams) - genericParam->AddRef(); - dupMethodInstance.mMethodInfoEx->mMethodCustomAttributes = NULL; - } - dupMethodInstance.mHasBeenProcessed = false; - dupMethodInstance.mIRFunction = BfIRValue(); - //dupMethodInstance.mIRFunction = workItem.mFunc; - dupMethodInstance.mMethodProcessRequest = NULL; - dupMethodInstance.mIsReified = true; - dupMethodInstance.mHotMethod = NULL; - dupMethodInstance.mInCEMachine = false; // Only have the original one - - mCeMachine->mCeModule->mIgnoreWarnings = true; - mCeMachine->mCeModule->mHadBuildError = false; - mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true); - - if (!dupMethodInstance.mIRFunction) - { - mCeFunction->mFailed = true; - return; - } - - auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen; - mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64); - mBeFunction = (BeFunction*)irCodeGen->GetBeValue(dupMethodInstance.mIRFunction.mId); + BfMethodInstance dupMethodInstance; + dupMethodInstance.CopyFrom(methodInstance); + //dupMethodInstance.mIRFunction = workItem.mFunc; + dupMethodInstance.mIsReified = true; + dupMethodInstance.mInCEMachine = false; // Only have the original one - if (!mCeFunction->mCeFunctionInfo->mName.IsEmpty()) - { - BF_ASSERT(mCeFunction->mCeFunctionInfo->mName == mBeFunction->mName); + int startFunctionCount = (int)beModule->mFunctions.size(); + //int startGlobalVariableCount = (int)beModule->mGlobalVariables.size(); + + mCeMachine->mCeModule->mHadBuildError = false; + mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true); + + if (!dupMethodInstance.mIRFunction) + { + mCeFunction->mFailed = true; + return; + } + + mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64); + mBeFunction = (BeFunction*)irCodeGen->GetBeValue(dupMethodInstance.mIRFunction.mId); + + for (int funcIdx = startFunctionCount; funcIdx < (int)beModule->mFunctions.size(); funcIdx++) + { + auto beFunction = beModule->mFunctions[funcIdx]; + if (beFunction == mBeFunction) + continue; + if (beFunction->mBlocks.IsEmpty()) + continue; + + CeFunction* innerFunction = new CeFunction(); + innerFunction->mCeInnerFunctionInfo = new CeInnerFunctionInfo(); + innerFunction->mCeInnerFunctionInfo->mName = beFunction->mName; + innerFunction->mCeInnerFunctionInfo->mBeFunction = beFunction; + innerFunction->mCeInnerFunctionInfo->mOwner = mCeFunction; + mInnerFunctionMap[beFunction] = (int)mCeFunction->mInnerFunctions.size(); + mCeFunction->mInnerFunctions.Add(innerFunction); + } + +// for (int globalVarIdx = startGlobalVariableCount; globalVarIdx < (int)beModule->mGlobalVariables.size(); globalVarIdx++) +// { +// auto beGlobalVariable = beModule->mGlobalVariables[globalVarIdx]; +// if (beGlobalVariable->mInitializer == NULL) +// continue; +// +// CeStaticFieldInfo* staticFieldInfoPtr = NULL; +// mCeMachine->mStaticFieldMap.TryAdd(beGlobalVariable->mName, NULL, &staticFieldInfoPtr); +// staticFieldInfoPtr->mBeConstant = beGlobalVariable; +// } + + if (!mCeFunction->mCeFunctionInfo->mName.IsEmpty()) + { + BF_ASSERT(mCeFunction->mCeFunctionInfo->mName == mBeFunction->mName); + } + else + { + mCeFunction->mCeFunctionInfo->mName = mBeFunction->mName; + mCeMachine->mNamedFunctionMap[mCeFunction->mCeFunctionInfo->mName] = mCeFunction->mCeFunctionInfo; + } + + if (mCeMachine->mCeModule->mHadBuildError) + { + mCeFunction->mGenError = "Method had errors"; + mCeMachine->mCeModule->mHadBuildError = false; + return; + } } else { - mCeFunction->mCeFunctionInfo->mName = mBeFunction->mName; - mCeMachine->mNamedFunctionMap[mCeFunction->mCeFunctionInfo->mName] = mCeFunction->mCeFunctionInfo; + BF_ASSERT(mCeFunction->mCeInnerFunctionInfo != NULL); + mBeFunction = mCeFunction->mCeInnerFunctionInfo->mBeFunction; + BF_ASSERT(mBeFunction != NULL); + mCeFunction->mCeInnerFunctionInfo->mBeFunction = NULL; } - if (mCeMachine->mCeModule->mHadBuildError) - { - mCeFunction->mGenError = "Method had errors"; - mCeMachine->mCeModule->mHadBuildError = false; - return; - } - - - auto beModule = irCodeGen->mBeModule; SetAndRestoreValue prevBeFunction(beModule->mActiveFunction, mBeFunction); // Create blocks @@ -1372,7 +1523,7 @@ void CeBuilder::Build() BeTypeCode fromTypeCode = fromType->mTypeCode; BeTypeCode toTypeCode = toType->mTypeCode; - if (castedInst->mToSigned) + if ((castedInst->mValSigned) && (castedInst->mToSigned)) { switch (fromTypeCode) { @@ -1719,6 +1870,29 @@ void CeBuilder::Build() auto ptrValue = FrameAlloc(elementPtrType); result = ptrValue; + if (ceIdx1.mType->mSize < 4) + { + auto ceNewIdx = FrameAlloc(mIntPtrType); + if (mIntPtrType->mSize == 8) + { + if (ceIdx1.mType->mSize == 1) + Emit(CeOp_Conv_I8_I64); + else + Emit(CeOp_Conv_I16_I64); + } + else + { + if (ceIdx1.mType->mSize == 1) + Emit(CeOp_Conv_I8_I32); + else + Emit(CeOp_Conv_I16_I32); + } + EmitFrameOffset(ceNewIdx); + EmitFrameOffset(ceIdx1); + + ceIdx1 = ceNewIdx; + } + result = FrameAlloc(elementPtrType); if (mPtrSize == 4) @@ -1866,6 +2040,122 @@ void CeBuilder::Build() } } break; + case BeExtractValueInst::TypeId: + { + auto castedInst = (BeExtractValueInst*)inst; + + BeConstant* constant = BeValueDynCast(castedInst->mAggVal); + CeOperand mcAgg; + + if (constant == NULL) + { + mcAgg = GetOperand(castedInst->mAggVal, false, true); + if (mcAgg.mKind == CeOperandKind_ConstAgg) + { + constant = mcAgg.mConstant; + } + } + + if (constant != NULL) + { + result.mImmediate = 0; + BeType* wantDefaultType = NULL; + if (constant->mType->IsStruct()) + { + BeStructType* structType = (BeStructType*)constant->mType; + auto& member = structType->mMembers[castedInst->mIdx]; + wantDefaultType = member.mType; + } + else if (constant->mType->IsSizedArray()) + { + BeSizedArrayType* arrayType = (BeSizedArrayType*)constant->mType; + wantDefaultType = arrayType->mElementType; + } + + if (wantDefaultType != NULL) + { +// switch (wantDefaultType->mTypeCode) +// { +// case BeTypeCode_Boolean: +// case BeTypeCode_Int8: +// result.mKind = BeMCOperandKind_Immediate_i8; +// break; +// case BeTypeCode_Int16: +// result.mKind = BeMCOperandKind_Immediate_i16; +// break; +// case BeTypeCode_Int32: +// result.mKind = BeMCOperandKind_Immediate_i32; +// break; +// case BeTypeCode_Int64: +// result.mKind = BeMCOperandKind_Immediate_i64; +// break; +// case BeTypeCode_Float: +// result.mKind = BeMCOperandKind_Immediate_f32; +// break; +// case BeTypeCode_Double: +// result.mKind = BeMCOperandKind_Immediate_f64; +// break; +// case BeTypeCode_Pointer: +// result.mKind = BeMCOperandKind_Immediate_Null; +// result.mType = wantDefaultType; +// break; +// case BeTypeCode_Struct: +// case BeTypeCode_SizedArray: +// { +// auto subConst = mAlloc.Alloc(); +// subConst->mType = wantDefaultType; +// result.mConstant = subConst; +// result.mKind = BeMCOperandKind_ConstAgg; +// } +// break; +// default: +// NotImpl(); +// } + Fail("Unhandled extract"); + } + + break; + } + + auto aggType = mcAgg.mType; + int byteOffset = 0; + BeType* memberType = NULL; + + if (aggType->IsSizedArray()) + { + auto sizedArray = (BeSizedArrayType*)aggType; + memberType = sizedArray->mElementType; + byteOffset = BF_ALIGN(memberType->mSize, memberType->mAlign) * castedInst->mIdx; + } + else + { + BF_ASSERT(aggType->IsStruct()); + BeStructType* structType = (BeStructType*)aggType; + auto& structMember = structType->mMembers[castedInst->mIdx]; + byteOffset = structMember.mByteOffset; + memberType = structMember.mType; + } + + if (byteOffset != 0) + { + auto ptrVal = FrameAlloc(beModule->mContext->GetPrimitiveType(BeTypeCode_Int32)); + Emit(CeOp_FrameAddrOfs_32); + EmitFrameOffset(ptrVal); + EmitFrameOffset(mcAgg); + Emit((int32)byteOffset); + + result = FrameAlloc(memberType); + EmitSizedOp(CeOp_Load_8, memberType->mSize); + EmitFrameOffset(result); + EmitFrameOffset(ptrVal); + } + else + { + result = mcAgg; + result.mType = memberType; + } + } + break; case BeBrInst::TypeId: { auto castedInst = (BeBrInst*)inst; @@ -1944,15 +2234,12 @@ void CeBuilder::Build() break; case BeCallInst::TypeId: { - auto castedInst = (BeCallInst*)inst; - CeOperand ceFunc; + auto castedInst = (BeCallInst*)inst; BeType* returnType = NULL; bool isVarArg = false; - bool useAltArgs = false; - //SizedArray args; - - int callIdx = -1; + + CeOperand ceFunc; BeFunctionType* beFuncType = NULL; CeOperand virtTarget; int ifaceTypeId = -1; @@ -1980,6 +2267,9 @@ void CeBuilder::Build() EmitFrameOffset(ceSize); } break; + case BfIRIntrinsic_AtomicFence: + // Nothing to do + break; default: Emit(CeOp_Error); Emit((int32)CeErrorKind_Intrinsic); @@ -2008,25 +2298,7 @@ void CeBuilder::Build() break; } - int* callIdxPtr = NULL; - if (mFunctionMap.TryAdd(beFunction, NULL, &callIdxPtr)) - { - CeFunctionInfo* ceFunctionInfo = NULL; - mCeMachine->mNamedFunctionMap.TryGetValue(beFunction->mName, &ceFunctionInfo); - if (ceFunctionInfo != NULL) - ceFunctionInfo->mRefCount++; - else - { - Fail(StrFormat("Unable to locate method %s", beFunction->mName.c_str())); - } - - CeCallEntry callEntry; - callEntry.mFunctionInfo = ceFunctionInfo; - *callIdxPtr = (int)mCeFunction->mCallTable.size(); - mCeFunction->mCallTable.Add(callEntry); - } - - callIdx = *callIdxPtr; + ceFunc = GetOperand(beFunction, false, true); } else if (auto beGetVirtualFunc = BeValueDynCast(castedInst->mFunc)) { @@ -2041,7 +2313,7 @@ void CeBuilder::Build() { virtTarget = GetOperand(beGetInterfaceFunc->mValue); ifaceTypeId = beGetInterfaceFunc->mIFaceTypeId; - virtualTableIdx = beGetInterfaceFunc->mVirtualTableIdx; + virtualTableIdx = beGetInterfaceFunc->mMethodIdx; auto resultType = beGetInterfaceFunc->GetType(); BF_ASSERT(resultType->IsPointer()); @@ -2049,23 +2321,19 @@ void CeBuilder::Build() } else { - Emit(CeOp_Error); - Emit((int32)CeErrorKind_FunctionPointer); - - auto funcType = castedInst->mFunc->GetType(); - if (funcType->IsPointer()) - { - auto ptrType = (BePointerType*)funcType; - if (ptrType->mElementType->mTypeCode == BeTypeCode_Function) - { - auto beFuncType = (BeFunctionType*)ptrType->mElementType; - if (beFuncType->mReturnType->mSize > 0) - result = FrameAlloc(beFuncType->mReturnType); - } - } + ceFunc = GetOperand(castedInst->mFunc, false, true); + auto funcType = castedInst->mFunc->GetType(); + if (funcType->IsPointer()) + { + auto ptrType = (BePointerType*)funcType; + if (ptrType->mElementType->mTypeCode == BeTypeCode_Function) + { + beFuncType = (BeFunctionType*)ptrType->mElementType; + } + } } - if ((callIdx != -1) || (virtualTableIdx != -1)) + if ((ceFunc) || (virtualTableIdx != -1)) { CeOperand thisOperand; @@ -2079,7 +2347,7 @@ void CeBuilder::Build() } int stackAdjust = 0; - + if (beFuncType->mReturnType->mSize > 0) { Emit(CeOp_AdjustSPConst); @@ -2087,25 +2355,38 @@ void CeBuilder::Build() stackAdjust += beFuncType->mReturnType->mSize; } + if (!ceFunc) + ceFunc = FrameAlloc(beModule->mContext->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32)); + if (ifaceTypeId != -1) { - Emit(CeOp_Call_IFace); + Emit(CeOp_GetMethod_IFace); + EmitFrameOffset(ceFunc); EmitFrameOffset(thisOperand); Emit((int32)ifaceTypeId); Emit((int32)virtualTableIdx); } else if (virtualTableIdx != -1) { - Emit(CeOp_Call_Virt); + Emit(CeOp_GetMethod_Virt); + EmitFrameOffset(ceFunc); EmitFrameOffset(thisOperand); Emit((int32)virtualTableIdx); } - else + + if (ceFunc.mKind == CeOperandKind_CallTableIdx) { - Emit(CeOp_Call); - Emit((int32)callIdx); + CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32)); + Emit(CeOp_GetMethod); + EmitFrameOffset(result); + Emit((int32)ceFunc.mCallTableIdx); + + ceFunc = result; } + Emit(CeOp_Call); + EmitFrameOffset(ceFunc); + if (beFuncType->mReturnType->mSize > 0) { result = FrameAlloc(beFuncType->mReturnType); @@ -2175,12 +2456,23 @@ void CeBuilder::Build() result.mType = beModule->mContext->GetPrimitiveType(BeTypeCode_Int32); } break; + case BeConstEvalGetReflectType::TypeId: + { + auto castedInst = (BeConstEvalGetReflectType*)inst; + auto ptrType = beModule->mContext->GetVoidPtrType(); + result = FrameAlloc(ptrType); + + Emit(CeOp_GetReflectType); + EmitFrameOffset(result); + Emit((int32)castedInst->mTypeId); + } + break; case BeConstEvalDynamicCastCheck::TypeId: { auto castedInst = (BeConstEvalDynamicCastCheck*)inst; auto mcValue = GetOperand(castedInst->mValue); - auto ptrType = beModule->mContext->GetPrimitiveType(BeTypeCode_NullPtr); + auto ptrType = beModule->mContext->GetVoidPtrType(); result = FrameAlloc(ptrType); Emit(CeOp_DynamicCastCheck); @@ -2266,6 +2558,7 @@ CeMachine::CeMachine(BfCompiler* compiler) mCurTargetSrc = NULL; mCurModule = NULL; mHeap = NULL; + mStringCharsOffset = -1; } CeMachine::~CeMachine() @@ -2320,13 +2613,17 @@ BfError* CeMachine::Fail(const CeFrame& curFrame, const StringImpl& str) StringT<256> err; if (isHeadEntry) + { err = str; + err += " "; + } + + err += StrFormat("in const evaluation of "); + if (ceFunction->mMethodInstance != NULL) + err += mCeModule->MethodToString(ceFunction->mMethodInstance, BfMethodNameFlag_OmitParams); else { - StrFormat("in const evaluation of"); - err += mCeModule->MethodToString(ceFunction->mMethodInstance, BfMethodNameFlag_OmitParams); - //err += "("; - //err += ")"; + err += mCeModule->MethodToString(ceFunction->mCeInnerFunctionInfo->mOwner->mMethodInstance, BfMethodNameFlag_OmitParams); } if (emitEntry != NULL) @@ -2387,6 +2684,114 @@ bool CeMachine::CeFree(addr_ce addr) #endif } +addr_ce CeMachine::GetConstantData(BeConstant* constant) +{ + auto writeConstant = constant; + if (auto gvConstant = BeValueDynCast(writeConstant)) + { + if (gvConstant->mInitializer != NULL) + writeConstant = gvConstant->mInitializer; + } + + Array data; + auto result = WriteConstant(data, writeConstant); + BF_ASSERT(result == CeErrorKind_None); + + uint8* ptr = CeMalloc(data.mSize); + memcpy(ptr, data.mVals, data.mSize); + return (addr_ce)(ptr - mMemory.mVals); +} + +addr_ce CeMachine::GetReflectType(int typeId) +{ + addr_ce* addrPtr = NULL; + if (!mReflectMap.TryAdd(typeId, NULL, &addrPtr)) + return *addrPtr; + + if (mCeModule->mContext->mBfTypeType == NULL) + mCeModule->mContext->ReflectInit(); + + if ((uintptr)typeId >= (uintptr)mCeModule->mContext->mTypes.mSize) + return 0; + auto bfType = mCeModule->mContext->mTypes[typeId]; + if (bfType == NULL) + return 0; + + mCeModule->PopulateType(bfType, BfPopulateType_DataAndMethods); + + Dictionary usedStringMap; + auto irData = mCeModule->CreateTypeData(bfType, usedStringMap, true, true, true, false); + + BeValue* beValue = NULL; + if (auto constant = mCeModule->mBfIRBuilder->GetConstant(irData)) + { + if (constant->mConstType == BfConstType_BitCast) + { + auto bitcast = (BfConstantBitCast*)constant; + constant = mCeModule->mBfIRBuilder->GetConstantById(bitcast->mTarget); + } + if (constant->mConstType == BfConstType_GlobalVar) + { + auto globalVar = (BfGlobalVar*)constant; + beValue = mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(globalVar->mStreamId); + } + } + + if (auto constant = BeValueDynCast(beValue)) + *addrPtr = GetConstantData(constant); + + return *addrPtr; +} + +addr_ce CeMachine::GetString(int stringId) +{ + addr_ce* ceAddrPtr = NULL; + if (!mStringMap.TryAdd(stringId, NULL, &ceAddrPtr)) + return *ceAddrPtr; + + BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data); + + String str; + BfStringPoolEntry* entry = NULL; + if (mCeModule->mContext->mStringObjectIdMap.TryGetValue(stringId, &entry)) + { + str = entry->mString; + } + + int allocSize = stringTypeInst->mInstSize + (int)str.length() + 1; + int charsOffset = stringTypeInst->mInstSize; + mStringCharsOffset = charsOffset; + + uint8* mem = CeMalloc(allocSize); + + memset(mem, 0, allocSize); + + auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize; + auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset; + auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset; + auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset; + + // Write TypeId into there + *(int32*)(mem) = stringTypeInst->mTypeId; + *(int32*)(mem + lenOffset) = (int)str.length(); + if (lenByteCount == 4) + *(int32*)(mem + allocSizeOffset) = 0x40000000 + (int)str.length() + 1; + else + *(int64*)(mem + allocSizeOffset) = 0x4000000000000000LL + (int)str.length() + 1; + *(int32*)(mem + ptrOffset) = (mem + charsOffset) - mMemory.mVals; + memcpy(mem + charsOffset, str.c_str(), str.length()); + + *ceAddrPtr = mem - mMemory.mVals; + return *ceAddrPtr; +} + +BfType* CeMachine::GetBfType(int typeId) +{ + if ((uintptr)typeId < (uintptr)mCeModule->mContext->mTypes.size()) + return mCeModule->mContext->mTypes[typeId]; + return NULL; +} + BeContext* CeMachine::GetBeContext() { if (mCeModule == NULL) @@ -2484,6 +2889,153 @@ int CeMachine::GetConstantSize(BfConstant* constant) return -1; } +CeErrorKind CeMachine::WriteConstant(Array& arr, BeConstant* constVal) +{ + auto beType = constVal->GetType(); + if (auto globalVar = BeValueDynCast(constVal)) + { + if (globalVar->mName.StartsWith("__bfStrObj")) + { + int stringId = atoi(globalVar->mName.c_str() + 10); + addr_ce stringAddr = GetString(stringId); + + auto ptr = arr.GrowUninitialized(mCeModule->mSystem->mPtrSize); + int64 addr64 = stringAddr; + memcpy(ptr, &addr64, mCeModule->mSystem->mPtrSize); + return CeErrorKind_None; + } + + if (globalVar->mInitializer == NULL) + return CeErrorKind_GlobalVariable; + + //uint8* gvData = CeMalloc(globalVar->mType->mSize); + Array gvData; + auto result = WriteConstant(gvData, globalVar->mInitializer); + if (result != CeErrorKind_None) + return result; + + uint8* gvPtr = CeMalloc(gvData.mSize); + memcpy(gvPtr, gvData.mVals, gvData.mSize); + + auto ptr = arr.GrowUninitialized(mCeModule->mSystem->mPtrSize); + int64 addr64 = (addr_ce)(gvPtr - mMemory.mVals); + memcpy(ptr, &addr64, mCeModule->mSystem->mPtrSize); + return CeErrorKind_None; + } + else if (auto beFunc = BeValueDynCast(constVal)) + { + return CeErrorKind_FunctionPointer; + } + else if (auto constStruct = BeValueDynCast(constVal)) + { + int startOfs = arr.mSize; + if (constStruct->mType->mTypeCode == BeTypeCode_Struct) + { + BeStructType* structType = (BeStructType*)constStruct->mType; + BF_ASSERT(structType->mMembers.size() == constStruct->mMemberValues.size()); + for (int memberIdx = 0; memberIdx < (int)constStruct->mMemberValues.size(); memberIdx++) + { + auto& member = structType->mMembers[memberIdx]; + // Do any per-member alignment + int wantZeroes = member.mByteOffset - (arr.mSize - startOfs); + if (wantZeroes > 0) + arr.Insert(arr.size(), (uint8)0, wantZeroes); + + auto result = WriteConstant(arr, constStruct->mMemberValues[memberIdx]); + if (result != CeErrorKind_None) + return result; + } + // Do end padding + arr.Insert(arr.size(), (uint8)0, structType->mSize - (arr.mSize - startOfs)); + } + else if (constStruct->mType->mTypeCode == BeTypeCode_SizedArray) + { + for (auto& memberVal : constStruct->mMemberValues) + { + auto result = WriteConstant(arr, memberVal); + if (result != CeErrorKind_None) + return result; + } + } + else + BF_FATAL("Invalid StructConst type"); + } + else if (auto constStr = BeValueDynCast(constVal)) + { + arr.Insert(arr.mSize, (uint8*)constStr->mString.c_str(), (int)constStr->mString.length() + 1); + } + else if (auto constCast = BeValueDynCast(constVal)) + { + auto result = WriteConstant(arr, constCast->mTarget); + if (result != CeErrorKind_None) + return result; + } + else if (auto constGep = BeValueDynCast(constVal)) + { + if (auto globalVar = BeValueDynCast(constGep->mTarget)) + { + BF_ASSERT(constGep->mIdx0 == 0); + + int64 dataOfs = 0; + if (globalVar->mType->mTypeCode == BeTypeCode_Struct) + { + auto structType = (BeStructType*)globalVar->mType; + dataOfs = structType->mMembers[constGep->mIdx1].mByteOffset; + } + else if (globalVar->mType->mTypeCode == BeTypeCode_SizedArray) + { + auto arrayType = (BeSizedArrayType*)globalVar->mType; + dataOfs = arrayType->mElementType->mSize * constGep->mIdx1; + } + else + { + BF_FATAL("Invalid GEP"); + } + + return CeErrorKind_GlobalVariable; + + // auto sym = GetSymbol(globalVar); + // + // BeMCRelocation reloc; + // reloc.mKind = BeMCRelocationKind_ADDR64; + // reloc.mOffset = sect.mData.GetPos(); + // reloc.mSymTableIdx = sym->mIdx; + // sect.mRelocs.push_back(reloc); + // sect.mData.Write((int64)dataOfs); + } + else + { + BF_FATAL("Invalid GEPConstant"); + } + } + else if ((beType->IsPointer()) && (constVal->mTarget != NULL)) + { + auto result = WriteConstant(arr, constVal->mTarget); + if (result != CeErrorKind_None) + return result; + } + else if (beType->IsComposite()) + { + BF_ASSERT(constVal->mInt64 == 0); + + int64 zero = 0; + int sizeLeft = beType->mSize; + while (sizeLeft > 0) + { + int writeSize = BF_MIN(sizeLeft, 8); + auto ptr = arr.GrowUninitialized(writeSize); + memset(ptr, 0, writeSize); + sizeLeft -= writeSize; + } + } + else + { + auto ptr = arr.GrowUninitialized(beType->mSize); + memcpy(ptr, &constVal->mInt64, beType->mSize); + } + return CeErrorKind_None; +} + #define CE_GETC(T) *((T*)(ptr += sizeof(T)) - 1) void CeMachine::WriteConstant(uint8* ptr, BfConstant* constant) @@ -2686,74 +3238,204 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* Fail(_GetCurFrame(), "Const method not available"); return false; } - if (checkFunction->mFunctionKind == CeFunctionKind_OOB) - { - Fail(_GetCurFrame(), "Array out of bounds"); - return false; - } - else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite) - { - int32 ptrVal = *(int32*)((uint8*)stackPtr + 0); - auto size = *(int32*)(stackPtr + mCeModule->mSystem->mPtrSize); - CE_CHECKADDR(ptrVal, size); - char* strPtr = (char*)(ptrVal + memStart); - String str; - str.Insert(0, strPtr, size); - OutputDebugStr(str); - handled = true; - return true; - } - else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int) - { - int32 intVal = *(int32*)((uint8*)stackPtr + 0); - OutputDebugStrF("Debug Val: %d\n", intVal); - handled = true; - return true; - } - else if (checkFunction->mFunctionKind == CeFunctionKind_FatalError) - { - int32 strInstAddr = *(int32*)((uint8*)stackPtr + 0); - CE_CHECKADDR(strInstAddr, 0); - - BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data); - auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize; - auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset; - auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset; - auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset; - - uint8* strInst = (uint8*)(strInstAddr + memStart); - int32 lenVal = *(int32*)(strInst + lenOffset); - - char* charPtr = NULL; - - if (lenByteCount == 4) + if (checkFunction->mFunctionKind != CeFunctionKind_Normal) + { + if (checkFunction->mFunctionKind == CeFunctionKind_OOB) { - int32 allocSizeVal = *(int32*)(strInst + allocSizeOffset); - if ((allocSizeVal & 0x40000000) != 0) - { - int32 ptrVal = *(int32*)(strInst + ptrOffset); - charPtr = (char*)(ptrVal + memStart); - } - else - { - charPtr = (char*)(strInst + ptrOffset); - } + Fail(_GetCurFrame(), "Array out of bounds"); + return false; } + else if (checkFunction->mFunctionKind == CeFunctionKind_Malloc) + { + int32 size = *(int32*)((uint8*)stackPtr + 4); + CE_CHECKALLOC(size); + uint8* ptr = CeMalloc(size); + addr_ce& result = *(addr_ce*)((uint8*)stackPtr + 0); + result = (addr_ce)(ptr - memStart); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Free) + { + addr_ce freeAddr = *(addr_ce*)((uint8*)stackPtr + 4); + bool success = CeFree(freeAddr); + if (!success) + _Fail("Invalid heap address"); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite) + { + int32 ptrVal = *(int32*)((uint8*)stackPtr + 0); + auto size = *(int32*)(stackPtr + mCeModule->mSystem->mPtrSize); + CE_CHECKADDR(ptrVal, size); + char* strPtr = (char*)(ptrVal + memStart); + String str; + str.Insert(0, strPtr, size); + OutputDebugStr(str); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int) + { + int32 intVal = *(int32*)((uint8*)stackPtr + 0); + OutputDebugStrF("Debug Val: %d\n", intVal); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType) + { + int32 typeId = *(int32*)((uint8*)stackPtr + mCeModule->mSystem->mPtrSize); + auto reflectType = GetReflectType(typeId); + _FixVariables(); + *(addr_ce*)(stackPtr + 0) = reflectType; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_FatalError) + { + int32 strInstAddr = *(int32*)((uint8*)stackPtr + 0); + CE_CHECKADDR(strInstAddr, 0); - int32 ptrVal = *(int32*)(strInst + ptrOffset); + BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data); - String error = "Fatal Error: "; - if (charPtr != NULL) - error.Insert(error.length(), charPtr, lenVal); - _Fail(error); + auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize; + auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset; + auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset; + auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset; - return false; - } - else if (checkFunction->mFunctionKind != CeFunctionKind_Normal) - { + uint8* strInst = (uint8*)(strInstAddr + memStart); + int32 lenVal = *(int32*)(strInst + lenOffset); + + char* charPtr = NULL; + + if (lenByteCount == 4) + { + int32 allocSizeVal = *(int32*)(strInst + allocSizeOffset); + if ((allocSizeVal & 0x40000000) != 0) + { + int32 ptrVal = *(int32*)(strInst + ptrOffset); + charPtr = (char*)(ptrVal + memStart); + } + else + { + charPtr = (char*)(strInst + ptrOffset); + } + } + + int32 ptrVal = *(int32*)(strInst + ptrOffset); + + String error = "Fatal Error: "; + if (charPtr != NULL) + error.Insert(error.length(), charPtr, lenVal); + _Fail(error); + + return false; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_ToLower) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 4); + result = utf8proc_tolower(val); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_ToUpper) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 4); + result = utf8proc_toupper(val); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsLower) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + result = utf8proc_category(val) == UTF8PROC_CATEGORY_LL; + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsUpper) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + result = utf8proc_category(val) == UTF8PROC_CATEGORY_LU; + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsWhiteSpace_EX) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + auto cat = utf8proc_category(val); + result = (cat == UTF8PROC_CATEGORY_ZS) || (cat == UTF8PROC_CATEGORY_ZL) || (cat == UTF8PROC_CATEGORY_ZP); + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsLetterOrDigit) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + auto cat = utf8proc_category(val); + switch (cat) + { + case UTF8PROC_CATEGORY_LU: + case UTF8PROC_CATEGORY_LL: + case UTF8PROC_CATEGORY_LT: + case UTF8PROC_CATEGORY_LM: + case UTF8PROC_CATEGORY_LO: + case UTF8PROC_CATEGORY_ND: + case UTF8PROC_CATEGORY_NL: + case UTF8PROC_CATEGORY_NO: + result = true; + break; + default: + result = false; + } + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsLetter) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + auto cat = utf8proc_category(val); + switch (cat) + { + case UTF8PROC_CATEGORY_LU: + case UTF8PROC_CATEGORY_LL: + case UTF8PROC_CATEGORY_LT: + case UTF8PROC_CATEGORY_LM: + case UTF8PROC_CATEGORY_LO: + result = true; + break; + default: + result = false; + } + handled = true; + return true; + } + else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_IsNumber) + { + int32& result = *(int32*)((uint8*)stackPtr + 0); + int32 val = *(int32*)((uint8*)stackPtr + 1); + auto cat = utf8proc_category(val); + switch (cat) + { + case UTF8PROC_CATEGORY_ND: + case UTF8PROC_CATEGORY_NL: + case UTF8PROC_CATEGORY_NO: + result = true; + break; + default: + result = false; + } + handled = true; + return true; + } + Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", mCeModule->MethodToString(checkFunction->mMethodInstance).c_str())); - return false; + return false; } if (!checkFunction->mFailed) @@ -2776,15 +3458,18 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* volatile bool* cancelPtr = &mCompiler->mCanceling; int callCount = 0; + int instIdx = 0; while (true) - { + { if (*cancelPtr) { _Fail("Cancelled"); return false; } + ++instIdx; + CeOp op = CE_GETINST(CeOp); switch (op) { @@ -2850,15 +3535,37 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* auto valueAddr = CE_GETFRAME(addr_ce); int32 ifaceId = CE_GETINST(int32); - CE_CHECKADDR(valueAddr, sizeof(int32)); - - auto ifaceType = mCeModule->mContext->mTypes[ifaceId]; - int32 objTypeId = *(int32*)(memStart + valueAddr); - auto valueType = mCeModule->mContext->mTypes[objTypeId]; - if (mCeModule->TypeIsSubTypeOf(valueType->ToTypeInstance(), ifaceType->ToTypeInstance(), false)) - result = valueAddr; - else + if (valueAddr == 0) + { result = 0; + } + else + { + CE_CHECKADDR(valueAddr, sizeof(int32)); + + auto ifaceType = GetBfType(ifaceId); + int32 objTypeId = *(int32*)(memStart + valueAddr); + auto valueType = GetBfType(objTypeId); + if ((ifaceType == NULL) || (valueType == NULL)) + { + _Fail("Invalid type"); + return false; + } + + if (mCeModule->TypeIsSubTypeOf(valueType->ToTypeInstance(), ifaceType->ToTypeInstance(), false)) + result = valueAddr; + else + result = 0; + } + } + break; + case CeOp_GetReflectType: + { + auto frameOfs = CE_GETINST(int32); + int32 typeId = CE_GETINST(int32); + auto reflectType = GetReflectType(typeId); + _FixVariables(); + *(addr_ce*)(framePtr + frameOfs) = reflectType; } break; case CeOp_GetString: @@ -2867,47 +3574,9 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* auto stringTableIdx = CE_GETINST(int32); auto& ceStringEntry = ceFunction->mStringTable[stringTableIdx]; if (ceStringEntry.mBindExecuteId != mExecuteId) - { - addr_ce* ceAddrPtr = NULL; - if (mStringMap.TryAdd(ceStringEntry.mStringId, NULL, &ceAddrPtr)) - { - String str; - BfStringPoolEntry* entry = NULL; - if (mCeModule->mContext->mStringObjectIdMap.TryGetValue(ceStringEntry.mStringId, &entry)) - { - str = entry->mString; - } - - BfTypeInstance* stringTypeInst = (BfTypeInstance*)mCeModule->ResolveTypeDef(mCompiler->mStringTypeDef, BfPopulateType_Data); - - int allocSize = stringTypeInst->mInstSize + (int)str.length() + 1; - int charsOffset = stringTypeInst->mInstSize; - - CE_CHECKALLOC(allocSize); - uint8* mem = CeMalloc(allocSize); - _FixVariables(); - - memset(mem, 0, allocSize); - - auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize; - auto lenOffset = stringTypeInst->mFieldInstances[0].mDataOffset; - auto allocSizeOffset = stringTypeInst->mFieldInstances[1].mDataOffset; - auto ptrOffset = stringTypeInst->mFieldInstances[2].mDataOffset; - - // Write TypeId into there - *(int32*)(mem) = stringTypeInst->mTypeId; - *(int32*)(mem + lenOffset) = (int)str.length(); - if (lenByteCount == 4) - *(int32*)(mem + allocSizeOffset) = 0x40000000 + (int)str.length() + 1; - else - *(int64*)(mem + allocSizeOffset) = 0x4000000000000000LL + (int)str.length() + 1; - *(int32*)(mem + ptrOffset) = (mem + charsOffset) - memStart; - memcpy(mem + charsOffset, str.c_str(), str.length()); - - *ceAddrPtr = mem - memStart; - } - - ceStringEntry.mStringAddr = *ceAddrPtr; + { + ceStringEntry.mStringAddr = GetString(ceStringEntry.mStringId); + _FixVariables(); ceStringEntry.mBindExecuteId = mExecuteId; } @@ -2963,6 +3632,39 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* result = addr - memStart; } break; + case CeOp_FrameAddrOfs_32: + { + auto& result = CE_GETFRAME(int32); + auto addr = &CE_GETFRAME(uint8); + int32 ofs = CE_GETINST(int32); + result = (int32)(addr - memStart + ofs); + } + break; + case CeOp_ConstDataRef: + { + auto frameOfs = CE_GETINST(int32); + int32 constIdx = CE_GETINST(int32); + auto& constEntry = ceFunction->mConstStructTable[constIdx]; + if (constEntry.mBindExecuteId != mExecuteId) + { + if (constEntry.mHash.IsZero()) + constEntry.mHash = Hash128(&constEntry.mData[0], constEntry.mData.mSize); + + addr_ce* constAddrPtr = NULL; + if (mConstDataMap.TryAdd(constEntry.mHash, NULL, &constAddrPtr)) + { + uint8* data = CeMalloc(constEntry.mData.mSize); + _FixVariables(); + memcpy(data, &constEntry.mData[0], constEntry.mData.mSize); + *constAddrPtr = (addr_ce)(data - memStart); + } + + constEntry.mAddr = *constAddrPtr; + constEntry.mBindExecuteId = mExecuteId; + } + *(addr_ce*)(framePtr + frameOfs) = constEntry.mAddr; + } + break; case CeOp_Zero: { auto resultPtr = &CE_GETFRAME(uint8); @@ -2996,8 +3698,8 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* break; case CeOp_Const_X: { - auto resultPtr = &CE_GETFRAME(uint8); int32 constSize = CE_GETINST(int32); + auto resultPtr = &CE_GETFRAME(uint8); memcpy(resultPtr, instPtr, constSize); instPtr += constSize; } @@ -3109,10 +3811,81 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* stackPtr = memStart + addr; } break; - case CeOp_Call: + case CeOp_GetStaticField: { - callCount++; + auto frameOfs = CE_GETINST(int32); + int32 tableIdx = CE_GETINST(int32); + + CeFunction* ctorCallFunction = NULL; + auto& ceStaticFieldEntry = ceFunction->mStaticFieldTable[tableIdx]; + if (ceStaticFieldEntry.mBindExecuteId != mExecuteId) + { + if (mStaticCtorExecSet.TryAdd(ceStaticFieldEntry.mTypeId, NULL)) + { + auto bfType = GetBfType(ceStaticFieldEntry.mTypeId); + BfTypeInstance* bfTypeInstance = NULL; + if (bfType != NULL) + bfTypeInstance = bfType->ToTypeInstance(); + if (bfTypeInstance == NULL) + { + _Fail("Invalid type"); + return false; + } + + auto methodDef = bfTypeInstance->mTypeDef->GetMethodByName("__BfStaticCtor"); + if (methodDef == NULL) + { + _Fail("No static ctor found"); + return false; + } + + auto moduleMethodInstance = mCeModule->GetMethodInstance(bfTypeInstance, methodDef, BfTypeVector()); + if (!moduleMethodInstance) + { + _Fail("No static ctor instance found"); + return false; + } + + bool added = false; + ctorCallFunction = GetFunction(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, added); + if (!ctorCallFunction->mInitialized) + PrepareFunction(ctorCallFunction, NULL); + } + + CeStaticFieldInfo* staticFieldInfo = NULL; + mStaticFieldMap.TryAdd(ceStaticFieldEntry.mName, NULL, &staticFieldInfo); + + if (staticFieldInfo->mAddr == 0) + { + CE_CHECKALLOC(ceStaticFieldEntry.mSize); + uint8* ptr = CeMalloc(ceStaticFieldEntry.mSize); + _FixVariables(); + memset(ptr, 0, ceStaticFieldEntry.mSize); + staticFieldInfo->mAddr = (addr_ce)(ptr - memStart); + } + + ceStaticFieldEntry.mAddr = staticFieldInfo->mAddr; + + ceStaticFieldEntry.mBindExecuteId = mExecuteId; + } + + *(addr_ce*)(framePtr + frameOfs) = ceStaticFieldEntry.mAddr; + + if (ctorCallFunction != NULL) + { + bool handled = false; + if (!_CheckFunction(ctorCallFunction, handled)) + return false; + if (handled) + break; + CE_CALL(ctorCallFunction); + } + } + break; + case CeOp_GetMethod: + { + auto& result = CE_GETFRAME(CeFunction*); int32 callIdx = CE_GETINST(int32); auto& callEntry = ceFunction->mCallTable[callIdx]; if (callEntry.mBindRevision != mRevision) @@ -3135,7 +3908,7 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* if (moduleMethodInstance) { - QueueMethod(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc); + QueueMethod(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc); } } @@ -3148,21 +3921,13 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction; if (!callEntry.mFunction->mInitialized) { - PrepareFunction(callEntry.mFunction); + PrepareFunction(callEntry.mFunction, NULL); } - - bool handled = false; - if (!_CheckFunction(callEntry.mFunction, handled)) - return false; - if (handled) - break; - + callEntry.mBindRevision = mRevision; } - CE_CALL(callEntry.mFunction); - - + result = callEntry.mFunction; // if (callEntry.mFunction->mName.Contains("__static_dump")) // { // int32 val = *(int32*)(stackPtr); @@ -3170,8 +3935,21 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* // } } break; - case CeOp_Call_Virt: + case CeOp_GetMethod_Inner: { + auto& result = CE_GETFRAME(CeFunction*); + int32 innerIdx = CE_GETINST(int32); + + auto outerFunction = ceFunction; + if (outerFunction->mCeInnerFunctionInfo != NULL) + outerFunction = outerFunction->mCeInnerFunctionInfo->mOwner; + auto& callEntry = outerFunction->mInnerFunctions[innerIdx]; + result = callEntry; + } + break; + case CeOp_GetMethod_Virt: + { + auto& result = CE_GETFRAME(CeFunction*); auto valueAddr = CE_GETFRAME(addr_ce); int32 virtualIdx = CE_GETINST(int32); @@ -3181,8 +3959,63 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* if (valueType->mVirtualMethodTable.IsEmpty()) mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod; - - auto callFunction = GetPreparedFunction(methodInstance); + + auto callFunction = GetPreparedFunction(methodInstance); + result = callFunction; + } + break; + case CeOp_GetMethod_IFace: + { + auto& result = CE_GETFRAME(CeFunction*); + auto valueAddr = CE_GETFRAME(addr_ce); + int32 ifaceId = CE_GETINST(int32); + int32 methodIdx = CE_GETINST(int32); + + auto ifaceType = mCeModule->mContext->mTypes[ifaceId]->ToTypeInstance(); + + CE_CHECKADDR(valueAddr, sizeof(int32)); + int32 objTypeId = *(int32*)(memStart + valueAddr); + auto valueType = mCeModule->mContext->mTypes[objTypeId]->ToTypeInstance(); + if (valueType->mVirtualMethodTable.IsEmpty()) + mCeModule->PopulateType(valueType, BfPopulateType_DataAndMethods); + + BfMethodInstance* methodInstance = NULL; + + auto checkType = valueType; + while (checkType != NULL) + { + for (auto& iface : checkType->mInterfaces) + { + if (iface.mInterfaceType == ifaceType) + { + methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef; + break; + } + } + checkType = checkType->mBaseType; + } + + if (methodInstance == NULL) + { + _Fail("Failed to invoke interface method"); + return false; + } + + auto callFunction = GetPreparedFunction(methodInstance); + result = callFunction; + } + break; + case CeOp_Call: + { + callCount++; + auto callFunction = CE_GETFRAME(CeFunction*); + + bool handled = false; + if (!_CheckFunction(callFunction, handled)) + return false; + if (handled) + break; + CE_CALL(callFunction); } break; @@ -3716,45 +4549,74 @@ bool CeMachine::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* return true; } -void CeMachine::PrepareFunction(CeFunction* ceFunction) +void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder) { - auto methodDef = ceFunction->mMethodInstance->mMethodDef; - if (methodDef->mIsExtern) + if (ceFunction->mMethodInstance != NULL) { - ceFunction->mFunctionKind = CeFunctionKind_Extern; - - auto owner = ceFunction->mMethodInstance->GetOwner(); - if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) + auto methodDef = ceFunction->mMethodInstance->mMethodDef; + if (methodDef->mIsExtern) { - if (methodDef->mName == "Write") + ceFunction->mFunctionKind = CeFunctionKind_Extern; + + auto owner = ceFunction->mMethodInstance->GetOwner(); + if (owner == mCeModule->mContext->mBfObjectType) { - if (ceFunction->mMethodInstance->GetParamCount() == 1) - ceFunction->mFunctionKind = CeFunctionKind_DebugWrite_Int; - else - ceFunction->mFunctionKind = CeFunctionKind_DebugWrite; + if (methodDef->mName == "ConstEval_GetType") + { + ceFunction->mFunctionKind = CeFunctionKind_GetReflectType; + } + } + else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) + { + if (methodDef->mName == "Write") + { + if (ceFunction->mMethodInstance->GetParamCount() == 1) + ceFunction->mFunctionKind = CeFunctionKind_DebugWrite_Int; + else + ceFunction->mFunctionKind = CeFunctionKind_DebugWrite; + } + } + else if (owner->IsInstanceOf(mCeModule->mCompiler->mInternalTypeDef)) + { + if (methodDef->mName == "ThrowIndexOutOfRange") + ceFunction->mFunctionKind = CeFunctionKind_OOB; + else if (methodDef->mName == "FatalError") + ceFunction->mFunctionKind = CeFunctionKind_FatalError; + else if (methodDef->mName == "Dbg_RawAlloc") + ceFunction->mFunctionKind = CeFunctionKind_Malloc; + else if (methodDef->mName == "Dbg_RawFree") + ceFunction->mFunctionKind = CeFunctionKind_Free; + } + else if (owner->IsInstanceOf(mCeModule->mCompiler->mChar32TypeDef)) + { + if (methodDef->mName == "get__ToLower") + ceFunction->mFunctionKind = CeFunctionKind_Char32_ToLower; + else if (methodDef->mName == "get__ToUpper") + ceFunction->mFunctionKind = CeFunctionKind_Char32_ToUpper; + else if (methodDef->mName == "get__IsLower") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsLower; + else if (methodDef->mName == "get__IsUpper") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsUpper; + else if (methodDef->mName == "get__IsWhiteSpace_EX") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsWhiteSpace_EX; + else if (methodDef->mName == "get__IsLetter") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsLetter; + else if (methodDef->mName == "get__IsLetterOrDigit") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsLetterOrDigit; + else if (methodDef->mName == "get__IsNumer") + ceFunction->mFunctionKind = CeFunctionKind_Char32_IsNumber; } - //MAKE CeFunctionKind_DebugWrite_Int + ceFunction->mInitialized = true; + return; } - else if (owner->IsInstanceOf(mCeModule->mCompiler->mInternalTypeDef)) - { - if (methodDef->mName == "ThrowIndexOutOfRange") - { - ceFunction->mFunctionKind = CeFunctionKind_OOB; - } - else if (methodDef->mName == "FatalError") - { - ceFunction->mFunctionKind = CeFunctionKind_FatalError; - } - } - - return; } BF_ASSERT(!ceFunction->mInitialized); ceFunction->mInitialized = true; CeBuilder ceBuilder; + ceBuilder.mParentBuilder = parentBuilder; ceBuilder.mPtrSize = mCeModule->mCompiler->mSystem->mPtrSize; ceBuilder.mCeMachine = this; ceBuilder.mCeFunction = ceFunction; @@ -3847,7 +4709,7 @@ CeFunction* CeMachine::GetPreparedFunction(BfMethodInstance* methodInstance) if (ceFunction == NULL) return NULL; if (!ceFunction->mInitialized) - PrepareFunction(ceFunction); + PrepareFunction(ceFunction, NULL); return ceFunction; } @@ -3862,6 +4724,13 @@ void CeMachine::QueueMethod(BfModuleMethodInstance moduleMethodInstance) QueueMethod(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc); } +void CeMachine::QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName) +{ + CeStaticFieldInfo staticFieldInfo; + staticFieldInfo.mFieldInstance = fieldInstance; + mStaticFieldMap[mangledFieldName] = staticFieldInfo; +} + BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags) { // for (int argIdx = 0; argIdx < (int)args.size(); argIdx++) @@ -3892,7 +4761,7 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns bool added = false; CeFunction* ceFunction = GetFunction(methodInstance, BfIRValue(), added); if (!ceFunction->mInitialized) - PrepareFunction(ceFunction); + PrepareFunction(ceFunction, NULL); if (mHeap == NULL) mHeap = new ContiguousHeap(); @@ -3993,9 +4862,15 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns } mStringMap.Clear(); + mReflectMap.Clear(); + mConstDataMap.Clear(); mMemory.Clear(); + if (mMemory.mAllocSize > BF_CE_MAX_CARRYOVER_MEMORY) + mMemory.Dispose(); mCallStack.Clear(); - mHeap->Clear(); + mStaticCtorExecSet.Clear(); + mStaticFieldMap.Clear(); + mHeap->Clear(BF_CE_MAX_CARRYOVER_HEAP); return returnValue; } diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index e3c02630..7e65f3fd 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -13,11 +13,13 @@ class BeContext; class BeDbgLoc; class BeType; class BeValue; +class BeConstant; class BeInst; class BeDbgFile; class BePhiInst; class BeFunction; class BeSwitchInst; +class BeGlobalVariable; class CeMachine; class CeFunction; @@ -68,6 +70,7 @@ enum CeOp : int16 CeOp_Error, CeOp_DynamicCastCheck, + CeOp_GetReflectType, CeOp_GetString, CeOp_Malloc, CeOp_Free, @@ -78,7 +81,9 @@ enum CeOp : int16 CeOp_FrameAddr_32, CeOp_FrameAddr_64, + CeOp_FrameAddrOfs_32, + CeOp_ConstDataRef, CeOp_Zero, CEOP_SIZED(Const), CEOP_SIZED(Load), @@ -92,9 +97,12 @@ enum CeOp : int16 CeOp_AdjustSPConst, CeOp_GetSP, CeOp_SetSP, + CeOp_GetStaticField, + CeOp_GetMethod, + CeOp_GetMethod_Inner, + CeOp_GetMethod_Virt, + CeOp_GetMethod_IFace, CeOp_Call, - CeOp_Call_Virt, - CeOp_Call_IFace, CeOp_Conv_I8_I16, CeOp_Conv_I8_I32, @@ -231,16 +239,71 @@ enum CeFunctionKind CeFunctionKind_Normal, CeFunctionKind_Extern, CeFunctionKind_OOB, + CeFunctionKind_Malloc, + CeFunctionKind_Free, CeFunctionKind_FatalError, CeFunctionKind_DebugWrite, CeFunctionKind_DebugWrite_Int, + CeFunctionKind_GetReflectType, + CeFunctionKind_Char32_ToLower, + CeFunctionKind_Char32_ToUpper, + CeFunctionKind_Char32_IsLower, + CeFunctionKind_Char32_IsUpper, + CeFunctionKind_Char32_IsWhiteSpace_EX, + CeFunctionKind_Char32_IsLetterOrDigit, + CeFunctionKind_Char32_IsLetter, + CeFunctionKind_Char32_IsNumber, +}; + +class CeConstStructData +{ +public: + Val128 mHash; + Array mData; + addr_ce mAddr; + int mBindExecuteId; + +public: + CeConstStructData() + { + mBindExecuteId = -1; + mAddr = 0; + } +}; + +class CeInnerFunctionInfo +{ +public: + String mName; + BeFunction* mBeFunction; + CeFunction* mOwner; +}; + +class CeStaticFieldEntry +{ +public: + String mName; + int mTypeId; + int mSize; + addr_ce mAddr; + int mBindExecuteId; + +public: + CeStaticFieldEntry() + { + mTypeId = -1; + mSize = 0; + mAddr = 0; + mBindExecuteId = -1; + } }; class CeFunction { public: CeFunctionInfo* mCeFunctionInfo; - BfMethodInstance* mMethodInstance; + CeInnerFunctionInfo* mCeInnerFunctionInfo; + BfMethodInstance* mMethodInstance; CeFunctionKind mFunctionKind; bool mInitialized; bool mFailed; @@ -249,7 +312,10 @@ public: Array mEmitTable; Array mCallTable; Array mStringTable; + Array mConstStructTable; + Array mStaticFieldTable; Array mTypeTable; + Array mInnerFunctions; String mGenError; int mFrameSize; @@ -257,6 +323,7 @@ public: CeFunction() { mCeFunctionInfo = NULL; + mCeInnerFunctionInfo = NULL; mFunctionKind = CeFunctionKind_Normal; mInitialized = false; mMethodInstance = NULL; @@ -278,7 +345,9 @@ enum CeOperandKind CeOperandKind_FrameOfs, CeOperandKind_AllocaAddr, CeOperandKind_Block, - CeOperandKind_Immediate + CeOperandKind_Immediate, + CeOperandKind_ConstAgg, + CeOperandKind_CallTableIdx }; class CeOperand @@ -290,6 +359,8 @@ public: int mFrameOfs; int mBlockIdx; int mImmediate; + int mCallTableIdx; + BeConstant* mConstant; }; BeType* mType; @@ -312,8 +383,10 @@ public: } }; -#define BF_CE_STACK_SIZE 1024*1024 +#define BF_CE_STACK_SIZE 4*1024*1024 #define BF_CE_MAX_MEMORY 128*1024*1024 +#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_STACK_SIZE + 1024*1024 +#define BF_CE_MAX_CARRYOVER_HEAP 1024*1024 enum CeOperandInfoKind { @@ -385,6 +458,7 @@ public: class CeBuilder { public: + CeBuilder* mParentBuilder; CeMachine* mCeMachine; CeFunction* mCeFunction; BeFunction* mBeFunction; @@ -401,10 +475,14 @@ public: Dictionary mDbgFileMap; Dictionary mFunctionMap; Dictionary mStringMap; + Dictionary mConstDataMap; + Dictionary mInnerFunctionMap; + Dictionary mStaticFieldMap; public: CeBuilder() { + mParentBuilder = NULL; mPtrSize = 0; mCeFunction = NULL; mBeFunction = NULL; @@ -417,6 +495,7 @@ public: CeOperand FrameAlloc(BeType* type); CeOperand EmitConst(int64 val, int size); + CeErrorKind EmitConst(Array& arr, BeConstant* constant); CeOperand GetOperand(BeValue* value, bool allowAlloca = false, bool allowImmediate = false); CeSizeClass GetSizeClass(int size); int GetCodePos(); @@ -430,6 +509,7 @@ public: void Emit(int64 val); void Emit(bool val); void Emit(void* ptr, int size); + void EmitZeroes(int size); void EmitJump(CeOp op, const CeOperand& block); void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx); @@ -454,15 +534,24 @@ public: CeFrame() { mFunction = NULL; - mStackAddr = NULL; - mFrameAddr = NULL; + mStackAddr = 0; + mFrameAddr = 0; mInstPtr = NULL; } }; -class CeFunctionRef +class CeStaticFieldInfo { - //CeFunction* ; +public: + BfFieldInstance* mFieldInstance; + addr_ce mAddr; + +public: + CeStaticFieldInfo() + { + mFieldInstance = NULL; + mAddr = 0; + } }; class CeMachine @@ -470,15 +559,22 @@ class CeMachine public: Dictionary mFunctions; Dictionary mNamedFunctionMap; + BfCompiler* mCompiler; BfModule* mCeModule; int mRevision; int mExecuteId; + // These are only valid for the current execution ContiguousHeap* mHeap; Array mCallStack; Array mMemory; Dictionary mStringMap; + int mStringCharsOffset; + Dictionary mReflectMap; + Dictionary mConstDataMap; + Dictionary mStaticFieldMap; + HashSet mStaticCtorExecSet; BfAstNode* mCurTargetSrc; BfModule* mCurModule; @@ -492,24 +588,30 @@ public: void Init(); uint8* CeMalloc(int size); bool CeFree(addr_ce addr); + addr_ce GetReflectType(int typeId); + addr_ce GetString(int stringId); + addr_ce GetConstantData(BeConstant* constant); + BfType* GetBfType(int typeId); BeContext* GetBeContext(); BeModule* GetBeModule(); void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo); - void RemoveMethod(BfMethodInstance* methodInstance); + void RemoveMethod(BfMethodInstance* methodInstance); int GetConstantSize(BfConstant* constant); + CeErrorKind WriteConstant(Array& arr, BeConstant* constVal); void WriteConstant(uint8* ptr, BfConstant* constant); void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr); - void PrepareFunction(CeFunction* methodInstance); + void PrepareFunction(CeFunction* methodInstance, CeBuilder* parentBuilder); CeFunction* GetFunction(BfMethodInstance* methodInstance, BfIRValue func, bool& added); CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance); - + public: void CompileStarted(); void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func); void QueueMethod(BfModuleMethodInstance moduleMethodInstance); + void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName); BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags); };