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

View file

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

View file

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

View file

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

View file

@ -2941,6 +2941,8 @@ BeMCOperand BeMCContext::CreateCall(const BeMCOperand& func, const SizedArrayImp
SizedArray<_ShadowReg, 8> shadowRegs; SizedArray<_ShadowReg, 8> shadowRegs;
BF_ASSERT(mMaxCallParamCount >= argCount);
mMaxCallParamCount = BF_MAX(mMaxCallParamCount, argCount); mMaxCallParamCount = BF_MAX(mMaxCallParamCount, argCount);
for (int argIdx = args.size() - 1; argIdx >= 0; argIdx--) 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(); int vregIdx = (int)mVRegInfo.size();
BeMCVRegInfo* vregInfo = mAlloc.Alloc<BeMCVRegInfo>(); BeMCVRegInfo* vregInfo = mAlloc.Alloc<BeMCVRegInfo>();
vregInfo->mType = type; vregInfo->mType = type;
vregInfo->mAlign = type->mAlign;
vregInfo->mRefCount = refCount; vregInfo->mRefCount = refCount;
vregInfo->mForceReg = mustBeReg; vregInfo->mForceReg = mustBeReg;
mVRegInfo.push_back(vregInfo); mVRegInfo.push_back(vregInfo);
@ -3661,7 +3664,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe
if (mDebugging) if (mDebugging)
{ {
if (mcOperand.mVRegIdx == 31) if (mcOperand.mVRegIdx == 3)
{ {
NOP; NOP;
} }
@ -7902,12 +7905,6 @@ void BeMCContext::DoFrameObjPass()
// we need for calls with more than 4 params. // we need for calls with more than 4 params.
// If we're doing UseBP, we have to allocate these at call time // If we're doing UseBP, we have to allocate these at call time
int homeSize = BF_ALIGN(BF_MAX(mMaxCallParamCount, 4) * 8, 16); 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; mStackSize = 0;
@ -7947,12 +7944,13 @@ void BeMCContext::DoFrameObjPass()
if ((vregInfo->mRefCount > 0) && (!vregInfo->mIsExpr) && (vregInfo->mReg == X64Reg_None) && (vregInfo->mFrameOffset == INT_MIN)) 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 alignOffset = regStackOffset + 8;
int alignedPosition = (mStackSize + alignOffset + (align - 1)) & ~(align - 1); int alignedPosition = (mStackSize + alignOffset + (align - 1)) & ~(align - 1);
mStackSize = alignedPosition - alignOffset; mStackSize = alignedPosition - alignOffset;
//vregInfo->mFrameOffset = -mStackSize - regStackOffset - 8; //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; vregInfo->mFrameOffset = -mStackSize - regStackOffset;
} }
} }
@ -8893,6 +8891,7 @@ bool BeMCContext::DoLegalization()
auto relVRegInfo = mVRegInfo[relVRegIdx]; auto relVRegInfo = mVRegInfo[relVRegIdx];
setInst->mKind = BeMCInstKind_MovSX; setInst->mKind = BeMCInstKind_MovSX;
relVRegInfo->mType = mModule->mContext->GetPrimitiveType(BeTypeCode_Int64); relVRegInfo->mType = mModule->mContext->GetPrimitiveType(BeTypeCode_Int64);
relVRegInfo->mAlign = relVRegInfo->mType->mAlign;
if (debugging) if (debugging)
OutputDebugStrF(" Def MovSX\n"); OutputDebugStrF(" Def MovSX\n");
isFinalRun = false; isFinalRun = false;
@ -14693,7 +14692,7 @@ String BeMCContext::ToString(bool showVRegFlags, bool showVRegDetails)
{ {
str += " "; str += " ";
str += ToString(BeMCOperand::FromVReg(vregIdx)); 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; X64CPURegister reg;
int offset; int offset;
@ -14840,7 +14839,9 @@ void BeMCContext::Generate(BeFunction* function)
mDbgPreferredRegs[32] = X64Reg_R8;*/ mDbgPreferredRegs[32] = X64Reg_R8;*/
//mDbgPreferredRegs[8] = X64Reg_RAX; //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"; //"?Main@Program@bf@@CAHPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z";
//"?Hey@Blurg@bf@@SAXXZ"; //"?Hey@Blurg@bf@@SAXXZ";
@ -14875,6 +14876,7 @@ void BeMCContext::Generate(BeFunction* function)
SizedArray<int, 64> stackSaveVRegs; SizedArray<int, 64> stackSaveVRegs;
// Scan pass // Scan pass
mMaxCallParamCount = 4;
for (int blockIdx = 0; blockIdx < (int)function->mBlocks.size(); blockIdx++) for (int blockIdx = 0; blockIdx < (int)function->mBlocks.size(); blockIdx++)
{ {
auto beBlock = function->mBlocks[blockIdx]; auto beBlock = function->mBlocks[blockIdx];
@ -14889,7 +14891,8 @@ void BeMCContext::Generate(BeFunction* function)
{ {
case BeAllocaInst::TypeId: case BeAllocaInst::TypeId:
{ {
if (!inHeadAlloca) auto castedInst = (BeAllocaInst*)inst;
if ((!inHeadAlloca) || (castedInst->mAlign > 16))
mUseBP = true; mUseBP = true;
} }
break; break;
@ -14902,6 +14905,12 @@ void BeMCContext::Generate(BeFunction* function)
stackSaveVRegs.push_back(stackVReg.mVRegIdx); stackSaveVRegs.push_back(stackVReg.mVRegIdx);
} }
break; break;
case BeCallInst::TypeId:
{
auto castedInst = (BeCallInst*)inst;
mMaxCallParamCount = BF_MAX(mMaxCallParamCount, (int)castedInst->mArgs.size());
}
break;
default: default:
inHeadAlloca = false; inHeadAlloca = false;
break; break;
@ -15361,9 +15370,16 @@ void BeMCContext::Generate(BeFunction* function)
break; break;
case BeAllocaInst::TypeId: case BeAllocaInst::TypeId:
{ {
if (mDebugging)
{
NOP;
}
int homeSize = BF_ALIGN(BF_MAX(mMaxCallParamCount, 4) * 8, 16);
auto castedInst = (BeAllocaInst*)inst; auto castedInst = (BeAllocaInst*)inst;
auto mcSize = BeMCOperand::FromImmediate(castedInst->mType->mSize); auto mcSize = BeMCOperand::FromImmediate(castedInst->mType->mSize);
bool isAligned16 = false; bool isAligned16 = false;
int align = castedInst->mAlign;
BeType* allocType = castedInst->mType; BeType* allocType = castedInst->mType;
bool preservedVolatiles = false; bool preservedVolatiles = false;
bool doPtrCast = 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); result = AllocVirtualReg(allocType);
auto vregInfo = mVRegInfo[result.mVRegIdx]; auto vregInfo = mVRegInfo[result.mVRegIdx];
vregInfo->mAlign = castedInst->mAlign;
vregInfo->mHasDynLife = true; vregInfo->mHasDynLife = true;
if (castedInst->mForceMem) if (castedInst->mForceMem)
vregInfo->mForceMem = true; vregInfo->mForceMem = true;
@ -15416,6 +15434,7 @@ void BeMCContext::Generate(BeFunction* function)
vregInfo->mIsExpr = true; vregInfo->mIsExpr = true;
vregInfo->mRelTo = result; vregInfo->mRelTo = result;
vregInfo->mType = resultType; vregInfo->mType = resultType;
vregInfo->mAlign = resultType->mSize;
CreateDefineVReg(ptrResult); CreateDefineVReg(ptrResult);
result = ptrResult; result = ptrResult;
@ -15438,6 +15457,8 @@ void BeMCContext::Generate(BeFunction* function)
} }
} }
int stackAlign = BF_MAX(align, 16);
BeMCOperand mcFunc; BeMCOperand mcFunc;
mcFunc.mKind = BeMCOperandKind_SymbolAddr; mcFunc.mKind = BeMCOperandKind_SymbolAddr;
mcFunc.mSymbolIdx = mCOFFObject->GetSymbolRef("__chkstk")->mIdx; 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)); AllocInst(BeMCInstKind_Sub, BeMCOperand::FromReg(X64Reg_RSP), BeMCOperand::FromReg(X64Reg_RAX));
if (doFastChkStk) if (doFastChkStk)
{ {
AllocInst(BeMCInstKind_FastCheckStack, BeMCOperand::FromReg(X64Reg_RSP)); AllocInst(BeMCInstKind_FastCheckStack, BeMCOperand::FromReg(X64Reg_RSP));
@ -15514,8 +15534,7 @@ void BeMCContext::Generate(BeFunction* function)
auto vregInfo = mVRegInfo[ptrValue.mVRegIdx]; auto vregInfo = mVRegInfo[ptrValue.mVRegIdx];
vregInfo->mIsExpr = true; vregInfo->mIsExpr = true;
vregInfo->mRelTo = BeMCOperand::FromReg(X64Reg_RSP); vregInfo->mRelTo = BeMCOperand::FromReg(X64Reg_RSP);
vregInfo->mRelOffset = BeMCOperand::FromImmediate(-1); vregInfo->mRelOffset = BeMCOperand::FromImmediate(homeSize);
mDeferredHomeSizeOffsets.Add(ptrValue.mVRegIdx);
CreateDefineVReg(ptrValue); CreateDefineVReg(ptrValue);
} }
else else
@ -15530,6 +15549,14 @@ void BeMCContext::Generate(BeFunction* function)
AllocInst(BeMCInstKind_Mov, result, ptrValue); 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); BF_ASSERT(mUseBP);
} }
} }
@ -16037,6 +16064,7 @@ void BeMCContext::Generate(BeFunction* function)
auto vregInfo = GetVRegInfo(castedTarget); auto vregInfo = GetVRegInfo(castedTarget);
vregInfo->mMustExist = true; vregInfo->mMustExist = true;
vregInfo->mType = valType; vregInfo->mType = valType;
vregInfo->mAlign = valType->mAlign;
vregInfo->mIsExpr = true; vregInfo->mIsExpr = true;
vregInfo->mRelTo = mcTarget; vregInfo->mRelTo = mcTarget;
CreateDefineVReg(castedTarget); CreateDefineVReg(castedTarget);

View file

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

View file

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

View file

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

View file

@ -956,6 +956,15 @@ void BfAstNode::ToString(StringImpl& str)
str.Append(source->mSrc + GetSrcStart(), srcLen); 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) void BfBlock::Init(const SizedArrayImpl<BfAstNode*>& vec, BfAstAllocator* alloc)

View file

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

View file

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

View file

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

View file

@ -143,7 +143,7 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
isConst = false; isConst = false;
} }
if (!isConst) if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0))
{ {
mModule->Fail("Expression does not evaluate to a constant value", expr); 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->mScopeToken);
VisitChild(scopeNode->mColonToken); VisitChild(scopeNode->mColonToken);
VisitChild(scopeNode->mTargetNode); VisitChild(scopeNode->mTargetNode);
VisitChild(scopeNode->mAttributes);
} }
void BfElementVisitor::Visit(BfNewNode* newNode) void BfElementVisitor::Visit(BfNewNode* newNode)
@ -141,6 +142,7 @@ void BfElementVisitor::Visit(BfNewNode* newNode)
VisitChild(newNode->mNewToken); VisitChild(newNode->mNewToken);
VisitChild(newNode->mColonToken); VisitChild(newNode->mColonToken);
VisitChild(newNode->mAllocNode); VisitChild(newNode->mAllocNode);
VisitChild(newNode->mAttributes);
} }
void BfElementVisitor::Visit(BfLabeledBlock* labeledBlock) void BfElementVisitor::Visit(BfLabeledBlock* labeledBlock)
@ -532,12 +534,6 @@ void BfElementVisitor::Visit(BfLambdaBindExpression* lambdaBindExpr)
Visit(lambdaBindExpr->ToBase()); Visit(lambdaBindExpr->ToBase());
VisitChild(lambdaBindExpr->mNewToken); VisitChild(lambdaBindExpr->mNewToken);
if (lambdaBindExpr->mLambdaCapture != NULL)
{
VisitChild(lambdaBindExpr->mLambdaCapture->mOpenBracket);
VisitChild(lambdaBindExpr->mLambdaCapture->mCaptureToken);
VisitChild(lambdaBindExpr->mLambdaCapture->mCloseBracket);
}
VisitChild(lambdaBindExpr->mOpenParen); VisitChild(lambdaBindExpr->mOpenParen);
VisitChild(lambdaBindExpr->mCloseParen); VisitChild(lambdaBindExpr->mCloseParen);

