1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Comptime improvments, IOn<X> interfaces, const payload enum

This commit is contained in:
Brian Fiete 2022-02-11 05:47:32 -05:00
parent e7fe91facb
commit f37fb2c1b7
20 changed files with 884 additions and 364 deletions

View file

@ -181,8 +181,8 @@ namespace Beefy
}
int fileLen = (.)sr.Length;
if (sr.TryRead(.((.)outBuffer.PrepareBuffer(fileLen), fileLen)) case .Err(let readErr))
return .Err(.ReadError(readErr));
if (sr.TryRead(.((.)outBuffer.PrepareBuffer(fileLen), fileLen)) case .Err)
return .Err(.ReadError(.Unknown));
if (onPreFilter != null)
onPreFilter();

View file

@ -540,6 +540,26 @@ namespace System
}
}
interface IOnTypeInit
{
void OnTypeInit(Type type, Self* prev) mut;
}
interface IOnTypeDone
{
void OnTypeDone(Type type, Self* prev) mut;
}
interface IOnFieldInit
{
void OnFieldInit(ComptimeFieldInfo type, Self* prev) mut;
}
interface IOnMethodInit
{
void OnMethodInit(ComptimeMethodInfo type, Self* prev) mut;
}
interface IComptimeTypeApply
{
void ApplyToType(Type type);

View file

@ -44,8 +44,8 @@ namespace System.IO
if (bytes == 0)
return .Ok;
outData.AddRange(.(&buffer, bytes));
case .Err(let err):
return .Err(err);
case .Err:
return .Err(.Unknown);
}
}
}

View file

@ -150,4 +150,31 @@ namespace System.Reflection
}
}
}
[Ordered]
struct ComptimeFieldInfo
{
int64 mNativeFieldInstance;
TypeId mOwner;
TypeId mTypeId;
int32 mFieldIdx;
FieldFlags mFlags;
public StringView Name
{
get
{
if (Compiler.IsComptime)
return Type.[Friend]Comptime_Field_GetName(mNativeFieldInstance);
return "?";
}
}
public Type Owner => Type.[Friend]GetType_((.)mOwner);
public Type FieldType => Type.[Friend]GetType_((.)mTypeId);
public int FieldIdx => mFieldIdx;
public bool IsConst => mFlags.HasFlag(.Const);
public bool IsStatic => mFlags.HasFlag(.Static);
public bool IsInstanceField => !mFlags.HasFlag(.Static) && !mFlags.HasFlag(.Const);
}
}

View file

@ -159,6 +159,7 @@ namespace System
.Int16,
.Int32,
.Int64,
.Int,
.Float,
.Double:
return true;
@ -483,6 +484,15 @@ namespace System
}
}
public virtual int32 BitSize
{
[Error("This property can only be accessed directly from a typeof() expression")]
get
{
return 0;
}
}
public int32 GetTypeId()
{
return (int32)mTypeId;
@ -497,6 +507,7 @@ namespace System
static extern int64 Comptime_GetMethod(int32 typeId, int32 methodIdx);
static extern String Comptime_Method_ToString(int64 methodHandle);
static extern String Comptime_Method_GetName(int64 methodHandle);
static extern String Comptime_Field_GetName(int64 fieldHandle);
static extern ComptimeMethodInfo.Info Comptime_Method_GetInfo(int64 methodHandle);
static extern ComptimeMethodInfo.ParamInfo Comptime_Method_GetParamInfo(int64 methodHandle, int32 paramIdx);

View file

@ -1,3 +1,4 @@
using System.Reflection;
namespace System
{
public struct Attribute
@ -495,6 +496,26 @@ namespace System
}
}
interface IOnTypeInit
{
void OnTypeInit(Type type, Self* prev) mut;
}
interface IOnTypeDone
{
void OnTypeDone(Type type, Self* prev) mut;
}
interface IOnFieldInit
{
void OnFieldInit(ComptimeFieldInfo type, Self* prev) mut;
}
interface IOnMethodInit
{
void OnMethodInit(ComptimeMethodInfo type, Self* prev) mut;
}
interface IComptimeTypeApply
{
void ApplyToType(Type type);

View file

@ -327,4 +327,18 @@ namespace System.Reflection
}
}
}
struct ComptimeMethodInfo
{
public int64 mNativeMethodInstance;
}
struct ComptimeFieldInfo
{
int64 mNativeFieldInstance;
TypeId mOwner;
TypeId mTypeId;
int32 mFieldIdx;
FieldFlags mFlags;
}
}

View file

@ -430,6 +430,11 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mIHashableTypeDef = NULL;
mIComptimeTypeApply = NULL;
mIComptimeMethodApply = NULL;
mComptimeFieldInfoTypeDef = NULL;
mIOnTypeInitTypeDef = NULL;
mIOnTypeDoneTypeDef = NULL;
mIOnFieldInitTypeDef = NULL;
mIOnMethodInitTypeDef = NULL;
mLinkNameAttributeTypeDef = NULL;
mCallingConventionAttributeTypeDef = NULL;
mMethodRefTypeDef = NULL;
@ -5007,6 +5012,9 @@ void BfCompiler::GetSymbolReferences()
if ((fieldDef->mIsConst) && (fieldDef->mInitializer != NULL))
{
BfMethodState methodState;
methodState.mTempKind = BfMethodState::TempKind_Static;
SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, &methodState);
BfConstResolver constResolver(module);
constResolver.Resolve(fieldDef->mInitializer);
}
@ -6825,6 +6833,12 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mIHashableTypeDef = _GetRequiredType("System.IHashable");
mIComptimeTypeApply = _GetRequiredType("System.IComptimeTypeApply");
mIComptimeMethodApply = _GetRequiredType("System.IComptimeMethodApply");
mComptimeFieldInfoTypeDef = _GetRequiredType("System.Reflection.ComptimeFieldInfo");
mIOnTypeInitTypeDef = _GetRequiredType("System.IOnTypeInit");
mIOnTypeDoneTypeDef = _GetRequiredType("System.IOnTypeDone");
mIOnFieldInitTypeDef = _GetRequiredType("System.IOnFieldInit");
mIOnMethodInitTypeDef = _GetRequiredType("System.IOnMethodInit");
mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute");
mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);

View file

@ -390,6 +390,11 @@ public:
BfTypeDef* mIHashableTypeDef;
BfTypeDef* mIComptimeTypeApply;
BfTypeDef* mIComptimeMethodApply;
BfTypeDef* mComptimeFieldInfoTypeDef;
BfTypeDef* mIOnTypeInitTypeDef;
BfTypeDef* mIOnTypeDoneTypeDef;
BfTypeDef* mIOnFieldInitTypeDef;
BfTypeDef* mIOnMethodInitTypeDef;
BfTypeDef* mMethodRefTypeDef;
BfTypeDef* mNullableTypeDef;

View file

@ -1684,6 +1684,24 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds)
BfLogSysM("Deleting Type: %p %s\n", type, mScratchModule->TypeToString(type).c_str());
if (typeInst != NULL)
{
for (auto& methodInstGroup : typeInst->mMethodInstanceGroups)
{
if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mInCEMachine))
mCompiler->mCEMachine->RemoveMethod(methodInstGroup.mDefault);
if (methodInstGroup.mMethodSpecializationMap != NULL)
{
for (auto& methodSpecializationItr : *methodInstGroup.mMethodSpecializationMap)
{
auto methodInstance = methodSpecializationItr.mValue;
if (methodInstance->mInCEMachine)
mCompiler->mCEMachine->RemoveMethod(methodInstance);
}
}
}
}
// All dependencies cause rebuilds when we delete types
if (dType != NULL)
{

View file

@ -2296,26 +2296,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if (mModule->mCurMethodInstance != NULL)
allowSpecializeFail = mModule->mCurMethodInstance->mIsUnspecialized;
// if (mModule->mModuleName == "BeefTest_TestProgram")
// {
// OutputDebugStrF("?Prv: %s\n %s\n?New: %s\n %s\n\n",
// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None, &mBestMethodGenericArguments).c_str(),
// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None).c_str(),
// mModule->MethodToString(methodInstance, BfMethodNameFlag_None, genericArgumentsSubstitute).c_str(),
// mModule->MethodToString(methodInstance, BfMethodNameFlag_None).c_str());
// }
CompareMethods(prevMethodInstance, &mBestMethodGenericArguments, methodInstance, genericArgumentsSubstitute, &isBetter, &isWorse, allowSpecializeFail);
// if (mModule->mModuleName == "BeefTest_TestProgram")
// {
// OutputDebugStrF("%sPrv: %s\n %s\n%sNew: %s\n %s\n\n",
// isWorse ? "*" : " ", mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None, &mBestMethodGenericArguments).c_str(),
// mModule->MethodToString(prevMethodInstance, BfMethodNameFlag_None).c_str(),
// isBetter ? "*" : " ", mModule->MethodToString(methodInstance, BfMethodNameFlag_None, genericArgumentsSubstitute).c_str(),
// mModule->MethodToString(methodInstance, BfMethodNameFlag_None).c_str());
// }
// If we had both a 'better' and 'worse', that's ambiguous because the methods are each better in different ways (not allowed)
// And if neither better nor worse then they are equally good, which is not allowed either
if (((!isBetter) && (!isWorse)) || ((isBetter) && (isWorse)))
@ -7421,7 +7403,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
argValue = mModule->Cast(refNode, argValue, underlyingType);
}
else
argValue = mModule->Cast(refNode, argValue, underlyingType);
argValue = mModule->Cast(refNode, argValue, underlyingType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None);
if (argValue)
argValue = mModule->ToRef(argValue, (BfRefType*)wantType);
}
@ -7430,10 +7412,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (mModule->mCurMethodState != NULL)
{
SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData);
argValue = mModule->Cast(refNode, argValue, wantType);
argValue = mModule->Cast(refNode, argValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None);
}
else
argValue = mModule->Cast(refNode, argValue, wantType);
argValue = mModule->Cast(refNode, argValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) ? BfCastFlags_WantsConst : BfCastFlags_None);
}
if (!argValue)
@ -8145,10 +8127,8 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
constFailed = true;
continue;
}
if (argValue.IsValuelessType())
{
if (resolvedFieldType->IsValuelessType())
continue;
}
// Used receiving value?
if (argValue.mValue == receivingValue.mValue)
@ -8167,7 +8147,7 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
{
// argValue can have a value even if tuplePtr does not have a value. This can happen if we are assigning to a (void) tuple,
// but we have a value that needs to be attempted to be casted to void
argValue = mModule->Cast(argValues.mResolvedArgs[tupleFieldIdx].mExpression, argValue, resolvedFieldType);
argValue = mModule->Cast(argValues.mResolvedArgs[tupleFieldIdx].mExpression, argValue, resolvedFieldType, wantConst ? BfCastFlags_WantsConst : BfCastFlags_None);
if (wantConst)
{
if (!argValue.mValue.IsConst())
@ -10777,9 +10757,55 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
}
}
}
else if (memberName == "BitSize")
{
auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32);
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef);
return true;
}
if ((typeInstance != NULL) && (typeInstance->IsEnum()))
{
if (typeInstance->mTypeInfoEx != NULL)
{
int64 minValue = typeInstance->mTypeInfoEx->mMinValue;
if (minValue < 0)
minValue = ~minValue;
int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue;
if (maxValue < 0)
maxValue = ~maxValue;
uint64 value = (uint64)minValue | (uint64)maxValue;
int bitCount = 1;
if (typeInstance->mTypeInfoEx->mMinValue < 0)
bitCount++;
while (value >>= 1)
bitCount++;
mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type);
return true;
}
}
int bitSize = checkType->mSize * 8;
if (checkType->GetTypeCode() == BfTypeCode_Boolean)
bitSize = 1;
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type);
return true;
}
else if ((memberName == "MinValue") || (memberName == "MaxValue"))
{
bool isMin = memberName == "MinValue";
bool isBitSize = memberName == "BitSize";
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
@ -10833,6 +10859,7 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
{
if (typeInstance->mTypeInfoEx != NULL)
{
mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance);
return true;
}
@ -20693,7 +20720,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
else if (!CheckModifyResult(mResult, unaryOpExpr, "take address of", false, true))
{
if (!mResult.IsAddr())
mResult = mModule->MakeAddressable(mResult);
mResult = mModule->MakeAddressable(mResult, false, true);
mResult = BfTypedValue(mResult.mValue, ptrType, false);
}
else
@ -21409,7 +21436,9 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
mResult = BfTypedValue(alloca, allocType, true);
MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, false);
auto result = MatchConstructor(opToken, NULL, mResult, allocType, argValues, true, false);
if ((result) && (!result.mType->IsVoid()))
mResult = result;
return;
}

