1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Added support for C-style vararg methods

This commit is contained in:
Brian Fiete 2020-02-11 07:34:47 -08:00
parent 89e6b0d577
commit 7741344fd2
16 changed files with 129 additions and 68 deletions

View file

@ -202,7 +202,7 @@ class BeFunctionType : public BeType
public:
String mName;
BeType* mReturnType;
std::vector<BeFunctionTypeParam> mParams;
Array<BeFunctionTypeParam> mParams;
bool mIsVarArg;
virtual void HashContent(BeHashContext& hashCtx) override

View file

@ -1960,6 +1960,14 @@ String BeModule::ToString(BeFunction* wantFunc)
dc.mSeenNames[param.mName] = 0;
str += "%" + param.mName;
}
if (funcType->mIsVarArg)
{
if (!funcType->mParams.IsEmpty())
str += ", ";
str += "...";
}
str += ")";
if (func->mAlwaysInline)
@ -2917,6 +2925,14 @@ void BeModule::ToString(StringImpl& str, BeType* type)
str += ", ";
ToString(str, funcType->mParams[paramIdx].mType);
}
if (funcType->mIsVarArg)
{
if (!funcType->mParams.IsEmpty())
str += ", ";
str += "...";
}
str += ")";
return;
}

View file

@ -211,7 +211,7 @@ void BfStructuralVisitor::Visit(BfQualifiedTypeReference* qualifiedTypeRef)
Visit(qualifiedTypeRef->ToBase());
}
void BfStructuralVisitor::Visit(BfDotTypeReference * typeRef)
void BfStructuralVisitor::Visit(BfDotTypeReference* typeRef)
{
Visit(typeRef->ToBase());
}
@ -1411,6 +1411,8 @@ const char* Beefy::BfTokenToString(BfToken token)
return ".";
case BfToken_DotDot:
return "..";
case BfToken_DotDotDot:
return "...";
case BfToken_QuestionDot:
return "?.";
case BfToken_QuestionLBracket:

View file

@ -215,6 +215,7 @@ enum BfToken : uint8
BfToken_Comma,
BfToken_Dot,
BfToken_DotDot,
BfToken_DotDotDot,
BfToken_QuestionDot,
BfToken_QuestionLBracket,
BfToken_AutocompleteDot,

View file