View file

@ -2818,6 +2818,11 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
varSkipCount--; varSkipCount--;
} }
if (varDecl->mNotCaptured)
{
mModule->Fail("Local variable is not captured", refNode);
}
if ((varSkipCount == 0) && (varDecl != NULL)) if ((varSkipCount == 0) && (varDecl != NULL))
{ {
if ((closureTypeInst != NULL) && (wantName == "this")) 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(); auto rootMethodState = mModule->mCurMethodState->GetRootMethodState();
BfLambdaInstance* lambdaInstance = NULL; BfLambdaInstance* lambdaInstance = NULL;
@ -9527,8 +9532,11 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
return NULL; 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) if (lambdaBindExpr->mDtor != NULL)
{ {
mModule->Fail("Valueless method reference cannot contain destructor. Consider either removing destructor or using an allocated lambda.", lambdaBindExpr->mDtor->mTildeToken); 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; 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(); BfClosureInstanceInfo* closureInstanceInfo = new BfClosureInstanceInfo();
auto checkInsertBlock = mModule->mBfIRBuilder->GetInsertBlock(); auto checkInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
@ -9704,6 +9795,9 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
VisitLambdaBodies(lambdaBindExpr->mBody, lambdaBindExpr->mDtor); 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 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)) if ((methodState.mPrevMethodState->mClosureState != NULL) && (methodState.mPrevMethodState->mClosureState->mCapturing))
{ {
@ -9731,18 +9825,27 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
prevIgnoreWrites.Restore(); prevIgnoreWrites.Restore();
mModule->mBfIRBuilder->RestoreDebugLocation(); mModule->mBfIRBuilder->RestoreDebugLocation();
BfCaptureType captureType = BfCaptureType_Value; auto _GetCaptureType = [&](const StringImpl& str)
if ((lambdaBindExpr->mLambdaCapture != NULL) && (lambdaBindExpr->mLambdaCapture->mCaptureToken != NULL))
{ {
if (lambdaBindExpr->mLambdaCapture->mCaptureToken->GetToken() == BfToken_Ampersand) if (allocTarget.mCaptureInfo.mCaptures.IsEmpty())
captureType = BfCaptureType_Reference; return BfCaptureType_Copy;
else
captureType = 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; Array<BfClosureCapturedEntry> capturedEntries;
bool copyOuterCaptures = false; bool copyOuterCaptures = false;
//
{ {
auto varMethodState = methodState.mPrevMethodState; auto varMethodState = methodState.mPrevMethodState;
@ -9771,6 +9874,11 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
auto capturedType = outerLocal->mResolvedType; auto capturedType = outerLocal->mResolvedType;
bool captureByRef = false; bool captureByRef = false;
auto captureType = _GetCaptureType(localVar->mName);
if (captureType == BfCaptureType_None)
{
continue;
}
if (!capturedType->IsRef()) 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) for (auto copyField : closureState.mReferencedOuterClosureMembers)
{ {
auto fieldDef = copyField->GetFieldDef(); auto fieldDef = copyField->GetFieldDef();
auto captureType = _GetCaptureType(fieldDef->mName);
BfClosureCapturedEntry capturedEntry; BfClosureCapturedEntry capturedEntry;
capturedEntry.mName = fieldDef->mName; capturedEntry.mName = fieldDef->mName;
capturedEntry.mType = copyField->mResolvedType; capturedEntry.mType = copyField->mResolvedType;
@ -10200,7 +10316,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr)
return; return;
} }
BfLambdaInstance* lambdaInstance = GetLambdaInstance(lambdaBindExpr); BfLambdaInstance* lambdaInstance = GetLambdaInstance(lambdaBindExpr, allocTarget);
if (lambdaInstance == NULL) if (lambdaInstance == NULL)
return; return;
BfTypeInstance* delegateTypeInstance = lambdaInstance->mDelegateTypeInstance; 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); arrayValue = BfTypedValue(mModule->AppendAllocFromType(resultType, BfIRValue(), 0, arraySize, (int)dimLengthVals.size(), isRawArrayAlloc, false), ptrType);
else 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); _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); arrayValue = BfTypedValue(mModule->AppendAllocFromType(resultType, BfIRValue(), 0, arraySize, (int)dimLengthVals.size(), isRawArrayAlloc, zeroMemory), arrayType);
else 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) if (isScopeAlloc)
{ {
@ -11538,6 +11654,7 @@ void BfExprEvaluator::Visit(BfBoxExpression* boxExpr)
BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenNode*& newToken) BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenNode*& newToken)
{ {
auto autoComplete = GetAutoComplete(); auto autoComplete = GetAutoComplete();
BfAttributeDirective* attributeDirective = NULL;
BfAllocTarget allocTarget; BfAllocTarget allocTarget;
allocTarget.mRefNode = allocNode; allocTarget.mRefNode = allocNode;
@ -11555,6 +11672,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
if ((scopeNode->mTargetNode == NULL) || (targetIdentifier != NULL)) if ((scopeNode->mTargetNode == NULL) || (targetIdentifier != NULL))
autoComplete->CheckLabel(targetIdentifier, scopeNode->mColonToken); autoComplete->CheckLabel(targetIdentifier, scopeNode->mColonToken);
} }
attributeDirective = scopeNode->mAttributes;
} }
if (auto newNode = BfNodeDynCast<BfNewNode>(allocNode)) if (auto newNode = BfNodeDynCast<BfNewNode>(allocNode))
{ {
@ -11568,6 +11686,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
{ {
allocTarget.mScopedInvocationTarget = scopedInvocationTarget; allocTarget.mScopedInvocationTarget = scopedInvocationTarget;
} }
attributeDirective = newNode->mAttributes;
} }
} }
else if (newToken->GetToken() == BfToken_Scope) else if (newToken->GetToken() == BfToken_Scope)
@ -11580,6 +11699,38 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
if (mModule->mCurMethodState != NULL) if (mModule->mCurMethodState != NULL)
allocTarget.mScopeData = &mModule->mCurMethodState->mHeadScope; 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; return allocTarget;
} }

