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