1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 12:02: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; BfRefType* refType = (BfRefType*)varDecl->mResolvedType;
BfType* innerType = refType->mElementType; BfType* innerType = refType->mElementType;
if (innerType->IsValuelessType()) if (innerType->IsValuelessNonOpaqueType())
{ {
if (refType->mRefKind == BfRefType::RefKind_Mut) if (refType->mRefKind == BfRefType::RefKind_Mut)
return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), innerType, BfTypedValueKind_MutableValue); return BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), innerType, BfTypedValueKind_MutableValue);
@ -4314,7 +4314,7 @@ BfTypedValue BfExprEvaluator::LoadLocal(BfLocalVariable* varDecl, bool allowRef)
else else
localResult = BfTypedValue(varDecl->mAddr, varDecl->mResolvedType, varDecl->mIsReadOnly ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr); 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)) if ((varDecl->mResolvedType->IsRef()) && (!allowRef))
{ {
@ -7309,7 +7309,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType); argVal = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
} }
if (argVal.mType->IsValuelessType()) if (argVal.mType->IsValuelessNonOpaqueType())
return; return;
bool wantSplat = false; bool wantSplat = false;
if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime())) if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsComptime()))
@ -7456,14 +7456,14 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
} }
} }
if (argVal.mType->IsValuelessType()) if (argVal.mType->IsValuelessNonOpaqueType())
return; return;
auto owner = methodInstance->GetOwner(); auto owner = methodInstance->GetOwner();
bool allowThisSplatting; bool allowThisSplatting;
if (mModule->mIsComptimeModule) if (mModule->mIsComptimeModule)
allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType(); allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessNonOpaqueType();
else else
allowThisSplatting = methodInstance->AllowsSplatting(-1); allowThisSplatting = methodInstance->AllowsSplatting(-1);
@ -21057,7 +21057,11 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool
} }
else 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(); mModule->EmitEnsureInstructionAt();
} }
@ -22577,7 +22581,11 @@ void BfExprEvaluator::HandleIndexerExpression(BfIndexerExpression* indexerExpr,
auto underlyingType = pointerType->mElementType; auto underlyingType = pointerType->mElementType;
mModule->mBfIRBuilder->PopulateType(underlyingType); 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); mResult = mModule->GetDefaultTypedValue(underlyingType, false, BfDefaultValueKind_Addr);
} }
@ -23014,7 +23022,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
mModule->FixIntUnknown(mResult); mModule->FixIntUnknown(mResult);
mModule->PopulateType(mResult.mType); mModule->PopulateType(mResult.mType);
auto ptrType = mModule->CreatePointerType(mResult.mType); auto ptrType = mModule->CreatePointerType(mResult.mType);
if (mResult.mType->IsValuelessType()) if ((mResult.mType->IsValuelessType()) && (!mResult.mType->IsOpaque()))
{ {
if (!mModule->IsInSpecializedSection()) if (!mModule->IsInSpecializedSection())
{ {
@ -23072,7 +23080,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
BfPointerType* pointerType = (BfPointerType*)derefTarget.mType; BfPointerType* pointerType = (BfPointerType*)derefTarget.mType;
auto resolvedType = pointerType->mElementType; auto resolvedType = pointerType->mElementType;
mModule->PopulateType(resolvedType); mModule->PopulateType(resolvedType);
if (resolvedType->IsValuelessType()) if (resolvedType->IsValuelessNonOpaqueType())
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true); mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), resolvedType, true);
else else
mResult = BfTypedValue(derefTarget.mValue, resolvedType, true); mResult = BfTypedValue(derefTarget.mValue, resolvedType, true);

View file

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

View file

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

View file

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

View file

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

View file

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