1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28: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

@ -25,6 +25,7 @@ namespace System
GenericParameter = 0x8000,
Invocation = 0x10000,
MemberAccess = 0x20000,
Alloc = 0x40000,
All = Assembly | Module | Class | Struct | Enum | Constructor |
Method | Property | Field | StaticField | Interface | Parameter |
@ -57,7 +58,7 @@ namespace System
public sealed struct AttributeUsageAttribute : Attribute
{
internal AttributeTargets mAttributeTarget = AttributeTargets.All;
internal AttributeTargets mAttributeTarget = .All;
internal AttributeFlags mAttributeFlags = .None;
internal ReflectKind mReflectUser = .None;
@ -93,7 +94,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.All)]
[AttributeUsage(.All)]
public struct ReflectAttribute : Attribute
{
public this(ReflectKind reflectKind = .All)
@ -101,13 +102,13 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Method /*1*/ | .Invocation | .Property)]
[AttributeUsage(.Method /*1*/ | .Invocation | .Property)]
public struct InlineAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Invocation)]
[AttributeUsage(.Invocation)]
public struct UnboundAttribute : Attribute
{
@ -125,13 +126,13 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.MemberAccess)]
[AttributeUsage(.MemberAccess)]
public struct FriendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.MemberAccess)]
[AttributeUsage(.MemberAccess)]
public struct SkipAccessCheckAttribute : Attribute
{
@ -143,13 +144,13 @@ namespace System
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
[AttributeUsage(.Method /*2*/ | .StaticField)]
public struct CLinkAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
[AttributeUsage(.Method /*2*/ | .StaticField)]
public struct LinkNameAttribute : Attribute
{
public this(String linkName)
@ -158,31 +159,31 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Method | .Delegate | .Function)]
[AttributeUsage(.Method | .Delegate | .Function)]
public struct StdCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct CVarArgsAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct NoReturnAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct SkipCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct IntrinsicAttribute : Attribute
{
public this(String intrinName)
@ -191,7 +192,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct /*2*/)]
[AttributeUsage(.Class | .Struct /*2*/)]
public struct StaticInitPriorityAttribute : Attribute
{
public this(int priority)
@ -200,7 +201,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Class /*2*/ | AttributeTargets.Struct /*2*/)]
[AttributeUsage(.Class /*2*/ | .Struct /*2*/)]
public struct StaticInitAfterAttribute : Attribute
{
public this()
@ -214,50 +215,59 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Struct)]
[AttributeUsage(.Struct)]
public struct ForceAddrAttribute : Attribute
{
}
/// This attribute is required on constructors that include 'append' allocations.
[AttributeUsage(AttributeTargets.Constructor)]
[AttributeUsage(.Constructor)]
public struct AllowAppendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct PackedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct | .Alloc)]
public struct AlignAttribute : Attribute
{
public this(int align)
{
}
}
[AttributeUsage(.Class | .Struct)]
public struct UnionAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct CReprAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct OrderedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
[AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
[AttributeUsage(.Field | .Method /*2*/)]
public struct HideAttribute : Attribute
{
@ -269,7 +279,7 @@ namespace System
{
}
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
[AttributeUsage(.Method/*, AlwaysIncludeTarget=true*/)]
public struct TestAttribute : Attribute
{
public bool ShouldFail;
@ -289,7 +299,7 @@ namespace System
}
[AttributeUsage(AttributeTargets.StaticField | AttributeTargets.Field, .NotInherited)]
[AttributeUsage(.StaticField | .Field, .NotInherited)]
public struct ThreadStaticAttribute : Attribute
{
public this()
@ -321,7 +331,7 @@ namespace System
/// Generally used as a per-method optimization, [DisableObjectAccessChecks] will avoid the runtime per-object-access
/// checks which by default are only applied in debug builds anyway.
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
[AttributeUsage(.Method/*, AlwaysIncludeTarget=true*/)]
public struct DisableObjectAccessChecksAttribute : Attribute
{
}

View file

@ -25,6 +25,7 @@ namespace System
GenericParameter = 0x8000,
Invocation = 0x10000,
MemberAccess = 0x20000,
Alloc = 0x40000,
All = Assembly | Module | Class | Struct | Enum | Constructor |
Method | Property | Field | StaticField | Interface | Parameter |
@ -93,7 +94,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.All)]
[AttributeUsage(.All)]
public struct ReflectAttribute : Attribute
{
public this(ReflectKind reflectKind = .All)
@ -101,13 +102,13 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Method /*1*/ | .Invocation | .Property)]
[AttributeUsage(.Method /*1*/ | .Invocation | .Property)]
public struct InlineAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Invocation)]
[AttributeUsage(.Invocation)]
public struct UnboundAttribute : Attribute
{
@ -125,13 +126,13 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.MemberAccess)]
[AttributeUsage(.MemberAccess)]
public struct FriendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.MemberAccess)]
[AttributeUsage(.MemberAccess)]
public struct SkipAccessCheckAttribute : Attribute
{
@ -143,13 +144,13 @@ namespace System
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
[AttributeUsage(.Method /*2*/ | .StaticField)]
public struct CLinkAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/ | AttributeTargets.StaticField)]
[AttributeUsage(.Method /*2*/ | .StaticField)]
public struct LinkNameAttribute : Attribute
{
public this(String linkName)
@ -158,31 +159,31 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Method | .Delegate | .Function)]
[AttributeUsage(.Method | .Delegate | .Function)]
public struct StdCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct CVarArgsAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct NoReturnAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct SkipCallAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method /*2*/)]
[AttributeUsage(.Method /*2*/)]
public struct IntrinsicAttribute : Attribute
{
public this(String intrinName)
@ -206,7 +207,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct /*2*/)]
[AttributeUsage(.Class | .Struct /*2*/)]
public struct StaticInitPriorityAttribute : Attribute
{
public this(int priority)
@ -215,7 +216,7 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Class /*2*/ | AttributeTargets.Struct /*2*/)]
[AttributeUsage(.Class /*2*/ | .Struct /*2*/)]
public struct StaticInitAfterAttribute : Attribute
{
public this()
@ -229,49 +230,58 @@ namespace System
}
}
[AttributeUsage(AttributeTargets.Struct)]
[AttributeUsage(.Struct)]
public struct ForceAddrAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Constructor)]
[AttributeUsage(.Constructor)]
public struct AllowAppendAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct PackedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct | .Alloc)]
public struct AlignAttribute : Attribute
{
public this(int align)
{
}
}
[AttributeUsage(.Class | .Struct)]
public struct UnionAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct CReprAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
[AttributeUsage(.Class | .Struct)]
public struct OrderedAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
[AttributeUsage(.Field | .Method /*2*/)]
public struct NoShowAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field | .Method /*2*/)]
[AttributeUsage(.Field | .Method /*2*/)]
public struct HideAttribute : Attribute
{
@ -283,7 +293,7 @@ namespace System
{
}
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
[AttributeUsage(.Method/*, AlwaysIncludeTarget=true*/)]
public struct TestAttribute : Attribute
{
public bool ShouldFail;
@ -303,7 +313,7 @@ namespace System
}
[AttributeUsage(AttributeTargets.StaticField | AttributeTargets.Field, .NotInherited)]
[AttributeUsage(.StaticField | .Field, .NotInherited)]
public struct ThreadStaticAttribute : Attribute
{
public this()
@ -327,7 +337,7 @@ namespace System
{
}
[AttributeUsage(AttributeTargets.Method/*, AlwaysIncludeTarget=true*/)]
[AttributeUsage(.Method/*, AlwaysIncludeTarget=true*/)]
public struct DisableObjectAccessChecksAttribute : Attribute
{
}

View file

@ -164,7 +164,7 @@ namespace IDE
IDEUtils.FixFilePath(llvmDir);
llvmDir.Append("llvm/");
#else
String llvmDir = "";
//String llvmDir = "";
#endif
//String error = scope String();

View file

@ -1386,7 +1386,10 @@ void BeIRCodeGen::HandleNextCmd()
{
BF_ASSERT(!((BeStructType*)type)->mIsOpaque);
}
SetResult(curId, mBeModule->CreateAlloca(type));
auto allocaInst = mBeModule->CreateAlloca(type);
allocaInst->mAlign = type->mAlign;
SetResult(curId, allocaInst);
}
break;
case BfIRCmd_AllocaArray:
@ -1396,6 +1399,7 @@ void BeIRCodeGen::HandleNextCmd()
auto allocaInst = mBeModule->AllocInst<BeAllocaInst>();
allocaInst->mType = type;
allocaInst->mAlign = type->mAlign;
allocaInst->mArraySize = arraySize;
SetResult(curId, allocaInst);
@ -1406,6 +1410,8 @@ void BeIRCodeGen::HandleNextCmd()
CMD_PARAM(BeValue*, val);
CMD_PARAM(int, alignment);
auto inst = BeValueDynCast<BeAllocaInst>(val);
inst->mAlign = alignment;
//TODO: Implement
/*inst->setAlignment(alignment);*/
}

