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:
parent
c21be1eea1
commit
2f98e7f579
7 changed files with 72 additions and 26 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
32
IDEHelper/Tests/src/Opaques.bf
Normal file
32
IDEHelper/Tests/src/Opaques.bf
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue