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:
Matt Pharr
2011-10-29 10:46:59 -07:00
parent cc298cd5fe
commit d5a8538192
6 changed files with 555 additions and 527 deletions

975
expr.cpp

File diff suppressed because it is too large Load Diff

19
expr.h
View File

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

View File

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

View File

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

View File

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

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