View file

@ -2941,6 +2941,8 @@ BeMCOperand BeMCContext::CreateCall(const BeMCOperand& func, const SizedArrayImp
SizedArray<_ShadowReg, 8> shadowRegs;
BF_ASSERT(mMaxCallParamCount >= argCount);
mMaxCallParamCount = BF_MAX(mMaxCallParamCount, argCount);
for (int argIdx = args.size() - 1; argIdx >= 0; argIdx--)
{
@ -3651,6 +3653,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe
int vregIdx = (int)mVRegInfo.size();
BeMCVRegInfo* vregInfo = mAlloc.Alloc<BeMCVRegInfo>();
vregInfo->mType = type;
vregInfo->mAlign = type->mAlign;
vregInfo->mRefCount = refCount;
vregInfo->mForceReg = mustBeReg;
mVRegInfo.push_back(vregInfo);
@ -3661,7 +3664,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe
if (mDebugging)
{
if (mcOperand.mVRegIdx == 31)
if (mcOperand.mVRegIdx == 3)
{
NOP;
}
@ -7902,12 +7905,6 @@ void BeMCContext::DoFrameObjPass()
// we need for calls with more than 4 params.
// If we're doing UseBP, we have to allocate these at call time
int homeSize = BF_ALIGN(BF_MAX(mMaxCallParamCount, 4) * 8, 16);
for (int homeVRegIdx : mDeferredHomeSizeOffsets)
{
auto vregInfo = mVRegInfo[homeVRegIdx];
BF_ASSERT(vregInfo->mRelOffset.mImmediate == -1);
vregInfo->mRelOffset.mImmediate = BF_ALIGN(homeSize, 16);
}
mStackSize = 0;
@ -7947,12 +7944,13 @@ void BeMCContext::DoFrameObjPass()
if ((vregInfo->mRefCount > 0) && (!vregInfo->mIsExpr) && (vregInfo->mReg == X64Reg_None) && (vregInfo->mFrameOffset == INT_MIN))
{
int align = BF_MAX(vregInfo->mType->mAlign, 1);
BF_ASSERT(vregInfo->mAlign != -1);
int align = BF_MAX(vregInfo->mAlign, 1);
int alignOffset = regStackOffset + 8;
int alignedPosition = (mStackSize + alignOffset + (align - 1)) & ~(align - 1);
mStackSize = alignedPosition - alignOffset;
//vregInfo->mFrameOffset = -mStackSize - regStackOffset - 8;
mStackSize += BF_ALIGN(vregInfo->mType->mSize, vregInfo->mType->mAlign);
mStackSize += BF_ALIGN(vregInfo->mType->mSize, vregInfo->mAlign);
vregInfo->mFrameOffset = -mStackSize - regStackOffset;
}
}
@ -8893,6 +8891,7 @@ bool BeMCContext::DoLegalization()
auto relVRegInfo = mVRegInfo[relVRegIdx];
setInst->mKind = BeMCInstKind_MovSX;
relVRegInfo->mType = mModule->mContext->GetPrimitiveType(BeTypeCode_Int64);
relVRegInfo->mAlign = relVRegInfo->mType->mAlign;
if (debugging)
OutputDebugStrF(" Def MovSX\n");
isFinalRun = false;
@ -14693,7 +14692,7 @@ String BeMCContext::ToString(bool showVRegFlags, bool showVRegDetails)
{
str += " ";
str += ToString(BeMCOperand::FromVReg(vregIdx));
str += StrFormat(": size=%d, align=%d, at ", vregInfo->mType->mSize, vregInfo->mType->mAlign);
str += StrFormat(": size=%d, align=%d, at ", vregInfo->mType->mSize, vregInfo->mAlign);
X64CPURegister reg;
int offset;
@ -14840,7 +14839,9 @@ void BeMCContext::Generate(BeFunction* function)
mDbgPreferredRegs[32] = X64Reg_R8;*/
//mDbgPreferredRegs[8] = X64Reg_RAX;
//mDebugging = function->mName == "?DoResolveConfigString@IDEApp@IDE@bf@@QEAA_NPEAVString@System@3@PEAVOptions@Workspace@23@PEAVProject@23@PEAVOptions@823@UStringView@53@00@Z";
mDebugging = function->mName ==
//"?TestPrimitives@Nullable@Tests@bf@@SAXXZ"
"?TestAlloc@Blurg@bf@@SAXXZ";
//"?Main@Program@bf@@CAHPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z";
//"?Hey@Blurg@bf@@SAXXZ";
@ -14875,6 +14876,7 @@ void BeMCContext::Generate(BeFunction* function)
SizedArray<int, 64> stackSaveVRegs;
// Scan pass
mMaxCallParamCount = 4;
for (int blockIdx = 0; blockIdx < (int)function->mBlocks.size(); blockIdx++)
{
auto beBlock = function->mBlocks[blockIdx];
@ -14889,7 +14891,8 @@ void BeMCContext::Generate(BeFunction* function)
{
case BeAllocaInst::TypeId:
{
if (!inHeadAlloca)
auto castedInst = (BeAllocaInst*)inst;
if ((!inHeadAlloca) || (castedInst->mAlign > 16))
mUseBP = true;
}
break;
@ -14902,6 +14905,12 @@ void BeMCContext::Generate(BeFunction* function)
stackSaveVRegs.push_back(stackVReg.mVRegIdx);
}
break;
case BeCallInst::TypeId:
{
auto castedInst = (BeCallInst*)inst;
mMaxCallParamCount = BF_MAX(mMaxCallParamCount, (int)castedInst->mArgs.size());
}
break;
default:
inHeadAlloca = false;
break;
@ -15361,9 +15370,16 @@ void BeMCContext::Generate(BeFunction* function)
break;
case BeAllocaInst::TypeId:
{
if (mDebugging)
{
NOP;
}
int homeSize = BF_ALIGN(BF_MAX(mMaxCallParamCount, 4) * 8, 16);
auto castedInst = (BeAllocaInst*)inst;
auto mcSize = BeMCOperand::FromImmediate(castedInst->mType->mSize);
bool isAligned16 = false;
int align = castedInst->mAlign;
BeType* allocType = castedInst->mType;
bool preservedVolatiles = false;
bool doPtrCast = false;
@ -15395,10 +15411,12 @@ void BeMCContext::Generate(BeFunction* function)
}
}
if (inHeadAlloca)
// The stack is 16-byte aligned on entry - we have to manually adjust for any alignment greater than that
if ((inHeadAlloca) && (align <= 16))
{
result = AllocVirtualReg(allocType);
auto vregInfo = mVRegInfo[result.mVRegIdx];
vregInfo->mAlign = castedInst->mAlign;
vregInfo->mHasDynLife = true;
if (castedInst->mForceMem)
vregInfo->mForceMem = true;
@ -15416,6 +15434,7 @@ void BeMCContext::Generate(BeFunction* function)
vregInfo->mIsExpr = true;
vregInfo->mRelTo = result;
vregInfo->mType = resultType;
vregInfo->mAlign = resultType->mSize;
CreateDefineVReg(ptrResult);
result = ptrResult;
@ -15438,6 +15457,8 @@ void BeMCContext::Generate(BeFunction* function)
}
}
int stackAlign = BF_MAX(align, 16);
BeMCOperand mcFunc;
mcFunc.mKind = BeMCOperandKind_SymbolAddr;
mcFunc.mSymbolIdx = mCOFFObject->GetSymbolRef("__chkstk")->mIdx;
@ -15494,7 +15515,6 @@ void BeMCContext::Generate(BeFunction* function)
}
AllocInst(BeMCInstKind_Sub, BeMCOperand::FromReg(X64Reg_RSP), BeMCOperand::FromReg(X64Reg_RAX));
if (doFastChkStk)
{
AllocInst(BeMCInstKind_FastCheckStack, BeMCOperand::FromReg(X64Reg_RSP));
@ -15514,8 +15534,7 @@ void BeMCContext::Generate(BeFunction* function)
auto vregInfo = mVRegInfo[ptrValue.mVRegIdx];
vregInfo->mIsExpr = true;
vregInfo->mRelTo = BeMCOperand::FromReg(X64Reg_RSP);
vregInfo->mRelOffset = BeMCOperand::FromImmediate(-1);
mDeferredHomeSizeOffsets.Add(ptrValue.mVRegIdx);
vregInfo->mRelOffset = BeMCOperand::FromImmediate(homeSize);
CreateDefineVReg(ptrValue);
}
else
@ -15530,6 +15549,14 @@ void BeMCContext::Generate(BeFunction* function)
AllocInst(BeMCInstKind_Mov, result, ptrValue);
if (stackAlign > 16)
{
// We have to align after everything - note that we always have to keep the 'homeSize' space available from RSP for calls,
// so the ANDing for alignment must be done here
AllocInst(BeMCInstKind_And, result, BeMCOperand::FromImmediate(~(stackAlign - 1)));
AllocInst(BeMCInstKind_Sub, BeMCOperand::FromReg(X64Reg_RSP), BeMCOperand::FromImmediate(stackAlign - 16));
}
BF_ASSERT(mUseBP);
}
}
@ -16037,6 +16064,7 @@ void BeMCContext::Generate(BeFunction* function)
auto vregInfo = GetVRegInfo(castedTarget);
vregInfo->mMustExist = true;
vregInfo->mType = valType;
vregInfo->mAlign = valType->mAlign;
vregInfo->mIsExpr = true;
vregInfo->mRelTo = mcTarget;
CreateDefineVReg(castedTarget);