View file

@ -378,7 +378,7 @@ public:
BfTypeInstance* VerifyBaseDelegateType(BfTypeInstance* delegateType); BfTypeInstance* VerifyBaseDelegateType(BfTypeInstance* delegateType);
void ConstResolve(BfExpression* expr); 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); 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 VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* fieldDtor);
void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic); void FixitAddMember(BfTypeInstance* typeInst, BfType* fieldType, const StringImpl& fieldName, bool isStatic);
void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken); void PerformUnaryOperation(BfExpression* unaryOpExpr, BfUnaryOp unaryOp, BfTokenNode* opToken);

View file

@ -7521,7 +7521,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
} }
if (!isDynAlloc) if (!isDynAlloc)
mBfIRBuilder->ClearDebugLocation(allocaInst); mBfIRBuilder->ClearDebugLocation(allocaInst);
mBfIRBuilder->SetAllocaAlignment(allocaInst, type->mAlign); mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
if (!isDynAlloc) if (!isDynAlloc)
mBfIRBuilder->SetInsertPoint(prevInsertBlock); mBfIRBuilder->SetInsertPoint(prevInsertBlock);
auto typedVal = BfTypedValue(result, type, BfTypedValueKind_Addr); 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); auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(byteType), sizeValue);
if (!isDynAlloc) if (!isDynAlloc)
mBfIRBuilder->ClearDebugLocation(allocaInst); mBfIRBuilder->ClearDebugLocation(allocaInst);
mBfIRBuilder->SetAllocaAlignment(allocaInst, arrayType->mAlign); mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
auto typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(arrayType)), arrayType); auto typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(arrayType)), arrayType);
mBfIRBuilder->ClearDebugLocation_Last(); mBfIRBuilder->ClearDebugLocation_Last();
if (!isDynAlloc) if (!isDynAlloc)
@ -9214,6 +9214,7 @@ static String GetAttributesTargetListString(BfAttributeTargets attrTarget)
AddAttributeTargetName(flagsLeft, BfAttributeTargets_GenericParameter, resultStr, "generic parameters"); AddAttributeTargetName(flagsLeft, BfAttributeTargets_GenericParameter, resultStr, "generic parameters");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Invocation, resultStr, "invocations"); AddAttributeTargetName(flagsLeft, BfAttributeTargets_Invocation, resultStr, "invocations");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_MemberAccess, resultStr, "member access"); AddAttributeTargetName(flagsLeft, BfAttributeTargets_MemberAccess, resultStr, "member access");
AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alloc, resultStr, "allocations");
if (resultStr.IsEmpty()) if (resultStr.IsEmpty())
return "<nothing>"; return "<nothing>";
return resultStr; 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) && if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) &&
(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != 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) 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); BfAutoParentNodeEntry autoParentNodeEntry(this, attributesDirective);
BfCustomAttribute customAttribute; BfCustomAttribute customAttribute;
@ -9510,6 +9531,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
customAttribute.mType = attrTypeInst; customAttribute.mType = attrTypeInst;
BfConstResolver constResolver(this); BfConstResolver constResolver(this);
if (allowNonConstArgs)
constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
bool inPropSet = false; bool inPropSet = false;
SizedArray<BfResolvedArg, 2> argValues; SizedArray<BfResolvedArg, 2> argValues;
@ -9775,7 +9798,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
// Move all those to the constHolder // Move all those to the constHolder
for (auto& ctorArg : customAttribute.mCtorArgs) for (auto& ctorArg : customAttribute.mCtorArgs)
{ {
CurrentAddToConstHolder(ctorArg); if (ctorArg.IsConst())
CurrentAddToConstHolder(ctorArg);
} }
if (attributesDirective->mAttributeTargetSpecifier != NULL) if (attributesDirective->mAttributeTargetSpecifier != NULL)
@ -9835,10 +9859,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
ValidateCustomAttributes(customAttributes, attrTarget); 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(); BfCustomAttributes* customAttributes = new BfCustomAttributes();
GetCustomAttributes(customAttributes, attributesDirective, attrType); GetCustomAttributes(customAttributes, attributesDirective, attrType, allowNonConstArgs, captureInfo);
return customAttributes; return customAttributes;
} }

View file

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

View file

@ -588,6 +588,35 @@ void BfPrinter::Visit(BfErrorNode* errorNode)
VisitChild(errorNode->mRefNode); 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) void BfPrinter::Visit(BfExpression* expr)
{ {
Visit(expr->ToBase()); Visit(expr->ToBase());
@ -699,13 +728,18 @@ void BfPrinter::Visit(BfAttributeDirective* attributeDirective)
} }
} }
if (attributeDirective->mAttributeTargetSpecifier != NULL) if (attributeDirective->mAttributeTargetSpecifier != NULL)
{ {
VisitChild(attributeDirective->mAttributeTargetSpecifier->mTargetToken); if (auto attributeTargetSpecifier = BfNodeDynCast<BfAttributeTargetSpecifier>(attributeDirective->mAttributeTargetSpecifier))
VisitChild(attributeDirective->mAttributeTargetSpecifier->mColonToken); {
ExpectSpace(); VisitChild(attributeTargetSpecifier->mTargetToken);
VisitChild(attributeTargetSpecifier->mColonToken);
ExpectSpace();
}
else
{
VisitChild(attributeDirective->mAttributeTargetSpecifier);
}
} }
VisitChild(attributeDirective->mAttributeTypeRef); VisitChild(attributeDirective->mAttributeTypeRef);
@ -1227,12 +1261,6 @@ void BfPrinter::Visit(BfLambdaBindExpression* lambdaBindExpr)
VisitChild(lambdaBindExpr->mNewToken); VisitChild(lambdaBindExpr->mNewToken);
ExpectSpace(); ExpectSpace();
if (lambdaBindExpr->mLambdaCapture != NULL)
{
VisitChild(lambdaBindExpr->mLambdaCapture->mOpenBracket);
VisitChild(lambdaBindExpr->mLambdaCapture->mCaptureToken);
VisitChild(lambdaBindExpr->mLambdaCapture->mCloseBracket);
}
VisitChild(lambdaBindExpr->mOpenParen); VisitChild(lambdaBindExpr->mOpenParen);
for (int i = 0; i < (int)lambdaBindExpr->mParams.size(); i++) 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(BfAstNode* bfAstNode) override;
virtual void Visit(BfErrorNode* bfErrorNode) 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(BfExpression* expr) override;
virtual void Visit(BfExpressionStatement* exprStmt) override; virtual void Visit(BfExpressionStatement* exprStmt) override;
virtual void Visit(BfAttributedExpression* attribExpr) override; virtual void Visit(BfAttributedExpression* attribExpr) override;

