diff --git a/ast.cpp b/ast.cpp index b375f333..81070eab 100644 --- a/ast.cpp +++ b/ast.cpp @@ -249,3 +249,27 @@ Stmt * Optimize(Stmt *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); +} diff --git a/ast.h b/ast.h index 161f4cde..68fc9a03 100644 --- a/ast.h +++ b/ast.h @@ -113,8 +113,28 @@ typedef ASTNode * (* ASTPostCallBackFunc)(ASTNode *node, void *data); extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc, void *data); -extern Expr *Optimize(Expr *); -extern Stmt *Optimize(Stmt *); +/** Perform simple optimizations on the AST or portion thereof passed to + this function, returning the resulting AST. */ 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 diff --git a/decl.cpp b/decl.cpp index 11a665de..59c79302 100644 --- a/decl.cpp +++ b/decl.cpp @@ -381,7 +381,7 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const { } if (decl->initExpr != NULL && - (decl->initExpr = decl->initExpr->TypeCheck()) != NULL && + (decl->initExpr = TypeCheck(decl->initExpr)) != NULL && (decl->initExpr = Optimize(decl->initExpr)) != NULL && (init = dynamic_cast(decl->initExpr)) == NULL) { Error(decl->initExpr->pos, "Default value for parameter " diff --git a/expr.cpp b/expr.cpp index 359abb04..ade233f1 100644 --- a/expr.cpp +++ b/expr.cpp @@ -142,7 +142,7 @@ lArrayToPointer(Expr *expr) { Expr *zero = new ConstExpr(AtomicType::UniformInt32, 0, expr->pos); Expr *index = new IndexExpr(expr, zero, expr->pos); Expr *addr = new AddressOfExpr(index, expr->pos); - addr = addr->TypeCheck(); + addr = TypeCheck(addr); Assert(addr != NULL); addr = Optimize(addr); Assert(addr != NULL); @@ -927,16 +927,11 @@ UnaryExpr::Optimize() { Expr * UnaryExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); - if (expr == NULL) + const Type *type; + if (expr == NULL || (type = expr->GetType()) == NULL) // something went wrong in type checking... return NULL; - const Type *type = expr->GetType(); - if (type == NULL) - return NULL; - if (op == PreInc || op == PreDec || op == PostInc || op == PostDec) { if (type->IsConstType()) { 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]; Expr *einv = new ConstExpr(type1, inv, constArg1->pos); Expr *e = new BinaryExpr(Mul, arg0, einv, pos); - e = e->TypeCheck(); + e = ::TypeCheck(e); if (e == NULL) return NULL; return ::Optimize(e); @@ -1529,7 +1524,7 @@ BinaryExpr::Optimize() { ExprList *args = new ExprList(arg1, arg1->pos); Expr *rcpCall = new FunctionCallExpr(rcpSymExpr, args, arg1->pos); - rcpCall = rcpCall->TypeCheck(); + rcpCall = ::TypeCheck(rcpCall); if (rcpCall == NULL) return NULL; rcpCall = ::Optimize(rcpCall); @@ -1537,7 +1532,7 @@ BinaryExpr::Optimize() { return NULL; Expr *ret = new BinaryExpr(Mul, arg0, rcpCall, pos); - ret = ret->TypeCheck(); + ret = ::TypeCheck(ret); if (ret == NULL) return NULL; return ::Optimize(ret); @@ -1628,11 +1623,6 @@ BinaryExpr::Optimize() { Expr * BinaryExpr::TypeCheck() { - if (arg0 != NULL) - arg0 = arg0->TypeCheck(); - if (arg1 != NULL) - arg1 = arg1->TypeCheck(); - if (arg0 == NULL || arg1 == NULL) return NULL; @@ -2124,10 +2114,6 @@ lCheckForConstStructMember(SourcePos pos, const StructType *structType, Expr * AssignExpr::TypeCheck() { - if (lvalue != NULL) - lvalue = lvalue->TypeCheck(); - if (rvalue != NULL) - rvalue = rvalue->TypeCheck(); if (lvalue == NULL || rvalue == NULL) return NULL; @@ -2405,13 +2391,6 @@ SelectExpr::Optimize() { Expr * SelectExpr::TypeCheck() { - if (test) - test = test->TypeCheck(); - if (expr1) - expr1 = expr1->TypeCheck(); - if (expr2) - expr2 = expr2->TypeCheck(); - if (test == NULL || expr1 == NULL || expr2 == NULL) return NULL; @@ -2636,128 +2615,122 @@ FunctionCallExpr::Optimize() { Expr * FunctionCallExpr::TypeCheck() { - if (func != NULL) - func = func->TypeCheck(); - if (args != NULL) - args = args->TypeCheck(); - if (launchCountExpr != NULL) - launchCountExpr = launchCountExpr->TypeCheck(); + if (func == NULL || args == NULL) + return NULL; - if (args != NULL && func != NULL) { - std::vector argTypes; - std::vector argCouldBeNULL; - for (unsigned int i = 0; i < args->exprs.size(); ++i) { - if (args->exprs[i] == NULL) - return NULL; - const Type *t = args->exprs[i]->GetType(); - if (t == NULL) - return NULL; - argTypes.push_back(t); - argCouldBeNULL.push_back(lIsAllIntZeros(args->exprs[i])); + std::vector argTypes; + std::vector argCouldBeNULL; + for (unsigned int i = 0; i < args->exprs.size(); ++i) { + if (args->exprs[i] == NULL) + return NULL; + const Type *t = args->exprs[i]->GetType(); + if (t == NULL) + return NULL; + argTypes.push_back(t); + argCouldBeNULL.push_back(lIsAllIntZeros(args->exprs[i])); + } + + FunctionSymbolExpr *fse = dynamic_cast(func); + if (fse != NULL) { + // Regular function call + + if (fse->ResolveOverloads(args->pos, argTypes, &argCouldBeNULL) == false) + return NULL; + + func = fse->TypeCheck(); + if (func == NULL) + return NULL; + + const PointerType *pt = + dynamic_cast(func->GetType()); + const FunctionType *ft = (pt == NULL) ? NULL : + dynamic_cast(pt->GetBaseType()); + if (ft == NULL) { + Error(pos, "Valid function name must be used for function call."); + return NULL; } - FunctionSymbolExpr *fse = dynamic_cast(func); - if (fse != NULL) { - // Regular function call - - if (fse->ResolveOverloads(args->pos, argTypes, &argCouldBeNULL) == false) + if (ft->isTask) { + if (!isLaunch) + Error(pos, "\"launch\" expression needed to call function " + "with \"task\" qualifier."); + if (!launchCountExpr) return NULL; - func = fse->TypeCheck(); - if (func == NULL) + launchCountExpr = + TypeConvertExpr(launchCountExpr, AtomicType::UniformInt32, + "task launch count"); + if (launchCountExpr == NULL) return NULL; - - const PointerType *pt = - dynamic_cast(func->GetType()); - const FunctionType *ft = (pt == NULL) ? NULL : - dynamic_cast(pt->GetBaseType()); - if (ft == NULL) { - Error(pos, "Valid function name must be used for function call."); - return NULL; - } - - if (ft->isTask) { - if (!isLaunch) - Error(pos, "\"launch\" expression needed to call function " - "with \"task\" qualifier."); - if (!launchCountExpr) - return NULL; - - launchCountExpr = - TypeConvertExpr(launchCountExpr, AtomicType::UniformInt32, - "task launch count"); - if (launchCountExpr == NULL) - return NULL; - } - else { - if (isLaunch) - Error(pos, "\"launch\" expression illegal with non-\"task\"-" - "qualified function."); - Assert(launchCountExpr == NULL); - } } else { - // Call through a function pointer - const Type *fptrType = func->GetType(); - if (fptrType == NULL) - return NULL; + if (isLaunch) + Error(pos, "\"launch\" expression illegal with non-\"task\"-" + "qualified function."); + Assert(launchCountExpr == NULL); + } + } + else { + // Call through a function pointer + const Type *fptrType = func->GetType(); + if (fptrType == NULL) + return NULL; - Assert(dynamic_cast(fptrType) != NULL); - const FunctionType *funcType = - dynamic_cast(fptrType->GetBaseType()); - if (funcType == NULL) { - Error(pos, "Must provide function name or function pointer for " - "function call expression."); - return NULL; - } + Assert(dynamic_cast(fptrType) != NULL); + const FunctionType *funcType = + dynamic_cast(fptrType->GetBaseType()); + if (funcType == NULL) { + Error(pos, "Must provide function name or function pointer for " + "function call expression."); + return NULL; + } - // Make sure we don't have too many arguments for the function - if ((int)argTypes.size() > funcType->GetNumParameters()) { - Error(args->pos, "Too many parameter values provided in " - "function call (%d provided, %d expected).", - (int)argTypes.size(), funcType->GetNumParameters()); - return NULL; - } - // It's ok to have too few arguments, as long as the function's - // default parameter values have started by the time we run out - // of arguments - if ((int)argTypes.size() < funcType->GetNumParameters() && - funcType->GetParameterDefault(argTypes.size()) == NULL) { - Error(args->pos, "Too few parameter values provided in " - "function call (%d provided, %d expected).", - (int)argTypes.size(), funcType->GetNumParameters()); - return NULL; - } + // Make sure we don't have too many arguments for the function + if ((int)argTypes.size() > funcType->GetNumParameters()) { + Error(args->pos, "Too many parameter values provided in " + "function call (%d provided, %d expected).", + (int)argTypes.size(), funcType->GetNumParameters()); + return NULL; + } + // It's ok to have too few arguments, as long as the function's + // default parameter values have started by the time we run out + // of arguments + if ((int)argTypes.size() < funcType->GetNumParameters() && + funcType->GetParameterDefault(argTypes.size()) == NULL) { + Error(args->pos, "Too few parameter values provided in " + "function call (%d provided, %d expected).", + (int)argTypes.size(), funcType->GetNumParameters()); + return NULL; + } - // Now make sure they can all type convert to the corresponding - // parameter types.. - for (int i = 0; i < (int)argTypes.size(); ++i) { - if (i < funcType->GetNumParameters()) { - // make sure it can type convert - const Type *paramType = funcType->GetParameterType(i); - if (CanConvertTypes(argTypes[i], paramType) == false && - !(argCouldBeNULL[i] == true && - dynamic_cast(paramType) != NULL)) { - Error(args->exprs[i]->pos, "Can't convert argument of " - "type \"%s\" to type \"%s\" for funcion call " - "argument.", argTypes[i]->GetString().c_str(), - paramType->GetString().c_str()); - return NULL; - } + // Now make sure they can all type convert to the corresponding + // parameter types.. + for (int i = 0; i < (int)argTypes.size(); ++i) { + if (i < funcType->GetNumParameters()) { + // make sure it can type convert + const Type *paramType = funcType->GetParameterType(i); + if (CanConvertTypes(argTypes[i], paramType) == false && + !(argCouldBeNULL[i] == true && + dynamic_cast(paramType) != NULL)) { + Error(args->exprs[i]->pos, "Can't convert argument of " + "type \"%s\" to type \"%s\" for funcion call " + "argument.", argTypes[i]->GetString().c_str(), + paramType->GetString().c_str()); + return NULL; } - else - // Otherwise the parameter default saves us. It should - // be there for sure, given the check right above the - // for loop. - Assert(funcType->GetParameterDefault(i) != NULL); } + else + // Otherwise the parameter default saves us. It should + // be there for sure, given the check right above the + // for loop. + Assert(funcType->GetParameterDefault(i) != NULL); + } - if (fptrType->IsVaryingType() && - funcType->GetReturnType()->IsUniformType()) { - Error(pos, "Illegal to call a varying function pointer that " - "points to a function with a uniform return type."); - return NULL; - } + if (fptrType->IsVaryingType() && + funcType->GetReturnType()->IsUniformType()) { + Error(pos, "Illegal to call a varying function pointer that " + "points to a function with a uniform return type."); + return NULL; } } @@ -2834,9 +2807,6 @@ ExprList::Optimize() { ExprList * ExprList::TypeCheck() { - for (unsigned int i = 0; i < exprs.size(); ++i) - if (exprs[i]) - exprs[i] = exprs[i]->TypeCheck(); return this; } @@ -3199,16 +3169,11 @@ IndexExpr::Optimize() { Expr * IndexExpr::TypeCheck() { - if (baseExpr) - baseExpr = baseExpr->TypeCheck(); - if (index) - index = index->TypeCheck(); - - if (!baseExpr || !index || !index->GetType()) + if (baseExpr == NULL || index == NULL || index->GetType() == NULL) return NULL; const Type *baseExprType = baseExpr->GetType(); - if (!baseExprType) + if (baseExprType == NULL) return NULL; if (!dynamic_cast(baseExprType->GetReferenceTarget()) && @@ -3741,8 +3706,6 @@ MemberExpr::GetLValueType() const { Expr * MemberExpr::TypeCheck() { - if (expr) - expr = expr->TypeCheck(); return expr ? this : NULL; } @@ -5268,7 +5231,7 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const { Assert(Type::EqualIgnoringConst(arrayAsPtr->GetType()->GetAsVaryingType(), toPointerType) == true); arrayAsPtr = new TypeCastExpr(toPointerType, arrayAsPtr, false, pos); - arrayAsPtr = arrayAsPtr->TypeCheck(); + arrayAsPtr = ::TypeCheck(arrayAsPtr); Assert(arrayAsPtr != NULL); arrayAsPtr = ::Optimize(arrayAsPtr); Assert(arrayAsPtr != NULL); @@ -5435,8 +5398,6 @@ lDeconstifyType(const Type *t) { Expr * TypeCastExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); if (expr == NULL) return NULL; @@ -5448,7 +5409,7 @@ TypeCastExpr::TypeCheck() { toType->IsVaryingType()) { TypeCastExpr *tce = new TypeCastExpr(toType->GetAsUniformType(), expr, false, pos); - return tce->TypeCheck(); + return ::TypeCheck(tce); } fromType = lDeconstifyType(fromType); @@ -5699,8 +5660,6 @@ ReferenceExpr::Optimize() { Expr * ReferenceExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); if (expr == NULL) return NULL; return this; @@ -5797,8 +5756,6 @@ DereferenceExpr::GetType() const { Expr * DereferenceExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); if (expr == NULL) return NULL; return this; @@ -5896,8 +5853,6 @@ AddressOfExpr::Print() const { Expr * AddressOfExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); return this; } @@ -5964,8 +5919,6 @@ SizeOfExpr::Print() const { Expr * SizeOfExpr::TypeCheck() { - if (expr != NULL) - expr = expr->TypeCheck(); return this; } diff --git a/func.cpp b/func.cpp index 4dd5b341..0327bff9 100644 --- a/func.cpp +++ b/func.cpp @@ -82,7 +82,7 @@ Function::Function(Symbol *s, const std::vector &a, Stmt *c) { fprintf(stderr, "---------------------\n"); } - code = code->TypeCheck(); + code = TypeCheck(code); if (code != NULL && g->debugPrint) { fprintf(stderr, "After typechecking function \"%s\":\n", diff --git a/module.cpp b/module.cpp index 107b601e..9fade4b9 100644 --- a/module.cpp +++ b/module.cpp @@ -263,7 +263,7 @@ Module::AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst) { "global variable \"%s\".", sym->name.c_str()); } else if (initExpr != NULL) { - initExpr = initExpr->TypeCheck(); + initExpr = TypeCheck(initExpr); if (initExpr != NULL) { // We need to make sure the initializer expression is // the same type as the global. (But not if it's an diff --git a/parse.yy b/parse.yy index 552e63ec..8510244a 100644 --- a/parse.yy +++ b/parse.yy @@ -1674,7 +1674,7 @@ static bool lGetConstantInt(Expr *expr, int *value, SourcePos pos, const char *usage) { if (expr == NULL) return false; - expr = expr->TypeCheck(); + expr = TypeCheck(expr); if (expr == NULL) return false; expr = Optimize(expr); diff --git a/stmt.cpp b/stmt.cpp index 63a3f803..b3ec0c39 100644 --- a/stmt.cpp +++ b/stmt.cpp @@ -88,8 +88,6 @@ ExprStmt::EmitCode(FunctionEmitContext *ctx) const { Stmt * ExprStmt::TypeCheck() { - if (expr) - expr = expr->TypeCheck(); return this; } @@ -420,18 +418,13 @@ Stmt * DeclStmt::TypeCheck() { bool encounteredError = false; for (unsigned int i = 0; i < vars.size(); ++i) { - if (!vars[i].sym) { + if (vars[i].sym == NULL) { encounteredError = true; continue; } if (vars[i].init == NULL) 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 // the int->float type conversion is in there and we don't return @@ -566,24 +559,17 @@ IfStmt::EmitCode(FunctionEmitContext *ctx) const { Stmt * IfStmt::TypeCheck() { if (test != NULL) { - test = test->TypeCheck(); - if (test != NULL) { - const Type *testType = test->GetType(); - if (testType != NULL) { - bool isUniform = (testType->IsUniformType() && - !g->opt.disableUniformControlFlow); - test = TypeConvertExpr(test, isUniform ? AtomicType::UniformBool : - AtomicType::VaryingBool, - "\"if\" statement test"); - if (test == NULL) - return NULL; - } + const Type *testType = test->GetType(); + if (testType != NULL) { + bool isUniform = (testType->IsUniformType() && + !g->opt.disableUniformControlFlow); + test = TypeConvertExpr(test, isUniform ? AtomicType::UniformBool : + AtomicType::VaryingBool, + "\"if\" statement test"); + if (test == NULL) + return NULL; } } - if (trueStmts != NULL) - trueStmts = trueStmts->TypeCheck(); - if (falseStmts != NULL) - falseStmts = falseStmts->TypeCheck(); return this; } @@ -1122,43 +1108,38 @@ void DoStmt::EmitCode(FunctionEmitContext *ctx) const { Stmt * DoStmt::TypeCheck() { - if (testExpr) { - testExpr = testExpr->TypeCheck(); - if (testExpr) { - const Type *testType = testExpr->GetType(); - if (testType) { - if (!testType->IsNumericType() && !testType->IsBoolType()) { - Error(testExpr->pos, "Type \"%s\" can't be converted to boolean for \"while\" " - "test in \"do\" loop.", testExpr->GetType()->GetString().c_str()); - return NULL; - } - - // Should the test condition for the loop be uniform or - // varying? It can be uniform only if three conditions are - // met. First and foremost, the type of the test condition - // must be uniform. 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. - bool uniformTest = (testType->IsUniformType() && - !g->opt.disableUniformControlFlow && - !lHasVaryingBreakOrContinue(bodyStmts)); - testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : - AtomicType::VaryingBool, - testExpr, false, testExpr->pos); - } + const Type *testType; + if (testExpr != NULL && (testType = testExpr->GetType()) != NULL) { + if (!testType->IsNumericType() && !testType->IsBoolType()) { + Error(testExpr->pos, "Type \"%s\" can't be converted to boolean for \"while\" " + "test in \"do\" loop.", testExpr->GetType()->GetString().c_str()); + return NULL; } + + // Should the test condition for the loop be uniform or varying? + // It can be uniform only if three conditions are met: + // + // - First and foremost, the type of the test condition must be + // uniform. + // + // - 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. + // + bool uniformTest = (testType->IsUniformType() && + !g->opt.disableUniformControlFlow && + !lHasVaryingBreakOrContinue(bodyStmts)); + testExpr = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : + AtomicType::VaryingBool, + testExpr, false, testExpr->pos); } - if (bodyStmts) - bodyStmts = bodyStmts->TypeCheck(); return this; } @@ -1324,35 +1305,27 @@ ForStmt::EmitCode(FunctionEmitContext *ctx) const { Stmt * ForStmt::TypeCheck() { - if (test) { - test = test->TypeCheck(); - if (test) { - const Type *testType = test->GetType(); - if (testType) { - if (!testType->IsNumericType() && !testType->IsBoolType()) { - Error(test->pos, "Type \"%s\" can't be converted to boolean for for loop test.", - test->GetType()->GetString().c_str()); - return NULL; - } - - // See comments in DoStmt::TypeCheck() regarding - // 'uniformTest' and the type cast here. - bool uniformTest = (testType->IsUniformType() && - !g->opt.disableUniformControlFlow && - !lHasVaryingBreakOrContinue(stmts)); - test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : - AtomicType::VaryingBool, - test, false, test->pos); - } + const Type *testType; + if (test && (testType = test->GetType()) != NULL) { + if (!testType->IsNumericType() && !testType->IsBoolType()) { + Error(test->pos, "Type \"%s\" can't be converted to boolean for \"for\" " + "loop test.", test->GetType()->GetString().c_str()); + return NULL; } + + // See comments in DoStmt::TypeCheck() regarding + // 'uniformTest' and the type cast here. + bool uniformTest = (testType->IsUniformType() && + !g->opt.disableUniformControlFlow && + !lHasVaryingBreakOrContinue(stmts)); + test = new TypeCastExpr(uniformTest ? AtomicType::UniformBool : + AtomicType::VaryingBool, + 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; } @@ -1813,9 +1786,6 @@ Stmt * ForeachStmt::TypeCheck() { bool anyErrors = false; 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) startExprs[i] = TypeConvertExpr(startExprs[i], AtomicType::UniformInt32, @@ -1823,18 +1793,12 @@ ForeachStmt::TypeCheck() { anyErrors |= (startExprs[i] == NULL); } for (unsigned int i = 0; i < endExprs.size(); ++i) { - if (endExprs[i] != NULL) - endExprs[i] = endExprs[i]->TypeCheck(); if (endExprs[i] != NULL) endExprs[i] = TypeConvertExpr(endExprs[i], AtomicType::UniformInt32, "foreach ending value"); anyErrors |= (endExprs[i] == NULL); } - if (stmts != NULL) - stmts = stmts->TypeCheck(); - anyErrors |= (stmts == NULL); - if (startExprs.size() < dimVariables.size()) { Error(pos, "Not enough initial values provided for \"foreach\" loop; " "got %d, expected %d\n", (int)startExprs.size(), (int)dimVariables.size()); @@ -1938,11 +1902,6 @@ ReturnStmt::EmitCode(FunctionEmitContext *ctx) const { Stmt * 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; } @@ -1982,9 +1941,6 @@ StmtList::EmitCode(FunctionEmitContext *ctx) const { Stmt * StmtList::TypeCheck() { - for (unsigned int i = 0; i < stmts.size(); ++i) - if (stmts[i]) - stmts[i] = stmts[i]->TypeCheck(); return this; } @@ -2194,8 +2150,6 @@ PrintStmt::Print(int indent) const { Stmt * PrintStmt::TypeCheck() { - if (values) - values = values->TypeCheck(); return this; } @@ -2270,21 +2224,18 @@ AssertStmt::Print(int indent) const { Stmt * AssertStmt::TypeCheck() { - if (expr) - expr = expr->TypeCheck(); - if (expr) { - const Type *type = expr->GetType(); - if (type) { - bool isUniform = type->IsUniformType(); - if (!type->IsNumericType() && !type->IsBoolType()) { - Error(expr->pos, "Type \"%s\" can't be converted to boolean for \"assert\".", - type->GetString().c_str()); - return NULL; - } - expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool : - AtomicType::VaryingBool, - expr, false, expr->pos); + const Type *type; + if (expr && (type = expr->GetType()) != NULL) { + bool isUniform = type->IsUniformType(); + if (!type->IsNumericType() && !type->IsBoolType()) { + Error(expr->pos, "Type \"%s\" can't be converted to boolean for \"assert\".", + type->GetString().c_str()); + return NULL; } + expr = new TypeCastExpr(isUniform ? AtomicType::UniformBool : + AtomicType::VaryingBool, + expr, false, expr->pos); + expr = ::TypeCheck(expr); } return this; }