Transition type checking to use WalkAST() infrastructure.
This commit is contained in:
24
ast.cpp
24
ast.cpp
@@ -249,3 +249,27 @@ Stmt *
|
|||||||
Optimize(Stmt *stmt) {
|
Optimize(Stmt *stmt) {
|
||||||
return (Stmt *)Optimize((ASTNode *)stmt);
|
return (Stmt *)Optimize((ASTNode *)stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ASTNode *
|
||||||
|
lTypeCheckNode(ASTNode *node, void *) {
|
||||||
|
return node->TypeCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ASTNode *
|
||||||
|
TypeCheck(ASTNode *root) {
|
||||||
|
return WalkAST(root, NULL, lTypeCheckNode, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
TypeCheck(Expr *expr) {
|
||||||
|
return (Expr *)TypeCheck((ASTNode *)expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Stmt *
|
||||||
|
TypeCheck(Stmt *stmt) {
|
||||||
|
return (Stmt *)TypeCheck((ASTNode *)stmt);
|
||||||
|
}
|
||||||
|
|||||||
24
ast.h
24
ast.h
@@ -113,8 +113,28 @@ typedef ASTNode * (* ASTPostCallBackFunc)(ASTNode *node, void *data);
|
|||||||
extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc,
|
extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc,
|
||||||
ASTPostCallBackFunc postFunc, void *data);
|
ASTPostCallBackFunc postFunc, void *data);
|
||||||
|
|
||||||
extern Expr *Optimize(Expr *);
|
/** Perform simple optimizations on the AST or portion thereof passed to
|
||||||
extern Stmt *Optimize(Stmt *);
|
this function, returning the resulting AST. */
|
||||||
extern ASTNode *Optimize(ASTNode *root);
|
extern ASTNode *Optimize(ASTNode *root);
|
||||||
|
|
||||||
|
/** Convenience version of Optimize() for Expr *s that returns an Expr *
|
||||||
|
(rather than an ASTNode *, which would require the caller to cast back
|
||||||
|
to an Expr *). */
|
||||||
|
extern Expr *Optimize(Expr *);
|
||||||
|
|
||||||
|
/** Convenience version of Optimize() for Expr *s that returns an Stmt *
|
||||||
|
(rather than an ASTNode *, which would require the caller to cast back
|
||||||
|
to a Stmt *). */
|
||||||
|
extern Stmt *Optimize(Stmt *);
|
||||||
|
|
||||||
|
/* Perform type-checking on the given AST (or portion of one), returning a
|
||||||
|
pointer to the root of the resulting AST. */
|
||||||
|
extern ASTNode *TypeCheck(ASTNode *root);
|
||||||
|
|
||||||
|
/* Convenience version of TypeCheck() for Expr *s that returns an Expr *. */
|
||||||
|
extern Expr *TypeCheck(Expr *);
|
||||||
|
|
||||||
|
/* Convenience version of TypeCheck() for Stmt *s that returns an Stmt *. */
|
||||||
|
extern Stmt *TypeCheck(Stmt *);
|
||||||
|
|
||||||
#endif // ISPC_AST_H
|
#endif // ISPC_AST_H
|
||||||
|
|||||||
2
decl.cpp
2
decl.cpp
@@ -381,7 +381,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (decl->initExpr != NULL &&
|
if (decl->initExpr != NULL &&
|
||||||
(decl->initExpr = decl->initExpr->TypeCheck()) != NULL &&
|
(decl->initExpr = TypeCheck(decl->initExpr)) != NULL &&
|
||||||
(decl->initExpr = Optimize(decl->initExpr)) != NULL &&
|
(decl->initExpr = Optimize(decl->initExpr)) != NULL &&
|
||||||
(init = dynamic_cast<ConstExpr *>(decl->initExpr)) == NULL) {
|
(init = dynamic_cast<ConstExpr *>(decl->initExpr)) == NULL) {
|
||||||
Error(decl->initExpr->pos, "Default value for parameter "
|
Error(decl->initExpr->pos, "Default value for parameter "
|
||||||
|
|||||||
71
expr.cpp
71
expr.cpp
@@ -142,7 +142,7 @@ lArrayToPointer(Expr *expr) {
|
|||||||
Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, expr->pos);
|
Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, expr->pos);
|
||||||
Expr *index = new IndexExpr(expr, zero, expr->pos);
|
Expr *index = new IndexExpr(expr, zero, expr->pos);
|
||||||
Expr *addr = new AddressOfExpr(index, expr->pos);
|
Expr *addr = new AddressOfExpr(index, expr->pos);
|
||||||
addr = addr->TypeCheck();
|
addr = TypeCheck(addr);
|
||||||
Assert(addr != NULL);
|
Assert(addr != NULL);
|
||||||
addr = Optimize(addr);
|
addr = Optimize(addr);
|
||||||
Assert(addr != NULL);
|
Assert(addr != NULL);
|
||||||
@@ -927,16 +927,11 @@ UnaryExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
UnaryExpr::TypeCheck() {
|
UnaryExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
const Type *type;
|
||||||
expr = expr->TypeCheck();
|
if (expr == NULL || (type = expr->GetType()) == NULL)
|
||||||
if (expr == NULL)
|
|
||||||
// something went wrong in type checking...
|
// something went wrong in type checking...
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const Type *type = expr->GetType();
|
|
||||||
if (type == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (op == PreInc || op == PreDec || op == PostInc || op == PostDec) {
|
if (op == PreInc || op == PreDec || op == PostInc || op == PostDec) {
|
||||||
if (type->IsConstType()) {
|
if (type->IsConstType()) {
|
||||||
Error(pos, "Can't assign to type \"%s\" on left-hand side of "
|
Error(pos, "Can't assign to type \"%s\" on left-hand side of "
|
||||||
@@ -1506,7 +1501,7 @@ BinaryExpr::Optimize() {
|
|||||||
inv[i] = 1.f / inv[i];
|
inv[i] = 1.f / inv[i];
|
||||||
Expr *einv = new ConstExpr(type1, inv, constArg1->pos);
|
Expr *einv = new ConstExpr(type1, inv, constArg1->pos);
|
||||||
Expr *e = new BinaryExpr(Mul, arg0, einv, pos);
|
Expr *e = new BinaryExpr(Mul, arg0, einv, pos);
|
||||||
e = e->TypeCheck();
|
e = ::TypeCheck(e);
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return ::Optimize(e);
|
return ::Optimize(e);
|
||||||
@@ -1529,7 +1524,7 @@ BinaryExpr::Optimize() {
|
|||||||
ExprList *args = new ExprList(arg1, arg1->pos);
|
ExprList *args = new ExprList(arg1, arg1->pos);
|
||||||
Expr *rcpCall = new FunctionCallExpr(rcpSymExpr, args,
|
Expr *rcpCall = new FunctionCallExpr(rcpSymExpr, args,
|
||||||
arg1->pos);
|
arg1->pos);
|
||||||
rcpCall = rcpCall->TypeCheck();
|
rcpCall = ::TypeCheck(rcpCall);
|
||||||
if (rcpCall == NULL)
|
if (rcpCall == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
rcpCall = ::Optimize(rcpCall);
|
rcpCall = ::Optimize(rcpCall);
|
||||||
@@ -1537,7 +1532,7 @@ BinaryExpr::Optimize() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Expr *ret = new BinaryExpr(Mul, arg0, rcpCall, pos);
|
Expr *ret = new BinaryExpr(Mul, arg0, rcpCall, pos);
|
||||||
ret = ret->TypeCheck();
|
ret = ::TypeCheck(ret);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return ::Optimize(ret);
|
return ::Optimize(ret);
|
||||||
@@ -1628,11 +1623,6 @@ BinaryExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
BinaryExpr::TypeCheck() {
|
BinaryExpr::TypeCheck() {
|
||||||
if (arg0 != NULL)
|
|
||||||
arg0 = arg0->TypeCheck();
|
|
||||||
if (arg1 != NULL)
|
|
||||||
arg1 = arg1->TypeCheck();
|
|
||||||
|
|
||||||
if (arg0 == NULL || arg1 == NULL)
|
if (arg0 == NULL || arg1 == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -2124,10 +2114,6 @@ lCheckForConstStructMember(SourcePos pos, const StructType *structType,
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
AssignExpr::TypeCheck() {
|
AssignExpr::TypeCheck() {
|
||||||
if (lvalue != NULL)
|
|
||||||
lvalue = lvalue->TypeCheck();
|
|
||||||
if (rvalue != NULL)
|
|
||||||
rvalue = rvalue->TypeCheck();
|
|
||||||
if (lvalue == NULL || rvalue == NULL)
|
if (lvalue == NULL || rvalue == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -2405,13 +2391,6 @@ SelectExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
SelectExpr::TypeCheck() {
|
SelectExpr::TypeCheck() {
|
||||||
if (test)
|
|
||||||
test = test->TypeCheck();
|
|
||||||
if (expr1)
|
|
||||||
expr1 = expr1->TypeCheck();
|
|
||||||
if (expr2)
|
|
||||||
expr2 = expr2->TypeCheck();
|
|
||||||
|
|
||||||
if (test == NULL || expr1 == NULL || expr2 == NULL)
|
if (test == NULL || expr1 == NULL || expr2 == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -2636,14 +2615,9 @@ FunctionCallExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
FunctionCallExpr::TypeCheck() {
|
FunctionCallExpr::TypeCheck() {
|
||||||
if (func != NULL)
|
if (func == NULL || args == NULL)
|
||||||
func = func->TypeCheck();
|
return NULL;
|
||||||
if (args != NULL)
|
|
||||||
args = args->TypeCheck();
|
|
||||||
if (launchCountExpr != NULL)
|
|
||||||
launchCountExpr = launchCountExpr->TypeCheck();
|
|
||||||
|
|
||||||
if (args != NULL && func != NULL) {
|
|
||||||
std::vector<const Type *> argTypes;
|
std::vector<const Type *> argTypes;
|
||||||
std::vector<bool> argCouldBeNULL;
|
std::vector<bool> argCouldBeNULL;
|
||||||
for (unsigned int i = 0; i < args->exprs.size(); ++i) {
|
for (unsigned int i = 0; i < args->exprs.size(); ++i) {
|
||||||
@@ -2759,7 +2733,6 @@ FunctionCallExpr::TypeCheck() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (func == NULL || args == NULL)
|
if (func == NULL || args == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -2834,9 +2807,6 @@ ExprList::Optimize() {
|
|||||||
|
|
||||||
ExprList *
|
ExprList *
|
||||||
ExprList::TypeCheck() {
|
ExprList::TypeCheck() {
|
||||||
for (unsigned int i = 0; i < exprs.size(); ++i)
|
|
||||||
if (exprs[i])
|
|
||||||
exprs[i] = exprs[i]->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3199,16 +3169,11 @@ IndexExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
IndexExpr::TypeCheck() {
|
IndexExpr::TypeCheck() {
|
||||||
if (baseExpr)
|
if (baseExpr == NULL || index == NULL || index->GetType() == NULL)
|
||||||
baseExpr = baseExpr->TypeCheck();
|
|
||||||
if (index)
|
|
||||||
index = index->TypeCheck();
|
|
||||||
|
|
||||||
if (!baseExpr || !index || !index->GetType())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
const Type *baseExprType = baseExpr->GetType();
|
const Type *baseExprType = baseExpr->GetType();
|
||||||
if (!baseExprType)
|
if (baseExprType == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!dynamic_cast<const SequentialType *>(baseExprType->GetReferenceTarget()) &&
|
if (!dynamic_cast<const SequentialType *>(baseExprType->GetReferenceTarget()) &&
|
||||||
@@ -3741,8 +3706,6 @@ MemberExpr::GetLValueType() const {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
MemberExpr::TypeCheck() {
|
MemberExpr::TypeCheck() {
|
||||||
if (expr)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
return expr ? this : NULL;
|
return expr ? this : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5268,7 +5231,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
|
Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(),
|
||||||
toPointerType) == true);
|
toPointerType) == true);
|
||||||
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos);
|
arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos);
|
||||||
arrayAsPtr = arrayAsPtr->TypeCheck();
|
arrayAsPtr = ::TypeCheck(arrayAsPtr);
|
||||||
Assert(arrayAsPtr != NULL);
|
Assert(arrayAsPtr != NULL);
|
||||||
arrayAsPtr = ::Optimize(arrayAsPtr);
|
arrayAsPtr = ::Optimize(arrayAsPtr);
|
||||||
Assert(arrayAsPtr != NULL);
|
Assert(arrayAsPtr != NULL);
|
||||||
@@ -5435,8 +5398,6 @@ lDeconstifyType(const Type *t) {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
TypeCastExpr::TypeCheck() {
|
TypeCastExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -5448,7 +5409,7 @@ TypeCastExpr::TypeCheck() {
|
|||||||
toType->IsVaryingType()) {
|
toType->IsVaryingType()) {
|
||||||
TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(),
|
TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(),
|
||||||
expr, false, pos);
|
expr, false, pos);
|
||||||
return tce->TypeCheck();
|
return ::TypeCheck(tce);
|
||||||
}
|
}
|
||||||
|
|
||||||
fromType = lDeconstifyType(fromType);
|
fromType = lDeconstifyType(fromType);
|
||||||
@@ -5699,8 +5660,6 @@ ReferenceExpr::Optimize() {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
ReferenceExpr::TypeCheck() {
|
ReferenceExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return this;
|
return this;
|
||||||
@@ -5797,8 +5756,6 @@ DereferenceExpr::GetType() const {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
DereferenceExpr::TypeCheck() {
|
DereferenceExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return this;
|
return this;
|
||||||
@@ -5896,8 +5853,6 @@ AddressOfExpr::Print() const {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
AddressOfExpr::TypeCheck() {
|
AddressOfExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5964,8 +5919,6 @@ SizeOfExpr::Print() const {
|
|||||||
|
|
||||||
Expr *
|
Expr *
|
||||||
SizeOfExpr::TypeCheck() {
|
SizeOfExpr::TypeCheck() {
|
||||||
if (expr != NULL)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
func.cpp
2
func.cpp
@@ -82,7 +82,7 @@ Function::Function(Symbol *s, const std::vector<Symbol *> &a, Stmt *c) {
|
|||||||
fprintf(stderr, "---------------------\n");
|
fprintf(stderr, "---------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
code = code->TypeCheck();
|
code = TypeCheck(code);
|
||||||
|
|
||||||
if (code != NULL && g->debugPrint) {
|
if (code != NULL && g->debugPrint) {
|
||||||
fprintf(stderr, "After typechecking function \"%s\":\n",
|
fprintf(stderr, "After typechecking function \"%s\":\n",
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ Module::AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst) {
|
|||||||
"global variable \"%s\".", sym->name.c_str());
|
"global variable \"%s\".", sym->name.c_str());
|
||||||
}
|
}
|
||||||
else if (initExpr != NULL) {
|
else if (initExpr != NULL) {
|
||||||
initExpr = initExpr->TypeCheck();
|
initExpr = TypeCheck(initExpr);
|
||||||
if (initExpr != NULL) {
|
if (initExpr != NULL) {
|
||||||
// We need to make sure the initializer expression is
|
// We need to make sure the initializer expression is
|
||||||
// the same type as the global. (But not if it's an
|
// the same type as the global. (But not if it's an
|
||||||
|
|||||||
2
parse.yy
2
parse.yy
@@ -1674,7 +1674,7 @@ static bool
|
|||||||
lGetConstantInt(Expr *expr, int *value, SourcePos pos, const char *usage) {
|
lGetConstantInt(Expr *expr, int *value, SourcePos pos, const char *usage) {
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return false;
|
return false;
|
||||||
expr = expr->TypeCheck();
|
expr = TypeCheck(expr);
|
||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return false;
|
return false;
|
||||||
expr = Optimize(expr);
|
expr = Optimize(expr);
|
||||||
|
|||||||
105
stmt.cpp
105
stmt.cpp
@@ -88,8 +88,6 @@ ExprStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
ExprStmt::TypeCheck() {
|
ExprStmt::TypeCheck() {
|
||||||
if (expr)
|
|
||||||
expr = expr->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,18 +418,13 @@ Stmt *
|
|||||||
DeclStmt::TypeCheck() {
|
DeclStmt::TypeCheck() {
|
||||||
bool encounteredError = false;
|
bool encounteredError = false;
|
||||||
for (unsigned int i = 0; i < vars.size(); ++i) {
|
for (unsigned int i = 0; i < vars.size(); ++i) {
|
||||||
if (!vars[i].sym) {
|
if (vars[i].sym == NULL) {
|
||||||
encounteredError = true;
|
encounteredError = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vars[i].init == NULL)
|
if (vars[i].init == NULL)
|
||||||
continue;
|
continue;
|
||||||
vars[i].init = vars[i].init->TypeCheck();
|
|
||||||
if (vars[i].init == NULL) {
|
|
||||||
encounteredError = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the right type for stuff like const float foo = 2; so that
|
// get the right type for stuff like const float foo = 2; so that
|
||||||
// the int->float type conversion is in there and we don't return
|
// the int->float type conversion is in there and we don't return
|
||||||
@@ -565,8 +558,6 @@ IfStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
IfStmt::TypeCheck() {
|
IfStmt::TypeCheck() {
|
||||||
if (test != NULL) {
|
|
||||||
test = test->TypeCheck();
|
|
||||||
if (test != NULL) {
|
if (test != NULL) {
|
||||||
const Type *testType = test->GetType();
|
const Type *testType = test->GetType();
|
||||||
if (testType != NULL) {
|
if (testType != NULL) {
|
||||||
@@ -579,11 +570,6 @@ IfStmt::TypeCheck() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (trueStmts != NULL)
|
|
||||||
trueStmts = trueStmts->TypeCheck();
|
|
||||||
if (falseStmts != NULL)
|
|
||||||
falseStmts = falseStmts->TypeCheck();
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -1122,31 +1108,30 @@ void DoStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
DoStmt::TypeCheck() {
|
DoStmt::TypeCheck() {
|
||||||
if (testExpr) {
|
const Type *testType;
|
||||||
testExpr = testExpr->TypeCheck();
|
if (testExpr != NULL && (testType = testExpr->GetType()) != NULL) {
|
||||||
if (testExpr) {
|
|
||||||
const Type *testType = testExpr->GetType();
|
|
||||||
if (testType) {
|
|
||||||
if (!testType->IsNumericType() && !testType->IsBoolType()) {
|
if (!testType->IsNumericType() && !testType->IsBoolType()) {
|
||||||
Error(testExpr->pos, "Type \"%s\" can't be converted to boolean for \"while\" "
|
Error(testExpr->pos, "Type \"%s\" can't be converted to boolean for \"while\" "
|
||||||
"test in \"do\" loop.", testExpr->GetType()->GetString().c_str());
|
"test in \"do\" loop.", testExpr->GetType()->GetString().c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should the test condition for the loop be uniform or
|
// Should the test condition for the loop be uniform or varying?
|
||||||
// varying? It can be uniform only if three conditions are
|
// It can be uniform only if three conditions are met:
|
||||||
// met. First and foremost, the type of the test condition
|
//
|
||||||
// must be uniform. Second, the user must not have set the
|
// - First and foremost, the type of the test condition must be
|
||||||
// dis-optimization option that disables uniform flow
|
// uniform.
|
||||||
// control.
|
//
|
||||||
|
// - Second, the user must not have set the dis-optimization option
|
||||||
|
// that disables uniform flow control.
|
||||||
|
//
|
||||||
|
// - Thirdly, and most subtlely, there must not be any break or
|
||||||
|
// continue statements inside the loop that are within the scope
|
||||||
|
// of a 'varying' if statement. If there are, then we type cast
|
||||||
|
// the test to be 'varying', so that the code generated for the
|
||||||
|
// loop includes masking stuff, so that we can track which lanes
|
||||||
|
// actually want to be running, accounting for breaks/continues.
|
||||||
//
|
//
|
||||||
// Thirdly, and most subtlely, there must not be any break
|
|
||||||
// or continue statements inside the loop that are within
|
|
||||||
// the scope of a 'varying' if statement. If there are,
|
|
||||||
// then we type cast the test to be 'varying', so that the
|
|
||||||
// code generated for the loop includes masking stuff, so
|
|
||||||
// that we can track which lanes actually want to be
|
|
||||||
// running, accounting for breaks/continues.
|
|
||||||
bool uniformTest = (testType->IsUniformType() &&
|
bool uniformTest = (testType->IsUniformType() &&
|
||||||
!g->opt.disableUniformControlFlow &&
|
!g->opt.disableUniformControlFlow &&
|
||||||
!lHasVaryingBreakOrContinue(bodyStmts));
|
!lHasVaryingBreakOrContinue(bodyStmts));
|
||||||
@@ -1154,11 +1139,7 @@ DoStmt::TypeCheck() {
|
|||||||
AtomicType::VaryingBool,
|
AtomicType::VaryingBool,
|
||||||
testExpr, false, testExpr->pos);
|
testExpr, false, testExpr->pos);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bodyStmts)
|
|
||||||
bodyStmts = bodyStmts->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,14 +1305,11 @@ ForStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
ForStmt::TypeCheck() {
|
ForStmt::TypeCheck() {
|
||||||
if (test) {
|
const Type *testType;
|
||||||
test = test->TypeCheck();
|
if (test && (testType = test->GetType()) != NULL) {
|
||||||
if (test) {
|
|
||||||
const Type *testType = test->GetType();
|
|
||||||
if (testType) {
|
|
||||||
if (!testType->IsNumericType() && !testType->IsBoolType()) {
|
if (!testType->IsNumericType() && !testType->IsBoolType()) {
|
||||||
Error(test->pos, "Type \"%s\" can't be converted to boolean for for loop test.",
|
Error(test->pos, "Type \"%s\" can't be converted to boolean for \"for\" "
|
||||||
test->GetType()->GetString().c_str());
|
"loop test.", test->GetType()->GetString().c_str());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,16 +1321,11 @@ ForStmt::TypeCheck() {
|
|||||||
test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool :
|
||||||
AtomicType::VaryingBool,
|
AtomicType::VaryingBool,
|
||||||
test, false, test->pos);
|
test, false, test->pos);
|
||||||
}
|
test = ::TypeCheck(test);
|
||||||
}
|
if (test == NULL)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init)
|
|
||||||
init = init->TypeCheck();
|
|
||||||
if (step)
|
|
||||||
step = step->TypeCheck();
|
|
||||||
if (stmts)
|
|
||||||
stmts = stmts->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1813,9 +1786,6 @@ Stmt *
|
|||||||
ForeachStmt::TypeCheck() {
|
ForeachStmt::TypeCheck() {
|
||||||
bool anyErrors = false;
|
bool anyErrors = false;
|
||||||
for (unsigned int i = 0; i < startExprs.size(); ++i) {
|
for (unsigned int i = 0; i < startExprs.size(); ++i) {
|
||||||
// Typecheck first, to resolve function overloads
|
|
||||||
if (startExprs[i] != NULL)
|
|
||||||
startExprs[i] = startExprs[i]->TypeCheck();
|
|
||||||
if (startExprs[i] != NULL)
|
if (startExprs[i] != NULL)
|
||||||
startExprs[i] = TypeConvertExpr(startExprs[i],
|
startExprs[i] = TypeConvertExpr(startExprs[i],
|
||||||
AtomicType::UniformInt32,
|
AtomicType::UniformInt32,
|
||||||
@@ -1823,18 +1793,12 @@ ForeachStmt::TypeCheck() {
|
|||||||
anyErrors |= (startExprs[i] == NULL);
|
anyErrors |= (startExprs[i] == NULL);
|
||||||
}
|
}
|
||||||
for (unsigned int i = 0; i < endExprs.size(); ++i) {
|
for (unsigned int i = 0; i < endExprs.size(); ++i) {
|
||||||
if (endExprs[i] != NULL)
|
|
||||||
endExprs[i] = endExprs[i]->TypeCheck();
|
|
||||||
if (endExprs[i] != NULL)
|
if (endExprs[i] != NULL)
|
||||||
endExprs[i] = TypeConvertExpr(endExprs[i], AtomicType::UniformInt32,
|
endExprs[i] = TypeConvertExpr(endExprs[i], AtomicType::UniformInt32,
|
||||||
"foreach ending value");
|
"foreach ending value");
|
||||||
anyErrors |= (endExprs[i] == NULL);
|
anyErrors |= (endExprs[i] == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stmts != NULL)
|
|
||||||
stmts = stmts->TypeCheck();
|
|
||||||
anyErrors |= (stmts == NULL);
|
|
||||||
|
|
||||||
if (startExprs.size() < dimVariables.size()) {
|
if (startExprs.size() < dimVariables.size()) {
|
||||||
Error(pos, "Not enough initial values provided for \"foreach\" loop; "
|
Error(pos, "Not enough initial values provided for \"foreach\" loop; "
|
||||||
"got %d, expected %d\n", (int)startExprs.size(), (int)dimVariables.size());
|
"got %d, expected %d\n", (int)startExprs.size(), (int)dimVariables.size());
|
||||||
@@ -1938,11 +1902,6 @@ ReturnStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
ReturnStmt::TypeCheck() {
|
ReturnStmt::TypeCheck() {
|
||||||
// FIXME: We don't have ctx->functionType available here; should we?
|
|
||||||
// We ned up needing to type conversion stuff in EmitCode() method via
|
|
||||||
// FunctionEmitContext::SetReturnValue as a result, which is kind of ugly...
|
|
||||||
if (val)
|
|
||||||
val = val->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1982,9 +1941,6 @@ StmtList::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
StmtList::TypeCheck() {
|
StmtList::TypeCheck() {
|
||||||
for (unsigned int i = 0; i < stmts.size(); ++i)
|
|
||||||
if (stmts[i])
|
|
||||||
stmts[i] = stmts[i]->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2194,8 +2150,6 @@ PrintStmt::Print(int indent) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
PrintStmt::TypeCheck() {
|
PrintStmt::TypeCheck() {
|
||||||
if (values)
|
|
||||||
values = values->TypeCheck();
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2270,11 +2224,8 @@ AssertStmt::Print(int indent) const {
|
|||||||
|
|
||||||
Stmt *
|
Stmt *
|
||||||
AssertStmt::TypeCheck() {
|
AssertStmt::TypeCheck() {
|
||||||
if (expr)
|
const Type *type;
|
||||||
expr = expr->TypeCheck();
|
if (expr && (type = expr->GetType()) != NULL) {
|
||||||
if (expr) {
|
|
||||||
const Type *type = expr->GetType();
|
|
||||||
if (type) {
|
|
||||||
bool isUniform = type->IsUniformType();
|
bool isUniform = type->IsUniformType();
|
||||||
if (!type->IsNumericType() && !type->IsBoolType()) {
|
if (!type->IsNumericType() && !type->IsBoolType()) {
|
||||||
Error(expr->pos, "Type \"%s\" can't be converted to boolean for \"assert\".",
|
Error(expr->pos, "Type \"%s\" can't be converted to boolean for \"assert\".",
|
||||||
@@ -2284,7 +2235,7 @@ AssertStmt::TypeCheck() {
|
|||||||
expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
|
expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool :
|
||||||
AtomicType::VaryingBool,
|
AtomicType::VaryingBool,
|
||||||
expr, false, expr->pos);
|
expr, false, expr->pos);
|
||||||
}
|
expr = ::TypeCheck(expr);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user