From 5267e18783c9f280431de7b691edb7e138a46586 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 19 Jan 2022 10:38:20 -0500 Subject: [PATCH] 'var' improvements, fixed cast issues with typed prim & constraint check --- IDEHelper/Compiler/BfExprEvaluator.cpp | 37 +++++++-- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 98 ++++++++++++++++-------- IDEHelper/Compiler/BfStmtEvaluator.cpp | 14 +++- 3 files changed, 108 insertions(+), 41 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index c7f335a1..37d19043 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -10962,6 +10962,12 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr) mModule->AddDependency(targetType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean); + if (targetValue.mType->IsVar()) + { + mResult = mModule->GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef); + return; + } + if (targetValue.mType->IsValueTypeOrValueTypePtr()) { auto typeInstance = targetValue.mType->ToTypeInstance(); @@ -11113,6 +11119,12 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr) targetType = typeConstraint; } + if (targetType->IsVar()) + { + mResult = mModule->GetDefaultTypedValue(targetType); + return; + } + if ((!targetType->IsObjectOrInterface()) && (!targetType->IsNullable())) { mModule->Fail(StrFormat("The as operator must be used with a reference type or nullable type ('%s' is a non-nullable value type)", @@ -11159,6 +11171,12 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr) return; } + if (targetValue.mType->IsVar()) + { + mResult = mModule->GetDefaultTypedValue(targetType, false, BfDefaultValueKind_Undef); + return; + } + if (targetValue.mType->IsValueTypeOrValueTypePtr()) { mModule->Warn(0, StrFormat("Type '%s' is not applicable for dynamic casting", @@ -15254,7 +15272,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, if (genericArg->IsVar()) { - BF_ASSERT(methodMatcher.mHasVarArguments); + //BF_ASSERT(methodMatcher.mHasVarArguments); hasVarGenerics = true; } @@ -19373,14 +19391,14 @@ BfTypedValue BfExprEvaluator::SetupNullConditional(BfTypedValue thisValue, BfTok return thisValue; } - if (thisValue.mType->IsNullable()) + if ((thisValue.mType->IsNullable()) || (thisValue.mType->IsVar())) { // Success } else if ((thisValue.mType->IsPointer()) || (thisValue.mType->IsObjectOrInterface())) { // Also good - } + } else { mModule->Warn(0, StrFormat("Null conditional reference is unnecessary since value type '%s' can never be null", mModule->TypeToString(thisValue.mType).c_str()), dotToken); @@ -22345,8 +22363,17 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod auto underlyingType = resultType->GetUnderlyingType(); - BfIRValue convResultValue = mModule->CastToValue(resultTypeSrc, *resultTypedValue, underlyingType, BfCastFlags_Explicit); - BfIRValue convOtherValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, underlyingType, BfCastFlags_Explicit); + BfIRValue convResultValue; + if (resultTypedValue->mType == resultType) + convResultValue = mModule->LoadValue(*resultTypedValue).mValue; + else + convResultValue = mModule->CastToValue(resultTypeSrc, *resultTypedValue, underlyingType, BfCastFlags_Explicit); + + BfIRValue convOtherValue; + if (otherTypedValue->mType == resultType) + convOtherValue = mModule->LoadValue(*otherTypedValue).mValue; + else + convOtherValue = mModule->CastToValue(otherTypeSrc, *otherTypedValue, underlyingType, BfCastFlags_Explicit); if ((!underlyingType->IsValuelessType()) && ((!convResultValue) || (!convOtherValue))) return; diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 6b0308ad..9cd263a1 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2800,6 +2800,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde if (typeInstance->mTypeInfoEx == NULL) typeInstance->mTypeInfoEx = new BfTypeInfoEx(); + bool isAllInt64 = true; + for (auto& fieldInstanceRef : typeInstance->mFieldInstances) { auto fieldInstance = &fieldInstanceRef; @@ -2810,7 +2812,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde continue; auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); - BF_ASSERT((constant->mTypeCode == BfTypeCode_Int64) || (!underlyingTypeDeferred)); + if (constant->mTypeCode != BfTypeCode_Int64) + isAllInt64 = false; if (isFirst) { @@ -2851,7 +2854,7 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde if (typeInstance->mIsCRepr) typeCode = BfTypeCode_Int32; - if (typeCode != BfTypeCode_Int64) + if ((typeCode != BfTypeCode_Int64) || (!isAllInt64)) { for (auto& fieldInstanceRef : typeInstance->mFieldInstances) { @@ -2861,6 +2864,8 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry()) continue; auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); + if (constant->mTypeCode == typeCode) + continue; BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64); fieldInstance->mConstIdx = newConstant.mId; } @@ -4849,6 +4854,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } } + if (_CheckTypeDone()) + return; + if (typeInstance->mDefineState < BfTypeDefineState_Defined) { typeInstance->mDefineState = BfTypeDefineState_Defined; @@ -10551,9 +10559,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula { auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue)); if ((genericArg == NULL) || (genericArg->IsVar())) - { + { mContext->mResolvedTypes.RemoveEntry(resolvedEntry); - return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); + return ResolveTypeResult(typeRef, genericArg->IsVar() ? genericArg : NULL, populateType, resolveFlags); } genericArgs.Add(genericArg); } @@ -12713,7 +12721,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp { auto result = BfTypedValue(mBfIRBuilder->GetFakeVal(), operatorConstraintReturnType); if (result.mType != toType) - return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags); + return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags); if (result) return result.mValue; } @@ -12741,50 +12749,74 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } } + bool doCall = true; + auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher); if (moduleMethodInstance.mMethodInstance != NULL) { - auto paramType = moduleMethodInstance.mMethodInstance->GetParamType(0); - auto wantType = paramType; - if (wantType->IsRef()) - wantType = wantType->GetUnderlyingType(); - auto typedVal = methodMatcher.mArguments[0].mTypedValue; - if (wantType != typedVal.mType) + auto returnType = moduleMethodInstance.mMethodInstance->mReturnType; + if (typedVal.mType->IsTypedPrimitive()) { - if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType))) + auto underlyingType = typedVal.mType->GetUnderlyingType(); + if ((returnType != underlyingType) && (CanCast(GetFakeTypedValue(underlyingType), toType, (BfCastFlags)(castFlags | BfCastFlags_NoConversionOperator)))) { - typedVal = MakeAddressable(typedVal); - methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())), - paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr); + if ((CanCast(GetFakeTypedValue(underlyingType), returnType)) && + (!CanCast(GetFakeTypedValue(returnType), underlyingType))) + { + doCall = true; + } + else + doCall = false; } - else + } + + if (doCall) + { + auto paramType = moduleMethodInstance.mMethodInstance->GetParamType(0); + auto wantType = paramType; + if (wantType->IsRef()) + wantType = wantType->GetUnderlyingType(); + auto typedVal = methodMatcher.mArguments[0].mTypedValue; + if (wantType != typedVal.mType) { - methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator)); - if (paramType->IsRef()) + if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType))) { typedVal = MakeAddressable(typedVal); - typedVal.mKind = BfTypedValueKind_Addr; + methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())), + paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr); + } + else + { + methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator)); + if (paramType->IsRef()) + { + typedVal = MakeAddressable(typedVal); + typedVal.mKind = BfTypedValueKind_Addr; + } } } } } - result = exprEvaluator.CreateCall(&methodMatcher, BfTypedValue()); - if (resultFlags != NULL) + if (doCall) { - if (result.IsAddr()) - *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr); - if (result.mKind == BfTypedValueKind_TempAddr) - *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp); + result = exprEvaluator.CreateCall(&methodMatcher, BfTypedValue()); + if (resultFlags != NULL) + { + if (result.IsAddr()) + *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr); + if (result.mKind == BfTypedValueKind_TempAddr) + *resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp); + } + else if (result.IsAddr()) + result = LoadValue(result); + + if (result.mType != toType) + return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags); + + if (result) + return result.mValue; } - else if (result.IsAddr()) - result = LoadValue(result); - - if (result.mType != toType) - return CastToValue(srcNode, result, toType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator), resultFlags); - - if (result) - return result.mValue; } } diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 19fda2df..618b022a 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -1209,7 +1209,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp if (CanCast(initValue, varType)) { - if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface())) + if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()) && (!varType->IsVar())) { if (!IsInSpecializedSection()) { @@ -1260,7 +1260,11 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp mBfIRBuilder->CreateAlignedStore(initValue.mValue, localVar->mAddr, initValue.mType->mAlign); } - if ((varType->IsPointer()) || (varType->IsObjectOrInterface())) + if (varType->IsVar()) + { + checkResult = GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef); + } + else if ((varType->IsPointer()) || (varType->IsObjectOrInterface())) { checkResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType); } @@ -1841,8 +1845,12 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD { exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType); } - else + else if (resolvedType->IsVar()) { + exprEvaluator->mResult = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean), false, BfDefaultValueKind_Undef); + } + else + { // Always true if ((!IsInSpecializedSection()) && (!resolvedType->IsGenericParam())) Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' since a value of type '%s' can never be null",