2
0
Эх сурвалжийг харах

Improved opaques - can now be used with extension methods

Brian Fiete 8 сар өмнө
parent
commit
2f98e7f579

+ 18 - 10
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -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);

+ 2 - 2
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -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
 		{

+ 8 - 8
IDEHelper/Compiler/BfModule.cpp

@@ -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++;
 			}

+ 9 - 4
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -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()))

+ 2 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -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

+ 1 - 1
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -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

+ 32 - 0
IDEHelper/Tests/src/Opaques.bf

@@ -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);
+	}
+}