1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00
Beef/IDEHelper/Compiler/BfConstResolver.cpp

449 lines
14 KiB
C++
Raw Normal View History

2019-08-23 11:56:54 -07:00
#pragma warning(push)
#pragma warning(disable:4800)
#pragma warning(disable:4244)
#pragma warning(disable:4141)
#pragma warning(disable:4624)
#pragma warning(disable:4146)
#pragma warning(disable:4267)
#pragma warning(disable:4291)
#include "BfCompiler.h"
#include "BfConstResolver.h"
#include "BfAutoComplete.h"
#include "BfResolvePass.h"
#include "llvm/IR/GlobalVariable.h"
#include "BfExprEvaluator.h"
#pragma warning(pop)
USING_NS_BF;
using namespace llvm;
bool BfConstResolver::CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode)
{
if (typedValue.mValue.IsConst())
return true;
mModule->Fail("Expression does not evaluate to a constant value", refNode);
return false;
}
BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule)
{
mIsInvalidConstExpr = false;
}
BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags)
2021-02-25 10:14:22 -08:00
{
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
// Handle the 'int[?] val = .(1, 2, 3)' case
if ((flags & BfConstResolveFlag_ArrayInitSize) != 0)
{
if (auto uninitExpr = BfNodeDynCast<BfUninitializedExpression>(expr))
{
BfAstNode* initializer = NULL;
int arraySize = -1;
if (mModule->mContext->mCurTypeState != NULL)
{
if (mModule->mContext->mCurTypeState->mCurFieldDef != NULL)
2022-04-16 16:43:21 -07:00
initializer = mModule->mContext->mCurTypeState->mCurFieldDef->GetInitializer();
if (mModule->mContext->mCurTypeState->mCurVarInitializer != NULL)
initializer = mModule->mContext->mCurTypeState->mCurVarInitializer;
if (mModule->mContext->mCurTypeState->mArrayInitializerSize != -1)
arraySize = mModule->mContext->mCurTypeState->mArrayInitializerSize;
}
if (initializer != NULL)
{
if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(initializer))
{
if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(invocationExpr->mTarget))
{
// Dot-initialized
if (memberRefExpr->mTarget == NULL)
arraySize = (int)invocationExpr->mArguments.size();
2022-07-26 13:27:03 -04:00
}
else if (auto indexerExpr = BfNodeDynCast<BfIndexerExpression>(invocationExpr->mTarget))
{
2021-01-09 09:43:11 -08:00
if (indexerExpr->mArguments.size() == 0)
{
// Inferred-type sized array initializer
arraySize = (int)invocationExpr->mArguments.size();
2022-07-26 13:27:03 -04:00
}
}
}
}
if (arraySize != -1)
2022-07-26 13:27:03 -04:00
{
mResult = BfTypedValue(mModule->GetConstValue(arraySize), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
return mResult;
}
else
2022-07-26 13:27:03 -04:00
{
2020-12-23 08:53:38 -08:00
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_IntPtr)), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
return mResult;
}
}
}
2019-08-23 11:56:54 -07:00
bool explicitCast = (flags & BfConstResolveFlag_ExplicitCast) != 0;
bool noCast = (flags & BfConstResolveFlag_NoCast) != 0;
bool allowSoftFail = (flags & BfConstResolveFlag_AllowSoftFail) != 0;
bool wantIgnoreWrites = mModule->mBfIRBuilder->mIgnoreWrites;
/*if (BfNodeDynCastExact<BfTypeOfExpression>(expr) != NULL)
{
// Some specific expressions should be allowed to do writes like creating global variables
}
else*/
{
wantIgnoreWrites = true;
}
2021-01-15 14:28:21 -08:00
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, wantIgnoreWrites);
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
mNoBind = true;
if (wantType != NULL)
mExpectingType = wantType;
VisitChildNoRef(expr);
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
mResult = GetResult();
2022-07-26 13:27:03 -04:00
auto compilerVal = mModule->GetCompilerFieldValue(mResult);
if (compilerVal)
mResult = compilerVal;
2019-08-23 11:56:54 -07:00
if ((mResult) && (wantType != NULL))
{
auto typeInst = mResult.mType->ToTypeInstance();
if ((typeInst != NULL) && (typeInst->IsInstanceOf(mModule->mCompiler->mStringTypeDef)))
2019-08-23 11:56:54 -07:00
{
BfType* toType = wantType;
if (toType == NULL)
toType = mResult.mType;
if ((mResult.mValue.IsConst()) &&
(((toType->IsPointer()) && (toType->GetUnderlyingType() == mModule->GetPrimitiveType(BfTypeCode_Char8))) ||
(toType == mResult.mType)))
{
auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if (constant->mTypeCode == BfTypeCode_NullPtr)
{
return mModule->GetDefaultTypedValue(toType);
}
else
{
2022-07-26 13:27:03 -04:00
int stringId = mModule->GetStringPoolIdx(mResult.mValue);
if (stringId != -1)
{
2021-02-25 10:14:22 -08:00
if ((flags & BfConstResolveFlag_ActualizeValues) != 0)
{
2021-01-15 14:28:21 -08:00
prevIgnoreWrites.Restore();
mModule->mBfIRBuilder->PopulateType(mResult.mType);
2021-02-25 10:14:22 -08:00
return BfTypedValue(mModule->GetStringObjectValue(stringId, false, true), mResult.mType);
}
return BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId), toType);
}
2019-08-23 11:56:54 -07:00
}
}
}
if (noCast)
{
//
}
else if (allowSoftFail)
{
SetAndRestoreValue<bool> prevIgnoreFail(mModule->mIgnoreErrors, true);
auto convValue = mModule->Cast(expr, mResult, wantType, explicitCast ? BfCastFlags_Explicit : BfCastFlags_None);
if (convValue)
mResult = convValue;
}
else
2022-07-26 13:27:03 -04:00
{
2024-12-31 07:48:03 -08:00
mResult = mModule->Cast(expr, mResult, wantType, (BfCastFlags)(BfCastFlags_WantsConst | (explicitCast ? BfCastFlags_Explicit : BfCastFlags_None)));
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
}
if (mResult.mKind == BfTypedValueKind_GenericConstValue)
{
if ((mBfEvalExprFlags & BfEvalExprFlags_AllowGenericConstValue) != 0)
2019-08-23 11:56:54 -07:00
return mResult;
}
if (mResult)
{
bool isConst = mResult.mValue.IsConst();
if (isConst)
{
auto constant = mModule->mBfIRBuilder->GetConstant(mResult.mValue);
2024-12-02 08:28:24 -05:00
if ((constant->mTypeCode != BfTypeCode_StringId) && (mModule->HasStringId(mResult.mValue, mModule->mBfIRBuilder)))
{
mModule->Fail("Invalid usage of string constant", expr);
mResult = BfTypedValue();
}
else if ((constant->mConstType == BfConstType_GlobalVar) && ((flags & BfConstResolveFlag_AllowGlobalVariable) == 0))
2022-03-02 09:51:28 -08:00
{
int stringId = mModule->GetStringPoolIdx(mResult.mValue, mModule->mBfIRBuilder);
if (stringId != -1)
{
mResult.mValue = mModule->mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId);
}
else
isConst = false;
2024-12-02 08:28:24 -05:00
}
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
if ((!isConst) && ((mBfEvalExprFlags & BfEvalExprFlags_AllowNonConst) == 0))
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
mModule->Fail("Expression does not evaluate to a constant value", expr);
if (wantType != NULL)
mResult = mModule->GetDefaultTypedValue(wantType);
else
mResult = BfTypedValue();
}
}
else
{
if (wantType != NULL)
mResult = mModule->GetDefaultTypedValue(wantType);
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
if (prevInsertBlock)
mModule->mBfIRBuilder->SetInsertPoint(prevInsertBlock);
/*ignoreWrites.Restore();
if ((!mModule->mBfIRBuilder->mIgnoreWrites) && (prevInsertBlock))
{
BF_ASSERT(!prevInsertBlock.IsFake());
mModule->mBfIRBuilder->SetInsertPoint(prevInsertBlock);
}*/
2022-07-26 13:27:03 -04:00
mModule->FixIntUnknown(mResult);
2021-02-25 10:14:22 -08:00
if ((flags & BfConstResolveFlag_NoActualizeValues) == 0)
2021-11-23 15:01:10 -08:00
{
prevIgnoreWrites.Restore();
2021-02-25 10:14:22 -08:00
mModule->FixValueActualization(mResult, !prevIgnoreWrites.mPrevVal || ((flags & BfConstResolveFlag_ActualizeValues) != 0));
2021-11-23 15:01:10 -08:00
}
2019-08-23 11:56:54 -07:00
return mResult;
}
bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatcher* methodMatcher, Array<BfIRValue>& llvmArgs)
{
int argIdx = 0;
int paramIdx = 0;
int extendedParamIdx = 0;
SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
llvm::SmallVector<BfIRValue, 4> expandedParamsConstValues;
BfType* expandedParamsElementType = NULL;
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
// We don't do GetMethodInstance in mModule, because our module may not have init finished yet
//auto targetModule = methodMatcher->mBestMethodTypeInstance->mModule;
auto targetModule = mModule->mContext->mUnreifiedModule;
auto moduleMethodInstance = targetModule->GetMethodInstance(methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, methodMatcher->mBestMethodGenericArguments);
auto methodInstance = moduleMethodInstance.mMethodInstance;
if (methodInstance->mReturnType == NULL)
{
mModule->AssertErrorState();
return false;
}
auto methodDef = methodMatcher->mBestMethodDef;
auto& arguments = methodMatcher->mArguments;
mModule->AddDependency(methodInstance->mReturnType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
2022-07-26 13:27:03 -04:00
for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
2019-08-23 11:56:54 -07:00
{
auto paramType = methodInstance->GetParamType(paramIdx);
mModule->AddDependency(paramType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
}
while (true)
{
if (paramIdx >= (int)methodInstance->GetParamCount())
{
if (argIdx < (int)arguments.size())
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
BfAstNode* errorRef = arguments[methodInstance->GetParamCount()].mExpression;
if (errorRef->GetSourceData() == NULL)
errorRef = targetSrc;
mModule->Fail(StrFormat("Too many arguments. Expected %d fewer.", (int)arguments.size() - methodInstance->GetParamCount()), errorRef);
if (methodInstance->mMethodDef->mMethodDeclaration != NULL)
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->mMethodDeclaration);
return false;
}
break;
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
BfType* wantType = NULL;
if (expandedParamsElementType != NULL)
{
wantType = expandedParamsElementType;
}
else
{
wantType = methodInstance->GetParamType(paramIdx);
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params)
{
//TODO: Check to see if it's a direct array pass
bool isDirectPass = false;
if (argIdx < (int)arguments.size())
{
if (!arguments[argIdx].mTypedValue.mValue)
return false;
if (mModule->CanCast(arguments[argIdx].mTypedValue, wantType))
2019-08-23 11:56:54 -07:00
isDirectPass = true;
}
2024-11-20 09:30:05 -05:00
if ((!isDirectPass) && (wantType->IsArray()))
2019-08-23 11:56:54 -07:00
{
BfArrayType* arrayType = (BfArrayType*)wantType;
if (arrayType->IsIncomplete())
mModule->PopulateType(arrayType, BfPopulateType_DataAndMethods);
expandedParamsElementType = arrayType->mGenericTypeInfo->mTypeGenericArguments[0];
2019-08-23 11:56:54 -07:00
continue;
}
}
}
BfTypedValue argValue;
2019-08-23 11:56:54 -07:00
BfAstNode* argExpr = NULL;
if (argIdx < (int)arguments.size())
{
argExpr = arguments[argIdx].mExpression;
}
else
{
if (expandedParamsElementType != NULL)
break;
if ((argIdx >= (int)methodInstance->mDefaultValues.size()) || (!methodInstance->mDefaultValues[argIdx]))
{
BfAstNode* refNode = targetSrc;
if (arguments.size() > 0)
refNode = arguments.back().mExpression;
BfAstNode* prevNode = NULL;
#ifdef BF_AST_HAS_PARENT_MEMBER
if (auto attributeDirective = BfNodeDynCast<BfAttributeDirective>(targetSrc->mParent))
{
BF_ASSERT(mModule->mParentNodeEntry->mNode == attributeDirective);
}
#endif
if (mModule->mParentNodeEntry != NULL)
{
if (auto attributeDirective = BfNodeDynCast<BfAttributeDirective>(mModule->mParentNodeEntry->mNode))
{
if (attributeDirective->mCommas.size() > 0)
prevNode = attributeDirective->mCommas.back();
else
prevNode = attributeDirective->mCtorOpenParen;
if (attributeDirective->mCtorCloseParen != NULL)
refNode = attributeDirective->mCtorCloseParen;
}
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
auto autoComplete = GetAutoComplete();
if (autoComplete != NULL)
{
if (prevNode != NULL)
{
autoComplete->CheckEmptyStart(prevNode, wantType);
}
}
2022-07-26 13:27:03 -04:00
2021-01-11 09:41:43 -08:00
if (mModule->PreFail())
2022-02-11 08:12:30 -05:00
mModule->Fail(StrFormat("Not enough parameters specified. Expected %d more.", methodInstance->GetParamCount() - (int)arguments.size()), refNode);
2019-08-23 11:56:54 -07:00
return false;
}
auto foreignDefaultVal = methodInstance->mDefaultValues[argIdx];
2022-07-26 13:27:03 -04:00
auto foreignConst = methodInstance->GetOwner()->mConstHolder->GetConstant(foreignDefaultVal.mValue);
argValue = mModule->GetTypedValueFromConstant(foreignConst, methodInstance->GetOwner()->mConstHolder, foreignDefaultVal.mType);
2019-08-23 11:56:54 -07:00
}
if ((!argValue) && (argIdx < arguments.size()))
2019-08-23 11:56:54 -07:00
{
argValue = arguments[argIdx].mTypedValue;
auto& arg = arguments[argIdx];
if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0)
{
mExpectingType = arg.mExpectedType;
if (mExpectingType == NULL)
mExpectingType = wantType;
2019-08-23 11:56:54 -07:00
if (auto expr = BfNodeDynCast<BfExpression>(argExpr))
argValue = Resolve(expr, mExpectingType);
arg.mArgFlags = BfArgFlag_None;
}
2019-08-23 11:56:54 -07:00
}
2022-07-26 13:27:03 -04:00
2019-08-23 11:56:54 -07:00
if (!argValue)
return BfTypedValue();
if (argExpr != NULL)
{
2024-12-31 07:48:03 -08:00
argValue = mModule->Cast(argExpr, argValue, wantType, (BfCastFlags)(BfCastFlags_WantsConst));
2019-08-23 11:56:54 -07:00
if (!argValue)
return false;
}
if (!argValue)
{
mModule->Fail("Invalid expression type", argExpr);
return false;
}
if (expandedParamsElementType != NULL)
{
expandedParamsConstValues.push_back(argValue.mValue);
extendedParamIdx++;
}
else
2022-07-26 13:27:03 -04:00
{
2021-02-25 10:14:22 -08:00
bool requiresConst = false;
if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Mixin))
requiresConst = true;
if ((requiresConst) && (argValue.mValue.IsFake()) && (!argValue.mType->IsValuelessType()))
2022-07-26 13:27:03 -04:00
{
mModule->Fail("Expression does not evaluate to a constant value", argExpr);
}
2021-02-25 10:14:22 -08:00
if (!argValue.mType->IsVar())
{
if ((!requiresConst) || (argValue.mValue.IsConst()) || (argValue.mType->IsValuelessType()))
llvmArgs.push_back(argValue.mValue);
else
llvmArgs.push_back(mModule->GetDefaultValue(argValue.mType));
}
2019-08-23 11:56:54 -07:00
paramIdx++;
}
argIdx++;
}
if (expandedParamsElementType != NULL)
2022-07-26 13:27:03 -04:00
{
2019-08-23 11:56:54 -07:00
auto arrayType = mModule->mBfIRBuilder->GetSizedArrayType(mModule->mBfIRBuilder->MapType(expandedParamsElementType), (int)expandedParamsConstValues.size());
auto constArray = mModule->mBfIRBuilder->CreateConstAgg(arrayType, expandedParamsConstValues);
2019-08-23 11:56:54 -07:00
llvmArgs.push_back(constArray);
2022-07-26 13:27:03 -04:00
}
2019-08-23 11:56:54 -07:00
return true;
}