Move logic for resolving function call overloads.
This code previously lived in FunctionCallExpr but is now part of FunctionSymbolExpr. This change doesn't change any current functionality, but lays groundwork for function pointers in the language, where we'll want to do function call overload resolution at other times besides when a function call is actually being made.
This commit is contained in:
19
expr.h
19
expr.h
@@ -42,8 +42,6 @@
|
||||
#include "ast.h"
|
||||
#include "type.h"
|
||||
|
||||
class FunctionSymbolExpr;
|
||||
|
||||
/** @brief Expr is the abstract base class that defines the interface that
|
||||
all expression types must implement.
|
||||
*/
|
||||
@@ -266,10 +264,6 @@ public:
|
||||
ExprList *args;
|
||||
bool isLaunch;
|
||||
Expr *launchCountExpr;
|
||||
|
||||
private:
|
||||
void resolveFunctionOverloads(bool exactMatchOnly);
|
||||
bool tryResolve(int (*matchFunc)(Expr *, const Type *));
|
||||
};
|
||||
|
||||
|
||||
@@ -495,7 +489,8 @@ private:
|
||||
probably-different type. */
|
||||
class TypeCastExpr : public Expr {
|
||||
public:
|
||||
TypeCastExpr(const Type *t, Expr *e, SourcePos p);
|
||||
TypeCastExpr(const Type *t, Expr *e, bool preserveUniformity,
|
||||
SourcePos p);
|
||||
|
||||
llvm::Value *GetValue(FunctionEmitContext *ctx) const;
|
||||
const Type *GetType() const;
|
||||
@@ -506,6 +501,7 @@ public:
|
||||
|
||||
const Type *type;
|
||||
Expr *expr;
|
||||
bool preserveUniformity;
|
||||
};
|
||||
|
||||
|
||||
@@ -581,8 +577,12 @@ public:
|
||||
void Print() const;
|
||||
int EstimateCost() const;
|
||||
|
||||
bool ResolveOverloads(const std::vector<Expr *> &args);
|
||||
Symbol *GetMatchingFunction();
|
||||
|
||||
private:
|
||||
friend class FunctionCallExpr;
|
||||
bool tryResolve(int (*matchFunc)(Expr *, const Type *),
|
||||
const std::vector<Expr *> &args);
|
||||
|
||||
/** Name of the function that is being called. */
|
||||
std::string name;
|
||||
@@ -592,8 +592,7 @@ private:
|
||||
overload is the best match. */
|
||||
std::vector<Symbol *> *candidateFunctions;
|
||||
|
||||
/** The actual matching function found after overload resolution; this
|
||||
value is set by FunctionCallExpr::resolveFunctionOverloads() */
|
||||
/** The actual matching function found after overload resolution. */
|
||||
Symbol *matchingFunc;
|
||||
};
|
||||
|
||||
|
||||
14
parse.yy
14
parse.yy
@@ -326,19 +326,13 @@ cast_expression
|
||||
: unary_expression
|
||||
| '(' type_name ')' cast_expression
|
||||
{
|
||||
// If type_name isn't explicitly a varying, We do a GetUniform()
|
||||
// call here so that things like:
|
||||
// Pass true here to try to preserve uniformity
|
||||
// so that things like:
|
||||
// uniform int y = ...;
|
||||
// uniform float x = 1. / (float)y;
|
||||
// don't issue an error due to (float)y being inadvertently
|
||||
// and undesirably-to-the-user "varying"...
|
||||
if ($2 == NULL || $4 == NULL || $4->GetType() == NULL)
|
||||
$$ = NULL;
|
||||
else {
|
||||
if ($4->GetType()->IsUniformType())
|
||||
$2 = $2->GetAsUniformType();
|
||||
$$ = new TypeCastExpr($2, $4, @1);
|
||||
}
|
||||
$$ = new TypeCastExpr($2, $4, true, @1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1463,7 +1457,7 @@ lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
|
||||
the actual enum type here and optimize it, which will have
|
||||
us end up with a ConstExpr with the desired EnumType... */
|
||||
Expr *castExpr = new TypeCastExpr(enumType, enums[i]->constValue,
|
||||
enums[i]->pos);
|
||||
false, enums[i]->pos);
|
||||
castExpr = castExpr->Optimize();
|
||||
enums[i]->constValue = dynamic_cast<ConstExpr *>(castExpr);
|
||||
assert(enums[i]->constValue != NULL);
|
||||
|
||||
17
stmt.cpp
17
stmt.cpp
@@ -519,15 +519,16 @@ Stmt *IfStmt::TypeCheck() {
|
||||
if (test) {
|
||||
const Type *testType = test->GetType();
|
||||
if (testType) {
|
||||
bool isUniform = testType->IsUniformType() && !g->opt.disableUniformControlFlow;
|
||||
bool isUniform = (testType->IsUniformType() &&
|
||||
!g->opt.disableUniformControlFlow);
|
||||
if (!testType->IsNumericType() && !testType->IsBoolType()) {
|
||||
Error(test->pos, "Type \"%s\" can't be converted to boolean for \"if\" test.",
|
||||
testType->GetString().c_str());
|
||||
Error(test->pos, "Type \"%s\" can't be converted to boolean "
|
||||
"for \"if\" test.", testType->GetString().c_str());
|
||||
return NULL;
|
||||
}
|
||||
test = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
test, test->pos);
|
||||
test, false, test->pos);
|
||||
assert(test);
|
||||
}
|
||||
}
|
||||
@@ -1171,7 +1172,7 @@ DoStmt::TypeCheck() {
|
||||
!lHasVaryingBreakOrContinue(bodyStmts));
|
||||
testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
testExpr, testExpr->pos);
|
||||
testExpr, false, testExpr->pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1373,7 +1374,7 @@ ForStmt::TypeCheck() {
|
||||
!lHasVaryingBreakOrContinue(stmts));
|
||||
test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
test, test->pos);
|
||||
test, false, test->pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1685,7 +1686,7 @@ lProcessPrintArg(Expr *expr, FunctionEmitContext *ctx, std::string &argTypes) {
|
||||
baseType == AtomicType::UniformUInt16) {
|
||||
expr = new TypeCastExpr(type->IsUniformType() ? AtomicType::UniformInt32 :
|
||||
AtomicType::VaryingInt32,
|
||||
expr, expr->pos);
|
||||
expr, false, expr->pos);
|
||||
type = expr->GetType();
|
||||
}
|
||||
|
||||
@@ -1908,7 +1909,7 @@ AssertStmt::TypeCheck() {
|
||||
}
|
||||
expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
|
||||
AtomicType::VaryingBool,
|
||||
expr, expr->pos);
|
||||
expr, false, expr->pos);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
9
type.cpp
9
type.cpp
@@ -1887,6 +1887,15 @@ FunctionType::SetArgumentDefaults(const std::vector<ConstExpr *> &d) const {
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
FunctionType::GetArgumentName(int i) const {
|
||||
if (i >= (int)argNames.size())
|
||||
return "";
|
||||
else
|
||||
return argNames[i];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
|
||||
|
||||
2
type.h
2
type.h
@@ -677,7 +677,7 @@ public:
|
||||
|
||||
const std::vector<const Type *> &GetArgumentTypes() const { return argTypes; }
|
||||
const std::vector<ConstExpr *> &GetArgumentDefaults() const { return argDefaults; }
|
||||
const std::string &GetArgumentName(int i) const { return argNames[i]; }
|
||||
std::string GetArgumentName(int i) const;
|
||||
|
||||
/** @todo It would be nice to pull this information together and pass
|
||||
it when the constructor is called; it's kind of ugly to set it like
|
||||
|
||||
Reference in New Issue
Block a user