View file

@ -5105,6 +5105,8 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
ReplaceNode(startToken, attributeDirective); ReplaceNode(startToken, attributeDirective);
attributeDirective->mAttrOpenToken = startToken; attributeDirective->mAttrOpenToken = startToken;
bool isHandled = false;
auto nextNode = mVisitorPos.GetNext(); auto nextNode = mVisitorPos.GetNext();
auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode); auto tokenNode = BfNodeDynCast<BfTokenNode>(nextNode);
if (tokenNode != NULL) if (tokenNode != NULL)
@ -5114,32 +5116,50 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
auto attributeTargetSpecifier = mAlloc->Alloc<BfAttributeTargetSpecifier>(); auto attributeTargetSpecifier = mAlloc->Alloc<BfAttributeTargetSpecifier>();
ReplaceNode(tokenNode, attributeTargetSpecifier); ReplaceNode(tokenNode, attributeTargetSpecifier);
MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, attributeTargetSpecifier); MEMBER_SET(attributeDirective, mAttributeTargetSpecifier, attributeTargetSpecifier);
attributeDirective->mAttributeTargetSpecifier->mTargetToken = tokenNode; attributeTargetSpecifier->mTargetToken = tokenNode;
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
tokenNode = ExpectTokenAfter(attributeDirective, BfToken_Colon); tokenNode = ExpectTokenAfter(attributeDirective, BfToken_Colon);
if (tokenNode != NULL) if (tokenNode != NULL)
MEMBER_SET(attributeDirective->mAttributeTargetSpecifier, mColonToken, tokenNode); MEMBER_SET(attributeTargetSpecifier, mColonToken, tokenNode);
attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd()); attributeDirective->SetSrcEnd(attributeDirective->mAttributeTargetSpecifier->GetSrcEnd());
} }
} else if ((tokenNode->mToken == BfToken_Ampersand) || (tokenNode->mToken == BfToken_AssignEquals))
auto typeRef = CreateTypeRefAfter(attributeDirective);
if (typeRef == NULL)
{
auto nextNode = mVisitorPos.GetNext();
if (BfTokenNode* endToken = BfNodeDynCast<BfTokenNode>(nextNode))
{ {
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(); mVisitorPos.MoveNext();
MEMBER_SET(attributeDirective, mCtorCloseParen, endToken); nextNode = mVisitorPos.GetNext();
return attributeDirective;
} }
} }
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); tokenNode = ExpectTokenAfter(attributeDirective, BfToken_LParen, BfToken_RBracket, BfToken_Comma);
if (tokenNode == NULL) if (tokenNode == NULL)
return attributeDirective; return attributeDirective;
@ -5160,7 +5180,6 @@ BfAttributeDirective* BfReducer::CreateAttributeDirective(BfTokenNode* startToke
if (tokenNode == NULL) if (tokenNode == NULL)
return attributeDirective; return attributeDirective;
} }
Do_RBracket: Do_RBracket:
if (tokenNode->GetToken() == BfToken_RBracket) if (tokenNode->GetToken() == BfToken_RBracket)
{ {
@ -5173,7 +5192,6 @@ Do_RBracket:
} }
// Has another one- chain it // Has another one- chain it
//mVisitorPos.MoveNext();
auto nextAttribute = CreateAttributeDirective(tokenNode); auto nextAttribute = CreateAttributeDirective(tokenNode);
if (nextAttribute != NULL) if (nextAttribute != NULL)
{ {
@ -6810,41 +6828,10 @@ BfLambdaBindExpression* BfReducer::CreateLambdaBindExpression(BfAstNode* allocNo
ReplaceNode(parenToken, lambdaBindExpr); ReplaceNode(parenToken, lambdaBindExpr);
tokenNode = parenToken; tokenNode = parenToken;
} }
//auto tokenNode = ExpectTokenAfter(lambdaBindExpr, BfToken_LParen, BfToken_LBracket);
if (tokenNode == NULL) if (tokenNode == NULL)
return lambdaBindExpr; 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); MEMBER_SET_CHECKED(lambdaBindExpr, mOpenParen, tokenNode);
for (int paramIdx = 0; true; paramIdx++) for (int paramIdx = 0; true; paramIdx++)
@ -7051,11 +7038,17 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
if (allocToken->GetToken() == BfToken_Scope) if (allocToken->GetToken() == BfToken_Scope)
{ {
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()); 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)
{ {
auto scopeNode = mAlloc->Alloc<BfScopeNode>();
ReplaceNode(allocToken, scopeNode);
scopeNode->mScopeToken = allocToken;
MEMBER_SET(scopeNode, mColonToken, nextToken); MEMBER_SET(scopeNode, mColonToken, nextToken);
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
@ -7077,19 +7070,36 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
{ {
FailAfter("Expected scope name", scopeNode); 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) if (allocToken->GetToken() == BfToken_New)
{// {
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext()); auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
if ((nextToken != NULL) && (nextToken->GetToken() == BfToken_Colon))
{ // if (nextToken == NULL)
auto newNode = mAlloc->Alloc<BfNewNode>(); return allocToken;
ReplaceNode(allocToken, newNode); if ((nextToken->mToken != BfToken_Colon) && (nextToken->mToken != BfToken_LBracket))
newNode->mNewToken = allocToken; return allocToken;
auto newNode = mAlloc->Alloc<BfNewNode>();
ReplaceNode(allocToken, newNode);
newNode->mNewToken = allocToken;
if (nextToken->mToken == BfToken_Colon)
{
MEMBER_SET(newNode, mColonToken, nextToken); MEMBER_SET(newNode, mColonToken, nextToken);
mVisitorPos.MoveNext(); mVisitorPos.MoveNext();
@ -7168,14 +7178,6 @@ BfAstNode* BfReducer::CreateAllocNode(BfTokenNode* allocToken)
mVisitorPos.MoveNext(); 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); 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; return allocToken;

View file

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

View file

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