View file

@ -1001,6 +1001,15 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
return false;
}
if (typeInst->IsUnion())
{
auto innerType = typeInst->GetUnionInnerType();
if (!WriteConstant(aggConstant->mValues[1], (uint8*)ptr, innerType))
return false;
}
if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum()))
{
for (auto& fieldInstance : typeInst->mFieldInstances)
{
if (fieldInstance.mDataOffset < 0)
@ -1009,6 +1018,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
return false;
}
}
}
return true;
}
@ -1110,6 +1120,17 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
irValues.Add(val);
}
if (typeInst->IsUnion())
{
auto innerType = typeInst->GetUnionInnerType();
auto val = ReadConstant(ptr, innerType);
if (!val)
return BfIRValue();
irValues.Add(val);
}
if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum()))
{
for (auto& fieldInstance : typeInst->mFieldInstances)
{
if (fieldInstance.mDataOffset < 0)
@ -1119,6 +1140,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
return BfIRValue();
irValues.Add(val);
}
}
BfIRType irType;
irType.mKind = BfIRTypeData::TypeKind_TypeId;
irType.mId = type->mTypeId;
@ -1656,6 +1678,15 @@ String BfIRBuilder::ToString(BfIRValue irValue)
{
return ToString(constant->mIRType) + " zeroinitializer";
}
else if (constant->mConstType == BfConstType_AggCE)
{
auto constAgg = (BfConstantAggCE*)constant;
return ToString(constAgg->mType) + StrFormat(" aggCe@%p", constAgg->mCEAddr);
}
else if (constant->mConstType == BfConstType_ArrayZero8)
{
return StrFormat("zero8[%d]", constant->mInt32);
}
else if (constant->mConstType == BfConstType_TypeOf)
{
auto typeofConst = (BfTypeOf_Const*)constant;
@ -1666,6 +1697,7 @@ String BfIRBuilder::ToString(BfIRValue irValue)
auto typeofConst = (BfTypeOf_WithData_Const*)constant;
return "typeof_withData " + mModule->TypeToString(typeofConst->mType);
}
else
{
BF_FATAL("Unhandled");
@ -1783,7 +1815,15 @@ String BfIRBuilder::ToString(BfIRType irType)
}
else if (irType.mKind == BfIRTypeData::TypeKind_TypeId)
{
return StrFormat("Type Id %d (%s)", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str());
return StrFormat("Type#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str());
}
else if (irType.mKind == BfIRTypeData::TypeKind_TypeInstId)
{
return StrFormat("TypeInst#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str());
}
else if (irType.mKind == BfIRTypeData::TypeKind_TypeInstPtrId)
{
return StrFormat("TypeInstPtr#%d:%s", irType.mId, mModule->TypeToString(mModule->mContext->mTypes[irType.mId]).c_str());
}
else
{
@ -3940,7 +3980,7 @@ BfIRType BfIRBuilder::MapTypeInst(BfTypeInstance* typeInst, BfIRPopulateType pop
PopulateType(typeInst, populateType);
}
if (!mIgnoreWrites)
if ((!mIgnoreWrites) && (populateType != BfIRPopulateType_Identity))
BF_ASSERT(mTypeMap.ContainsKey(typeInst));
BfIRType retType;
retType.mKind = BfIRType::TypeKind_TypeInstId;

View file

@ -6479,18 +6479,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
SizedArray<BfIRValue, 16> fieldTypes;
enum FieldFlags
{
FieldFlags_Protected = 3,
FieldFlags_Public = 6,
FieldFlags_Static = 0x10,
FieldFlags_Const = 0x40,
FieldFlags_SpecialName = 0x80,
FieldFlags_EnumPayload = 0x100,
FieldFlags_EnumDiscriminator = 0x200,
FieldFlags_EnumCase = 0x400
};
bool is32Bit = mCompiler->mSystem->mPtrSize == 4;
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
@ -6509,7 +6497,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId
GetConstValue(0, intPtrType), // mData
GetConstValue(0, intPtrType), // mDataHi
GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags
GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags
GetConstValue(-1, intType), // mCustomAttributesIdx
};
}
@ -6521,7 +6509,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
payloadNameConst, // mName
GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId
GetConstValue(0, intPtrType), // mData
GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags
GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags
GetConstValue(-1, intType), // mCustomAttributesIdx
};
}
@ -6542,7 +6530,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId
GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData
GetConstValue(0, intPtrType), // mDataHi
GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags
GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags
GetConstValue(-1, intType), // mCustomAttributesIdx
};
}
@ -6554,7 +6542,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
dscrNameConst, // mName
GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId
GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData
GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags
GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags
GetConstValue(-1, intType), // mCustomAttributesIdx
};
}
@ -6581,18 +6569,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
else
typeId = fieldType->mTypeId;
FieldFlags fieldFlags = (FieldFlags)0;
BfFieldFlags fieldFlags = (BfFieldFlags)0;
if (fieldDef->mProtection == BfProtection_Protected)
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Protected);
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Protected);
if (fieldDef->mProtection == BfProtection_Public)
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Public);
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Public);
if (fieldDef->mIsStatic)
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Static);
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Static);
if (fieldDef->mIsConst)
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Const);
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Const);
if (fieldDef->IsEnumCaseEntry())
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_EnumCase);
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_EnumCase);
int customAttrIdx = _HandleCustomAttrs(fieldInstance->mCustomAttributes);
BfIRValue constValue;
@ -11329,6 +11317,18 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
newVals.Add(baseVal);
}
if (wantType->IsUnion())
{
auto innerType = wantType->ToTypeInstance()->GetUnionInnerType();
if (!innerType->IsValuelessType())
{
auto val = ConstantToCurrent(constHolder->GetConstant(constArray->mValues[1]), constHolder, innerType);
newVals.Add(val);
}
}
if ((!wantType->IsUnion()) || (wantType->IsPayloadEnum()))
{
for (auto& fieldInstance : wantTypeInst->mFieldInstances)
{
if (fieldInstance.mDataIdx < 0)
@ -11344,6 +11344,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
newVals[fieldInstance.mDataIdx] = memberVal;
}
}
}
for (auto& val : newVals)
{
@ -11743,6 +11744,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
}
BfMethodMatcher methodMatcher(attributesDirective, this, "", argValues, BfMethodGenericArguments());
methodMatcher.mBfEvalExprFlags = constResolver.mBfEvalExprFlags;
attrTypeDef = attrTypeInst->mTypeDef;
bool success = true;
@ -12969,6 +12971,7 @@ bool BfModule::IsCompatibleInterfaceMethod(BfMethodInstance* iMethodInst, BfMeth
if (iMethodInst->GetParamCount() != methodInstance->GetParamCount())
return false;
auto selfType = methodInstance->GetOwner();
for (int paramIdx = 0; paramIdx < (int)iMethodInst->GetParamCount(); paramIdx++)
{
if (iMethodInst->GetParamKind(paramIdx) != methodInstance->GetParamKind(paramIdx))
@ -12977,12 +12980,10 @@ bool BfModule::IsCompatibleInterfaceMethod(BfMethodInstance* iMethodInst, BfMeth
BfType* iParamType = iMethodInst->GetParamType(paramIdx);
BfType* methodParamType = methodInstance->GetParamType(paramIdx);
if (iParamType->IsSelf())
{
if (methodParamType != methodInstance->GetOwner())
return false;
}
else if (!iParamType->IsGenericParam())
iParamType = ResolveSelfType(iParamType, selfType);
methodParamType = ResolveSelfType(methodParamType, selfType);
if (!iParamType->IsGenericParam())
{
if (methodParamType != iParamType)
return false;
@ -13730,6 +13731,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
// We haven't processed it yet
_SetReified();
CheckHotMethod(methodInstance, "");
if (methodInstance->mMethodProcessRequest == NULL)
AddMethodToWorkList(methodInstance);
}
}
}
@ -24121,7 +24125,6 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
hadNameMatch = iMethodInst;
bool doesMethodSignatureMatch = CompareMethodSignatures(iMethodInst, methodInstance);
if ((!doesMethodSignatureMatch) && (iMethodInst->GetNumGenericParams() == 0) && (interfaceMethodEntry->mMethodRef.IsNull()))
{
doesMethodSignatureMatch = IsCompatibleInterfaceMethod(iMethodInst, methodInstance);

View file

@ -103,6 +103,7 @@ enum BfCastFlags
BfCastFlags_WarnOnBox = 0x800,
BfCastFlags_IsCastCheck = 0x1000,
BfCastFlags_IsConstraintCheck = 0x2000,
BfCastFlags_WantsConst = 0x4000
};
enum BfCastResultFlags
@ -1762,7 +1763,7 @@ public:
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred);
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary<BfTypeInstance*, BfIRValue>& foundAttributes, bool underlyingTypeDeferred);
void CEMixin(BfAstNode* refNode, const StringImpl& src);
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);

