From 08e38a03f92cca2d232744933510d0a2a3f59ba6 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 13 Jun 2020 08:36:39 -0700 Subject: [PATCH] Added [?] implied size for sized arrays with initializers --- IDEHelper/Compiler/BfConstResolver.cpp | 32 +++ IDEHelper/Compiler/BfConstResolver.h | 5 +- IDEHelper/Compiler/BfContext.h | 7 + IDEHelper/Compiler/BfExprEvaluator.cpp | 307 +++++++++++---------- IDEHelper/Compiler/BfModule.cpp | 42 ++- IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 2 +- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 4 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 4 + IDEHelper/Tests/src/SizedArrays.bf | 7 + 10 files changed, 250 insertions(+), 162 deletions(-) diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 26e1bdab..94960a7d 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -36,6 +36,38 @@ BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule) BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags) { + // Handle the 'int[?] val = .(1, 2, 3)' case + if ((flags & BfConstResolveFlag_ArrayInitSize) != 0) + { + if (auto uninitExpr = BfNodeDynCast(expr)) + { + BfAstNode* initializer = NULL; + int arraySize = -1; + + if (mModule->mContext->mCurTypeState != NULL) + { + if (mModule->mContext->mCurTypeState->mCurFieldDef != NULL) + initializer = mModule->mContext->mCurTypeState->mCurFieldDef->mInitializer; + if (mModule->mContext->mCurTypeState->mCurVarInitializer != NULL) + initializer = mModule->mContext->mCurTypeState->mCurVarInitializer; + if (mModule->mContext->mCurTypeState->mArrayInitializerSize != -1) + arraySize = mModule->mContext->mCurTypeState->mArrayInitializerSize; + } + + if (initializer != NULL) + { + if (auto invocationExpr = BfNodeDynCast(initializer)) + arraySize = (int)invocationExpr->mArguments.size(); + } + + if (arraySize != -1) + { + mResult = BfTypedValue(mModule->GetConstValue(arraySize), mModule->GetPrimitiveType(BfTypeCode_IntPtr)); + return mResult; + } + } + } + bool explicitCast = (flags & BfConstResolveFlag_ExplicitCast) != 0; bool noCast = (flags & BfConstResolveFlag_NoCast) != 0; bool allowSoftFail = (flags & BfConstResolveFlag_AllowSoftFail) != 0; diff --git a/IDEHelper/Compiler/BfConstResolver.h b/IDEHelper/Compiler/BfConstResolver.h index 0c0cbc2d..c7a8be32 100644 --- a/IDEHelper/Compiler/BfConstResolver.h +++ b/IDEHelper/Compiler/BfConstResolver.h @@ -15,7 +15,8 @@ enum BfConstResolveFlags BfConstResolveFlag_ExplicitCast = 1, BfConstResolveFlag_NoCast = 2, BfConstResolveFlag_AllowSoftFail = 4, - BfConstResolveFlag_RemapFromStringId = 8 + BfConstResolveFlag_RemapFromStringId = 8, + BfConstResolveFlag_ArrayInitSize = 0x10 }; class BfConstResolver : public BfExprEvaluator @@ -31,7 +32,7 @@ public: BfConstResolver(BfModule* bfModule); BfTypedValue Resolve(BfExpression* expr, BfType* wantType = NULL, BfConstResolveFlags flags = BfConstResolveFlag_None); - bool PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatcher* methodMatcher, Array& llvmArgs); + bool PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatcher* methodMatcher, Array& llvmArgs); }; NS_BF_END \ No newline at end of file diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 308fe0bb..b8b07542 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -116,6 +116,7 @@ public: ResolveKind_BuildingGenericParams, ResolveKind_ResolvingVarType, ResolveKind_UnionInnerType, + ResolveKind_LocalVariable, }; public: @@ -131,6 +132,8 @@ public: BfFieldDef* mCurFieldDef; BfTypeDef* mCurTypeDef; ResolveKind mResolveKind; + BfAstNode* mCurVarInitializer; + int mArrayInitializerSize; public: BfTypeState() @@ -144,6 +147,8 @@ public: mCurFieldDef = NULL; mCurAttributeTypeRef = NULL; mCurTypeDef = NULL; + mCurVarInitializer = NULL; + mArrayInitializerSize = -1; mResolveKind = ResolveKind_None; } @@ -158,6 +163,8 @@ public: mCurFieldDef = NULL; mCurAttributeTypeRef = NULL; mCurTypeDef = NULL; + mCurVarInitializer = NULL; + mArrayInitializerSize = -1; mResolveKind = ResolveKind_None; } }; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 63245e35..d3252482 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -11796,174 +11796,193 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) int writeIdx = 0; - std::function& valueExprs)> _HandleInitExprs = [&](BfIRValue addr, int curDim, const BfSizedArray& valueExprs) + struct BfInitContext { - int exprIdx = 0; - int dimWriteIdx = 0; - bool isUninit = false; - - int dimLength = -1; - if (dimLengthVals[curDim].IsConst()) + public: + BfModule* mModule; + BfType* resultType; + int dimensions; + SizedArray& dimLengthVals; + BfIRValue arraySize; + int& writeIdx; + + BfInitContext(BfModule* module, BfType* resultType, int dimensions, SizedArray& dimLengthVals, BfIRValue arraySize, int& writeIdx) : + mModule(module), resultType(resultType), dimensions(dimensions), dimLengthVals(dimLengthVals), arraySize(arraySize), writeIdx(writeIdx) { - auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[curDim]); - dimLength = constant->mInt32; + } - while (exprIdx < (int)valueExprs.size()) + void Handle(BfIRValue addr, int curDim, const BfSizedArray& valueExprs) { - auto initExpr = valueExprs[exprIdx]; - exprIdx++; - if (!initExpr) - break; - if (auto unintExpr = BfNodeDynCastExact(initExpr)) + int exprIdx = 0; + int dimWriteIdx = 0; + bool isUninit = false; + + int dimLength = -1; + if (dimLengthVals[curDim].IsConst()) { - isUninit = true; - break; + auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[curDim]); + dimLength = constant->mInt32; } - if (exprIdx > dimLength) - break; - - if (curDim < dimensions - 1) - { - if (auto innerTupleExpr = BfNodeDynCast(initExpr)) + while (exprIdx < (int)valueExprs.size()) + { + auto initExpr = valueExprs[exprIdx]; + exprIdx++; + if (!initExpr) + break; + if (auto unintExpr = BfNodeDynCastExact(initExpr)) { - _HandleInitExprs(addr, curDim + 1, innerTupleExpr->mValues); - } - else if (auto parenExpr = BfNodeDynCast(initExpr)) - { - SizedArray values; - values.Add(parenExpr->mExpression); - _HandleInitExprs(addr, curDim + 1, values); - } - else if (auto innerInitExpr = BfNodeDynCast(initExpr)) - { - _HandleInitExprs(addr, curDim + 1, innerInitExpr->mValues); + isUninit = true; + break; } - dimWriteIdx++; - continue; - } + if (exprIdx > dimLength) + break; - auto elemAddr = mModule->CreateIndexedValue(resultType, addr, writeIdx); - writeIdx++; - dimWriteIdx++; - - BfTypedValue elemPtrTypedVal = BfTypedValue(elemAddr, resultType, BfTypedValueKind_Addr); - - BfExprEvaluator exprEvaluator(mModule); - exprEvaluator.mExpectingType = resultType; - exprEvaluator.mReceivingValue = &elemPtrTypedVal; - exprEvaluator.Evaluate(initExpr); - exprEvaluator.GetResult(); - - if (exprEvaluator.mReceivingValue == NULL) - { - // We wrote directly to the array in-place, we're done with this element - continue; - } - auto storeValue = exprEvaluator.mResult; - if (!storeValue) - continue; - storeValue = mModule->Cast(initExpr, storeValue, resultType); - if (!storeValue) - continue; - if (!resultType->IsValuelessType()) - { - storeValue = mModule->LoadValue(storeValue); - mModule->mBfIRBuilder->CreateStore(storeValue.mValue, elemAddr); - } - } - - int clearFromIdx = writeIdx; - int sectionElemCount = 1; - - BfIRValue numElemsLeft = arraySize; - if (dimLength != -1) - { - int clearCount = dimLength - dimWriteIdx; - if (clearCount > 0) - { - for (int checkDim = curDim + 1; checkDim < (int)dimLengthVals.size(); checkDim++) + if (curDim < dimensions - 1) { - if (dimLengthVals[checkDim].IsConst()) + if (auto innerTupleExpr = BfNodeDynCast(initExpr)) { - auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[checkDim]); - clearCount *= constant->mInt32; - sectionElemCount *= constant->mInt32; + Handle(addr, curDim + 1, innerTupleExpr->mValues); + } + else if (auto parenExpr = BfNodeDynCast(initExpr)) + { + SizedArray values; + values.Add(parenExpr->mExpression); + Handle(addr, curDim + 1, values); + } + else if (auto innerInitExpr = BfNodeDynCast(initExpr)) + { + Handle(addr, curDim + 1, innerInitExpr->mValues); + } + + dimWriteIdx++; + continue; + } + + auto elemAddr = mModule->CreateIndexedValue(resultType, addr, writeIdx); + writeIdx++; + dimWriteIdx++; + + BfTypedValue elemPtrTypedVal = BfTypedValue(elemAddr, resultType, BfTypedValueKind_Addr); + + BfExprEvaluator exprEvaluator(mModule); + exprEvaluator.mExpectingType = resultType; + exprEvaluator.mReceivingValue = &elemPtrTypedVal; + exprEvaluator.Evaluate(initExpr); + exprEvaluator.GetResult(); + + if (exprEvaluator.mReceivingValue == NULL) + { + // We wrote directly to the array in-place, we're done with this element + continue; + } + auto storeValue = exprEvaluator.mResult; + if (!storeValue) + continue; + storeValue = mModule->Cast(initExpr, storeValue, resultType); + if (!storeValue) + continue; + if (!resultType->IsValuelessType()) + { + storeValue = mModule->LoadValue(storeValue); + mModule->mBfIRBuilder->CreateStore(storeValue.mValue, elemAddr); + } + } + + int clearFromIdx = writeIdx; + int sectionElemCount = 1; + + BfIRValue numElemsLeft = arraySize; + if (dimLength != -1) + { + int clearCount = dimLength - dimWriteIdx; + if (clearCount > 0) + { + for (int checkDim = curDim + 1; checkDim < (int)dimLengthVals.size(); checkDim++) + { + if (dimLengthVals[checkDim].IsConst()) + { + auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[checkDim]); + clearCount *= constant->mInt32; + sectionElemCount *= constant->mInt32; + } } } + + writeIdx += clearCount; + numElemsLeft = mModule->GetConstValue(clearCount); } - writeIdx += clearCount; - numElemsLeft = mModule->GetConstValue(clearCount); - } + // Actually leave it alone? + if ((isUninit) && (mModule->IsOptimized())) + return; - // Actually leave it alone? - if ((isUninit) && (mModule->IsOptimized())) - return; - - bool doClear = true; - if (numElemsLeft.IsConst()) - { - auto constant = mModule->mBfIRBuilder->GetConstant(numElemsLeft); - doClear = constant->mInt64 > 0; - } - if (doClear) - { - // We multiply by GetStride. This relies on the fact that we over-allocate on the array allocation -- the last - // element doesn't need to be padded out to the element alignment, but we do anyway. Otherwise this would be - // a more complicated computation - auto clearBytes = mModule->mBfIRBuilder->CreateMul(numElemsLeft, mModule->GetConstValue(resultType->GetStride())); - - if (isUninit) + bool doClear = true; + if (numElemsLeft.IsConst()) { - // Limit to a reasonable number of bytes to stomp with 0xCC - int maxStompBytes = BF_MIN(128, resultType->GetStride() * sectionElemCount); - if (clearBytes.IsConst()) - { - auto constant = mModule->mBfIRBuilder->GetConstant(clearBytes); - if (constant->mInt64 > maxStompBytes) - clearBytes = mModule->GetConstValue(maxStompBytes); - } - else - { - auto insertBlock = mModule->mBfIRBuilder->GetInsertBlock(); - - auto gtBlock = mModule->mBfIRBuilder->CreateBlock("unint.gt"); - auto contBlock = mModule->mBfIRBuilder->CreateBlock("unint.cont"); - - auto cmp = mModule->mBfIRBuilder->CreateCmpLTE(clearBytes, mModule->GetConstValue(maxStompBytes), true); - mModule->mBfIRBuilder->CreateCondBr(cmp, contBlock, gtBlock); - - mModule->mBfIRBuilder->AddBlock(gtBlock); - mModule->mBfIRBuilder->SetInsertPoint(gtBlock); - mModule->mBfIRBuilder->CreateBr(contBlock); - - mModule->mBfIRBuilder->AddBlock(contBlock); - mModule->mBfIRBuilder->SetInsertPoint(contBlock); - auto phi = mModule->mBfIRBuilder->CreatePhi(mModule->mBfIRBuilder->MapType(mModule->GetPrimitiveType(BfTypeCode_IntPtr)), 2); - mModule->mBfIRBuilder->AddPhiIncoming(phi, clearBytes, insertBlock); - mModule->mBfIRBuilder->AddPhiIncoming(phi, mModule->GetConstValue(maxStompBytes), gtBlock); - - clearBytes = phi; - } + auto constant = mModule->mBfIRBuilder->GetConstant(numElemsLeft); + doClear = constant->mInt64 > 0; } - - mModule->mBfIRBuilder->PopulateType(resultType); - if (!resultType->IsValuelessType()) + if (doClear) { - mModule->mBfIRBuilder->CreateMemSet(mModule->CreateIndexedValue(resultType, addr, clearFromIdx), - mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int8, isUninit ? 0xCC : 0), clearBytes, resultType->mAlign); + // We multiply by GetStride. This relies on the fact that we over-allocate on the array allocation -- the last + // element doesn't need to be padded out to the element alignment, but we do anyway. Otherwise this would be + // a more complicated computation + auto clearBytes = mModule->mBfIRBuilder->CreateMul(numElemsLeft, mModule->GetConstValue(resultType->GetStride())); + + if (isUninit) + { + // Limit to a reasonable number of bytes to stomp with 0xCC + int maxStompBytes = BF_MIN(128, resultType->GetStride() * sectionElemCount); + if (clearBytes.IsConst()) + { + auto constant = mModule->mBfIRBuilder->GetConstant(clearBytes); + if (constant->mInt64 > maxStompBytes) + clearBytes = mModule->GetConstValue(maxStompBytes); + } + else + { + auto insertBlock = mModule->mBfIRBuilder->GetInsertBlock(); + + auto gtBlock = mModule->mBfIRBuilder->CreateBlock("unint.gt"); + auto contBlock = mModule->mBfIRBuilder->CreateBlock("unint.cont"); + + auto cmp = mModule->mBfIRBuilder->CreateCmpLTE(clearBytes, mModule->GetConstValue(maxStompBytes), true); + mModule->mBfIRBuilder->CreateCondBr(cmp, contBlock, gtBlock); + + mModule->mBfIRBuilder->AddBlock(gtBlock); + mModule->mBfIRBuilder->SetInsertPoint(gtBlock); + mModule->mBfIRBuilder->CreateBr(contBlock); + + mModule->mBfIRBuilder->AddBlock(contBlock); + mModule->mBfIRBuilder->SetInsertPoint(contBlock); + auto phi = mModule->mBfIRBuilder->CreatePhi(mModule->mBfIRBuilder->MapType(mModule->GetPrimitiveType(BfTypeCode_IntPtr)), 2); + mModule->mBfIRBuilder->AddPhiIncoming(phi, clearBytes, insertBlock); + mModule->mBfIRBuilder->AddPhiIncoming(phi, mModule->GetConstValue(maxStompBytes), gtBlock); + + clearBytes = phi; + } + } + + mModule->mBfIRBuilder->PopulateType(resultType); + if (!resultType->IsValuelessType()) + { + mModule->mBfIRBuilder->CreateMemSet(mModule->CreateIndexedValue(resultType, addr, clearFromIdx), + mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int8, isUninit ? 0xCC : 0), clearBytes, resultType->mAlign); + } } } }; + + BfInitContext initContext(mModule, resultType, dimensions, dimLengthVals, arraySize, writeIdx); if (resultType->IsVar()) { SetAndRestoreValue prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true); mResult = BfTypedValue(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), mModule->GetPrimitiveType(BfTypeCode_Var))); - _HandleInitExprs(mResult.mValue, 0, objCreateExpr->mArguments); + initContext.Handle(mResult.mValue, 0, objCreateExpr->mArguments); return; } @@ -11978,7 +11997,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) arrayValue = BfTypedValue(mModule->AllocFromType(resultType, allocTarget, BfIRValue(), arraySize, (int)dimLengthVals.size(), allocFlags, allocTarget.mAlignOverride), ptrType); } - _HandleInitExprs(arrayValue.mValue, 0, objCreateExpr->mArguments); + initContext.Handle(arrayValue.mValue, 0, objCreateExpr->mArguments); mResult = arrayValue; return; @@ -12073,7 +12092,8 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) addr = mModule->mBfIRBuilder->GetFakeVal(); else addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayValue.mValue, 0, firstElementFieldInstance->mDataIdx); - _HandleInitExprs(addr, 0, objCreateExpr->mArguments); + + initContext.Handle(addr, 0, objCreateExpr->mArguments); return; } @@ -14370,13 +14390,18 @@ void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr) int arrSize = 0; + BfTypeState typeState; + typeState.mArrayInitializerSize = (int)invocationExpr->mArguments.size(); + SetAndRestoreValue prevTypeState(mModule->mContext->mCurTypeState, &typeState); + if (indexerExpr->mArguments.size() != 0) { BfConstResolver constResolver(mModule); auto arg = indexerExpr->mArguments[0]; + constResolver.mExpectingType = mModule->GetPrimitiveType(BfTypeCode_IntPtr); if (arg != NULL) - constResolver.Resolve(arg); + constResolver.Resolve(arg, NULL, BfConstResolveFlag_ArrayInitSize); if (constResolver.mResult.mValue.IsConst()) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 350ee4eb..eb13794a 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3721,7 +3721,7 @@ bool BfModule::IsThreadLocal(BfFieldInstance * fieldInstance) return false; } -BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer, BfFieldDef* fieldDef, BfType* fieldType) +BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer, BfFieldDef* fieldDef, BfType* fieldType, bool doStore) { if (fieldDef == NULL) fieldDef = fieldInstance->GetFieldDef(); @@ -3734,6 +3734,8 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, initializer = fieldDef->mInitializer; } + BfTypedValue staticVarRef; + BfTypedValue result; if (initializer == NULL) { @@ -3779,16 +3781,34 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, return constResolver.Resolve(initializer, fieldType, resolveFlags); } } - + + BfExprEvaluator exprEvaluator(this); + if (doStore) + { + staticVarRef = ReferenceStaticField(fieldInstance); + exprEvaluator.mReceivingValue = &staticVarRef; + } if (fieldType->IsVar()) - result = CreateValueFromExpression(initializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer)); + result = CreateValueFromExpression(exprEvaluator, initializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer)); else - result = CreateValueFromExpression(initializer, fieldType, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer)); + result = CreateValueFromExpression(exprEvaluator, initializer, fieldType, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer)); + if (doStore) + { + if (exprEvaluator.mReceivingValue == NULL) + doStore = false; // Already stored + } } if (fieldInstance != NULL) MarkFieldInitialized(fieldInstance); + if (doStore) + { + result = LoadValue(result); + if (!result.mType->IsValuelessType()) + mBfIRBuilder->CreateStore(result.mValue, staticVarRef.mValue); + } + return result; } @@ -13893,16 +13913,8 @@ void BfModule::CreateStaticCtor() { continue; } - auto assignValue = GetFieldInitializerValue(fieldInst); - if (assignValue) - { - assignValue = LoadValue(assignValue); - if (!assignValue.mType->IsValuelessType()) - { - auto staticVarRef = ReferenceStaticField(fieldInst).mValue; - mBfIRBuilder->CreateStore(assignValue.mValue, staticVarRef); - } - } + GetFieldInitializerValue(fieldInst, NULL, NULL, NULL, true); + } } } @@ -16457,7 +16469,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } BfTypeState typeState(mCurTypeInstance); - SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); + SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (mCurTypeInstance->IsUnspecializedTypeVariation()); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 195115b8..b7688ca3 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1609,7 +1609,7 @@ public: BfFieldInstance* GetFieldByName(BfTypeInstance* typeInstance, const StringImpl& fieldName, bool isRequired = true, BfAstNode* refNode = NULL); void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = false); void ResolveConstField(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field, bool forceResolve = false); - BfTypedValue GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer = NULL, BfFieldDef* fieldDef = NULL, BfType* fieldType = NULL); + BfTypedValue GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer = NULL, BfFieldDef* fieldDef = NULL, BfType* fieldType = NULL, bool doStore = false); void MarkFieldInitialized(BfFieldInstance* fieldInstance); bool IsThreadLocal(BfFieldInstance* fieldInstance); BfType* ResolveVarFieldType(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 6bc13cda..a8247eae 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -7870,7 +7870,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula BfTypedValue typedVal; { SetAndRestoreValue prevIgnoreErrors(mIgnoreErrors, true); - typedVal = constResolver.Resolve(sizeExpr); + typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize); } if (typedVal.mKind == BfTypedValueKind_GenericConstValue) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 83b95f13..fda6621d 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2654,7 +2654,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr); constResolver.mAllowGenericConstValue = true; constResolver.mExpectingType = intType; - BfTypedValue typedVal = constResolver.Resolve(sizeExpr); + BfTypedValue typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize); if (typedVal.mKind == BfTypedValueKind_GenericConstValue) { int elemHash = Hash(typedVal.mType, ctx); @@ -3550,7 +3550,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr); constResolver.mAllowGenericConstValue = true; constResolver.mExpectingType = intType; - BfTypedValue typedVal = constResolver.Resolve(sizeExpr); + BfTypedValue typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize); if (typedVal.mKind == BfTypedValueKind_GenericConstValue) { if (!lhs->IsUnknownSizedArray()) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 98cc4105..61f86152 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -1563,6 +1563,10 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD } else { + BfTypeState typeState; + typeState.mCurVarInitializer = varDecl->mInitializer; + SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); + unresolvedType = ResolveTypeRef(varDecl->mTypeRef, BfPopulateType_Data, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef)); if (unresolvedType == NULL) unresolvedType = GetPrimitiveType(BfTypeCode_Var); diff --git a/IDEHelper/Tests/src/SizedArrays.bf b/IDEHelper/Tests/src/SizedArrays.bf index b6a69e05..b229777c 100644 --- a/IDEHelper/Tests/src/SizedArrays.bf +++ b/IDEHelper/Tests/src/SizedArrays.bf @@ -5,6 +5,7 @@ namespace Tests class SizedArrays { public static int[8] iArr = .(123, 234, 345, ); + public static int[?] iArr2 = .(12, 23, 34); [Test] static void TestBasics() @@ -24,6 +25,12 @@ namespace Tests val2[0][0] = 9; Test.Assert(val0 != val2); Test.Assert(val2[1] == val1); + + int[?] val3 = .(9, 10); + Test.Assert(val3[0] == 9); + + var val4 = int[?](11, 12); + Test.Assert(val4[0] == 11); } [Test]