blob: 5073e3fdebb23c1e1b6386b34e1ed7ba7badc8cb [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 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05007
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLIRGenerator.h"
ethannicholasb3058bd2016-07-01 08:22:01 -07009
10#include "limits.h"
John Stilesfbd050b2020-08-03 13:21:46 -040011#include <memory>
Ethan Nicholasaf197692017-02-27 13:26:45 -050012#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070013
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/sksl/SkSLCompiler.h"
15#include "src/sksl/SkSLParser.h"
Brian Osman3000d6b2020-07-31 15:57:28 -040016#include "src/sksl/SkSLUtil.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/sksl/ir/SkSLBinaryExpression.h"
18#include "src/sksl/ir/SkSLBoolLiteral.h"
19#include "src/sksl/ir/SkSLBreakStatement.h"
20#include "src/sksl/ir/SkSLConstructor.h"
21#include "src/sksl/ir/SkSLContinueStatement.h"
22#include "src/sksl/ir/SkSLDiscardStatement.h"
23#include "src/sksl/ir/SkSLDoStatement.h"
24#include "src/sksl/ir/SkSLEnum.h"
25#include "src/sksl/ir/SkSLExpressionStatement.h"
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040026#include "src/sksl/ir/SkSLExternalFunctionCall.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040027#include "src/sksl/ir/SkSLExternalValueReference.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "src/sksl/ir/SkSLField.h"
29#include "src/sksl/ir/SkSLFieldAccess.h"
30#include "src/sksl/ir/SkSLFloatLiteral.h"
31#include "src/sksl/ir/SkSLForStatement.h"
32#include "src/sksl/ir/SkSLFunctionCall.h"
33#include "src/sksl/ir/SkSLFunctionDeclaration.h"
34#include "src/sksl/ir/SkSLFunctionDefinition.h"
35#include "src/sksl/ir/SkSLFunctionReference.h"
36#include "src/sksl/ir/SkSLIfStatement.h"
37#include "src/sksl/ir/SkSLIndexExpression.h"
38#include "src/sksl/ir/SkSLIntLiteral.h"
39#include "src/sksl/ir/SkSLInterfaceBlock.h"
40#include "src/sksl/ir/SkSLLayout.h"
Chris Daltonb0fd4b12019-10-29 13:41:22 -060041#include "src/sksl/ir/SkSLNop.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050042#include "src/sksl/ir/SkSLNullLiteral.h"
43#include "src/sksl/ir/SkSLPostfixExpression.h"
44#include "src/sksl/ir/SkSLPrefixExpression.h"
45#include "src/sksl/ir/SkSLReturnStatement.h"
46#include "src/sksl/ir/SkSLSetting.h"
47#include "src/sksl/ir/SkSLSwitchCase.h"
48#include "src/sksl/ir/SkSLSwitchStatement.h"
49#include "src/sksl/ir/SkSLSwizzle.h"
50#include "src/sksl/ir/SkSLTernaryExpression.h"
51#include "src/sksl/ir/SkSLUnresolvedFunction.h"
52#include "src/sksl/ir/SkSLVarDeclarations.h"
53#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
54#include "src/sksl/ir/SkSLVariable.h"
55#include "src/sksl/ir/SkSLVariableReference.h"
56#include "src/sksl/ir/SkSLWhileStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070057
58namespace SkSL {
59
60class AutoSymbolTable {
61public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050062 AutoSymbolTable(IRGenerator* ir)
ethannicholasb3058bd2016-07-01 08:22:01 -070063 : fIR(ir)
64 , fPrevious(fIR->fSymbolTable) {
65 fIR->pushSymbolTable();
66 }
67
68 ~AutoSymbolTable() {
69 fIR->popSymbolTable();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040070 SkASSERT(fPrevious == fIR->fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -070071 }
72
73 IRGenerator* fIR;
74 std::shared_ptr<SymbolTable> fPrevious;
75};
76
ethannicholas22f939e2016-10-13 13:25:34 -070077class AutoLoopLevel {
78public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050079 AutoLoopLevel(IRGenerator* ir)
ethannicholas22f939e2016-10-13 13:25:34 -070080 : fIR(ir) {
81 fIR->fLoopLevel++;
82 }
83
84 ~AutoLoopLevel() {
85 fIR->fLoopLevel--;
86 }
87
88 IRGenerator* fIR;
89};
90
Ethan Nicholasaf197692017-02-27 13:26:45 -050091class AutoSwitchLevel {
92public:
93 AutoSwitchLevel(IRGenerator* ir)
94 : fIR(ir) {
95 fIR->fSwitchLevel++;
96 }
97
98 ~AutoSwitchLevel() {
99 fIR->fSwitchLevel--;
100 }
101
102 IRGenerator* fIR;
103};
104
John Stilesd1c4dac2020-08-11 18:50:50 -0400105class AutoDisableInline {
106public:
107 AutoDisableInline(IRGenerator* ir, bool canInline = false)
108 : fIR(ir) {
109 fOldCanInline = ir->fCanInline;
John Stiles46d17582020-08-12 11:48:48 -0400110 fIR->fCanInline &= canInline;
John Stilesd1c4dac2020-08-11 18:50:50 -0400111 }
112
113 ~AutoDisableInline() {
114 fIR->fCanInline = fOldCanInline;
115 }
116
117 IRGenerator* fIR;
118 bool fOldCanInline;
119};
120
Ethan Nicholas11d53972016-11-28 11:23:23 -0500121IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ethannicholasb3058bd2016-07-01 08:22:01 -0700122 ErrorReporter& errorReporter)
ethannicholasd598f792016-07-25 10:08:54 -0700123: fContext(*context)
124, fCurrentFunction(nullptr)
Ethan Nicholas762466e2017-06-29 10:03:38 -0400125, fRootSymbolTable(symbolTable)
126, fSymbolTable(symbolTable)
ethannicholas22f939e2016-10-13 13:25:34 -0700127, fLoopLevel(0)
Ethan Nicholasaf197692017-02-27 13:26:45 -0500128, fSwitchLevel(0)
ethannicholasd598f792016-07-25 10:08:54 -0700129, fErrors(errorReporter) {}
ethannicholasb3058bd2016-07-01 08:22:01 -0700130
131void IRGenerator::pushSymbolTable() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400132 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700133}
134
135void IRGenerator::popSymbolTable() {
136 fSymbolTable = fSymbolTable->fParent;
137}
138
Ethan Nicholas762466e2017-06-29 10:03:38 -0400139static void fill_caps(const SKSL_CAPS_CLASS& caps,
140 std::unordered_map<String, Program::Settings::Value>* capsMap) {
Brian Salomon23356442018-11-30 15:33:19 -0500141#define CAP(name) \
142 capsMap->insert(std::make_pair(String(#name), Program::Settings::Value(caps.name())))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500143 CAP(fbFetchSupport);
Brian Salomond4013302018-04-04 13:58:33 +0000144 CAP(fbFetchNeedsCustomOutput);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500145 CAP(flatInterpolationSupport);
146 CAP(noperspectiveInterpolationSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500147 CAP(externalTextureSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500148 CAP(mustEnableAdvBlendEqs);
149 CAP(mustEnableSpecificAdvBlendEqs);
150 CAP(mustDeclareFragmentShaderOutput);
Michael Ludwig4f94ef62018-09-12 15:22:16 -0400151 CAP(mustDoOpBetweenFloorAndAbs);
Brian Salomonf8c187c2019-12-19 14:41:57 -0500152 CAP(mustGuardDivisionEvenAfterExplicitZeroCheck);
153 CAP(inBlendModesFailRandomlyForAllZeroVec);
Michael Ludwig24d438b2018-09-12 15:22:50 -0400154 CAP(atan2ImplementedAsAtanYOverX);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500155 CAP(canUseAnyFunctionInShader);
Chris Dalton47c8ed32017-11-15 18:27:09 -0700156 CAP(floatIs32Bits);
Ethan Nicholas07990de2017-07-18 09:47:43 -0400157 CAP(integerSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500158#undef CAP
159}
160
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400161void IRGenerator::start(const Program::Settings* settings,
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400162 std::vector<std::unique_ptr<ProgramElement>>* inherited,
163 bool isBuiltinCode) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500164 fSettings = settings;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400165 fInherited = inherited;
166 fIsBuiltinCode = isBuiltinCode;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500167 fCapsMap.clear();
168 if (settings->fCaps) {
169 fill_caps(*settings->fCaps, &fCapsMap);
Ethan Nicholas00543112018-07-31 09:44:36 -0400170 } else {
171 fCapsMap.insert(std::make_pair(String("integerSupport"),
172 Program::Settings::Value(true)));
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500173 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500174 this->pushSymbolTable();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400175 fInvocations = -1;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500176 fInputs.reset();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000177 fSkPerVertex = nullptr;
178 fRTAdjust = nullptr;
179 fRTAdjustInterfaceBlock = nullptr;
Michael Ludwig9861b7c2020-06-23 18:37:17 -0400180 fInlineVarCounter = 0;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400181 if (inherited) {
182 for (const auto& e : *inherited) {
183 if (e->fKind == ProgramElement::kInterfaceBlock_Kind) {
184 InterfaceBlock& intf = (InterfaceBlock&) *e;
185 if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400186 SkASSERT(!fSkPerVertex);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400187 fSkPerVertex = &intf.fVariable;
188 }
189 }
190 }
191 }
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500192 SkASSERT(fIntrinsics);
193 for (auto& pair : *fIntrinsics) {
194 pair.second.second = false;
195 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500196}
197
Ethan Nicholasfc994162019-06-06 10:04:27 -0400198std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragment name) {
John Stilesfbd050b2020-08-03 13:21:46 -0400199 return std::make_unique<Extension>(offset, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700200}
201
Ethan Nicholasfc994162019-06-06 10:04:27 -0400202void IRGenerator::finish() {
203 this->popSymbolTable();
204 fSettings = nullptr;
205}
206
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400207std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700208 switch (statement.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400209 case ASTNode::Kind::kBlock:
210 return this->convertBlock(statement);
211 case ASTNode::Kind::kVarDeclarations:
212 return this->convertVarDeclarationStatement(statement);
213 case ASTNode::Kind::kIf:
214 return this->convertIf(statement);
215 case ASTNode::Kind::kFor:
216 return this->convertFor(statement);
217 case ASTNode::Kind::kWhile:
218 return this->convertWhile(statement);
219 case ASTNode::Kind::kDo:
220 return this->convertDo(statement);
221 case ASTNode::Kind::kSwitch:
222 return this->convertSwitch(statement);
223 case ASTNode::Kind::kReturn:
224 return this->convertReturn(statement);
225 case ASTNode::Kind::kBreak:
226 return this->convertBreak(statement);
227 case ASTNode::Kind::kContinue:
228 return this->convertContinue(statement);
229 case ASTNode::Kind::kDiscard:
230 return this->convertDiscard(statement);
231 default:
232 // it's an expression
233 std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000234 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400235 SkASSERT(result->fKind == Statement::kExpression_Kind);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000236 Expression& expr = *((ExpressionStatement&) *result).fExpression;
237 if (expr.fKind == Expression::kFunctionCall_Kind) {
238 FunctionCall& fc = (FunctionCall&) expr;
239 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
240 std::vector<std::unique_ptr<Statement>> statements;
241 statements.push_back(getNormalizeSkPositionCode());
242 statements.push_back(std::move(result));
John Stilesfbd050b2020-08-03 13:21:46 -0400243 return std::make_unique<Block>(statement.fOffset, std::move(statements),
244 fSymbolTable);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000245 }
246 }
247 }
248 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700249 }
250}
251
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400252std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
253 std::vector<std::unique_ptr<Statement>> oldExtraStatements = std::move(fExtraStatements);
254 std::unique_ptr<Statement> result = this->convertSingleStatement(statement);
255 if (!result) {
256 fExtraStatements = std::move(oldExtraStatements);
257 return nullptr;
258 }
259 if (fExtraStatements.size()) {
260 fExtraStatements.push_back(std::move(result));
261 std::unique_ptr<Statement> block(new Block(-1, std::move(fExtraStatements), nullptr,
262 false));
263 fExtraStatements = std::move(oldExtraStatements);
264 return block;
265 }
266 fExtraStatements = std::move(oldExtraStatements);
267 return result;
268}
269
Ethan Nicholasfc994162019-06-06 10:04:27 -0400270std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
271 SkASSERT(block.fKind == ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -0700272 AutoSymbolTable table(this);
273 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400274 for (const auto& child : block) {
275 std::unique_ptr<Statement> statement = this->convertStatement(child);
ethannicholasb3058bd2016-07-01 08:22:01 -0700276 if (!statement) {
277 return nullptr;
278 }
279 statements.push_back(std::move(statement));
280 }
John Stilesfbd050b2020-08-03 13:21:46 -0400281 return std::make_unique<Block>(block.fOffset, std::move(statements), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700282}
283
Ethan Nicholasfc994162019-06-06 10:04:27 -0400284std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
285 SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
286 auto decl = this->convertVarDeclarations(s, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700287 if (!decl) {
288 return nullptr;
289 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700290 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700291}
292
Ethan Nicholasfc994162019-06-06 10:04:27 -0400293std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNode& decls,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700294 Variable::Storage storage) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400295 SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
296 auto iter = decls.begin();
297 const Modifiers& modifiers = iter++->getModifiers();
298 const ASTNode& rawType = *(iter++);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000299 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400300 const Type* baseType = this->convertType(rawType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700301 if (!baseType) {
302 return nullptr;
303 }
Brian Osman82329002020-07-21 09:39:27 -0400304 if (baseType->nonnullable() == *fContext.fFragmentProcessor_Type &&
305 storage != Variable::kGlobal_Storage) {
306 fErrors.error(decls.fOffset,
307 "variables of type '" + baseType->displayName() + "' must be global");
308 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500309 if (fKind != Program::kFragmentProcessor_Kind) {
310 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
311 baseType->kind() == Type::Kind::kMatrix_Kind) {
312 fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
313 }
Brian Osman088913a2019-12-19 15:44:56 -0500314 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
315 (modifiers.fFlags & Modifiers::kUniform_Flag)) {
316 fErrors.error(decls.fOffset,
317 "'in uniform' variables only permitted within fragment processors");
318 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500319 if (modifiers.fLayout.fWhen.fLength) {
320 fErrors.error(decls.fOffset, "'when' is only permitted within fragment processors");
321 }
322 if (modifiers.fLayout.fFlags & Layout::kTracked_Flag) {
323 fErrors.error(decls.fOffset, "'tracked' is only permitted within fragment processors");
324 }
325 if (modifiers.fLayout.fCType != Layout::CType::kDefault) {
326 fErrors.error(decls.fOffset, "'ctype' is only permitted within fragment processors");
327 }
328 if (modifiers.fLayout.fKey) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400329 fErrors.error(decls.fOffset, "'key' is only permitted within fragment processors");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400330 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500331 }
Brian Osmana4b91692020-08-10 14:26:16 -0400332 if (fKind == Program::kPipelineStage_Kind) {
333 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
334 baseType->nonnullable() != *fContext.fFragmentProcessor_Type) {
335 fErrors.error(decls.fOffset, "'in' variables not permitted in runtime effects");
336 }
337 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500338 if (modifiers.fLayout.fKey && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
339 fErrors.error(decls.fOffset, "'key' is not permitted on 'uniform' variables");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400340 }
Brian Osmanf59a9612020-04-15 14:18:13 -0400341 if (modifiers.fLayout.fMarker.fLength) {
342 if (fKind != Program::kPipelineStage_Kind) {
343 fErrors.error(decls.fOffset, "'marker' is only permitted in runtime effects");
344 }
345 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
346 fErrors.error(decls.fOffset, "'marker' is only permitted on 'uniform' variables");
347 }
348 if (*baseType != *fContext.fFloat4x4_Type) {
349 fErrors.error(decls.fOffset, "'marker' is only permitted on float4x4 variables");
350 }
351 }
Brian Osmanb32d66b2020-04-30 17:12:03 -0400352 if (modifiers.fLayout.fFlags & Layout::kSRGBUnpremul_Flag) {
353 if (fKind != Program::kPipelineStage_Kind) {
354 fErrors.error(decls.fOffset, "'srgb_unpremul' is only permitted in runtime effects");
355 }
356 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
357 fErrors.error(decls.fOffset,
358 "'srgb_unpremul' is only permitted on 'uniform' variables");
359 }
360 auto validColorXformType = [](const Type& t) {
361 return t.kind() == Type::kVector_Kind && t.componentType().isFloat() &&
362 (t.columns() == 3 || t.columns() == 4);
363 };
364 if (!validColorXformType(*baseType) && !(baseType->kind() == Type::kArray_Kind &&
365 validColorXformType(baseType->componentType()))) {
366 fErrors.error(decls.fOffset,
367 "'srgb_unpremul' is only permitted on half3, half4, float3, or float4 "
368 "variables");
369 }
370 }
Brian Osman3c358422020-03-23 10:44:12 -0400371 if (modifiers.fFlags & Modifiers::kVarying_Flag) {
372 if (fKind != Program::kPipelineStage_Kind) {
373 fErrors.error(decls.fOffset, "'varying' is only permitted in runtime effects");
374 }
375 if (!baseType->isFloat() &&
376 !(baseType->kind() == Type::kVector_Kind && baseType->componentType().isFloat())) {
377 fErrors.error(decls.fOffset, "'varying' must be float scalar or vector");
378 }
379 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400380 for (; iter != decls.end(); ++iter) {
381 const ASTNode& varDecl = *iter;
382 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
383 (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
384 varDecl.getVarData().fName != "sk_FragColor") {
385 fErrors.error(varDecl.fOffset,
Ethan Nicholas6c942712018-03-16 09:45:11 -0400386 "out location=0, index=0 is reserved for sk_FragColor");
387 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400388 const ASTNode::VarData& varData = varDecl.getVarData();
ethannicholasd598f792016-07-25 10:08:54 -0700389 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700390 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400391 auto iter = varDecl.begin();
Brian Osman82d49702019-12-30 13:44:01 -0500392 if (varData.fSizeCount > 0 && (modifiers.fFlags & Modifiers::kIn_Flag)) {
393 fErrors.error(varDecl.fOffset, "'in' variables may not have array type");
394 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400395 for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
396 const ASTNode& rawSize = *iter;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700397 if (rawSize) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400398 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700399 if (!size) {
400 return nullptr;
401 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700402 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500403 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700404 if (size->fKind == Expression::kIntLiteral_Kind) {
405 count = ((IntLiteral&) *size).fValue;
406 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700407 fErrors.error(size->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400408 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700409 }
410 name += "[" + to_string(count) + "]";
411 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400412 fErrors.error(size->fOffset, "array size must be specified");
413 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700414 }
John Stiles3ae071e2020-08-05 15:29:29 -0400415 type = fSymbolTable->takeOwnershipOfSymbol(
416 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700417 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700418 } else {
John Stiles3ae071e2020-08-05 15:29:29 -0400419 type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
420 type->name() + "[]", Type::kArray_Kind, *type, /*columns=*/-1));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700421 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 }
423 }
John Stilesfbd050b2020-08-03 13:21:46 -0400424 auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, *type,
425 storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000426 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400427 SkASSERT(!fRTAdjust);
428 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000429 fRTAdjust = var.get();
430 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700431 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400432 if (iter != varDecl.end()) {
433 value = this->convertExpression(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700434 if (!value) {
435 return nullptr;
436 }
ethannicholasd598f792016-07-25 10:08:54 -0700437 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500438 if (!value) {
439 return nullptr;
440 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400441 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500442 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700443 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400444 if (storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor" &&
445 (*fSymbolTable)[var->fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700446 // already defined, ignore
Ethan Nicholasfc994162019-06-06 10:04:27 -0400447 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[var->fName] &&
448 (*fSymbolTable)[var->fName]->fKind == Symbol::kVariable_Kind &&
449 ((Variable*) (*fSymbolTable)[var->fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700450 // already defined, just update the modifiers
Ethan Nicholasfc994162019-06-06 10:04:27 -0400451 Variable* old = (Variable*) (*fSymbolTable)[var->fName];
ethannicholasf789b382016-08-03 12:43:36 -0700452 old->fModifiers = var->fModifiers;
453 } else {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000454 variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
455 std::move(value)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400456 StringFragment name = var->fName;
457 fSymbolTable->add(name, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700458 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700459 }
John Stilesfbd050b2020-08-03 13:21:46 -0400460 return std::make_unique<VarDeclarations>(decls.fOffset, baseType, std::move(variables));
ethannicholasb3058bd2016-07-01 08:22:01 -0700461}
462
Ethan Nicholasfc994162019-06-06 10:04:27 -0400463std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
464 SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
465 Modifiers modifiers = m.getModifiers();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400466 if (modifiers.fLayout.fInvocations != -1) {
Ethan Nicholasf06576b2019-04-03 15:45:25 -0400467 if (fKind != Program::kGeometry_Kind) {
468 fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
469 return nullptr;
470 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400471 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600472 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400473 modifiers.fLayout.fInvocations = -1;
474 Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400475 SkASSERT(invocationId);
Ethan Nicholasd1d52562018-03-20 16:30:34 -0400476 invocationId->fModifiers.fFlags = 0;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400477 invocationId->fModifiers.fLayout.fBuiltin = -1;
478 if (modifiers.fLayout.description() == "") {
479 return nullptr;
480 }
481 }
482 }
483 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600484 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400485 modifiers.fLayout.fMaxVertices *= fInvocations;
486 }
John Stilesfbd050b2020-08-03 13:21:46 -0400487 return std::make_unique<ModifiersDeclaration>(modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700488}
489
Ethan Nicholasfc994162019-06-06 10:04:27 -0400490std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
491 SkASSERT(n.fKind == ASTNode::Kind::kIf);
492 auto iter = n.begin();
493 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -0700494 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700495 if (!test) {
496 return nullptr;
497 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400498 std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700499 if (!ifTrue) {
500 return nullptr;
501 }
502 std::unique_ptr<Statement> ifFalse;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400503 if (iter != n.end()) {
504 ifFalse = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700505 if (!ifFalse) {
506 return nullptr;
507 }
508 }
ethannicholas08a92112016-11-09 13:26:45 -0800509 if (test->fKind == Expression::kBoolLiteral_Kind) {
510 // static boolean value, fold down to a single branch
511 if (((BoolLiteral&) *test).fValue) {
512 return ifTrue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400513 } else if (ifFalse) {
ethannicholas08a92112016-11-09 13:26:45 -0800514 return ifFalse;
515 } else {
516 // False & no else clause. Not an error, so don't return null!
517 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400518 return std::unique_ptr<Statement>(new Block(n.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800519 fSymbolTable));
520 }
521 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400522 return std::unique_ptr<Statement>(new IfStatement(n.fOffset, n.getBool(), std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700523 std::move(ifTrue), std::move(ifFalse)));
524}
525
Ethan Nicholasfc994162019-06-06 10:04:27 -0400526std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
527 SkASSERT(f.fKind == ASTNode::Kind::kFor);
ethannicholas22f939e2016-10-13 13:25:34 -0700528 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700529 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700530 std::unique_ptr<Statement> initializer;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400531 auto iter = f.begin();
532 if (*iter) {
533 initializer = this->convertStatement(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700534 if (!initializer) {
535 return nullptr;
536 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700537 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400538 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700539 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400540 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400541 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400542 test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
ethannicholas22f939e2016-10-13 13:25:34 -0700543 if (!test) {
544 return nullptr;
545 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400546
ethannicholasb3058bd2016-07-01 08:22:01 -0700547 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400548 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700549 std::unique_ptr<Expression> next;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400550 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400551 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400552 next = this->convertExpression(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700553 if (!next) {
554 return nullptr;
555 }
556 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700557 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400558 ++iter;
559 std::unique_ptr<Statement> statement = this->convertStatement(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700560 if (!statement) {
561 return nullptr;
562 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400563 return std::make_unique<ForStatement>(f.fOffset, std::move(initializer), std::move(test),
564 std::move(next), std::move(statement), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700565}
566
Ethan Nicholasfc994162019-06-06 10:04:27 -0400567std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
568 SkASSERT(w.fKind == ASTNode::Kind::kWhile);
ethannicholas22f939e2016-10-13 13:25:34 -0700569 AutoLoopLevel level(this);
John Stilesd1c4dac2020-08-11 18:50:50 -0400570 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400571 auto iter = w.begin();
John Stilesd1c4dac2020-08-11 18:50:50 -0400572 {
573 AutoDisableInline disableInline(this);
574 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
575 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700576 if (!test) {
577 return nullptr;
578 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400579 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700580 if (!statement) {
581 return nullptr;
582 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400583 return std::make_unique<WhileStatement>(w.fOffset, std::move(test), std::move(statement));
ethannicholasb3058bd2016-07-01 08:22:01 -0700584}
585
Ethan Nicholasfc994162019-06-06 10:04:27 -0400586std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
587 SkASSERT(d.fKind == ASTNode::Kind::kDo);
ethannicholas22f939e2016-10-13 13:25:34 -0700588 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400589 auto iter = d.begin();
590 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
591 if (!statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700592 return nullptr;
593 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400594 std::unique_ptr<Expression> test;
595 {
596 AutoDisableInline disableInline(this);
597 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
598 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400599 if (!test) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700600 return nullptr;
601 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400602 return std::make_unique<DoStatement>(d.fOffset, std::move(statement), std::move(test));
ethannicholasb3058bd2016-07-01 08:22:01 -0700603}
604
Ethan Nicholasfc994162019-06-06 10:04:27 -0400605std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
606 SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500607 AutoSwitchLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400608 auto iter = s.begin();
609 std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500610 if (!value) {
611 return nullptr;
612 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500613 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500614 value = this->coerce(std::move(value), *fContext.fInt_Type);
615 if (!value) {
616 return nullptr;
617 }
618 }
619 AutoSymbolTable table(this);
620 std::unordered_set<int> caseValues;
621 std::vector<std::unique_ptr<SwitchCase>> cases;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400622 for (; iter != s.end(); ++iter) {
623 const ASTNode& c = *iter;
624 SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500625 std::unique_ptr<Expression> caseValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400626 auto childIter = c.begin();
627 if (*childIter) {
628 caseValue = this->convertExpression(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500629 if (!caseValue) {
630 return nullptr;
631 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500632 caseValue = this->coerce(std::move(caseValue), value->fType);
633 if (!caseValue) {
634 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500635 }
Brian Osmanb6b95732020-06-30 11:44:27 -0400636 if (!caseValue->isCompileTimeConstant()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700637 fErrors.error(caseValue->fOffset, "case value must be a constant");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500638 return nullptr;
639 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500640 int64_t v;
641 this->getConstantInt(*caseValue, &v);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500642 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700643 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500644 }
645 caseValues.insert(v);
646 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400647 ++childIter;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500648 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400649 for (; childIter != c.end(); ++childIter) {
650 std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500651 if (!converted) {
652 return nullptr;
653 }
654 statements.push_back(std::move(converted));
655 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400656 cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500657 std::move(statements)));
658 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400659 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400660 std::move(value), std::move(cases),
661 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500662}
663
Ethan Nicholasfc994162019-06-06 10:04:27 -0400664std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
665 std::unique_ptr<Expression> e = this->convertExpression(s);
ethannicholasb3058bd2016-07-01 08:22:01 -0700666 if (!e) {
667 return nullptr;
668 }
669 this->checkValid(*e);
670 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
671}
672
Ethan Nicholasfc994162019-06-06 10:04:27 -0400673std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
674 SkASSERT(r.fKind == ASTNode::Kind::kReturn);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400675 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000676 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400677 // SkASSERT that we aren't doing that. It is of course possible to fix this by adding a
Robert Phillipsfe8da172018-01-24 14:52:02 +0000678 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400679 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400680 if (r.begin() != r.end()) {
681 std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -0700682 if (!result) {
683 return nullptr;
684 }
ethannicholasd598f792016-07-25 10:08:54 -0700685 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700686 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700687 } else {
688 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
689 if (!result) {
690 return nullptr;
691 }
692 }
693 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
694 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700695 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700696 fErrors.error(r.fOffset, "expected function to return '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500697 fCurrentFunction->fReturnType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700698 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700699 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700700 }
701}
702
Ethan Nicholasfc994162019-06-06 10:04:27 -0400703std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
704 SkASSERT(b.fKind == ASTNode::Kind::kBreak);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500705 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700706 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700707 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700708 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700709 return nullptr;
710 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700711}
712
Ethan Nicholasfc994162019-06-06 10:04:27 -0400713std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
714 SkASSERT(c.fKind == ASTNode::Kind::kContinue);
ethannicholas22f939e2016-10-13 13:25:34 -0700715 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700716 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700717 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700718 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700719 return nullptr;
720 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700721}
722
Ethan Nicholasfc994162019-06-06 10:04:27 -0400723std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
724 SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700725 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700726}
727
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500728std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400729 Layout invokeLayout;
730 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700731 FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400732 invokeModifiers,
733 "_invoke",
734 std::vector<const Variable*>(),
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400735 *fContext.fVoid_Type,
736 false);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500737 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
738 new FunctionDefinition(-1, *invokeDecl, std::move(main))));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400739 fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
740
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000741 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400742 Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400743 SkASSERT(loopIdx);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700744 std::unique_ptr<Expression> test(new BinaryExpression(-1,
745 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400746 Token::Kind::TK_LT,
John Stilesfbd050b2020-08-03 13:21:46 -0400747 std::make_unique<IntLiteral>(fContext, -1, fInvocations),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400748 *fContext.fBool_Type));
749 std::unique_ptr<Expression> next(new PostfixExpression(
750 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700751 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400752 *loopIdx,
753 VariableReference::kReadWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400754 Token::Kind::TK_PLUSPLUS));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400755 ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400756 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400757 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400758
759 std::vector<std::unique_ptr<Statement>> loopBody;
760 std::vector<std::unique_ptr<Expression>> invokeArgs;
761 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700762 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400763 *invokeDecl,
764 std::vector<std::unique_ptr<Expression>>()))));
765 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700766 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400767 std::move(endPrimitive),
768 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700769 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400770 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx,
771 VariableReference::kWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400772 Token::Kind::TK_EQ,
John Stilesfbd050b2020-08-03 13:21:46 -0400773 std::make_unique<IntLiteral>(fContext, -1, 0),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400774 *fContext.fInt_Type));
775 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
776 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700777 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400778 std::move(initializer),
779 std::move(test),
780 std::move(next),
John Stilesfbd050b2020-08-03 13:21:46 -0400781 std::make_unique<Block>(-1, std::move(loopBody)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400782 fSymbolTable));
783 std::vector<std::unique_ptr<Statement>> children;
784 children.push_back(std::move(loop));
John Stilesfbd050b2020-08-03 13:21:46 -0400785 return std::make_unique<Block>(-1, std::move(children));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400786}
787
Robert Phillipsfe8da172018-01-24 14:52:02 +0000788std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400789 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000790 // 0,
791 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400792 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000793 #define REF(var) std::unique_ptr<Expression>(\
794 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400795 #define WREF(var) std::unique_ptr<Expression>(\
796 new VariableReference(-1, *var, VariableReference::kWrite_RefKind))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000797 #define FIELD(var, idx) std::unique_ptr<Expression>(\
798 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400799 #define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
Robert Phillipsfe8da172018-01-24 14:52:02 +0000800 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
801 #define ADJUST (fRTAdjustInterfaceBlock ? \
802 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
803 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400804 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
805 { __VA_ARGS__ }))
806 #define OP(left, op, right) std::unique_ptr<Expression>( \
807 new BinaryExpression(-1, left, op, right, \
808 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000809 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400810 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 0, 2)),
811 Token::Kind::TK_PLUS,
812 OP(SWIZZLE(POS, 3, 3), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000813 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
814 children.push_back(SWIZZLE(POS, 3));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400815 std::unique_ptr<Expression> result = OP(POS, Token::Kind::TK_EQ,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000816 std::unique_ptr<Expression>(new Constructor(-1,
817 *fContext.fFloat4_Type,
818 std::move(children))));
819 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
820}
821
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400822template<typename T>
823class AutoClear {
824public:
825 AutoClear(T* container)
826 : fContainer(container) {
827 SkASSERT(container->empty());
828 }
829
830 ~AutoClear() {
831 fContainer->clear();
832 }
833
834private:
835 T* fContainer;
836};
837
John Stilesb8e010c2020-08-11 18:05:39 -0400838template <typename T> AutoClear(T* c) -> AutoClear<T>;
839
Ethan Nicholasfc994162019-06-06 10:04:27 -0400840void IRGenerator::convertFunction(const ASTNode& f) {
John Stilesb8e010c2020-08-11 18:05:39 -0400841 AutoClear clear(&fReferencedIntrinsics);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400842 auto iter = f.begin();
843 const Type* returnType = this->convertType(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700844 if (!returnType) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400845 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700846 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400847 auto type_is_allowed = [&](const Type* t) {
848#if defined(SKSL_STANDALONE)
849 return true;
850#else
851 GrSLType unusedSLType;
852 return fKind != Program::kPipelineStage_Kind ||
853 type_to_grsltype(fContext, *t, &unusedSLType);
854#endif
855 };
856 if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type ||
857 !type_is_allowed(returnType)) {
Brian Osman82329002020-07-21 09:39:27 -0400858 fErrors.error(f.fOffset,
859 "functions may not return type '" + returnType->displayName() + "'");
860 return;
861 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400862 const ASTNode::FunctionData& fd = f.getFunctionData();
ethannicholasd598f792016-07-25 10:08:54 -0700863 std::vector<const Variable*> parameters;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400864 for (size_t i = 0; i < fd.fParameterCount; ++i) {
865 const ASTNode& param = *(iter++);
866 SkASSERT(param.fKind == ASTNode::Kind::kParameter);
867 ASTNode::ParameterData pd = param.getParameterData();
868 auto paramIter = param.begin();
869 const Type* type = this->convertType(*(paramIter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700870 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400871 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700872 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400873 for (int j = (int) pd.fSizeCount; j >= 1; j--) {
874 int size = (param.begin() + j)->getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400875 String name = type->name() + "[" + to_string(size) + "]";
John Stiles3ae071e2020-08-05 15:29:29 -0400876 type = fSymbolTable->takeOwnershipOfSymbol(
877 std::make_unique<Type>(std::move(name), Type::kArray_Kind, *type, size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700878 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400879 // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
880 if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
881 !type_is_allowed(type)) {
882 fErrors.error(param.fOffset,
883 "parameters of type '" + type->displayName() + "' not allowed");
884 return;
885 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400886 StringFragment name = pd.fName;
John Stiles3ae071e2020-08-05 15:29:29 -0400887 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
888 param.fOffset, pd.fModifiers, name, *type, Variable::kParameter_Storage));
ethannicholasd598f792016-07-25 10:08:54 -0700889 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700890 }
891
Ethan Nicholasfc994162019-06-06 10:04:27 -0400892 if (fd.fName == "main") {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400893 switch (fKind) {
894 case Program::kPipelineStage_Kind: {
895 bool valid;
896 switch (parameters.size()) {
Brian Osman7353dc52020-02-07 13:37:12 -0500897 case 2:
898 valid = parameters[0]->fType == *fContext.fFloat2_Type &&
Ethan Nicholas0d997662019-04-08 09:46:01 -0400899 parameters[0]->fModifiers.fFlags == 0 &&
Brian Osman7353dc52020-02-07 13:37:12 -0500900 parameters[1]->fType == *fContext.fHalf4_Type &&
901 parameters[1]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Ethan Nicholas0d997662019-04-08 09:46:01 -0400902 Modifiers::kOut_Flag);
903 break;
904 case 1:
905 valid = parameters[0]->fType == *fContext.fHalf4_Type &&
906 parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
907 Modifiers::kOut_Flag);
908 break;
909 default:
910 valid = false;
911 }
912 if (!valid) {
Brian Osman7353dc52020-02-07 13:37:12 -0500913 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(float2, "
914 "inout half4) or main(inout half4)");
Ethan Nicholas0d997662019-04-08 09:46:01 -0400915 return;
916 }
917 break;
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500918 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -0400919 case Program::kFragmentProcessor_Kind: {
920 bool valid = parameters.size() <= 1;
921 if (parameters.size() == 1) {
922 valid = parameters[0]->fType == *fContext.fFloat2_Type &&
923 parameters[0]->fModifiers.fFlags == 0;
924 }
925
926 if (!valid) {
927 fErrors.error(f.fOffset, ".fp 'main' must be declared main() or main(float2)");
928 return;
929 }
930 break;
931 }
Ethan Nicholas746035a2019-04-23 13:31:09 -0400932 case Program::kGeneric_Kind:
Ethan Nicholas0d997662019-04-08 09:46:01 -0400933 break;
Ethan Nicholas0d997662019-04-08 09:46:01 -0400934 default:
935 if (parameters.size()) {
936 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
937 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400938 }
939 }
940
ethannicholasb3058bd2016-07-01 08:22:01 -0700941 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700942 const FunctionDeclaration* decl = nullptr;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400943 auto entry = (*fSymbolTable)[fd.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700944 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700945 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700946 switch (entry->fKind) {
947 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700948 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700949 break;
950 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700951 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700952 break;
953 default:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400954 fErrors.error(f.fOffset, "symbol '" + fd.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400955 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700956 }
957 for (const auto& other : functions) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400958 SkASSERT(other->fName == fd.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700959 if (parameters.size() == other->fParameters.size()) {
960 bool match = true;
961 for (size_t i = 0; i < parameters.size(); i++) {
962 if (parameters[i]->fType != other->fParameters[i]->fType) {
963 match = false;
964 break;
965 }
966 }
967 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700968 if (*returnType != other->fReturnType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400969 FunctionDeclaration newDecl(f.fOffset, fd.fModifiers, fd.fName, parameters,
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400970 *returnType, fIsBuiltinCode);
971 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
972 "' and '" + other->description() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700973 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400974 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700975 }
976 decl = other;
977 for (size_t i = 0; i < parameters.size(); i++) {
978 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700979 fErrors.error(f.fOffset, "modifiers on parameter " +
980 to_string((uint64_t) i + 1) +
981 " differ between declaration and "
982 "definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400983 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700984 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700985 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400986 if (other->fDefinition && !other->fBuiltin) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700987 fErrors.error(f.fOffset, "duplicate definition of " +
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400988 other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700989 }
990 break;
991 }
992 }
993 }
994 }
995 if (!decl) {
996 // couldn't find an existing declaration
John Stilesfbd050b2020-08-03 13:21:46 -0400997 auto newDecl = std::make_unique<FunctionDeclaration>(f.fOffset,
998 fd.fModifiers,
999 fd.fName,
1000 parameters,
1001 *returnType,
1002 fIsBuiltinCode);
ethannicholas471e8942016-10-28 09:02:46 -07001003 decl = newDecl.get();
1004 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -07001005 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001006 if (iter != f.end()) {
1007 // compile body
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001008 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -07001009 fCurrentFunction = decl;
ethannicholasd598f792016-07-25 10:08:54 -07001010 std::shared_ptr<SymbolTable> old = fSymbolTable;
1011 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001012 if (fd.fName == "main" && fKind == Program::kPipelineStage_Kind) {
Brian Osman7353dc52020-02-07 13:37:12 -05001013 if (parameters.size() == 2) {
1014 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1015 parameters[1]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
Ethan Nicholasa70693b2019-03-04 13:07:36 -05001016 } else {
1017 SkASSERT(parameters.size() == 1);
1018 parameters[0]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
1019 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -04001020 } else if (fd.fName == "main" && fKind == Program::kFragmentProcessor_Kind) {
1021 if (parameters.size() == 1) {
1022 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1023 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001024 }
ethannicholasd598f792016-07-25 10:08:54 -07001025 for (size_t i = 0; i < parameters.size(); i++) {
1026 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -07001027 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001028 bool needInvocationIDWorkaround = fInvocations != -1 && fd.fName == "main" &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -06001029 fSettings->fCaps &&
1030 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001031 std::unique_ptr<Block> body = this->convertBlock(*iter);
ethannicholasd598f792016-07-25 10:08:54 -07001032 fCurrentFunction = nullptr;
1033 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001034 return;
1035 }
1036 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001037 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -07001038 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001039 // conservatively assume all user-defined functions have side effects
1040 ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001041 if (Program::kVertex_Kind == fKind && fd.fName == "main" && fRTAdjust) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00001042 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
1043 }
John Stilesb8e010c2020-08-11 18:05:39 -04001044 auto result = std::make_unique<FunctionDefinition>(f.fOffset, *decl, std::move(body),
1045 std::move(fReferencedIntrinsics));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001046 decl->fDefinition = result.get();
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001047 result->fSource = &f;
1048 fProgramElements->push_back(std::move(result));
ethannicholasb3058bd2016-07-01 08:22:01 -07001049 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001050}
1051
Ethan Nicholasfc994162019-06-06 10:04:27 -04001052std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
1053 SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
1054 ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
ethannicholasb3058bd2016-07-01 08:22:01 -07001055 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001056 this->pushSymbolTable();
1057 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001058 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001059 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +00001060 bool foundRTAdjust = false;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001061 auto iter = intf.begin();
1062 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
ethannicholas14fe8cc2016-09-07 13:37:16 -07001063 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04001064 *(iter++),
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001065 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -07001066 if (!decl) {
1067 return nullptr;
1068 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001069 for (const auto& stmt : decl->fVars) {
1070 VarDeclaration& vd = (VarDeclaration&) *stmt;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001071 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001072 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001073 "only the last entry in an interface block may be a runtime-sized "
1074 "array");
1075 }
Robert Phillipsfe8da172018-01-24 14:52:02 +00001076 if (vd.fVar == fRTAdjust) {
1077 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001078 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +00001079 fRTAdjustFieldIndex = fields.size();
1080 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001081 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
1082 &vd.fVar->fType));
1083 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001084 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001085 "initializers are not permitted on interface block fields");
1086 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001087 if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
Ethan Nicholasfc994162019-06-06 10:04:27 -04001088 Modifiers::kOut_Flag |
1089 Modifiers::kUniform_Flag |
1090 Modifiers::kBuffer_Flag |
1091 Modifiers::kConst_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001092 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001093 "interface block fields may not have storage qualifiers");
1094 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001095 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
1096 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001097 haveRuntimeArray = true;
1098 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001099 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001100 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001101 this->popSymbolTable();
John Stiles3ae071e2020-08-05 15:29:29 -04001102 const Type* type =
1103 old->takeOwnershipOfSymbol(std::make_unique<Type>(intf.fOffset, id.fTypeName, fields));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001104 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001105 for (size_t i = 0; i < id.fSizeCount; ++i) {
1106 const ASTNode& size = *(iter++);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001107 if (size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001108 std::unique_ptr<Expression> converted = this->convertExpression(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001109 if (!converted) {
1110 return nullptr;
1111 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001112 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001113 int64_t count;
1114 if (converted->fKind == Expression::kIntLiteral_Kind) {
1115 count = ((IntLiteral&) *converted).fValue;
1116 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001117 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -04001118 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001119 }
1120 name += "[" + to_string(count) + "]";
1121 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001122 fErrors.error(intf.fOffset, "array size must be specified");
1123 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001124 }
John Stiles3ae071e2020-08-05 15:29:29 -04001125 type = symbols->takeOwnershipOfSymbol(
1126 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001127 sizes.push_back(std::move(converted));
1128 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001129 fErrors.error(intf.fOffset, "array size must be specified");
1130 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001131 }
1132 }
John Stiles3ae071e2020-08-05 15:29:29 -04001133 const Variable* var = old->takeOwnershipOfSymbol(
1134 std::make_unique<Variable>(intf.fOffset,
1135 id.fModifiers,
1136 id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
1137 *type,
1138 Variable::kGlobal_Storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +00001139 if (foundRTAdjust) {
1140 fRTAdjustInterfaceBlock = var;
1141 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001142 if (id.fInstanceName.fLength) {
1143 old->addWithoutOwnership(id.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -07001144 } else {
1145 for (size_t i = 0; i < fields.size(); i++) {
John Stilesfbd050b2020-08-03 13:21:46 -04001146 old->add(fields[i].fName, std::make_unique<Field>(intf.fOffset, *var, (int)i));
ethannicholasb3058bd2016-07-01 08:22:01 -07001147 }
1148 }
John Stilesfbd050b2020-08-03 13:21:46 -04001149 return std::make_unique<InterfaceBlock>(intf.fOffset,
1150 var,
1151 id.fTypeName,
1152 id.fInstanceName,
1153 std::move(sizes),
1154 symbols);
ethannicholasb3058bd2016-07-01 08:22:01 -07001155}
1156
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001157void IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
1158 switch (value.fKind) {
1159 case Expression::kIntLiteral_Kind:
1160 *out = ((const IntLiteral&) value).fValue;
1161 break;
1162 case Expression::kVariableReference_Kind: {
1163 const Variable& var = ((VariableReference&) value).fVariable;
1164 if ((var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
1165 var.fInitialValue) {
1166 this->getConstantInt(*var.fInitialValue, out);
1167 }
1168 break;
1169 }
1170 default:
1171 fErrors.error(value.fOffset, "expected a constant int");
1172 }
1173}
1174
Ethan Nicholasfc994162019-06-06 10:04:27 -04001175void IRGenerator::convertEnum(const ASTNode& e) {
1176 SkASSERT(e.fKind == ASTNode::Kind::kEnum);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001177 std::vector<Variable*> variables;
1178 int64_t currentValue = 0;
1179 Layout layout;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001180 ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
1181 ASTNode::TypeData(e.getString(), false, false));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001182 const Type* type = this->convertType(enumType);
1183 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001184 std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable));
Ethan Nicholaseace9352018-10-15 20:09:54 +00001185 fSymbolTable = symbols;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001186 for (auto iter = e.begin(); iter != e.end(); ++iter) {
1187 const ASTNode& child = *iter;
1188 SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001189 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001190 if (child.begin() != child.end()) {
1191 value = this->convertExpression(*child.begin());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001192 if (!value) {
Ethan Nicholaseace9352018-10-15 20:09:54 +00001193 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001194 return;
1195 }
1196 this->getConstantInt(*value, &currentValue);
1197 }
1198 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
1199 ++currentValue;
John Stilesfbd050b2020-08-03 13:21:46 -04001200 auto var = std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), *type,
1201 Variable::kGlobal_Storage, value.get());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001202 variables.push_back(var.get());
Ethan Nicholasfc994162019-06-06 10:04:27 -04001203 symbols->add(child.getString(), std::move(var));
John Stiles3ae071e2020-08-05 15:29:29 -04001204 symbols->takeOwnershipOfIRNode(std::move(value));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001205 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001206 fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.getString(),
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001207 symbols, fIsBuiltinCode)));
Ethan Nicholaseace9352018-10-15 20:09:54 +00001208 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001209}
1210
Ethan Nicholasfc994162019-06-06 10:04:27 -04001211const Type* IRGenerator::convertType(const ASTNode& type) {
1212 ASTNode::TypeData td = type.getTypeData();
1213 const Symbol* result = (*fSymbolTable)[td.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001214 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001215 if (td.fIsNullable) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001216 if (((Type&) *result) == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001217 if (type.begin() != type.end()) {
1218 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001219 "an array");
1220 }
John Stiles3ae071e2020-08-05 15:29:29 -04001221 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1222 String(result->fName) + "?", Type::kNullable_Kind, (const Type&)*result));
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001223 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001224 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001225 }
1226 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001227 for (const auto& size : type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001228 String name(result->fName);
1229 name += "[";
Ethan Nicholasfc994162019-06-06 10:04:27 -04001230 if (size) {
1231 name += to_string(size.getInt());
Ethan Nicholas50afc172017-02-16 14:49:57 -05001232 }
1233 name += "]";
John Stiles3ae071e2020-08-05 15:29:29 -04001234 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1235 name, Type::kArray_Kind, (const Type&)*result, size ? size.getInt() : 0));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001236 }
ethannicholasd598f792016-07-25 10:08:54 -07001237 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001238 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001239 fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001240 return nullptr;
1241}
1242
Ethan Nicholasfc994162019-06-06 10:04:27 -04001243std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001244 switch (expr.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001245 case ASTNode::Kind::kBinary:
1246 return this->convertBinaryExpression(expr);
1247 case ASTNode::Kind::kBool:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001248 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001249 expr.getBool()));
1250 case ASTNode::Kind::kCall:
1251 return this->convertCallExpression(expr);
1252 case ASTNode::Kind::kField:
1253 return this->convertFieldExpression(expr);
1254 case ASTNode::Kind::kFloat:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001255 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001256 expr.getFloat()));
1257 case ASTNode::Kind::kIdentifier:
1258 return this->convertIdentifier(expr);
1259 case ASTNode::Kind::kIndex:
1260 return this->convertIndexExpression(expr);
1261 case ASTNode::Kind::kInt:
1262 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
1263 expr.getInt()));
1264 case ASTNode::Kind::kNull:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001265 return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001266 case ASTNode::Kind::kPostfix:
1267 return this->convertPostfixExpression(expr);
1268 case ASTNode::Kind::kPrefix:
1269 return this->convertPrefixExpression(expr);
1270 case ASTNode::Kind::kTernary:
1271 return this->convertTernaryExpression(expr);
ethannicholasb3058bd2016-07-01 08:22:01 -07001272 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001273#ifdef SK_DEBUG
Ethan Nicholasfc994162019-06-06 10:04:27 -04001274 ABORT("unsupported expression: %s\n", expr.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001275#endif
1276 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001277 }
1278}
1279
Ethan Nicholasfc994162019-06-06 10:04:27 -04001280std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
1281 SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
1282 const Symbol* result = (*fSymbolTable)[identifier.getString()];
ethannicholasb3058bd2016-07-01 08:22:01 -07001283 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001284 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001285 return nullptr;
1286 }
1287 switch (result->fKind) {
1288 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001289 std::vector<const FunctionDeclaration*> f = {
1290 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -07001291 };
John Stilesfbd050b2020-08-03 13:21:46 -04001292 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001293 }
1294 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001295 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001296 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
ethannicholasb3058bd2016-07-01 08:22:01 -07001297 }
1298 case Symbol::kVariable_Kind: {
Ethan Nicholas38657112017-02-09 17:01:22 -05001299 const Variable* var = (const Variable*) result;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001300 switch (var->fModifiers.fLayout.fBuiltin) {
1301 case SK_WIDTH_BUILTIN:
1302 fInputs.fRTWidth = true;
1303 break;
1304 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001305 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001306 break;
1307#ifndef SKSL_STANDALONE
1308 case SK_FRAGCOORD_BUILTIN:
Brian Osman9f313b62019-10-02 12:03:11 -04001309 fInputs.fFlipY = true;
1310 if (fSettings->fFlipY &&
1311 (!fSettings->fCaps ||
1312 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1313 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001314 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001315#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001316 }
Ethan Nicholas33c59ed2019-08-13 10:21:38 -04001317 if (fKind == Program::kFragmentProcessor_Kind &&
1318 (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
1319 !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
1320 !var->fModifiers.fLayout.fKey &&
1321 var->fModifiers.fLayout.fBuiltin == -1 &&
1322 var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
1323 var->fType.kind() != Type::kSampler_Kind) {
1324 bool valid = false;
1325 for (const auto& decl : fFile->root()) {
1326 if (decl.fKind == ASTNode::Kind::kSection) {
1327 ASTNode::SectionData section = decl.getSectionData();
1328 if (section.fName == "setData") {
1329 valid = true;
1330 break;
1331 }
1332 }
1333 }
1334 if (!valid) {
1335 fErrors.error(identifier.fOffset, "'in' variable must be either 'uniform' or "
1336 "'layout(key)', or there must be a custom "
1337 "@setData function");
1338 }
1339 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001340 // default to kRead_RefKind; this will be corrected later if the variable is written to
John Stilesfbd050b2020-08-03 13:21:46 -04001341 return std::make_unique<VariableReference>(identifier.fOffset,
1342 *var,
1343 VariableReference::kRead_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001344 }
1345 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001346 const Field* field = (const Field*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001347 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001348 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001349 return std::unique_ptr<Expression>(new FieldAccess(
1350 std::unique_ptr<Expression>(base),
1351 field->fFieldIndex,
1352 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001353 }
1354 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001355 const Type* t = (const Type*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001356 return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001357 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001358 case Symbol::kExternal_Kind: {
1359 ExternalValue* r = (ExternalValue*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001360 return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
Ethan Nicholas91164d12019-05-15 15:29:54 -04001361 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001362 default:
1363 ABORT("unsupported symbol type %d\n", result->fKind);
1364 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001365}
1366
Ethan Nicholasfc994162019-06-06 10:04:27 -04001367std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
1368 ASTNode::SectionData section = s.getSectionData();
John Stilesfbd050b2020-08-03 13:21:46 -04001369 return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument,
1370 section.fText);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001371}
1372
1373
Ethan Nicholas11d53972016-11-28 11:23:23 -05001374std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001375 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001376 if (!expr) {
1377 return nullptr;
1378 }
ethannicholasd598f792016-07-25 10:08:54 -07001379 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001380 return expr;
1381 }
1382 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001383 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001384 return nullptr;
1385 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001386 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001387 fErrors.error(expr->fOffset, "expected '" + type.displayName() + "', but found '" +
1388 expr->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001389 return nullptr;
1390 }
ethannicholasd598f792016-07-25 10:08:54 -07001391 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001392 std::vector<std::unique_ptr<Expression>> args;
1393 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001394 std::unique_ptr<Expression> ctor;
1395 if (type == *fContext.fFloatLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001396 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1397 "float"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001398 } else if (type == *fContext.fIntLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001399 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1400 "int"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001401 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001402 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1403 type.fName));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001404 }
1405 if (!ctor) {
1406 printf("error, null identifier: %s\n", String(type.fName).c_str());
1407 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001408 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001409 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001410 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001411 if (expr->fKind == Expression::kNullLiteral_Kind) {
1412 SkASSERT(type.kind() == Type::kNullable_Kind);
1413 return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
1414 }
ethannicholas5961bc92016-10-12 06:39:56 -07001415 std::vector<std::unique_ptr<Expression>> args;
1416 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001417 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001418}
1419
ethannicholasf789b382016-08-03 12:43:36 -07001420static bool is_matrix_multiply(const Type& left, const Type& right) {
1421 if (left.kind() == Type::kMatrix_Kind) {
1422 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1423 }
1424 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1425}
ethannicholasea4567c2016-10-17 11:24:37 -07001426
ethannicholasb3058bd2016-07-01 08:22:01 -07001427/**
1428 * Determines the operand and result types of a binary expression. Returns true if the expression is
1429 * legal, false otherwise. If false, the values of the out parameters are undefined.
1430 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001431static bool determine_binary_type(const Context& context,
1432 Token::Kind op,
1433 const Type& left,
1434 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001435 const Type** outLeftType,
1436 const Type** outRightType,
1437 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001438 bool tryFlipped) {
1439 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001440 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001441 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001442 case Token::Kind::TK_EQ:
ethannicholasea4567c2016-10-17 11:24:37 -07001443 *outLeftType = &left;
1444 *outRightType = &left;
1445 *outResultType = &left;
1446 return right.canCoerceTo(left);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001447 case Token::Kind::TK_EQEQ: // fall through
1448 case Token::Kind::TK_NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001449 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001450 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001451 *outRightType = &left;
1452 *outResultType = context.fBool_Type.get();
1453 return true;
1454 } if (left.canCoerceTo(right)) {
1455 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001456 *outRightType = &right;
1457 *outResultType = context.fBool_Type.get();
1458 return true;
1459 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001460 return false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001461 case Token::Kind::TK_LT: // fall through
1462 case Token::Kind::TK_GT: // fall through
1463 case Token::Kind::TK_LTEQ: // fall through
1464 case Token::Kind::TK_GTEQ:
ethannicholasb3058bd2016-07-01 08:22:01 -07001465 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001466 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001467 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001468 case Token::Kind::TK_LOGICALOR: // fall through
1469 case Token::Kind::TK_LOGICALAND: // fall through
1470 case Token::Kind::TK_LOGICALXOR: // fall through
1471 case Token::Kind::TK_LOGICALOREQ: // fall through
1472 case Token::Kind::TK_LOGICALANDEQ: // fall through
1473 case Token::Kind::TK_LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001474 *outLeftType = context.fBool_Type.get();
1475 *outRightType = context.fBool_Type.get();
1476 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001477 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001478 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001479 case Token::Kind::TK_STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001480 if (left.kind() == Type::kScalar_Kind) {
1481 *outLeftType = &left;
1482 *outRightType = &left;
1483 *outResultType = &left;
1484 return right.canCoerceTo(left);
1485 }
John Stiles30212b72020-06-11 17:55:07 -04001486 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001487 case Token::Kind::TK_STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001488 if (is_matrix_multiply(left, right)) {
1489 // determine final component type
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001490 if (determine_binary_type(context, Token::Kind::TK_STAR, left.componentType(),
ethannicholasf789b382016-08-03 12:43:36 -07001491 right.componentType(), outLeftType, outRightType,
1492 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001493 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001494 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001495 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001496 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001497 int leftColumns = left.columns();
1498 int leftRows = left.rows();
1499 int rightColumns;
1500 int rightRows;
1501 if (right.kind() == Type::kVector_Kind) {
1502 // matrix * vector treats the vector as a column vector, so we need to
1503 // transpose it
1504 rightColumns = right.rows();
1505 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001506 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001507 } else {
1508 rightColumns = right.columns();
1509 rightRows = right.rows();
1510 }
1511 if (rightColumns > 1) {
1512 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1513 leftRows);
1514 } else {
1515 // result was a column vector, transpose it back to a row
1516 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1517 rightColumns);
1518 }
1519 return leftColumns == rightRows;
1520 } else {
1521 return false;
1522 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001523 }
ethannicholasea4567c2016-10-17 11:24:37 -07001524 isLogical = false;
1525 validMatrixOrVectorOp = true;
1526 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001527 case Token::Kind::TK_PLUSEQ:
1528 case Token::Kind::TK_MINUSEQ:
1529 case Token::Kind::TK_SLASHEQ:
1530 case Token::Kind::TK_PERCENTEQ:
1531 case Token::Kind::TK_SHLEQ:
1532 case Token::Kind::TK_SHREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001533 if (left.kind() == Type::kScalar_Kind) {
1534 *outLeftType = &left;
1535 *outRightType = &left;
1536 *outResultType = &left;
1537 return right.canCoerceTo(left);
1538 }
John Stiles30212b72020-06-11 17:55:07 -04001539 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001540 case Token::Kind::TK_PLUS: // fall through
1541 case Token::Kind::TK_MINUS: // fall through
1542 case Token::Kind::TK_SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001543 isLogical = false;
1544 validMatrixOrVectorOp = true;
1545 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001546 case Token::Kind::TK_COMMA:
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001547 *outLeftType = &left;
1548 *outRightType = &right;
1549 *outResultType = &right;
1550 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001551 default:
1552 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001553 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001554 }
ethannicholasea4567c2016-10-17 11:24:37 -07001555 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001556 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1557 right.canCoerceTo(left)) {
1558 if (left.priority() > right.priority()) {
1559 *outLeftType = &left;
1560 *outRightType = &left;
1561 } else {
1562 *outLeftType = &right;
1563 *outRightType = &right;
1564 }
1565 if (isLogical) {
1566 *outResultType = context.fBool_Type.get();
1567 } else {
1568 *outResultType = &left;
1569 }
1570 return true;
1571 }
1572 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001573 *outLeftType = &left;
1574 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001575 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001576 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001577 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001578 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001579 }
1580 return true;
1581 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001582 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001583 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001584 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001585 outRightType, outResultType, false)) {
1586 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001587 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001588 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001589 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001590 }
1591 return true;
1592 }
1593 return false;
1594 }
1595 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001596 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001597 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001598 }
1599 return false;
1600}
1601
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001602static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1603 const Expression& left,
1604 Token::Kind op,
1605 const Expression& right) {
1606 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
1607 bool leftVal = ((BoolLiteral&) left).fValue;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001608 if (op == Token::Kind::TK_LOGICALAND) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001609 // (true && expr) -> (expr) and (false && expr) -> (false)
1610 return leftVal ? right.clone()
1611 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001612 } else if (op == Token::Kind::TK_LOGICALOR) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001613 // (true || expr) -> (true) and (false || expr) -> (expr)
1614 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1615 : right.clone();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001616 } else if (op == Token::Kind::TK_LOGICALXOR) {
Noah Lavine334d0ba2019-12-18 23:03:49 -05001617 // (true ^^ expr) -> !(expr) and (false ^^ expr) -> (expr)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001618 return leftVal ? std::unique_ptr<Expression>(new PrefixExpression(
1619 Token::Kind::TK_LOGICALNOT,
1620 right.clone()))
Noah Lavine334d0ba2019-12-18 23:03:49 -05001621 : right.clone();
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001622 } else {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001623 return nullptr;
1624 }
1625}
1626
ethannicholas08a92112016-11-09 13:26:45 -08001627std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1628 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001629 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001630 // If the left side is a constant boolean literal, the right side does not need to be constant
1631 // for short circuit optimizations to allow the constant to be folded.
Brian Osmanb6b95732020-06-30 11:44:27 -04001632 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001633 return short_circuit_boolean(fContext, left, op, right);
Brian Osmanb6b95732020-06-30 11:44:27 -04001634 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001635 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1636 // (right OP left) for short-circuit optimizations
1637 return short_circuit_boolean(fContext, right, op, left);
1638 }
1639
1640 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Brian Osmanb6b95732020-06-30 11:44:27 -04001641 if (!left.isCompileTimeConstant() || !right.isCompileTimeConstant()) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001642 return nullptr;
1643 }
ethannicholas08a92112016-11-09 13:26:45 -08001644 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1645 // precision to calculate the results and hope the result makes sense. The plan is to move the
1646 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1647 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001648 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001649 right.fKind == Expression::kBoolLiteral_Kind) {
1650 bool leftVal = ((BoolLiteral&) left).fValue;
1651 bool rightVal = ((BoolLiteral&) right).fValue;
1652 bool result;
1653 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001654 case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
1655 case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
1656 case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
ethannicholas08a92112016-11-09 13:26:45 -08001657 default: return nullptr;
1658 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001659 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001660 }
John Stilesfbd050b2020-08-03 13:21:46 -04001661 #define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1662 leftVal op rightVal)
1663 #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1664 (uint32_t) leftVal op \
1665 (uint32_t) rightVal)
ethannicholas08a92112016-11-09 13:26:45 -08001666 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
1667 int64_t leftVal = ((IntLiteral&) left).fValue;
1668 int64_t rightVal = ((IntLiteral&) right).fValue;
1669 switch (op) {
Ethan Nicholas66869e92020-04-30 09:27:54 -04001670 case Token::Kind::TK_PLUS: return URESULT(Int, +);
1671 case Token::Kind::TK_MINUS: return URESULT(Int, -);
1672 case Token::Kind::TK_STAR: return URESULT(Int, *);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001673 case Token::Kind::TK_SLASH:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001674 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1675 fErrors.error(right.fOffset, "arithmetic overflow");
1676 return nullptr;
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001677 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001678 if (!rightVal) {
1679 fErrors.error(right.fOffset, "division by zero");
1680 return nullptr;
1681 }
1682 return RESULT(Int, /);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001683 case Token::Kind::TK_PERCENT:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001684 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1685 fErrors.error(right.fOffset, "arithmetic overflow");
1686 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001687 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001688 if (!rightVal) {
1689 fErrors.error(right.fOffset, "division by zero");
1690 return nullptr;
1691 }
1692 return RESULT(Int, %);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001693 case Token::Kind::TK_BITWISEAND: return RESULT(Int, &);
1694 case Token::Kind::TK_BITWISEOR: return RESULT(Int, |);
1695 case Token::Kind::TK_BITWISEXOR: return RESULT(Int, ^);
1696 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1697 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1698 case Token::Kind::TK_GT: return RESULT(Bool, >);
1699 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1700 case Token::Kind::TK_LT: return RESULT(Bool, <);
1701 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1702 case Token::Kind::TK_SHL:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001703 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001704 return URESULT(Int, <<);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001705 }
1706 fErrors.error(right.fOffset, "shift value out of range");
1707 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001708 case Token::Kind::TK_SHR:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001709 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001710 return URESULT(Int, >>);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001711 }
1712 fErrors.error(right.fOffset, "shift value out of range");
1713 return nullptr;
1714
1715 default:
1716 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001717 }
1718 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001719 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001720 right.fKind == Expression::kFloatLiteral_Kind) {
1721 double leftVal = ((FloatLiteral&) left).fValue;
1722 double rightVal = ((FloatLiteral&) right).fValue;
1723 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001724 case Token::Kind::TK_PLUS: return RESULT(Float, +);
1725 case Token::Kind::TK_MINUS: return RESULT(Float, -);
1726 case Token::Kind::TK_STAR: return RESULT(Float, *);
1727 case Token::Kind::TK_SLASH:
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001728 if (rightVal) {
1729 return RESULT(Float, /);
1730 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001731 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001732 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001733 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1734 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1735 case Token::Kind::TK_GT: return RESULT(Bool, >);
1736 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1737 case Token::Kind::TK_LT: return RESULT(Bool, <);
1738 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1739 default: return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001740 }
1741 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001742 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001743 left.fType == right.fType) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001744 std::vector<std::unique_ptr<Expression>> args;
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001745 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1746 for (int i = 0; i < left.fType.columns(); i++) { \
1747 float value = left.getFVecComponent(i) op \
1748 right.getFVecComponent(i); \
1749 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
1750 } \
1751 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001752 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001753 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001754 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001755 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001756 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001757 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001758 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001759 !left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001760 case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1761 case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1762 case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1763 case Token::Kind::TK_SLASH:
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001764 for (int i = 0; i < left.fType.columns(); i++) {
1765 SKSL_FLOAT rvalue = right.getFVecComponent(i);
1766 if (rvalue == 0.0) {
1767 fErrors.error(right.fOffset, "division by zero");
1768 return nullptr;
1769 }
1770 float value = left.getFVecComponent(i) / rvalue;
1771 args.emplace_back(new FloatLiteral(fContext, -1, value));
1772 }
1773 return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
1774 std::move(args)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001775 default: return nullptr;
1776 }
1777 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001778 if (left.fType.kind() == Type::kMatrix_Kind &&
1779 right.fType.kind() == Type::kMatrix_Kind &&
1780 left.fKind == right.fKind) {
1781 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001782 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001783 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001784 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001785 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001786 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001787 !left.compareConstant(fContext, right)));
1788 default:
1789 return nullptr;
1790 }
1791 }
ethannicholas08a92112016-11-09 13:26:45 -08001792 #undef RESULT
1793 return nullptr;
1794}
1795
Ethan Nicholasfc994162019-06-06 10:04:27 -04001796std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
1797 SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
1798 auto iter = expression.begin();
1799 std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001800 if (!left) {
1801 return nullptr;
1802 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001803 Token::Kind op = expression.getToken().fKind;
John Stilesd1c4dac2020-08-11 18:50:50 -04001804 std::unique_ptr<Expression> right;
1805 {
1806 // Can't inline the right side of a short-circuiting boolean, because our inlining
1807 // approach runs things out of order.
1808 AutoDisableInline disableInline(this, /*canInline=*/(op != Token::Kind::TK_LOGICALAND &&
1809 op != Token::Kind::TK_LOGICALOR));
1810 right = this->convertExpression(*(iter++));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001811 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001812 if (!right) {
1813 return nullptr;
1814 }
ethannicholasd598f792016-07-25 10:08:54 -07001815 const Type* leftType;
1816 const Type* rightType;
1817 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001818 const Type* rawLeftType;
1819 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1820 rawLeftType = &right->fType;
1821 } else {
1822 rawLeftType = &left->fType;
1823 }
1824 const Type* rawRightType;
1825 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1826 rawRightType = &left->fType;
1827 } else {
1828 rawRightType = &right->fType;
1829 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001830 if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
1831 &resultType, !Compiler::IsAssignment(op))) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001832 fErrors.error(expression.fOffset, String("type mismatch: '") +
Ethan Nicholasfc994162019-06-06 10:04:27 -04001833 Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001834 "' cannot operate on '" + left->fType.displayName() +
1835 "', '" + right->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001836 return nullptr;
1837 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001838 if (Compiler::IsAssignment(op)) {
Ethan Nicholas4fadce42020-07-30 13:29:30 -04001839 if (!this->setRefKind(*left, op != Token::Kind::TK_EQ
1840 ? VariableReference::kReadWrite_RefKind
1841 : VariableReference::kWrite_RefKind)) {
1842 return nullptr;
1843 }
ethannicholasea4567c2016-10-17 11:24:37 -07001844 }
1845 left = this->coerce(std::move(left), *leftType);
1846 right = this->coerce(std::move(right), *rightType);
1847 if (!left || !right) {
1848 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001850 std::unique_ptr<Expression> result = this->constantFold(*left.get(), op, *right.get());
ethannicholas08a92112016-11-09 13:26:45 -08001851 if (!result) {
John Stilesd1c4dac2020-08-11 18:50:50 -04001852 result = std::make_unique<BinaryExpression>(expression.fOffset, std::move(left), op,
1853 std::move(right), *resultType);
ethannicholas08a92112016-11-09 13:26:45 -08001854 }
1855 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001856}
1857
Ethan Nicholasfc994162019-06-06 10:04:27 -04001858std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
1859 SkASSERT(node.fKind == ASTNode::Kind::kTernary);
1860 auto iter = node.begin();
1861 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -07001862 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001863 if (!test) {
1864 return nullptr;
1865 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001866 std::unique_ptr<Expression> ifTrue = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001867 if (!ifTrue) {
1868 return nullptr;
1869 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001870 std::unique_ptr<Expression> ifFalse = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001871 if (!ifFalse) {
1872 return nullptr;
1873 }
ethannicholasd598f792016-07-25 10:08:54 -07001874 const Type* trueType;
1875 const Type* falseType;
1876 const Type* resultType;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001877 if (!determine_binary_type(fContext, Token::Kind::TK_EQEQ, ifTrue->fType, ifFalse->fType,
1878 &trueType, &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001879 fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001880 ifTrue->fType.displayName() + "', '" +
1881 ifFalse->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001882 return nullptr;
1883 }
Brian Osman82329002020-07-21 09:39:27 -04001884 if (trueType->nonnullable() == *fContext.fFragmentProcessor_Type) {
1885 fErrors.error(node.fOffset,
1886 "ternary expression of type '" + trueType->displayName() + "' not allowed");
1887 return nullptr;
1888 }
ethannicholasd598f792016-07-25 10:08:54 -07001889 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001890 if (!ifTrue) {
1891 return nullptr;
1892 }
ethannicholasd598f792016-07-25 10:08:54 -07001893 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001894 if (!ifFalse) {
1895 return nullptr;
1896 }
ethannicholas08a92112016-11-09 13:26:45 -08001897 if (test->fKind == Expression::kBoolLiteral_Kind) {
1898 // static boolean test, just return one of the branches
1899 if (((BoolLiteral&) *test).fValue) {
1900 return ifTrue;
1901 } else {
1902 return ifFalse;
1903 }
1904 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001905 return std::unique_ptr<Expression>(new TernaryExpression(node.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001906 std::move(test),
Ethan Nicholas11d53972016-11-28 11:23:23 -05001907 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -07001908 std::move(ifFalse)));
1909}
1910
John Stilesddefaee2020-08-11 15:13:26 -04001911std::unique_ptr<Expression> IRGenerator::inlineExpression(
1912 int offset,
1913 std::unordered_map<const Variable*, const Variable*>* varMap,
1914 const Expression& expression) {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001915 auto expr = [&](const std::unique_ptr<Expression>& e) {
1916 if (e) {
1917 return this->inlineExpression(offset, varMap, *e);
1918 }
1919 return std::unique_ptr<Expression>(nullptr);
1920 };
1921 switch (expression.fKind) {
1922 case Expression::kBinary_Kind: {
1923 const BinaryExpression& b = (const BinaryExpression&) expression;
1924 return std::unique_ptr<Expression>(new BinaryExpression(offset,
1925 expr(b.fLeft),
1926 b.fOperator,
1927 expr(b.fRight),
1928 b.fType));
1929 }
1930 case Expression::kBoolLiteral_Kind:
1931 case Expression::kIntLiteral_Kind:
1932 case Expression::kFloatLiteral_Kind:
1933 case Expression::kNullLiteral_Kind:
1934 return expression.clone();
1935 case Expression::kConstructor_Kind: {
1936 const Constructor& c = (const Constructor&) expression;
1937 std::vector<std::unique_ptr<Expression>> args;
1938 for (const auto& arg : c.fArguments) {
1939 args.push_back(expr(arg));
1940 }
1941 return std::unique_ptr<Expression>(new Constructor(offset, c.fType, std::move(args)));
1942 }
1943 case Expression::kExternalFunctionCall_Kind: {
1944 const ExternalFunctionCall& e = (const ExternalFunctionCall&) expression;
1945 std::vector<std::unique_ptr<Expression>> args;
1946 for (const auto& arg : e.fArguments) {
1947 args.push_back(expr(arg));
1948 }
1949 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, e.fType,
1950 e.fFunction,
1951 std::move(args)));
1952 }
1953 case Expression::kExternalValue_Kind:
1954 return expression.clone();
1955 case Expression::kFieldAccess_Kind: {
1956 const FieldAccess& f = (const FieldAccess&) expression;
1957 return std::unique_ptr<Expression>(new FieldAccess(expr(f.fBase), f.fFieldIndex,
1958 f.fOwnerKind));
1959 }
1960 case Expression::kFunctionCall_Kind: {
1961 const FunctionCall& c = (const FunctionCall&) expression;
1962 std::vector<std::unique_ptr<Expression>> args;
1963 for (const auto& arg : c.fArguments) {
1964 args.push_back(expr(arg));
1965 }
1966 return std::unique_ptr<Expression>(new FunctionCall(offset, c.fType, c.fFunction,
1967 std::move(args)));
1968 }
1969 case Expression::kIndex_Kind: {
1970 const IndexExpression& idx = (const IndexExpression&) expression;
1971 return std::unique_ptr<Expression>(new IndexExpression(fContext, expr(idx.fBase),
1972 expr(idx.fIndex)));
1973 }
1974 case Expression::kPrefix_Kind: {
1975 const PrefixExpression& p = (const PrefixExpression&) expression;
1976 return std::unique_ptr<Expression>(new PrefixExpression(p.fOperator, expr(p.fOperand)));
1977 }
1978 case Expression::kPostfix_Kind: {
1979 const PostfixExpression& p = (const PostfixExpression&) expression;
1980 return std::unique_ptr<Expression>(new PostfixExpression(expr(p.fOperand),
1981 p.fOperator));
1982 }
1983 case Expression::kSetting_Kind:
1984 return expression.clone();
1985 case Expression::kSwizzle_Kind: {
1986 const Swizzle& s = (const Swizzle&) expression;
1987 return std::unique_ptr<Expression>(new Swizzle(fContext, expr(s.fBase), s.fComponents));
1988 }
1989 case Expression::kTernary_Kind: {
1990 const TernaryExpression& t = (const TernaryExpression&) expression;
1991 return std::unique_ptr<Expression>(new TernaryExpression(offset, expr(t.fTest),
1992 expr(t.fIfTrue),
1993 expr(t.fIfFalse)));
1994 }
1995 case Expression::kVariableReference_Kind: {
1996 const VariableReference& v = (const VariableReference&) expression;
1997 auto found = varMap->find(&v.fVariable);
1998 if (found != varMap->end()) {
1999 return std::unique_ptr<Expression>(new VariableReference(offset,
2000 *found->second,
2001 v.fRefKind));
2002 }
2003 return v.clone();
2004 }
2005 default:
2006 SkASSERT(false);
2007 return nullptr;
2008 }
2009}
2010
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002011const Type* copy_if_needed(const Type* src, SymbolTable& symbolTable) {
2012 if (src->kind() == Type::kArray_Kind) {
John Stiles3ae071e2020-08-05 15:29:29 -04002013 return symbolTable.takeOwnershipOfSymbol(std::make_unique<Type>(*src));
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002014 }
2015 return src;
2016}
2017
John Stilesddefaee2020-08-11 15:13:26 -04002018std::unique_ptr<Statement> IRGenerator::inlineStatement(
2019 int offset,
2020 std::unordered_map<const Variable*, const Variable*>* varMap,
2021 const Variable* returnVar,
2022 bool haveEarlyReturns,
2023 const Statement& statement) {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002024 auto stmt = [&](const std::unique_ptr<Statement>& s) {
2025 if (s) {
2026 return this->inlineStatement(offset, varMap, returnVar, haveEarlyReturns, *s);
2027 }
2028 return std::unique_ptr<Statement>(nullptr);
2029 };
2030 auto stmts = [&](const std::vector<std::unique_ptr<Statement>>& ss) {
2031 std::vector<std::unique_ptr<Statement>> result;
2032 for (const auto& s : ss) {
2033 result.push_back(stmt(s));
2034 }
2035 return result;
2036 };
2037 auto expr = [&](const std::unique_ptr<Expression>& e) {
2038 if (e) {
2039 return this->inlineExpression(offset, varMap, *e);
2040 }
2041 return std::unique_ptr<Expression>(nullptr);
2042 };
2043 switch (statement.fKind) {
2044 case Statement::kBlock_Kind: {
2045 const Block& b = (const Block&) statement;
John Stilesfbd050b2020-08-03 13:21:46 -04002046 return std::make_unique<Block>(offset, stmts(b.fStatements), b.fSymbols, b.fIsScope);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002047 }
2048
2049 case Statement::kBreak_Kind:
2050 case Statement::kContinue_Kind:
2051 case Statement::kDiscard_Kind:
2052 return statement.clone();
2053
2054 case Statement::kDo_Kind: {
2055 const DoStatement& d = (const DoStatement&) statement;
John Stilesfbd050b2020-08-03 13:21:46 -04002056 return std::make_unique<DoStatement>(offset, stmt(d.fStatement), expr(d.fTest));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002057 }
2058 case Statement::kExpression_Kind: {
2059 const ExpressionStatement& e = (const ExpressionStatement&) statement;
John Stilesfbd050b2020-08-03 13:21:46 -04002060 return std::make_unique<ExpressionStatement>(expr(e.fExpression));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002061 }
2062 case Statement::kFor_Kind: {
2063 const ForStatement& f = (const ForStatement&) statement;
2064 // need to ensure initializer is evaluated first so that we've already remapped its
2065 // declarations by the time we evaluate test & next
2066 std::unique_ptr<Statement> initializer = stmt(f.fInitializer);
John Stilesfbd050b2020-08-03 13:21:46 -04002067 return std::make_unique<ForStatement>(offset, std::move(initializer), expr(f.fTest),
2068 expr(f.fNext), stmt(f.fStatement), f.fSymbols);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002069 }
2070 case Statement::kIf_Kind: {
2071 const IfStatement& i = (const IfStatement&) statement;
John Stilesfbd050b2020-08-03 13:21:46 -04002072 return std::make_unique<IfStatement>(offset, i.fIsStatic, expr(i.fTest),
2073 stmt(i.fIfTrue), stmt(i.fIfFalse));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002074 }
2075 case Statement::kNop_Kind:
2076 return statement.clone();
2077 case Statement::kReturn_Kind: {
2078 const ReturnStatement& r = (const ReturnStatement&) statement;
2079 if (r.fExpression) {
John Stilesfbd050b2020-08-03 13:21:46 -04002080 std::unique_ptr<Statement> assignment = std::make_unique<ExpressionStatement>(
2081 std::make_unique<BinaryExpression>(
2082 offset,
2083 std::make_unique<VariableReference>(offset, *returnVar,
2084 VariableReference::kWrite_RefKind),
2085 Token::Kind::TK_EQ,
2086 expr(r.fExpression),
2087 returnVar->fType));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002088 if (haveEarlyReturns) {
2089 std::vector<std::unique_ptr<Statement>> block;
2090 block.push_back(std::move(assignment));
2091 block.emplace_back(new BreakStatement(offset));
John Stilesfbd050b2020-08-03 13:21:46 -04002092 return std::make_unique<Block>(offset, std::move(block), nullptr, false);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002093 } else {
2094 return assignment;
2095 }
2096 } else {
2097 if (haveEarlyReturns) {
John Stilesfbd050b2020-08-03 13:21:46 -04002098 return std::make_unique<BreakStatement>(offset);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002099 } else {
John Stilesfbd050b2020-08-03 13:21:46 -04002100 return std::make_unique<Nop>();
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002101 }
2102 }
2103 }
2104 case Statement::kSwitch_Kind: {
2105 const SwitchStatement& ss = (const SwitchStatement&) statement;
2106 std::vector<std::unique_ptr<SwitchCase>> cases;
2107 for (const auto& sc : ss.fCases) {
2108 cases.emplace_back(new SwitchCase(offset, expr(sc->fValue),
2109 stmts(sc->fStatements)));
2110 }
John Stilesfbd050b2020-08-03 13:21:46 -04002111 return std::make_unique<SwitchStatement>(offset, ss.fIsStatic, expr(ss.fValue),
2112 std::move(cases), ss.fSymbols);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002113 }
2114 case Statement::kVarDeclaration_Kind: {
2115 const VarDeclaration& decl = (const VarDeclaration&) statement;
2116 std::vector<std::unique_ptr<Expression>> sizes;
2117 for (const auto& size : decl.fSizes) {
2118 sizes.push_back(expr(size));
2119 }
2120 std::unique_ptr<Expression> initialValue = expr(decl.fValue);
2121 const Variable* old = decl.fVar;
Ethan Nicholase8ad02c2020-06-03 16:58:20 -04002122 // need to copy the var name in case the originating function is discarded and we lose
2123 // its symbols
2124 std::unique_ptr<String> name(new String(old->fName));
John Stiles3ae071e2020-08-05 15:29:29 -04002125 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002126 const Type* typePtr = copy_if_needed(&old->fType, *fSymbolTable);
John Stiles3ae071e2020-08-05 15:29:29 -04002127 const Variable* clone = fSymbolTable->takeOwnershipOfSymbol(
2128 std::make_unique<Variable>(offset,
2129 old->fModifiers,
2130 namePtr->c_str(),
2131 *typePtr,
2132 old->fStorage,
2133 initialValue.get()));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002134 (*varMap)[old] = clone;
John Stilesfbd050b2020-08-03 13:21:46 -04002135 return std::make_unique<VarDeclaration>(clone, std::move(sizes),
2136 std::move(initialValue));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002137 }
2138 case Statement::kVarDeclarations_Kind: {
2139 const VarDeclarations& decls = *((VarDeclarationsStatement&) statement).fDeclaration;
2140 std::vector<std::unique_ptr<VarDeclaration>> vars;
2141 for (const auto& var : decls.fVars) {
2142 vars.emplace_back((VarDeclaration*) stmt(var).release());
2143 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002144 const Type* typePtr = copy_if_needed(&decls.fBaseType, *fSymbolTable);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002145 return std::unique_ptr<Statement>(new VarDeclarationsStatement(
John Stilesfbd050b2020-08-03 13:21:46 -04002146 std::make_unique<VarDeclarations>(offset, typePtr, std::move(vars))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002147 }
2148 case Statement::kWhile_Kind: {
2149 const WhileStatement& w = (const WhileStatement&) statement;
John Stilesfbd050b2020-08-03 13:21:46 -04002150 return std::make_unique<WhileStatement>(offset, expr(w.fTest), stmt(w.fStatement));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002151 }
2152 default:
2153 SkASSERT(false);
2154 return nullptr;
2155 }
2156}
2157
2158int return_count(const Statement& statement) {
2159 switch (statement.fKind) {
2160 case Statement::kBlock_Kind: {
2161 const Block& b = (const Block&) statement;
2162 int result = 0;
2163 for (const auto& s : b.fStatements) {
2164 result += return_count(*s);
2165 }
2166 return result;
2167 }
2168 case Statement::kDo_Kind: {
2169 const DoStatement& d = (const DoStatement&) statement;
2170 return return_count(*d.fStatement);
2171 }
2172 case Statement::kFor_Kind: {
2173 const ForStatement& f = (const ForStatement&) statement;
2174 return return_count(*f.fStatement);
2175 }
2176 case Statement::kIf_Kind: {
2177 const IfStatement& i = (const IfStatement&) statement;
2178 int result = return_count(*i.fIfTrue);
2179 if (i.fIfFalse) {
2180 result += return_count(*i.fIfFalse);
2181 }
2182 return result;
2183 }
2184 case Statement::kReturn_Kind:
2185 return 1;
2186 case Statement::kSwitch_Kind: {
2187 const SwitchStatement& ss = (const SwitchStatement&) statement;
2188 int result = 0;
2189 for (const auto& sc : ss.fCases) {
2190 for (const auto& s : ((SwitchCase&) *sc).fStatements) {
2191 result += return_count(*s);
2192 }
2193 }
2194 return result;
2195 }
2196 case Statement::kWhile_Kind: {
2197 const WhileStatement& w = (const WhileStatement&) statement;
2198 return return_count(*w.fStatement);
2199 }
2200 case Statement::kBreak_Kind:
2201 case Statement::kContinue_Kind:
2202 case Statement::kDiscard_Kind:
2203 case Statement::kExpression_Kind:
2204 case Statement::kNop_Kind:
2205 case Statement::kVarDeclaration_Kind:
2206 case Statement::kVarDeclarations_Kind:
2207 return 0;
2208 default:
2209 SkASSERT(false);
2210 return 0;
2211 }
2212}
2213
2214bool has_early_return(const FunctionDefinition& f) {
2215 int returnCount = return_count(*f.fBody);
2216 if (returnCount == 0) {
2217 return false;
2218 }
2219 if (returnCount > 1) {
2220 return true;
2221 }
2222 SkASSERT(f.fBody->fKind == Statement::kBlock_Kind);
2223 return ((Block&) *f.fBody).fStatements.back()->fKind != Statement::kReturn_Kind;
2224}
2225
2226std::unique_ptr<Expression> IRGenerator::inlineCall(
2227 int offset,
2228 const FunctionDefinition& function,
2229 std::vector<std::unique_ptr<Expression>> arguments) {
2230 // Inlining is more complicated here than in a typical compiler, because we have to have a
2231 // high-level IR and can't just drop statements into the middle of an expression or even use
2232 // gotos.
2233 //
2234 // Since we can't insert statements into an expression, we run the inline function as extra
2235 // statements before the statement we're currently processing, relying on a lack of execution
2236 // order guarantees. Since we can't use gotos (which are normally used to replace return
2237 // statements), we wrap the whole function in a loop and use break statements to jump to the
2238 // end.
Brian Osmanb5f0f522020-07-23 13:28:14 -04002239
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002240 // Use unique variable names based on the function signature. Otherwise there are situations in
2241 // which an inlined function is later inlined into another function, and we end up with
2242 // duplicate names like 'inlineResult0' because the counter was reset. (skbug.com/10526)
2243 String raw = function.fDeclaration.description();
2244 String inlineSalt;
2245 for (size_t i = 0; i < raw.length(); ++i) {
2246 char c = raw[i];
2247 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
2248 c == '_') {
2249 inlineSalt += c;
2250 }
Brian Osmanb5f0f522020-07-23 13:28:14 -04002251 }
2252
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002253 Variable* resultVar;
2254 if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
2255 std::unique_ptr<String> name(new String());
Michael Ludwig9861b7c2020-06-23 18:37:17 -04002256 int varIndex = fInlineVarCounter++;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002257 name->appendf("_inlineResult%s%d", inlineSalt.c_str(), varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002258 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
2259 resultVar = new Variable(/*offset=*/-1, Modifiers(), namePtr->c_str(),
John Stilesfbd050b2020-08-03 13:21:46 -04002260 function.fDeclaration.fReturnType,
2261 Variable::kLocal_Storage,
2262 nullptr);
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002263 fSymbolTable->add(resultVar->fName, std::unique_ptr<Symbol>(resultVar));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002264 std::vector<std::unique_ptr<VarDeclaration>> variables;
2265 variables.emplace_back(new VarDeclaration(resultVar, {}, nullptr));
John Stilesfbd050b2020-08-03 13:21:46 -04002266 fExtraStatements.emplace_back(
2267 new VarDeclarationsStatement(std::make_unique<VarDeclarations>(
2268 offset, &resultVar->fType, std::move(variables))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002269
2270 } else {
2271 resultVar = nullptr;
2272 }
John Stilesddefaee2020-08-11 15:13:26 -04002273 std::unordered_map<const Variable*, const Variable*> varMap;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002274 // create variables to hold the arguments and assign the arguments to them
Michael Ludwig9861b7c2020-06-23 18:37:17 -04002275 int argIndex = fInlineVarCounter++;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002276 for (int i = 0; i < (int) arguments.size(); ++i) {
2277 std::unique_ptr<String> argName(new String());
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002278 argName->appendf("_inlineArg%s%d_%d", inlineSalt.c_str(), argIndex, i);
John Stiles3ae071e2020-08-05 15:29:29 -04002279 const String* argNamePtr = fSymbolTable->takeOwnershipOfString(std::move(argName));
2280 Variable* argVar =
2281 new Variable(/*offset=*/-1, Modifiers(), argNamePtr->c_str(), arguments[i]->fType,
2282 Variable::kLocal_Storage, arguments[i].get());
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002283 fSymbolTable->add(argVar->fName, std::unique_ptr<Symbol>(argVar));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002284 varMap[function.fDeclaration.fParameters[i]] = argVar;
2285 std::vector<std::unique_ptr<VarDeclaration>> vars;
2286 if (function.fDeclaration.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
2287 vars.emplace_back(new VarDeclaration(argVar, {}, arguments[i]->clone()));
2288 } else {
2289 vars.emplace_back(new VarDeclaration(argVar, {}, std::move(arguments[i])));
2290 }
2291 fExtraStatements.emplace_back(new VarDeclarationsStatement(
John Stilesfbd050b2020-08-03 13:21:46 -04002292 std::make_unique<VarDeclarations>(offset,
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002293 &argVar->fType,
John Stilesfbd050b2020-08-03 13:21:46 -04002294 std::move(vars))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002295 }
2296 SkASSERT(function.fBody->fKind == Statement::kBlock_Kind);
2297 const Block& body = (Block&) *function.fBody;
2298 bool hasEarlyReturn = has_early_return(function);
2299 std::vector<std::unique_ptr<Statement>> inlined;
2300 for (const auto& s : body.fStatements) {
2301 inlined.push_back(this->inlineStatement(offset, &varMap, resultVar, hasEarlyReturn, *s));
2302 }
2303 if (hasEarlyReturn) {
2304 // Since we output to backends that don't have a goto statement (which would normally be
2305 // used to perform an early return), we fake it by wrapping the function in a
2306 // do { } while (false); and then use break statements to jump to the end in order to
2307 // emulate a goto.
2308 fExtraStatements.emplace_back(new DoStatement(-1,
2309 std::unique_ptr<Statement>(new Block(-1, std::move(inlined))),
2310 std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false))));
2311 } else {
2312 // No early returns, so we can just dump the code in. We need to use a block so we don't get
2313 // name conflicts with locals.
2314 fExtraStatements.emplace_back(std::unique_ptr<Statement>(new Block(-1,
2315 std::move(inlined))));
2316 }
2317 // copy the values of out parameters into their destinations
2318 for (size_t i = 0; i < arguments.size(); ++i) {
2319 const Variable* p = function.fDeclaration.fParameters[i];
2320 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
2321 std::unique_ptr<Expression> varRef(new VariableReference(offset, *varMap[p]));
2322 fExtraStatements.emplace_back(new ExpressionStatement(
2323 std::unique_ptr<Expression>(new BinaryExpression(offset,
2324 arguments[i]->clone(),
2325 Token::Kind::TK_EQ,
2326 std::move(varRef),
2327 arguments[i]->fType))));
2328 }
2329 }
2330 if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
2331 return std::unique_ptr<Expression>(new VariableReference(-1, *resultVar));
2332 } else {
2333 // it's a void function, so it doesn't actually result in anything, but we have to return
2334 // something non-null as a standin
2335 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false));
2336 }
2337}
2338
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002339void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
2340 auto found = fIntrinsics->find(function.description());
2341 if (found != fIntrinsics->end() && !found->second.second) {
2342 found->second.second = true;
2343 FunctionDefinition& original = ((FunctionDefinition&) *found->second.first);
2344 for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
2345 this->copyIntrinsicIfNeeded(*f);
2346 }
2347 fProgramElements->push_back(original.clone());
2348 }
2349}
2350
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002351std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002352 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07002353 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002354 if (function.fBuiltin) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002355 if (function.fDefinition) {
2356 fReferencedIntrinsics.insert(&function);
2357 }
2358 if (!fIsBuiltinCode) {
2359 this->copyIntrinsicIfNeeded(function);
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002360 }
2361 }
ethannicholasd598f792016-07-25 10:08:54 -07002362 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002363 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05002364 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07002365 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07002366 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002367 msg += "s";
2368 }
ethannicholas5961bc92016-10-12 06:39:56 -07002369 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002370 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07002371 return nullptr;
2372 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002373 if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
Brian Osman5f6b41e2020-03-09 11:53:24 -04002374 String msg = "call to undefined function '" + function.fName + "'";
2375 fErrors.error(offset, msg);
2376 return nullptr;
2377 }
ethannicholas471e8942016-10-28 09:02:46 -07002378 std::vector<const Type*> types;
2379 const Type* returnType;
2380 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002381 String msg = "no match for " + function.fName + "(";
2382 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07002383 for (size_t i = 0; i < arguments.size(); i++) {
2384 msg += separator;
2385 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002386 msg += arguments[i]->fType.displayName();
ethannicholas471e8942016-10-28 09:02:46 -07002387 }
2388 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002389 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07002390 return nullptr;
2391 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002392 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07002393 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07002394 if (!arguments[i]) {
2395 return nullptr;
2396 }
ethannicholasd598f792016-07-25 10:08:54 -07002397 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002398 this->setRefKind(*arguments[i],
2399 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
2400 VariableReference::kReadWrite_RefKind :
2401 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002402 }
2403 }
Brian Osman3e8fae72020-08-07 18:09:37 +00002404 if (fCanInline && function.fDefinition && function.fDefinition->canBeInlined() &&
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002405 ((fSettings->fCaps && fSettings->fCaps->canUseDoLoops()) ||
2406 !has_early_return(*function.fDefinition))) {
2407 return this->inlineCall(offset, *function.fDefinition, std::move(arguments));
2408 }
John Stilesfbd050b2020-08-03 13:21:46 -04002409 return std::make_unique<FunctionCall>(offset, *returnType, function,
2410 std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002411}
2412
2413/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002414 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
2415 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
2416 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07002417 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002418int IRGenerator::callCost(const FunctionDeclaration& function,
2419 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07002420 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002421 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002422 }
2423 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07002424 std::vector<const Type*> types;
2425 const Type* ignored;
2426 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002427 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07002428 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002429 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002430 int cost = arguments[i]->coercionCost(*types[i]);
2431 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002432 total += cost;
2433 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002434 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002435 }
2436 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002437 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07002438}
2439
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002440std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002441 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07002442 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002443 switch (functionValue->fKind) {
2444 case Expression::kTypeReference_Kind:
2445 return this->convertConstructor(offset,
2446 ((TypeReference&) *functionValue).fValue,
2447 std::move(arguments));
2448 case Expression::kExternalValue_Kind: {
2449 ExternalValue* v = ((ExternalValueReference&) *functionValue).fValue;
2450 if (!v->canCall()) {
2451 fErrors.error(offset, "this external value is not a function");
2452 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002453 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002454 int count = v->callParameterCount();
2455 if (count != (int) arguments.size()) {
2456 fErrors.error(offset, "external function expected " + to_string(count) +
2457 " arguments, but found " + to_string((int) arguments.size()));
2458 return nullptr;
2459 }
2460 static constexpr int PARAMETER_MAX = 16;
2461 SkASSERT(count < PARAMETER_MAX);
2462 const Type* types[PARAMETER_MAX];
2463 v->getCallParameterTypes(types);
2464 for (int i = 0; i < count; ++i) {
2465 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
2466 if (!arguments[i]) {
2467 return nullptr;
2468 }
2469 }
2470 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(),
2471 v, std::move(arguments)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002472 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002473 case Expression::kFunctionReference_Kind: {
2474 FunctionReference* ref = (FunctionReference*) functionValue.get();
2475 int bestCost = INT_MAX;
2476 const FunctionDeclaration* best = nullptr;
2477 if (ref->fFunctions.size() > 1) {
2478 for (const auto& f : ref->fFunctions) {
2479 int cost = this->callCost(*f, arguments);
2480 if (cost < bestCost) {
2481 bestCost = cost;
2482 best = f;
2483 }
2484 }
2485 if (best) {
2486 return this->call(offset, *best, std::move(arguments));
2487 }
2488 String msg = "no match for " + ref->fFunctions[0]->fName + "(";
2489 String separator;
2490 for (size_t i = 0; i < arguments.size(); i++) {
2491 msg += separator;
2492 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002493 msg += arguments[i]->fType.displayName();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002494 }
2495 msg += ")";
2496 fErrors.error(offset, msg);
2497 return nullptr;
2498 }
2499 return this->call(offset, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002500 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002501 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002502 fErrors.error(offset, "not a function");
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002503 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002504 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002505}
2506
Ethan Nicholas84645e32017-02-09 13:57:14 -05002507std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002508 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002509 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07002510 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002511 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05002512 if (args.size() != 1) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002513 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002514 "' constructor, (expected exactly 1 argument, but found " +
2515 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07002516 return nullptr;
2517 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002518 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002519 return std::move(args[0]);
2520 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002521 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
2522 double value = ((FloatLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002523 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002524 }
2525 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002526 int64_t value = ((IntLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002527 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002528 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002529 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
2530 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04002531 return std::unique_ptr<Expression>(new IntLiteral(offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002532 ((IntLiteral&) *args[0]).fValue,
2533 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002534 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002535 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002536 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
2537 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002538 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002539 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05002540 this->coerce(std::move(one), type),
2541 this->coerce(std::move(zero),
2542 type)));
2543 }
2544 if (!args[0]->fType.isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002545 fErrors.error(offset, "invalid argument to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002546 "' constructor (expected a number or bool, but found '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002547 args[0]->fType.displayName() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002548 return nullptr;
2549 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002550 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002551}
2552
2553int component_count(const Type& type) {
2554 switch (type.kind()) {
2555 case Type::kVector_Kind:
2556 return type.columns();
2557 case Type::kMatrix_Kind:
2558 return type.columns() * type.rows();
2559 default:
2560 return 1;
2561 }
2562}
2563
2564std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002565 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002566 const Type& type,
2567 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002568 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05002569 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
2570 args[0]->fType.kind() == Type::kMatrix_Kind) {
2571 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002572 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002573 }
2574 int actual = 0;
2575 int expected = type.rows() * type.columns();
2576 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
2577 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07002578 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002579 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002580 if (type.componentType().isNumber() !=
2581 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002582 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2583 "parameter to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002584 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002585 return nullptr;
2586 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002587 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002588 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
2589 actual += 1;
2590 if (type.kind() != Type::kScalar_Kind) {
2591 args[i] = this->coerce(std::move(args[i]), type.componentType());
2592 if (!args[i]) {
2593 return nullptr;
2594 }
2595 }
2596 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002597 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2598 "parameter to '" + type.displayName() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002599 return nullptr;
2600 }
2601 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002602 if (actual != 1 && actual != expected) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002603 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002604 "' constructor (expected " + to_string(expected) +
2605 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002606 return nullptr;
2607 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002608 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002609 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002610}
2611
Ethan Nicholas84645e32017-02-09 13:57:14 -05002612std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002613 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002614 const Type& type,
2615 std::vector<std::unique_ptr<Expression>> args) {
2616 // FIXME: add support for structs
Brian Osman82329002020-07-21 09:39:27 -04002617 if (args.size() == 1 && args[0]->fType == type &&
2618 type.nonnullable() != *fContext.fFragmentProcessor_Type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002619 // argument is already the right type, just return it
2620 return std::move(args[0]);
2621 }
Brian Osman82329002020-07-21 09:39:27 -04002622 Type::Kind kind = type.kind();
Ethan Nicholas84645e32017-02-09 13:57:14 -05002623 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002624 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002625 } else if (kind == Type::kArray_Kind) {
2626 const Type& base = type.componentType();
2627 for (size_t i = 0; i < args.size(); i++) {
2628 args[i] = this->coerce(std::move(args[i]), base);
2629 if (!args[i]) {
2630 return nullptr;
2631 }
2632 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002633 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002634 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002635 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002636 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002637 fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002638 return nullptr;
2639 }
2640}
2641
Ethan Nicholasfc994162019-06-06 10:04:27 -04002642std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
2643 SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
2644 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -07002645 if (!base) {
2646 return nullptr;
2647 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002648 switch (expression.getToken().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002649 case Token::Kind::TK_PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05002650 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
2651 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002652 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002653 "'+' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002654 return nullptr;
2655 }
2656 return base;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002657 case Token::Kind::TK_MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07002658 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002659 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002660 -((IntLiteral&) *base).fValue));
2661 }
2662 if (base->fKind == Expression::kFloatLiteral_Kind) {
2663 double value = -((FloatLiteral&) *base).fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002664 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002665 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07002666 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05002667 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
2668 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002669 "'-' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholase1f55022019-02-05 17:17:40 -05002670 return nullptr;
2671 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002672 return std::unique_ptr<Expression>(new PrefixExpression(Token::Kind::TK_MINUS,
2673 std::move(base)));
2674 case Token::Kind::TK_PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07002675 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002676 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002677 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002678 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002679 return nullptr;
2680 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002681 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002682 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002683 case Token::Kind::TK_MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07002684 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002685 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002686 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002687 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002688 return nullptr;
2689 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002690 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002691 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002692 case Token::Kind::TK_LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07002693 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002694 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002695 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002696 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002697 return nullptr;
2698 }
ethannicholas08a92112016-11-09 13:26:45 -08002699 if (base->fKind == Expression::kBoolLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002700 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08002701 !((BoolLiteral&) *base).fValue));
2702 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002703 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002704 case Token::Kind::TK_BITWISENOT:
Brian Osman73fb39c2019-09-24 16:22:55 -04002705 if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002706 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002707 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002708 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholas5961bc92016-10-12 06:39:56 -07002709 return nullptr;
2710 }
2711 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002712 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07002713 ABORT("unsupported prefix operator\n");
2714 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002715 return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
ethannicholasb3058bd2016-07-01 08:22:01 -07002716 std::move(base)));
2717}
2718
2719std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002720 const ASTNode& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002721 if (base->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002722 if (index.fKind == ASTNode::Kind::kInt) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002723 const Type& oldType = ((TypeReference&) *base).fValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002724 SKSL_INT size = index.getInt();
John Stiles3ae071e2020-08-05 15:29:29 -04002725 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(
2726 std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]",
2727 Type::kArray_Kind, oldType, size));
2728 return std::make_unique<TypeReference>(fContext, base->fOffset, *newType);
Ethan Nicholas50afc172017-02-16 14:49:57 -05002729
2730 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002731 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05002732 return nullptr;
2733 }
2734 }
ethannicholas5961bc92016-10-12 06:39:56 -07002735 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
2736 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002737 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002738 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002739 return nullptr;
2740 }
2741 std::unique_ptr<Expression> converted = this->convertExpression(index);
2742 if (!converted) {
2743 return nullptr;
2744 }
ethannicholas5961bc92016-10-12 06:39:56 -07002745 if (converted->fType != *fContext.fUInt_Type) {
2746 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
2747 if (!converted) {
2748 return nullptr;
2749 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002750 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05002751 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07002752 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002753}
2754
2755std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002756 StringFragment field) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04002757 if (base->fKind == Expression::kExternalValue_Kind) {
2758 ExternalValue& ev = *((ExternalValueReference&) *base).fValue;
2759 ExternalValue* result = ev.getChild(String(field).c_str());
2760 if (!result) {
2761 fErrors.error(base->fOffset, "external value does not have a child named '" + field +
2762 "'");
2763 return nullptr;
2764 }
2765 return std::unique_ptr<Expression>(new ExternalValueReference(base->fOffset, result));
2766 }
ethannicholasd598f792016-07-25 10:08:54 -07002767 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07002768 for (size_t i = 0; i < fields.size(); i++) {
2769 if (fields[i].fName == field) {
2770 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
2771 }
2772 }
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002773 fErrors.error(base->fOffset, "type '" + base->fType.displayName() + "' does not have a "
Brian Osmanb08cc022020-04-02 11:38:40 -04002774 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07002775 return nullptr;
2776}
2777
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002778// counts the number of chunks of contiguous 'x's in a swizzle, e.g. xxx1 has one and x0xx has two
2779int count_contiguous_swizzle_chunks(const std::vector<int>& components) {
2780 int chunkCount = 0;
2781 for (size_t i = 0; i < components.size(); ++i) {
2782 SkASSERT(components[i] <= 0);
2783 if (components[i] == 0) {
2784 ++chunkCount;
2785 while (i + 1 < components.size() && components[i + 1] == 0) {
2786 ++i;
2787 }
2788 }
2789 }
2790 return chunkCount;
2791}
2792
ethannicholasb3058bd2016-07-01 08:22:01 -07002793std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002794 StringFragment fields) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002795 if (base->fType.kind() != Type::kVector_Kind && !base->fType.isNumber()) {
2796 fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() +
2797 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002798 return nullptr;
2799 }
2800 std::vector<int> swizzleComponents;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002801 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05002802 switch (fields[i]) {
Ethan Nicholasac285b12019-02-12 16:05:18 -05002803 case '0':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002804 swizzleComponents.push_back(SKSL_SWIZZLE_0);
2805 break;
2806 case '1':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002807 swizzleComponents.push_back(SKSL_SWIZZLE_1);
2808 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002809 case 'x':
2810 case 'r':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002811 case 's':
Ethan Nicholase455f652019-09-13 12:52:55 -04002812 case 'L':
ethannicholasb3058bd2016-07-01 08:22:01 -07002813 swizzleComponents.push_back(0);
2814 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002815 case 'y':
2816 case 'g':
ethannicholasb3058bd2016-07-01 08:22:01 -07002817 case 't':
Ethan Nicholase455f652019-09-13 12:52:55 -04002818 case 'T':
ethannicholasd598f792016-07-25 10:08:54 -07002819 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002820 swizzleComponents.push_back(1);
2821 break;
2822 }
John Stiles30212b72020-06-11 17:55:07 -04002823 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002824 case 'z':
2825 case 'b':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002826 case 'p':
Ethan Nicholase455f652019-09-13 12:52:55 -04002827 case 'R':
ethannicholasd598f792016-07-25 10:08:54 -07002828 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002829 swizzleComponents.push_back(2);
2830 break;
2831 }
John Stiles30212b72020-06-11 17:55:07 -04002832 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002833 case 'w':
2834 case 'a':
ethannicholasb3058bd2016-07-01 08:22:01 -07002835 case 'q':
Ethan Nicholase455f652019-09-13 12:52:55 -04002836 case 'B':
ethannicholasd598f792016-07-25 10:08:54 -07002837 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002838 swizzleComponents.push_back(3);
2839 break;
2840 }
John Stiles30212b72020-06-11 17:55:07 -04002841 [[fallthrough]];
ethannicholasb3058bd2016-07-01 08:22:01 -07002842 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002843 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
2844 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07002845 return nullptr;
2846 }
2847 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002848 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07002849 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002850 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002851 return nullptr;
2852 }
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002853 if (base->fType.isNumber()) {
2854 // Swizzling a single scalar. Something like foo.x0x1 is equivalent to float4(foo, 0, foo,
2855 // 1)
2856 int offset = base->fOffset;
2857 std::unique_ptr<Expression> expr;
2858 switch (base->fKind) {
2859 case Expression::kVariableReference_Kind:
2860 case Expression::kFloatLiteral_Kind:
2861 case Expression::kIntLiteral_Kind:
2862 // the value being swizzled is just a constant or variable reference, so we can
2863 // safely re-use copies of it without reevaluation concerns
2864 expr = std::move(base);
2865 break;
2866 default:
2867 // It's a value we can't safely re-use multiple times. If it's all in one contiguous
2868 // chunk it's easy (e.g. foo.xxx0 can be turned into half4(half3(x), 0)), but
2869 // for multiple discontiguous chunks we'll need to copy it into a temporary value.
2870 int chunkCount = count_contiguous_swizzle_chunks(swizzleComponents);
2871 if (chunkCount <= 1) {
2872 // no copying needed, so we can just use the value directly
2873 expr = std::move(base);
2874 } else {
2875 // store the value in a temporary variable so we can re-use it
2876 int varIndex = fInlineVarCounter++;
2877 auto name = std::make_unique<String>();
2878 name->appendf("_tmpSwizzle%d", varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002879 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
2880 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
2881 std::make_unique<Variable>(offset,
2882 Modifiers(),
2883 namePtr->c_str(),
2884 base->fType,
2885 Variable::kLocal_Storage,
2886 base.get()));
Ethan Nicholasd2dc2062020-08-03 16:05:04 -04002887 expr = std::make_unique<VariableReference>(offset, *var);
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002888 std::vector<std::unique_ptr<VarDeclaration>> variables;
2889 variables.emplace_back(new VarDeclaration(var, {}, std::move(base)));
2890 fExtraStatements.emplace_back(new VarDeclarationsStatement(
2891 std::make_unique<VarDeclarations>(offset, &expr->fType,
2892 std::move(variables))));
2893 }
2894 }
2895 std::vector<std::unique_ptr<Expression>> args;
2896 for (size_t i = 0; i < swizzleComponents.size(); ++i) {
2897 switch (swizzleComponents[i]) {
2898 case 0: {
2899 args.push_back(expr->clone());
2900 int count = 1;
2901 while (i + 1 < swizzleComponents.size() && swizzleComponents[i + 1] == 0) {
2902 ++i;
2903 ++count;
2904 }
2905 if (count > 1) {
2906 std::vector<std::unique_ptr<Expression>> constructorArgs;
2907 constructorArgs.push_back(std::move(args.back()));
2908 args.pop_back();
2909 args.emplace_back(new Constructor(offset, expr->fType.toCompound(fContext,
2910 count,
2911 1),
2912 std::move(constructorArgs)));
2913 }
2914 break;
2915 }
2916 case SKSL_SWIZZLE_0:
2917 args.emplace_back(new IntLiteral(fContext, offset, 0));
2918 break;
2919 case SKSL_SWIZZLE_1:
2920 args.emplace_back(new IntLiteral(fContext, offset, 1));
2921 break;
2922 }
2923 }
2924 return std::unique_ptr<Expression>(new Constructor(offset,
2925 expr->fType.toCompound(
2926 fContext,
2927 swizzleComponents.size(),
2928 1),
2929 std::move(args)));
2930 }
ethannicholasd598f792016-07-25 10:08:54 -07002931 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07002932}
2933
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002934std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05002935 auto found = fCapsMap.find(name);
2936 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002937 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002938 return nullptr;
2939 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002940 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002941 return std::unique_ptr<Expression>(new Setting(offset, fullName,
2942 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002943}
2944
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002945std::unique_ptr<Expression> IRGenerator::findEnumRef(
2946 int offset,
2947 const Type& type,
2948 StringFragment field,
2949 std::vector<std::unique_ptr<ProgramElement>>& elements) {
2950 for (const auto& e : elements) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002951 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
2952 std::shared_ptr<SymbolTable> old = fSymbolTable;
2953 fSymbolTable = ((Enum&) *e).fSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002954 std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset,
2955 ASTNode::Kind::kIdentifier,
2956 field));
2957 if (result) {
2958 SkASSERT(result->fKind == Expression::kVariableReference_Kind);
2959 const Variable& v = ((VariableReference&) *result).fVariable;
2960 SkASSERT(v.fInitialValue);
2961 SkASSERT(v.fInitialValue->fKind == Expression::kIntLiteral_Kind);
John Stilesfbd050b2020-08-03 13:21:46 -04002962 result = std::make_unique<IntLiteral>(
2963 offset, ((IntLiteral&)*v.fInitialValue).fValue, &type);
Ethan Nicholas9fdab9f2020-05-01 11:02:15 -04002964 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002965 fSymbolTable = old;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002966 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002967 }
2968 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002969 return nullptr;
2970}
2971
2972std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2973 StringFragment field) {
2974 std::unique_ptr<Expression> result = this->findEnumRef(offset, type, field, *fProgramElements);
2975 if (fInherited && !result) {
2976 result = this->findEnumRef(offset, type, field, *fInherited);
2977 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002978 if (!result) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002979 auto found = fIntrinsics->find(type.fName);
2980 if (found != fIntrinsics->end()) {
2981 SkASSERT(!found->second.second);
2982 found->second.second = true;
2983 fProgramElements->push_back(found->second.first->clone());
2984 return this->convertTypeField(offset, type, field);
2985 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002986 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2987 "'");
2988 }
2989 return result;
2990}
2991
Ethan Nicholasfc994162019-06-06 10:04:27 -04002992std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
2993 SkASSERT(index.fKind == ASTNode::Kind::kIndex);
2994 auto iter = index.begin();
2995 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07002996 if (!base) {
2997 return nullptr;
2998 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002999 if (iter != index.end()) {
3000 return this->convertIndex(std::move(base), *(iter++));
3001 } else if (base->fKind == Expression::kTypeReference_Kind) {
3002 const Type& oldType = ((TypeReference&) *base).fValue;
John Stiles3ae071e2020-08-05 15:29:29 -04003003 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
3004 oldType.name() + "[]", Type::kArray_Kind, oldType, /*columns=*/-1));
Ethan Nicholasfc994162019-06-06 10:04:27 -04003005 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
3006 *newType));
ethannicholasb3058bd2016-07-01 08:22:01 -07003007 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003008 fErrors.error(index.fOffset, "'[]' must follow a type name");
3009 return nullptr;
3010}
3011
3012std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
3013 SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
3014 auto iter = callNode.begin();
3015 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
3016 if (!base) {
3017 return nullptr;
3018 }
3019 std::vector<std::unique_ptr<Expression>> arguments;
3020 for (; iter != callNode.end(); ++iter) {
3021 std::unique_ptr<Expression> converted = this->convertExpression(*iter);
3022 if (!converted) {
3023 return nullptr;
3024 }
3025 arguments.push_back(std::move(converted));
3026 }
3027 return this->call(callNode.fOffset, std::move(base), std::move(arguments));
3028}
3029
3030std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
3031 std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
3032 if (!base) {
3033 return nullptr;
3034 }
3035 StringFragment field = fieldNode.getString();
3036 if (base->fType == *fContext.fSkCaps_Type) {
3037 return this->getCap(fieldNode.fOffset, field);
3038 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003039 if (base->fKind == Expression::kTypeReference_Kind) {
3040 return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
3041 field);
3042 }
3043 if (base->fKind == Expression::kExternalValue_Kind) {
3044 return this->convertField(std::move(base), field);
3045 }
3046 switch (base->fType.kind()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04003047 case Type::kOther_Kind:
3048 case Type::kStruct_Kind:
3049 return this->convertField(std::move(base), field);
3050 default:
Ethan Nicholas7b9da252020-08-03 13:43:50 -04003051 return this->convertSwizzle(std::move(base), field);
Ethan Nicholasfc994162019-06-06 10:04:27 -04003052 }
3053}
3054
3055std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
3056 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
3057 if (!base) {
3058 return nullptr;
3059 }
3060 if (!base->fType.isNumber()) {
3061 fErrors.error(expression.fOffset,
3062 "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003063 "' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04003064 return nullptr;
3065 }
3066 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
3067 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
3068 expression.getToken().fKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07003069}
3070
3071void IRGenerator::checkValid(const Expression& expr) {
3072 switch (expr.fKind) {
3073 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003074 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07003075 break;
3076 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003077 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07003078 break;
3079 default:
ethannicholasea4567c2016-10-17 11:24:37 -07003080 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003081 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07003082 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003083 }
3084}
3085
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003086bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
ethannicholasb3058bd2016-07-01 08:22:01 -07003087 int bits = 0;
3088 for (int idx : swizzle.fComponents) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003089 if (idx < 0) {
3090 fErrors.error(swizzle.fOffset, "cannot write to a swizzle mask containing a constant");
3091 return false;
3092 }
3093 SkASSERT(idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07003094 int bit = 1 << idx;
3095 if (bits & bit) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003096 fErrors.error(swizzle.fOffset,
3097 "cannot write to the same swizzle field more than once");
3098 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003099 }
3100 bits |= bit;
3101 }
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003102 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07003103}
3104
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003105bool IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07003106 switch (expr.fKind) {
3107 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07003108 const Variable& var = ((VariableReference&) expr).fVariable;
Brian Osman3c358422020-03-23 10:44:12 -04003109 if (var.fModifiers.fFlags &
3110 (Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) {
3111 fErrors.error(expr.fOffset, "cannot modify immutable variable '" + var.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003112 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003113 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04003114 ((VariableReference&) expr).setRefKind(kind);
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003115 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07003116 }
3117 case Expression::kFieldAccess_Kind:
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003118 return this->setRefKind(*((FieldAccess&) expr).fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003119 case Expression::kSwizzle_Kind: {
3120 const Swizzle& swizzle = (Swizzle&) expr;
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003121 return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003122 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003123 case Expression::kIndex_Kind:
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003124 return this->setRefKind(*((IndexExpression&) expr).fBase, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05003125 case Expression::kTernary_Kind: {
3126 TernaryExpression& t = (TernaryExpression&) expr;
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003127 return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05003128 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04003129 case Expression::kExternalValue_Kind: {
3130 const ExternalValue& v = *((ExternalValueReference&) expr).fValue;
3131 if (!v.canWrite()) {
3132 fErrors.error(expr.fOffset,
3133 "cannot modify immutable external value '" + v.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003134 return false;
Ethan Nicholas91164d12019-05-15 15:29:54 -04003135 }
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003136 return true;
Ethan Nicholas91164d12019-05-15 15:29:54 -04003137 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003138 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003139 fErrors.error(expr.fOffset, "cannot assign to this expression");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003140 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003141 }
3142}
3143
Robert Phillipsfe8da172018-01-24 14:52:02 +00003144void IRGenerator::convertProgram(Program::Kind kind,
3145 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003146 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003147 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00003148 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003149 fProgramElements = out;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003150 Parser parser(text, length, *fSymbolTable, fErrors);
Ethan Nicholasfc994162019-06-06 10:04:27 -04003151 fFile = parser.file();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003152 if (fErrors.errorCount()) {
3153 return;
3154 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003155 this->pushSymbolTable(); // this is popped by Compiler upon completion
Ethan Nicholasfc994162019-06-06 10:04:27 -04003156 SkASSERT(fFile);
3157 for (const auto& decl : fFile->root()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003158 switch (decl.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04003159 case ASTNode::Kind::kVarDeclarations: {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003160 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04003161 decl,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003162 Variable::kGlobal_Storage);
3163 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003164 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003165 }
3166 break;
3167 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003168 case ASTNode::Kind::kEnum: {
3169 this->convertEnum(decl);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003170 break;
3171 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003172 case ASTNode::Kind::kFunction: {
3173 this->convertFunction(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003174 break;
3175 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003176 case ASTNode::Kind::kModifiers: {
3177 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003178 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003179 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003180 }
3181 break;
3182 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003183 case ASTNode::Kind::kInterfaceBlock: {
3184 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003185 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003186 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003187 }
3188 break;
3189 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003190 case ASTNode::Kind::kExtension: {
3191 std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
3192 decl.getString());
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003193 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003194 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003195 }
3196 break;
3197 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003198 case ASTNode::Kind::kSection: {
3199 std::unique_ptr<Section> s = this->convertSection(decl);
Ethan Nicholas762466e2017-06-29 10:03:38 -04003200 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003201 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04003202 }
3203 break;
3204 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003205 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003206#ifdef SK_DEBUG
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003207 ABORT("unsupported declaration: %s\n", decl.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003208#endif
3209 break;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003210 }
3211 }
3212}
3213
3214
John Stilesa6841be2020-08-06 14:11:56 -04003215} // namespace SkSL