blob: bb8ac60e14f4191ea2e32a25183cf0a8742d3626 [file] [log] [blame]
ethannicholasb3058bd2016-07-01 08:22:01 -07001/*
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 */
Mike Klein6ad99092016-10-26 10:35:22 -04007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLCompiler.h"
ethannicholasb3058bd2016-07-01 08:22:01 -07009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/sksl/SkSLByteCodeGenerator.h"
11#include "src/sksl/SkSLCFGGenerator.h"
12#include "src/sksl/SkSLCPPCodeGenerator.h"
13#include "src/sksl/SkSLGLSLCodeGenerator.h"
14#include "src/sksl/SkSLHCodeGenerator.h"
15#include "src/sksl/SkSLIRGenerator.h"
16#include "src/sksl/SkSLMetalCodeGenerator.h"
17#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
18#include "src/sksl/SkSLSPIRVCodeGenerator.h"
19#include "src/sksl/ir/SkSLEnum.h"
20#include "src/sksl/ir/SkSLExpression.h"
21#include "src/sksl/ir/SkSLExpressionStatement.h"
22#include "src/sksl/ir/SkSLFunctionCall.h"
23#include "src/sksl/ir/SkSLIntLiteral.h"
24#include "src/sksl/ir/SkSLModifiersDeclaration.h"
25#include "src/sksl/ir/SkSLNop.h"
26#include "src/sksl/ir/SkSLSymbolTable.h"
27#include "src/sksl/ir/SkSLTernaryExpression.h"
28#include "src/sksl/ir/SkSLUnresolvedFunction.h"
29#include "src/sksl/ir/SkSLVarDeclarations.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070030
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -040031#ifdef SK_ENABLE_SPIRV_VALIDATION
32#include "spirv-tools/libspirv.hpp"
33#endif
34
ethannicholasb3058bd2016-07-01 08:22:01 -070035// include the built-in shader symbols as static strings
36
Ethan Nicholas79707652017-11-16 11:20:11 -050037#define STRINGIFY(x) #x
38
Ethan Nicholas8da1e652019-05-24 11:01:59 -040039static const char* SKSL_GPU_INCLUDE =
40#include "sksl_gpu.inc"
41;
42
43static const char* SKSL_INTERP_INCLUDE =
44#include "sksl_interp.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070045;
46
ethannicholas5961bc92016-10-12 06:39:56 -070047static const char* SKSL_VERT_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050048#include "sksl_vert.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070049;
50
ethannicholas5961bc92016-10-12 06:39:56 -070051static const char* SKSL_FRAG_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050052#include "sksl_frag.inc"
ethannicholasb3058bd2016-07-01 08:22:01 -070053;
54
Ethan Nicholas52cad152017-02-16 16:37:32 -050055static const char* SKSL_GEOM_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050056#include "sksl_geom.inc"
Ethan Nicholas52cad152017-02-16 16:37:32 -050057;
58
Ethan Nicholas762466e2017-06-29 10:03:38 -040059static const char* SKSL_FP_INCLUDE =
Ben Wagnera56c4d22018-01-24 17:32:17 -050060#include "sksl_enums.inc"
61#include "sksl_fp.inc"
Ethan Nicholas762466e2017-06-29 10:03:38 -040062;
63
Ethan Nicholas8da1e652019-05-24 11:01:59 -040064static const char* SKSL_PIPELINE_INCLUDE =
65#include "sksl_pipeline.inc"
Ethan Nicholas0d997662019-04-08 09:46:01 -040066;
67
ethannicholasb3058bd2016-07-01 08:22:01 -070068namespace SkSL {
69
Ethan Nicholasdb80f692019-11-22 14:06:12 -050070static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
71 std::map<StringFragment, std::pair<std::unique_ptr<ProgramElement>, bool>>* target) {
72 for (auto& element : *src) {
73 switch (element->fKind) {
74 case ProgramElement::kFunction_Kind: {
75 FunctionDefinition& f = (FunctionDefinition&) *element;
76 StringFragment name = f.fDeclaration.fName;
77 SkASSERT(target->find(name) == target->end());
78 (*target)[name] = std::make_pair(std::move(element), false);
79 break;
80 }
81 case ProgramElement::kEnum_Kind: {
82 Enum& e = (Enum&) *element;
83 StringFragment name = e.fTypeName;
84 SkASSERT(target->find(name) == target->end());
85 (*target)[name] = std::make_pair(std::move(element), false);
86 break;
87 }
88 default:
89 printf("unsupported include file element\n");
90 SkASSERT(false);
91 }
92 }
93}
94
95
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040096Compiler::Compiler(Flags flags)
97: fFlags(flags)
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040098, fContext(new Context())
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -040099, fErrorCount(0) {
Ethan Nicholas8feeff92017-03-30 14:11:58 -0400100 auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
101 auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400102 fIRGenerator = new IRGenerator(fContext.get(), symbols, *this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700103 fTypes = types;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400104 #define ADD_TYPE(t) types->addWithoutOwnership(fContext->f ## t ## _Type->fName, \
105 fContext->f ## t ## _Type.get())
ethannicholasb3058bd2016-07-01 08:22:01 -0700106 ADD_TYPE(Void);
107 ADD_TYPE(Float);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400108 ADD_TYPE(Float2);
109 ADD_TYPE(Float3);
110 ADD_TYPE(Float4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400111 ADD_TYPE(Half);
112 ADD_TYPE(Half2);
113 ADD_TYPE(Half3);
114 ADD_TYPE(Half4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700115 ADD_TYPE(Double);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400116 ADD_TYPE(Double2);
117 ADD_TYPE(Double3);
118 ADD_TYPE(Double4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700119 ADD_TYPE(Int);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400120 ADD_TYPE(Int2);
121 ADD_TYPE(Int3);
122 ADD_TYPE(Int4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700123 ADD_TYPE(UInt);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400124 ADD_TYPE(UInt2);
125 ADD_TYPE(UInt3);
126 ADD_TYPE(UInt4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400127 ADD_TYPE(Short);
128 ADD_TYPE(Short2);
129 ADD_TYPE(Short3);
130 ADD_TYPE(Short4);
131 ADD_TYPE(UShort);
132 ADD_TYPE(UShort2);
133 ADD_TYPE(UShort3);
134 ADD_TYPE(UShort4);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400135 ADD_TYPE(Byte);
136 ADD_TYPE(Byte2);
137 ADD_TYPE(Byte3);
138 ADD_TYPE(Byte4);
139 ADD_TYPE(UByte);
140 ADD_TYPE(UByte2);
141 ADD_TYPE(UByte3);
142 ADD_TYPE(UByte4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700143 ADD_TYPE(Bool);
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400144 ADD_TYPE(Bool2);
145 ADD_TYPE(Bool3);
146 ADD_TYPE(Bool4);
147 ADD_TYPE(Float2x2);
148 ADD_TYPE(Float2x3);
149 ADD_TYPE(Float2x4);
150 ADD_TYPE(Float3x2);
151 ADD_TYPE(Float3x3);
152 ADD_TYPE(Float3x4);
153 ADD_TYPE(Float4x2);
154 ADD_TYPE(Float4x3);
155 ADD_TYPE(Float4x4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400156 ADD_TYPE(Half2x2);
157 ADD_TYPE(Half2x3);
158 ADD_TYPE(Half2x4);
159 ADD_TYPE(Half3x2);
160 ADD_TYPE(Half3x3);
161 ADD_TYPE(Half3x4);
162 ADD_TYPE(Half4x2);
163 ADD_TYPE(Half4x3);
164 ADD_TYPE(Half4x4);
165 ADD_TYPE(Double2x2);
166 ADD_TYPE(Double2x3);
167 ADD_TYPE(Double2x4);
168 ADD_TYPE(Double3x2);
169 ADD_TYPE(Double3x3);
170 ADD_TYPE(Double3x4);
171 ADD_TYPE(Double4x2);
172 ADD_TYPE(Double4x3);
173 ADD_TYPE(Double4x4);
ethannicholasb3058bd2016-07-01 08:22:01 -0700174 ADD_TYPE(GenType);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400175 ADD_TYPE(GenHType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700176 ADD_TYPE(GenDType);
177 ADD_TYPE(GenIType);
178 ADD_TYPE(GenUType);
179 ADD_TYPE(GenBType);
180 ADD_TYPE(Mat);
181 ADD_TYPE(Vec);
182 ADD_TYPE(GVec);
183 ADD_TYPE(GVec2);
184 ADD_TYPE(GVec3);
185 ADD_TYPE(GVec4);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400186 ADD_TYPE(HVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700187 ADD_TYPE(DVec);
188 ADD_TYPE(IVec);
189 ADD_TYPE(UVec);
Ethan Nicholasdcba08e2017-08-02 10:52:54 -0400190 ADD_TYPE(SVec);
191 ADD_TYPE(USVec);
Ruiqi Maob609e6d2018-07-17 10:19:38 -0400192 ADD_TYPE(ByteVec);
193 ADD_TYPE(UByteVec);
ethannicholasb3058bd2016-07-01 08:22:01 -0700194 ADD_TYPE(BVec);
195
196 ADD_TYPE(Sampler1D);
197 ADD_TYPE(Sampler2D);
198 ADD_TYPE(Sampler3D);
ethannicholas5961bc92016-10-12 06:39:56 -0700199 ADD_TYPE(SamplerExternalOES);
ethannicholasb3058bd2016-07-01 08:22:01 -0700200 ADD_TYPE(SamplerCube);
201 ADD_TYPE(Sampler2DRect);
202 ADD_TYPE(Sampler1DArray);
203 ADD_TYPE(Sampler2DArray);
204 ADD_TYPE(SamplerCubeArray);
205 ADD_TYPE(SamplerBuffer);
206 ADD_TYPE(Sampler2DMS);
207 ADD_TYPE(Sampler2DMSArray);
208
Brian Salomonbf7b6202016-11-11 16:08:03 -0500209 ADD_TYPE(ISampler2D);
210
Brian Salomon2a51de82016-11-16 12:06:01 -0500211 ADD_TYPE(Image2D);
212 ADD_TYPE(IImage2D);
213
Greg Daniel64773e62016-11-22 09:44:03 -0500214 ADD_TYPE(SubpassInput);
215 ADD_TYPE(SubpassInputMS);
216
ethannicholasb3058bd2016-07-01 08:22:01 -0700217 ADD_TYPE(GSampler1D);
218 ADD_TYPE(GSampler2D);
219 ADD_TYPE(GSampler3D);
220 ADD_TYPE(GSamplerCube);
221 ADD_TYPE(GSampler2DRect);
222 ADD_TYPE(GSampler1DArray);
223 ADD_TYPE(GSampler2DArray);
224 ADD_TYPE(GSamplerCubeArray);
225 ADD_TYPE(GSamplerBuffer);
226 ADD_TYPE(GSampler2DMS);
227 ADD_TYPE(GSampler2DMSArray);
228
229 ADD_TYPE(Sampler1DShadow);
230 ADD_TYPE(Sampler2DShadow);
231 ADD_TYPE(SamplerCubeShadow);
232 ADD_TYPE(Sampler2DRectShadow);
233 ADD_TYPE(Sampler1DArrayShadow);
234 ADD_TYPE(Sampler2DArrayShadow);
235 ADD_TYPE(SamplerCubeArrayShadow);
236 ADD_TYPE(GSampler2DArrayShadow);
237 ADD_TYPE(GSamplerCubeArrayShadow);
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400238 ADD_TYPE(FragmentProcessor);
Stephen Whiteff5d7a22019-07-26 17:42:06 -0400239 ADD_TYPE(Sampler);
240 ADD_TYPE(Texture2D);
ethannicholasb3058bd2016-07-01 08:22:01 -0700241
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700242 StringFragment skCapsName("sk_Caps");
243 Variable* skCaps = new Variable(-1, Modifiers(), skCapsName,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400244 *fContext->fSkCaps_Type, Variable::kGlobal_Storage);
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500245 fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
246
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700247 StringFragment skArgsName("sk_Args");
248 Variable* skArgs = new Variable(-1, Modifiers(), skArgsName,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400249 *fContext->fSkArgs_Type, Variable::kGlobal_Storage);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400250 fIRGenerator->fSymbolTable->add(skArgsName, std::unique_ptr<Symbol>(skArgs));
251
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500252 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
253 std::vector<std::unique_ptr<ProgramElement>> gpuIntrinsics;
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400254 this->processIncludeFile(Program::kFragment_Kind, SKSL_GPU_INCLUDE, strlen(SKSL_GPU_INCLUDE),
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500255 symbols, &gpuIntrinsics, &fGpuSymbolTable);
256 grab_intrinsics(&gpuIntrinsics, &fGPUIntrinsics);
257 // need to hang on to the source so that FunctionDefinition.fSource pointers in this file
258 // remain valid
259 fGpuIncludeSource = std::move(fIRGenerator->fFile);
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400260 this->processIncludeFile(Program::kVertex_Kind, SKSL_VERT_INCLUDE, strlen(SKSL_VERT_INCLUDE),
261 fGpuSymbolTable, &fVertexInclude, &fVertexSymbolTable);
262 this->processIncludeFile(Program::kFragment_Kind, SKSL_FRAG_INCLUDE, strlen(SKSL_FRAG_INCLUDE),
263 fGpuSymbolTable, &fFragmentInclude, &fFragmentSymbolTable);
264 this->processIncludeFile(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE, strlen(SKSL_GEOM_INCLUDE),
265 fGpuSymbolTable, &fGeometryInclude, &fGeometrySymbolTable);
266 this->processIncludeFile(Program::kPipelineStage_Kind, SKSL_PIPELINE_INCLUDE,
267 strlen(SKSL_PIPELINE_INCLUDE), fGpuSymbolTable, &fPipelineInclude,
268 &fPipelineSymbolTable);
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500269 std::vector<std::unique_ptr<ProgramElement>> interpIntrinsics;
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400270 this->processIncludeFile(Program::kGeneric_Kind, SKSL_INTERP_INCLUDE,
271 strlen(SKSL_INTERP_INCLUDE), symbols, &fInterpreterInclude,
272 &fInterpreterSymbolTable);
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500273 grab_intrinsics(&interpIntrinsics, &fInterpreterIntrinsics);
ethannicholasb3058bd2016-07-01 08:22:01 -0700274}
275
276Compiler::~Compiler() {
277 delete fIRGenerator;
278}
279
Ethan Nicholas8da1e652019-05-24 11:01:59 -0400280void Compiler::processIncludeFile(Program::Kind kind, const char* src, size_t length,
281 std::shared_ptr<SymbolTable> base,
282 std::vector<std::unique_ptr<ProgramElement>>* outElements,
283 std::shared_ptr<SymbolTable>* outSymbolTable) {
284 fIRGenerator->fSymbolTable = std::move(base);
285 Program::Settings settings;
286 fIRGenerator->start(&settings, nullptr);
287 fIRGenerator->convertProgram(kind, src, length, *fTypes, outElements);
288 if (this->fErrorCount) {
289 printf("Unexpected errors: %s\n", this->fErrorText.c_str());
290 }
291 SkASSERT(!fErrorCount);
292 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
293 *outSymbolTable = fIRGenerator->fSymbolTable;
294}
295
ethannicholas22f939e2016-10-13 13:25:34 -0700296// add the definition created by assigning to the lvalue to the definition set
Ethan Nicholas86a43402017-01-19 13:32:00 -0500297void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expression>* expr,
298 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700299 switch (lvalue->fKind) {
300 case Expression::kVariableReference_Kind: {
301 const Variable& var = ((VariableReference*) lvalue)->fVariable;
302 if (var.fStorage == Variable::kLocal_Storage) {
303 (*definitions)[&var] = expr;
304 }
305 break;
306 }
307 case Expression::kSwizzle_Kind:
308 // We consider the variable written to as long as at least some of its components have
309 // been written to. This will lead to some false negatives (we won't catch it if you
310 // write to foo.x and then read foo.y), but being stricter could lead to false positives
Mike Klein6ad99092016-10-26 10:35:22 -0400311 // (we write to foo.x, and then pass foo to a function which happens to only read foo.x,
312 // but since we pass foo as a whole it is flagged as an error) unless we perform a much
ethannicholas22f939e2016-10-13 13:25:34 -0700313 // more complicated whole-program analysis. This is probably good enough.
Mike Klein6ad99092016-10-26 10:35:22 -0400314 this->addDefinition(((Swizzle*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400315 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700316 definitions);
317 break;
318 case Expression::kIndex_Kind:
319 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400320 this->addDefinition(((IndexExpression*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400321 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700322 definitions);
323 break;
324 case Expression::kFieldAccess_Kind:
325 // see comments in Swizzle
Mike Klein6ad99092016-10-26 10:35:22 -0400326 this->addDefinition(((FieldAccess*) lvalue)->fBase.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400327 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
ethannicholas22f939e2016-10-13 13:25:34 -0700328 definitions);
329 break;
Ethan Nicholasa583b812018-01-18 13:32:11 -0500330 case Expression::kTernary_Kind:
331 // To simplify analysis, we just pretend that we write to both sides of the ternary.
332 // This allows for false positives (meaning we fail to detect that a variable might not
333 // have been assigned), but is preferable to false negatives.
334 this->addDefinition(((TernaryExpression*) lvalue)->fIfTrue.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400335 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
Ethan Nicholasa583b812018-01-18 13:32:11 -0500336 definitions);
337 this->addDefinition(((TernaryExpression*) lvalue)->fIfFalse.get(),
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400338 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
Ethan Nicholasa583b812018-01-18 13:32:11 -0500339 definitions);
340 break;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400341 case Expression::kExternalValue_Kind:
342 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700343 default:
344 // not an lvalue, can't happen
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400345 SkASSERT(false);
ethannicholas22f939e2016-10-13 13:25:34 -0700346 }
347}
348
349// add local variables defined by this node to the set
Mike Klein6ad99092016-10-26 10:35:22 -0400350void Compiler::addDefinitions(const BasicBlock::Node& node,
Ethan Nicholas86a43402017-01-19 13:32:00 -0500351 DefinitionMap* definitions) {
ethannicholas22f939e2016-10-13 13:25:34 -0700352 switch (node.fKind) {
353 case BasicBlock::Node::kExpression_Kind: {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400354 SkASSERT(node.expression());
Ethan Nicholascb670962017-04-20 19:31:52 -0400355 const Expression* expr = (Expression*) node.expression()->get();
Ethan Nicholas86a43402017-01-19 13:32:00 -0500356 switch (expr->fKind) {
357 case Expression::kBinary_Kind: {
358 BinaryExpression* b = (BinaryExpression*) expr;
359 if (b->fOperator == Token::EQ) {
360 this->addDefinition(b->fLeft.get(), &b->fRight, definitions);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700361 } else if (Compiler::IsAssignment(b->fOperator)) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500362 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400363 b->fLeft.get(),
364 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
365 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500366
367 }
368 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700369 }
Ethan Nicholasc6a19f12018-03-29 16:46:56 -0400370 case Expression::kFunctionCall_Kind: {
371 const FunctionCall& c = (const FunctionCall&) *expr;
372 for (size_t i = 0; i < c.fFunction.fParameters.size(); ++i) {
373 if (c.fFunction.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
374 this->addDefinition(
375 c.fArguments[i].get(),
376 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
377 definitions);
378 }
379 }
380 break;
381 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500382 case Expression::kPrefix_Kind: {
383 const PrefixExpression* p = (PrefixExpression*) expr;
384 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
385 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400386 p->fOperand.get(),
387 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
388 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500389 }
390 break;
391 }
392 case Expression::kPostfix_Kind: {
393 const PostfixExpression* p = (PostfixExpression*) expr;
394 if (p->fOperator == Token::MINUSMINUS || p->fOperator == Token::PLUSPLUS) {
395 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400396 p->fOperand.get(),
397 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
398 definitions);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500399 }
400 break;
401 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400402 case Expression::kVariableReference_Kind: {
403 const VariableReference* v = (VariableReference*) expr;
404 if (v->fRefKind != VariableReference::kRead_RefKind) {
405 this->addDefinition(
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400406 v,
407 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
408 definitions);
Ethan Nicholascb670962017-04-20 19:31:52 -0400409 }
410 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500411 default:
412 break;
ethannicholas22f939e2016-10-13 13:25:34 -0700413 }
414 break;
415 }
416 case BasicBlock::Node::kStatement_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400417 const Statement* stmt = (Statement*) node.statement()->get();
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000418 if (stmt->fKind == Statement::kVarDeclaration_Kind) {
419 VarDeclaration& vd = (VarDeclaration&) *stmt;
420 if (vd.fValue) {
421 (*definitions)[vd.fVar] = &vd.fValue;
ethannicholas22f939e2016-10-13 13:25:34 -0700422 }
423 }
424 break;
425 }
426 }
427}
428
429void Compiler::scanCFG(CFG* cfg, BlockId blockId, std::set<BlockId>* workList) {
430 BasicBlock& block = cfg->fBlocks[blockId];
431
432 // compute definitions after this block
Ethan Nicholas86a43402017-01-19 13:32:00 -0500433 DefinitionMap after = block.fBefore;
ethannicholas22f939e2016-10-13 13:25:34 -0700434 for (const BasicBlock::Node& n : block.fNodes) {
435 this->addDefinitions(n, &after);
436 }
437
438 // propagate definitions to exits
439 for (BlockId exitId : block.fExits) {
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400440 if (exitId == blockId) {
441 continue;
442 }
ethannicholas22f939e2016-10-13 13:25:34 -0700443 BasicBlock& exit = cfg->fBlocks[exitId];
444 for (const auto& pair : after) {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500445 std::unique_ptr<Expression>* e1 = pair.second;
446 auto found = exit.fBefore.find(pair.first);
447 if (found == exit.fBefore.end()) {
448 // exit has no definition for it, just copy it
449 workList->insert(exitId);
ethannicholas22f939e2016-10-13 13:25:34 -0700450 exit.fBefore[pair.first] = e1;
451 } else {
Ethan Nicholas86a43402017-01-19 13:32:00 -0500452 // exit has a (possibly different) value already defined
453 std::unique_ptr<Expression>* e2 = exit.fBefore[pair.first];
ethannicholas22f939e2016-10-13 13:25:34 -0700454 if (e1 != e2) {
455 // definition has changed, merge and add exit block to worklist
456 workList->insert(exitId);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500457 if (e1 && e2) {
458 exit.fBefore[pair.first] =
Ethan Nicholas26a9aad2018-03-27 14:10:52 -0400459 (std::unique_ptr<Expression>*) &fContext->fDefined_Expression;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500460 } else {
461 exit.fBefore[pair.first] = nullptr;
462 }
ethannicholas22f939e2016-10-13 13:25:34 -0700463 }
464 }
465 }
466 }
467}
468
469// returns a map which maps all local variables in the function to null, indicating that their value
470// is initially unknown
Ethan Nicholas86a43402017-01-19 13:32:00 -0500471static DefinitionMap compute_start_state(const CFG& cfg) {
472 DefinitionMap result;
Mike Klein6ad99092016-10-26 10:35:22 -0400473 for (const auto& block : cfg.fBlocks) {
474 for (const auto& node : block.fNodes) {
ethannicholas22f939e2016-10-13 13:25:34 -0700475 if (node.fKind == BasicBlock::Node::kStatement_Kind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400476 SkASSERT(node.statement());
Ethan Nicholascb670962017-04-20 19:31:52 -0400477 const Statement* s = node.statement()->get();
ethannicholas22f939e2016-10-13 13:25:34 -0700478 if (s->fKind == Statement::kVarDeclarations_Kind) {
479 const VarDeclarationsStatement* vd = (const VarDeclarationsStatement*) s;
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000480 for (const auto& decl : vd->fDeclaration->fVars) {
481 if (decl->fKind == Statement::kVarDeclaration_Kind) {
482 result[((VarDeclaration&) *decl).fVar] = nullptr;
483 }
Mike Klein6ad99092016-10-26 10:35:22 -0400484 }
ethannicholas22f939e2016-10-13 13:25:34 -0700485 }
486 }
487 }
488 }
489 return result;
490}
491
Ethan Nicholascb670962017-04-20 19:31:52 -0400492/**
493 * Returns true if assigning to this lvalue has no effect.
494 */
495static bool is_dead(const Expression& lvalue) {
496 switch (lvalue.fKind) {
497 case Expression::kVariableReference_Kind:
498 return ((VariableReference&) lvalue).fVariable.dead();
499 case Expression::kSwizzle_Kind:
500 return is_dead(*((Swizzle&) lvalue).fBase);
501 case Expression::kFieldAccess_Kind:
502 return is_dead(*((FieldAccess&) lvalue).fBase);
503 case Expression::kIndex_Kind: {
504 const IndexExpression& idx = (IndexExpression&) lvalue;
505 return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
506 }
Ethan Nicholasa583b812018-01-18 13:32:11 -0500507 case Expression::kTernary_Kind: {
508 const TernaryExpression& t = (TernaryExpression&) lvalue;
509 return !t.fTest->hasSideEffects() && is_dead(*t.fIfTrue) && is_dead(*t.fIfFalse);
510 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400511 case Expression::kExternalValue_Kind:
512 return false;
Ethan Nicholascb670962017-04-20 19:31:52 -0400513 default:
514 ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
515 }
516}
ethannicholas22f939e2016-10-13 13:25:34 -0700517
Ethan Nicholascb670962017-04-20 19:31:52 -0400518/**
519 * Returns true if this is an assignment which can be collapsed down to just the right hand side due
520 * to a dead target and lack of side effects on the left hand side.
521 */
522static bool dead_assignment(const BinaryExpression& b) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700523 if (!Compiler::IsAssignment(b.fOperator)) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400524 return false;
525 }
526 return is_dead(*b.fLeft);
527}
528
529void Compiler::computeDataFlow(CFG* cfg) {
530 cfg->fBlocks[cfg->fStart].fBefore = compute_start_state(*cfg);
ethannicholas22f939e2016-10-13 13:25:34 -0700531 std::set<BlockId> workList;
Ethan Nicholascb670962017-04-20 19:31:52 -0400532 for (BlockId i = 0; i < cfg->fBlocks.size(); i++) {
ethannicholas22f939e2016-10-13 13:25:34 -0700533 workList.insert(i);
534 }
535 while (workList.size()) {
536 BlockId next = *workList.begin();
537 workList.erase(workList.begin());
Ethan Nicholascb670962017-04-20 19:31:52 -0400538 this->scanCFG(cfg, next, &workList);
ethannicholas22f939e2016-10-13 13:25:34 -0700539 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400540}
541
542/**
543 * Attempts to replace the expression pointed to by iter with a new one (in both the CFG and the
544 * IR). If the expression can be cleanly removed, returns true and updates the iterator to point to
545 * the newly-inserted element. Otherwise updates only the IR and returns false (and the CFG will
546 * need to be regenerated).
547 */
548bool try_replace_expression(BasicBlock* b,
549 std::vector<BasicBlock::Node>::iterator* iter,
550 std::unique_ptr<Expression>* newExpression) {
551 std::unique_ptr<Expression>* target = (*iter)->expression();
552 if (!b->tryRemoveExpression(iter)) {
553 *target = std::move(*newExpression);
554 return false;
555 }
556 *target = std::move(*newExpression);
557 return b->tryInsertExpression(iter, target);
558}
559
560/**
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400561 * Returns true if the expression is a constant numeric literal with the specified value, or a
562 * constant vector with all elements equal to the specified value.
Ethan Nicholascb670962017-04-20 19:31:52 -0400563 */
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400564bool is_constant(const Expression& expr, double value) {
Ethan Nicholascb670962017-04-20 19:31:52 -0400565 switch (expr.fKind) {
566 case Expression::kIntLiteral_Kind:
567 return ((IntLiteral&) expr).fValue == value;
568 case Expression::kFloatLiteral_Kind:
569 return ((FloatLiteral&) expr).fValue == value;
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400570 case Expression::kConstructor_Kind: {
571 Constructor& c = (Constructor&) expr;
Ethan Nicholasd188c182019-06-10 15:55:38 -0400572 bool isFloat = c.fType.columns() > 1 ? c.fType.componentType().isFloat()
573 : c.fType.isFloat();
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400574 if (c.fType.kind() == Type::kVector_Kind && c.isConstant()) {
575 for (int i = 0; i < c.fType.columns(); ++i) {
Ethan Nicholasd188c182019-06-10 15:55:38 -0400576 if (isFloat) {
577 if (c.getFVecComponent(i) != value) {
578 return false;
579 }
580 } else if (c.getIVecComponent(i) != value) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400581 return false;
582 }
583 }
584 return true;
585 }
586 return false;
587 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400588 default:
589 return false;
590 }
591}
592
593/**
594 * Collapses the binary expression pointed to by iter down to just the right side (in both the IR
595 * and CFG structures).
596 */
597void delete_left(BasicBlock* b,
598 std::vector<BasicBlock::Node>::iterator* iter,
599 bool* outUpdated,
600 bool* outNeedsRescan) {
601 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400602 std::unique_ptr<Expression>* target = (*iter)->expression();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400603 SkASSERT((*target)->fKind == Expression::kBinary_Kind);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400604 BinaryExpression& bin = (BinaryExpression&) **target;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400605 SkASSERT(!bin.fLeft->hasSideEffects());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400606 bool result;
607 if (bin.fOperator == Token::EQ) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400608 result = b->tryRemoveLValueBefore(iter, bin.fLeft.get());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400609 } else {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400610 result = b->tryRemoveExpressionBefore(iter, bin.fLeft.get());
Ethan Nicholascb670962017-04-20 19:31:52 -0400611 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400612 *target = std::move(bin.fRight);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400613 if (!result) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400614 *outNeedsRescan = true;
615 return;
616 }
617 if (*iter == b->fNodes.begin()) {
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400618 *outNeedsRescan = true;
619 return;
620 }
621 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400622 if ((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
623 (*iter)->expression() != &bin.fRight) {
624 *outNeedsRescan = true;
625 return;
626 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400627 *iter = b->fNodes.erase(*iter);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400628 SkASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400629}
630
631/**
632 * Collapses the binary expression pointed to by iter down to just the left side (in both the IR and
633 * CFG structures).
634 */
635void delete_right(BasicBlock* b,
636 std::vector<BasicBlock::Node>::iterator* iter,
637 bool* outUpdated,
638 bool* outNeedsRescan) {
639 *outUpdated = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400640 std::unique_ptr<Expression>* target = (*iter)->expression();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400641 SkASSERT((*target)->fKind == Expression::kBinary_Kind);
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400642 BinaryExpression& bin = (BinaryExpression&) **target;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400643 SkASSERT(!bin.fRight->hasSideEffects());
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400644 if (!b->tryRemoveExpressionBefore(iter, bin.fRight.get())) {
645 *target = std::move(bin.fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400646 *outNeedsRescan = true;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400647 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400648 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400649 *target = std::move(bin.fLeft);
650 if (*iter == b->fNodes.begin()) {
651 *outNeedsRescan = true;
652 return;
653 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400654 --(*iter);
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400655 if (((*iter)->fKind != BasicBlock::Node::kExpression_Kind ||
656 (*iter)->expression() != &bin.fLeft)) {
657 *outNeedsRescan = true;
658 return;
659 }
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400660 *iter = b->fNodes.erase(*iter);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400661 SkASSERT((*iter)->expression() == target);
Ethan Nicholascb670962017-04-20 19:31:52 -0400662}
663
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400664/**
665 * Constructs the specified type using a single argument.
666 */
667static std::unique_ptr<Expression> construct(const Type& type, std::unique_ptr<Expression> v) {
668 std::vector<std::unique_ptr<Expression>> args;
669 args.push_back(std::move(v));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700670 auto result = std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400671 return result;
672}
673
674/**
675 * Used in the implementations of vectorize_left and vectorize_right. Given a vector type and an
676 * expression x, deletes the expression pointed to by iter and replaces it with <type>(x).
677 */
678static void vectorize(BasicBlock* b,
679 std::vector<BasicBlock::Node>::iterator* iter,
680 const Type& type,
681 std::unique_ptr<Expression>* otherExpression,
682 bool* outUpdated,
683 bool* outNeedsRescan) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400684 SkASSERT((*(*iter)->expression())->fKind == Expression::kBinary_Kind);
685 SkASSERT(type.kind() == Type::kVector_Kind);
686 SkASSERT((*otherExpression)->fType.kind() == Type::kScalar_Kind);
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400687 *outUpdated = true;
688 std::unique_ptr<Expression>* target = (*iter)->expression();
689 if (!b->tryRemoveExpression(iter)) {
690 *target = construct(type, std::move(*otherExpression));
691 *outNeedsRescan = true;
692 } else {
693 *target = construct(type, std::move(*otherExpression));
694 if (!b->tryInsertExpression(iter, target)) {
695 *outNeedsRescan = true;
696 }
697 }
698}
699
700/**
701 * Given a binary expression of the form x <op> vec<n>(y), deletes the right side and vectorizes the
702 * left to yield vec<n>(x).
703 */
704static void vectorize_left(BasicBlock* b,
705 std::vector<BasicBlock::Node>::iterator* iter,
706 bool* outUpdated,
707 bool* outNeedsRescan) {
708 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
709 vectorize(b, iter, bin.fRight->fType, &bin.fLeft, outUpdated, outNeedsRescan);
710}
711
712/**
713 * Given a binary expression of the form vec<n>(x) <op> y, deletes the left side and vectorizes the
714 * right to yield vec<n>(y).
715 */
716static void vectorize_right(BasicBlock* b,
717 std::vector<BasicBlock::Node>::iterator* iter,
718 bool* outUpdated,
719 bool* outNeedsRescan) {
720 BinaryExpression& bin = (BinaryExpression&) **(*iter)->expression();
721 vectorize(b, iter, bin.fLeft->fType, &bin.fRight, outUpdated, outNeedsRescan);
722}
723
724// Mark that an expression which we were writing to is no longer being written to
725void clear_write(const Expression& expr) {
726 switch (expr.fKind) {
727 case Expression::kVariableReference_Kind: {
728 ((VariableReference&) expr).setRefKind(VariableReference::kRead_RefKind);
729 break;
730 }
731 case Expression::kFieldAccess_Kind:
732 clear_write(*((FieldAccess&) expr).fBase);
733 break;
734 case Expression::kSwizzle_Kind:
735 clear_write(*((Swizzle&) expr).fBase);
736 break;
737 case Expression::kIndex_Kind:
738 clear_write(*((IndexExpression&) expr).fBase);
739 break;
740 default:
741 ABORT("shouldn't be writing to this kind of expression\n");
742 break;
743 }
744}
745
Ethan Nicholascb670962017-04-20 19:31:52 -0400746void Compiler::simplifyExpression(DefinitionMap& definitions,
747 BasicBlock& b,
748 std::vector<BasicBlock::Node>::iterator* iter,
749 std::unordered_set<const Variable*>* undefinedVariables,
750 bool* outUpdated,
751 bool* outNeedsRescan) {
752 Expression* expr = (*iter)->expression()->get();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400753 SkASSERT(expr);
Ethan Nicholascb670962017-04-20 19:31:52 -0400754 if ((*iter)->fConstantPropagation) {
755 std::unique_ptr<Expression> optimized = expr->constantPropagate(*fIRGenerator, definitions);
756 if (optimized) {
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400757 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -0400758 if (!try_replace_expression(&b, iter, &optimized)) {
759 *outNeedsRescan = true;
Ethan Nicholas4b330df2017-05-17 10:52:55 -0400760 return;
Ethan Nicholascb670962017-04-20 19:31:52 -0400761 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400762 SkASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
Ethan Nicholascb670962017-04-20 19:31:52 -0400763 expr = (*iter)->expression()->get();
Ethan Nicholascb670962017-04-20 19:31:52 -0400764 }
765 }
766 switch (expr->fKind) {
767 case Expression::kVariableReference_Kind: {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -0400768 const VariableReference& ref = (VariableReference&) *expr;
769 const Variable& var = ref.fVariable;
770 if (ref.refKind() != VariableReference::kWrite_RefKind &&
771 ref.refKind() != VariableReference::kPointer_RefKind &&
772 var.fStorage == Variable::kLocal_Storage && !definitions[&var] &&
Ethan Nicholascb670962017-04-20 19:31:52 -0400773 (*undefinedVariables).find(&var) == (*undefinedVariables).end()) {
774 (*undefinedVariables).insert(&var);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000775 this->error(expr->fOffset,
776 "'" + var.fName + "' has not been assigned");
Ethan Nicholascb670962017-04-20 19:31:52 -0400777 }
778 break;
779 }
780 case Expression::kTernary_Kind: {
781 TernaryExpression* t = (TernaryExpression*) expr;
782 if (t->fTest->fKind == Expression::kBoolLiteral_Kind) {
783 // ternary has a constant test, replace it with either the true or
784 // false branch
785 if (((BoolLiteral&) *t->fTest).fValue) {
786 (*iter)->setExpression(std::move(t->fIfTrue));
787 } else {
788 (*iter)->setExpression(std::move(t->fIfFalse));
789 }
790 *outUpdated = true;
791 *outNeedsRescan = true;
792 }
793 break;
794 }
795 case Expression::kBinary_Kind: {
Ethan Nicholascb670962017-04-20 19:31:52 -0400796 BinaryExpression* bin = (BinaryExpression*) expr;
Ethan Nicholasc2371a42017-05-05 10:04:06 -0400797 if (dead_assignment(*bin)) {
798 delete_left(&b, iter, outUpdated, outNeedsRescan);
799 break;
800 }
801 // collapse useless expressions like x * 1 or x + 0
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400802 if (((bin->fLeft->fType.kind() != Type::kScalar_Kind) &&
803 (bin->fLeft->fType.kind() != Type::kVector_Kind)) ||
804 ((bin->fRight->fType.kind() != Type::kScalar_Kind) &&
805 (bin->fRight->fType.kind() != Type::kVector_Kind))) {
806 break;
807 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400808 switch (bin->fOperator) {
809 case Token::STAR:
810 if (is_constant(*bin->fLeft, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400811 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
812 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400813 // float4(1) * x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400814 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
815 } else {
816 // 1 * x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400817 // 1 * float4(x) -> float4(x)
818 // float4(1) * float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400819 delete_left(&b, iter, outUpdated, outNeedsRescan);
820 }
821 }
822 else if (is_constant(*bin->fLeft, 0)) {
823 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500824 bin->fRight->fType.kind() == Type::kVector_Kind &&
825 !bin->fRight->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400826 // 0 * float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400827 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
828 } else {
829 // 0 * x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400830 // float4(0) * x -> float4(0)
831 // float4(0) * float4(x) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500832 if (!bin->fRight->hasSideEffects()) {
833 delete_right(&b, iter, outUpdated, outNeedsRescan);
834 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400835 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400836 }
837 else if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400838 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
839 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400840 // x * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400841 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
842 } else {
843 // x * 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400844 // float4(x) * 1 -> float4(x)
845 // float4(x) * float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400846 delete_right(&b, iter, outUpdated, outNeedsRescan);
847 }
848 }
849 else if (is_constant(*bin->fRight, 0)) {
850 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500851 bin->fRight->fType.kind() == Type::kScalar_Kind &&
852 !bin->fLeft->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400853 // float4(x) * 0 -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400854 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
855 } else {
856 // x * 0 -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400857 // x * float4(0) -> float4(0)
858 // float4(x) * float4(0) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500859 if (!bin->fLeft->hasSideEffects()) {
860 delete_left(&b, iter, outUpdated, outNeedsRescan);
861 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400862 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400863 }
864 break;
Ethan Nicholas56e42712017-04-21 10:23:37 -0400865 case Token::PLUS:
Ethan Nicholascb670962017-04-20 19:31:52 -0400866 if (is_constant(*bin->fLeft, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400867 if (bin->fLeft->fType.kind() == Type::kVector_Kind &&
868 bin->fRight->fType.kind() == Type::kScalar_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400869 // float4(0) + x -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400870 vectorize_right(&b, iter, outUpdated, outNeedsRescan);
871 } else {
872 // 0 + x -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400873 // 0 + float4(x) -> float4(x)
874 // float4(0) + float4(x) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400875 delete_left(&b, iter, outUpdated, outNeedsRescan);
876 }
877 } else if (is_constant(*bin->fRight, 0)) {
878 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
879 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400880 // x + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400881 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
882 } else {
883 // x + 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400884 // float4(x) + 0 -> float4(x)
885 // float4(x) + float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400886 delete_right(&b, iter, outUpdated, outNeedsRescan);
887 }
Ethan Nicholas56e42712017-04-21 10:23:37 -0400888 }
889 break;
890 case Token::MINUS:
891 if (is_constant(*bin->fRight, 0)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400892 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
893 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400894 // x - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400895 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
896 } else {
897 // x - 0 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400898 // float4(x) - 0 -> float4(x)
899 // float4(x) - float4(0) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400900 delete_right(&b, iter, outUpdated, outNeedsRescan);
901 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400902 }
903 break;
904 case Token::SLASH:
905 if (is_constant(*bin->fRight, 1)) {
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400906 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
907 bin->fRight->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400908 // x / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400909 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
910 } else {
911 // x / 1 -> x
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400912 // float4(x) / 1 -> float4(x)
913 // float4(x) / float4(1) -> float4(x)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400914 delete_right(&b, iter, outUpdated, outNeedsRescan);
915 }
916 } else if (is_constant(*bin->fLeft, 0)) {
917 if (bin->fLeft->fType.kind() == Type::kScalar_Kind &&
Ethan Nicholas08dae922018-01-23 10:31:56 -0500918 bin->fRight->fType.kind() == Type::kVector_Kind &&
919 !bin->fRight->hasSideEffects()) {
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400920 // 0 / float4(x) -> float4(0)
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400921 vectorize_left(&b, iter, outUpdated, outNeedsRescan);
922 } else {
923 // 0 / x -> 0
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400924 // float4(0) / x -> float4(0)
925 // float4(0) / float4(x) -> float4(0)
Ethan Nicholas51493ee2017-12-11 12:34:33 -0500926 if (!bin->fRight->hasSideEffects()) {
927 delete_right(&b, iter, outUpdated, outNeedsRescan);
928 }
Ethan Nicholasfe53e582017-04-27 16:24:51 -0400929 }
930 }
931 break;
932 case Token::PLUSEQ:
933 if (is_constant(*bin->fRight, 0)) {
934 clear_write(*bin->fLeft);
935 delete_right(&b, iter, outUpdated, outNeedsRescan);
936 }
937 break;
938 case Token::MINUSEQ:
939 if (is_constant(*bin->fRight, 0)) {
940 clear_write(*bin->fLeft);
941 delete_right(&b, iter, outUpdated, outNeedsRescan);
942 }
943 break;
944 case Token::STAREQ:
945 if (is_constant(*bin->fRight, 1)) {
946 clear_write(*bin->fLeft);
947 delete_right(&b, iter, outUpdated, outNeedsRescan);
948 }
949 break;
950 case Token::SLASHEQ:
951 if (is_constant(*bin->fRight, 1)) {
952 clear_write(*bin->fLeft);
Ethan Nicholascb670962017-04-20 19:31:52 -0400953 delete_right(&b, iter, outUpdated, outNeedsRescan);
954 }
955 break;
956 default:
957 break;
958 }
Ethan Nicholas409f6f02019-09-17 12:34:39 -0400959 break;
960 }
961 case Expression::kSwizzle_Kind: {
962 Swizzle& s = (Swizzle&) *expr;
963 // detect identity swizzles like foo.rgba
964 if ((int) s.fComponents.size() == s.fBase->fType.columns()) {
965 bool identity = true;
966 for (int i = 0; i < (int) s.fComponents.size(); ++i) {
967 if (s.fComponents[i] != i) {
968 identity = false;
969 break;
970 }
971 }
972 if (identity) {
973 *outUpdated = true;
974 if (!try_replace_expression(&b, iter, &s.fBase)) {
975 *outNeedsRescan = true;
976 return;
977 }
978 SkASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
979 break;
980 }
981 }
982 // detect swizzles of swizzles, e.g. replace foo.argb.r000 with foo.a000
983 if (s.fBase->fKind == Expression::kSwizzle_Kind) {
984 Swizzle& base = (Swizzle&) *s.fBase;
985 std::vector<int> final;
986 for (int c : s.fComponents) {
987 if (c == SKSL_SWIZZLE_0 || c == SKSL_SWIZZLE_1) {
988 final.push_back(c);
989 } else {
990 final.push_back(base.fComponents[c]);
991 }
992 }
993 *outUpdated = true;
994 std::unique_ptr<Expression> replacement(new Swizzle(*fContext, base.fBase->clone(),
995 std::move(final)));
996 if (!try_replace_expression(&b, iter, &replacement)) {
997 *outNeedsRescan = true;
998 return;
999 }
1000 SkASSERT((*iter)->fKind == BasicBlock::Node::kExpression_Kind);
1001 break;
1002 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001003 }
1004 default:
1005 break;
1006 }
1007}
1008
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001009// returns true if this statement could potentially execute a break at the current level (we ignore
1010// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
Ethan Nicholas5005a222018-08-24 13:06:27 -04001011static bool contains_conditional_break(Statement& s, bool inConditional) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001012 switch (s.fKind) {
1013 case Statement::kBlock_Kind:
1014 for (const auto& sub : ((Block&) s).fStatements) {
Ethan Nicholas5005a222018-08-24 13:06:27 -04001015 if (contains_conditional_break(*sub, inConditional)) {
1016 return true;
1017 }
1018 }
1019 return false;
1020 case Statement::kBreak_Kind:
1021 return inConditional;
1022 case Statement::kIf_Kind: {
1023 const IfStatement& i = (IfStatement&) s;
1024 return contains_conditional_break(*i.fIfTrue, true) ||
1025 (i.fIfFalse && contains_conditional_break(*i.fIfFalse, true));
1026 }
1027 default:
1028 return false;
1029 }
1030}
1031
1032// returns true if this statement definitely executes a break at the current level (we ignore
1033// nested loops and switches, since any breaks inside of them will merely break the loop / switch)
1034static bool contains_unconditional_break(Statement& s) {
1035 switch (s.fKind) {
1036 case Statement::kBlock_Kind:
1037 for (const auto& sub : ((Block&) s).fStatements) {
1038 if (contains_unconditional_break(*sub)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001039 return true;
1040 }
1041 }
1042 return false;
1043 case Statement::kBreak_Kind:
1044 return true;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001045 default:
1046 return false;
1047 }
1048}
1049
1050// Returns a block containing all of the statements that will be run if the given case matches
1051// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
1052// broken by this call and must then be discarded).
1053// Returns null (and leaves the switch unmodified) if no such simple reduction is possible, such as
1054// when break statements appear inside conditionals.
1055static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase* c) {
1056 bool capturing = false;
1057 std::vector<std::unique_ptr<Statement>*> statementPtrs;
1058 for (const auto& current : s->fCases) {
1059 if (current.get() == c) {
1060 capturing = true;
1061 }
1062 if (capturing) {
1063 for (auto& stmt : current->fStatements) {
Ethan Nicholas5005a222018-08-24 13:06:27 -04001064 if (contains_conditional_break(*stmt, s->fKind == Statement::kIf_Kind)) {
1065 return nullptr;
1066 }
1067 if (contains_unconditional_break(*stmt)) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001068 capturing = false;
1069 break;
1070 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001071 statementPtrs.push_back(&stmt);
1072 }
1073 if (!capturing) {
1074 break;
1075 }
1076 }
1077 }
1078 std::vector<std::unique_ptr<Statement>> statements;
1079 for (const auto& s : statementPtrs) {
1080 statements.push_back(std::move(*s));
1081 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001082 return std::unique_ptr<Statement>(new Block(-1, std::move(statements), s->fSymbols));
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001083}
1084
Ethan Nicholascb670962017-04-20 19:31:52 -04001085void Compiler::simplifyStatement(DefinitionMap& definitions,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001086 BasicBlock& b,
1087 std::vector<BasicBlock::Node>::iterator* iter,
1088 std::unordered_set<const Variable*>* undefinedVariables,
1089 bool* outUpdated,
1090 bool* outNeedsRescan) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001091 Statement* stmt = (*iter)->statement()->get();
1092 switch (stmt->fKind) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001093 case Statement::kVarDeclaration_Kind: {
1094 const auto& varDecl = (VarDeclaration&) *stmt;
1095 if (varDecl.fVar->dead() &&
1096 (!varDecl.fValue ||
1097 !varDecl.fValue->hasSideEffects())) {
1098 if (varDecl.fValue) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001099 SkASSERT((*iter)->statement()->get() == stmt);
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001100 if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) {
1101 *outNeedsRescan = true;
Ethan Nicholascb670962017-04-20 19:31:52 -04001102 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001103 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001104 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001105 *outUpdated = true;
Ethan Nicholascb670962017-04-20 19:31:52 -04001106 }
1107 break;
1108 }
1109 case Statement::kIf_Kind: {
1110 IfStatement& i = (IfStatement&) *stmt;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001111 if (i.fTest->fKind == Expression::kBoolLiteral_Kind) {
1112 // constant if, collapse down to a single branch
1113 if (((BoolLiteral&) *i.fTest).fValue) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001114 SkASSERT(i.fIfTrue);
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001115 (*iter)->setStatement(std::move(i.fIfTrue));
1116 } else {
1117 if (i.fIfFalse) {
1118 (*iter)->setStatement(std::move(i.fIfFalse));
1119 } else {
1120 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1121 }
1122 }
1123 *outUpdated = true;
1124 *outNeedsRescan = true;
1125 break;
1126 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001127 if (i.fIfFalse && i.fIfFalse->isEmpty()) {
1128 // else block doesn't do anything, remove it
1129 i.fIfFalse.reset();
1130 *outUpdated = true;
1131 *outNeedsRescan = true;
1132 }
1133 if (!i.fIfFalse && i.fIfTrue->isEmpty()) {
1134 // if block doesn't do anything, no else block
1135 if (i.fTest->hasSideEffects()) {
1136 // test has side effects, keep it
1137 (*iter)->setStatement(std::unique_ptr<Statement>(
1138 new ExpressionStatement(std::move(i.fTest))));
1139 } else {
1140 // no if, no else, no test side effects, kill the whole if
1141 // statement
1142 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1143 }
1144 *outUpdated = true;
1145 *outNeedsRescan = true;
1146 }
1147 break;
1148 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001149 case Statement::kSwitch_Kind: {
1150 SwitchStatement& s = (SwitchStatement&) *stmt;
1151 if (s.fValue->isConstant()) {
1152 // switch is constant, replace it with the case that matches
1153 bool found = false;
1154 SwitchCase* defaultCase = nullptr;
1155 for (const auto& c : s.fCases) {
1156 if (!c->fValue) {
1157 defaultCase = c.get();
1158 continue;
1159 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001160 SkASSERT(c->fValue->fKind == s.fValue->fKind);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001161 found = c->fValue->compareConstant(*fContext, *s.fValue);
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001162 if (found) {
1163 std::unique_ptr<Statement> newBlock = block_for_case(&s, c.get());
1164 if (newBlock) {
1165 (*iter)->setStatement(std::move(newBlock));
1166 break;
1167 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001168 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001169 this->error(s.fOffset,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001170 "static switch contains non-static conditional break");
1171 s.fIsStatic = false;
1172 }
1173 return; // can't simplify
1174 }
1175 }
1176 }
1177 if (!found) {
1178 // no matching case. use default if it exists, or kill the whole thing
1179 if (defaultCase) {
1180 std::unique_ptr<Statement> newBlock = block_for_case(&s, defaultCase);
1181 if (newBlock) {
1182 (*iter)->setStatement(std::move(newBlock));
1183 } else {
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001184 if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001185 this->error(s.fOffset,
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001186 "static switch contains non-static conditional break");
1187 s.fIsStatic = false;
1188 }
1189 return; // can't simplify
1190 }
1191 } else {
1192 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1193 }
1194 }
1195 *outUpdated = true;
1196 *outNeedsRescan = true;
1197 }
1198 break;
1199 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001200 case Statement::kExpression_Kind: {
1201 ExpressionStatement& e = (ExpressionStatement&) *stmt;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001202 SkASSERT((*iter)->statement()->get() == &e);
Ethan Nicholascb670962017-04-20 19:31:52 -04001203 if (!e.fExpression->hasSideEffects()) {
1204 // Expression statement with no side effects, kill it
1205 if (!b.tryRemoveExpressionBefore(iter, e.fExpression.get())) {
1206 *outNeedsRescan = true;
1207 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001208 SkASSERT((*iter)->statement()->get() == stmt);
Ethan Nicholascb670962017-04-20 19:31:52 -04001209 (*iter)->setStatement(std::unique_ptr<Statement>(new Nop()));
1210 *outUpdated = true;
1211 }
1212 break;
1213 }
1214 default:
1215 break;
1216 }
1217}
1218
1219void Compiler::scanCFG(FunctionDefinition& f) {
1220 CFG cfg = CFGGenerator().getCFG(f);
1221 this->computeDataFlow(&cfg);
ethannicholas22f939e2016-10-13 13:25:34 -07001222
1223 // check for unreachable code
1224 for (size_t i = 0; i < cfg.fBlocks.size(); i++) {
Mike Klein6ad99092016-10-26 10:35:22 -04001225 if (i != cfg.fStart && !cfg.fBlocks[i].fEntrances.size() &&
ethannicholas22f939e2016-10-13 13:25:34 -07001226 cfg.fBlocks[i].fNodes.size()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001227 int offset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001228 switch (cfg.fBlocks[i].fNodes[0].fKind) {
1229 case BasicBlock::Node::kStatement_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001230 offset = (*cfg.fBlocks[i].fNodes[0].statement())->fOffset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001231 break;
1232 case BasicBlock::Node::kExpression_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001233 offset = (*cfg.fBlocks[i].fNodes[0].expression())->fOffset;
Ethan Nicholas86a43402017-01-19 13:32:00 -05001234 break;
1235 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001236 this->error(offset, String("unreachable"));
ethannicholas22f939e2016-10-13 13:25:34 -07001237 }
1238 }
1239 if (fErrorCount) {
1240 return;
1241 }
1242
Ethan Nicholascb670962017-04-20 19:31:52 -04001243 // check for dead code & undefined variables, perform constant propagation
1244 std::unordered_set<const Variable*> undefinedVariables;
1245 bool updated;
1246 bool needsRescan = false;
1247 do {
1248 if (needsRescan) {
1249 cfg = CFGGenerator().getCFG(f);
1250 this->computeDataFlow(&cfg);
1251 needsRescan = false;
Ethan Nicholas113628d2017-02-02 16:11:39 -05001252 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001253
1254 updated = false;
1255 for (BasicBlock& b : cfg.fBlocks) {
1256 DefinitionMap definitions = b.fBefore;
1257
1258 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan; ++iter) {
1259 if (iter->fKind == BasicBlock::Node::kExpression_Kind) {
1260 this->simplifyExpression(definitions, b, &iter, &undefinedVariables, &updated,
1261 &needsRescan);
1262 } else {
1263 this->simplifyStatement(definitions, b, &iter, &undefinedVariables, &updated,
1264 &needsRescan);
1265 }
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001266 if (needsRescan) {
1267 break;
1268 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001269 this->addDefinitions(*iter, &definitions);
1270 }
1271 }
1272 } while (updated);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001273 SkASSERT(!needsRescan);
ethannicholas22f939e2016-10-13 13:25:34 -07001274
Ethan Nicholas91a10532017-06-22 11:24:38 -04001275 // verify static ifs & switches, clean up dead variable decls
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001276 for (BasicBlock& b : cfg.fBlocks) {
1277 DefinitionMap definitions = b.fBefore;
1278
Ethan Nicholas91a10532017-06-22 11:24:38 -04001279 for (auto iter = b.fNodes.begin(); iter != b.fNodes.end() && !needsRescan;) {
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001280 if (iter->fKind == BasicBlock::Node::kStatement_Kind) {
1281 const Statement& s = **iter->statement();
1282 switch (s.fKind) {
1283 case Statement::kIf_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001284 if (((const IfStatement&) s).fIsStatic &&
1285 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001286 this->error(s.fOffset, "static if has non-static test");
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001287 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001288 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001289 break;
1290 case Statement::kSwitch_Kind:
Ethan Nicholas6e1cbc02017-07-14 10:12:15 -04001291 if (((const SwitchStatement&) s).fIsStatic &&
1292 !(fFlags & kPermitInvalidStaticTests_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001293 this->error(s.fOffset, "static switch has non-static test");
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001294 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001295 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001296 break;
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001297 case Statement::kVarDeclarations_Kind: {
1298 VarDeclarations& decls = *((VarDeclarationsStatement&) s).fDeclaration;
1299 for (auto varIter = decls.fVars.begin(); varIter != decls.fVars.end();) {
1300 if ((*varIter)->fKind == Statement::kNop_Kind) {
1301 varIter = decls.fVars.erase(varIter);
1302 } else {
1303 ++varIter;
1304 }
1305 }
1306 if (!decls.fVars.size()) {
1307 iter = b.fNodes.erase(iter);
1308 } else {
1309 ++iter;
1310 }
1311 break;
1312 }
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001313 default:
Ethan Nicholas91a10532017-06-22 11:24:38 -04001314 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001315 break;
1316 }
Ethan Nicholas91a10532017-06-22 11:24:38 -04001317 } else {
1318 ++iter;
Ethan Nicholas5ac13c22017-05-10 15:06:17 -04001319 }
1320 }
1321 }
1322
ethannicholas22f939e2016-10-13 13:25:34 -07001323 // check for missing return
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001324 if (f.fDeclaration.fReturnType != *fContext->fVoid_Type) {
ethannicholas22f939e2016-10-13 13:25:34 -07001325 if (cfg.fBlocks[cfg.fExit].fEntrances.size()) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001326 this->error(f.fOffset, String("function '" + String(f.fDeclaration.fName) +
1327 "' can exit without returning a value"));
ethannicholas22f939e2016-10-13 13:25:34 -07001328 }
1329 }
1330}
1331
Ethan Nicholas91164d12019-05-15 15:29:54 -04001332void Compiler::registerExternalValue(ExternalValue* value) {
1333 fIRGenerator->fRootSymbolTable->addWithoutOwnership(value->fName, value);
1334}
1335
1336Symbol* Compiler::takeOwnership(std::unique_ptr<Symbol> symbol) {
1337 return fIRGenerator->fRootSymbolTable->takeOwnership(std::move(symbol));
1338}
1339
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001340std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, String text,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001341 const Program::Settings& settings) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001342 fErrorText = "";
1343 fErrorCount = 0;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001344 std::vector<std::unique_ptr<ProgramElement>>* inherited;
ethannicholasd598f792016-07-25 10:08:54 -07001345 std::vector<std::unique_ptr<ProgramElement>> elements;
ethannicholasb3058bd2016-07-01 08:22:01 -07001346 switch (kind) {
1347 case Program::kVertex_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001348 inherited = &fVertexInclude;
1349 fIRGenerator->fSymbolTable = fVertexSymbolTable;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001350 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001351 fIRGenerator->start(&settings, inherited);
ethannicholasb3058bd2016-07-01 08:22:01 -07001352 break;
1353 case Program::kFragment_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001354 inherited = &fFragmentInclude;
1355 fIRGenerator->fSymbolTable = fFragmentSymbolTable;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001356 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001357 fIRGenerator->start(&settings, inherited);
ethannicholasb3058bd2016-07-01 08:22:01 -07001358 break;
Ethan Nicholas52cad152017-02-16 16:37:32 -05001359 case Program::kGeometry_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001360 inherited = &fGeometryInclude;
1361 fIRGenerator->fSymbolTable = fGeometrySymbolTable;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001362 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001363 fIRGenerator->start(&settings, inherited);
Ethan Nicholas52cad152017-02-16 16:37:32 -05001364 break;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001365 case Program::kFragmentProcessor_Kind:
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001366 inherited = nullptr;
Ethan Nicholas8da1e652019-05-24 11:01:59 -04001367 fIRGenerator->fSymbolTable = fGpuSymbolTable;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001368 fIRGenerator->start(&settings, nullptr);
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001369 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
Robert Phillipsfe8da172018-01-24 14:52:02 +00001370 fIRGenerator->convertProgram(kind, SKSL_FP_INCLUDE, strlen(SKSL_FP_INCLUDE), *fTypes,
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001371 &elements);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001372 fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
Ethan Nicholas762466e2017-06-29 10:03:38 -04001373 break;
Ethan Nicholas8da1e652019-05-24 11:01:59 -04001374 case Program::kPipelineStage_Kind:
1375 inherited = &fPipelineInclude;
1376 fIRGenerator->fSymbolTable = fPipelineSymbolTable;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001377 fIRGenerator->fIntrinsics = &fGPUIntrinsics;
Ethan Nicholas8da1e652019-05-24 11:01:59 -04001378 fIRGenerator->start(&settings, inherited);
1379 break;
Ethan Nicholas746035a2019-04-23 13:31:09 -04001380 case Program::kGeneric_Kind:
Ethan Nicholas8da1e652019-05-24 11:01:59 -04001381 inherited = &fInterpreterInclude;
1382 fIRGenerator->fSymbolTable = fInterpreterSymbolTable;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001383 fIRGenerator->fIntrinsics = &fInterpreterIntrinsics;
Ethan Nicholas8da1e652019-05-24 11:01:59 -04001384 fIRGenerator->start(&settings, inherited);
Ethan Nicholas0d997662019-04-08 09:46:01 -04001385 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001386 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001387 for (auto& element : elements) {
1388 if (element->fKind == ProgramElement::kEnum_Kind) {
1389 ((Enum&) *element).fBuiltin = true;
1390 }
1391 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001392 std::unique_ptr<String> textPtr(new String(std::move(text)));
1393 fSource = textPtr.get();
Robert Phillipsfe8da172018-01-24 14:52:02 +00001394 fIRGenerator->convertProgram(kind, textPtr->c_str(), textPtr->size(), *fTypes, &elements);
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001395 auto result = std::unique_ptr<Program>(new Program(kind,
1396 std::move(textPtr),
1397 settings,
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001398 fContext,
Ethan Nicholas3c6ae622018-04-24 13:06:09 -04001399 inherited,
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001400 std::move(elements),
1401 fIRGenerator->fSymbolTable,
1402 fIRGenerator->fInputs));
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001403 if (fErrorCount) {
1404 return nullptr;
1405 }
1406 return result;
1407}
1408
Ethan Nicholas00543112018-07-31 09:44:36 -04001409bool Compiler::optimize(Program& program) {
1410 SkASSERT(!fErrorCount);
1411 if (!program.fIsOptimized) {
1412 program.fIsOptimized = true;
1413 fIRGenerator->fKind = program.fKind;
1414 fIRGenerator->fSettings = &program.fSettings;
1415 for (auto& element : program) {
1416 if (element.fKind == ProgramElement::kFunction_Kind) {
1417 this->scanCFG((FunctionDefinition&) element);
1418 }
1419 }
Ethan Nicholas0dc80872019-02-08 15:46:24 -05001420 if (program.fKind != Program::kFragmentProcessor_Kind) {
1421 for (auto iter = program.fElements.begin(); iter != program.fElements.end();) {
1422 if ((*iter)->fKind == ProgramElement::kVar_Kind) {
1423 VarDeclarations& vars = (VarDeclarations&) **iter;
1424 for (auto varIter = vars.fVars.begin(); varIter != vars.fVars.end();) {
1425 const Variable& var = *((VarDeclaration&) **varIter).fVar;
1426 if (var.dead()) {
1427 varIter = vars.fVars.erase(varIter);
1428 } else {
1429 ++varIter;
1430 }
1431 }
1432 if (vars.fVars.size() == 0) {
1433 iter = program.fElements.erase(iter);
1434 continue;
1435 }
1436 }
1437 ++iter;
1438 }
1439 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001440 }
1441 return fErrorCount == 0;
1442}
1443
1444std::unique_ptr<Program> Compiler::specialize(
1445 Program& program,
1446 const std::unordered_map<SkSL::String, SkSL::Program::Settings::Value>& inputs) {
1447 std::vector<std::unique_ptr<ProgramElement>> elements;
1448 for (const auto& e : program) {
1449 elements.push_back(e.clone());
1450 }
1451 Program::Settings settings;
1452 settings.fCaps = program.fSettings.fCaps;
1453 for (auto iter = inputs.begin(); iter != inputs.end(); ++iter) {
1454 settings.fArgs.insert(*iter);
1455 }
1456 std::unique_ptr<Program> result(new Program(program.fKind,
1457 nullptr,
1458 settings,
1459 program.fContext,
1460 program.fInheritedElements,
1461 std::move(elements),
1462 program.fSymbols,
1463 program.fInputs));
1464 return result;
1465}
1466
Brian Osmanfb32ddf2019-06-18 10:14:20 -04001467#if defined(SKSL_STANDALONE) || SK_SUPPORT_GPU
1468
Ethan Nicholas00543112018-07-31 09:44:36 -04001469bool Compiler::toSPIRV(Program& program, OutputStream& out) {
1470 if (!this->optimize(program)) {
1471 return false;
1472 }
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001473#ifdef SK_ENABLE_SPIRV_VALIDATION
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001474 StringStream buffer;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001475 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001476 SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001477 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001478 fSource = nullptr;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001479 if (result) {
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001480 spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001481 const String& data = buffer.str();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001482 SkASSERT(0 == data.size() % 4);
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001483 auto dumpmsg = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
1484 SkDebugf("SPIR-V validation error: %s\n", m);
1485 };
1486 tools.SetMessageConsumer(dumpmsg);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001487 // Verify that the SPIR-V we produced is valid. If this SkASSERT fails, check the logs prior
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001488 // to the failure to see the validation errors.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001489 SkAssertResult(tools.Validate((const uint32_t*) data.c_str(), data.size() / 4));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001490 out.write(data.c_str(), data.size());
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001491 }
1492#else
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001493 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001494 SPIRVCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001495 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001496 fSource = nullptr;
Ethan Nicholasa6ae1f72017-03-16 09:56:54 -04001497#endif
Ethan Nicholasce33f102016-12-09 17:22:59 -05001498 return result;
1499}
1500
Ethan Nicholas00543112018-07-31 09:44:36 -04001501bool Compiler::toSPIRV(Program& program, String* out) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001502 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001503 bool result = this->toSPIRV(program, buffer);
1504 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001505 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001506 }
1507 return result;
1508}
1509
Ethan Nicholas00543112018-07-31 09:44:36 -04001510bool Compiler::toGLSL(Program& program, OutputStream& out) {
1511 if (!this->optimize(program)) {
1512 return false;
1513 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001514 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001515 GLSLCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001516 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001517 fSource = nullptr;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001518 return result;
1519}
1520
Ethan Nicholas00543112018-07-31 09:44:36 -04001521bool Compiler::toGLSL(Program& program, String* out) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001522 StringStream buffer;
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001523 bool result = this->toGLSL(program, buffer);
1524 if (result) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001525 *out = buffer.str();
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001526 }
1527 return result;
1528}
1529
Ethan Nicholas00543112018-07-31 09:44:36 -04001530bool Compiler::toMetal(Program& program, OutputStream& out) {
1531 if (!this->optimize(program)) {
1532 return false;
1533 }
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001534 MetalCodeGenerator cg(fContext.get(), &program, this, &out);
Ethan Nicholascc305772017-10-13 16:17:45 -04001535 bool result = cg.generateCode();
Ethan Nicholascc305772017-10-13 16:17:45 -04001536 return result;
1537}
1538
Ethan Nicholas00543112018-07-31 09:44:36 -04001539bool Compiler::toMetal(Program& program, String* out) {
1540 if (!this->optimize(program)) {
1541 return false;
1542 }
Timothy Liangb8eeb802018-07-23 16:46:16 -04001543 StringStream buffer;
1544 bool result = this->toMetal(program, buffer);
1545 if (result) {
1546 *out = buffer.str();
1547 }
1548 return result;
1549}
1550
Ethan Nicholas00543112018-07-31 09:44:36 -04001551bool Compiler::toCPP(Program& program, String name, OutputStream& out) {
1552 if (!this->optimize(program)) {
1553 return false;
1554 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001555 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001556 CPPCodeGenerator cg(fContext.get(), &program, this, name, &out);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001557 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001558 fSource = nullptr;
Ethan Nicholas762466e2017-06-29 10:03:38 -04001559 return result;
1560}
1561
Ethan Nicholas00543112018-07-31 09:44:36 -04001562bool Compiler::toH(Program& program, String name, OutputStream& out) {
1563 if (!this->optimize(program)) {
1564 return false;
1565 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001566 fSource = program.fSource.get();
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04001567 HCodeGenerator cg(fContext.get(), &program, this, name, &out);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001568 bool result = cg.generateCode();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001569 fSource = nullptr;
Ethan Nicholas00543112018-07-31 09:44:36 -04001570 return result;
1571}
1572
Brian Osman2e29ab52019-09-20 12:19:11 -04001573#endif
1574
1575#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
Ethan Nicholas00543112018-07-31 09:44:36 -04001576bool Compiler::toPipelineStage(const Program& program, String* out,
Brian Osman2e29ab52019-09-20 12:19:11 -04001577 std::vector<FormatArg>* outFormatArgs,
1578 std::vector<GLSLFunction>* outFunctions) {
Ethan Nicholas00543112018-07-31 09:44:36 -04001579 SkASSERT(program.fIsOptimized);
1580 fSource = program.fSource.get();
1581 StringStream buffer;
Brian Osman2e29ab52019-09-20 12:19:11 -04001582 PipelineStageCodeGenerator cg(fContext.get(), &program, this, &buffer, outFormatArgs,
1583 outFunctions);
Ethan Nicholas00543112018-07-31 09:44:36 -04001584 bool result = cg.generateCode();
1585 fSource = nullptr;
1586 if (result) {
1587 *out = buffer.str();
1588 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04001589 return result;
1590}
Brian Osmanfb32ddf2019-06-18 10:14:20 -04001591#endif
1592
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001593std::unique_ptr<ByteCode> Compiler::toByteCode(Program& program) {
Brian Osman489cf882019-07-09 10:48:28 -04001594#if defined(SK_ENABLE_SKSL_INTERPRETER)
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001595 if (!this->optimize(program)) {
1596 return nullptr;
1597 }
1598 std::unique_ptr<ByteCode> result(new ByteCode());
1599 ByteCodeGenerator cg(fContext.get(), &program, this, result.get());
1600 if (cg.generateCode()) {
1601 return result;
1602 }
Brian Osman489cf882019-07-09 10:48:28 -04001603#else
1604 ABORT("ByteCode interpreter not enabled");
1605#endif
Ethan Nicholas0e9401d2019-03-21 11:05:37 -04001606 return nullptr;
1607}
1608
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001609const char* Compiler::OperatorName(Token::Kind kind) {
1610 switch (kind) {
1611 case Token::PLUS: return "+";
1612 case Token::MINUS: return "-";
1613 case Token::STAR: return "*";
1614 case Token::SLASH: return "/";
1615 case Token::PERCENT: return "%";
1616 case Token::SHL: return "<<";
1617 case Token::SHR: return ">>";
1618 case Token::LOGICALNOT: return "!";
1619 case Token::LOGICALAND: return "&&";
1620 case Token::LOGICALOR: return "||";
1621 case Token::LOGICALXOR: return "^^";
1622 case Token::BITWISENOT: return "~";
1623 case Token::BITWISEAND: return "&";
1624 case Token::BITWISEOR: return "|";
1625 case Token::BITWISEXOR: return "^";
1626 case Token::EQ: return "=";
1627 case Token::EQEQ: return "==";
1628 case Token::NEQ: return "!=";
1629 case Token::LT: return "<";
1630 case Token::GT: return ">";
1631 case Token::LTEQ: return "<=";
1632 case Token::GTEQ: return ">=";
1633 case Token::PLUSEQ: return "+=";
1634 case Token::MINUSEQ: return "-=";
1635 case Token::STAREQ: return "*=";
1636 case Token::SLASHEQ: return "/=";
1637 case Token::PERCENTEQ: return "%=";
1638 case Token::SHLEQ: return "<<=";
1639 case Token::SHREQ: return ">>=";
1640 case Token::LOGICALANDEQ: return "&&=";
1641 case Token::LOGICALOREQ: return "||=";
1642 case Token::LOGICALXOREQ: return "^^=";
1643 case Token::BITWISEANDEQ: return "&=";
1644 case Token::BITWISEOREQ: return "|=";
1645 case Token::BITWISEXOREQ: return "^=";
1646 case Token::PLUSPLUS: return "++";
1647 case Token::MINUSMINUS: return "--";
1648 case Token::COMMA: return ",";
1649 default:
1650 ABORT("unsupported operator: %d\n", kind);
1651 }
1652}
1653
1654
1655bool Compiler::IsAssignment(Token::Kind op) {
1656 switch (op) {
1657 case Token::EQ: // fall through
1658 case Token::PLUSEQ: // fall through
1659 case Token::MINUSEQ: // fall through
1660 case Token::STAREQ: // fall through
1661 case Token::SLASHEQ: // fall through
1662 case Token::PERCENTEQ: // fall through
1663 case Token::SHLEQ: // fall through
1664 case Token::SHREQ: // fall through
1665 case Token::BITWISEOREQ: // fall through
1666 case Token::BITWISEXOREQ: // fall through
1667 case Token::BITWISEANDEQ: // fall through
1668 case Token::LOGICALOREQ: // fall through
1669 case Token::LOGICALXOREQ: // fall through
1670 case Token::LOGICALANDEQ:
1671 return true;
1672 default:
1673 return false;
1674 }
1675}
1676
1677Position Compiler::position(int offset) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001678 SkASSERT(fSource);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001679 int line = 1;
1680 int column = 1;
1681 for (int i = 0; i < offset; i++) {
1682 if ((*fSource)[i] == '\n') {
1683 ++line;
1684 column = 1;
1685 }
1686 else {
1687 ++column;
1688 }
1689 }
1690 return Position(line, column);
1691}
1692
1693void Compiler::error(int offset, String msg) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001694 fErrorCount++;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001695 Position pos = this->position(offset);
1696 fErrorText += "error: " + to_string(pos.fLine) + ": " + msg.c_str() + "\n";
ethannicholasb3058bd2016-07-01 08:22:01 -07001697}
1698
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001699String Compiler::errorText() {
Ethan Nicholas00543112018-07-31 09:44:36 -04001700 this->writeErrorCount();
1701 fErrorCount = 0;
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001702 String result = fErrorText;
ethannicholasb3058bd2016-07-01 08:22:01 -07001703 return result;
1704}
1705
1706void Compiler::writeErrorCount() {
1707 if (fErrorCount) {
1708 fErrorText += to_string(fErrorCount) + " error";
1709 if (fErrorCount > 1) {
1710 fErrorText += "s";
1711 }
1712 fErrorText += "\n";
1713 }
1714}
1715
ethannicholasb3058bd2016-07-01 08:22:01 -07001716} // namespace