View file

@ -2139,27 +2139,49 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
}
}
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred)
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary<BfTypeInstance*, BfIRValue>& prevAttrInstances, bool underlyingTypeDeferred)
{
BfTypeInstance* iComptimeTypeApply = NULL;
for (auto& customAttribute : customAttributes->mAttributes)
{
auto attrType = customAttribute.mType;
mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods);
if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
continue;
for (auto& ifaceEntry : attrType->mInterfaces)
BfMethodInstance* methodInstance = NULL;
bool isFieldApply = false;
BfIRValue irValue;
int checkDepth = 0;
auto checkAttrType = attrType;
while (checkAttrType != NULL)
{
if (iComptimeTypeApply == NULL)
iComptimeTypeApply = ResolveTypeDef(mCompiler->mIComptimeTypeApply)->ToTypeInstance();
if (ifaceEntry.mInterfaceType != iComptimeTypeApply)
mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods);
if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
break;
for (auto& ifaceEntry : checkAttrType->mInterfaces)
{
isFieldApply = false;
isFieldApply = (ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnFieldInitTypeDef));
if ((isFieldApply) ||
((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeTypeApply))) ||
((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeInitTypeDef))) ||
((ceEmitContext == NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeDoneTypeDef))))
{
// Passes
}
else
continue;
if (!foundAttributes.Add(attrType))
continue;
prevAttrInstances.TryGetValue(checkAttrType, &irValue);
methodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
break;
}
if (methodInstance != NULL)
break;
checkAttrType = checkAttrType->mBaseType;
checkDepth++;
}
BfMethodInstance* methodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
if (methodInstance == NULL)
continue;
@ -2167,14 +2189,76 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
auto ceContext = mCompiler->mCEMachine->AllocContext();
BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0);
SizedArray<BfIRValue, 1> args;
if (!attrType->IsValuelessType())
args.Add(attrVal);
if (isFieldApply)
{
auto fieldDef = fieldInstance->GetFieldDef();
BfFieldFlags fieldFlags = (BfFieldFlags)0;
if (fieldDef->mProtection == BfProtection_Protected)
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Protected);
if (fieldDef->mProtection == BfProtection_Public)
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Public);
if (fieldDef->mIsStatic)
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Static);
if (fieldDef->mIsConst)
fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Const);
auto fieldInfoType = ResolveTypeDef(mCompiler->mComptimeFieldInfoTypeDef);
if (fieldInfoType != NULL)
{
SizedArray<BfIRValue, 9> fieldData =
{
mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity)),
GetConstValue((uint64)(intptr)fieldInstance, GetPrimitiveType(BfTypeCode_Int64)), // mNativeFieldInstance
GetConstValue(typeInstance->mTypeId, GetPrimitiveType(BfTypeCode_Int32)), // mOwner
GetConstValue((fieldInstance->mResolvedType != NULL) ? fieldInstance->mResolvedType->mTypeId : 0, GetPrimitiveType(BfTypeCode_Int32)), // mTypeId
GetConstValue(fieldDef->mIdx, GetPrimitiveType(BfTypeCode_Int32)), // mFieldIdx
GetConstValue((int)fieldFlags, GetPrimitiveType(BfTypeCode_Int16)), // mFieldFlags
};
FixConstValueParams(fieldInfoType->ToTypeInstance(), fieldData);
auto fieldDataAgg = mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity), fieldData);
args.Add(fieldDataAgg);
}
}
else
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
if (methodInstance->GetParamCount() > 1)
{
if (irValue)
args.Add(irValue);
else
args.Add(mBfIRBuilder->CreateConstNull());
}
else
{
// Only allow a single instance
if (irValue)
continue;
}
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
if (fieldInstance != NULL)
mCompiler->mCEMachine->mFieldInstanceSet.Add(fieldInstance);
BfTypedValue result;
///
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_ForceReturnThis, NULL);
}
if (fieldInstance != NULL)
mCompiler->mCEMachine->mFieldInstanceSet.Remove(fieldInstance);
if (result.mType == methodInstance->GetOwner())
prevAttrInstances[methodInstance->GetOwner()] = result.mValue;
if (ceEmitContext == NULL)
continue;
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
return;
@ -2217,7 +2301,9 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish))
{
String ctxStr = "comptime ApplyToType of ";
String ctxStr = "comptime ";
ctxStr += methodInstance->mMethodDef->mName;
ctxStr += " of ";
ctxStr += TypeToString(attrType);
ctxStr += " to ";
ctxStr += TypeToString(typeInstance);
@ -2230,7 +2316,6 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
mCompiler->mCEMachine->ReleaseContext(ceContext);
}
}
}
void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
{
@ -2306,16 +2391,17 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred)
{
HashSet<BfTypeInstance*> foundAttributes;
Dictionary<BfTypeInstance*, BfIRValue> prevAttrInstances;
if (typeInstance->mCustomAttributes != NULL)
HandleCEAttributes(ceEmitContext, typeInstance, NULL, typeInstance->mCustomAttributes, prevAttrInstances, underlyingTypeDeferred);
if (ceEmitContext != NULL)
{
if (typeInstance->mCustomAttributes != NULL)
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes, underlyingTypeDeferred);
for (auto& fieldInstance : typeInstance->mFieldInstances)
{
if (fieldInstance.mCustomAttributes != NULL)
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes, underlyingTypeDeferred);
HandleCEAttributes(ceEmitContext, typeInstance, &fieldInstance, fieldInstance.mCustomAttributes, prevAttrInstances, underlyingTypeDeferred);
}
}
@ -2357,7 +2443,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
if (onCompileAttribute == NULL)
continue;
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes, underlyingTypeDeferred);
HandleCEAttributes(ceEmitContext, typeInstance, NULL, customAttributes, prevAttrInstances, underlyingTypeDeferred);
if (onCompileAttribute->mCtorArgs.size() < 1)
continue;
@ -2478,25 +2564,41 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
CeEmitContext ceEmitContext;
ceEmitContext.mMethodInstance = methodInstance;
BfTypeInstance* iComptimeMethodApply = NULL;
Dictionary<BfTypeInstance*, BfIRValue> prevAttrInstances;
for (auto& customAttribute : customAttributes->mAttributes)
{
auto attrType = customAttribute.mType;
mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods);
if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
continue;
for (auto& ifaceEntry : attrType->mInterfaces)
BfMethodInstance* applyMethodInstance = NULL;
BfIRValue irValue;
int checkDepth = 0;
auto checkAttrType = attrType;
while (checkAttrType != NULL)
{
if (iComptimeMethodApply == NULL)
iComptimeMethodApply = ResolveTypeDef(mCompiler->mIComptimeMethodApply)->ToTypeInstance();
if (ifaceEntry.mInterfaceType != iComptimeMethodApply)
mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods);
if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
break;
for (auto& ifaceEntry : checkAttrType->mInterfaces)
{
if ((!ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeMethodApply)) &&
(!ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnMethodInitTypeDef)))
continue;
// if (!foundAttributes.Add(attrType))
// continue;
prevAttrInstances.TryGetValue(checkAttrType, &irValue);
applyMethodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
break;
}
if (applyMethodInstance != NULL)
break;
checkAttrType = checkAttrType->mBaseType;
checkDepth++;
}
BfMethodInstance* applyMethodInstance = attrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
if (applyMethodInstance == NULL)
continue;
@ -2504,11 +2606,27 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
auto ceContext = mCompiler->mCEMachine->AllocContext();
BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0);
SizedArray<BfIRValue, 1> args;
if (!attrType->IsValuelessType())
args.Add(attrVal);
args.Add(mBfIRBuilder->CreateConst(BfTypeCode_UInt64, (uint64)(intptr)methodInstance));
if (applyMethodInstance->GetParamCount() > 1)
{
if (irValue)
args.Add(irValue);
else
args.Add(mBfIRBuilder->CreateConstNull());
}
else
{
// Only allow a single instance
if (irValue)
continue;
}
mCompiler->mCEMachine->mMethodInstanceSet.Add(methodInstance);
//TESTING
@ -2516,8 +2634,18 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
// ceContext = mCompiler->mCEMachine->AllocContext();
// ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize;
auto activeTypeDef = typeInstance->mTypeDef;
auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL);
//auto result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_None, NULL);
BfTypedValue result;
///
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
result = ceContext->Call(customAttribute.mRef, this, applyMethodInstance, args, CeEvalFlags_ForceReturnThis, NULL);
}
if (result.mType == methodInstance->GetOwner())
prevAttrInstances[methodInstance->GetOwner()] = result.mValue;
if ((!result) && (mCompiler->mFastFinish))
{
@ -2586,7 +2714,6 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
mCompiler->mCEMachine->ReleaseContext(ceContext);
}
}
}
void BfModule::DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance)
{
@ -4183,15 +4310,46 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (!fieldInstance->mFieldIncluded)
continue;
if (fieldInstance->mCustomAttributes != NULL)
{
// Already handled
}
else if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
{
if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
{
// Handled elsewhere
}
else
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mCurFieldDef = fieldDef;
typeState.mCurTypeDef = fieldDef->mDeclaringType;
typeState.mType = typeInstance;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes)
{
if (TypeToString(customAttr.mType) == "System.ThreadStaticAttribute")
{
if ((!fieldDef->mIsStatic) || (fieldDef->mIsConst))
{
Fail("ThreadStatic attribute can only be used on static fields", fieldDef->mFieldDeclaration->mAttributes);
}
}
}
}
}
if (resolvedFieldType == NULL)
{
if ((underlyingType != NULL) || (typeInstance->IsPayloadEnum()))
continue;
}
if (!fieldInstance->mFieldIncluded)
continue;
if (fieldDef == NULL)
continue;
@ -4226,6 +4384,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
}
}
}
}
bool tryCE = true;
@ -4475,37 +4635,6 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
auto fieldDef = fieldInstance->GetFieldDef();
BF_ASSERT(fieldInstance->mCustomAttributes == NULL);
if ((fieldDef != NULL) && (fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
{
if (auto propDecl = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
{
// Handled elsewhere
}
else
{
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mCurFieldDef = fieldDef;
typeState.mCurTypeDef = fieldDef->mDeclaringType;
typeState.mType = typeInstance;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
fieldInstance->mCustomAttributes = GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mIsStatic ? BfAttributeTargets_StaticField : BfAttributeTargets_Field);
for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes)
{
if (TypeToString(customAttr.mType) == "System.ThreadStaticAttribute")
{
if ((!fieldDef->mIsStatic) || (fieldDef->mIsConst))
{
Fail("ThreadStatic attribute can only be used on static fields", fieldDef->mFieldDeclaration->mAttributes);
}
}
}
}
}
if (fieldInstance->mResolvedType != NULL)
{
auto resolvedFieldType = fieldInstance->GetResolvedType();
@ -12897,6 +13026,8 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
BfTypedValue result;
BfExprEvaluator exprEvaluator(this);
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp;
if ((castFlags & BfCastFlags_WantsConst) != 0)
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_Comptime);
auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodMatcher.mBestMethodDef->mMethodDeclaration);
if ((methodDeclaration != NULL) && (methodDeclaration->mBody == NULL))

