1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Alloc allign attributes, lambda captures

This commit is contained in:
Brian Fiete 2019-11-26 13:11:17 -08:00
parent 79ccb33586
commit 12e5b525ad
23 changed files with 540 additions and 219 deletions

View file

@ -938,7 +938,7 @@ StringView BfAstNode::ToStringView()
return StringView();
}
auto source = GetSourceData();
auto source = GetSourceData();
return StringView(source->mSrc + GetSrcStart(), srcLen);
}
@ -956,6 +956,15 @@ void BfAstNode::ToString(StringImpl& str)
str.Append(source->mSrc + GetSrcStart(), srcLen);
}
bool BfAstNode::Equals(const StringImpl& str)
{
int len = mSrcEnd - mSrcStart;
if (len != str.mLength)
return false;
auto source = GetSourceData();
return strncmp(str.GetPtr(), source->mSrc + mSrcStart, len) == 0;
}
//////////////////////////////////////////////////////////////////////////
void BfBlock::Init(const SizedArrayImpl<BfAstNode*>& vec, BfAstAllocator* alloc)

View file

@ -1022,6 +1022,7 @@ public:
String ToString();
StringView ToStringView();
void ToString(StringImpl& str);
bool Equals(const StringImpl& str);
void Init(BfParser* bfParser);
void Accept(BfStructuralVisitor* bfVisitor);
static void ClassAccept(BfAstNode* node, BfStructuralVisitor* bfVisitor) { bfVisitor->Visit(node); }
@ -1733,6 +1734,7 @@ public:
BfTokenNode* mScopeToken;
BfTokenNode* mColonToken;
BfAstNode* mTargetNode; // . : or identifier
BfAttributeDirective* mAttributes;
}; BF_AST_DECL(BfScopeNode, BfAstNode);
class BfNewNode : public BfAstNode
@ -1743,6 +1745,7 @@ public:
BfTokenNode* mNewToken;
BfTokenNode* mColonToken;
BfAstNode* mAllocNode; // Expression or BfScopedInvocationTarget
BfAttributeDirective* mAttributes;
}; BF_AST_DECL(BfNewNode, BfAstNode);
enum BfCommentKind
@ -1849,7 +1852,7 @@ public:
ASTREF(BfTokenNode*) mAttrOpenToken; // [ @ ,
ASTREF(BfTokenNode*) mAttrCloseToken;
ASTREF(BfAttributeTargetSpecifier*) mAttributeTargetSpecifier;
ASTREF(BfAstNode*) mAttributeTargetSpecifier;
ASTREF(BfTypeReference*) mAttributeTypeRef;
ASTREF(BfTokenNode*) mCtorOpenParen;
@ -2534,23 +2537,12 @@ public:
BfGenericArgumentsNode* mGenericArgs;
}; BF_AST_DECL(BfDelegateBindExpression, BfMethodBoundExpression);
class BfLambdaCapture : public BfAstNode
{
public:
BF_AST_TYPE(BfLambdaCapture, BfAstNode);
BfTokenNode* mOpenBracket;
BfTokenNode* mCloseBracket;
BfTokenNode* mCaptureToken;
}; BF_AST_DECL(BfLambdaCapture, BfAstNode);
class BfLambdaBindExpression : public BfExpression
{
public:
BF_AST_TYPE(BfLambdaBindExpression, BfExpression);
BfAstNode* mNewToken;
BfLambdaCapture* mLambdaCapture;
BfAstNode* mNewToken;
BfTokenNode* mOpenParen;
BfTokenNode* mCloseParen;
BfSizedArray<ASTREF(BfIdentifierNode*)> mParams;

View file

@ -380,6 +380,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mClassVDataTypeDef = NULL;
mCLinkAttributeTypeDef = NULL;
mCReprAttributeTypeDef = NULL;
mAlignAttributeTypeDef = NULL;
mNoDiscardAttributeTypeDef = NULL;
mDisableObjectAccessChecksAttributeTypeDef = NULL;
mDbgRawAllocDataTypeDef = NULL;
@ -5832,6 +5833,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mClassVDataTypeDef = _GetRequiredType("System.ClassVData");
mCLinkAttributeTypeDef = _GetRequiredType("System.CLinkAttribute");
mCReprAttributeTypeDef = _GetRequiredType("System.CReprAttribute");
mAlignAttributeTypeDef = _GetRequiredType("System.AlignAttribute");
mNoDiscardAttributeTypeDef = _GetRequiredType("System.NoDiscardAttribute");
mDisableObjectAccessChecksAttributeTypeDef = _GetRequiredType("System.DisableObjectAccessChecksAttribute");
mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData");

View file

@ -378,6 +378,7 @@ public:
BfTypeDef* mInlineAttributeTypeDef;
BfTypeDef* mCLinkAttributeTypeDef;
BfTypeDef* mCReprAttributeTypeDef;
BfTypeDef* mAlignAttributeTypeDef;
BfTypeDef* mNoDiscardAttributeTypeDef;
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
BfTypeDef* mFriendAttributeTypeDef;

View file

@ -143,8 +143,8 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
isConst = false;
}
if (!isConst)
{
if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0))
{
mModule->Fail("Expression does not evaluate to a constant value", expr);
if (wantType != NULL)

View file

@ -132,6 +132,7 @@ void BfElementVisitor::Visit(BfScopeNode* scopeNode)
VisitChild(scopeNode->mScopeToken);
VisitChild(scopeNode->mColonToken);
VisitChild(scopeNode->mTargetNode);
VisitChild(scopeNode->mAttributes);
}
void BfElementVisitor::Visit(BfNewNode* newNode)
@ -141,6 +142,7 @@ void BfElementVisitor::Visit(BfNewNode* newNode)
VisitChild(newNode->mNewToken);
VisitChild(newNode->mColonToken);
VisitChild(newNode->mAllocNode);
VisitChild(newNode->mAttributes);
}
void BfElementVisitor::Visit(BfLabeledBlock* labeledBlock)
@ -532,12 +534,6 @@ void BfElementVisitor::Visit(BfLambdaBindExpression* lambdaBindExpr)
Visit(lambdaBindExpr->ToBase());
VisitChild(lambdaBindExpr->mNewToken);
if (lambdaBindExpr->mLambdaCapture != NULL)
{
VisitChild(lambdaBindExpr->mLambdaCapture->mOpenBracket);
VisitChild(lambdaBindExpr->mLambdaCapture->mCaptureToken);
VisitChild(lambdaBindExpr->mLambdaCapture->mCloseBracket);
}
VisitChild(lambdaBindExpr->mOpenParen);
VisitChild(lambdaBindExpr->mCloseParen);

View file

@ -2818,6 +2818,11 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
varSkipCount--;
}
if (varDecl->mNotCaptured)
{
mModule->Fail("Local variable is not captured", refNode);
}
if ((varSkipCount == 0) && (varDecl != NULL))
{
if ((closureTypeInst != NULL) && (wantName == "this"))
@ -9376,7 +9381,7 @@ void BfExprEvaluator::VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration*
}
}
BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr)
BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget)
{
auto rootMethodState = mModule->mCurMethodState->GetRootMethodState();
BfLambdaInstance* lambdaInstance = NULL;
@ -9527,8 +9532,11 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
return NULL;
}
if (lambdaBindExpr->mNewToken == NULL)
if ((lambdaBindExpr->mNewToken == NULL) || (isFunctionBind))
{
if ((lambdaBindExpr->mNewToken != NULL) && (isFunctionBind))
mModule->Fail("Binds to functions should do not require allocations.", lambdaBindExpr->mNewToken);
if (lambdaBindExpr->mDtor != NULL)
{
mModule->Fail("Valueless method reference cannot contain destructor. Consider either removing destructor or using an allocated lambda.", lambdaBindExpr->mDtor->mTildeToken);
@ -9695,6 +9703,89 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
methodDef->mBody = lambdaBindExpr->mBody;
///
auto varMethodState = methodState.mPrevMethodState;
bool hasExplicitCaptureNames = false;
for (auto& captureEntry : allocTarget.mCaptureInfo.mCaptures)
{
if (captureEntry.mNameNode == NULL)
{
hasExplicitCaptureNames = false;
break;
}
hasExplicitCaptureNames = true;
}
auto _SetNotCapturedFlag = [&](bool notCaptured)
{
auto varMethodState = methodState.mPrevMethodState;
while (varMethodState != NULL)
{
for (int localIdx = 0; localIdx < varMethodState->mLocals.size(); localIdx++)
{
auto localVar = varMethodState->mLocals[localIdx];
localVar->mNotCaptured = notCaptured;
}
varMethodState = varMethodState->mPrevMethodState;
if (varMethodState == NULL)
break;
if (varMethodState->mMixinState != NULL)
break;
if (varMethodState->mClosureState != NULL)
{
if (!varMethodState->mClosureState->mCapturing)
break;
}
}
};
if (hasExplicitCaptureNames)
{
_SetNotCapturedFlag(true);
auto varMethodState = methodState.mPrevMethodState;
while (varMethodState != NULL)
{
for (auto& captureEntry : allocTarget.mCaptureInfo.mCaptures)
{
if (captureEntry.mNameNode != NULL)
{
StringT<64> captureName;
captureEntry.mNameNode->ToString(captureName);
BfLocalVarEntry* entry;
if (varMethodState->mLocalVarSet.TryGetWith<StringImpl&>(captureName, &entry))
{
auto localVar = entry->mLocalVar;
while (localVar != NULL)
{
if (autoComplete != NULL)
autoComplete->CheckLocalRef(captureEntry.mNameNode, localVar);
if (((mModule->mCurMethodState->mClosureState == NULL) || (mModule->mCurMethodState->mClosureState->mCapturing)) &&
(mModule->mCompiler->mResolvePassData != NULL) && (mModule->mCurMethodInstance != NULL))
mModule->mCompiler->mResolvePassData->HandleLocalReference(captureEntry.mNameNode, localVar->mNameNode, mModule->mCurTypeInstance->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVar->mLocalVarId);
localVar->mNotCaptured = false;
localVar = localVar->mShadowedLocal;
}
}
}
}
varMethodState = varMethodState->mPrevMethodState;
if (varMethodState == NULL)
break;
if (varMethodState->mMixinState != NULL)
break;
if (varMethodState->mClosureState != NULL)
{
if (!varMethodState->mClosureState->mCapturing)
break;
}
}
}
BfClosureInstanceInfo* closureInstanceInfo = new BfClosureInstanceInfo();
auto checkInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
@ -9704,6 +9795,9 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
VisitLambdaBodies(lambdaBindExpr->mBody, lambdaBindExpr->mDtor);
if (hasExplicitCaptureNames)
_SetNotCapturedFlag(false);
// If we ended up being called by a method with a lower captureStartAccessId, propagate that to whoever is calling us, too...
if ((methodState.mPrevMethodState->mClosureState != NULL) && (methodState.mPrevMethodState->mClosureState->mCapturing))
{
@ -9731,18 +9825,27 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
prevIgnoreWrites.Restore();
mModule->mBfIRBuilder->RestoreDebugLocation();
BfCaptureType captureType = BfCaptureType_Value;
if ((lambdaBindExpr->mLambdaCapture != NULL) && (lambdaBindExpr->mLambdaCapture->mCaptureToken != NULL))
auto _GetCaptureType = [&](const StringImpl& str)
{
if (lambdaBindExpr->mLambdaCapture->mCaptureToken->GetToken() == BfToken_Ampersand)
captureType = BfCaptureType_Reference;
else
captureType = BfCaptureType_Copy;
}
if (allocTarget.mCaptureInfo.mCaptures.IsEmpty())
return BfCaptureType_Copy;
for (auto& captureEntry : allocTarget.mCaptureInfo.mCaptures)
{
if ((captureEntry.mNameNode == NULL) || (captureEntry.mNameNode->Equals(str)))
{
captureEntry.mUsed = true;
return captureEntry.mCaptureType;
}
}
return BfCaptureType_None;
};
Array<BfClosureCapturedEntry> capturedEntries;
bool copyOuterCaptures = false;
//
{
auto varMethodState = methodState.mPrevMethodState;
@ -9771,6 +9874,11 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
auto capturedType = outerLocal->mResolvedType;
bool captureByRef = false;
auto captureType = _GetCaptureType(localVar->mName);
if (captureType == BfCaptureType_None)
{
continue;
}
if (!capturedType->IsRef())
{
@ -9823,9 +9931,17 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
}
}
for (auto& captureEntry : allocTarget.mCaptureInfo.mCaptures)
{
if ((!captureEntry.mUsed) && (captureEntry.mNameNode != NULL))
mModule->Warn(0, "Capture specifier not used", captureEntry.mNameNode);
}
for (auto copyField : closureState.mReferencedOuterClosureMembers)
{
auto fieldDef = copyField->GetFieldDef();
auto captureType = _GetCaptureType(fieldDef->mName);
BfClosureCapturedEntry capturedEntry;
capturedEntry.mName = fieldDef->mName;
capturedEntry.mType = copyField->mResolvedType;
@ -10200,7 +10316,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr)
return;
}
BfLambdaInstance* lambdaInstance = GetLambdaInstance(lambdaBindExpr);
BfLambdaInstance* lambdaInstance = GetLambdaInstance(lambdaBindExpr, allocTarget);
if (lambdaInstance == NULL)
return;
BfTypeInstance* delegateTypeInstance = lambdaInstance->mDelegateTypeInstance;
@ -11052,7 +11168,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
arrayValue = BfTypedValue(mModule->AppendAllocFromType(resultType, BfIRValue(), 0, arraySize, (int)dimLengthVals.size(), isRawArrayAlloc, false), ptrType);
else
{
arrayValue = BfTypedValue(mModule->AllocFromType(resultType, allocTarget, BfIRValue(), arraySize, (int)dimLengthVals.size(), allocFlags), ptrType);
arrayValue = BfTypedValue(mModule->AllocFromType(resultType, allocTarget, BfIRValue(), arraySize, (int)dimLengthVals.size(), allocFlags, allocTarget.mAlignOverride), ptrType);
}
_HandleInitExprs(arrayValue.mValue, 0, objCreateExpr->mArguments);
@ -11071,7 +11187,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
arrayValue = BfTypedValue(mModule->AppendAllocFromType(resultType, BfIRValue(), 0, arraySize, (int)dimLengthVals.size(), isRawArrayAlloc, zeroMemory), arrayType);
else
{
arrayValue = BfTypedValue(mModule->AllocFromType(resultType, allocTarget, BfIRValue(), arraySize, (int)dimLengthVals.size(), allocFlags), arrayType);
arrayValue = BfTypedValue(mModule->AllocFromType(resultType, allocTarget, BfIRValue(), arraySize, (int)dimLengthVals.size(), allocFlags, allocTarget.mAlignOverride), arrayType);
if (isScopeAlloc)
{
@ -11538,6 +11654,7 @@ void BfExprEvaluator::Visit(BfBoxExpression* boxExpr)
BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenNode*& newToken)
{
auto autoComplete = GetAutoComplete();
BfAttributeDirective* attributeDirective = NULL;
BfAllocTarget allocTarget;
allocTarget.mRefNode = allocNode;
@ -11555,6 +11672,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
if ((scopeNode->mTargetNode == NULL) || (targetIdentifier != NULL))
autoComplete->CheckLabel(targetIdentifier, scopeNode->mColonToken);
}
attributeDirective = scopeNode->mAttributes;
}
if (auto newNode = BfNodeDynCast<BfNewNode>(allocNode))
{
@ -11568,6 +11686,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
{
allocTarget.mScopedInvocationTarget = scopedInvocationTarget;
}
attributeDirective = newNode->mAttributes;
}
}
else if (newToken->GetToken() == BfToken_Scope)
@ -11580,6 +11699,38 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
if (mModule->mCurMethodState != NULL)
allocTarget.mScopeData = &mModule->mCurMethodState->mHeadScope;
}
if (attributeDirective != NULL)
{
auto customAttrs = mModule->GetCustomAttributes(attributeDirective, BfAttributeTargets_Alloc, true, &allocTarget.mCaptureInfo);
if (customAttrs != NULL)
{
for (auto& attrib : customAttrs->mAttributes)
{
if (attrib.mType->mTypeDef == mModule->mCompiler->mAlignAttributeTypeDef)
{
allocTarget.mAlignOverride = 16; // System conservative default
if (!attrib.mCtorArgs.IsEmpty())
{
BfIRConstHolder* constHolder = mModule->mCurTypeInstance->mConstHolder;
auto constant = constHolder->GetConstant(attrib.mCtorArgs[0]);
if (constant != NULL)
{
int alignOverride = (int)BF_MAX(1, constant->mInt64);
if ((alignOverride & (alignOverride - 1)) == 0)
allocTarget.mAlignOverride = alignOverride;
else
mModule->Fail("Alignment must be a power of 2", attrib.mRef);
}
}
}
}
delete customAttrs;
}
}
return allocTarget;
}

View file

@ -378,7 +378,7 @@ public:
BfTypeInstance* VerifyBaseDelegateType(BfTypeInstance* delegateType);
void ConstResolve(BfExpression* expr);
void ProcessArrayInitializer(BfTokenNode* openToken, const BfSizedArray<BfExpression*>& values, const BfSizedArray<BfTokenNode*>& commas, BfTokenNode* closeToken, int dimensions, SizedArrayImpl<int64>& dimLengths, int dim, bool& hasFailed);
BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr);
BfLambdaInstance* GetLambdaInstance(BfLambdaBindExpression* lambdaBindExpr, BfAllocTarget& allocTarget);
void VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);

View file

@ -7521,7 +7521,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
}
if (!isDynAlloc)
mBfIRBuilder->ClearDebugLocation(allocaInst);
mBfIRBuilder->SetAllocaAlignment(allocaInst, type->mAlign);
mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
if (!isDynAlloc)
mBfIRBuilder->SetInsertPoint(prevInsertBlock);
auto typedVal = BfTypedValue(result, type, BfTypedValueKind_Addr);
@ -7606,7 +7606,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(byteType), sizeValue);
if (!isDynAlloc)
mBfIRBuilder->ClearDebugLocation(allocaInst);
mBfIRBuilder->SetAllocaAlignment(allocaInst, arrayType->mAlign);
mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
auto typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(arrayType)), arrayType);
mBfIRBuilder->ClearDebugLocation_Last();
if (!isDynAlloc)
@ -9214,6 +9214,7 @@ static String GetAttributesTargetListString(BfAttributeTargets attrTarget)
AddAttributeTargetName(flagsLeft, BfAttributeTargets_GenericParameter, resultStr, "generic parameters");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Invocation, resultStr, "invocations");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_MemberAccess, resultStr, "member access");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alloc, resultStr, "allocations");
if (resultStr.IsEmpty())
return "<nothing>";
return resultStr;
@ -9377,7 +9378,7 @@ void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, Bf
}
}
void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget)
void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget, bool allowNonConstArgs, BfCaptureInfo* captureInfo)
{
if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) &&
(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
@ -9398,6 +9399,26 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
for (; attributesDirective != NULL; attributesDirective = attributesDirective->mNextAttribute)
{
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(attributesDirective->mAttributeTargetSpecifier))
{
if (captureInfo == NULL)
{
Fail("Capture specifiers can only be used in lambda allocations", attributesDirective);
continue;
}
BfCaptureInfo::Entry captureEntry;
captureEntry.mCaptureType = (tokenNode->mToken == BfToken_Ampersand) ? BfCaptureType_Reference : BfCaptureType_Copy;
if (!attributesDirective->mArguments.IsEmpty())
{
captureEntry.mNameNode = BfNodeDynCast<BfIdentifierNode>(attributesDirective->mArguments[0]);
if ((captureEntry.mNameNode != NULL) && (autoComplete != NULL))
autoComplete->CheckIdentifier(captureEntry.mNameNode);
}
captureInfo->mCaptures.Add(captureEntry);
continue;
}
BfAutoParentNodeEntry autoParentNodeEntry(this, attributesDirective);
BfCustomAttribute customAttribute;
@ -9509,7 +9530,9 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
customAttribute.mType = attrTypeInst;
BfConstResolver constResolver(this);
BfConstResolver constResolver(this);
if (allowNonConstArgs)
constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
bool inPropSet = false;
SizedArray<BfResolvedArg, 2> argValues;
@ -9775,7 +9798,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
// Move all those to the constHolder
for (auto& ctorArg : customAttribute.mCtorArgs)
{
CurrentAddToConstHolder(ctorArg);
if (ctorArg.IsConst())
CurrentAddToConstHolder(ctorArg);
}
if (attributesDirective->mAttributeTargetSpecifier != NULL)
@ -9835,10 +9859,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
ValidateCustomAttributes(customAttributes, attrTarget);
}
BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType)
BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs, BfCaptureInfo* captureInfo)
{
BfCustomAttributes* customAttributes = new BfCustomAttributes();
GetCustomAttributes(customAttributes, attributesDirective, attrType);
GetCustomAttributes(customAttributes, attributesDirective, attrType, allowNonConstArgs, captureInfo);
return customAttributes;
}

View file

@ -65,7 +65,8 @@ enum BfEvalExprFlags
BfEvalExprFlags_AllowOutExpr = 0x1000,
BfEvalExprFlags_FieldInitializer = 0x2000,
BfEvalExprFlags_VariableDeclaration = 0x4000,
BfEvalExprFlags_NoAutoComplete = 0x8000
BfEvalExprFlags_NoAutoComplete = 0x8000,
BfEvalExprFlags_AllowNonConst = 0x10000
};
enum BfCastFlags
@ -146,6 +147,7 @@ public:
bool mAllowAddr;
bool mIsShadow;
bool mUsedImplicitly; // Passed implicitly to a local method, capture by ref if we can
bool mNotCaptured;
BfLocalVariable* mShadowedLocal;
public:
@ -172,6 +174,7 @@ public:
mAllowAddr = false;
mIsShadow = false;
mUsedImplicitly = false;
mNotCaptured = false;
mShadowedLocal = NULL;
}
@ -441,6 +444,27 @@ public:
}
};
struct BfCaptureInfo
{
public:
struct Entry
{
BfCaptureType mCaptureType;
bool mUsed;
BfIdentifierNode* mNameNode;
Entry()
{
mCaptureType = BfCaptureType_Copy;
mUsed = false;
mNameNode = NULL;
}
};
public:
Array<Entry> mCaptures;
};
class BfAllocTarget
{
public:
@ -448,6 +472,8 @@ public:
BfAstNode* mRefNode;
BfTypedValue mCustomAllocator;
BfScopedInvocationTarget* mScopedInvocationTarget;
int mAlignOverride;
BfCaptureInfo mCaptureInfo;
public:
BfAllocTarget()
@ -456,6 +482,7 @@ public:
mRefNode = NULL;
mCustomAllocator = NULL;
mScopedInvocationTarget = NULL;
mAlignOverride = -1;
}
BfAllocTarget(BfScopeData* scopeData)
@ -464,6 +491,7 @@ public:
mRefNode = NULL;
mCustomAllocator = NULL;
mScopedInvocationTarget = NULL;
mAlignOverride = -1;
}
BfAllocTarget(const BfTypedValue& customAllocator, BfAstNode* refNode)
@ -472,6 +500,7 @@ public:
mCustomAllocator = customAllocator;
mRefNode = NULL;
mScopedInvocationTarget = NULL;
mAlignOverride = -1;
}
};
@ -1409,8 +1438,8 @@ public:
BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType);
void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget);
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType);
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType);
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL);
void ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered);
void ProcessCustomAttributeData();
bool TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue, StringImpl& str);