@ -597,7 +597,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
bool didDefaultsError = false;
bool hadParams = false;
bool hasDefault = false;
for (int paramIdx = 0; paramIdx < (int) methodDeclaration->mParams.size(); paramIdx++)
for (int paramIdx = 0; paramIdx < (int)methodDeclaration->mParams.size(); paramIdx++)
{
BfParameterDeclaration* paramDecl = methodDeclaration->mParams[paramIdx];
@ -612,6 +612,17 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
else //
paramDef->mParamKind = BfParamKind_Params;
if (auto dotTypeRef = BfNodeDynCast<BfDotTypeReference>(paramDef->mTypeRef))
{
if (dotTypeRef->mDotToken->mToken == BfToken_DotDotDot)
{
if (paramIdx == (int)methodDeclaration->mParams.size() - 1)
paramDef->mParamKind = BfParamKind_VarArgs;
else
Fail("Varargs specifier must be the last parameter", methodDef->mParams[paramIdx - 1]->mParamDeclaration);
}
}
if (paramDef->mParamDeclaration != NULL)
{
if (paramDef->mParamKind == BfParamKind_Params)

View file

@ -1435,10 +1435,10 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
}
}
//TODO: Does this ever get hit?
// Not enough arguments?
// Too many arguments (not all incoming arguments processed)
if (argIdx < (int)mArguments.size())
{
if (!methodInstance->IsVarArgs())
goto NoMatch;
}
@ -4431,8 +4431,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
argIdx++;
}
int paramCount = methodInstance->GetParamCount();
for ( ; argIdx < (int)irArgs.size(); /*argIdx++*/)
{
if (argIdx >= paramCount)
break;
auto _HandleParamType = [&] (BfType* paramType)
{
if (paramType->IsStruct())
@ -4986,6 +4991,31 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (paramIdx >= (int)methodInstance->GetParamCount())
{
if (methodInstance->IsVarArgs())
{
if (argIdx >= (int)argValues.size())
break;
BfTypedValue argValue = ResolveArgValue(argValues[argIdx], NULL);
if (argValue)
{
auto typeInst = argValue.mType->ToTypeInstance();
if (argValue.mType == mModule->GetPrimitiveType(BfTypeCode_Single))
argValue = mModule->Cast(argValues[argIdx].mExpression, argValue, mModule->GetPrimitiveType(BfTypeCode_Double));
if ((typeInst != NULL) && (typeInst->mTypeDef == mModule->mCompiler->mStringTypeDef))
{
BfType* charType = mModule->GetPrimitiveType(BfTypeCode_Char8);
BfType* charPtrType = mModule->CreatePointerType(charType);
argValue = mModule->Cast(argValues[argIdx].mExpression, argValue, charPtrType);
}
PushArg(argValue, irArgs, true, false);
}
argIdx++;
continue;
}
if (argIdx < (int)argValues.size())
{
BfAstNode* errorRef = argValues[argIdx].mExpression;
@ -5632,41 +5662,10 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
BfEvalExprFlags flags = BfEvalExprFlags_NoCast;
if ((paramKind == BfParamKind_Params) || (paramKind == BfParamKind_DelegateParam))
flags = (BfEvalExprFlags)(flags | BfEvalExprFlags_AllowParamsExpr);
// if ((mModule->mCurMethodInstance->mHadGenericDelegateParams) && (!mModule->mCurMethodInstance->mIsUnspecialized))
// flags = (BfEvalExprFlags)(flags | BfEvalExprFlags_AllowParamsExpr);
argValue = mModule->CreateValueFromExpression(exprEvaluator, expr, wantType, flags);
// if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
// {
// if ((mModule->mCurMethodState != NULL) && (exprEvaluator.mResultLocalVar != NULL) && (exprEvaluator.mResultLocalVarRefNode != NULL))
// {
// auto localVar = exprEvaluator.mResultLocalVar;
// int fieldIdx = mResultLocalVarField - 1;
// auto methodState = mModule->mCurMethodState->GetMethodStateForLocal(localVar);
// if (localVar->mCompositeCount >= 0)
// {
// for (int compositeIdx = 0; compositeIdx < localVar->mCompositeCount; compositeIdx++)
// {
// BfResolvedArg compositeResolvedArg;
// auto compositeLocalVar = methodState->mLocals[localVar->mLocalVarIdx + compositeIdx + 1];
// auto argValue = exprEvaluator.LoadLocal(compositeLocalVar);
// if (argValue)
// {
// if (argValue.mType->IsRef())
// argValue.mKind = BfTypedValueKind_Value;
// else if (!argValue.mType->IsStruct())
// argValue = mModule->LoadValue(argValue, NULL, exprEvaluator.mIsVolatileReference);
// }
// resolvedArg.mTypedValue = argValue;
// resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_FromParamComposite);
// return resolvedArg.mTypedValue;
// }
// }
// }
// }
if ((argValue) && (argValue.mType != wantType))
if ((argValue) && (argValue.mType != wantType) && (wantType != NULL))
{
if ((mDeferScopeAlloc != NULL) && (wantType == mModule->mContext->mBfObjectType))
{
@ -5686,7 +5685,7 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
auto expr = BfNodeDynCast<BfExpression>(resolvedArg.mExpression);
BF_ASSERT(expr != NULL);
argValue = mModule->CreateValueFromExpression(expr, wantType, (BfEvalExprFlags)(BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr));
if (argValue)
if ((argValue) && (wantType != NULL))
argValue = mModule->Cast(expr, argValue, wantType);
}
else if ((resolvedArg.mArgFlags & (BfArgFlag_UntypedDefault)) != 0)
@ -5748,8 +5747,6 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
CheckVariableDeclaration(resolvedArg.mExpression, false, false, false);
argValue = BfTypedValue(localVar->mAddr, mModule->CreateRefType(variableType, BfRefType::RefKind_Out));
//argValue = mModule->GetDefaultTypedValue(wantType);
}
return argValue;
}

View file

@ -4257,7 +4257,7 @@ BfIRFunctionType BfIRBuilder::MapMethod(BfMethodInstance* methodInstance)
SizedArray<BfIRType, 8> paramTypes;
methodInstance->GetIRFunctionInfo(mModule, retType, paramTypes);
auto funcType = CreateFunctionType(retType, paramTypes, false);
auto funcType = CreateFunctionType(retType, paramTypes, methodInstance->IsVarArgs());
if (useCache)
mMethodTypeMap[methodInstance] = funcType;

View file

@ -8794,6 +8794,11 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
if (mCompiler->IsSkippingExtraResolveChecks())
return BfIRValue();
if (methodInstance->mMethodDef->mName == "Check")
{
NOP;
}
if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface())
{
//BF_ASSERT(!methodInstance->mIRFunction);
@ -8841,7 +8846,7 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
BfIRType returnType;
SizedArray<BfIRType, 8> paramTypes;
methodInstance->GetIRFunctionInfo(this, returnType, paramTypes);
auto funcType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes);
auto funcType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs());
auto func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName);
auto callingConv = GetIRCallingConvention(methodInstance);
@ -13859,7 +13864,7 @@ BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, b
SizedArray<BfIRType, 8> paramTypes;
methodInstance->GetIRFunctionInfo(this, returnType, paramTypes);
BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, false);
BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs());
auto ptrType = mBfIRBuilder->GetPointerTo(externFunctionType);
BfIRValue initVal;
@ -13907,14 +13912,14 @@ void BfModule::CreateDllImportMethod()
BfIRType returnType;
SizedArray<BfIRType, 8> paramTypes;
mCurMethodInstance->GetIRFunctionInfo(this, returnType, paramTypes);
mCurMethodInstance->GetIRFunctionInfo(this, returnType, paramTypes, mCurMethodInstance->IsVarArgs());
SizedArray<BfIRValue, 8> args;
for (int i = 0; i < (int)paramTypes.size(); i++)
args.push_back(mBfIRBuilder->GetArgument(i));
BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, false);
BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, mCurMethodInstance->IsVarArgs());
if (isHotCompile)
{
@ -18115,7 +18120,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth
BfIRFunctionType funcType;
auto voidType = GetPrimitiveType(BfTypeCode_None);
SizedArray<BfIRType, 0> paramTypes;
funcType = mBfIRBuilder->CreateFunctionType(mBfIRBuilder->MapType(voidType), paramTypes, false);
funcType = mBfIRBuilder->CreateFunctionType(mBfIRBuilder->MapType(voidType), paramTypes, methodInstance->IsVarArgs());
mBfIRBuilder->SaveDebugLocation();
auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
@ -19229,6 +19234,9 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
if (hadParams)
break;
if ((paramDef != NULL) && (paramDef->mParamKind == BfParamKind_VarArgs))
continue;
if ((paramDef != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) &&
(paramDef->mParamKind != BfParamKind_AppendIdx))
mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(paramDef->mTypeRef, false);

View file

@ -6470,7 +6470,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
if (auto dotType = BfNodeDynCastExact<BfDotTypeReference>(typeRef))
{
Fail("Invalid use of '.'", typeRef);
Fail(StrFormat("Invalid use of '%s'", BfTokenToString(dotType->mDotToken->mToken)), typeRef);
return NULL;
}

View file

@ -2067,12 +2067,22 @@ void BfParser::NextToken(int endIdx)
break;
case '.':
if (mSrc[mSrcIdx] == '.')
{
if (mSrc[mSrcIdx + 1] == '.')
{
mSrcIdx += 2;
mTokenEnd = mSrcIdx;
mToken = BfToken_DotDotDot;
mSyntaxToken = BfSyntaxToken_Token;
}
else
{
mSrcIdx++;
mTokenEnd = mSrcIdx;
mToken = BfToken_DotDot;
mSyntaxToken = BfSyntaxToken_Token;
}
}
else
{
mToken = BfToken_Dot;

View file

@ -4446,7 +4446,15 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
dotTypeRef->mDotToken = tokenNode;
firstNode = dotTypeRef;
isHandled = true;
//return dotTypeRef;
}
else if (token == BfToken_DotDotDot)
{
auto dotTypeRef = mAlloc->Alloc<BfDotTypeReference>();
ReplaceNode(firstNode, dotTypeRef);
dotTypeRef->mDotToken = tokenNode;
firstNode = dotTypeRef;
isHandled = true;
return dotTypeRef;
}
else if ((token == BfToken_Star) && (mAllowTypeWildcard))
{
@ -8402,7 +8410,8 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
(token == BfToken_Out) || (token == BfToken_Ref) || (token == BfToken_Mut) ||
(token == BfToken_Delegate) || (token == BfToken_Function) ||
(token == BfToken_Params) || (token == BfToken_LParen) ||
(token == BfToken_Var) || (token == BfToken_LBracket)))
(token == BfToken_Var) || (token == BfToken_LBracket) ||
(token == BfToken_DotDotDot)))
{
// These get picked up below
}
@ -8453,7 +8462,8 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
{
BfToken token = tokenNode->GetToken();
if ((token == BfToken_Var) || (token == BfToken_LParen) ||
(token == BfToken_Delegate) || (token == BfToken_Function))
(token == BfToken_Delegate) || (token == BfToken_Function) ||
(token == BfToken_DotDotDot))
{
mVisitorPos.MoveNext();
typeRef = CreateTypeRef(tokenNode);
@ -8517,6 +8527,9 @@ BfTokenNode* BfReducer::ParseMethodParams(BfAstNode* node, SizedArrayImpl<BfPara
MEMBER_SET(paramDecl, mModToken, modTokenNode);
}
if ((tokenNode != NULL) && (tokenNode->mToken == BfToken_DotDotDot))
continue;
bool allowNameFail = false;
bool nextIsName = false;
auto afterNameTokenNode = BfNodeDynCast<BfTokenNode>(mVisitorPos.Get(mVisitorPos.mReadPos + 2));

View file

@ -216,7 +216,6 @@ public:
BfTypeReference* CreateTypeRef(BfAstNode* identifierNode, CreateTypeRefFlags createTypeRefFlags = CreateTypeRefFlags_None);
BfTypeReference* CreateTypeRefAfter(BfAstNode* astNode, CreateTypeRefFlags createTypeRefFlags = CreateTypeRefFlags_None);
BfTypeReference* CreateRefTypeRef(BfTypeReference* elementType, BfTokenNode* refToken);
BfTypeReference* CreateConstTypeRef(BfTypeReference* elementType, BfTokenNode* refToken);
bool ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayImpl<BfParameterDeclaration*>* params, SizedArrayImpl<BfTokenNode*>* commas, bool alwaysIncludeBlock = false);
BfGenericArgumentsNode* CreateGenericArguments(BfTokenNode* tokenNode);
BfGenericParamsDeclaration* CreateGenericParamsDeclaration(BfTokenNode* tokenNode);

