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