From f37fb2c1b7292a98774d84237be246aa0430e61c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 11 Feb 2022 05:47:32 -0500 Subject: [PATCH] Comptime improvments, IOn interfaces, const payload enum --- BeefLibs/Beefy2D/src/Utils.bf | 4 +- BeefLibs/corlib/src/Attribute.bf | 20 + BeefLibs/corlib/src/IO/File.bf | 4 +- .../corlib/src/Reflection/CEMethodInfo.bf | 27 + BeefLibs/corlib/src/Type.bf | 11 + IDE/mintest/minlib/src/System/Attribute.bf | 21 + .../minlib/src/System/Reflection/FieldInfo.bf | 14 + IDEHelper/Compiler/BfCompiler.cpp | 14 + IDEHelper/Compiler/BfCompiler.h | 5 + IDEHelper/Compiler/BfContext.cpp | 20 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 83 ++- IDEHelper/Compiler/BfIRBuilder.cpp | 60 +- IDEHelper/Compiler/BfModule.cpp | 123 ++-- IDEHelper/Compiler/BfModule.h | 5 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 541 +++++++++++------- IDEHelper/Compiler/BfResolvedTypeUtils.h | 28 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 2 +- IDEHelper/Compiler/BfSystem.h | 12 + IDEHelper/Compiler/CeMachine.cpp | 236 ++++++-- IDEHelper/Compiler/CeMachine.h | 18 +- 20 files changed, 884 insertions(+), 364 deletions(-) diff --git a/BeefLibs/Beefy2D/src/Utils.bf b/BeefLibs/Beefy2D/src/Utils.bf index 3791b477..a17074d1 100644 --- a/BeefLibs/Beefy2D/src/Utils.bf +++ b/BeefLibs/Beefy2D/src/Utils.bf @@ -181,8 +181,8 @@ namespace Beefy } int fileLen = (.)sr.Length; - if (sr.TryRead(.((.)outBuffer.PrepareBuffer(fileLen), fileLen)) case .Err(let readErr)) - return .Err(.ReadError(readErr)); + if (sr.TryRead(.((.)outBuffer.PrepareBuffer(fileLen), fileLen)) case .Err) + return .Err(.ReadError(.Unknown)); if (onPreFilter != null) onPreFilter(); diff --git a/BeefLibs/corlib/src/Attribute.bf b/BeefLibs/corlib/src/Attribute.bf index eafc1f6c..0cf75859 100644 --- a/BeefLibs/corlib/src/Attribute.bf +++ b/BeefLibs/corlib/src/Attribute.bf @@ -540,6 +540,26 @@ namespace System } } + interface IOnTypeInit + { + void OnTypeInit(Type type, Self* prev) mut; + } + + interface IOnTypeDone + { + void OnTypeDone(Type type, Self* prev) mut; + } + + interface IOnFieldInit + { + void OnFieldInit(ComptimeFieldInfo type, Self* prev) mut; + } + + interface IOnMethodInit + { + void OnMethodInit(ComptimeMethodInfo type, Self* prev) mut; + } + interface IComptimeTypeApply { void ApplyToType(Type type); diff --git a/BeefLibs/corlib/src/IO/File.bf b/BeefLibs/corlib/src/IO/File.bf index 31ef4530..bfae4061 100644 --- a/BeefLibs/corlib/src/IO/File.bf +++ b/BeefLibs/corlib/src/IO/File.bf @@ -44,8 +44,8 @@ namespace System.IO if (bytes == 0) return .Ok; outData.AddRange(.(&buffer, bytes)); - case .Err(let err): - return .Err(err); + case .Err: + return .Err(.Unknown); } } } diff --git a/BeefLibs/corlib/src/Reflection/CEMethodInfo.bf b/BeefLibs/corlib/src/Reflection/CEMethodInfo.bf index 996d4480..dea28095 100644 --- a/BeefLibs/corlib/src/Reflection/CEMethodInfo.bf +++ b/BeefLibs/corlib/src/Reflection/CEMethodInfo.bf @@ -150,4 +150,31 @@ namespace System.Reflection } } } + + [Ordered] + struct ComptimeFieldInfo + { + int64 mNativeFieldInstance; + TypeId mOwner; + TypeId mTypeId; + int32 mFieldIdx; + FieldFlags mFlags; + + public StringView Name + { + get + { + if (Compiler.IsComptime) + return Type.[Friend]Comptime_Field_GetName(mNativeFieldInstance); + return "?"; + } + } + + public Type Owner => Type.[Friend]GetType_((.)mOwner); + public Type FieldType => Type.[Friend]GetType_((.)mTypeId); + public int FieldIdx => mFieldIdx; + public bool IsConst => mFlags.HasFlag(.Const); + public bool IsStatic => mFlags.HasFlag(.Static); + public bool IsInstanceField => !mFlags.HasFlag(.Static) && !mFlags.HasFlag(.Const); + } } diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index eabef8a6..649f9781 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -159,6 +159,7 @@ namespace System .Int16, .Int32, .Int64, + .Int, .Float, .Double: return true; @@ -483,6 +484,15 @@ namespace System } } + public virtual int32 BitSize + { + [Error("This property can only be accessed directly from a typeof() expression")] + get + { + return 0; + } + } + public int32 GetTypeId() { return (int32)mTypeId; @@ -497,6 +507,7 @@ namespace System static extern int64 Comptime_GetMethod(int32 typeId, int32 methodIdx); static extern String Comptime_Method_ToString(int64 methodHandle); static extern String Comptime_Method_GetName(int64 methodHandle); + static extern String Comptime_Field_GetName(int64 fieldHandle); static extern ComptimeMethodInfo.Info Comptime_Method_GetInfo(int64 methodHandle); static extern ComptimeMethodInfo.ParamInfo Comptime_Method_GetParamInfo(int64 methodHandle, int32 paramIdx); diff --git a/IDE/mintest/minlib/src/System/Attribute.bf b/IDE/mintest/minlib/src/System/Attribute.bf index 0af5dd70..ee52a68a 100644 --- a/IDE/mintest/minlib/src/System/Attribute.bf +++ b/IDE/mintest/minlib/src/System/Attribute.bf @@ -1,3 +1,4 @@ +using System.Reflection; namespace System { public struct Attribute @@ -495,6 +496,26 @@ namespace System } } + interface IOnTypeInit + { + void OnTypeInit(Type type, Self* prev) mut; + } + + interface IOnTypeDone + { + void OnTypeDone(Type type, Self* prev) mut; + } + + interface IOnFieldInit + { + void OnFieldInit(ComptimeFieldInfo type, Self* prev) mut; + } + + interface IOnMethodInit + { + void OnMethodInit(ComptimeMethodInfo type, Self* prev) mut; + } + interface IComptimeTypeApply { void ApplyToType(Type type); diff --git a/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf b/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf index 3478a6dd..c819ffb8 100644 --- a/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf +++ b/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf @@ -327,4 +327,18 @@ namespace System.Reflection } } } + + struct ComptimeMethodInfo + { + public int64 mNativeMethodInstance; + } + + struct ComptimeFieldInfo + { + int64 mNativeFieldInstance; + TypeId mOwner; + TypeId mTypeId; + int32 mFieldIdx; + FieldFlags mFlags; + } } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 34f2e7c8..3bcf59c8 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -430,6 +430,11 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mIHashableTypeDef = NULL; mIComptimeTypeApply = NULL; mIComptimeMethodApply = NULL; + mComptimeFieldInfoTypeDef = NULL; + mIOnTypeInitTypeDef = NULL; + mIOnTypeDoneTypeDef = NULL; + mIOnFieldInitTypeDef = NULL; + mIOnMethodInitTypeDef = NULL; mLinkNameAttributeTypeDef = NULL; mCallingConventionAttributeTypeDef = NULL; mMethodRefTypeDef = NULL; @@ -5007,6 +5012,9 @@ void BfCompiler::GetSymbolReferences() if ((fieldDef->mIsConst) && (fieldDef->mInitializer != NULL)) { + BfMethodState methodState; + methodState.mTempKind = BfMethodState::TempKind_Static; + SetAndRestoreValue prevMethodState(module->mCurMethodState, &methodState); BfConstResolver constResolver(module); constResolver.Resolve(fieldDef->mInitializer); } @@ -6825,6 +6833,12 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mIHashableTypeDef = _GetRequiredType("System.IHashable"); mIComptimeTypeApply = _GetRequiredType("System.IComptimeTypeApply"); mIComptimeMethodApply = _GetRequiredType("System.IComptimeMethodApply"); + mComptimeFieldInfoTypeDef = _GetRequiredType("System.Reflection.ComptimeFieldInfo"); + mIOnTypeInitTypeDef = _GetRequiredType("System.IOnTypeInit"); + mIOnTypeDoneTypeDef = _GetRequiredType("System.IOnTypeDone"); + mIOnFieldInitTypeDef = _GetRequiredType("System.IOnFieldInit"); + mIOnMethodInitTypeDef = _GetRequiredType("System.IOnMethodInit"); + mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute"); mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute"); mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 7878ee96..97e84e75 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -390,6 +390,11 @@ public: BfTypeDef* mIHashableTypeDef; BfTypeDef* mIComptimeTypeApply; BfTypeDef* mIComptimeMethodApply; + BfTypeDef* mComptimeFieldInfoTypeDef; + BfTypeDef* mIOnTypeInitTypeDef; + BfTypeDef* mIOnTypeDoneTypeDef; + BfTypeDef* mIOnFieldInitTypeDef; + BfTypeDef* mIOnMethodInitTypeDef; BfTypeDef* mMethodRefTypeDef; BfTypeDef* mNullableTypeDef; diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 48db06c2..c3f29707 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -1684,6 +1684,24 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) BfLogSysM("Deleting Type: %p %s\n", type, mScratchModule->TypeToString(type).c_str()); + if (typeInst != NULL) + { + for (auto& methodInstGroup : typeInst->mMethodInstanceGroups) + { + if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mInCEMachine)) + mCompiler->mCEMachine->RemoveMethod(methodInstGroup.mDefault); + if (methodInstGroup.mMethodSpecializationMap != NULL) + { + for (auto& methodSpecializationItr : *methodInstGroup.mMethodSpecializationMap) + { + auto methodInstance = methodSpecializationItr.mValue; + if (methodInstance->mInCEMachine) + mCompiler->mCEMachine->RemoveMethod(methodInstance); + } + } + } + } + // All dependencies cause rebuilds when we delete types if (dType != NULL) { @@ -1775,7 +1793,7 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) for (auto dependentType : rebuildTypeQueue) RebuildType(dependentType); - } + } } void BfContext::UpdateAfterDeletingTypes() diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 72e6cbfc..f9b8abc2 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2296,26 +2296,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst if (mModule->mCurMethodInstance != NULL) allowSpecializeFail = mModule->mCurMethodInstance->mIsUnspecialized; -// if (mModule->mModuleName == "BeefTest_TestProgram") -// { -// OutputDebugStrF("?Prv: %s\n %s\n?New: %s\n %s\n\n", -// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None, &mBestMethodGenericArguments).c_str(), -// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None).c_str(), -// mModule->MethodToString(methodInstance, BfMethodNameFlag_None, genericArgumentsSubstitute).c_str(), -// mModule->MethodToString(methodInstance, BfMethodNameFlag_None).c_str()); -// } - CompareMethods(prevMethodInstance, &mBestMethodGenericArguments, methodInstance, genericArgumentsSubstitute, &isBetter, &isWorse, allowSpecializeFail); -// if (mModule->mModuleName == "BeefTest_TestProgram") -// { -// OutputDebugStrF("%sPrv: %s\n %s\n%sNew: %s\n %s\n\n", -// isWorse ? "*" : " ", mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None, &mBestMethodGenericArguments).c_str(), -// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None).c_str(), -// isBetter ? "*" : " ", mModule->MethodToString(methodInstance, BfMethodNameFlag_None, genericArgumentsSubstitute).c_str(), -// mModule->MethodToString(methodInstance, BfMethodNameFlag_None).c_str()); -// } - // If we had both a 'better' and 'worse', that's ambiguous because the methods are each better in different ways (not allowed) // And if neither better nor worse then they are equally good, which is not allowed either if (((!isBetter) && (!isWorse)) || ((isBetter) && (isWorse))) @@ -7421,7 +7403,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu argValue = mModule->Cast(refNode, argValue, underlyingType); } else - argValue = mModule->Cast(refNode, argValue, underlyingType); + argValue = mModule->Cast(refNode, argValue, underlyingType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None); if (argValue) argValue = mModule->ToRef(argValue, (BfRefType*)wantType); } @@ -7430,10 +7412,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu if (mModule->mCurMethodState != NULL) { SetAndRestoreValue prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData); - argValue = mModule->Cast(refNode, argValue, wantType); + argValue = mModule->Cast(refNode, argValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None); } else - argValue = mModule->Cast(refNode, argValue, wantType); + argValue = mModule->Cast(refNode, argValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None); } if (!argValue) @@ -8145,10 +8127,8 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst constFailed = true; continue; } - if (argValue.IsValuelessType()) - { + if (resolvedFieldType->IsValuelessType()) continue; - } // Used receiving value? if (argValue.mValue == receivingValue.mValue) @@ -8167,7 +8147,7 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst { // argValue can have a value even if tuplePtr does not have a value. This can happen if we are assigning to a (void) tuple, // but we have a value that needs to be attempted to be casted to void - argValue = mModule->Cast(argValues.mResolvedArgs[tupleFieldIdx].mExpression, argValue, resolvedFieldType); + argValue = mModule->Cast(argValues.mResolvedArgs[tupleFieldIdx].mExpression, argValue, resolvedFieldType, wantConst ? BfCastFlags_WantsConst : BfCastFlags_None); if (wantConst) { if (!argValue.mValue.IsConst()) @@ -10777,9 +10757,55 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie } } } + else if (memberName == "BitSize") + { + auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32); + + BfType* checkType = type; + if (checkType->IsTypedPrimitive()) + checkType = checkType->GetUnderlyingType(); + + if (checkType->IsGenericParam()) + { + mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef); + return true; + } + + if ((typeInstance != NULL) && (typeInstance->IsEnum())) + { + if (typeInstance->mTypeInfoEx != NULL) + { + int64 minValue = typeInstance->mTypeInfoEx->mMinValue; + if (minValue < 0) + minValue = ~minValue; + int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue; + if (maxValue < 0) + maxValue = ~maxValue; + uint64 value = (uint64)minValue | (uint64)maxValue; + + int bitCount = 1; + if (typeInstance->mTypeInfoEx->mMinValue < 0) + bitCount++; + + while (value >>= 1) + bitCount++; + + mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields); + mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type); + return true; + } + } + + int bitSize = checkType->mSize * 8; + if (checkType->GetTypeCode() == BfTypeCode_Boolean) + bitSize = 1; + mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type); + return true; + } else if ((memberName == "MinValue") || (memberName == "MaxValue")) { bool isMin = memberName == "MinValue"; + bool isBitSize = memberName == "BitSize"; BfType* checkType = type; if (checkType->IsTypedPrimitive()) @@ -10833,6 +10859,7 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie { if (typeInstance->mTypeInfoEx != NULL) { + mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields); mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance); return true; } @@ -20693,7 +20720,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, else if (!CheckModifyResult(mResult, unaryOpExpr, "take address of", false, true)) { if (!mResult.IsAddr()) - mResult = mModule->MakeAddressable(mResult); + mResult = mModule->MakeAddressable(mResult, false, true); mResult = BfTypedValue(mResult.mValue, ptrType, false); } else @@ -21409,7 +21436,9 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval); mResult = BfTypedValue(alloca, allocType, true); - MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, false); + auto result = MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, false); + if ((result) && (!result.mType->IsVoid())) + mResult = result; return; } diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 57aba0e6..ecea0415 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -1001,13 +1001,23 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type) return false; } - for (auto& fieldInstance : typeInst->mFieldInstances) + if (typeInst->IsUnion()) { - if (fieldInstance.mDataOffset < 0) - continue; - if (!WriteConstant(aggConstant->mValues[fieldInstance.mDataIdx], (uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType)) + auto innerType = typeInst->GetUnionInnerType(); + if (!WriteConstant(aggConstant->mValues[1], (uint8*)ptr, innerType)) return false; } + + if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum())) + { + for (auto& fieldInstance : typeInst->mFieldInstances) + { + if (fieldInstance.mDataOffset < 0) + continue; + if (!WriteConstant(aggConstant->mValues[fieldInstance.mDataIdx], (uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType)) + return false; + } + } } return true; } @@ -1110,15 +1120,27 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type) irValues.Add(val); } - for (auto& fieldInstance : typeInst->mFieldInstances) + if (typeInst->IsUnion()) { - if (fieldInstance.mDataOffset < 0) - continue; - auto val = ReadConstant((uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType); + auto innerType = typeInst->GetUnionInnerType(); + auto val = ReadConstant(ptr, innerType); if (!val) return BfIRValue(); irValues.Add(val); } + + if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum())) + { + for (auto& fieldInstance : typeInst->mFieldInstances) + { + if (fieldInstance.mDataOffset < 0) + continue; + auto val = ReadConstant((uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType); + if (!val) + return BfIRValue(); + irValues.Add(val); + } + } BfIRType irType; irType.mKind = BfIRTypeData::TypeKind_TypeId; irType.mId = type->mTypeId; @@ -1656,6 +1678,15 @@ String BfIRBuilder::ToString(BfIRValue irValue) { return ToString(constant->mIRType) + " zeroinitializer"; } + else if (constant->mConstType == BfConstType_AggCE) + { + auto constAgg = (BfConstantAggCE*)constant; + return ToString(constAgg->mType) + StrFormat(" aggCe@%p", constAgg->mCEAddr); + } + else if (constant->mConstType == BfConstType_ArrayZero8) + { + return StrFormat("zero8[%d]", constant->mInt32); + } else if (constant->mConstType == BfConstType_TypeOf) { auto typeofConst = (BfTypeOf_Const*)constant; @@ -1666,6 +1697,7 @@ String BfIRBuilder::ToString(BfIRValue irValue) auto typeofConst = (BfTypeOf_WithData_Const*)constant; return "typeof_withData " + mModule->TypeToString(typeofConst->mType); } + else { BF_FATAL("Unhandled"); @@ -1783,7 +1815,15 @@ String BfIRBuilder::ToString(BfIRType irType) } else if (irType.mKind == BfIRTypeData::TypeKind_TypeId) { - return StrFormat("Type Id %d (%s)", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str()); + return StrFormat("Type#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str()); + } + else if (irType.mKind == BfIRTypeData::TypeKind_TypeInstId) + { + return StrFormat("TypeInst#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str()); + } + else if (irType.mKind == BfIRTypeData::TypeKind_TypeInstPtrId) + { + return StrFormat("TypeInstPtr#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str()); } else { @@ -3940,7 +3980,7 @@ BfIRType BfIRBuilder::MapTypeInst(BfTypeInstance* typeInst, BfIRPopulateType pop PopulateType(typeInst, populateType); } - if (!mIgnoreWrites) + if ((!mIgnoreWrites) && (populateType != BfIRPopulateType_Identity)) BF_ASSERT(mTypeMap.ContainsKey(typeInst)); BfIRType retType; retType.mKind = BfIRType::TypeKind_TypeInstId; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 7ca94ec6..f14633bf 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6477,19 +6477,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } - SizedArray fieldTypes; - - enum FieldFlags - { - FieldFlags_Protected = 3, - FieldFlags_Public = 6, - FieldFlags_Static = 0x10, - FieldFlags_Const = 0x40, - FieldFlags_SpecialName = 0x80, - FieldFlags_EnumPayload = 0x100, - FieldFlags_EnumDiscriminator = 0x200, - FieldFlags_EnumCase = 0x400 - }; + SizedArray fieldTypes; bool is32Bit = mCompiler->mSystem->mPtrSize == 4; @@ -6509,7 +6497,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(0, intPtrType), // mData GetConstValue(0, intPtrType), // mDataHi - GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags + GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx }; } @@ -6521,7 +6509,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin payloadNameConst, // mName GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(0, intPtrType), // mData - GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags + GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx }; } @@ -6542,7 +6530,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData GetConstValue(0, intPtrType), // mDataHi - GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags + GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx }; } @@ -6554,7 +6542,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin dscrNameConst, // mName GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData - GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags + GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx }; } @@ -6581,18 +6569,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin else typeId = fieldType->mTypeId; - FieldFlags fieldFlags = (FieldFlags)0; + BfFieldFlags fieldFlags = (BfFieldFlags)0; if (fieldDef->mProtection == BfProtection_Protected) - fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Protected); + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Protected); if (fieldDef->mProtection == BfProtection_Public) - fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Public); + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Public); if (fieldDef->mIsStatic) - fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Static); + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Static); if (fieldDef->mIsConst) - fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Const); + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Const); if (fieldDef->IsEnumCaseEntry()) - fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_EnumCase); + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_EnumCase); int customAttrIdx = _HandleCustomAttrs(fieldInstance->mCustomAttributes); BfIRValue constValue; @@ -11319,7 +11307,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con { newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType)); } - } + } else { auto wantTypeInst = wantType->ToTypeInstance(); @@ -11329,19 +11317,32 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con newVals.Add(baseVal); } - for (auto& fieldInstance : wantTypeInst->mFieldInstances) + if (wantType->IsUnion()) { - if (fieldInstance.mDataIdx < 0) - continue; - auto val = constArray->mValues[fieldInstance.mDataIdx]; - BfIRValue memberVal = ConstantToCurrent(constHolder->GetConstant(val), constHolder, fieldInstance.mResolvedType); - if (fieldInstance.mDataIdx == newVals.mSize) - newVals.Add(memberVal); - else + auto innerType = wantType->ToTypeInstance()->GetUnionInnerType(); + if (!innerType->IsValuelessType()) { - while (fieldInstance.mDataIdx >= newVals.mSize) - newVals.Add(BfIRValue()); - newVals[fieldInstance.mDataIdx] = memberVal; + auto val = ConstantToCurrent(constHolder->GetConstant(constArray->mValues[1]), constHolder, innerType); + newVals.Add(val); + } + } + + if ((!wantType->IsUnion()) || (wantType->IsPayloadEnum())) + { + for (auto& fieldInstance : wantTypeInst->mFieldInstances) + { + if (fieldInstance.mDataIdx < 0) + continue; + auto val = constArray->mValues[fieldInstance.mDataIdx]; + BfIRValue memberVal = ConstantToCurrent(constHolder->GetConstant(val), constHolder, fieldInstance.mResolvedType); + if (fieldInstance.mDataIdx == newVals.mSize) + newVals.Add(memberVal); + else + { + while (fieldInstance.mDataIdx >= newVals.mSize) + newVals.Add(BfIRValue()); + newVals[fieldInstance.mDataIdx] = memberVal; + } } } @@ -11539,7 +11540,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri BfConstResolver constResolver(this); if (allowNonConstArgs) constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst); - + bool inPropSet = false; SizedArray argValues; for (BfExpression* arg : attributesDirective->mArguments) @@ -11743,6 +11744,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri } BfMethodMatcher methodMatcher(attributesDirective, this, "", argValues, BfMethodGenericArguments()); + methodMatcher.mBfEvalExprFlags = constResolver.mBfEvalExprFlags; attrTypeDef = attrTypeInst->mTypeDef; bool success = true; @@ -12969,6 +12971,7 @@ bool BfModule::IsCompatibleInterfaceMethod(BfMethodInstance* iMethodInst, BfMeth if (iMethodInst->GetParamCount() != methodInstance->GetParamCount()) return false; + auto selfType = methodInstance->GetOwner(); for (int paramIdx = 0; paramIdx < (int)iMethodInst->GetParamCount(); paramIdx++) { if (iMethodInst->GetParamKind(paramIdx) != methodInstance->GetParamKind(paramIdx)) @@ -12977,12 +12980,10 @@ bool BfModule::IsCompatibleInterfaceMethod(BfMethodInstance* iMethodInst, BfMeth BfType* iParamType = iMethodInst->GetParamType(paramIdx); BfType* methodParamType = methodInstance->GetParamType(paramIdx); - if (iParamType->IsSelf()) - { - if (methodParamType != methodInstance->GetOwner()) - return false; - } - else if (!iParamType->IsGenericParam()) + iParamType = ResolveSelfType(iParamType, selfType); + methodParamType = ResolveSelfType(methodParamType, selfType); + + if (!iParamType->IsGenericParam()) { if (methodParamType != iParamType) return false; @@ -13730,6 +13731,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM // We haven't processed it yet _SetReified(); CheckHotMethod(methodInstance, ""); + + if (methodInstance->mMethodProcessRequest == NULL) + AddMethodToWorkList(methodInstance); } } } @@ -24120,28 +24124,27 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo if (iMethodInst->mMethodDef->mName == methodInstance->mMethodDef->mName) hadNameMatch = iMethodInst; - bool doesMethodSignatureMatch = CompareMethodSignatures(iMethodInst, methodInstance); - + bool doesMethodSignatureMatch = CompareMethodSignatures(iMethodInst, methodInstance); if ((!doesMethodSignatureMatch) && (iMethodInst->GetNumGenericParams() == 0) && (interfaceMethodEntry->mMethodRef.IsNull())) { doesMethodSignatureMatch = IsCompatibleInterfaceMethod(iMethodInst, methodInstance); } - if ((doesMethodSignatureMatch) && (methodInstance->GetOwner()->IsValueType())) - { - if ((!iMethodInst->mMethodDef->mIsMutating) && (methodInstance->mMethodDef->mIsMutating)) - { - if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface == ifaceInst)) - { - auto error = mCompiler->mPassInstance->Fail(StrFormat("Implementation method '%s' cannot specify 'mut' because the interface method does not allow it", - MethodToString(methodInstance).c_str()), methodInstance->mMethodDef->GetMutNode()); - if (error != NULL) - mCompiler->mPassInstance->MoreInfo(StrFormat("Declare the interface method as 'mut' to allow matching 'mut' implementations"), iMethodInst->mMethodDef->mMethodDeclaration); - showedError = true; - } - } - } - + if ((doesMethodSignatureMatch) && (methodInstance->GetOwner()->IsValueType())) + { + if ((!iMethodInst->mMethodDef->mIsMutating) && (methodInstance->mMethodDef->mIsMutating)) + { + if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface == ifaceInst)) + { + auto error = mCompiler->mPassInstance->Fail(StrFormat("Implementation method '%s' cannot specify 'mut' because the interface method does not allow it", + MethodToString(methodInstance).c_str()), methodInstance->mMethodDef->GetMutNode()); + if (error != NULL) + mCompiler->mPassInstance->MoreInfo(StrFormat("Declare the interface method as 'mut' to allow matching 'mut' implementations"), iMethodInst->mMethodDef->mMethodDeclaration); + showedError = true; + } + } + } + if (doesMethodSignatureMatch) { usedMethod = true; @@ -24455,7 +24458,7 @@ void BfModule::DbgFinish() BfIRValue linkMarker; if (mBfIRBuilder->DbgHasInfo()) - { + { bool needForceLinking = false; for (auto& ownedType : mOwnedTypeInstances) { diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 2ed68f81..ee5aa5a2 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -102,7 +102,8 @@ enum BfCastFlags BfCastFlags_PreferAddr = 0x400, BfCastFlags_WarnOnBox = 0x800, BfCastFlags_IsCastCheck = 0x1000, - BfCastFlags_IsConstraintCheck = 0x2000, + BfCastFlags_IsConstraintCheck = 0x2000, + BfCastFlags_WantsConst = 0x4000 }; enum BfCastResultFlags @@ -1762,7 +1763,7 @@ public: void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext); BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src); void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode); - void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet foundAttributes, bool underlyingTypeDeferred); + void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary& foundAttributes, bool underlyingTypeDeferred); void CEMixin(BfAstNode* refNode, const StringImpl& src); void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred); void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index a8bc79a0..e57976ee 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2139,96 +2139,181 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn } } -void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet foundAttributes, bool underlyingTypeDeferred) +void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary& prevAttrInstances, bool underlyingTypeDeferred) { - BfTypeInstance* iComptimeTypeApply = NULL; for (auto& customAttribute : customAttributes->mAttributes) { auto attrType = customAttribute.mType; - mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); - if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) + + BfMethodInstance* methodInstance = NULL; + bool isFieldApply = false; + BfIRValue irValue; + int checkDepth = 0; + auto checkAttrType = attrType; + while (checkAttrType != NULL) + { + mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods); + if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) + break; + + for (auto& ifaceEntry : checkAttrType->mInterfaces) + { + isFieldApply = false; + isFieldApply = (ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnFieldInitTypeDef)); + + if ((isFieldApply) || + ((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeTypeApply))) || + ((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeInitTypeDef))) || + ((ceEmitContext == NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeDoneTypeDef)))) + { + // Passes + } + else + continue; + + prevAttrInstances.TryGetValue(checkAttrType, &irValue); + methodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef; + break; + } + if (methodInstance != NULL) + break; + + checkAttrType = checkAttrType->mBaseType; + checkDepth++; + } + + if (methodInstance == NULL) continue; - for (auto& ifaceEntry : attrType->mInterfaces) - { - if (iComptimeTypeApply == NULL) - iComptimeTypeApply = ResolveTypeDef(mCompiler->mIComptimeTypeApply)->ToTypeInstance(); - if (ifaceEntry.mInterfaceType != iComptimeTypeApply) - continue; - - if (!foundAttributes.Add(attrType)) - continue; - - BfMethodInstance* methodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef; - if (methodInstance == NULL) - continue; - - SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, ceEmitContext); - auto ceContext = mCompiler->mCEMachine->AllocContext(); + SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, ceEmitContext); + auto ceContext = mCompiler->mCEMachine->AllocContext(); - BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute); + BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute); + for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++) + attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0); - SizedArray args; - if (!attrType->IsValuelessType()) - args.Add(attrVal); + SizedArray args; + if (!attrType->IsValuelessType()) + args.Add(attrVal); + if (isFieldApply) + { + auto fieldDef = fieldInstance->GetFieldDef(); + BfFieldFlags fieldFlags = (BfFieldFlags)0; + + if (fieldDef->mProtection == BfProtection_Protected) + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Protected); + if (fieldDef->mProtection == BfProtection_Public) + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Public); + if (fieldDef->mIsStatic) + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Static); + if (fieldDef->mIsConst) + fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Const); + + auto fieldInfoType = ResolveTypeDef(mCompiler->mComptimeFieldInfoTypeDef); + if (fieldInfoType != NULL) + { + SizedArray fieldData = + { + mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity)), + GetConstValue((uint64)(intptr)fieldInstance, GetPrimitiveType(BfTypeCode_Int64)), // mNativeFieldInstance + GetConstValue(typeInstance->mTypeId, GetPrimitiveType(BfTypeCode_Int32)), // mOwner + GetConstValue((fieldInstance->mResolvedType != NULL) ? fieldInstance->mResolvedType->mTypeId : 0, GetPrimitiveType(BfTypeCode_Int32)), // mTypeId + GetConstValue(fieldDef->mIdx, GetPrimitiveType(BfTypeCode_Int32)), // mFieldIdx + GetConstValue((int)fieldFlags, GetPrimitiveType(BfTypeCode_Int16)), // mFieldFlags + }; + FixConstValueParams(fieldInfoType->ToTypeInstance(), fieldData); + auto fieldDataAgg = mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity), fieldData); + args.Add(fieldDataAgg); + } + } + else args.Add(mBfIRBuilder->CreateTypeOf(typeInstance)); - DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred); - auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL); - - if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted) - return; - - if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit) - { - // We populated before we could finish - AssertErrorState(); - } + if (methodInstance->GetParamCount() > 1) + { + if (irValue) + args.Add(irValue); else + args.Add(mBfIRBuilder->CreateConstNull()); + } + else + { + // Only allow a single instance + if (irValue) + continue; + } + + DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred); + if (fieldInstance != NULL) + mCompiler->mCEMachine->mFieldInstanceSet.Add(fieldInstance); + BfTypedValue result; + /// + { + SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); + result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_ForceReturnThis, NULL); + } + if (fieldInstance != NULL) + mCompiler->mCEMachine->mFieldInstanceSet.Remove(fieldInstance); + if (result.mType == methodInstance->GetOwner()) + prevAttrInstances[methodInstance->GetOwner()] = result.mValue; + + if (ceEmitContext == NULL) + continue; + + if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted) + return; + + if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit) + { + // We populated before we could finish + AssertErrorState(); + } + else + { + auto owner = methodInstance->GetOwner(); + int typeId = owner->mTypeId; + if ((!result) && (mCompiler->mFastFinish)) { - auto owner = methodInstance->GetOwner(); - int typeId = owner->mTypeId; - if ((!result) && (mCompiler->mFastFinish)) + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) + typeInstance->mCeTypeInfo->mNext->mFailed = true; + if (typeInstance->mCeTypeInfo != NULL) { - if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) - typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); - if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) - typeInstance->mCeTypeInfo->mNext->mFailed = true; - if (typeInstance->mCeTypeInfo != NULL) + BfCeTypeEmitEntry* entry = NULL; + if (typeInstance->mCeTypeInfo->mTypeIFaceMap.TryGetValue(typeId, &entry)) { - BfCeTypeEmitEntry* entry = NULL; - if (typeInstance->mCeTypeInfo->mTypeIFaceMap.TryGetValue(typeId, &entry)) - { - ceEmitContext->mEmitData = entry->mEmitData; - } + ceEmitContext->mEmitData = entry->mEmitData; } } - else if (ceEmitContext->HasEmissions()) - { - if (typeInstance->mCeTypeInfo == NULL) - typeInstance->mCeTypeInfo = new BfCeTypeInfo(); - if (typeInstance->mCeTypeInfo->mNext == NULL) - typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); + } + else if (ceEmitContext->HasEmissions()) + { + if (typeInstance->mCeTypeInfo == NULL) + typeInstance->mCeTypeInfo = new BfCeTypeInfo(); + if (typeInstance->mCeTypeInfo->mNext == NULL) + typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); - BfCeTypeEmitEntry entry; - entry.mEmitData = ceEmitContext->mEmitData; - typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; - } - - if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish)) - { - String ctxStr = "comptime ApplyToType of "; - ctxStr += TypeToString(attrType); - ctxStr += " to "; - ctxStr += TypeToString(typeInstance); - ctxStr += " "; - ctxStr += customAttribute.mRef->LocationToString(); - UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, customAttribute.mRef); - } + BfCeTypeEmitEntry entry; + entry.mEmitData = ceEmitContext->mEmitData; + typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; } - mCompiler->mCEMachine->ReleaseContext(ceContext); + if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish)) + { + String ctxStr = "comptime "; + ctxStr += methodInstance->mMethodDef->mName; + ctxStr += " of "; + ctxStr += TypeToString(attrType); + ctxStr += " to "; + ctxStr += TypeToString(typeInstance); + ctxStr += " "; + ctxStr += customAttribute.mRef->LocationToString(); + UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, customAttribute.mRef); + } } + + mCompiler->mCEMachine->ReleaseContext(ceContext); } } @@ -2306,16 +2391,17 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code) void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred) { - HashSet foundAttributes; + Dictionary prevAttrInstances; + + if (typeInstance->mCustomAttributes != NULL) + HandleCEAttributes(ceEmitContext, typeInstance, NULL, typeInstance->mCustomAttributes, prevAttrInstances, underlyingTypeDeferred); + if (ceEmitContext != NULL) { - if (typeInstance->mCustomAttributes != NULL) - HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes, underlyingTypeDeferred); - for (auto& fieldInstance : typeInstance->mFieldInstances) { if (fieldInstance.mCustomAttributes != NULL) - HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes, underlyingTypeDeferred); + HandleCEAttributes(ceEmitContext, typeInstance, &fieldInstance, fieldInstance.mCustomAttributes, prevAttrInstances, underlyingTypeDeferred); } } @@ -2357,7 +2443,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* if (onCompileAttribute == NULL) continue; - HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes, underlyingTypeDeferred); + HandleCEAttributes(ceEmitContext, typeInstance, NULL, customAttributes, prevAttrInstances, underlyingTypeDeferred); if (onCompileAttribute->mCtorArgs.size() < 1) continue; @@ -2477,114 +2563,155 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance) CeEmitContext ceEmitContext; ceEmitContext.mMethodInstance = methodInstance; + + Dictionary prevAttrInstances; - BfTypeInstance* iComptimeMethodApply = NULL; for (auto& customAttribute : customAttributes->mAttributes) { auto attrType = customAttribute.mType; - mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); - if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) - continue; + + BfMethodInstance* applyMethodInstance = NULL; + BfIRValue irValue; + int checkDepth = 0; + auto checkAttrType = attrType; - for (auto& ifaceEntry : attrType->mInterfaces) + while (checkAttrType != NULL) { - if (iComptimeMethodApply == NULL) - iComptimeMethodApply = ResolveTypeDef(mCompiler->mIComptimeMethodApply)->ToTypeInstance(); - if (ifaceEntry.mInterfaceType != iComptimeMethodApply) + mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods); + if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) + break; + + for (auto& ifaceEntry : checkAttrType->mInterfaces) + { + if ((!ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeMethodApply)) && + (!ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnMethodInitTypeDef))) + continue; + + prevAttrInstances.TryGetValue(checkAttrType, &irValue); + applyMethodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef; + break; + } + + if (applyMethodInstance != NULL) + break; + + checkAttrType = checkAttrType->mBaseType; + checkDepth++; + } + + if (applyMethodInstance == NULL) + continue; + + SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, &ceEmitContext); + auto ceContext = mCompiler->mCEMachine->AllocContext(); + + BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute); + for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++) + attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0); + + SizedArray args; + if (!attrType->IsValuelessType()) + args.Add(attrVal); + args.Add(mBfIRBuilder->CreateConst(BfTypeCode_UInt64, (uint64)(intptr)methodInstance)); + if (applyMethodInstance->GetParamCount() > 1) + { + if (irValue) + args.Add(irValue); + else + args.Add(mBfIRBuilder->CreateConstNull()); + } + else + { + // Only allow a single instance + if (irValue) continue; + } -// if (!foundAttributes.Add(attrType)) -// continue; + mCompiler->mCEMachine->mMethodInstanceSet.Add(methodInstance); - BfMethodInstance* applyMethodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef; - if (applyMethodInstance == NULL) - continue; - - SetAndRestoreValue prevEmitContext(mCompiler->mCEMachine->mCurEmitContext, &ceEmitContext); - auto ceContext = mCompiler->mCEMachine->AllocContext(); - - BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute); - - SizedArray args; - if (!attrType->IsValuelessType()) - args.Add(attrVal); - args.Add(mBfIRBuilder->CreateConst(BfTypeCode_UInt64, (uint64)(intptr)methodInstance)); - mCompiler->mCEMachine->mMethodInstanceSet.Add(methodInstance); - - //TESTING + //TESTING // mCompiler->mCEMachine->ReleaseContext(ceContext); // ceContext = mCompiler->mCEMachine->AllocContext(); // ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize; + - auto activeTypeDef = typeInstance->mTypeDef; - auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL); + auto activeTypeDef = typeInstance->mTypeDef; + + //auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL); + BfTypedValue result; + /// + { + SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); + result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_ForceReturnThis, NULL); + } + if (result.mType == methodInstance->GetOwner()) + prevAttrInstances[methodInstance->GetOwner()] = result.mValue; - if ((!result) && (mCompiler->mFastFinish)) - { - methodInstance->mCeCancelled = true; - } - - if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty())) - { - String src; - src += "// Code emission in comptime ApplyToMethod of "; - src += TypeToString(attrType); - src += " to "; - src += MethodToString(methodInstance); - src += " "; - src += customAttribute.mRef->LocationToString(); - src += "\n"; - - //auto emitTypeDef = typeInstance->mCeTypeInfo->mNext->mTypeDef; - //auto emitParser = emitTypeDef->mSource->ToParser(); - - //auto emitParser = activeTypeDef->mEmitParser; - - BfReducer bfReducer; - //bfReducer.mSource = emitParser; - bfReducer.mPassInstance = mCompiler->mPassInstance; - bfReducer.mSystem = mSystem; - bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration; - bfReducer.mCurMethodDecl = BfNodeDynCast(methodInstance->mMethodDef->mMethodDeclaration); - - if (!ceEmitContext.mEmitData.IsEmpty()) - { - SetAndRestoreValue prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef); - - String entrySrc = src; - if (mCurTypeInstance->mTypeDef->mEmitParent != NULL) - entrySrc += "\n\n"; - entrySrc += src; - entrySrc += ceEmitContext.mEmitData; - BfCEParseContext ceParseContext = CEEmitParse(typeInstance, entrySrc); - auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser(); - bfReducer.mSource = emitParser; - bfReducer.mAlloc = emitParser->mAlloc; - bfReducer.HandleBlock(emitParser->mRootNode, false); - Visit(emitParser->mRootNode); - FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext); - } - - if (!ceEmitContext.mExitEmitData.IsEmpty()) - { - String exitSrc; - if (mCurTypeInstance->mTypeDef->mEmitParent != NULL) - exitSrc += "\n\n"; - exitSrc += src; - exitSrc += ceEmitContext.mExitEmitData; - BfCEParseContext ceParseContext = CEEmitParse(typeInstance, exitSrc); - auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser(); - bfReducer.mSource = emitParser; - bfReducer.mAlloc = emitParser->mAlloc; - bfReducer.HandleBlock(emitParser->mRootNode, false); - auto deferredBlock = AddDeferredBlock(emitParser->mRootNode, &mCurMethodState->mHeadScope); - deferredBlock->mEmitRefNode = customAttribute.mRef; - FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext); - } - } - - mCompiler->mCEMachine->ReleaseContext(ceContext); + if ((!result) && (mCompiler->mFastFinish)) + { + methodInstance->mCeCancelled = true; } + + if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty())) + { + String src; + src += "// Code emission in comptime ApplyToMethod of "; + src += TypeToString(attrType); + src += " to "; + src += MethodToString(methodInstance); + src += " "; + src += customAttribute.mRef->LocationToString(); + src += "\n"; + + //auto emitTypeDef = typeInstance->mCeTypeInfo->mNext->mTypeDef; + //auto emitParser = emitTypeDef->mSource->ToParser(); + + //auto emitParser = activeTypeDef->mEmitParser; + + BfReducer bfReducer; + //bfReducer.mSource = emitParser; + bfReducer.mPassInstance = mCompiler->mPassInstance; + bfReducer.mSystem = mSystem; + bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration; + bfReducer.mCurMethodDecl = BfNodeDynCast(methodInstance->mMethodDef->mMethodDeclaration); + + if (!ceEmitContext.mEmitData.IsEmpty()) + { + SetAndRestoreValue prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef); + + String entrySrc = src; + if (mCurTypeInstance->mTypeDef->mEmitParent != NULL) + entrySrc += "\n\n"; + entrySrc += src; + entrySrc += ceEmitContext.mEmitData; + BfCEParseContext ceParseContext = CEEmitParse(typeInstance, entrySrc); + auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser(); + bfReducer.mSource = emitParser; + bfReducer.mAlloc = emitParser->mAlloc; + bfReducer.HandleBlock(emitParser->mRootNode, false); + Visit(emitParser->mRootNode); + FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext); + } + + if (!ceEmitContext.mExitEmitData.IsEmpty()) + { + String exitSrc; + if (mCurTypeInstance->mTypeDef->mEmitParent != NULL) + exitSrc += "\n\n"; + exitSrc += src; + exitSrc += ceEmitContext.mExitEmitData; + BfCEParseContext ceParseContext = CEEmitParse(typeInstance, exitSrc); + auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser(); + bfReducer.mSource = emitParser; + bfReducer.mAlloc = emitParser->mAlloc; + bfReducer.HandleBlock(emitParser->mRootNode, false); + auto deferredBlock = AddDeferredBlock(emitParser->mRootNode, &mCurMethodState->mHeadScope); + deferredBlock->mEmitRefNode = customAttribute.mRef; + FinishCEParseContext(customAttribute.mRef, typeInstance, &ceParseContext); + } + } + + mCompiler->mCEMachine->ReleaseContext(ceContext); } } @@ -4183,15 +4310,46 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (!fieldInstance->mFieldIncluded) continue; + if (fieldInstance->mCustomAttributes != NULL) + { + // Already handled + } + else if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL)) + { + if (auto propDecl = BfNodeDynCast(fieldDef->mFieldDeclaration)) + { + // Handled elsewhere + } + else + { + BfTypeState typeState; + typeState.mPrevState = mContext->mCurTypeState; + typeState.mCurFieldDef = fieldDef; + typeState.mCurTypeDef = fieldDef->mDeclaringType; + typeState.mType = typeInstance; + SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); + + fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field); + + for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes) + { + if (TypeToString(customAttr.mType) == "System.ThreadStaticAttribute") + { + if ((!fieldDef->mIsStatic) || (fieldDef->mIsConst)) + { + Fail("ThreadStatic attribute can only be used on static fields", fieldDef->mFieldDeclaration->mAttributes); + } + } + } + } + } + if (resolvedFieldType == NULL) { if ((underlyingType != NULL) || (typeInstance->IsPayloadEnum())) continue; } - if (!fieldInstance->mFieldIncluded) - continue; - if (fieldDef == NULL) continue; @@ -4226,6 +4384,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } } } + + } bool tryCE = true; @@ -4473,38 +4633,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy AddDependency(resolvedFieldType, typeInstance, BfDependencyMap::DependencyFlag_StaticValue); } - auto fieldDef = fieldInstance->GetFieldDef(); - - BF_ASSERT(fieldInstance->mCustomAttributes == NULL); - if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL)) - { - if (auto propDecl = BfNodeDynCast(fieldDef->mFieldDeclaration)) - { - // Handled elsewhere - } - else - { - BfTypeState typeState; - typeState.mPrevState = mContext->mCurTypeState; - typeState.mCurFieldDef = fieldDef; - typeState.mCurTypeDef = fieldDef->mDeclaringType; - typeState.mType = typeInstance; - SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); - - fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field); - - for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes) - { - if (TypeToString(customAttr.mType) == "System.ThreadStaticAttribute") - { - if ((!fieldDef->mIsStatic) || (fieldDef->mIsConst)) - { - Fail("ThreadStatic attribute can only be used on static fields", fieldDef->mFieldDeclaration->mAttributes); - } - } - } - } - } + auto fieldDef = fieldInstance->GetFieldDef(); if (fieldInstance->mResolvedType != NULL) { @@ -12896,7 +13025,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp { BfTypedValue result; BfExprEvaluator exprEvaluator(this); - exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp; + exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp; + if ((castFlags & BfCastFlags_WantsConst) != 0) + exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_Comptime); auto methodDeclaration = BfNodeDynCast(methodMatcher.mBestMethodDef->mMethodDeclaration); if ((methodDeclaration != NULL) && (methodDeclaration->mBody == NULL)) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 4b35ee81..6aec80b7 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1383,9 +1383,11 @@ public: public: BfFieldDef* GetFieldDef(); - BfFieldInstance(const BfFieldInstance& copyFrom) + BfFieldInstance(BfFieldInstance&& copyFrom) { - BF_ASSERT(copyFrom.mCustomAttributes == NULL); + mCustomAttributes = copyFrom.mCustomAttributes; + copyFrom.mCustomAttributes = NULL; + mOwner = copyFrom.mOwner; mResolvedType = copyFrom.mResolvedType; @@ -1404,6 +1406,28 @@ public: mLastRevisionReferenced = copyFrom.mLastRevisionReferenced; } + BfFieldInstance(const BfFieldInstance& copyFrom) + { + BF_ASSERT(copyFrom.mCustomAttributes == NULL); + + mOwner = copyFrom.mOwner; + mResolvedType = copyFrom.mResolvedType; + + mCustomAttributes = copyFrom.mCustomAttributes; + mConstIdx = copyFrom.mConstIdx; + mFieldIdx = copyFrom.mFieldIdx; + mDataIdx = copyFrom.mDataIdx; + mMergedDataIdx = copyFrom.mMergedDataIdx; + mDataOffset = copyFrom.mDataOffset; + mDataSize = copyFrom.mDataSize; + mFieldIncluded = copyFrom.mFieldIncluded; + mIsEnumPayloadCase = copyFrom.mIsEnumPayloadCase; + mIsThreadLocal = copyFrom.mIsThreadLocal; + mIsInferredType = copyFrom.mIsInferredType; + mHadConstEval = copyFrom.mHadConstEval; + mLastRevisionReferenced = copyFrom.mLastRevisionReferenced; + } + BfFieldInstance() { mFieldIdx = -1; diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 6c528bba..4b5fd9b9 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -2981,7 +2981,7 @@ BfTypedValue BfModule::HandleCaseBind(BfTypedValue enumVal, const BfTypedValue& if (type->IsEnum()) { auto enumType = (BfTypeInstance*)type; - for (auto fieldInstance : enumType->mFieldInstances) + for (auto& fieldInstance : enumType->mFieldInstances) { auto fieldDef = fieldInstance.GetFieldDef(); if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()) && (fieldDef->mName == findName)) diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index fad865ab..903b16db 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1471,6 +1471,18 @@ enum BfOptionFlags }; +enum BfFieldFlags +{ + BfFieldFlags_Protected = 3, + BfFieldFlags_Public = 6, + BfFieldFlags_Static = 0x10, + BfFieldFlags_Const = 0x40, + BfFieldFlags_SpecialName = 0x80, + BfFieldFlags_EnumPayload = 0x100, + BfFieldFlags_EnumDiscriminator = 0x200, + BfFieldFlags_EnumCase = 0x400 +}; + enum BfReflectKind { BfReflectKind_None = 0, diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 5d0e51ac..37c31a81 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -3376,7 +3376,7 @@ void CeContext::PrepareConstStructEntry(CeConstStructData& constEntry) bool CeContext::CheckMemory(addr_ce addr, int32 size) { - if (((addr)-0x10000) + (size) > (mMemory.mSize - 0x10000)) + if ((addr < 0x10000) || (addr + size > mMemory.mSize)) return false; return true; } @@ -3441,10 +3441,12 @@ bool CeContext::GetStringFromStringView(addr_ce addr, StringImpl& str) addr_ce charsPtr = *(addr_ce*)(mMemory.mVals + addr); int32 len = *(int32*)(mMemory.mVals + addr + ptrSize); - if (!CheckMemory(charsPtr, len)) - return false; - - str.Append((const char*)(mMemory.mVals + charsPtr), len); + if (len > 0) + { + if (!CheckMemory(charsPtr, len)) + return false; + str.Append((const char*)(mMemory.mVals + charsPtr), len); + } return true; } @@ -3595,6 +3597,19 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta return false; } + if (typeInst->IsPayloadEnum()) + { + auto innerType = typeInst->GetUnionInnerType(); + if (!innerType->IsValuelessType()) + { + auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[1]); + if (fieldConstant == NULL) + return false; + if (!WriteConstant(module, addr, fieldConstant, innerType)) + return false; + } + } + for (auto& fieldInstance : typeInst->mFieldInstances) { if (fieldInstance.mDataOffset < 0) @@ -3611,9 +3626,15 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta } if (constant->mConstType == BfConstType_AggZero) - { + { BF_ASSERT(type->IsComposite()); - memset(mMemory.mVals + addr, 0, type->mSize); + memset(mMemory.mVals + addr, 0, type->mSize); + return true; + } + + if (constant->mConstType == BfConstType_ArrayZero8) + { + memset(mMemory.mVals + addr, 0, constant->mInt32); return true; } @@ -3722,6 +3743,29 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta return true; } + if (constant->mConstType == BfConstType_ExtractValue) + { + Array extractStack; + auto checkConstant = constant; + while (true) + { + if (checkConstant == NULL) + break; + + if (checkConstant->mConstType == BfConstType_ExtractValue) + { + auto gepConst = (BfConstantExtractValue*)constant; + BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget); + checkConstant = module->mBfIRBuilder->GetConstant(targetConst); + extractStack.Add(gepConst); + continue; + } + + if (checkConstant->mConstType == BfConstType_AggCE) + return WriteConstant(module, addr, checkConstant, type, isParams); + } + } + return false; } @@ -3926,8 +3970,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType if (typeInst->IsInstanceOf(ceModule->mCompiler->mTypeTypeDef)) { - addr_ce addr = *(addr_ce*)(instData); - int typeId = GetTypeIdFromType(addr); + int typeId = GetTypeIdFromType(instData - mMemory.mVals); if (typeId <= 0) { Fail("Unable to locate return type type"); @@ -3950,13 +3993,20 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType return BfIRValue(); fieldVals.Add(result); } - - if (typeInst->mIsUnion) + + if (typeInst->IsUnion()) { - auto unionInnerType = typeInst->GetUnionInnerType(); - fieldVals.Add(CreateConstant(module, ptr, unionInnerType, outType)); + auto innerType = typeInst->GetUnionInnerType(); + if (!innerType->IsValuelessType()) + { + auto result = CreateConstant(module, instData, innerType); + if (!result) + return BfIRValue(); + fieldVals.Add(result); + } } - else + + if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum())) { for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.size(); fieldIdx++) { @@ -3997,7 +4047,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType fieldVal = irBuilder->CreateConstArrayZero(0); } - auto instResult = irBuilder->CreateConstAgg(irBuilder->MapTypeInst(typeInst, BfIRPopulateType_Full), fieldVals); + auto instResult = irBuilder->CreateConstAgg(irBuilder->MapTypeInst(typeInst, BfIRPopulateType_Identity), fieldVals); return instResult; } @@ -4156,14 +4206,30 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns int thisArgIdx = -1; int appendAllocIdx = -1; bool hasAggData = false; - if (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor) + if (!methodInstance->mMethodDef->mIsStatic) { if (!methodInstance->GetOwner()->IsValuelessType()) { thisArgIdx = 0; - auto constant = module->mBfIRBuilder->GetConstant(args[0]); - if ((constant != NULL) && (constant->mConstType == BfConstType_AggCE)) - hasAggData = true; + auto checkConstant = module->mBfIRBuilder->GetConstant(args[0]); + while (checkConstant != NULL) + { + if ((checkConstant != NULL) && (checkConstant->mConstType == BfConstType_AggCE)) + { + hasAggData = true; + break; + } + + if (checkConstant->mConstType == BfConstType_ExtractValue) + { + auto gepConst = (BfConstantExtractValue*)checkConstant; + BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget); + checkConstant = module->mBfIRBuilder->GetConstant(targetConst); + continue; + } + + break; + } } if ((methodInstance->GetParamCount() >= 1) && (methodInstance->GetParamKind(0) == BfParamKind_AppendIdx)) @@ -4181,14 +4247,12 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns paramType = methodInstance->GetParamType(paramIdx); if (paramType->IsTypedPrimitive()) paramType = paramType->GetUnderlyingType(); - if (!paramType->IsValuelessType()) + if ((!paramType->IsValuelessType()) && (!paramType->IsVar())) break; } - if (paramType->IsComposite()) - { - paramCompositeSize += paramType->mSize; - } - + + BfType* compositeType = paramType->IsComposite() ? paramType : NULL; + auto arg = args[argIdx]; bool isConst = arg.IsConst(); if (isConst) @@ -4203,6 +4267,17 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns // else // isConst = false; } + else if (((constant->mConstType == BfConstType_AggZero) || (constant->mConstType == BfConstType_Agg)) && + ((paramType->IsPointer()) || (paramType->IsRef()))) + compositeType = paramType->GetUnderlyingType(); + } + + if (compositeType != NULL) + { + if ((paramType->IsPointer()) || (paramType->IsRef())) + paramCompositeSize += paramType->GetUnderlyingType()->mSize; + else + paramCompositeSize += paramType->mSize; } if (!isConst) @@ -4252,6 +4327,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns BfTypeInstance* thisType = methodInstance->GetOwner(); addr_ce allocThisInstAddr = 0; addr_ce allocThisAddr = 0; + addr_ce thisAddr = 0; int allocThisSize = -1; if ((thisArgIdx != -1) && (!hasAggData)) @@ -4294,6 +4370,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns allocThisInstAddr = allocThisPtr - memStart; allocThisAddr = allocThisInstAddr; + thisAddr = allocThisAddr; } addr_ce allocAppendIdxAddr = 0; @@ -4327,7 +4404,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns paramType = methodInstance->GetParamType(paramIdx); if (paramType->IsTypedPrimitive()) paramType = paramType->GetUnderlyingType(); - if (!paramType->IsValuelessType()) + if ((!paramType->IsValuelessType()) && (!paramType->IsVar())) break; } @@ -4357,10 +4434,14 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns } auto constant = module->mBfIRBuilder->GetConstant(arg); - if (paramType->IsComposite()) + BfType* compositeType = paramType->IsComposite() ? paramType : NULL; + if (((constant->mConstType == BfConstType_AggZero) || (constant->mConstType == BfConstType_Agg)) && + ((paramType->IsPointer()) || (paramType->IsRef()))) + compositeType = paramType->GetUnderlyingType(); + if (compositeType != NULL) { - useCompositeAddr -= paramType->mSize; - if (!WriteConstant(module, useCompositeAddr, constant, paramType, isParams)) + useCompositeAddr -= compositeType->mSize; + if (!WriteConstant(module, useCompositeAddr, constant, compositeType, isParams)) { Fail(StrFormat("Failed to process argument for param '%s'", methodInstance->GetParamName(paramIdx).c_str())); return BfTypedValue(); @@ -4369,17 +4450,47 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns stackPtr -= ceModule->mSystem->mPtrSize; int64 addr64 = useCompositeAddr; + if (argIdx == thisArgIdx) + thisAddr = addr64; memcpy(stackPtr, &addr64, ceModule->mSystem->mPtrSize); - } + } else - { + { stackPtr -= paramType->mSize; - if (!WriteConstant(module, stackPtr - memStart, constant, paramType, isParams)) + auto useCompositeAddr = stackPtr - memStart; + if (!WriteConstant(module, useCompositeAddr, constant, paramType, isParams)) { Fail(StrFormat("Failed to process argument for param '%s'", methodInstance->GetParamName(paramIdx).c_str())); return BfTypedValue(); } _FixVariables(); + + if (argIdx == thisArgIdx) + { + auto checkConstant = constant; + while (checkConstant != NULL) + { + if ((checkConstant != NULL) && (checkConstant->mConstType == BfConstType_AggCE)) + { + auto constAggData = (BfConstantAggCE*)checkConstant; + if (paramType->IsPointer()) + thisAddr = constAggData->mCEAddr; + else + thisAddr = useCompositeAddr; + break; + } + + if (checkConstant->mConstType == BfConstType_ExtractValue) + { + auto gepConst = (BfConstantExtractValue*)checkConstant; + BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget); + checkConstant = module->mBfIRBuilder->GetConstant(targetConst); + continue; + } + + break; + } + } } } @@ -4399,16 +4510,18 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns addr_ce retInstAddr = retAddr; - if (returnType->IsInstanceOf(mCeMachine->mCompiler->mTypeTypeDef)) - { - // Allow - } - else if ((returnType->IsObject()) || (returnType->IsPointer())) + if ((returnType->IsObject()) || (returnType->IsPointer())) { // Or pointer? retInstAddr = *(addr_ce*)(memStart + retAddr); } + if ((flags & CeEvalFlags_ForceReturnThis) != 0) + { + returnType = thisType; + retInstAddr = thisAddr; + } + BfTypedValue returnValue; if (success) @@ -4452,7 +4565,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns } else if (returnType->IsComposite()) { - returnValue = BfTypedValue(module->mBfIRBuilder->CreateConstArrayZero(module->mBfIRBuilder->MapType(returnType)), returnType); + returnValue = BfTypedValue(module->mBfIRBuilder->CreateConstAggZero(module->mBfIRBuilder->MapType(returnType, BfIRPopulateType_Identity)), returnType); } else if (returnType->IsValuelessType()) { @@ -4462,6 +4575,8 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns mCallStack.Clear(); + moduleCurMethodInstance.Restore(); + moduleCurTypeInstance.Restore(); module->AddDependency(methodInstance->GetOwner(), module->mCurTypeInstance, BfDependencyMap::DependencyFlag_ConstEval); return returnValue; @@ -5014,6 +5129,20 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* *(int16*)(stackPtr + 4) = 0; // Flags CeSetAddrVal(stackPtr + 4+2, stringAddr, ptrSize); } + else if (checkFunction->mFunctionKind == CeFunctionKind_Field_GetName) + { + int64 fieldHandle = *(int64*)((uint8*)stackPtr + ptrSize); + + auto fieldInstance = mCeMachine->GetFieldInstance(fieldHandle); + if (fieldInstance == NULL) + { + _Fail("Invalid field instance"); + return false; + } + + CeSetAddrVal(stackPtr + 0, GetString(fieldInstance->GetFieldDef()->mName), ptrSize); + _FixVariables(); + } else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody) { int32 typeId = *(int32*)((uint8*)stackPtr); @@ -7506,6 +7635,12 @@ void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo) delete ceFunctionInfo; } +void CeMachine::RemoveFunc(CeFunction* ceFunction) +{ + mFunctionIdMap.Remove(ceFunction->mId); + ceFunction->mId = -1; +} + void CeMachine::RemoveMethod(BfMethodInstance* methodInstance) { BfLogSys(methodInstance->GetOwner()->mModule->mSystem, "CeMachine::RemoveMethod %p\n", methodInstance); @@ -7527,13 +7662,9 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance) } if (ceFunction->mId != -1) { - mFunctionIdMap.Remove(ceFunction->mId); - ceFunction->mId = -1; + RemoveFunc(ceFunction); for (auto innerFunction : ceFunction->mInnerFunctions) - { - mFunctionIdMap.Remove(innerFunction->mId); - innerFunction->mId = -1; - } + RemoveFunc(innerFunction); } delete ceFunction; @@ -7555,6 +7686,7 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance) mFunctions.Remove(itr); } + methodInstance->mInCEMachine = false; } CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext) @@ -7865,6 +7997,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_Method_GetParamInfo; } + else if (methodDef->mName == "Comptime_Field_GetName") + { + ceFunction->mFunctionKind = CeFunctionKind_Field_GetName; + } } else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef)) { @@ -8208,7 +8344,7 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f ceFunction->mCeMachine = this; ceFunction->mIsVarReturn = methodInstance->mReturnType->IsVar(); ceFunction->mCeFunctionInfo = ceFunctionInfo; - ceFunction->mMethodInstance = methodInstance; + ceFunction->mMethodInstance = methodInstance; ceFunctionInfo->mMethodInstance = methodInstance; ceFunctionInfo->mCeFunction = ceFunction; MapFunctionId(ceFunction); @@ -8283,6 +8419,14 @@ BfMethodInstance* CeMachine::GetMethodInstance(int64 methodHandle) return methodInstance; } +BfFieldInstance* CeMachine::GetFieldInstance(int64 fieldHandle) +{ + BfFieldInstance* fieldInstance = (BfFieldInstance*)(intptr)fieldHandle; + if (!mFieldInstanceSet.Contains(fieldInstance)) + return NULL; + return fieldInstance; +} + CeFunction* CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func) { if (mPreparingFunction != NULL) @@ -8369,7 +8513,7 @@ void CeMachine::ReleaseContext(CeContext* ceContext) BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray& args, CeEvalFlags flags, BfType* expectingType) { auto ceContext = AllocContext(); - auto result = ceContext->Call(targetSrc, module, methodInstance, args, flags, expectingType); + auto result = ceContext->Call(targetSrc, module, methodInstance, args, flags, expectingType); ReleaseContext(ceContext); return result; } diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index c4c3e63b..a7a5b6e4 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -332,6 +332,7 @@ enum CeFunctionKind CeFunctionKind_Method_GetName, CeFunctionKind_Method_GetInfo, CeFunctionKind_Method_GetParamInfo, + CeFunctionKind_Field_GetName, CeFunctionKind_EmitTypeBody, CeFunctionKind_EmitAddInterface, @@ -516,7 +517,7 @@ public: String mGenError; int mFrameSize; int mMaxReturnSize; - int mId; + int mId; public: CeFunction() @@ -544,7 +545,8 @@ enum CeEvalFlags CeEvalFlags_Cascade = 1, CeEvalFlags_PersistantError = 2, CeEvalFlags_DeferIfNotOnlyError = 4, - CeEvalFlags_NoRebuild = 8 + CeEvalFlags_NoRebuild = 8, + CeEvalFlags_ForceReturnThis = 0x10 }; enum CeOperandKind @@ -689,8 +691,8 @@ public: Dictionary mConstDataMap; Dictionary mInnerFunctionMap; Dictionary mStaticFieldMap; - Dictionary mStaticFieldInstanceMap; - + Dictionary mStaticFieldInstanceMap; + public: CeBuilder() { @@ -927,7 +929,9 @@ public: Dictionary mFunctionIdMap; // Only used for 32-bit Dictionary mTypeInfoMap; HashSet mMethodInstanceSet; - + HashSet mFieldInstanceSet; + Array mFunctionList; + Array mContextList; BfCompiler* mCompiler; @@ -937,7 +941,7 @@ public: int mRevisionExecuteTime; int mCurFunctionId; int mExecuteId; - CeAppendAllocInfo* mAppendAllocInfo; + CeAppendAllocInfo* mAppendAllocInfo; CeContext* mCurContext; CeEmitContext* mCurEmitContext; @@ -957,6 +961,7 @@ public: BeModule* GetBeModule(); void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo); + void RemoveFunc(CeFunction* ceFunction); void RemoveMethod(BfMethodInstance* methodInstance); void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction); CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext); @@ -970,6 +975,7 @@ public: CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance); CeTypeInfo* GetTypeInfo(BfType* type); BfMethodInstance* GetMethodInstance(int64 methodHandle); + BfFieldInstance* GetFieldInstance(int64 fieldHandle); public: void CompileStarted();