mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 20:12:21 +02:00
Added [?] implied size for sized arrays with initializers
This commit is contained in:
parent
82d2963a9e
commit
08e38a03f9
10 changed files with 250 additions and 162 deletions
|
@ -36,6 +36,38 @@ BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule)
|
||||||
|
|
||||||
BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags)
|
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<BfUninitializedExpression>(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<BfInvocationExpression>(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 explicitCast = (flags & BfConstResolveFlag_ExplicitCast) != 0;
|
||||||
bool noCast = (flags & BfConstResolveFlag_NoCast) != 0;
|
bool noCast = (flags & BfConstResolveFlag_NoCast) != 0;
|
||||||
bool allowSoftFail = (flags & BfConstResolveFlag_AllowSoftFail) != 0;
|
bool allowSoftFail = (flags & BfConstResolveFlag_AllowSoftFail) != 0;
|
||||||
|
|
|
@ -15,7 +15,8 @@ enum BfConstResolveFlags
|
||||||
BfConstResolveFlag_ExplicitCast = 1,
|
BfConstResolveFlag_ExplicitCast = 1,
|
||||||
BfConstResolveFlag_NoCast = 2,
|
BfConstResolveFlag_NoCast = 2,
|
||||||
BfConstResolveFlag_AllowSoftFail = 4,
|
BfConstResolveFlag_AllowSoftFail = 4,
|
||||||
BfConstResolveFlag_RemapFromStringId = 8
|
BfConstResolveFlag_RemapFromStringId = 8,
|
||||||
|
BfConstResolveFlag_ArrayInitSize = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfConstResolver : public BfExprEvaluator
|
class BfConstResolver : public BfExprEvaluator
|
||||||
|
|
|
@ -116,6 +116,7 @@ public:
|
||||||
ResolveKind_BuildingGenericParams,
|
ResolveKind_BuildingGenericParams,
|
||||||
ResolveKind_ResolvingVarType,
|
ResolveKind_ResolvingVarType,
|
||||||
ResolveKind_UnionInnerType,
|
ResolveKind_UnionInnerType,
|
||||||
|
ResolveKind_LocalVariable,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -131,6 +132,8 @@ public:
|
||||||
BfFieldDef* mCurFieldDef;
|
BfFieldDef* mCurFieldDef;
|
||||||
BfTypeDef* mCurTypeDef;
|
BfTypeDef* mCurTypeDef;
|
||||||
ResolveKind mResolveKind;
|
ResolveKind mResolveKind;
|
||||||
|
BfAstNode* mCurVarInitializer;
|
||||||
|
int mArrayInitializerSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfTypeState()
|
BfTypeState()
|
||||||
|
@ -144,6 +147,8 @@ public:
|
||||||
mCurFieldDef = NULL;
|
mCurFieldDef = NULL;
|
||||||
mCurAttributeTypeRef = NULL;
|
mCurAttributeTypeRef = NULL;
|
||||||
mCurTypeDef = NULL;
|
mCurTypeDef = NULL;
|
||||||
|
mCurVarInitializer = NULL;
|
||||||
|
mArrayInitializerSize = -1;
|
||||||
mResolveKind = ResolveKind_None;
|
mResolveKind = ResolveKind_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +163,8 @@ public:
|
||||||
mCurFieldDef = NULL;
|
mCurFieldDef = NULL;
|
||||||
mCurAttributeTypeRef = NULL;
|
mCurAttributeTypeRef = NULL;
|
||||||
mCurTypeDef = NULL;
|
mCurTypeDef = NULL;
|
||||||
|
mCurVarInitializer = NULL;
|
||||||
|
mArrayInitializerSize = -1;
|
||||||
mResolveKind = ResolveKind_None;
|
mResolveKind = ResolveKind_None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11796,174 +11796,193 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
|
||||||
|
|
||||||
int writeIdx = 0;
|
int writeIdx = 0;
|
||||||
|
|
||||||
std::function<void(BfIRValue addr, int curDim, const BfSizedArray<BfExpression*>& valueExprs)> _HandleInitExprs = [&](BfIRValue addr, int curDim, const BfSizedArray<BfExpression*>& valueExprs)
|
struct BfInitContext
|
||||||
{
|
{
|
||||||
int exprIdx = 0;
|
public:
|
||||||
int dimWriteIdx = 0;
|
BfModule* mModule;
|
||||||
bool isUninit = false;
|
BfType* resultType;
|
||||||
|
int dimensions;
|
||||||
|
SizedArray<BfIRValue, 2>& dimLengthVals;
|
||||||
|
BfIRValue arraySize;
|
||||||
|
int& writeIdx;
|
||||||
|
|
||||||
int dimLength = -1;
|
BfInitContext(BfModule* module, BfType* resultType, int dimensions, SizedArray<BfIRValue, 2>& dimLengthVals, BfIRValue arraySize, int& writeIdx) :
|
||||||
if (dimLengthVals[curDim].IsConst())
|
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<BfExpression*>& valueExprs)
|
||||||
{
|
{
|
||||||
auto initExpr = valueExprs[exprIdx];
|
int exprIdx = 0;
|
||||||
exprIdx++;
|
int dimWriteIdx = 0;
|
||||||
if (!initExpr)
|
bool isUninit = false;
|
||||||
break;
|
|
||||||
if (auto unintExpr = BfNodeDynCastExact<BfUninitializedExpression>(initExpr))
|
int dimLength = -1;
|
||||||
|
if (dimLengthVals[curDim].IsConst())
|
||||||
{
|
{
|
||||||
isUninit = true;
|
auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[curDim]);
|
||||||
break;
|
dimLength = constant->mInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exprIdx > dimLength)
|
while (exprIdx < (int)valueExprs.size())
|
||||||
break;
|
|
||||||
|
|
||||||
if (curDim < dimensions - 1)
|
|
||||||
{
|
{
|
||||||
if (auto innerTupleExpr = BfNodeDynCast<BfTupleExpression>(initExpr))
|
auto initExpr = valueExprs[exprIdx];
|
||||||
|
exprIdx++;
|
||||||
|
if (!initExpr)
|
||||||
|
break;
|
||||||
|
if (auto unintExpr = BfNodeDynCastExact<BfUninitializedExpression>(initExpr))
|
||||||
{
|
{
|
||||||
_HandleInitExprs(addr, curDim + 1, innerTupleExpr->mValues);
|
isUninit = true;
|
||||||
}
|
break;
|
||||||
else if (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(initExpr))
|
|
||||||
{
|
|
||||||
SizedArray<BfExpression*, 1> values;
|
|
||||||
values.Add(parenExpr->mExpression);
|
|
||||||
_HandleInitExprs(addr, curDim + 1, values);
|
|
||||||
}
|
|
||||||
else if (auto innerInitExpr = BfNodeDynCast<BfCollectionInitializerExpression>(initExpr))
|
|
||||||
{
|
|
||||||
_HandleInitExprs(addr, curDim + 1, innerInitExpr->mValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dimWriteIdx++;
|
if (exprIdx > dimLength)
|
||||||
continue;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
auto elemAddr = mModule->CreateIndexedValue(resultType, addr, writeIdx);
|
if (curDim < dimensions - 1)
|
||||||
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())
|
if (auto innerTupleExpr = BfNodeDynCast<BfTupleExpression>(initExpr))
|
||||||
{
|
{
|
||||||
auto constant = mModule->mBfIRBuilder->GetConstant(dimLengthVals[checkDim]);
|
Handle(addr, curDim + 1, innerTupleExpr->mValues);
|
||||||
clearCount *= constant->mInt32;
|
}
|
||||||
sectionElemCount *= constant->mInt32;
|
else if (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(initExpr))
|
||||||
|
{
|
||||||
|
SizedArray<BfExpression*, 1> values;
|
||||||
|
values.Add(parenExpr->mExpression);
|
||||||
|
Handle(addr, curDim + 1, values);
|
||||||
|
}
|
||||||
|
else if (auto innerInitExpr = BfNodeDynCast<BfCollectionInitializerExpression>(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;
|
// Actually leave it alone?
|
||||||
numElemsLeft = mModule->GetConstValue(clearCount);
|
if ((isUninit) && (mModule->IsOptimized()))
|
||||||
}
|
return;
|
||||||
|
|
||||||
// Actually leave it alone?
|
bool doClear = true;
|
||||||
if ((isUninit) && (mModule->IsOptimized()))
|
if (numElemsLeft.IsConst())
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Limit to a reasonable number of bytes to stomp with 0xCC
|
auto constant = mModule->mBfIRBuilder->GetConstant(numElemsLeft);
|
||||||
int maxStompBytes = BF_MIN(128, resultType->GetStride() * sectionElemCount);
|
doClear = constant->mInt64 > 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (doClear)
|
||||||
mModule->mBfIRBuilder->PopulateType(resultType);
|
|
||||||
if (!resultType->IsValuelessType())
|
|
||||||
{
|
{
|
||||||
mModule->mBfIRBuilder->CreateMemSet(mModule->CreateIndexedValue(resultType, addr, clearFromIdx),
|
// We multiply by GetStride. This relies on the fact that we over-allocate on the array allocation -- the last
|
||||||
mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int8, isUninit ? 0xCC : 0), clearBytes, resultType->mAlign);
|
// 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())
|
if (resultType->IsVar())
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
mResult = BfTypedValue(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), mModule->GetPrimitiveType(BfTypeCode_Var)));
|
mResult = BfTypedValue(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), mModule->GetPrimitiveType(BfTypeCode_Var)));
|
||||||
_HandleInitExprs(mResult.mValue, 0, objCreateExpr->mArguments);
|
initContext.Handle(mResult.mValue, 0, objCreateExpr->mArguments);
|
||||||
return;
|
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);
|
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;
|
mResult = arrayValue;
|
||||||
return;
|
return;
|
||||||
|
@ -12073,7 +12092,8 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
|
||||||
addr = mModule->mBfIRBuilder->GetFakeVal();
|
addr = mModule->mBfIRBuilder->GetFakeVal();
|
||||||
else
|
else
|
||||||
addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayValue.mValue, 0, firstElementFieldInstance->mDataIdx);
|
addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayValue.mValue, 0, firstElementFieldInstance->mDataIdx);
|
||||||
_HandleInitExprs(addr, 0, objCreateExpr->mArguments);
|
|
||||||
|
initContext.Handle(addr, 0, objCreateExpr->mArguments);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -14370,13 +14390,18 @@ void BfExprEvaluator::Visit(BfInvocationExpression* invocationExpr)
|
||||||
|
|
||||||
int arrSize = 0;
|
int arrSize = 0;
|
||||||
|
|
||||||
|
BfTypeState typeState;
|
||||||
|
typeState.mArrayInitializerSize = (int)invocationExpr->mArguments.size();
|
||||||
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mModule->mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
if (indexerExpr->mArguments.size() != 0)
|
if (indexerExpr->mArguments.size() != 0)
|
||||||
{
|
{
|
||||||
BfConstResolver constResolver(mModule);
|
BfConstResolver constResolver(mModule);
|
||||||
auto arg = indexerExpr->mArguments[0];
|
auto arg = indexerExpr->mArguments[0];
|
||||||
|
constResolver.mExpectingType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
|
|
||||||
if (arg != NULL)
|
if (arg != NULL)
|
||||||
constResolver.Resolve(arg);
|
constResolver.Resolve(arg, NULL, BfConstResolveFlag_ArrayInitSize);
|
||||||
|
|
||||||
if (constResolver.mResult.mValue.IsConst())
|
if (constResolver.mResult.mValue.IsConst())
|
||||||
{
|
{
|
||||||
|
|
|
@ -3721,7 +3721,7 @@ bool BfModule::IsThreadLocal(BfFieldInstance * fieldInstance)
|
||||||
return false;
|
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)
|
if (fieldDef == NULL)
|
||||||
fieldDef = fieldInstance->GetFieldDef();
|
fieldDef = fieldInstance->GetFieldDef();
|
||||||
|
@ -3734,6 +3734,8 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
|
||||||
initializer = fieldDef->mInitializer;
|
initializer = fieldDef->mInitializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfTypedValue staticVarRef;
|
||||||
|
|
||||||
BfTypedValue result;
|
BfTypedValue result;
|
||||||
if (initializer == NULL)
|
if (initializer == NULL)
|
||||||
{
|
{
|
||||||
|
@ -3780,15 +3782,33 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
if (doStore)
|
||||||
|
{
|
||||||
|
staticVarRef = ReferenceStaticField(fieldInstance);
|
||||||
|
exprEvaluator.mReceivingValue = &staticVarRef;
|
||||||
|
}
|
||||||
if (fieldType->IsVar())
|
if (fieldType->IsVar())
|
||||||
result = CreateValueFromExpression(initializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer));
|
result = CreateValueFromExpression(exprEvaluator, initializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer));
|
||||||
else
|
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)
|
if (fieldInstance != NULL)
|
||||||
MarkFieldInitialized(fieldInstance);
|
MarkFieldInitialized(fieldInstance);
|
||||||
|
|
||||||
|
if (doStore)
|
||||||
|
{
|
||||||
|
result = LoadValue(result);
|
||||||
|
if (!result.mType->IsValuelessType())
|
||||||
|
mBfIRBuilder->CreateStore(result.mValue, staticVarRef.mValue);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13893,16 +13913,8 @@ void BfModule::CreateStaticCtor()
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto assignValue = GetFieldInitializerValue(fieldInst);
|
GetFieldInitializerValue(fieldInst, NULL, NULL, NULL, true);
|
||||||
if (assignValue)
|
|
||||||
{
|
|
||||||
assignValue = LoadValue(assignValue);
|
|
||||||
if (!assignValue.mType->IsValuelessType())
|
|
||||||
{
|
|
||||||
auto staticVarRef = ReferenceStaticField(fieldInst).mValue;
|
|
||||||
mBfIRBuilder->CreateStore(assignValue.mValue, staticVarRef);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1609,7 +1609,7 @@ public:
|
||||||
BfFieldInstance* GetFieldByName(BfTypeInstance* typeInstance, const StringImpl& fieldName, bool isRequired = true, BfAstNode* refNode = NULL);
|
BfFieldInstance* GetFieldByName(BfTypeInstance* typeInstance, const StringImpl& fieldName, bool isRequired = true, BfAstNode* refNode = NULL);
|
||||||
void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = false);
|
void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = false);
|
||||||
void ResolveConstField(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field, bool forceResolve = 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);
|
void MarkFieldInitialized(BfFieldInstance* fieldInstance);
|
||||||
bool IsThreadLocal(BfFieldInstance* fieldInstance);
|
bool IsThreadLocal(BfFieldInstance* fieldInstance);
|
||||||
BfType* ResolveVarFieldType(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field);
|
BfType* ResolveVarFieldType(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field);
|
||||||
|
|
|
@ -7870,7 +7870,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
BfTypedValue typedVal;
|
BfTypedValue typedVal;
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
|
||||||
typedVal = constResolver.Resolve(sizeExpr);
|
typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize);
|
||||||
}
|
}
|
||||||
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2654,7 +2654,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
||||||
BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
constResolver.mAllowGenericConstValue = true;
|
constResolver.mAllowGenericConstValue = true;
|
||||||
constResolver.mExpectingType = intType;
|
constResolver.mExpectingType = intType;
|
||||||
BfTypedValue typedVal = constResolver.Resolve(sizeExpr);
|
BfTypedValue typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize);
|
||||||
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
{
|
{
|
||||||
int elemHash = Hash(typedVal.mType, ctx);
|
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);
|
BfType* intType = ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
constResolver.mAllowGenericConstValue = true;
|
constResolver.mAllowGenericConstValue = true;
|
||||||
constResolver.mExpectingType = intType;
|
constResolver.mExpectingType = intType;
|
||||||
BfTypedValue typedVal = constResolver.Resolve(sizeExpr);
|
BfTypedValue typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize);
|
||||||
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
{
|
{
|
||||||
if (!lhs->IsUnknownSizedArray())
|
if (!lhs->IsUnknownSizedArray())
|
||||||
|
|
|
@ -1563,6 +1563,10 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
BfTypeState typeState;
|
||||||
|
typeState.mCurVarInitializer = varDecl->mInitializer;
|
||||||
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
unresolvedType = ResolveTypeRef(varDecl->mTypeRef, BfPopulateType_Data, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef));
|
unresolvedType = ResolveTypeRef(varDecl->mTypeRef, BfPopulateType_Data, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef));
|
||||||
if (unresolvedType == NULL)
|
if (unresolvedType == NULL)
|
||||||
unresolvedType = GetPrimitiveType(BfTypeCode_Var);
|
unresolvedType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Tests
|
||||||
class SizedArrays
|
class SizedArrays
|
||||||
{
|
{
|
||||||
public static int[8] iArr = .(123, 234, 345, );
|
public static int[8] iArr = .(123, 234, 345, );
|
||||||
|
public static int[?] iArr2 = .(12, 23, 34);
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
static void TestBasics()
|
static void TestBasics()
|
||||||
|
@ -24,6 +25,12 @@ namespace Tests
|
||||||
val2[0][0] = 9;
|
val2[0][0] = 9;
|
||||||
Test.Assert(val0 != val2);
|
Test.Assert(val0 != val2);
|
||||||
Test.Assert(val2[1] == val1);
|
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]
|
[Test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue