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

Improved opaques - can now be used with extension methods

This commit is contained in:
Brian Fiete 2025-01-19 07:02:18 -08:00
parent c21be1eea1
commit 2f98e7f579
7 changed files with 72 additions and 26 deletions

View file

@ -4288,7 +4288,7 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
BfRefType* refType = (BfRefType*)varDecl->mResolvedType;
BfType* innerType = refType->mElementType;
if (innerType->IsValuelessType())
if (innerType->IsValuelessNonOpaqueType())
{
if (refType->mRefKind == BfRefType::RefKind_Mut)
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), innerType, BfTypedValueKind_MutableValue);
@ -4314,7 +4314,7 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
else
localResult = BfTypedValue(varDecl->mAddr, varDecl->mResolvedType, varDecl->mIsReadOnly ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr);
}
else if (varDecl->mResolvedType->IsValuelessType())
else if (varDecl->mResolvedType->IsValuelessNonOpaqueType())
{
if ((varDecl->mResolvedType->IsRef()) && (!allowRef))
{
@ -7309,7 +7309,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
}
if (argVal.mType->IsValuelessType())
if (argVal.mType->IsValuelessNonOpaqueType())
return;
bool wantSplat = false;
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime()))
@ -7404,7 +7404,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMethodInstance* methodInstance, SizedArrayImpl<BfIRValue>& irArgs, bool skipMutCheck)
{
MakeBaseConcrete(argVal);
MakeBaseConcrete(argVal);
auto methodDef = methodInstance->mMethodDef;
if (methodInstance->IsSkipCall())
@ -7456,14 +7456,14 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
}
}
if (argVal.mType->IsValuelessType())
if (argVal.mType->IsValuelessNonOpaqueType())
return;
auto owner = methodInstance->GetOwner();
bool allowThisSplatting;
if (mModule->mIsComptimeModule)
allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType();
allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessNonOpaqueType();
else
allowThisSplatting = methodInstance->AllowsSplatting(-1);
@ -21057,7 +21057,11 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
}
else
{
if (ptr.mType->IsValuelessType())
if (ptr.mType->IsOpaque())
{
mModule->Fail(StrFormat("Unable to assign to opaque type '%s'", mModule->TypeToString(ptr.mType).c_str()), assignExpr);
}
else if (ptr.mType->IsValuelessType())
{
mModule->EmitEnsureInstructionAt();
}
@ -22577,7 +22581,11 @@ void BfExprEvaluator::HandleIndexerExpression(BfIndexerExpression* indexerExpr,
auto underlyingType = pointerType->mElementType;
mModule->mBfIRBuilder->PopulateType(underlyingType);
if (isUndefIndex)
if (underlyingType->IsOpaque())
{
mModule->Fail(StrFormat("Unable to index opaque pointer type '%s'", mModule->TypeToString(pointerType).c_str()), indexerExpr);
}
else if (isUndefIndex)
{
mResult = mModule->GetDefaultTypedValue(underlyingType, false, BfDefaultValueKind_Addr);
}
@ -23014,7 +23022,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
mModule->FixIntUnknown(mResult);
mModule->PopulateType(mResult.mType);
auto ptrType = mModule->CreatePointerType(mResult.mType);
if (mResult.mType->IsValuelessType())
if ((mResult.mType->IsValuelessType()) && (!mResult.mType->IsOpaque()))
{
if (!mModule->IsInSpecializedSection())
{
@ -23072,7 +23080,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
BfPointerType* pointerType = (BfPointerType*)derefTarget.mType;
auto resolvedType = pointerType->mElementType;
mModule->PopulateType(resolvedType);
if (resolvedType->IsValuelessType())
if (resolvedType->IsValuelessNonOpaqueType())
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true);
else
mResult = BfTypedValue(derefTarget.mValue, resolvedType, true);

View file

@ -2794,7 +2794,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
{
BfPointerType* pointerType = (BfPointerType*)type;
populateModule->PopulateType(pointerType->mElementType, BfPopulateType_Data);
if (pointerType->mElementType->IsValuelessType())
if (pointerType->mElementType->IsValuelessNonOpaqueType())
{
irType = GetPrimitiveType(BfTypeCode_NullPtr);
}
@ -2813,7 +2813,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
{
BfRefType* refType = (BfRefType*)type;
if (refType->mElementType->IsValuelessType())
if (refType->mElementType->IsValuelessNonOpaqueType())
irType = GetPrimitiveType(BfTypeCode_NullPtr);
else
{

View file

@ -13205,7 +13205,7 @@ BfTypedValue BfModule::ToRef(BfTypedValue typedValue, BfRefType* refType)
if (refType->mRefKind == BfRefType::RefKind_Mut)
refType = CreateRefType(typedValue.mType);
if (!typedValue.mType->IsValuelessType())
if (!typedValue.mType->IsValuelessNonOpaqueType())
typedValue = MakeAddressable(typedValue, false, true);
return BfTypedValue(typedValue.mValue, refType);
}
@ -13216,7 +13216,7 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
return typedValue;
PopulateType(typedValue.mType);
if ((typedValue.mType->IsValuelessType()) || (typedValue.mType->IsVar()))
if ((typedValue.mType->IsValuelessNonOpaqueType()) || (typedValue.mType->IsVar()))
return BfTypedValue(mBfIRBuilder->GetFakeVal(), typedValue.mType, false);
if (typedValue.mValue.IsConst())
@ -13518,7 +13518,7 @@ BfTypedValue BfModule::MakeAddressable(BfTypedValue typedVal, bool forceMutable,
if ((forceAddressable) ||
((typedVal.mType->IsValueType()) &&
(!typedVal.mType->IsValuelessType())))
(!typedVal.mType->IsValuelessNonOpaqueType())))
{
wasReadOnly = true; // Any non-addr is implicitly read-only
@ -21175,7 +21175,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
for ( ; argIdx < irParamCount; localIdx++)
{
bool isThis = ((localIdx == 0) && (!mCurMethodInstance->mMethodDef->mIsStatic));
if ((isThis) && (thisType->IsValuelessType()))
if ((isThis) && (thisType->IsValuelessNonOpaqueType()))
isThis = false;
if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() == argIdx))
@ -21192,7 +21192,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
paramVar = methodState.mLocals[localIdx];
if ((paramVar->mCompositeCount == -1) &&
(!paramVar->mIsConst) &&
((!paramVar->mResolvedType->IsValuelessType()) || (paramVar->mResolvedType->IsMethodRef())))
((!paramVar->mResolvedType->IsValuelessNonOpaqueType()) || (paramVar->mResolvedType->IsMethodRef())))
break;
localIdx++;
}
@ -21358,7 +21358,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
continue;
bool isThis = ((curLocalIdx == 0) && (!mCurMethodInstance->mMethodDef->mIsStatic));
if ((isThis) && (thisType->IsValuelessType()))
if ((isThis) && (thisType->IsValuelessNonOpaqueType()))
isThis = false;
if (paramVar->mValue.IsArg())
@ -21423,7 +21423,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
}
}
if (paramVar->mResolvedType->IsValuelessType())
if (paramVar->mResolvedType->IsValuelessNonOpaqueType())
{
diVariable = mBfIRBuilder->DbgCreateAutoVariable(diFunction,
paramName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
@ -21691,7 +21691,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if (loweredTypeCode2 != BfTypeCode_None)
argIdx++;
}
else if (!paramVar->mResolvedType->IsValuelessType())
else if (!paramVar->mResolvedType->IsValuelessNonOpaqueType())
{
argIdx++;
}

View file

@ -1090,8 +1090,8 @@ bool BfMethodInstance::HasThis()
if (mMethodDef->mIsStatic)
return false;
if ((mMethodInfoEx != NULL) && (mMethodInfoEx->mClosureInstanceInfo != NULL) && (mMethodInfoEx->mClosureInstanceInfo->mThisOverride != NULL))
return !mMethodInfoEx->mClosureInstanceInfo->mThisOverride->IsValuelessType();
return (!mMethodInstanceGroup->mOwner->IsValuelessType());
return !mMethodInfoEx->mClosureInstanceInfo->mThisOverride->IsValuelessNonOpaqueType();
return (!mMethodInstanceGroup->mOwner->IsValuelessNonOpaqueType());
}
bool BfMethodInstance::IsVirtual()
@ -1278,7 +1278,7 @@ bool BfMethodInstance::IsParamSkipped(int paramIdx)
BfType* paramType = GetParamType(paramIdx);
if ((paramType->CanBeValuelessType()) && (paramType->IsDataIncomplete()))
resolveModule->PopulateType(paramType, BfPopulateType_Data);
if ((paramType->IsValuelessType()) && (!paramType->IsMethodRef()))
if ((paramType->IsValuelessNonOpaqueType()) && (!paramType->IsMethodRef()))
return true;
return false;
}
@ -1378,6 +1378,11 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
{
if (mMethodDef->mName == "Test4")
{
NOP;
}
BfModule* resolveModule = module->mContext->mUnreifiedModule;
resolveModule->PopulateType(mReturnType);
@ -1498,7 +1503,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
if (checkType->CanBeValuelessType())
resolveModule->PopulateType(checkType, BfPopulateType_Data);
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
if ((checkType->IsValuelessNonOpaqueType()) && (!checkType->IsMethodRef()))
continue;
if ((doSplat) && (!checkType->IsMethodRef()))

View file

@ -560,6 +560,7 @@ public:
virtual bool IsVoidPtr() { return false; }
virtual bool CanBeValuelessType() { return false; }
virtual bool IsValuelessType() { BF_ASSERT(mSize != -1); BF_ASSERT(mDefineState >= BfTypeDefineState_Defined); return mSize == 0; }
virtual bool IsValuelessNonOpaqueType() { return IsValuelessType() && !IsOpaque(); }
virtual bool IsSelf() { return false; }
virtual bool IsDot() { return false; }
virtual bool IsVar() { return false; }
@ -2537,7 +2538,7 @@ public:
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); }
virtual bool IsUnspecializedTypeVariation() override { return mElementType->IsUnspecializedTypeVariation(); }
virtual bool CanBeValuelessType() override { return mElementType->CanBeValuelessType(); }
virtual bool IsValuelessType() override { return mElementType->IsValuelessType(); }
virtual bool IsValuelessType() override { return mElementType->IsValuelessNonOpaqueType(); }
};
class BfArrayType : public BfTypeInstance

View file

@ -1905,7 +1905,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
localDef->mValue = initValue.mValue;
if ((localDef->mAddr) && (!localDef->mResolvedType->IsValuelessType()))
{
if (!initValue.mType->IsVar())
if ((!initValue.mType->IsVar()) && (!initValue.mType->IsValuelessType()))
wantsStore = true;
}
else

View file

@ -0,0 +1,32 @@
using System;
namespace Tests;
class Opaques
{
struct StructA
{
public int mA;
public int mB;
}
struct StructB;
public static void Modify(this ref StructB @this, int addA, int addB)
{
StructB* sbPtr = &@this;
StructA* saPtr = (.)(void*)sbPtr;
saPtr.mA += addA;
saPtr.mB += addB;
}
[Test]
public static void TestBasics()
{
StructA sa = .() { mA = 123, mB = 234 };
StructB* sb = (.)&sa;
sb.Modify(1000, 2000);
Test.Assert(sa.mA == 1123);
Test.Assert(sa.mB == 2234);
}
}