View file

@ -628,6 +628,13 @@ bool BfMethodInstance::IsSkipCall(bool bypassVirtual)
return false;
}
bool BfMethodInstance::IsVarArgs()
{
if (mMethodDef->mParams.IsEmpty())
return false;
return mMethodDef->mParams.back()->mParamKind == BfParamKind_VarArgs;
}
bool BfMethodInstance::AlwaysInline()
{
return mAlwaysInline;
@ -856,11 +863,6 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
{
if ((mMethodDef->mNoSplat) && (GetOwner()->GetLoweredType() != BfTypeCode_None))
{
NOP;
}
module->PopulateType(mReturnType);
if (mReturnType->IsValuelessType())
{

View file

@ -810,6 +810,7 @@ public:
bool HasSelf();
bool IsAutocompleteMethod() { /*return mIdHash == -1;*/ return mIsAutocompleteMethod; }
bool IsSkipCall(bool bypassVirtual = false);
bool IsVarArgs();
bool AlwaysInline();
BfImportCallKind GetImportCallKind();
bool IsTestMethod();

View file

@ -456,6 +456,7 @@ enum BfParamKind : uint8
BfParamKind_DelegateParam,
BfParamKind_ImplicitCapture,
BfParamKind_AppendIdx,
BfParamKind_VarArgs
};
class BfParameterDef