SkSLCompiler.cpp revision 1cb41717bc4a44272eab48bd47ca7579425dc22e
1/* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkSLCompiler.h" 9 10#include "SkSLCFGGenerator.h" 11#include "SkSLCPPCodeGenerator.h" 12#include "SkSLGLSLCodeGenerator.h" 13#include "SkSLHCodeGenerator.h" 14#include "SkSLIRGenerator.h" 15#include "SkSLSPIRVCodeGenerator.h" 16#include "ir/SkSLExpression.h" 17#include "ir/SkSLExpressionStatement.h" 18#include "ir/SkSLIntLiteral.h" 19#include "ir/SkSLModifiersDeclaration.h" 20#include "ir/SkSLNop.h" 21#include "ir/SkSLSymbolTable.h" 22#include "ir/SkSLTernaryExpression.h" 23#include "ir/SkSLUnresolvedFunction.h" 24#include "ir/SkSLVarDeclarations.h" 25 26#ifdef SK_ENABLE_SPIRV_VALIDATION 27#include "spirv-tools/libspirv.hpp" 28#endif 29 30#define STRINGIFY(x) #x 31 32// include the built-in shader symbols as static strings 33 34static const char* SKSL_INCLUDE = 35#include "sksl.include" 36; 37 38static const char* SKSL_VERT_INCLUDE = 39#include "sksl_vert.include" 40; 41 42static const char* SKSL_FRAG_INCLUDE = 43#include "sksl_frag.include" 44; 45 46static const char* SKSL_GEOM_INCLUDE = 47#include "sksl_geom.include" 48; 49 50static const char* SKSL_FP_INCLUDE = 51#include "sksl_fp.include" 52; 53 54namespace SkSL { 55 56Compiler::Compiler(Flags flags) 57: fFlags(flags) 58, fErrorCount(0) { 59 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this)); 60 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this)); 61 fIRGenerator = new IRGenerator(&fContext, symbols, *this); 62 fTypes = types; 63 #define ADD_TYPE(t) types->addWithoutOwnership(fContext.f ## t ## _Type->fName, \ 64 fContext.f ## t ## _Type.get()) 65 ADD_TYPE(Void); 66 ADD_TYPE(Float); 67 ADD_TYPE(Float2); 68 ADD_TYPE(Float3); 69 ADD_TYPE(Float4); 70 ADD_TYPE(Half); 71 ADD_TYPE(Half2); 72 ADD_TYPE(Half3); 73 ADD_TYPE(Half4); 74 ADD_TYPE(Double); 75 ADD_TYPE(Double2); 76 ADD_TYPE(Double3); 77 ADD_TYPE(Double4); 78 ADD_TYPE(Int); 79 ADD_TYPE(Int2); 80 ADD_TYPE(Int3); 81 ADD_TYPE(Int4); 82 ADD_TYPE(UInt); 83 ADD_TYPE(UInt2); 84 ADD_TYPE(UInt3); 85 ADD_TYPE(UInt4); 86 ADD_TYPE(Short); 87 ADD_TYPE(Short2); 88 ADD_TYPE(Short3); 89 ADD_TYPE(Short4); 90 ADD_TYPE(UShort); 91 ADD_TYPE(UShort2); 92 ADD_TYPE(UShort3); 93 ADD_TYPE(UShort4); 94 ADD_TYPE(Bool); 95 ADD_TYPE(Bool2); 96 ADD_TYPE(Bool3); 97 ADD_TYPE(Bool4); 98 ADD_TYPE(Float2x2); 99 ADD_TYPE(Float2x3); 100 ADD_TYPE(Float2x4); 101 ADD_TYPE(Float3x2); 102 ADD_TYPE(Float3x3); 103 ADD_TYPE(Float3x4); 104 ADD_TYPE(Float4x2); 105 ADD_TYPE(Float4x3); 106 ADD_TYPE(Float4x4); 107 ADD_TYPE(Half2x2); 108 ADD_TYPE(Half2x3); 109 ADD_TYPE(Half2x4); 110 ADD_TYPE(Half3x2); 111 ADD_TYPE(Half3x3); 112 ADD_TYPE(Half3x4); 113 ADD_TYPE(Half4x2); 114 ADD_TYPE(Half4x3); 115 ADD_TYPE(Half4x4); 116 ADD_TYPE(Double2x2); 117 ADD_TYPE(Double2x3); 118 ADD_TYPE(Double2x4); 119 ADD_TYPE(Double3x2); 120 ADD_TYPE(Double3x3); 121 ADD_TYPE(Double3x4); 122 ADD_TYPE(Double4x2); 123 ADD_TYPE(Double4x3); 124 ADD_TYPE(Double4x4); 125 ADD_TYPE(GenType); 126 ADD_TYPE(GenHType); 127 ADD_TYPE(GenDType); 128 ADD_TYPE(GenIType); 129 ADD_TYPE(GenUType); 130 ADD_TYPE(GenBType); 131 ADD_TYPE(Mat); 132 ADD_TYPE(Vec); 133 ADD_TYPE(GVec); 134 ADD_TYPE(GVec2); 135 ADD_TYPE(GVec3); 136 ADD_TYPE(GVec4); 137 ADD_TYPE(HVec); 138 ADD_TYPE(DVec); 139 ADD_TYPE(IVec); 140 ADD_TYPE(UVec); 141 ADD_TYPE(SVec); 142 ADD_TYPE(USVec); 143 ADD_TYPE(BVec); 144 145 ADD_TYPE(Sampler1D); 146 ADD_TYPE(Sampler2D); 147 ADD_TYPE(Sampler3D); 148 ADD_TYPE(SamplerExternalOES); 149 ADD_TYPE(SamplerCube); 150 ADD_TYPE(Sampler2DRect); 151 ADD_TYPE(Sampler1DArray); 152 ADD_TYPE(Sampler2DArray); 153 ADD_TYPE(SamplerCubeArray); 154 ADD_TYPE(SamplerBuffer); 155 ADD_TYPE(Sampler2DMS); 156 ADD_TYPE(Sampler2DMSArray); 157 158 ADD_TYPE(ISampler2D); 159 160 ADD_TYPE(Image2D); 161 ADD_TYPE(IImage2D); 162 163 ADD_TYPE(SubpassInput); 164 ADD_TYPE(SubpassInputMS); 165 166 ADD_TYPE(GSampler1D); 167 ADD_TYPE(GSampler2D); 168 ADD_TYPE(GSampler3D); 169 ADD_TYPE(GSamplerCube); 170 ADD_TYPE(GSampler2DRect); 171 ADD_TYPE(GSampler1DArray); 172 ADD_TYPE(GSampler2DArray); 173 ADD_TYPE(GSamplerCubeArray); 174 ADD_TYPE(GSamplerBuffer); 175 ADD_TYPE(GSampler2DMS); 176 ADD_TYPE(GSampler2DMSArray); 177 178 ADD_TYPE(Sampler1DShadow); 179 ADD_TYPE(Sampler2DShadow); 180 ADD_TYPE(SamplerCubeShadow); 181 ADD_TYPE(Sampler2DRectShadow); 182 ADD_TYPE(Sampler1DArrayShadow); 183 ADD_TYPE(Sampler2DArrayShadow); 184 ADD_TYPE(SamplerCubeArrayShadow); 185 ADD_TYPE(GSampler2DArrayShadow); 186 ADD_TYPE(GSamplerCubeArrayShadow); 187 ADD_TYPE(FragmentProcessor); 188 189 StringFragment skCapsName("sk_Caps"); 190 Variable* skCaps = new Variable(-1, Modifiers(), skCapsName, 191 *fContext.fSkCaps_Type, Variable::kGlobal_Storage); 192 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps)); 193 194 StringFragment skArgsName("sk_Args"); 195 Variable* skArgs = new Variable(-1, Modifiers(), skArgsName, 196 *fContext.fSkArgs_Type, Variable::kGlobal_Storage); 197 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs)); 198 199 std::vector<std::unique_ptr<ProgramElement>> ignored; 200 fIRGenerator->convertProgram(SKSL_INCLUDE, strlen(SKSL_INCLUDE), *fTypes, &ignored); 201 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 202 if (fErrorCount) { 203 printf("Unexpected errors: %s\n", fErrorText.c_str()); 204 } 205 ASSERT(!fErrorCount); 206} 207 208Compiler::~Compiler() { 209 delete fIRGenerator; 210} 211 212// add the definition created by assigning to the lvalue to the definition set 213void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr, 214 DefinitionMap* definitions) { 215 switch (lvalue->fKind) { 216 case Expression::kVariableReference_Kind: { 217 const Variable& var = ((VariableReference*) lvalue)->fVariable; 218 if (var.fStorage == Variable::kLocal_Storage) { 219 (*definitions)[&var] = expr; 220 } 221 break; 222 } 223 case Expression::kSwizzle_Kind: 224 // We consider the variable written to as long as at least some of its components have 225 // been written to. This will lead to some false negatives (we won't catch it if you 226 // write to foo.x and then read foo.y), but being stricter could lead to false positives 227 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x, 228 // but since we pass foo as a whole it is flagged as an error) unless we perform a much 229 // more complicated whole-program analysis. This is probably good enough. 230 this->addDefinition(((Swizzle*) lvalue)->fBase.get(), 231 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 232 definitions); 233 break; 234 case Expression::kIndex_Kind: 235 // see comments in Swizzle 236 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(), 237 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 238 definitions); 239 break; 240 case Expression::kFieldAccess_Kind: 241 // see comments in Swizzle 242 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(), 243 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 244 definitions); 245 break; 246 default: 247 // not an lvalue, can't happen 248 ASSERT(false); 249 } 250} 251 252// add local variables defined by this node to the set 253void Compiler::addDefinitions(const BasicBlock::Node& node, 254 DefinitionMap* definitions) { 255 switch (node.fKind) { 256 case BasicBlock::Node::kExpression_Kind: { 257 ASSERT(node.expression()); 258 const Expression* expr = (Expression*) node.expression()->get(); 259 switch (expr->fKind) { 260 case Expression::kBinary_Kind: { 261 BinaryExpression* b = (BinaryExpression*) expr; 262 if (b->fOperator == Token::EQ) { 263 this->addDefinition(b->fLeft.get(), &b->fRight, definitions); 264 } else if (Compiler::IsAssignment(b->fOperator)) { 265 this->addDefinition( 266 b->fLeft.get(), 267 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 268 definitions); 269 270 } 271 break; 272 } 273 case Expression::kPrefix_Kind: { 274 const PrefixExpression* p = (PrefixExpression*) expr; 275 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 276 this->addDefinition( 277 p->fOperand.get(), 278 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 279 definitions); 280 } 281 break; 282 } 283 case Expression::kPostfix_Kind: { 284 const PostfixExpression* p = (PostfixExpression*) expr; 285 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) { 286 this->addDefinition( 287 p->fOperand.get(), 288 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 289 definitions); 290 } 291 break; 292 } 293 case Expression::kVariableReference_Kind: { 294 const VariableReference* v = (VariableReference*) expr; 295 if (v->fRefKind != VariableReference::kRead_RefKind) { 296 this->addDefinition( 297 v, 298 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression, 299 definitions); 300 } 301 } 302 default: 303 break; 304 } 305 break; 306 } 307 case BasicBlock::Node::kStatement_Kind: { 308 const Statement* stmt = (Statement*) node.statement()->get(); 309 if (stmt->fKind == Statement::kVarDeclaration_Kind) { 310 VarDeclaration& vd = (VarDeclaration&) *stmt; 311 if (vd.fValue) { 312 (*definitions)[vd.fVar] = &vd.fValue; 313 } 314 } 315 break; 316 } 317 } 318} 319 320void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) { 321 BasicBlock& block = cfg->fBlocks[blockId]; 322 323 // compute definitions after this block 324 DefinitionMap after = block.fBefore; 325 for (const BasicBlock::Node& n : block.fNodes) { 326 this->addDefinitions(n, &after); 327 } 328 329 // propagate definitions to exits 330 for (BlockId exitId : block.fExits) { 331 BasicBlock& exit = cfg->fBlocks[exitId]; 332 for (const auto& pair : after) { 333 std::unique_ptr<Expression>* e1 = pair.second; 334 auto found = exit.fBefore.find(pair.first); 335 if (found == exit.fBefore.end()) { 336 // exit has no definition for it, just copy it 337 workList->insert(exitId); 338 exit.fBefore[pair.first] = e1; 339 } else { 340 // exit has a (possibly different) value already defined 341 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first]; 342 if (e1 != e2) { 343 // definition has changed, merge and add exit block to worklist 344 workList->insert(exitId); 345 if (e1 && e2) { 346 exit.fBefore[pair.first] = 347 (std::unique_ptr<Expression>*) &fContext.fDefined_Expression; 348 } else { 349 exit.fBefore[pair.first] = nullptr; 350 } 351 } 352 } 353 } 354 } 355} 356 357// returns a map which maps all local variables in the function to null, indicating that their value 358// is initially unknown 359static DefinitionMap compute_start_state(const CFG& cfg) { 360 DefinitionMap result; 361 for (const auto& block : cfg.fBlocks) { 362 for (const auto& node : block.fNodes) { 363 if (node.fKind == BasicBlock::Node::kStatement_Kind) { 364 ASSERT(node.statement()); 365 const Statement* s = node.statement()->get(); 366 if (s->fKind == Statement::kVarDeclarations_Kind) { 367 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s; 368 for (const auto& decl : vd->fDeclaration->fVars) { 369 if (decl->fKind == Statement::kVarDeclaration_Kind) { 370 result[((VarDeclaration&) *decl).fVar] = nullptr; 371 } 372 } 373 } 374 } 375 } 376 } 377 return result; 378} 379 380/** 381 * Returns true if assigning to this lvalue has no effect. 382 */ 383static bool is_dead(const Expression& lvalue) { 384 switch (lvalue.fKind) { 385 case Expression::kVariableReference_Kind: 386 return ((VariableReference&) lvalue).fVariable.dead(); 387 case Expression::kSwizzle_Kind: 388 return is_dead(*((Swizzle&) lvalue).fBase); 389 case Expression::kFieldAccess_Kind: 390 return is_dead(*((FieldAccess&) lvalue).fBase); 391 case Expression::kIndex_Kind: { 392 const IndexExpression& idx = (IndexExpression&) lvalue; 393 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects(); 394 } 395 default: 396 ABORT("invalid lvalue: %s\n", lvalue.description().c_str()); 397 } 398} 399 400/** 401 * Returns true if this is an assignment which can be collapsed down to just the right hand side due 402 * to a dead target and lack of side effects on the left hand side. 403 */ 404static bool dead_assignment(const BinaryExpression& b) { 405 if (!Compiler::IsAssignment(b.fOperator)) { 406 return false; 407 } 408 return is_dead(*b.fLeft); 409} 410 411void Compiler::computeDataFlow(CFG* cfg) { 412 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg); 413 std::set<BlockId> workList; 414 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) { 415 workList.insert(i); 416 } 417 while (workList.size()) { 418 BlockId next = *workList.begin(); 419 workList.erase(workList.begin()); 420 this->scanCFG(cfg, next, &workList); 421 } 422} 423 424/** 425 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the 426 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to 427 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will 428 * need to be regenerated). 429 */ 430bool try_replace_expression(BasicBlock* b, 431 std::vector<BasicBlock::Node>::iterator* iter, 432 std::unique_ptr<Expression>* newExpression) { 433 std::unique_ptr<Expression>* target = (*iter)->expression(); 434 if (!b->tryRemoveExpression(iter)) { 435 *target = std::move(*newExpression); 436 return false; 437 } 438 *target = std::move(*newExpression); 439 return b->tryInsertExpression(iter, target); 440} 441 442/** 443 * Returns true if the expression is a constant numeric literal with the specified value, or a 444 * constant vector with all elements equal to the specified value. 445 */ 446bool is_constant(const Expression& expr, double value) { 447 switch (expr.fKind) { 448 case Expression::kIntLiteral_Kind: 449 return ((IntLiteral&) expr).fValue == value; 450 case Expression::kFloatLiteral_Kind: 451 return ((FloatLiteral&) expr).fValue == value; 452 case Expression::kConstructor_Kind: { 453 Constructor& c = (Constructor&) expr; 454 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) { 455 for (int i = 0; i < c.fType.columns(); ++i) { 456 if (!is_constant(c.getVecComponent(i), value)) { 457 return false; 458 } 459 } 460 return true; 461 } 462 return false; 463 } 464 default: 465 return false; 466 } 467} 468 469/** 470 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR 471 * and CFG structures). 472 */ 473void delete_left(BasicBlock* b, 474 std::vector<BasicBlock::Node>::iterator* iter, 475 bool* outUpdated, 476 bool* outNeedsRescan) { 477 *outUpdated = true; 478 std::unique_ptr<Expression>* target = (*iter)->expression(); 479 ASSERT((*target)->fKind == Expression::kBinary_Kind); 480 BinaryExpression& bin = (BinaryExpression&) **target; 481 bool result; 482 if (bin.fOperator == Token::EQ) { 483 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get()); 484 } else { 485 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get()); 486 } 487 *target = std::move(bin.fRight); 488 if (!result) { 489 *outNeedsRescan = true; 490 return; 491 } 492 if (*iter == b->fNodes.begin()) { 493 *outNeedsRescan = true; 494 return; 495 } 496 --(*iter); 497 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 498 (*iter)->expression() != &bin.fRight) { 499 *outNeedsRescan = true; 500 return; 501 } 502 *iter = b->fNodes.erase(*iter); 503 ASSERT((*iter)->expression() == target); 504} 505 506/** 507 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and 508 * CFG structures). 509 */ 510void delete_right(BasicBlock* b, 511 std::vector<BasicBlock::Node>::iterator* iter, 512 bool* outUpdated, 513 bool* outNeedsRescan) { 514 *outUpdated = true; 515 std::unique_ptr<Expression>* target = (*iter)->expression(); 516 ASSERT((*target)->fKind == Expression::kBinary_Kind); 517 BinaryExpression& bin = (BinaryExpression&) **target; 518 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) { 519 *target = std::move(bin.fLeft); 520 *outNeedsRescan = true; 521 return; 522 } 523 *target = std::move(bin.fLeft); 524 if (*iter == b->fNodes.begin()) { 525 *outNeedsRescan = true; 526 return; 527 } 528 --(*iter); 529 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind || 530 (*iter)->expression() != &bin.fLeft)) { 531 *outNeedsRescan = true; 532 return; 533 } 534 *iter = b->fNodes.erase(*iter); 535 ASSERT((*iter)->expression() == target); 536} 537 538/** 539 * Constructs the specified type using a single argument. 540 */ 541static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) { 542 std::vector<std::unique_ptr<Expression>> args; 543 args.push_back(std::move(v)); 544 auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args))); 545 return result; 546} 547 548/** 549 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an 550 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x). 551 */ 552static void vectorize(BasicBlock* b, 553 std::vector<BasicBlock::Node>::iterator* iter, 554 const Type& type, 555 std::unique_ptr<Expression>* otherExpression, 556 bool* outUpdated, 557 bool* outNeedsRescan) { 558 ASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind); 559 ASSERT(type.kind() == Type::kVector_Kind); 560 ASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind); 561 *outUpdated = true; 562 std::unique_ptr<Expression>* target = (*iter)->expression(); 563 if (!b->tryRemoveExpression(iter)) { 564 *target = construct(type, std::move(*otherExpression)); 565 *outNeedsRescan = true; 566 } else { 567 *target = construct(type, std::move(*otherExpression)); 568 if (!b->tryInsertExpression(iter, target)) { 569 *outNeedsRescan = true; 570 } 571 } 572} 573 574/** 575 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the 576 * left to yield vec<n>(x). 577 */ 578static void vectorize_left(BasicBlock* b, 579 std::vector<BasicBlock::Node>::iterator* iter, 580 bool* outUpdated, 581 bool* outNeedsRescan) { 582 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 583 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan); 584} 585 586/** 587 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the 588 * right to yield vec<n>(y). 589 */ 590static void vectorize_right(BasicBlock* b, 591 std::vector<BasicBlock::Node>::iterator* iter, 592 bool* outUpdated, 593 bool* outNeedsRescan) { 594 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression(); 595 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan); 596} 597 598// Mark that an expression which we were writing to is no longer being written to 599void clear_write(const Expression& expr) { 600 switch (expr.fKind) { 601 case Expression::kVariableReference_Kind: { 602 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind); 603 break; 604 } 605 case Expression::kFieldAccess_Kind: 606 clear_write(*((FieldAccess&) expr).fBase); 607 break; 608 case Expression::kSwizzle_Kind: 609 clear_write(*((Swizzle&) expr).fBase); 610 break; 611 case Expression::kIndex_Kind: 612 clear_write(*((IndexExpression&) expr).fBase); 613 break; 614 default: 615 ABORT("shouldn't be writing to this kind of expression\n"); 616 break; 617 } 618} 619 620void Compiler::simplifyExpression(DefinitionMap& definitions, 621 BasicBlock& b, 622 std::vector<BasicBlock::Node>::iterator* iter, 623 std::unordered_set<const Variable*>* undefinedVariables, 624 bool* outUpdated, 625 bool* outNeedsRescan) { 626 Expression* expr = (*iter)->expression()->get(); 627 ASSERT(expr); 628 if ((*iter)->fConstantPropagation) { 629 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions); 630 if (optimized) { 631 *outUpdated = true; 632 if (!try_replace_expression(&b, iter, &optimized)) { 633 *outNeedsRescan = true; 634 return; 635 } 636 ASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind); 637 expr = (*iter)->expression()->get(); 638 } 639 } 640 switch (expr->fKind) { 641 case Expression::kVariableReference_Kind: { 642 const Variable& var = ((VariableReference*) expr)->fVariable; 643 if (var.fStorage == Variable::kLocal_Storage && !definitions[&var] && 644 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) { 645 (*undefinedVariables).insert(&var); 646 this->error(expr->fOffset, 647 "'" + var.fName + "' has not been assigned"); 648 } 649 break; 650 } 651 case Expression::kTernary_Kind: { 652 TernaryExpression* t = (TernaryExpression*) expr; 653 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) { 654 // ternary has a constant test, replace it with either the true or 655 // false branch 656 if (((BoolLiteral&) *t->fTest).fValue) { 657 (*iter)->setExpression(std::move(t->fIfTrue)); 658 } else { 659 (*iter)->setExpression(std::move(t->fIfFalse)); 660 } 661 *outUpdated = true; 662 *outNeedsRescan = true; 663 } 664 break; 665 } 666 case Expression::kBinary_Kind: { 667 BinaryExpression* bin = (BinaryExpression*) expr; 668 if (dead_assignment(*bin)) { 669 delete_left(&b, iter, outUpdated, outNeedsRescan); 670 break; 671 } 672 // collapse useless expressions like x * 1 or x + 0 673 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) && 674 (bin->fLeft->fType.kind() != Type::kVector_Kind)) || 675 ((bin->fRight->fType.kind() != Type::kScalar_Kind) && 676 (bin->fRight->fType.kind() != Type::kVector_Kind))) { 677 break; 678 } 679 switch (bin->fOperator) { 680 case Token::STAR: 681 if (is_constant(*bin->fLeft, 1)) { 682 if (bin->fLeft->fType.kind() == Type::kVector_Kind && 683 bin->fRight->fType.kind() == Type::kScalar_Kind) { 684 // float4(1) * x -> float4(x) 685 vectorize_right(&b, iter, outUpdated, outNeedsRescan); 686 } else { 687 // 1 * x -> x 688 // 1 * float4(x) -> float4(x) 689 // float4(1) * float4(x) -> float4(x) 690 delete_left(&b, iter, outUpdated, outNeedsRescan); 691 } 692 } 693 else if (is_constant(*bin->fLeft, 0)) { 694 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 695 bin->fRight->fType.kind() == Type::kVector_Kind) { 696 // 0 * float4(x) -> float4(0) 697 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 698 } else { 699 // 0 * x -> 0 700 // float4(0) * x -> float4(0) 701 // float4(0) * float4(x) -> float4(0) 702 delete_right(&b, iter, outUpdated, outNeedsRescan); 703 } 704 } 705 else if (is_constant(*bin->fRight, 1)) { 706 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 707 bin->fRight->fType.kind() == Type::kVector_Kind) { 708 // x * float4(1) -> float4(x) 709 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 710 } else { 711 // x * 1 -> x 712 // float4(x) * 1 -> float4(x) 713 // float4(x) * float4(1) -> float4(x) 714 delete_right(&b, iter, outUpdated, outNeedsRescan); 715 } 716 } 717 else if (is_constant(*bin->fRight, 0)) { 718 if (bin->fLeft->fType.kind() == Type::kVector_Kind && 719 bin->fRight->fType.kind() == Type::kScalar_Kind) { 720 // float4(x) * 0 -> float4(0) 721 vectorize_right(&b, iter, outUpdated, outNeedsRescan); 722 } else { 723 // x * 0 -> 0 724 // x * float4(0) -> float4(0) 725 // float4(x) * float4(0) -> float4(0) 726 delete_left(&b, iter, outUpdated, outNeedsRescan); 727 } 728 } 729 break; 730 case Token::PLUS: 731 if (is_constant(*bin->fLeft, 0)) { 732 if (bin->fLeft->fType.kind() == Type::kVector_Kind && 733 bin->fRight->fType.kind() == Type::kScalar_Kind) { 734 // float4(0) + x -> float4(x) 735 vectorize_right(&b, iter, outUpdated, outNeedsRescan); 736 } else { 737 // 0 + x -> x 738 // 0 + float4(x) -> float4(x) 739 // float4(0) + float4(x) -> float4(x) 740 delete_left(&b, iter, outUpdated, outNeedsRescan); 741 } 742 } else if (is_constant(*bin->fRight, 0)) { 743 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 744 bin->fRight->fType.kind() == Type::kVector_Kind) { 745 // x + float4(0) -> float4(x) 746 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 747 } else { 748 // x + 0 -> x 749 // float4(x) + 0 -> float4(x) 750 // float4(x) + float4(0) -> float4(x) 751 delete_right(&b, iter, outUpdated, outNeedsRescan); 752 } 753 } 754 break; 755 case Token::MINUS: 756 if (is_constant(*bin->fRight, 0)) { 757 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 758 bin->fRight->fType.kind() == Type::kVector_Kind) { 759 // x - float4(0) -> float4(x) 760 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 761 } else { 762 // x - 0 -> x 763 // float4(x) - 0 -> float4(x) 764 // float4(x) - float4(0) -> float4(x) 765 delete_right(&b, iter, outUpdated, outNeedsRescan); 766 } 767 } 768 break; 769 case Token::SLASH: 770 if (is_constant(*bin->fRight, 1)) { 771 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 772 bin->fRight->fType.kind() == Type::kVector_Kind) { 773 // x / float4(1) -> float4(x) 774 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 775 } else { 776 // x / 1 -> x 777 // float4(x) / 1 -> float4(x) 778 // float4(x) / float4(1) -> float4(x) 779 delete_right(&b, iter, outUpdated, outNeedsRescan); 780 } 781 } else if (is_constant(*bin->fLeft, 0)) { 782 if (bin->fLeft->fType.kind() == Type::kScalar_Kind && 783 bin->fRight->fType.kind() == Type::kVector_Kind) { 784 // 0 / float4(x) -> float4(0) 785 vectorize_left(&b, iter, outUpdated, outNeedsRescan); 786 } else { 787 // 0 / x -> 0 788 // float4(0) / x -> float4(0) 789 // float4(0) / float4(x) -> float4(0) 790 delete_right(&b, iter, outUpdated, outNeedsRescan); 791 } 792 } 793 break; 794 case Token::PLUSEQ: 795 if (is_constant(*bin->fRight, 0)) { 796 clear_write(*bin->fLeft); 797 delete_right(&b, iter, outUpdated, outNeedsRescan); 798 } 799 break; 800 case Token::MINUSEQ: 801 if (is_constant(*bin->fRight, 0)) { 802 clear_write(*bin->fLeft); 803 delete_right(&b, iter, outUpdated, outNeedsRescan); 804 } 805 break; 806 case Token::STAREQ: 807 if (is_constant(*bin->fRight, 1)) { 808 clear_write(*bin->fLeft); 809 delete_right(&b, iter, outUpdated, outNeedsRescan); 810 } 811 break; 812 case Token::SLASHEQ: 813 if (is_constant(*bin->fRight, 1)) { 814 clear_write(*bin->fLeft); 815 delete_right(&b, iter, outUpdated, outNeedsRescan); 816 } 817 break; 818 default: 819 break; 820 } 821 } 822 default: 823 break; 824 } 825} 826 827// returns true if this statement could potentially execute a break at the current level (we ignore 828// nested loops and switches, since any breaks inside of them will merely break the loop / switch) 829static bool contains_break(Statement& s) { 830 switch (s.fKind) { 831 case Statement::kBlock_Kind: 832 for (const auto& sub : ((Block&) s).fStatements) { 833 if (contains_break(*sub)) { 834 return true; 835 } 836 } 837 return false; 838 case Statement::kBreak_Kind: 839 return true; 840 case Statement::kIf_Kind: { 841 const IfStatement& i = (IfStatement&) s; 842 return contains_break(*i.fIfTrue) || (i.fIfFalse && contains_break(*i.fIfFalse)); 843 } 844 default: 845 return false; 846 } 847} 848 849// Returns a block containing all of the statements that will be run if the given case matches 850// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be 851// broken by this call and must then be discarded). 852// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as 853// when break statements appear inside conditionals. 854static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) { 855 bool capturing = false; 856 std::vector<std::unique_ptr<Statement>*> statementPtrs; 857 for (const auto& current : s->fCases) { 858 if (current.get() == c) { 859 capturing = true; 860 } 861 if (capturing) { 862 for (auto& stmt : current->fStatements) { 863 if (stmt->fKind == Statement::kBreak_Kind) { 864 capturing = false; 865 break; 866 } 867 if (contains_break(*stmt)) { 868 return nullptr; 869 } 870 statementPtrs.push_back(&stmt); 871 } 872 if (!capturing) { 873 break; 874 } 875 } 876 } 877 std::vector<std::unique_ptr<Statement>> statements; 878 for (const auto& s : statementPtrs) { 879 statements.push_back(std::move(*s)); 880 } 881 return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols)); 882} 883 884void Compiler::simplifyStatement(DefinitionMap& definitions, 885 BasicBlock& b, 886 std::vector<BasicBlock::Node>::iterator* iter, 887 std::unordered_set<const Variable*>* undefinedVariables, 888 bool* outUpdated, 889 bool* outNeedsRescan) { 890 Statement* stmt = (*iter)->statement()->get(); 891 switch (stmt->fKind) { 892 case Statement::kVarDeclaration_Kind: { 893 const auto& varDecl = (VarDeclaration&) *stmt; 894 if (varDecl.fVar->dead() && 895 (!varDecl.fValue || 896 !varDecl.fValue->hasSideEffects())) { 897 if (varDecl.fValue) { 898 ASSERT((*iter)->statement()->get() == stmt); 899 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) { 900 *outNeedsRescan = true; 901 } 902 } 903 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 904 *outUpdated = true; 905 } 906 break; 907 } 908 case Statement::kIf_Kind: { 909 IfStatement& i = (IfStatement&) *stmt; 910 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) { 911 // constant if, collapse down to a single branch 912 if (((BoolLiteral&) *i.fTest).fValue) { 913 ASSERT(i.fIfTrue); 914 (*iter)->setStatement(std::move(i.fIfTrue)); 915 } else { 916 if (i.fIfFalse) { 917 (*iter)->setStatement(std::move(i.fIfFalse)); 918 } else { 919 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 920 } 921 } 922 *outUpdated = true; 923 *outNeedsRescan = true; 924 break; 925 } 926 if (i.fIfFalse && i.fIfFalse->isEmpty()) { 927 // else block doesn't do anything, remove it 928 i.fIfFalse.reset(); 929 *outUpdated = true; 930 *outNeedsRescan = true; 931 } 932 if (!i.fIfFalse && i.fIfTrue->isEmpty()) { 933 // if block doesn't do anything, no else block 934 if (i.fTest->hasSideEffects()) { 935 // test has side effects, keep it 936 (*iter)->setStatement(std::unique_ptr<Statement>( 937 new ExpressionStatement(std::move(i.fTest)))); 938 } else { 939 // no if, no else, no test side effects, kill the whole if 940 // statement 941 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 942 } 943 *outUpdated = true; 944 *outNeedsRescan = true; 945 } 946 break; 947 } 948 case Statement::kSwitch_Kind: { 949 SwitchStatement& s = (SwitchStatement&) *stmt; 950 if (s.fValue->isConstant()) { 951 // switch is constant, replace it with the case that matches 952 bool found = false; 953 SwitchCase* defaultCase = nullptr; 954 for (const auto& c : s.fCases) { 955 if (!c->fValue) { 956 defaultCase = c.get(); 957 continue; 958 } 959 ASSERT(c->fValue->fKind == s.fValue->fKind); 960 found = c->fValue->compareConstant(fContext, *s.fValue); 961 if (found) { 962 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get()); 963 if (newBlock) { 964 (*iter)->setStatement(std::move(newBlock)); 965 break; 966 } else { 967 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 968 this->error(s.fOffset, 969 "static switch contains non-static conditional break"); 970 s.fIsStatic = false; 971 } 972 return; // can't simplify 973 } 974 } 975 } 976 if (!found) { 977 // no matching case. use default if it exists, or kill the whole thing 978 if (defaultCase) { 979 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase); 980 if (newBlock) { 981 (*iter)->setStatement(std::move(newBlock)); 982 } else { 983 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) { 984 this->error(s.fOffset, 985 "static switch contains non-static conditional break"); 986 s.fIsStatic = false; 987 } 988 return; // can't simplify 989 } 990 } else { 991 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 992 } 993 } 994 *outUpdated = true; 995 *outNeedsRescan = true; 996 } 997 break; 998 } 999 case Statement::kExpression_Kind: { 1000 ExpressionStatement& e = (ExpressionStatement&) *stmt; 1001 ASSERT((*iter)->statement()->get() == &e); 1002 if (!e.fExpression->hasSideEffects()) { 1003 // Expression statement with no side effects, kill it 1004 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) { 1005 *outNeedsRescan = true; 1006 } 1007 ASSERT((*iter)->statement()->get() == stmt); 1008 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop())); 1009 *outUpdated = true; 1010 } 1011 break; 1012 } 1013 default: 1014 break; 1015 } 1016} 1017 1018void Compiler::scanCFG(FunctionDefinition& f) { 1019 CFG cfg = CFGGenerator().getCFG(f); 1020 this->computeDataFlow(&cfg); 1021 1022 // check for unreachable code 1023 for (size_t i = 0; i < cfg.fBlocks.size(); i++) { 1024 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() && 1025 cfg.fBlocks[i].fNodes.size()) { 1026 int offset; 1027 switch (cfg.fBlocks[i].fNodes[0].fKind) { 1028 case BasicBlock::Node::kStatement_Kind: 1029 offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset; 1030 break; 1031 case BasicBlock::Node::kExpression_Kind: 1032 offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset; 1033 break; 1034 } 1035 this->error(offset, String("unreachable")); 1036 } 1037 } 1038 if (fErrorCount) { 1039 return; 1040 } 1041 1042 // check for dead code & undefined variables, perform constant propagation 1043 std::unordered_set<const Variable*> undefinedVariables; 1044 bool updated; 1045 bool needsRescan = false; 1046 do { 1047 if (needsRescan) { 1048 cfg = CFGGenerator().getCFG(f); 1049 this->computeDataFlow(&cfg); 1050 needsRescan = false; 1051 } 1052 1053 updated = false; 1054 for (BasicBlock& b : cfg.fBlocks) { 1055 DefinitionMap definitions = b.fBefore; 1056 1057 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) { 1058 if (iter->fKind == BasicBlock::Node::kExpression_Kind) { 1059 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated, 1060 &needsRescan); 1061 } else { 1062 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated, 1063 &needsRescan); 1064 } 1065 if (needsRescan) { 1066 break; 1067 } 1068 this->addDefinitions(*iter, &definitions); 1069 } 1070 } 1071 } while (updated); 1072 ASSERT(!needsRescan); 1073 1074 // verify static ifs & switches, clean up dead variable decls 1075 for (BasicBlock& b : cfg.fBlocks) { 1076 DefinitionMap definitions = b.fBefore; 1077 1078 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) { 1079 if (iter->fKind == BasicBlock::Node::kStatement_Kind) { 1080 const Statement& s = **iter->statement(); 1081 switch (s.fKind) { 1082 case Statement::kIf_Kind: 1083 if (((const IfStatement&) s).fIsStatic && 1084 !(fFlags & kPermitInvalidStaticTests_Flag)) { 1085 this->error(s.fOffset, "static if has non-static test"); 1086 } 1087 ++iter; 1088 break; 1089 case Statement::kSwitch_Kind: 1090 if (((const SwitchStatement&) s).fIsStatic && 1091 !(fFlags & kPermitInvalidStaticTests_Flag)) { 1092 this->error(s.fOffset, "static switch has non-static test"); 1093 } 1094 ++iter; 1095 break; 1096 case Statement::kVarDeclarations_Kind: { 1097 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration; 1098 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) { 1099 if ((*varIter)->fKind == Statement::kNop_Kind) { 1100 varIter = decls.fVars.erase(varIter); 1101 } else { 1102 ++varIter; 1103 } 1104 } 1105 if (!decls.fVars.size()) { 1106 iter = b.fNodes.erase(iter); 1107 } else { 1108 ++iter; 1109 } 1110 break; 1111 } 1112 default: 1113 ++iter; 1114 break; 1115 } 1116 } else { 1117 ++iter; 1118 } 1119 } 1120 } 1121 1122 // check for missing return 1123 if (f.fDeclaration.fReturnType != *fContext.fVoid_Type) { 1124 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) { 1125 this->error(f.fOffset, String("function can exit without returning a value")); 1126 } 1127 } 1128} 1129 1130std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text, 1131 const Program::Settings& settings) { 1132 fErrorText = ""; 1133 fErrorCount = 0; 1134 fIRGenerator->start(&settings); 1135 std::vector<std::unique_ptr<ProgramElement>> elements; 1136 switch (kind) { 1137 case Program::kVertex_Kind: 1138 fIRGenerator->convertProgram(SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE), *fTypes, 1139 &elements); 1140 break; 1141 case Program::kFragment_Kind: 1142 fIRGenerator->convertProgram(SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE), *fTypes, 1143 &elements); 1144 break; 1145 case Program::kGeometry_Kind: 1146 fIRGenerator->convertProgram(SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE), *fTypes, 1147 &elements); 1148 break; 1149 case Program::kFragmentProcessor_Kind: 1150 fIRGenerator->convertProgram(SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes, 1151 &elements); 1152 break; 1153 } 1154 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin(); 1155 std::unique_ptr<String> textPtr(new String(std::move(text))); 1156 fSource = textPtr.get(); 1157 fIRGenerator->convertProgram(textPtr->c_str(), textPtr->size(), *fTypes, &elements); 1158 if (!fErrorCount) { 1159 for (auto& element : elements) { 1160 if (element->fKind == ProgramElement::kFunction_Kind) { 1161 this->scanCFG((FunctionDefinition&) *element); 1162 } 1163 } 1164 } 1165 auto result = std::unique_ptr<Program>(new Program(kind, 1166 std::move(textPtr), 1167 settings, 1168 &fContext, 1169 std::move(elements), 1170 fIRGenerator->fSymbolTable, 1171 fIRGenerator->fInputs)); 1172 fIRGenerator->finish(); 1173 fSource = nullptr; 1174 this->writeErrorCount(); 1175 if (fErrorCount) { 1176 return nullptr; 1177 } 1178 return result; 1179} 1180 1181bool Compiler::toSPIRV(const Program& program, OutputStream& out) { 1182#ifdef SK_ENABLE_SPIRV_VALIDATION 1183 StringStream buffer; 1184 fSource = program.fSource.get(); 1185 SPIRVCodeGenerator cg(&fContext, &program, this, &buffer); 1186 bool result = cg.generateCode(); 1187 fSource = nullptr; 1188 if (result) { 1189 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0); 1190 const String& data = buffer.str(); 1191 ASSERT(0 == data.size() % 4); 1192 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) { 1193 SkDebugf("SPIR-V validation error: %s\n", m); 1194 }; 1195 tools.SetMessageConsumer(dumpmsg); 1196 // Verify that the SPIR-V we produced is valid. If this assert fails, check the logs prior 1197 // to the failure to see the validation errors. 1198 ASSERT_RESULT(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4)); 1199 out.write(data.c_str(), data.size()); 1200 } 1201#else 1202 fSource = program.fSource.get(); 1203 SPIRVCodeGenerator cg(&fContext, &program, this, &out); 1204 bool result = cg.generateCode(); 1205 fSource = nullptr; 1206#endif 1207 this->writeErrorCount(); 1208 return result; 1209} 1210 1211bool Compiler::toSPIRV(const Program& program, String* out) { 1212 StringStream buffer; 1213 bool result = this->toSPIRV(program, buffer); 1214 if (result) { 1215 *out = buffer.str(); 1216 } 1217 return result; 1218} 1219 1220bool Compiler::toGLSL(const Program& program, OutputStream& out) { 1221 fSource = program.fSource.get(); 1222 GLSLCodeGenerator cg(&fContext, &program, this, &out); 1223 bool result = cg.generateCode(); 1224 fSource = nullptr; 1225 this->writeErrorCount(); 1226 return result; 1227} 1228 1229bool Compiler::toGLSL(const Program& program, String* out) { 1230 StringStream buffer; 1231 bool result = this->toGLSL(program, buffer); 1232 if (result) { 1233 *out = buffer.str(); 1234 } 1235 return result; 1236} 1237 1238bool Compiler::toCPP(const Program& program, String name, OutputStream& out) { 1239 fSource = program.fSource.get(); 1240 CPPCodeGenerator cg(&fContext, &program, this, name, &out); 1241 bool result = cg.generateCode(); 1242 fSource = nullptr; 1243 this->writeErrorCount(); 1244 return result; 1245} 1246 1247bool Compiler::toH(const Program& program, String name, OutputStream& out) { 1248 fSource = program.fSource.get(); 1249 HCodeGenerator cg(&fContext, &program, this, name, &out); 1250 bool result = cg.generateCode(); 1251 fSource = nullptr; 1252 this->writeErrorCount(); 1253 return result; 1254} 1255 1256const char* Compiler::OperatorName(Token::Kind kind) { 1257 switch (kind) { 1258 case Token::PLUS: return "+"; 1259 case Token::MINUS: return "-"; 1260 case Token::STAR: return "*"; 1261 case Token::SLASH: return "/"; 1262 case Token::PERCENT: return "%"; 1263 case Token::SHL: return "<<"; 1264 case Token::SHR: return ">>"; 1265 case Token::LOGICALNOT: return "!"; 1266 case Token::LOGICALAND: return "&&"; 1267 case Token::LOGICALOR: return "||"; 1268 case Token::LOGICALXOR: return "^^"; 1269 case Token::BITWISENOT: return "~"; 1270 case Token::BITWISEAND: return "&"; 1271 case Token::BITWISEOR: return "|"; 1272 case Token::BITWISEXOR: return "^"; 1273 case Token::EQ: return "="; 1274 case Token::EQEQ: return "=="; 1275 case Token::NEQ: return "!="; 1276 case Token::LT: return "<"; 1277 case Token::GT: return ">"; 1278 case Token::LTEQ: return "<="; 1279 case Token::GTEQ: return ">="; 1280 case Token::PLUSEQ: return "+="; 1281 case Token::MINUSEQ: return "-="; 1282 case Token::STAREQ: return "*="; 1283 case Token::SLASHEQ: return "/="; 1284 case Token::PERCENTEQ: return "%="; 1285 case Token::SHLEQ: return "<<="; 1286 case Token::SHREQ: return ">>="; 1287 case Token::LOGICALANDEQ: return "&&="; 1288 case Token::LOGICALOREQ: return "||="; 1289 case Token::LOGICALXOREQ: return "^^="; 1290 case Token::BITWISEANDEQ: return "&="; 1291 case Token::BITWISEOREQ: return "|="; 1292 case Token::BITWISEXOREQ: return "^="; 1293 case Token::PLUSPLUS: return "++"; 1294 case Token::MINUSMINUS: return "--"; 1295 case Token::COMMA: return ","; 1296 default: 1297 ABORT("unsupported operator: %d\n", kind); 1298 } 1299} 1300 1301 1302bool Compiler::IsAssignment(Token::Kind op) { 1303 switch (op) { 1304 case Token::EQ: // fall through 1305 case Token::PLUSEQ: // fall through 1306 case Token::MINUSEQ: // fall through 1307 case Token::STAREQ: // fall through 1308 case Token::SLASHEQ: // fall through 1309 case Token::PERCENTEQ: // fall through 1310 case Token::SHLEQ: // fall through 1311 case Token::SHREQ: // fall through 1312 case Token::BITWISEOREQ: // fall through 1313 case Token::BITWISEXOREQ: // fall through 1314 case Token::BITWISEANDEQ: // fall through 1315 case Token::LOGICALOREQ: // fall through 1316 case Token::LOGICALXOREQ: // fall through 1317 case Token::LOGICALANDEQ: 1318 return true; 1319 default: 1320 return false; 1321 } 1322} 1323 1324Position Compiler::position(int offset) { 1325 ASSERT(fSource); 1326 int line = 1; 1327 int column = 1; 1328 for (int i = 0; i < offset; i++) { 1329 if ((*fSource)[i] == '\n') { 1330 ++line; 1331 column = 1; 1332 } 1333 else { 1334 ++column; 1335 } 1336 } 1337 return Position(line, column); 1338} 1339 1340void Compiler::error(int offset, String msg) { 1341 fErrorCount++; 1342 Position pos = this->position(offset); 1343 fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n"; 1344} 1345 1346String Compiler::errorText() { 1347 String result = fErrorText; 1348 return result; 1349} 1350 1351void Compiler::writeErrorCount() { 1352 if (fErrorCount) { 1353 fErrorText += to_string(fErrorCount) + " error"; 1354 if (fErrorCount > 1) { 1355 fErrorText += "s"; 1356 } 1357 fErrorText += "\n"; 1358 } 1359} 1360 1361} // namespace 1362