mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Comptime can now run on unspecialized code
This commit is contained in:
parent
a4a5d99fd0
commit
4e18517c03
13 changed files with 289 additions and 155 deletions
|
@ -381,7 +381,15 @@ namespace System
|
|||
{
|
||||
get
|
||||
{
|
||||
return (mTypeFlags & (TypeFlags.SpecializedGeneric | TypeFlags.UnspecializedGeneric)) != 0;
|
||||
return (mTypeFlags & (.SpecializedGeneric | .UnspecializedGeneric)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGenericParam
|
||||
{
|
||||
get
|
||||
{
|
||||
return (mTypeFlags & .GenericParam) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,6 +649,8 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum TypeCode : uint8
|
||||
{
|
||||
None,
|
||||
|
@ -1298,6 +1308,7 @@ namespace System.Reflection
|
|||
Delegate = 0x20000,
|
||||
Function = 0x40000,
|
||||
HasDestructor = 0x80000,
|
||||
GenericParam = 0x100000,
|
||||
}
|
||||
|
||||
public enum FieldFlags : uint16
|
||||
|
|
|
@ -1094,13 +1094,25 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
|
||||
if (typeInst->mTypeDef->mEmitParent != NULL)
|
||||
{
|
||||
auto emitTypeDef = typeInst->mTypeDef;
|
||||
auto emitTypeDef = typeInst->mTypeDef;
|
||||
typeInst->mTypeDef = emitTypeDef->mEmitParent;
|
||||
BfLogSysM("Type %p queueing delete of typeDef %p, resetting typeDef to %p\n", typeInst, emitTypeDef, typeInst->mTypeDef);
|
||||
emitTypeDef->mDefState = BfTypeDef::DefState_Deleted;
|
||||
AutoCrit autoCrit(mSystem->mDataLock);
|
||||
BF_ASSERT(!mSystem->mTypeDefDeleteQueue.Contains(emitTypeDef));
|
||||
mSystem->mTypeDefDeleteQueue.push_back(emitTypeDef);
|
||||
if (emitTypeDef->mDefState != BfTypeDef::DefState_Deleted)
|
||||
{
|
||||
emitTypeDef->mDefState = BfTypeDef::DefState_Deleted;
|
||||
AutoCrit autoCrit(mSystem->mDataLock);
|
||||
BF_ASSERT(!mSystem->mTypeDefDeleteQueue.Contains(emitTypeDef));
|
||||
mSystem->mTypeDefDeleteQueue.push_back(emitTypeDef);
|
||||
|
||||
for (auto& dep : typeInst->mDependencyMap)
|
||||
{
|
||||
if (auto typeInst = dep.mKey->ToTypeInstance())
|
||||
{
|
||||
if (typeInst->mTypeDef == emitTypeDef)
|
||||
RebuildType(typeInst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//typeInst->mTypeDef->ClearEmitted();
|
||||
|
|
|
@ -2664,7 +2664,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
|
|||
if ((mModule->mCompiler->IsAutocomplete()) || (mModule->mContext->mResolvingVarField))
|
||||
return;
|
||||
|
||||
if ((mModule->mBfIRBuilder->mIgnoreWrites) && (!mBestMethodDef->mIsConcrete))
|
||||
if ((mModule->mBfIRBuilder->mIgnoreWrites) && (!mBestMethodDef->mIsConcrete) && (!mBestMethodTypeInstance->IsInterface()))
|
||||
return;
|
||||
|
||||
if (mBestMethodTypeInstance->IsInterface())
|
||||
|
@ -3443,7 +3443,7 @@ void BfExprEvaluator::Visit(BfCaseExpression* caseExpr)
|
|||
|
||||
}
|
||||
|
||||
if ((caseValAddr) && (caseValAddr.mType->IsVar()))
|
||||
if ((caseValAddr) && (IsVar(caseValAddr.mType)))
|
||||
{
|
||||
auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(caseExpr->mCaseExpression);
|
||||
if (invocationExpr != NULL)
|
||||
|
@ -3519,6 +3519,18 @@ static bool IsCharType(BfTypeCode typeCode)
|
|||
}
|
||||
}
|
||||
|
||||
bool BfExprEvaluator::IsVar(BfType* type)
|
||||
{
|
||||
if (type->IsVar())
|
||||
return true;
|
||||
if ((type->IsGenericParam()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||
{
|
||||
BF_ASSERT(mModule->mIsComptimeModule);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
|
||||
{
|
||||
switch (variant.mTypeCode)
|
||||
|
@ -4298,7 +4310,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
}
|
||||
}
|
||||
|
||||
if ((target.mType != NULL) && (target.mType->IsVar()))
|
||||
if ((target.mType != NULL) && (IsVar(target.mType)))
|
||||
return BfTypedValue(mModule->GetDefaultValue(target.mType), target.mType, true);
|
||||
|
||||
BfTypeInstance* startCheckType = mModule->mCurTypeInstance;
|
||||
|
@ -4496,7 +4508,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
mResultFieldInstance = fieldInstance;
|
||||
|
||||
// Are we accessing a 'var' field that has not yet been resolved?
|
||||
if (fieldInstance->mResolvedType->IsVar())
|
||||
if (IsVar(fieldInstance->mResolvedType))
|
||||
{
|
||||
// This can happen if we have one var field referencing another var field
|
||||
fieldInstance->mResolvedType = mModule->ResolveVarFieldType(curCheckType, fieldInstance, field);
|
||||
|
@ -5779,7 +5791,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
{
|
||||
// We're attempting to directly invoke a non-virtual interface method, this will happen during the unspecialized pass
|
||||
// OR if we had an error and didn't find an implementing member in the actual target
|
||||
if (!mModule->mCurMethodInstance->mIsUnspecialized)
|
||||
if ((!mModule->mCurMethodInstance->mIsUnspecialized) && (!mModule->mCurTypeInstance->IsInterface()))
|
||||
mModule->AssertErrorState();
|
||||
|
||||
if (returnType->IsInterface())
|
||||
|
@ -5814,7 +5826,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
return BfTypedValue();
|
||||
}
|
||||
|
||||
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized))
|
||||
if (((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized)) && (mModule->mBfIRBuilder->mIgnoreWrites))
|
||||
{
|
||||
// Don't actually do the call - our target may be a generic param
|
||||
return _GetDefaultReturnValue();
|
||||
|
@ -6248,7 +6260,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
|
|||
{
|
||||
MakeBaseConcrete(argVal);
|
||||
|
||||
if (argVal.mType->IsVar())
|
||||
if (IsVar(argVal.mType))
|
||||
{
|
||||
argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
|
||||
}
|
||||
|
@ -6774,9 +6786,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
}
|
||||
|
||||
wantType = methodInstance->GetParamType(paramIdx);
|
||||
if (wantType->IsSelf())
|
||||
wantType = methodInstance->GetOwner();
|
||||
if (wantType->IsVar())
|
||||
if (!mModule->mCurTypeInstance->IsInterface())
|
||||
{
|
||||
// Resolve `Self` types
|
||||
if (wantType->IsUnspecializedTypeVariation())
|
||||
wantType = mModule->ResolveGenericType(wantType, NULL, NULL);
|
||||
}
|
||||
|
||||
if (IsVar(wantType))
|
||||
{
|
||||
// Case happens when we can't find the argument type
|
||||
failed = true;
|
||||
|
@ -8109,7 +8126,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
}
|
||||
}
|
||||
|
||||
if ((!target.mType->IsGenericParam()) && (!target.IsSplat()) && (!target.mType->IsVar()))
|
||||
if ((!target.mType->IsGenericParam()) && (!target.IsSplat()) && (!IsVar(target.mType)))
|
||||
target = MakeCallableTarget(targetSrc, target);
|
||||
}
|
||||
|
||||
|
@ -8181,7 +8198,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (target.mType->IsVar())
|
||||
else if (IsVar(target.mType))
|
||||
isUnboundCall = true;
|
||||
}
|
||||
|
||||
|
@ -8238,12 +8255,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
bool wantsExtensionCheck = target;
|
||||
auto targetType = target.mType;
|
||||
BfTypeDef* curTypeDef = NULL;
|
||||
BfType* selfType = NULL;
|
||||
BfTypeInstance* targetTypeInst = NULL;
|
||||
bool checkNonStatic = true;
|
||||
|
||||
if (target)
|
||||
{
|
||||
if (targetType->IsVar())
|
||||
if (IsVar(targetType))
|
||||
return mModule->GetDefaultTypedValue(targetType);
|
||||
targetTypeInst = targetType->ToTypeInstance();
|
||||
if (targetTypeInst != NULL)
|
||||
|
@ -8312,6 +8330,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
curTypeDef = targetTypeInst->mTypeDef;
|
||||
checkNonStatic = true;
|
||||
target = mModule->GetThis();
|
||||
selfType = mModule->mCurTypeInstance;
|
||||
//target.mType = targetTypeInst;
|
||||
}
|
||||
else
|
||||
|
@ -8529,7 +8548,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
}
|
||||
|
||||
BfTypedValue staticResult;
|
||||
methodMatcher.TryDevirtualizeCall(target, &origTarget, &staticResult);
|
||||
//
|
||||
{
|
||||
auto devirtTarget = target;
|
||||
if ((devirtTarget.mType == NULL) && (selfType != NULL))
|
||||
devirtTarget.mType = selfType;
|
||||
methodMatcher.TryDevirtualizeCall(devirtTarget, &origTarget, &staticResult);
|
||||
}
|
||||
if (staticResult)
|
||||
return staticResult;
|
||||
bypassVirtual |= methodMatcher.mBypassVirtual;
|
||||
|
@ -8873,7 +8898,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
}
|
||||
return MatchMethod(targetSrc, NULL, fieldVal, false, false, "Invoke", argValues, methodGenericArguments, checkedKind);
|
||||
}
|
||||
if (fieldVal.mType->IsVar())
|
||||
if (IsVar(fieldVal.mType))
|
||||
{
|
||||
FinishDeferredEvals(argValues);
|
||||
return BfTypedValue(mModule->GetDefaultValue(fieldVal.mType), fieldVal.mType);
|
||||
|
@ -9456,17 +9481,27 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
|
||||
if (result)
|
||||
{
|
||||
if (result.mType->IsSelf())
|
||||
if ((result.mType->IsUnspecializedTypeVariation()) && (moduleMethodInstance.mMethodInstance->GetOwner()->IsInterface()))
|
||||
{
|
||||
BfType* selfType = NULL;
|
||||
|
||||
if (methodMatcher.mSelfType != NULL)
|
||||
{
|
||||
BF_ASSERT(mModule->IsInGeneric());
|
||||
result = mModule->GetDefaultTypedValue(methodMatcher.mSelfType);
|
||||
selfType = methodMatcher.mSelfType;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// Will be an error
|
||||
result = mModule->GetDefaultTypedValue(methodMatcher.mBestMethodTypeInstance);
|
||||
selfType = methodMatcher.mBestMethodTypeInstance;
|
||||
}
|
||||
|
||||
if ((selfType != NULL) && (!selfType->IsInterface()))
|
||||
{
|
||||
SetAndRestoreValue<BfTypeInstance*> prevCurTypeInst(mModule->mCurTypeInstance, selfType->ToTypeInstance());
|
||||
auto resolvedType = mModule->ResolveGenericType(result.mType, NULL, NULL);
|
||||
if ((resolvedType != NULL) && (resolvedType != result.mType))
|
||||
result = mModule->GetDefaultTypedValue(resolvedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9537,7 +9572,7 @@ void BfExprEvaluator::LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ig
|
|||
auto origResult = mResult;
|
||||
auto lookupType = BindGenericType(nameNode, mResult.mType);
|
||||
|
||||
if (mResult.mType->IsVar())
|
||||
if (IsVar(mResult.mType))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true);
|
||||
return;
|
||||
|
@ -9696,9 +9731,10 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
|||
mResult.mType = mResult.mType->GetUnderlyingType();
|
||||
|
||||
auto origResult = mResult;
|
||||
if (mResult.mType->IsVar())
|
||||
if (IsVar(mResult.mType))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(mResult.mType), mResult.mType, true);
|
||||
auto varType = mModule->GetPrimitiveType(BfTypeCode_Var);
|
||||
mResult = BfTypedValue(mModule->GetDefaultValue(varType), varType, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -10404,7 +10440,7 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr)
|
|||
return;
|
||||
}
|
||||
|
||||
if (type->IsGenericParam())
|
||||
if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
|
||||
}
|
||||
|
@ -10493,6 +10529,8 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
|
|||
_BoolResult(type->IsNullable());
|
||||
else if (memberName == "IsGenericType")
|
||||
_BoolResult(type->IsGenericTypeInstance());
|
||||
else if (memberName == "IsGenericParam")
|
||||
_BoolResult(type->IsGenericParam());
|
||||
else if (memberName == "IsArray")
|
||||
_BoolResult(type->IsArray());
|
||||
else if (memberName == "IsSizedArray")
|
||||
|
@ -10658,7 +10696,7 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
|
|||
else
|
||||
return false;
|
||||
|
||||
if (type->IsGenericParam())
|
||||
if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
|
||||
{
|
||||
if (mResult.mType != NULL)
|
||||
mResult = mModule->GetDefaultTypedValue(mResult.mType, false, Beefy::BfDefaultValueKind_Undef);
|
||||
|
@ -11817,7 +11855,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
|
||||
if (bindResult.mMethodInstance == NULL)
|
||||
{
|
||||
if ((mResult) && (mResult.mType->IsVar()))
|
||||
if ((mResult) && (IsVar(mResult.mType)))
|
||||
return;
|
||||
mResult = BfTypedValue();
|
||||
return;
|
||||
|
@ -13563,7 +13601,7 @@ void BfExprEvaluator::Visit(BfLambdaBindExpression* lambdaBindExpr)
|
|||
|
||||
if (capturedValue)
|
||||
{
|
||||
if (!capturedTypedVal.mType->IsVar())
|
||||
if (!IsVar(capturedTypedVal.mType))
|
||||
{
|
||||
auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mResult.mValue, 0, fieldInstance->mDataIdx);
|
||||
mModule->mBfIRBuilder->CreateStore(capturedValue, fieldPtr);
|
||||
|
@ -13942,7 +13980,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
}
|
||||
|
||||
resolvedTypeRef = unresolvedTypeRef;
|
||||
if ((resolvedTypeRef != NULL) && (resolvedTypeRef->IsVar()))
|
||||
if ((resolvedTypeRef != NULL) && (IsVar(resolvedTypeRef)))
|
||||
resolvedTypeRef = unresolvedTypeRef;
|
||||
}
|
||||
|
||||
|
@ -14300,7 +14338,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
|
||||
BfInitContext initContext(mModule, resultType, dimensions, dimLengthVals, arraySize, writeIdx);
|
||||
|
||||
if (resultType->IsVar())
|
||||
if (IsVar(resultType))
|
||||
{
|
||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||
mResult = BfTypedValue(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), mModule->GetPrimitiveType(BfTypeCode_Var)));
|
||||
|
@ -14613,7 +14651,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
appendAllocAlign = BF_MAX(appendAllocAlign, allocAlign);
|
||||
|
||||
BfIRValue allocValue;
|
||||
if (resolvedTypeRef->IsVar())
|
||||
if (IsVar(resolvedTypeRef))
|
||||
{
|
||||
mResult = mModule->GetDefaultTypedValue(resultType);
|
||||
return;
|
||||
|
@ -14958,7 +14996,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
|
|||
target = mModule->MakeAddressable(target);
|
||||
}
|
||||
|
||||
if (target.mType->IsVar())
|
||||
if (IsVar(target.mType))
|
||||
{
|
||||
target.mType = mModule->mContext->mBfObjectType;
|
||||
return target;
|
||||
|
|
|
@ -402,6 +402,7 @@ public:
|
|||
BfExprEvaluator(BfModule* module);
|
||||
~BfExprEvaluator();
|
||||
|
||||
bool IsVar(BfType* type);
|
||||
void GetLiteral(BfAstNode* refNode, const BfVariant& variant);
|
||||
void FinishExpressionResult();
|
||||
virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
|
||||
|
|
|
@ -2898,6 +2898,9 @@ bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool
|
|||
else
|
||||
methodInstance->mHasFailed = true;
|
||||
|
||||
if (!methodInstance->mHasStartedDeclaration)
|
||||
StartMethodDeclaration(methodInstance, NULL);
|
||||
|
||||
bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0));
|
||||
if (isSpecializedMethod)
|
||||
{
|
||||
|
@ -5393,6 +5396,9 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
typeDataSource = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance();
|
||||
else
|
||||
typeDataSource = mContext->mBfTypeType;
|
||||
|
||||
if (type->IsGenericParam())
|
||||
typeFlags |= BfTypeFlags_GenericParam;
|
||||
|
||||
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type))
|
||||
{
|
||||
|
@ -11396,10 +11402,12 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
customAttributes->mAttributes.push_back(customAttribute);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
SetAndRestoreValue<BfTypeInstance*> prevCurTypeInst(mContext->mUnreifiedModule->mCurTypeInstance, mCurTypeInstance);
|
||||
SetAndRestoreValue<BfMethodInstance*> prevCurMethodInst(mContext->mUnreifiedModule->mCurMethodInstance, mCurMethodInstance);
|
||||
if (mContext->mCurTypeState != NULL)
|
||||
{
|
||||
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurAttributeTypeRef, attributesDirective->mAttributeTypeRef);
|
||||
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurAttributeTypeRef, attributesDirective->mAttributeTypeRef);
|
||||
mContext->mUnreifiedModule->ResolveTypeResult(attributesDirective->mAttributeTypeRef, attrType, BfPopulateType_BaseType, (BfResolveTypeRefFlags)0);
|
||||
}
|
||||
else
|
||||
|
@ -13820,11 +13828,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
|||
{
|
||||
methodInstance->mMangleWithIdx = true;
|
||||
}
|
||||
|
||||
BfModule* declareModule = GetOrCreateMethodModule(methodInstance);
|
||||
if ((doingRedeclare) && (methodInstance->mDeclModule != mContext->mUnreifiedModule))
|
||||
declareModule = methodInstance->mDeclModule;
|
||||
|
||||
|
||||
BF_ASSERT(typeInst == methodInstance->GetOwner());
|
||||
|
||||
auto methodDeclaration = methodDef->GetMethodDeclaration();
|
||||
|
@ -13882,6 +13886,15 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
|||
addToWorkList = false;
|
||||
}
|
||||
|
||||
BfModule* declareModule;
|
||||
//
|
||||
{
|
||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
|
||||
declareModule = GetOrCreateMethodModule(methodInstance);
|
||||
}
|
||||
if ((doingRedeclare) && (methodInstance->mDeclModule != mContext->mUnreifiedModule))
|
||||
declareModule = methodInstance->mDeclModule;
|
||||
|
||||
BF_ASSERT(declareModule != NULL);
|
||||
methodInstance->mDeclModule = declareModule;
|
||||
|
||||
|
@ -18685,7 +18698,7 @@ void BfModule::EmitGCFindTLSMembers()
|
|||
CallChainedMethods(mCurMethodInstance, false);
|
||||
}
|
||||
|
||||
void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||
void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, bool forceIRWrites)
|
||||
{
|
||||
BP_ZONE_F("BfModule::ProcessMethod %s", BP_DYN_STR(methodInstance->mMethodDef->mName.c_str()));
|
||||
|
||||
|
@ -18714,7 +18727,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
}
|
||||
}
|
||||
|
||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || methodInstance->mIsUnspecialized);
|
||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, (mWantsIRIgnoreWrites || methodInstance->mIsUnspecialized) && (!forceIRWrites));
|
||||
|
||||
if ((HasCompiledOutput()) && (!mBfIRBuilder->mIgnoreWrites))
|
||||
{
|
||||
|
@ -20680,7 +20693,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
mBfIRBuilder->MergeBlockDown(mCurMethodState->mIRInitBlock, mCurMethodState->mIREntryBlock);
|
||||
mBfIRBuilder->MergeBlockDown(mCurMethodState->mIRHeadBlock, mCurMethodState->mIREntryBlock);
|
||||
|
||||
if ((mCurMethodInstance->mIsUnspecialized) /*|| (typeDef->mIsFunction)*/ || (mCurTypeInstance->IsUnspecializedType()))
|
||||
if (((mCurMethodInstance->mIsUnspecialized) /*|| (typeDef->mIsFunction)*/ || (mCurTypeInstance->IsUnspecializedType())) &&
|
||||
(!mIsComptimeModule))
|
||||
{
|
||||
// Don't keep instructions for unspecialized types
|
||||
mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
|
||||
|
@ -20712,7 +20726,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
// We don't want to hold on to pointers to LLVMFunctions of unspecialized types.
|
||||
// This allows us to delete the mScratchModule LLVM module without rebuilding all
|
||||
// unspecialized types
|
||||
if ((mCurTypeInstance->IsUnspecializedType()) || (mCurTypeInstance->IsInterface()))
|
||||
if (((mCurTypeInstance->IsUnspecializedType()) && (!mIsComptimeModule)) ||
|
||||
(mCurTypeInstance->IsInterface()))
|
||||
{
|
||||
BfLogSysM("ProcessMethod Clearing IRFunction: %p\n", methodInstance);
|
||||
methodInstance->mIRFunction = BfIRFunction();
|
||||
|
@ -21904,7 +21919,8 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
|
|||
if (!methodInstance->mIRFunction)
|
||||
{
|
||||
BfIRFunction func;
|
||||
bool wantsLLVMFunc = ((!typeInstance->IsUnspecializedType()) && (!methodDef->IsEmptyPartial())) && (funcType);
|
||||
bool wantsLLVMFunc = ((!typeInstance->IsUnspecializedType() || (mIsComptimeModule)) &&
|
||||
(!methodDef->IsEmptyPartial())) && (funcType);
|
||||
|
||||
/*if (mCurTypeInstance->mTypeDef->mName->ToString() == "ClassA")
|
||||
{
|
||||
|
@ -22042,6 +22058,79 @@ static void StackOverflow()
|
|||
StackOverflow();
|
||||
}
|
||||
|
||||
void BfModule::StartMethodDeclaration(BfMethodInstance* methodInstance, BfMethodState* prevMethodState)
|
||||
{
|
||||
methodInstance->mHasStartedDeclaration = true;
|
||||
auto methodDef = methodInstance->mMethodDef;
|
||||
auto typeInstance = methodInstance->GetOwner();
|
||||
|
||||
bool hasNonGenericParams = false;
|
||||
bool hasGenericParams = false;
|
||||
|
||||
int dependentGenericStartIdx = 0;
|
||||
|
||||
if (methodDef->mIsLocalMethod)
|
||||
{
|
||||
// If we're a local generic method inside an outer generic method, we can still be considered unspecialized
|
||||
// if our outer method's generic args are specialized but ours are unspecialized. This is because locals get
|
||||
// instantiated uniquely for each specialized or unspecialized pass through the outer method, but the local
|
||||
// method still 'inherits' the outer's generic arguments -- but we still need to make an unspecialized pass
|
||||
// over the local method each time
|
||||
auto rootMethodInstance = prevMethodState->GetRootMethodState()->mMethodInstance;
|
||||
dependentGenericStartIdx = 0;
|
||||
if (rootMethodInstance != NULL)
|
||||
{
|
||||
if (rootMethodInstance->mMethodInfoEx != NULL)
|
||||
dependentGenericStartIdx = (int)rootMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
|
||||
|
||||
methodInstance->mIsUnspecialized = rootMethodInstance->mIsUnspecialized;
|
||||
methodInstance->mIsUnspecializedVariation = rootMethodInstance->mIsUnspecializedVariation;
|
||||
}
|
||||
}
|
||||
|
||||
for (int genericArgIdx = dependentGenericStartIdx; genericArgIdx < (int)methodInstance->GetNumGenericArguments(); genericArgIdx++)
|
||||
{
|
||||
auto genericArgType = methodInstance->mMethodInfoEx->mMethodGenericArguments[genericArgIdx];
|
||||
if (genericArgType->IsGenericParam())
|
||||
{
|
||||
hasGenericParams = true;
|
||||
auto genericParam = (BfGenericParamType*)genericArgType;
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
if ((genericParam->mGenericParamKind != BfGenericParamKind_Method) || (genericParam->mGenericParamIdx != genericArgIdx))
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasNonGenericParams = true;
|
||||
if (genericArgType->IsUnspecializedType())
|
||||
{
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((hasGenericParams) && (hasNonGenericParams))
|
||||
{
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
|
||||
if (typeInstance->IsUnspecializedType())
|
||||
{
|
||||
// A specialized method within an unspecialized type is considered an unspecialized variation -- in the sense that we don't
|
||||
// actually want to do method processing on it
|
||||
if ((!methodInstance->mIsUnspecialized) && (methodInstance->GetNumGenericArguments() != 0))
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
}
|
||||
|
||||
if (methodInstance->mIsUnspecializedVariation)
|
||||
BF_ASSERT(methodInstance->mIsUnspecialized);
|
||||
|
||||
if (methodDef->mMethodType == BfMethodType_Mixin)
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
}
|
||||
|
||||
// methodDeclaration is NULL for default constructors
|
||||
void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool isTemporaryFunc, bool addToWorkList)
|
||||
{
|
||||
|
@ -22064,7 +22153,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
BfMethodState methodState;
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
|
||||
methodState.mTempKind = BfMethodState::TempKind_Static;
|
||||
|
||||
|
||||
defer({ mCurMethodInstance->mHasBeenDeclared = true; });
|
||||
|
||||
// If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info
|
||||
|
@ -22101,92 +22190,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
|
||||
if ((methodInstance->IsSpecializedByAutoCompleteMethod()) || (mCurTypeInstance->IsFunction()))
|
||||
addToWorkList = false;
|
||||
|
||||
bool hasNonGenericParams = false;
|
||||
bool hasGenericParams = false;
|
||||
|
||||
int dependentGenericStartIdx = 0;
|
||||
if (methodDef->mIsLocalMethod)
|
||||
{
|
||||
// If we're a local generic method inside an outer generic method, we can still be considered unspecialized
|
||||
// if our outer method's generic args are specialized but ours are unspecialized. This is because locals get
|
||||
// instantiated uniquely for each specialized or unspecialized pass through the outer method, but the local
|
||||
// method still 'inherits' the outer's generic arguments -- but we still need to make an unspecialized pass
|
||||
// over the local method each time
|
||||
auto rootMethodInstance = prevMethodState.mPrevVal->GetRootMethodState()->mMethodInstance;
|
||||
dependentGenericStartIdx = 0;
|
||||
if (rootMethodInstance != NULL)
|
||||
{
|
||||
if (rootMethodInstance->mMethodInfoEx != NULL)
|
||||
dependentGenericStartIdx = (int)rootMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
|
||||
|
||||
methodInstance->mIsUnspecialized = rootMethodInstance->mIsUnspecialized;
|
||||
methodInstance->mIsUnspecializedVariation = rootMethodInstance->mIsUnspecializedVariation;
|
||||
}
|
||||
}
|
||||
|
||||
for (int genericArgIdx = dependentGenericStartIdx; genericArgIdx < (int) methodInstance->GetNumGenericArguments(); genericArgIdx++)
|
||||
{
|
||||
auto genericArgType = methodInstance->mMethodInfoEx->mMethodGenericArguments[genericArgIdx];
|
||||
if (genericArgType->IsGenericParam())
|
||||
{
|
||||
hasGenericParams = true;
|
||||
auto genericParam = (BfGenericParamType*)genericArgType;
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
if ((genericParam->mGenericParamKind != BfGenericParamKind_Method) || (genericParam->mGenericParamIdx != genericArgIdx))
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasNonGenericParams = true;
|
||||
if (genericArgType->IsUnspecializedType())
|
||||
{
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((hasGenericParams) && (hasNonGenericParams))
|
||||
{
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
}
|
||||
|
||||
if (typeInstance->IsUnspecializedType())
|
||||
{
|
||||
// A specialized method within an unspecialized type is considered an unspecialized variation -- in the sense that we don't
|
||||
// actually want to do method processing on it
|
||||
if ((!methodInstance->mIsUnspecialized) && (methodInstance->GetNumGenericArguments() != 0))
|
||||
methodInstance->mIsUnspecializedVariation = true;
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
}
|
||||
|
||||
//methodInstance->mIsUnspecializedVariation |= typeInstance->IsUnspecializedTypeVariation();
|
||||
|
||||
for (auto genericParamDef : methodDef->mGenericParams)
|
||||
{
|
||||
if (mCompiler->IsAutocomplete())
|
||||
{
|
||||
auto autoComplete = mCompiler->mResolvePassData->mAutoComplete;
|
||||
//autoComplete->CheckTypeRef()
|
||||
}
|
||||
}
|
||||
|
||||
if (methodInstance->mIsUnspecializedVariation)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (methodInstance->mIsUnspecializedVariation)
|
||||
BF_ASSERT(methodInstance->mIsUnspecialized);
|
||||
|
||||
if (methodDef->mMethodType == BfMethodType_Mixin)
|
||||
methodInstance->mIsUnspecialized = true;
|
||||
|
||||
if (methodInstance->mIsUnspecialized)
|
||||
{
|
||||
//BF_ASSERT(methodInstance->mDeclModule == methodInstance->GetOwner()->mModule);
|
||||
}
|
||||
if (!methodInstance->mHasStartedDeclaration)
|
||||
StartMethodDeclaration(methodInstance, prevMethodState.mPrevVal);
|
||||
|
||||
BfAutoComplete* bfAutocomplete = NULL;
|
||||
if (mCompiler->mResolvePassData != NULL)
|
||||
|
@ -23164,7 +23170,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
|
||||
// Don't compare specialized generic methods against normal methods
|
||||
if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) &&
|
||||
(!methodDef->mIsLocalMethod))
|
||||
(!methodDef->mIsLocalMethod) && (!mCurTypeInstance->IsUnspecializedTypeVariation()))
|
||||
{
|
||||
if ((!methodInstance->mIsForeignMethodDef) && (methodDef->mMethodType != BfMethodType_Init))
|
||||
{
|
||||
|
|
|
@ -1888,6 +1888,7 @@ public:
|
|||
void GetMethodCustomAttributes(BfMethodInstance* methodInstance);
|
||||
void SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& mangledName, bool isTemporaryFunc, bool* outIsIntrinsic);
|
||||
void CheckHotMethod(BfMethodInstance* methodInstance, const StringImpl& mangledName);
|
||||
void StartMethodDeclaration(BfMethodInstance* methodInstance, BfMethodState* prevMethodState);
|
||||
void DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool isTemporaryFunc, bool addToWorkList = true);
|
||||
void AddMethodToWorkList(BfMethodInstance* methodInstance);
|
||||
bool IsInterestedInMethod(BfTypeInstance* typeInstance, BfMethodDef* methodDef);
|
||||
|
@ -1916,7 +1917,7 @@ public:
|
|||
void AddHotDataReferences(BfHotDataReferenceBuilder* builder);
|
||||
void ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfType* thisType, bool wantsDIData, SizedArrayImpl<BfIRMDNode>* diParams);
|
||||
void ProcessMethod_ProcessDeferredLocals(int startIdx = 0);
|
||||
void ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup = false);
|
||||
void ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup = false, bool forceIRWrites = false);
|
||||
void CreateDynamicCastMethod();
|
||||
void CreateValueTypeEqualsMethod(bool strictEquals);
|
||||
BfIRFunction GetIntrinsic(BfMethodInstance* methodInstance, bool reportFailure = false);
|
||||
|
|
|
@ -4178,13 +4178,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool tryCE = true;
|
||||
|
||||
if (typeInstance->IsUnspecializedType())
|
||||
tryCE = false;
|
||||
|
||||
if ((typeInstance->mDefineState == BfTypeDefineState_CETypeInit) && (tryCE))
|
||||
|
||||
if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit)
|
||||
{
|
||||
if (populateType <= BfPopulateType_AllowStaticMethods)
|
||||
return;
|
||||
|
@ -12296,6 +12291,9 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
}
|
||||
else if (constant->mConstType == BfConstType_Undef)
|
||||
{
|
||||
if (mIsComptimeModule)
|
||||
return mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(toType));
|
||||
|
||||
BF_ASSERT(mBfIRBuilder->mIgnoreWrites);
|
||||
|
||||
auto undefConst = (BfConstantUndef*)constant;
|
||||
|
|
|
@ -843,6 +843,7 @@ public:
|
|||
bool mIsUnspecialized:1;
|
||||
bool mIsUnspecializedVariation:1;
|
||||
bool mIsReified:1;
|
||||
bool mHasStartedDeclaration:1;
|
||||
bool mHasBeenDeclared:1;
|
||||
bool mHasBeenProcessed:1;
|
||||
bool mHasFailed:1;
|
||||
|
@ -885,6 +886,7 @@ public:
|
|||
mIsUnspecialized = false;
|
||||
mIsUnspecializedVariation = false;
|
||||
mIsReified = true;
|
||||
mHasStartedDeclaration = false;
|
||||
mHasBeenDeclared = false;
|
||||
mHasBeenProcessed = false;
|
||||
mHasFailed = false;
|
||||
|
@ -2640,7 +2642,7 @@ public:
|
|||
static String TypeToString(BfAstNode* typeRef);
|
||||
static String TypeToString(BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
||||
static bool TypeToString(StringImpl& str, BfTypeDef* typeDef, BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None);
|
||||
static bool TypeEquals(BfType* typeA, BfType* typeB, BfType* selfType);
|
||||
static bool TypeEquals(BfType* typeA, BfType* typeB, BfTypeInstance* selfType);
|
||||
|
||||
template <typename T>
|
||||
static void GetProjectList(BfType* checkType, T* projectList, int immutableLength)
|
||||
|
|
|
@ -187,6 +187,7 @@ enum BfTypeFlags
|
|||
BfTypeFlags_Delegate = 0x20000,
|
||||
BfTypeFlags_Function = 0x40000,
|
||||
BfTypeFlags_HasDestructor = 0x80000,
|
||||
BfTypeFlags_GenericParam = 0x100000
|
||||
};
|
||||
|
||||
enum BfMethodFlags
|
||||
|
|
|
@ -912,6 +912,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
|
|||
return result;
|
||||
}
|
||||
break;
|
||||
case BeUndefConstant::TypeId:
|
||||
case BeConstant::TypeId:
|
||||
{
|
||||
uint64 u64Val = 0;
|
||||
|
@ -1181,7 +1182,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
|
|||
// if (callInst->mInlineResult != NULL)
|
||||
// return GetOperand(callInst->mInlineResult);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
CeOperand* operandPtr = NULL;
|
||||
|
@ -1279,7 +1280,7 @@ void CeBuilder::HandleParams()
|
|||
}
|
||||
}
|
||||
|
||||
void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance)
|
||||
void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance, bool forceIRWrites)
|
||||
{
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodStateInConstEval(mCeMachine->mCeModule->mCurMethodState, NULL);
|
||||
BfAutoComplete* prevAutoComplete = NULL;
|
||||
|
@ -1299,7 +1300,7 @@ void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance
|
|||
mCeMachine->mCeModule->mHadBuildError = false;
|
||||
auto irState = irBuilder->GetState();
|
||||
auto beState = irCodeGen->GetState();
|
||||
mCeMachine->mCeModule->ProcessMethod(dupMethodInstance, true);
|
||||
mCeMachine->mCeModule->ProcessMethod(dupMethodInstance, true, forceIRWrites);
|
||||
irCodeGen->SetState(beState);
|
||||
irBuilder->SetState(irState);
|
||||
|
||||
|
@ -1322,27 +1323,27 @@ void CeBuilder::Build()
|
|||
BfMethodInstance dupMethodInstance;
|
||||
dupMethodInstance.CopyFrom(methodInstance);
|
||||
auto methodDef = methodInstance->mMethodDef;
|
||||
|
||||
|
||||
bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());
|
||||
int dependentGenericStartIdx = 0;
|
||||
if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
|
||||
((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod))))
|
||||
((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod) && (!methodInstance->mIsUnspecialized))))
|
||||
{
|
||||
auto unspecializedMethodInstance = mCeMachine->mCeModule->GetUnspecializedMethodInstance(methodInstance, !methodInstance->mMethodDef->mIsLocalMethod);
|
||||
if (!unspecializedMethodInstance->mHasBeenProcessed)
|
||||
{
|
||||
BfMethodInstance dupUnspecMethodInstance;
|
||||
dupUnspecMethodInstance.CopyFrom(unspecializedMethodInstance);
|
||||
ProcessMethod(unspecializedMethodInstance, &dupUnspecMethodInstance);
|
||||
ProcessMethod(unspecializedMethodInstance, &dupUnspecMethodInstance, false);
|
||||
dupMethodInstance.GetMethodInfoEx()->mGenericTypeBindings = dupUnspecMethodInstance.mMethodInfoEx->mGenericTypeBindings;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Clear this so we can properly get QueueStaticField calls
|
||||
mCeMachine->mCeModule->mStaticFieldRefs.Clear();
|
||||
|
||||
int startFunctionCount = (int)beModule->mFunctions.size();
|
||||
ProcessMethod(methodInstance, &dupMethodInstance);
|
||||
ProcessMethod(methodInstance, &dupMethodInstance, true);
|
||||
if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized)
|
||||
return;
|
||||
|
||||
|
|
|
@ -730,7 +730,7 @@ public:
|
|||
void EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeOperand& rhs, CeOperand& result);
|
||||
void EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result);
|
||||
void EmitSizedOp(CeOp op, const CeOperand& operand, CeOperand* result, bool allowNonStdSize);
|
||||
void ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance);
|
||||
void ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance, bool forceIRWrites);
|
||||
void Build();
|
||||
};
|
||||
|
||||
|
|
|
@ -8167,8 +8167,8 @@ void DbgExprEvaluator::Visit(BfTypeAttrExpression* typeAttrExpr)
|
|||
case BfToken_StrideOf:
|
||||
mResult.mInt64 = dbgType->GetStride();
|
||||
break;
|
||||
case BfToken_TypeOf:
|
||||
//TODO:
|
||||
default:
|
||||
Fail("Invalid attribute expression", typeAttrExpr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#pragma warning disable 168
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
|
@ -317,17 +320,75 @@ namespace Tests
|
|||
|
||||
interface IParsable
|
||||
{
|
||||
public enum Error
|
||||
{
|
||||
case Unknown;
|
||||
case Syntax(int pos);
|
||||
case InvalidValue;
|
||||
case UnexpectedEnd;
|
||||
}
|
||||
|
||||
static Self GetDefault(Self[] arr);
|
||||
static Result<Self> Parse(StringView sv, Self defaultVal);
|
||||
static Result<Self, Error> ParseEx(StringView str)
|
||||
{
|
||||
Self[] arr = null;
|
||||
Self defVal = GetDefault(arr);
|
||||
switch (Parse(str, default(Self)))
|
||||
{
|
||||
case .Ok(let val): return .Ok(val);
|
||||
case .Err: return .Err(.Unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ClassH : IParsable
|
||||
{
|
||||
static Self IParsable.GetDefault(ClassH[] arr)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
public static Result<Self> Parse(StringView sv, ClassH defaultVal)
|
||||
{
|
||||
return .Err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[AttributeUsage(.Method)]
|
||||
struct MethodTestAttribute : Attribute, IComptimeMethodApply
|
||||
{
|
||||
public static String gLog = new .() ~ delete _;
|
||||
|
||||
[Comptime]
|
||||
public void ApplyToMethod(ComptimeMethodInfo method)
|
||||
{
|
||||
Compiler.EmitMethodEntry(method, "int b = 2;");
|
||||
}
|
||||
}
|
||||
|
||||
struct Test4<T>
|
||||
{
|
||||
[Comptime, OnCompile(.TypeInit)]
|
||||
public static void Generator()
|
||||
{
|
||||
T val = default;
|
||||
Compiler.EmitTypeBody(typeof(Self), "int test = 0;");
|
||||
}
|
||||
|
||||
[MethodTest]
|
||||
public void Zank<T2>()
|
||||
{
|
||||
int c = b;
|
||||
}
|
||||
|
||||
public void Test() mut
|
||||
{
|
||||
test = 1;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestDefaults()
|
||||
{
|
||||
|
@ -367,6 +428,8 @@ namespace Tests
|
|||
TestIFaceD(cg);
|
||||
Test.Assert(cg.mA == 999);
|
||||
Test.Assert(TestIFaceD2(cg) == 999);
|
||||
|
||||
ClassH ch = scope .();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue