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