View file

@ -1383,9 +1383,33 @@ public:
public:
BfFieldDef* GetFieldDef();
BfFieldInstance(BfFieldInstance&& copyFrom)
{
mCustomAttributes = copyFrom.mCustomAttributes;
copyFrom.mCustomAttributes = NULL;
mOwner = copyFrom.mOwner;
mResolvedType = copyFrom.mResolvedType;
mCustomAttributes = copyFrom.mCustomAttributes;
mConstIdx = copyFrom.mConstIdx;
mFieldIdx = copyFrom.mFieldIdx;
mDataIdx = copyFrom.mDataIdx;
mMergedDataIdx = copyFrom.mMergedDataIdx;
mDataOffset = copyFrom.mDataOffset;
mDataSize = copyFrom.mDataSize;
mFieldIncluded = copyFrom.mFieldIncluded;
mIsEnumPayloadCase = copyFrom.mIsEnumPayloadCase;
mIsThreadLocal = copyFrom.mIsThreadLocal;
mIsInferredType = copyFrom.mIsInferredType;
mHadConstEval = copyFrom.mHadConstEval;
mLastRevisionReferenced = copyFrom.mLastRevisionReferenced;
}
BfFieldInstance(const BfFieldInstance& copyFrom)
{
BF_ASSERT(copyFrom.mCustomAttributes == NULL);
mOwner = copyFrom.mOwner;
mResolvedType = copyFrom.mResolvedType;

View file

@ -2981,7 +2981,7 @@ BfTypedValue BfModule::HandleCaseBind(BfTypedValue enumVal, const BfTypedValue&
if (type->IsEnum())
{
auto enumType = (BfTypeInstance*)type;
for (auto fieldInstance : enumType->mFieldInstances)
for (auto& fieldInstance : enumType->mFieldInstances)
{
auto fieldDef = fieldInstance.GetFieldDef();
if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()) && (fieldDef->mName == findName))

View file

@ -1471,6 +1471,18 @@ enum BfOptionFlags
};
enum BfFieldFlags
{
BfFieldFlags_Protected = 3,
BfFieldFlags_Public = 6,
BfFieldFlags_Static = 0x10,
BfFieldFlags_Const = 0x40,
BfFieldFlags_SpecialName = 0x80,
BfFieldFlags_EnumPayload = 0x100,
BfFieldFlags_EnumDiscriminator = 0x200,
BfFieldFlags_EnumCase = 0x400
};
enum BfReflectKind
{
BfReflectKind_None = 0,

View file

@ -3376,7 +3376,7 @@ void CeContext::PrepareConstStructEntry(CeConstStructData& constEntry)
bool CeContext::CheckMemory(addr_ce addr, int32 size)
{
if (((addr)-0x10000) + (size) > (mMemory.mSize - 0x10000))
if ((addr < 0x10000) || (addr + size > mMemory.mSize))
return false;
return true;
}
@ -3441,10 +3441,12 @@ bool CeContext::GetStringFromStringView(addr_ce addr, StringImpl& str)
addr_ce charsPtr = *(addr_ce*)(mMemory.mVals + addr);
int32 len = *(int32*)(mMemory.mVals + addr + ptrSize);
if (len > 0)
{
if (!CheckMemory(charsPtr, len))
return false;
str.Append((const char*)(mMemory.mVals + charsPtr), len);
}
return true;
}
@ -3595,6 +3597,19 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
return false;
}
if (typeInst->IsPayloadEnum())
{
auto innerType = typeInst->GetUnionInnerType();
if (!innerType->IsValuelessType())
{
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[1]);
if (fieldConstant == NULL)
return false;
if (!WriteConstant(module, addr, fieldConstant, innerType))
return false;
}
}
for (auto& fieldInstance : typeInst->mFieldInstances)
{
if (fieldInstance.mDataOffset < 0)
@ -3617,6 +3632,12 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
return true;
}
if (constant->mConstType == BfConstType_ArrayZero8)
{
memset(mMemory.mVals + addr, 0, constant->mInt32);
return true;
}
if (constant->mConstType == BfConstType_Undef)
{
memset(mMemory.mVals + addr, 0, type->mSize);
@ -3722,6 +3743,29 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
return true;
}
if (constant->mConstType == BfConstType_ExtractValue)
{
Array<BfConstantExtractValue*> extractStack;
auto checkConstant = constant;
while (true)
{
if (checkConstant == NULL)
break;
if (checkConstant->mConstType == BfConstType_ExtractValue)
{
auto gepConst = (BfConstantExtractValue*)constant;
BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
checkConstant = module->mBfIRBuilder->GetConstant(targetConst);
extractStack.Add(gepConst);
continue;
}
if (checkConstant->mConstType == BfConstType_AggCE)
return WriteConstant(module, addr, checkConstant, type, isParams);
}
}
return false;
}
@ -3926,8 +3970,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
if (typeInst->IsInstanceOf(ceModule->mCompiler->mTypeTypeDef))
{
addr_ce addr = *(addr_ce*)(instData);
int typeId = GetTypeIdFromType(addr);
int typeId = GetTypeIdFromType(instData - mMemory.mVals);
if (typeId <= 0)
{
Fail("Unable to locate return type type");
@ -3951,12 +3994,19 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
fieldVals.Add(result);
}
if (typeInst->mIsUnion)
if (typeInst->IsUnion())
{
auto unionInnerType = typeInst->GetUnionInnerType();
fieldVals.Add(CreateConstant(module, ptr, unionInnerType, outType));
auto innerType = typeInst->GetUnionInnerType();
if (!innerType->IsValuelessType())
{
auto result = CreateConstant(module, instData, innerType);
if (!result)
return BfIRValue();
fieldVals.Add(result);
}
else
}
if ((!typeInst->IsUnion()) || (typeInst->IsPayloadEnum()))
{
for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.size(); fieldIdx++)
{
@ -3997,7 +4047,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
fieldVal = irBuilder->CreateConstArrayZero(0);
}
auto instResult = irBuilder->CreateConstAgg(irBuilder->MapTypeInst(typeInst, BfIRPopulateType_Full), fieldVals);
auto instResult = irBuilder->CreateConstAgg(irBuilder->MapTypeInst(typeInst, BfIRPopulateType_Identity), fieldVals);
return instResult;
}
@ -4156,14 +4206,30 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
int thisArgIdx = -1;
int appendAllocIdx = -1;
bool hasAggData = false;
if (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor)
if (!methodInstance->mMethodDef->mIsStatic)
{
if (!methodInstance->GetOwner()->IsValuelessType())
{
thisArgIdx = 0;
auto constant = module->mBfIRBuilder->GetConstant(args[0]);
if ((constant != NULL) && (constant->mConstType == BfConstType_AggCE))
auto checkConstant = module->mBfIRBuilder->GetConstant(args[0]);
while (checkConstant != NULL)
{
if ((checkConstant != NULL) && (checkConstant->mConstType == BfConstType_AggCE))
{
hasAggData = true;
break;
}
if (checkConstant->mConstType == BfConstType_ExtractValue)
{
auto gepConst = (BfConstantExtractValue*)checkConstant;
BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
checkConstant = module->mBfIRBuilder->GetConstant(targetConst);
continue;
}
break;
}
}
if ((methodInstance->GetParamCount() >= 1) && (methodInstance->GetParamKind(0) == BfParamKind_AppendIdx))
@ -4181,13 +4247,11 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
paramType = methodInstance->GetParamType(paramIdx);
if (paramType->IsTypedPrimitive())
paramType = paramType->GetUnderlyingType();
if (!paramType->IsValuelessType())
if ((!paramType->IsValuelessType()) && (!paramType->IsVar()))
break;
}
if (paramType->IsComposite())
{
paramCompositeSize += paramType->mSize;
}
BfType* compositeType = paramType->IsComposite() ? paramType : NULL;
auto arg = args[argIdx];
bool isConst = arg.IsConst();
@ -4203,6 +4267,17 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
// else
// isConst = false;
}
else if (((constant->mConstType == BfConstType_AggZero) || (constant->mConstType == BfConstType_Agg)) &&
((paramType->IsPointer()) || (paramType->IsRef())))
compositeType = paramType->GetUnderlyingType();
}
if (compositeType != NULL)
{
if ((paramType->IsPointer()) || (paramType->IsRef()))
paramCompositeSize += paramType->GetUnderlyingType()->mSize;
else
paramCompositeSize += paramType->mSize;
}
if (!isConst)
@ -4252,6 +4327,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
BfTypeInstance* thisType = methodInstance->GetOwner();
addr_ce allocThisInstAddr = 0;
addr_ce allocThisAddr = 0;
addr_ce thisAddr = 0;
int allocThisSize = -1;
if ((thisArgIdx != -1) && (!hasAggData))
@ -4294,6 +4370,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
allocThisInstAddr = allocThisPtr - memStart;
allocThisAddr = allocThisInstAddr;
thisAddr = allocThisAddr;
}
addr_ce allocAppendIdxAddr = 0;
@ -4327,7 +4404,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
paramType = methodInstance->GetParamType(paramIdx);
if (paramType->IsTypedPrimitive())
paramType = paramType->GetUnderlyingType();
if (!paramType->IsValuelessType())
if ((!paramType->IsValuelessType()) && (!paramType->IsVar()))
break;
}
@ -4357,10 +4434,14 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
}
auto constant = module->mBfIRBuilder->GetConstant(arg);
if (paramType->IsComposite())
BfType* compositeType = paramType->IsComposite() ? paramType : NULL;
if (((constant->mConstType == BfConstType_AggZero) || (constant->mConstType == BfConstType_Agg)) &&
((paramType->IsPointer()) || (paramType->IsRef())))
compositeType = paramType->GetUnderlyingType();
if (compositeType != NULL)
{
useCompositeAddr -= paramType->mSize;
if (!WriteConstant(module, useCompositeAddr, constant, paramType, isParams))
useCompositeAddr -= compositeType->mSize;
if (!WriteConstant(module, useCompositeAddr, constant, compositeType, isParams))
{
Fail(StrFormat("Failed to process argument for param '%s'", methodInstance->GetParamName(paramIdx).c_str()));
return BfTypedValue();
@ -4369,17 +4450,47 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
stackPtr -= ceModule->mSystem->mPtrSize;
int64 addr64 = useCompositeAddr;
if (argIdx == thisArgIdx)
thisAddr = addr64;
memcpy(stackPtr, &addr64, ceModule->mSystem->mPtrSize);
}
else
{
stackPtr -= paramType->mSize;
if (!WriteConstant(module, stackPtr - memStart, constant, paramType, isParams))
auto useCompositeAddr = stackPtr - memStart;
if (!WriteConstant(module, useCompositeAddr, constant, paramType, isParams))
{
Fail(StrFormat("Failed to process argument for param '%s'", methodInstance->GetParamName(paramIdx).c_str()));
return BfTypedValue();
}
_FixVariables();
if (argIdx == thisArgIdx)
{
auto checkConstant = constant;
while (checkConstant != NULL)
{
if ((checkConstant != NULL) && (checkConstant->mConstType == BfConstType_AggCE))
{
auto constAggData = (BfConstantAggCE*)checkConstant;
if (paramType->IsPointer())
thisAddr = constAggData->mCEAddr;
else
thisAddr = useCompositeAddr;
break;
}
if (checkConstant->mConstType == BfConstType_ExtractValue)
{
auto gepConst = (BfConstantExtractValue*)checkConstant;
BfIRValue targetConst(BfIRValueFlags_Const, gepConst->mTarget);
checkConstant = module->mBfIRBuilder->GetConstant(targetConst);
continue;
}
break;
}
}
}
}
@ -4399,16 +4510,18 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
addr_ce retInstAddr = retAddr;
if (returnType->IsInstanceOf(mCeMachine->mCompiler->mTypeTypeDef))
{
// Allow
}
else if ((returnType->IsObject()) || (returnType->IsPointer()))
if ((returnType->IsObject()) || (returnType->IsPointer()))
{
// Or pointer?
retInstAddr = *(addr_ce*)(memStart + retAddr);
}
if ((flags & CeEvalFlags_ForceReturnThis) != 0)
{
returnType = thisType;
retInstAddr = thisAddr;
}
BfTypedValue returnValue;
if (success)
@ -4452,7 +4565,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
}
else if (returnType->IsComposite())
{
returnValue = BfTypedValue(module->mBfIRBuilder->CreateConstArrayZero(module->mBfIRBuilder->MapType(returnType)), returnType);
returnValue = BfTypedValue(module->mBfIRBuilder->CreateConstAggZero(module->mBfIRBuilder->MapType(returnType, BfIRPopulateType_Identity)), returnType);
}
else if (returnType->IsValuelessType())
{
@ -4462,6 +4575,8 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
mCallStack.Clear();
moduleCurMethodInstance.Restore();
moduleCurTypeInstance.Restore();
module->AddDependency(methodInstance->GetOwner(), module->mCurTypeInstance, BfDependencyMap::DependencyFlag_ConstEval);
return returnValue;
@ -5014,6 +5129,20 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
*(int16*)(stackPtr + 4) = 0; // Flags
CeSetAddrVal(stackPtr + 4+2, stringAddr, ptrSize);
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Field_GetName)
{
int64 fieldHandle = *(int64*)((uint8*)stackPtr + ptrSize);
auto fieldInstance = mCeMachine->GetFieldInstance(fieldHandle);
if (fieldInstance == NULL)
{
_Fail("Invalid field instance");
return false;
}
CeSetAddrVal(stackPtr + 0, GetString(fieldInstance->GetFieldDef()->mName), ptrSize);
_FixVariables();
}
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitTypeBody)
{
int32 typeId = *(int32*)((uint8*)stackPtr);
@ -7506,6 +7635,12 @@ void CeMachine::DerefMethodInfo(CeFunctionInfo* ceFunctionInfo)
delete ceFunctionInfo;
}
void CeMachine::RemoveFunc(CeFunction* ceFunction)
{
mFunctionIdMap.Remove(ceFunction->mId);
ceFunction->mId = -1;
}
void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
{
BfLogSys(methodInstance->GetOwner()->mModule->mSystem, "CeMachine::RemoveMethod %p\n", methodInstance);
@ -7527,13 +7662,9 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
}
if (ceFunction->mId != -1)
{
mFunctionIdMap.Remove(ceFunction->mId);
ceFunction->mId = -1;
RemoveFunc(ceFunction);
for (auto innerFunction : ceFunction->mInnerFunctions)
{
mFunctionIdMap.Remove(innerFunction->mId);
innerFunction->mId = -1;
}
RemoveFunc(innerFunction);
}
delete ceFunction;
@ -7555,6 +7686,7 @@ void CeMachine::RemoveMethod(BfMethodInstance* methodInstance)
mFunctions.Remove(itr);
}
methodInstance->mInCEMachine = false;
}
CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext)
@ -7865,6 +7997,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
{
ceFunction->mFunctionKind = CeFunctionKind_Method_GetParamInfo;
}
else if (methodDef->mName == "Comptime_Field_GetName")
{
ceFunction->mFunctionKind = CeFunctionKind_Field_GetName;
}
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mCompilerTypeDef))
{
@ -8283,6 +8419,14 @@ BfMethodInstance* CeMachine::GetMethodInstance(int64 methodHandle)
return methodInstance;
}
BfFieldInstance* CeMachine::GetFieldInstance(int64 fieldHandle)
{
BfFieldInstance* fieldInstance = (BfFieldInstance*)(intptr)fieldHandle;
if (!mFieldInstanceSet.Contains(fieldInstance))
return NULL;
return fieldInstance;
}
CeFunction* CeMachine::QueueMethod(BfMethodInstance* methodInstance, BfIRValue func)
{
if (mPreparingFunction != NULL)

View file

@ -332,6 +332,7 @@ enum CeFunctionKind
CeFunctionKind_Method_GetName,
CeFunctionKind_Method_GetInfo,
CeFunctionKind_Method_GetParamInfo,
CeFunctionKind_Field_GetName,
CeFunctionKind_EmitTypeBody,
CeFunctionKind_EmitAddInterface,
@ -544,7 +545,8 @@ enum CeEvalFlags
CeEvalFlags_Cascade = 1,
CeEvalFlags_PersistantError = 2,
CeEvalFlags_DeferIfNotOnlyError = 4,
CeEvalFlags_NoRebuild = 8
CeEvalFlags_NoRebuild = 8,
CeEvalFlags_ForceReturnThis = 0x10
};
enum CeOperandKind
@ -927,6 +929,8 @@ public:
Dictionary<int, CeFunction*> mFunctionIdMap; // Only used for 32-bit
Dictionary<BfType*, CeTypeInfo> mTypeInfoMap;
HashSet<BfMethodInstance*> mMethodInstanceSet;
HashSet<BfFieldInstance*> mFieldInstanceSet;
Array<BeFunction*> mFunctionList;
Array<CeContext*> mContextList;
@ -957,6 +961,7 @@ public:
BeModule* GetBeModule();
void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
void RemoveFunc(CeFunction* ceFunction);
void RemoveMethod(BfMethodInstance* methodInstance);
void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);
CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal, CeContext* ceContext);
@ -970,6 +975,7 @@ public:
CeFunction* GetPreparedFunction(BfMethodInstance* methodInstance);
CeTypeInfo* GetTypeInfo(BfType* type);
BfMethodInstance* GetMethodInstance(int64 methodHandle);
BfFieldInstance* GetFieldInstance(int64 fieldHandle);
public:
void CompileStarted();