From 54dc59e0495c1cf70db06627d5c8d792a8306a70 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 6 Jan 2022 06:27:39 -0500 Subject: [PATCH] Allow extending Object and ValueType --- IDEHelper/Compiler/BfContext.cpp | 59 ++++++++++++++++++++-- IDEHelper/Compiler/BfContext.h | 4 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 11 ++-- IDEHelper/Compiler/BfModule.cpp | 70 ++++++++++++++++++++------ IDEHelper/Compiler/BfModule.h | 2 + IDEHelper/Compiler/BfStmtEvaluator.cpp | 2 +- 6 files changed, 126 insertions(+), 22 deletions(-) diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index e6b1778e..c741da06 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -41,7 +41,9 @@ BfContext::BfContext(BfCompiler* compiler) : mSystem = compiler->mSystem; mBfTypeType = NULL; mBfClassVDataPtrType = NULL; - mBfObjectType = NULL; + mBfObjectType = NULL; + mCanSkipObjectCtor = true; + mCanSkipValueTypeCtor = true; mMappedObjectRevision = 0; mDeleting = false; mLockModules = false; @@ -1881,6 +1883,54 @@ void BfContext::UpdateRevisedTypes() BP_ZONE("BfContext::UpdateRevisedTypes"); BfLogSysM("BfContext::UpdateRevisedTypes\n"); + auto _CheckCanSkipCtor = [&](BfTypeDef* typeDef) + { + if (typeDef == NULL) + return true; + typeDef = typeDef->GetLatest(); + + for (auto fieldDef : typeDef->mFields) + { + if (fieldDef->mIsStatic) + continue; + if (fieldDef->mInitializer != NULL) + return false; + } + + for (auto methodDef : typeDef->mMethods) + { + if (methodDef->mMethodType == BfMethodType_Init) + return false; + } + + return true; + }; + + auto _CheckCanSkipCtorByName = [&](const StringImpl& name) + { + BfAtomComposite qualifiedFindName; + if (!mSystem->ParseAtomComposite(name, qualifiedFindName)) + return true; + auto itr = mSystem->mTypeDefs.TryGet(qualifiedFindName); + while (itr) + { + BfTypeDef* typeDef = *itr; + if ((typeDef->mDefState != BfTypeDef::DefState_Deleted) && + (!typeDef->mIsCombinedPartial)) + { + if (typeDef->mFullNameEx == qualifiedFindName) + if (!_CheckCanSkipCtor(typeDef)) + return false; + } + itr.MoveToNextHashMatch(); + } + + return true; + }; + + bool wantsCanSkipObjectCtor = _CheckCanSkipCtorByName("System.Object"); + bool wantsCanSkipValueTypeCtor = _CheckCanSkipCtorByName("System.ValueType"); + int wantPtrSize; if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) | (mCompiler->mOptions.mMachineType == BfMachineType_ARM) || @@ -1888,10 +1938,13 @@ void BfContext::UpdateRevisedTypes() wantPtrSize = 4; else wantPtrSize = 8; - if (wantPtrSize != mSystem->mPtrSize) + + if ((wantPtrSize != mSystem->mPtrSize) || (wantsCanSkipObjectCtor != mCanSkipObjectCtor) || (wantsCanSkipValueTypeCtor != mCanSkipValueTypeCtor)) { - BfLogSysM("Changing pointer size to: %d\n", wantPtrSize); + BfLogSysM("Full rebuild. Pointer: %d CanSkipObjectCtor:%d CanSkipValueTypeCtor:%d\n", wantPtrSize, wantsCanSkipObjectCtor, wantsCanSkipValueTypeCtor); mSystem->mPtrSize = wantPtrSize; + mCanSkipObjectCtor = wantsCanSkipObjectCtor; + mCanSkipValueTypeCtor = wantsCanSkipValueTypeCtor; auto intPtrType = mScratchModule->GetPrimitiveType(BfTypeCode_IntPtr); auto uintPtrType = mScratchModule->GetPrimitiveType(BfTypeCode_UIntPtr); if (intPtrType != NULL) diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 9ae036c2..560ef7d4 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -383,7 +383,9 @@ public: Array mSavedTypeData; BfTypeInstance* mBfTypeType; - BfTypeInstance* mBfObjectType; + BfTypeInstance* mBfObjectType; + bool mCanSkipObjectCtor; + bool mCanSkipValueTypeCtor; BfPointerType* mBfClassVDataPtrType; PtrWorkQueue mReifyModuleWorkList; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b31c7720..ba5ecc8b 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -6815,7 +6815,8 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu return BfTypedValue(); } - auto addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1); + auto& fieldInstance = arrayType->mBaseType->mFieldInstances[0]; + auto addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, fieldInstance.mDataIdx); if (arrayLengthBitCount == 64) mModule->mBfIRBuilder->CreateAlignedStore(mModule->GetConstValue64(numElements), addr, 8); else @@ -13459,6 +13460,10 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr) mModule->Fail("Invalid delegate type", lambdaBindExpr); return; } + mModule->PopulateType(baseDelegateType); + + auto& funcPtrField = baseDelegateType->mFieldInstances[0]; + auto& targetField = baseDelegateType->mFieldInstances[1]; auto baseDelegate = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->MapType(baseDelegateType)); // >> delegate.mTarget = bindResult.mTarget @@ -13468,7 +13473,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr) valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->MapType(nullPtrType)); else valPtr = mModule->GetDefaultValue(nullPtrType); - auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, 2); + auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, targetField.mDataIdx); mModule->mBfIRBuilder->CreateStore(valPtr, fieldPtr); // >> delegate.mFuncPtr = bindResult.mFunc @@ -13476,7 +13481,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr) { auto nullPtrType = mModule->GetPrimitiveType(BfTypeCode_NullPtr); auto valPtr = mModule->mBfIRBuilder->CreateBitCast(lambdaInstance->mClosureFunc, mModule->mBfIRBuilder->MapType(nullPtrType)); - auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, 1); + auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(baseDelegate, 0, funcPtrField.mDataIdx); mModule->mBfIRBuilder->CreateStore(valPtr, fieldPtr); } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 6473ce40..12e68428 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1562,6 +1562,34 @@ BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, boo return mBfIRBuilder->CreateInBoundsGEP(gv, 0, 0); } +void BfModule::FixConstValueParams(BfTypeInstance* typeInst, SizedArrayImpl& valueParams) +{ + if (!typeInst->mTypeDef->mIsCombinedPartial) + return; + + int prevDataIdx = -1; + int usedDataIdx = 0; + if (typeInst->mBaseType != NULL) + usedDataIdx++; + + int startingParamsSize = (int)valueParams.mSize; + for (int fieldIdx = 0; fieldIdx < (int)typeInst->mFieldInstances.size(); fieldIdx++) + { + auto fieldInstance = &typeInst->mFieldInstances[fieldIdx]; + if (fieldInstance->mDataIdx < 0) + continue; + + BF_ASSERT(fieldInstance->mDataIdx > prevDataIdx); + prevDataIdx = fieldInstance->mDataIdx; + + usedDataIdx++; + if (usedDataIdx <= valueParams.mSize) + continue; + + valueParams.Add(GetDefaultValue(fieldInstance->mResolvedType)); + } +} + BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId, bool define) { auto stringTypeInst = ResolveTypeDef(mCompiler->mStringTypeDef, define ? BfPopulateType_Data : BfPopulateType_Declaration)->ToTypeInstance(); @@ -1580,12 +1608,14 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId, SizedArray typeValueParams; GetConstClassValueParam(classVDataGlobal, typeValueParams); + FixConstValueParams(stringTypeInst->mBaseType, typeValueParams); auto objData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst->mBaseType, BfIRPopulateType_Full), typeValueParams); auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize; typeValueParams.clear(); typeValueParams.push_back(objData); + if (lenByteCount == 4) { typeValueParams.push_back(GetConstValue32((int)str.length())); // mLength @@ -1597,17 +1627,8 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId, typeValueParams.push_back(GetConstValue64(0x4000000000000000LL + str.length() + 1)); // mAllocSizeAndFlags } typeValueParams.push_back(stringCharsVal); // mPtr + FixConstValueParams(stringTypeInst, typeValueParams); - for (int fieldIdx = 0; fieldIdx < (int)stringTypeInst->mFieldInstances.size(); fieldIdx++) - { - auto fieldInstance = &stringTypeInst->mFieldInstances[fieldIdx]; - if (fieldInstance->mDataIdx < 4) - continue; - while (fieldInstance->mDataIdx >= typeValueParams.size()) - typeValueParams.Add(BfIRValue()); - typeValueParams[fieldInstance->mDataIdx] = GetDefaultValue(fieldInstance->mResolvedType); - } - stringValData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams); } @@ -5384,9 +5405,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType); auto voidPtrNull = GetDefaultValue(voidPtrType); - SizedArray typeValueParams; + SizedArray typeValueParams; GetConstClassValueParam(typeTypeData, typeValueParams); + FixConstValueParams(mContext->mBfObjectType, typeValueParams); BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams); StringT<128> typeDataName; @@ -5514,6 +5536,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(type->mAlign, byteType), // mAlign GetConstValue(stackCount, byteType), // mAllocStackCountOverride }; + FixConstValueParams(mContext->mBfTypeType, typeDataParams); auto typeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType, BfIRPopulateType_Full), typeDataParams); if (typeInstance == NULL) @@ -5532,6 +5555,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin }; auto reflectPointerType = ResolveTypeDef(mCompiler->mReflectPointerType)->ToTypeInstance(); + FixConstValueParams(reflectPointerType, pointerTypeDataParms); auto pointerTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectPointerType, BfIRPopulateType_Full), pointerTypeDataParms); typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectPointerType), true, BfIRLinkageType_External, pointerTypeData, typeDataName); @@ -5549,6 +5573,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin }; auto reflectRefType = ResolveTypeDef(mCompiler->mReflectRefType)->ToTypeInstance(); + FixConstValueParams(reflectRefType, refTypeDataParms); auto refTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectRefType, BfIRPopulateType_Full), refTypeDataParms); typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectRefType), true, BfIRLinkageType_External, refTypeData, typeDataName); @@ -5566,6 +5591,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin }; auto reflectSizedArrayType = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance(); + FixConstValueParams(reflectSizedArrayType, sizedArrayTypeDataParms); auto sizedArrayTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectSizedArrayType, BfIRPopulateType_Full), sizedArrayTypeDataParms); typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectSizedArrayType), true, BfIRLinkageType_External, sizedArrayTypeData, typeDataName); @@ -5583,6 +5609,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin }; auto reflectConstExprType = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance(); + FixConstValueParams(reflectConstExprType, constExprTypeDataParms); auto ConstExprTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectConstExprType, BfIRPopulateType_Full), constExprTypeDataParms); typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectConstExprType), true, BfIRLinkageType_External, ConstExprTypeData, typeDataName); @@ -6221,7 +6248,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin reflectKind = GetReflectKind(reflectKind, typeInstance); // Fields - BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef); + BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef); BfIRValue emptyValueType = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray()); auto _HandleCustomAttrs = [&](BfCustomAttributes* customAttributes) @@ -6450,6 +6477,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(-1, intType), // mCustomAttributesIdx }; } + FixConstValueParams(reflectFieldDataType->ToTypeInstance(), payloadFieldVals); auto payloadFieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), payloadFieldVals); fieldTypes.push_back(payloadFieldData); } @@ -7129,6 +7157,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin }; BfIRType typeInstanceDataType = mBfIRBuilder->MapTypeInst(typeInstanceType->ToTypeInstance(), BfIRPopulateType_Full); + FixConstValueParams(typeInstanceType->ToTypeInstance(), typeDataVals); auto typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, typeDataVals); if (!needsTypeData) @@ -14188,6 +14217,19 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) return BfTypedValue(globalValue, type, !fieldDef->mIsConst); } +int BfModule::GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName) +{ + if (typeInst->IsDataIncomplete()) + PopulateType(typeInst); + if (fieldIdx >= typeInst->mFieldInstances.mSize) + { + Fail(StrFormat("Invalid field data in type '%s'", TypeToString(typeInst).c_str())); + return 0; + } + auto& fieldInstance = typeInst->mFieldInstances[fieldIdx]; + return fieldInstance.mDataIdx; +} + BfTypedValue BfModule::GetThis() { auto useMethodState = mCurMethodState; @@ -17158,8 +17200,8 @@ void BfModule::EmitCtorBody(bool& skipBody) { auto baseType = mCurTypeInstance->mBaseType; if ((!mCurTypeInstance->IsTypedPrimitive()) && - (baseType->mTypeDef != mCompiler->mValueTypeTypeDef) && - (baseType->mTypeDef != mCompiler->mBfObjectTypeDef)) + ((baseType->mTypeDef != mCompiler->mValueTypeTypeDef) || (!mContext->mCanSkipValueTypeCtor)) && + ((baseType->mTypeDef != mCompiler->mBfObjectTypeDef) || (!mContext->mCanSkipObjectCtor))) { // Try to find a ctor without any params first BfMethodDef* matchedMethod = NULL; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 5832a356..d0c41a88 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1552,6 +1552,7 @@ public: BfIRValue GetDefaultValue(BfType* type); BfTypedValue GetFakeTypedValue(BfType* type); BfTypedValue GetDefaultTypedValue(BfType* type, bool allowRef = false, BfDefaultValueKind defaultValueKind = BfDefaultValueKind_Const); + void FixConstValueParams(BfTypeInstance* typeInst, SizedArrayImpl& valueParams); BfIRValue CreateStringObjectValue(const StringImpl& str, int stringId, bool define); BfIRValue CreateStringCharPtr(const StringImpl& str, int stringId, bool define); int GetStringPoolIdx(BfIRValue constantStr, BfIRConstHolder* constHolder = NULL); @@ -1668,6 +1669,7 @@ public: void HadSlotCountDependency(); BfTypedValue GetCompilerFieldValue(const StringImpl& str); BfTypedValue ReferenceStaticField(BfFieldInstance* fieldInstance); + int GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName = NULL); BfTypedValue GetThis(); BfLocalVariable* GetThisVariable(); bool IsInGeneric(); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 312a94af..8ac88907 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -6580,7 +6580,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt) } else { - auto lengthValAddr = mBfIRBuilder->CreateInBoundsGEP(arrayBaseValue, 0, 1); + auto lengthValAddr = mBfIRBuilder->CreateInBoundsGEP(arrayBaseValue, 0, GetFieldDataIdx(arrayType->mBaseType, 0, "mLength")); lengthVal = mBfIRBuilder->CreateLoad(lengthValAddr); } lengthVal = mBfIRBuilder->CreateNumericCast(lengthVal, true, BfTypeCode_IntPtr);