|
Intel SPMD Program Compiler
1.3.0
|
00001 /* 00002 Copyright (c) 2010-2012, Intel Corporation 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without 00006 modification, are permitted provided that the following conditions are 00007 met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 00016 * Neither the name of Intel Corporation nor the names of its 00017 contributors may be used to endorse or promote products derived from 00018 this software without specific prior written permission. 00019 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00022 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00023 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00024 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00025 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00027 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00028 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00029 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00030 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00031 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 */ 00033 00034 /** @file stmt.h 00035 @brief File with declarations for classes related to statements in the language 00036 */ 00037 00038 #ifndef ISPC_STMT_H 00039 #define ISPC_STMT_H 1 00040 00041 #include "ispc.h" 00042 #include "ast.h" 00043 00044 /** @brief Interface class for statements in the ispc language. 00045 00046 This abstract base-class encapsulates methods that AST nodes for 00047 statements in the language must implement. 00048 */ 00049 class Stmt : public ASTNode { 00050 public: 00051 Stmt(SourcePos p) : ASTNode(p) { } 00052 00053 /** Emit LLVM IR for the statement, using the FunctionEmitContext to create the 00054 necessary instructions. 00055 */ 00056 virtual void EmitCode(FunctionEmitContext *ctx) const = 0; 00057 00058 /** Print a representation of the statement (and any children AST 00059 nodes) to standard output. This method is used for debuggins. */ 00060 virtual void Print(int indent) const = 0; 00061 00062 // Redeclare these methods with Stmt * return values, rather than 00063 // ASTNode *s, as in the original ASTNode declarations of them. We'll 00064 // also provide a default implementation of Optimize(), since most 00065 // Stmts don't have anything to do here. 00066 virtual Stmt *Optimize(); 00067 virtual Stmt *TypeCheck() = 0; 00068 }; 00069 00070 00071 /** @brief Statement representing a single expression */ 00072 class ExprStmt : public Stmt { 00073 public: 00074 ExprStmt(Expr *expr, SourcePos pos); 00075 00076 void EmitCode(FunctionEmitContext *ctx) const; 00077 void Print(int indent) const; 00078 00079 Stmt *TypeCheck(); 00080 int EstimateCost() const; 00081 00082 Expr *expr; 00083 }; 00084 00085 00086 struct VariableDeclaration { 00087 VariableDeclaration(Symbol *s = NULL, Expr *i = NULL) { 00088 sym = s; init = i; 00089 } 00090 Symbol *sym; 00091 Expr *init; 00092 }; 00093 00094 /** @brief Statement representing a single declaration (which in turn may declare 00095 a number of variables. */ 00096 class DeclStmt : public Stmt { 00097 public: 00098 DeclStmt(const std::vector<VariableDeclaration> &v, SourcePos pos); 00099 00100 void EmitCode(FunctionEmitContext *ctx) const; 00101 void Print(int indent) const; 00102 00103 Stmt *Optimize(); 00104 Stmt *TypeCheck(); 00105 int EstimateCost() const; 00106 00107 std::vector<VariableDeclaration> vars; 00108 }; 00109 00110 00111 /** @brief Statement representing a single if statement, possibly with an 00112 else clause. */ 00113 class IfStmt : public Stmt { 00114 public: 00115 IfStmt(Expr *testExpr, Stmt *trueStmts, Stmt *falseStmts, 00116 bool doAllCheck, SourcePos pos); 00117 00118 void EmitCode(FunctionEmitContext *ctx) const; 00119 void Print(int indent) const; 00120 00121 Stmt *TypeCheck(); 00122 int EstimateCost() const; 00123 00124 // @todo these are only public for lHasVaryingBreakOrContinue(); would 00125 // be nice to clean that up... 00126 /** Expression giving the 'if' test. */ 00127 Expr *test; 00128 /** Statements to run if the 'if' test returns a true value */ 00129 Stmt *trueStmts; 00130 /** Statements to run if the 'if' test returns a false value */ 00131 Stmt *falseStmts; 00132 00133 private: 00134 /** This value records if this was a 'coherent' if statement in the 00135 source and thus, if the emitted code should check to see if all 00136 active program instances want to follow just one of the 'true' or 00137 'false' blocks. */ 00138 const bool doAllCheck; 00139 00140 void emitMaskedTrueAndFalse(FunctionEmitContext *ctx, llvm::Value *oldMask, 00141 llvm::Value *test) const; 00142 void emitVaryingIf(FunctionEmitContext *ctx, llvm::Value *test) const; 00143 void emitMaskAllOn(FunctionEmitContext *ctx, 00144 llvm::Value *test, llvm::BasicBlock *bDone) const; 00145 void emitMaskMixed(FunctionEmitContext *ctx, llvm::Value *oldMask, 00146 llvm::Value *test, llvm::BasicBlock *bDone) const; 00147 }; 00148 00149 00150 /** @brief Statement implementation representing a 'do' statement in the 00151 program. 00152 */ 00153 class DoStmt : public Stmt { 00154 public: 00155 DoStmt(Expr *testExpr, Stmt *bodyStmts, bool doCoherentCheck, 00156 SourcePos pos); 00157 00158 void EmitCode(FunctionEmitContext *ctx) const; 00159 void Print(int indent) const; 00160 00161 Stmt *TypeCheck(); 00162 int EstimateCost() const; 00163 00164 Expr *testExpr; 00165 Stmt *bodyStmts; 00166 const bool doCoherentCheck; 00167 }; 00168 00169 00170 /** @brief Statement implementation for 'for' loops (as well as for 'while' 00171 loops). 00172 */ 00173 class ForStmt : public Stmt { 00174 public: 00175 ForStmt(Stmt *initializer, Expr *testExpr, Stmt *stepStatements, 00176 Stmt *bodyStatements, bool doCoherentCheck, SourcePos pos); 00177 00178 void EmitCode(FunctionEmitContext *ctx) const; 00179 void Print(int indent) const; 00180 00181 Stmt *TypeCheck(); 00182 int EstimateCost() const; 00183 00184 /** 'for' statment initializer; may be NULL, indicating no intitializer */ 00185 Stmt *init; 00186 /** expression that returns a value indicating whether the loop should 00187 continue for the next iteration */ 00188 Expr *test; 00189 /** Statements to run at the end of the loop for the loop step, before 00190 the test expression is evaluated. */ 00191 Stmt *step; 00192 /** Loop body statements */ 00193 Stmt *stmts; 00194 const bool doCoherentCheck; 00195 }; 00196 00197 00198 /** @brief Statement implementation for a break or 'coherent' break 00199 statement in the program. */ 00200 class BreakStmt : public Stmt { 00201 public: 00202 BreakStmt(bool doCoherenceCheck, SourcePos pos); 00203 00204 void EmitCode(FunctionEmitContext *ctx) const; 00205 void Print(int indent) const; 00206 00207 Stmt *TypeCheck(); 00208 int EstimateCost() const; 00209 00210 private: 00211 /** This indicates whether the generated code will check to see if no 00212 more program instances are currently running after the break, in 00213 which case the code can have a jump to the end of the current 00214 loop. */ 00215 const bool doCoherenceCheck; 00216 }; 00217 00218 00219 /** @brief Statement implementation for a continue or 'coherent' continue 00220 statement in the program. */ 00221 class ContinueStmt : public Stmt { 00222 public: 00223 ContinueStmt(bool doCoherenceCheck, SourcePos pos); 00224 00225 void EmitCode(FunctionEmitContext *ctx) const; 00226 void Print(int indent) const; 00227 00228 Stmt *TypeCheck(); 00229 int EstimateCost() const; 00230 00231 private: 00232 /** This indicates whether the generated code will check to see if no 00233 more program instances are currently running after the continue, in 00234 which case the code can have a jump to the end of the current 00235 loop. */ 00236 const bool doCoherenceCheck; 00237 }; 00238 00239 00240 /** @brief Statement implementation for parallel 'foreach' loops. 00241 */ 00242 class ForeachStmt : public Stmt { 00243 public: 00244 ForeachStmt(const std::vector<Symbol *> &loopVars, 00245 const std::vector<Expr *> &startExprs, 00246 const std::vector<Expr *> &endExprs, 00247 Stmt *bodyStatements, bool tiled, SourcePos pos); 00248 00249 void EmitCode(FunctionEmitContext *ctx) const; 00250 void Print(int indent) const; 00251 00252 Stmt *TypeCheck(); 00253 int EstimateCost() const; 00254 00255 std::vector<Symbol *> dimVariables; 00256 std::vector<Expr *> startExprs; 00257 std::vector<Expr *> endExprs; 00258 bool isTiled; 00259 Stmt *stmts; 00260 }; 00261 00262 00263 /** Iteration over each executing program instance. 00264 */ 00265 class ForeachActiveStmt : public Stmt { 00266 public: 00267 ForeachActiveStmt(Symbol *iterSym, Stmt *stmts, SourcePos pos); 00268 00269 void EmitCode(FunctionEmitContext *ctx) const; 00270 void Print(int indent) const; 00271 00272 Stmt *TypeCheck(); 00273 int EstimateCost() const; 00274 00275 Symbol *sym; 00276 Stmt *stmts; 00277 }; 00278 00279 00280 /** Parallel iteration over each unique value in the given (varying) 00281 expression. 00282 */ 00283 class ForeachUniqueStmt : public Stmt { 00284 public: 00285 ForeachUniqueStmt(const char *iterName, Expr *expr, Stmt *stmts, 00286 SourcePos pos); 00287 00288 void EmitCode(FunctionEmitContext *ctx) const; 00289 void Print(int indent) const; 00290 00291 Stmt *TypeCheck(); 00292 int EstimateCost() const; 00293 00294 Symbol *sym; 00295 Expr *expr; 00296 Stmt *stmts; 00297 }; 00298 00299 00300 /** 00301 */ 00302 class UnmaskedStmt : public Stmt { 00303 public: 00304 UnmaskedStmt(Stmt *stmt, SourcePos pos); 00305 00306 void EmitCode(FunctionEmitContext *ctx) const; 00307 void Print(int indent) const; 00308 00309 Stmt *TypeCheck(); 00310 int EstimateCost() const; 00311 00312 Stmt *stmts; 00313 }; 00314 00315 00316 00317 /** @brief Statement implementation for a 'return' or 'coherent' return 00318 statement in the program. */ 00319 class ReturnStmt : public Stmt { 00320 public: 00321 ReturnStmt(Expr *e, bool cc, SourcePos p); 00322 00323 void EmitCode(FunctionEmitContext *ctx) const; 00324 void Print(int indent) const; 00325 00326 Stmt *TypeCheck(); 00327 int EstimateCost() const; 00328 00329 Expr *expr; 00330 /** This indicates whether the generated code will check to see if no 00331 more program instances are currently running after the return, in 00332 which case the code can possibly jump to the end of the current 00333 function. */ 00334 const bool doCoherenceCheck; 00335 }; 00336 00337 00338 /** Statement corresponding to a "case" label in the program. In addition 00339 to the value associated with the "case", this statement also stores the 00340 statements following it. */ 00341 class CaseStmt : public Stmt { 00342 public: 00343 CaseStmt(int value, Stmt *stmt, SourcePos pos); 00344 00345 void EmitCode(FunctionEmitContext *ctx) const; 00346 void Print(int indent) const; 00347 00348 Stmt *TypeCheck(); 00349 int EstimateCost() const; 00350 00351 /** Integer value after the "case" statement */ 00352 const int value; 00353 Stmt *stmts; 00354 }; 00355 00356 00357 /** Statement for a "default" label (as would be found inside a "switch" 00358 statement). */ 00359 class DefaultStmt : public Stmt { 00360 public: 00361 DefaultStmt(Stmt *stmt, SourcePos pos); 00362 00363 void EmitCode(FunctionEmitContext *ctx) const; 00364 void Print(int indent) const; 00365 00366 Stmt *TypeCheck(); 00367 int EstimateCost() const; 00368 00369 Stmt *stmts; 00370 }; 00371 00372 00373 /** A "switch" statement in the program. */ 00374 class SwitchStmt : public Stmt { 00375 public: 00376 SwitchStmt(Expr *expr, Stmt *stmts, SourcePos pos); 00377 00378 void EmitCode(FunctionEmitContext *ctx) const; 00379 void Print(int indent) const; 00380 00381 Stmt *TypeCheck(); 00382 int EstimateCost() const; 00383 00384 /** Expression that is used to determine which label to jump to. */ 00385 Expr *expr; 00386 /** Statement block after the "switch" expression. */ 00387 Stmt *stmts; 00388 }; 00389 00390 00391 /** A "goto" in an ispc program. */ 00392 class GotoStmt : public Stmt { 00393 public: 00394 GotoStmt(const char *label, SourcePos gotoPos, SourcePos idPos); 00395 00396 void EmitCode(FunctionEmitContext *ctx) const; 00397 void Print(int indent) const; 00398 00399 Stmt *Optimize(); 00400 Stmt *TypeCheck(); 00401 int EstimateCost() const; 00402 00403 /** Name of the label to jump to when the goto is executed. */ 00404 std::string label; 00405 SourcePos identifierPos; 00406 }; 00407 00408 00409 /** Statement corresponding to a label (as would be used as a goto target) 00410 in the program. */ 00411 class LabeledStmt : public Stmt { 00412 public: 00413 LabeledStmt(const char *label, Stmt *stmt, SourcePos p); 00414 00415 void EmitCode(FunctionEmitContext *ctx) const; 00416 void Print(int indent) const; 00417 00418 Stmt *Optimize(); 00419 Stmt *TypeCheck(); 00420 int EstimateCost() const; 00421 00422 /** Name of the label. */ 00423 std::string name; 00424 /** Statements following the label. */ 00425 Stmt *stmt; 00426 }; 00427 00428 00429 /** @brief Representation of a list of statements in the program. 00430 */ 00431 class StmtList : public Stmt { 00432 public: 00433 StmtList(SourcePos p) : Stmt(p) { } 00434 00435 void EmitCode(FunctionEmitContext *ctx) const; 00436 void Print(int indent) const; 00437 00438 Stmt *TypeCheck(); 00439 int EstimateCost() const; 00440 00441 void Add(Stmt *s) { if (s) stmts.push_back(s); } 00442 00443 std::vector<Stmt *> stmts; 00444 }; 00445 00446 00447 /** @brief Representation of a print() statement in the program. 00448 00449 It's currently necessary to have a special statement type for print() 00450 since strings aren't supported as first-class types in the language, 00451 but we need to be able to pass a formatting string as the first 00452 argument to print(). We also need this to be a variable argument 00453 function, which also isn't supported. Representing print() as a 00454 statement lets us work around both of those ugly little issues... 00455 */ 00456 class PrintStmt : public Stmt { 00457 public: 00458 PrintStmt(const std::string &f, Expr *v, SourcePos p); 00459 00460 void EmitCode(FunctionEmitContext *ctx) const; 00461 void Print(int indent) const; 00462 00463 Stmt *TypeCheck(); 00464 int EstimateCost() const; 00465 00466 /** Format string for the print() statement. */ 00467 const std::string format; 00468 /** This holds the arguments passed to the print() statement. If more 00469 than one was provided, this will be an ExprList. */ 00470 Expr *values; 00471 }; 00472 00473 00474 /** @brief Representation of an assert statement in the program. 00475 00476 Like print() above, since we don't have strings as first-class types in 00477 the language, we need to do some gymnastics to support it. Like 00478 assert() in C, assert() checks the given condition and prints an error 00479 and calls abort if the condition fails. For varying conditions, the 00480 assert triggers if it's true for any of the program instances. 00481 */ 00482 class AssertStmt : public Stmt { 00483 public: 00484 AssertStmt(const std::string &msg, Expr *e, SourcePos p); 00485 00486 void EmitCode(FunctionEmitContext *ctx) const; 00487 void Print(int indent) const; 00488 00489 Stmt *TypeCheck(); 00490 int EstimateCost() const; 00491 00492 /** Message to print if the assertion fails. */ 00493 const std::string message; 00494 /** The expression to be evaluated (that is asserted to be true). */ 00495 Expr *expr; 00496 }; 00497 00498 00499 /** Representation of a delete statement in the program. 00500 */ 00501 class DeleteStmt : public Stmt { 00502 public: 00503 DeleteStmt(Expr *e, SourcePos p); 00504 00505 void EmitCode(FunctionEmitContext *ctx) const; 00506 void Print(int indent) const; 00507 00508 Stmt *TypeCheck(); 00509 int EstimateCost() const; 00510 00511 /** Expression that gives the pointer value to be deleted. */ 00512 Expr *expr; 00513 }; 00514 00515 extern Stmt *CreateForeachActiveStmt(Symbol *iterSym, Stmt *stmts, 00516 SourcePos pos); 00517 00518 #endif // ISPC_STMT_H
1.7.5.1