View file

@ -588,6 +588,35 @@ void BfPrinter::Visit(BfErrorNode* errorNode)
VisitChild(errorNode->mRefNode);
}
void BfPrinter::Visit(BfScopeNode* scopeNode)
{
Visit(scopeNode->ToBase());
VisitChild(scopeNode->mScopeToken);
VisitChild(scopeNode->mColonToken);
VisitChild(scopeNode->mTargetNode);
if (scopeNode->mAttributes != NULL)
{
ExpectSpace();
VisitChild(scopeNode->mAttributes);
}
}
void BfPrinter::Visit(BfNewNode* newNode)
{
Visit(newNode->ToBase());
VisitChild(newNode->mNewToken);
VisitChild(newNode->mColonToken);
VisitChild(newNode->mAllocNode);
if (newNode->mAttributes != NULL)
{
ExpectSpace();
VisitChild(newNode->mAttributes);
}
}
void BfPrinter::Visit(BfExpression* expr)
{
Visit(expr->ToBase());
@ -698,14 +727,19 @@ void BfPrinter::Visit(BfAttributeDirective* attributeDirective)
VisitChild(attributeDirective->mAttrOpenToken);
}
}
if (attributeDirective->mAttributeTargetSpecifier != NULL)
{
VisitChild(attributeDirective->mAttributeTargetSpecifier->mTargetToken);
VisitChild(attributeDirective->mAttributeTargetSpecifier->mColonToken);
ExpectSpace();
if (auto attributeTargetSpecifier = BfNodeDynCast<BfAttributeTargetSpecifier>(attributeDirective->mAttributeTargetSpecifier))
{
VisitChild(attributeTargetSpecifier->mTargetToken);
VisitChild(attributeTargetSpecifier->mColonToken);
ExpectSpace();
}
else
{
VisitChild(attributeDirective->mAttributeTargetSpecifier);
}
}
VisitChild(attributeDirective->mAttributeTypeRef);
@ -1226,13 +1260,7 @@ void BfPrinter::Visit(BfLambdaBindExpression* lambdaBindExpr)
Visit(lambdaBindExpr->ToBase());
VisitChild(lambdaBindExpr->mNewToken);
ExpectSpace();
if (lambdaBindExpr->mLambdaCapture != NULL)
{
VisitChild(lambdaBindExpr->mLambdaCapture->mOpenBracket);
VisitChild(lambdaBindExpr->mLambdaCapture->mCaptureToken);
VisitChild(lambdaBindExpr->mLambdaCapture->mCloseBracket);
}
ExpectSpace();
VisitChild(lambdaBindExpr->mOpenParen);
for (int i = 0; i < (int)lambdaBindExpr->mParams.size(); i++)
{

View file

@ -101,6 +101,8 @@ public:
virtual void Visit(BfAstNode* bfAstNode) override;
virtual void Visit(BfErrorNode* bfErrorNode) override;
virtual void Visit(BfScopeNode * scopeNode) override;
virtual void Visit(BfNewNode * newNode) override;
virtual void Visit(BfExpression* expr) override;
virtual void Visit(BfExpressionStatement* exprStmt) override;
virtual void Visit(BfAttributedExpression* attribExpr) override;

View file

@ -5105,6 +5105,8 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
ReplaceNode(startToken, attributeDirective);
attributeDirective->mAttrOpenToken = startToken;
bool isHandled = false;
auto nextNode = mVisitorPos.GetNext();
auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
if (tokenNode != NULL)
@ -5114,32 +5116,50 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
auto attributeTargetSpecifier = mAlloc->Alloc<BfAttributeTargetSpecifier>();
ReplaceNode(tokenNode, attributeTargetSpecifier);
MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, attributeTargetSpecifier);
attributeDirective->mAttributeTargetSpecifier->mTargetToken = tokenNode;
attributeTargetSpecifier->mTargetToken = tokenNode;
mVisitorPos.MoveNext();
tokenNode = ExpectTokenAfter(attributeDirective, BfToken_Colon);
if (tokenNode != NULL)
MEMBER_SET(attributeDirective->mAttributeTargetSpecifier, mColonToken, tokenNode);
MEMBER_SET(attributeTargetSpecifier, mColonToken, tokenNode);
attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd());
}
}
auto typeRef = CreateTypeRefAfter(attributeDirective);
if (typeRef == NULL)
{
auto nextNode = mVisitorPos.GetNext();
if (BfTokenNode* endToken = BfNodeDynCast<BfTokenNode>(nextNode))
else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals))
{
if (endToken->GetToken() == BfToken_RBracket)
MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, tokenNode);
mVisitorPos.MoveNext();
isHandled = true;
nextNode = mVisitorPos.GetNext();
if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(nextNode))
{
attributeDirective->SetSrcEnd(identiferNode->GetSrcEnd());
arguments.push_back(identiferNode);
mVisitorPos.MoveNext();
MEMBER_SET(attributeDirective, mCtorCloseParen, endToken);
return attributeDirective;
nextNode = mVisitorPos.GetNext();
}
}
return attributeDirective;
}
MEMBER_SET(attributeDirective, mAttributeTypeRef, typeRef);
if (!isHandled)
{
auto typeRef = CreateTypeRefAfter(attributeDirective);
if (typeRef == NULL)
{
auto nextNode = mVisitorPos.GetNext();
if (BfTokenNode* endToken = BfNodeDynCast<BfTokenNode>(nextNode))
{
if (endToken->GetToken() == BfToken_RBracket)
{
mVisitorPos.MoveNext();
MEMBER_SET(attributeDirective, mCtorCloseParen, endToken);
return attributeDirective;
}
}
return attributeDirective;
}
MEMBER_SET(attributeDirective, mAttributeTypeRef, typeRef);
}
tokenNode = ExpectTokenAfter(attributeDirective, BfToken_LParen, BfToken_RBracket, BfToken_Comma);
if (tokenNode == NULL)
return attributeDirective;
@ -5159,8 +5179,7 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
tokenNode = ExpectTokenAfter(attributeDirective, BfToken_RBracket, BfToken_Comma);
if (tokenNode == NULL)
return attributeDirective;
}
}
Do_RBracket:
if (tokenNode->GetToken() == BfToken_RBracket)
{
@ -5171,9 +5190,8 @@ Do_RBracket:
return attributeDirective;
mVisitorPos.MoveNext();
}
// Has another one- chain it
//mVisitorPos.MoveNext();
// Has another one- chain it
auto nextAttribute = CreateAttributeDirective(tokenNode);
if (nextAttribute != NULL)
{
@ -6810,41 +6828,10 @@ BfLambdaBindExpression* BfReducer::CreateLambdaBindExpression(BfAstNode* allocNo
ReplaceNode(parenToken, lambdaBindExpr);
tokenNode = parenToken;
}
//auto tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_LParen, BfToken_LBracket);
if (tokenNode == NULL)
return lambdaBindExpr;
if (tokenNode->GetToken() == BfToken_LBracket)
{
auto lambdaCapture = mAlloc->Alloc<BfLambdaCapture>();
ReplaceNode(tokenNode, lambdaCapture);
MEMBER_SET(lambdaBindExpr, mLambdaCapture, lambdaCapture);
MEMBER_SET(lambdaCapture, mOpenBracket, tokenNode);
while (true)
{
tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_Ampersand, BfToken_AssignEquals, BfToken_RBracket);
if (tokenNode == NULL)
return lambdaBindExpr;
if ((tokenNode->GetToken() == BfToken_Ampersand) || (tokenNode->GetToken() == BfToken_AssignEquals))
{
MEMBER_SET(lambdaCapture, mCaptureToken, tokenNode);
lambdaBindExpr->SetSrcEnd(lambdaCapture->GetSrcEnd());
}
if (tokenNode->GetToken() == BfToken_RBracket)
{
MEMBER_SET(lambdaCapture, mCloseBracket, tokenNode);
lambdaBindExpr->SetSrcEnd(lambdaCapture->GetSrcEnd());
break;
}
}
tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_LParen);
}
MEMBER_SET_CHECKED(lambdaBindExpr, mOpenParen, tokenNode);
for (int paramIdx = 0; true; paramIdx++)
@ -7051,11 +7038,17 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
if (allocToken->GetToken() == BfToken_Scope)
{
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_Colon))
{
auto scopeNode = mAlloc->Alloc<BfScopeNode>();
ReplaceNode(allocToken, scopeNode);
scopeNode->mScopeToken = allocToken;
if (nextToken == NULL)
return allocToken;
if ((nextToken->mToken != BfToken_Colon) && (nextToken->mToken != BfToken_LBracket))
return allocToken;
auto scopeNode = mAlloc->Alloc<BfScopeNode>();
ReplaceNode(allocToken, scopeNode);
scopeNode->mScopeToken = allocToken;
if (nextToken->mToken == BfToken_Colon)
{
MEMBER_SET(scopeNode, mColonToken, nextToken);
mVisitorPos.MoveNext();
@ -7077,19 +7070,36 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
{
FailAfter("Expected scope name", scopeNode);
}
return scopeNode;
}
nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if (nextToken == NULL)
return scopeNode;
if (nextToken->mToken != BfToken_LBracket)
return scopeNode;
mVisitorPos.MoveNext();
auto attributeDirective = CreateAttributeDirective(nextToken);
MEMBER_SET(scopeNode, mAttributes, attributeDirective);
return scopeNode;
}
if (allocToken->GetToken() == BfToken_New)
{//
{
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_Colon))
{ //
auto newNode = mAlloc->Alloc<BfNewNode>();
ReplaceNode(allocToken, newNode);
newNode->mNewToken = allocToken;
if (nextToken == NULL)
return allocToken;
if ((nextToken->mToken != BfToken_Colon) && (nextToken->mToken != BfToken_LBracket))
return allocToken;
auto newNode = mAlloc->Alloc<BfNewNode>();
ReplaceNode(allocToken, newNode);
newNode->mNewToken = allocToken;
if (nextToken->mToken == BfToken_Colon)
{
MEMBER_SET(newNode, mColonToken, nextToken);
mVisitorPos.MoveNext();
@ -7166,15 +7176,7 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
{
MEMBER_SET(newNode, mAllocNode, identifier);
mVisitorPos.MoveNext();
}
// This causes parse ambiguities
/*mVisitorPos.mReadPos = nodeIdx;
auto allocExpr = CreateExpressionAfter(newNode, BfReducer::CreateExprFlags_NoCast);
if (allocExpr != NULL)
{
MEMBER_SET(newNode, mAllocNode, allocExpr);
}*/
}
}
}
@ -7183,9 +7185,19 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
{
FailAfter("Expected allocator expression", newNode);
}
return newNode;
}
nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if (nextToken == NULL)
return newNode;
if (nextToken->mToken != BfToken_LBracket)
return newNode;
mVisitorPos.MoveNext();
auto attributeDirective = CreateAttributeDirective(nextToken);
MEMBER_SET(newNode, mAttributes, attributeDirective);
return newNode;
}
return allocToken;