View file

@ -715,6 +715,7 @@ public:
X64CPURegister mReg;
X64CPURegister mNaturalReg; // From param
BeType* mType;
int mAlign;
int mFrameOffset; // 0 = 'RBP' (probably first local var or saved RBP), 8 means retAddr
bool mRegNumPinned;
bool mHasDynLife;
@ -756,6 +757,7 @@ public:
public:
BeMCVRegInfo()
{
mAlign = -1;
mRegNumPinned = false;
mReg = X64Reg_None;
mNaturalReg = X64Reg_None;
@ -1257,7 +1259,6 @@ public:
BeVTrackingList* mCurVRegsLive;
Array<int> mTextRelocs;
Array<BeMCSwitchEntry> mSwitchEntries;
Array<int> mDeferredHomeSizeOffsets;
Dictionary<int, X64CPURegister> mDbgPreferredRegs;

View file

@ -258,6 +258,9 @@ void BeInliner::Visit(BeAllocaInst* allocaInst)
auto destAllocInst = AllocInst(allocaInst);
destAllocInst->mType = allocaInst->mType;
destAllocInst->mArraySize = Remap(allocaInst->mArraySize);
destAllocInst->mAlign = allocaInst->mAlign;
destAllocInst->mNoChkStk = allocaInst->mNoChkStk;
destAllocInst->mForceMem = allocaInst->mForceMem;
}
void BeInliner::Visit(BeAliasValueInst* aliasValueInst)
@ -1525,7 +1528,9 @@ String BeDumpContext::ToString(BeDbgFunction* dbgFunction)
void BeDumpContext::ToString(StringImpl& str, int val)
{
str += StrFormat("%d", val);
char iStr[32];
sprintf(iStr, "%d", val);
str += iStr;
}
String BeDumpContext::ToString(int val)
@ -2146,6 +2151,8 @@ String BeModule::ToString(BeFunction* wantFunc)
str += ", ";
dc.ToString(str, castedInst->mArraySize);
}
str += ", align ";
dc.ToString(str, castedInst->mAlign);
}
break;
DISPLAY_INST1(BeAliasValueInst, "aliasvalue", mPtr);
@ -2672,6 +2679,9 @@ void BeModule::DoInlining(BeFunction* func)
auto destAlloca = mAlloc.Alloc<BeAllocaInst>();
destAlloca->mType = allocaInst->mType;
destAlloca->mArraySize = allocaInst->mArraySize;
destAlloca->mAlign = allocaInst->mAlign;
destAlloca->mNoChkStk = allocaInst->mNoChkStk;
destAlloca->mForceMem = allocaInst->mForceMem;
destAlloca->mName = allocaInst->mName;
auto destBlock = func->mBlocks[0];