View file

@ -1411,6 +1411,7 @@ enum BfAttributeTargets : int32
BfAttributeTargets_GenericParameter = 0x8000,
BfAttributeTargets_Invocation = 0x10000,
BfAttributeTargets_MemberAccess = 0x20000,
BfAttributeTargets_Alloc = 0x40000,
BfAttributeTargets_All = 0x3FFFF
};
@ -1879,9 +1880,9 @@ public:
enum BfCaptureType
{
BfCaptureType_Value,
BfCaptureType_Reference,
BfCaptureType_Copy
BfCaptureType_None,
BfCaptureType_Copy,
BfCaptureType_Reference,
};
class BfClosureType : public BfTypeInstance

View file

@ -206,8 +206,15 @@ void BfSourceClassifier::Visit(BfAttributeDirective* attributeDirective)
if (attributeDirective->mAttributeTargetSpecifier != NULL)
{
VisitChild(attributeDirective->mAttributeTargetSpecifier->mTargetToken);
VisitChild(attributeDirective->mAttributeTargetSpecifier->mColonToken);
if (auto attributeTargetSpecifier = BfNodeDynCast<BfAttributeTargetSpecifier>(attributeDirective->mAttributeTargetSpecifier))
{
VisitChild(attributeTargetSpecifier->mTargetToken);
VisitChild(attributeTargetSpecifier->mColonToken);
}
else
{
VisitChild(attributeDirective->mAttributeTargetSpecifier);
}
}
VisitChild(attributeDirective->mAttributeTypeRef);