View file

@ -811,6 +811,7 @@ public:
BeType* mType;
BeValue* mArraySize;
int mAlign;
bool mNoChkStk;
bool mForceMem;
@ -823,6 +824,7 @@ public:
mType->HashReference(hashCtx);
if (mArraySize != NULL)
mArraySize->HashReference(hashCtx);
hashCtx.Mixin(mAlign);
hashCtx.Mixin(mNoChkStk);
hashCtx.Mixin(mForceMem);
}

View file

@ -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;
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,7 +143,7 @@ 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);

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;
@ -9510,6 +9531,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
customAttribute.mType = attrTypeInst;
BfConstResolver constResolver(this);
if (allowNonConstArgs)
constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
bool inPropSet = false;
SizedArray<BfResolvedArg, 2> argValues;
@ -9775,6 +9798,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
// Move all those to the constHolder
for (auto& ctorArg : customAttribute.mCtorArgs)
{
if (ctorArg.IsConst())
CurrentAddToConstHolder(ctorArg);
}
@ -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());
@ -699,14 +728,19 @@ void BfPrinter::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);
ExpectSpace();
}
else
{
VisitChild(attributeDirective->mAttributeTargetSpecifier);
}
}
VisitChild(attributeDirective->mAttributeTypeRef);
VisitChild(attributeDirective->mCtorOpenParen);
@ -1227,12 +1261,6 @@ void BfPrinter::Visit(BfLambdaBindExpression* lambdaBindExpr)
VisitChild(lambdaBindExpr->mNewToken);
ExpectSpace();
if (lambdaBindExpr->mLambdaCapture != NULL)
{
VisitChild(lambdaBindExpr->mLambdaCapture->mOpenBracket);
VisitChild(lambdaBindExpr->mLambdaCapture->mCaptureToken);
VisitChild(lambdaBindExpr->mLambdaCapture->mCloseBracket);
}
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,15 +5116,31 @@ 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());
}
else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals))
{
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();
nextNode = mVisitorPos.GetNext();
}
}
}
if (!isHandled)
{
auto typeRef = CreateTypeRefAfter(attributeDirective);
if (typeRef == NULL)
{
@ -5140,6 +5158,8 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
return attributeDirective;
}
MEMBER_SET(attributeDirective, mAttributeTypeRef, typeRef);
}
tokenNode = ExpectTokenAfter(attributeDirective, BfToken_LParen, BfToken_RBracket, BfToken_Comma);
if (tokenNode == NULL)
return attributeDirective;
@ -5160,7 +5180,6 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
if (tokenNode == NULL)
return attributeDirective;
}
Do_RBracket:
if (tokenNode->GetToken() == BfToken_RBracket)
{
@ -5173,7 +5192,6 @@ Do_RBracket:
}
// Has another one- chain it
//mVisitorPos.MoveNext();
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))
{
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);
}
}
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))
{ //
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();
@ -7168,14 +7178,6 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
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,10 +7185,20 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
{
FailAfter("Expected allocator expression", 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_None,
BfCaptureType_Copy,
BfCaptureType_Reference,
BfCaptureType_Copy
};
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);