blob: 7eb005643b5c933aba0ec68f82d42c2ee352e354 [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 Nicholas63d7ee32020-08-17 10:57:12 -0400380 int permitted = Modifiers::kConst_Flag;
381 if (storage == Variable::kGlobal_Storage) {
382 permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
383 Modifiers::kFlat_Flag | Modifiers::kVarying_Flag |
384 Modifiers::kNoPerspective_Flag | Modifiers::kPLS_Flag |
385 Modifiers::kPLSIn_Flag | Modifiers::kPLSOut_Flag |
386 Modifiers::kRestrict_Flag | Modifiers::kVolatile_Flag |
387 Modifiers::kReadOnly_Flag | Modifiers::kWriteOnly_Flag |
388 Modifiers::kCoherent_Flag | Modifiers::kBuffer_Flag;
389 }
390 this->checkModifiers(decls.fOffset, modifiers, permitted);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400391 for (; iter != decls.end(); ++iter) {
392 const ASTNode& varDecl = *iter;
393 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
394 (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
395 varDecl.getVarData().fName != "sk_FragColor") {
396 fErrors.error(varDecl.fOffset,
Ethan Nicholas6c942712018-03-16 09:45:11 -0400397 "out location=0, index=0 is reserved for sk_FragColor");
398 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400399 const ASTNode::VarData& varData = varDecl.getVarData();
ethannicholasd598f792016-07-25 10:08:54 -0700400 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700401 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400402 auto iter = varDecl.begin();
Brian Osman82d49702019-12-30 13:44:01 -0500403 if (varData.fSizeCount > 0 && (modifiers.fFlags & Modifiers::kIn_Flag)) {
404 fErrors.error(varDecl.fOffset, "'in' variables may not have array type");
405 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400406 for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
407 const ASTNode& rawSize = *iter;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700408 if (rawSize) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400409 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700410 if (!size) {
411 return nullptr;
412 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700413 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500414 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700415 if (size->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -0400416 count = size->as<IntLiteral>().fValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700418 fErrors.error(size->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400419 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 }
421 name += "[" + to_string(count) + "]";
422 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400423 fErrors.error(size->fOffset, "array size must be specified");
424 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700425 }
John Stiles3ae071e2020-08-05 15:29:29 -0400426 type = fSymbolTable->takeOwnershipOfSymbol(
427 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700428 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700429 } else {
John Stiles3ae071e2020-08-05 15:29:29 -0400430 type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
431 type->name() + "[]", Type::kArray_Kind, *type, /*columns=*/-1));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700432 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700433 }
434 }
John Stilesfbd050b2020-08-03 13:21:46 -0400435 auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, *type,
436 storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000437 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400438 SkASSERT(!fRTAdjust);
439 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000440 fRTAdjust = var.get();
441 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700442 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400443 if (iter != varDecl.end()) {
444 value = this->convertExpression(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700445 if (!value) {
446 return nullptr;
447 }
ethannicholasd598f792016-07-25 10:08:54 -0700448 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500449 if (!value) {
450 return nullptr;
451 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400452 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500453 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700454 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400455 if (storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor" &&
456 (*fSymbolTable)[var->fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700457 // already defined, ignore
Ethan Nicholasfc994162019-06-06 10:04:27 -0400458 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[var->fName] &&
459 (*fSymbolTable)[var->fName]->fKind == Symbol::kVariable_Kind &&
460 ((Variable*) (*fSymbolTable)[var->fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700461 // already defined, just update the modifiers
Ethan Nicholasfc994162019-06-06 10:04:27 -0400462 Variable* old = (Variable*) (*fSymbolTable)[var->fName];
ethannicholasf789b382016-08-03 12:43:36 -0700463 old->fModifiers = var->fModifiers;
464 } else {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000465 variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
466 std::move(value)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400467 StringFragment name = var->fName;
468 fSymbolTable->add(name, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700469 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700470 }
John Stilesfbd050b2020-08-03 13:21:46 -0400471 return std::make_unique<VarDeclarations>(decls.fOffset, baseType, std::move(variables));
ethannicholasb3058bd2016-07-01 08:22:01 -0700472}
473
Ethan Nicholasfc994162019-06-06 10:04:27 -0400474std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
475 SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
476 Modifiers modifiers = m.getModifiers();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400477 if (modifiers.fLayout.fInvocations != -1) {
Ethan Nicholasf06576b2019-04-03 15:45:25 -0400478 if (fKind != Program::kGeometry_Kind) {
479 fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
480 return nullptr;
481 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400482 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600483 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400484 modifiers.fLayout.fInvocations = -1;
485 Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400486 SkASSERT(invocationId);
Ethan Nicholasd1d52562018-03-20 16:30:34 -0400487 invocationId->fModifiers.fFlags = 0;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400488 invocationId->fModifiers.fLayout.fBuiltin = -1;
489 if (modifiers.fLayout.description() == "") {
490 return nullptr;
491 }
492 }
493 }
494 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600495 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400496 modifiers.fLayout.fMaxVertices *= fInvocations;
497 }
John Stilesfbd050b2020-08-03 13:21:46 -0400498 return std::make_unique<ModifiersDeclaration>(modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700499}
500
Ethan Nicholasfc994162019-06-06 10:04:27 -0400501std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
502 SkASSERT(n.fKind == ASTNode::Kind::kIf);
503 auto iter = n.begin();
504 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -0700505 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700506 if (!test) {
507 return nullptr;
508 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400509 std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700510 if (!ifTrue) {
511 return nullptr;
512 }
513 std::unique_ptr<Statement> ifFalse;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400514 if (iter != n.end()) {
515 ifFalse = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700516 if (!ifFalse) {
517 return nullptr;
518 }
519 }
ethannicholas08a92112016-11-09 13:26:45 -0800520 if (test->fKind == Expression::kBoolLiteral_Kind) {
521 // static boolean value, fold down to a single branch
522 if (((BoolLiteral&) *test).fValue) {
523 return ifTrue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400524 } else if (ifFalse) {
ethannicholas08a92112016-11-09 13:26:45 -0800525 return ifFalse;
526 } else {
527 // False & no else clause. Not an error, so don't return null!
528 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400529 return std::unique_ptr<Statement>(new Block(n.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800530 fSymbolTable));
531 }
532 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400533 return std::unique_ptr<Statement>(new IfStatement(n.fOffset, n.getBool(), std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700534 std::move(ifTrue), std::move(ifFalse)));
535}
536
Ethan Nicholasfc994162019-06-06 10:04:27 -0400537std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
538 SkASSERT(f.fKind == ASTNode::Kind::kFor);
ethannicholas22f939e2016-10-13 13:25:34 -0700539 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700540 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700541 std::unique_ptr<Statement> initializer;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400542 auto iter = f.begin();
543 if (*iter) {
544 initializer = this->convertStatement(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700545 if (!initializer) {
546 return nullptr;
547 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700548 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400549 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700550 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400551 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400552 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400553 test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
ethannicholas22f939e2016-10-13 13:25:34 -0700554 if (!test) {
555 return nullptr;
556 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400557
ethannicholasb3058bd2016-07-01 08:22:01 -0700558 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400559 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700560 std::unique_ptr<Expression> next;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400561 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400562 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400563 next = this->convertExpression(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700564 if (!next) {
565 return nullptr;
566 }
567 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700568 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400569 ++iter;
570 std::unique_ptr<Statement> statement = this->convertStatement(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700571 if (!statement) {
572 return nullptr;
573 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400574 return std::make_unique<ForStatement>(f.fOffset, std::move(initializer), std::move(test),
575 std::move(next), std::move(statement), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700576}
577
Ethan Nicholasfc994162019-06-06 10:04:27 -0400578std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
579 SkASSERT(w.fKind == ASTNode::Kind::kWhile);
ethannicholas22f939e2016-10-13 13:25:34 -0700580 AutoLoopLevel level(this);
John Stilesd1c4dac2020-08-11 18:50:50 -0400581 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400582 auto iter = w.begin();
John Stilesd1c4dac2020-08-11 18:50:50 -0400583 {
584 AutoDisableInline disableInline(this);
585 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
586 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700587 if (!test) {
588 return nullptr;
589 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400590 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700591 if (!statement) {
592 return nullptr;
593 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400594 return std::make_unique<WhileStatement>(w.fOffset, std::move(test), std::move(statement));
ethannicholasb3058bd2016-07-01 08:22:01 -0700595}
596
Ethan Nicholasfc994162019-06-06 10:04:27 -0400597std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
598 SkASSERT(d.fKind == ASTNode::Kind::kDo);
ethannicholas22f939e2016-10-13 13:25:34 -0700599 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400600 auto iter = d.begin();
601 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
602 if (!statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 return nullptr;
604 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400605 std::unique_ptr<Expression> test;
606 {
607 AutoDisableInline disableInline(this);
608 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
609 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400610 if (!test) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700611 return nullptr;
612 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400613 return std::make_unique<DoStatement>(d.fOffset, std::move(statement), std::move(test));
ethannicholasb3058bd2016-07-01 08:22:01 -0700614}
615
Ethan Nicholasfc994162019-06-06 10:04:27 -0400616std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
617 SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500618 AutoSwitchLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400619 auto iter = s.begin();
620 std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500621 if (!value) {
622 return nullptr;
623 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500624 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500625 value = this->coerce(std::move(value), *fContext.fInt_Type);
626 if (!value) {
627 return nullptr;
628 }
629 }
630 AutoSymbolTable table(this);
631 std::unordered_set<int> caseValues;
632 std::vector<std::unique_ptr<SwitchCase>> cases;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400633 for (; iter != s.end(); ++iter) {
634 const ASTNode& c = *iter;
635 SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500636 std::unique_ptr<Expression> caseValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400637 auto childIter = c.begin();
638 if (*childIter) {
639 caseValue = this->convertExpression(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500640 if (!caseValue) {
641 return nullptr;
642 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500643 caseValue = this->coerce(std::move(caseValue), value->fType);
644 if (!caseValue) {
645 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500646 }
Brian Osman3e3db6c2020-08-14 09:42:12 -0400647 int64_t v = 0;
648 if (!this->getConstantInt(*caseValue, &v)) {
649 fErrors.error(caseValue->fOffset, "case value must be a constant integer");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500650 return nullptr;
651 }
Ethan Nicholasaf197692017-02-27 13:26:45 -0500652 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700653 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500654 }
655 caseValues.insert(v);
656 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400657 ++childIter;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500658 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400659 for (; childIter != c.end(); ++childIter) {
660 std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500661 if (!converted) {
662 return nullptr;
663 }
664 statements.push_back(std::move(converted));
665 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400666 cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500667 std::move(statements)));
668 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400669 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400670 std::move(value), std::move(cases),
671 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500672}
673
Ethan Nicholasfc994162019-06-06 10:04:27 -0400674std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
675 std::unique_ptr<Expression> e = this->convertExpression(s);
ethannicholasb3058bd2016-07-01 08:22:01 -0700676 if (!e) {
677 return nullptr;
678 }
679 this->checkValid(*e);
680 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
681}
682
Ethan Nicholasfc994162019-06-06 10:04:27 -0400683std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
684 SkASSERT(r.fKind == ASTNode::Kind::kReturn);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400685 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000686 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400687 // 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 +0000688 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400689 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400690 if (r.begin() != r.end()) {
691 std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -0700692 if (!result) {
693 return nullptr;
694 }
ethannicholasd598f792016-07-25 10:08:54 -0700695 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700696 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700697 } else {
698 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
699 if (!result) {
700 return nullptr;
701 }
702 }
703 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
704 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700705 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700706 fErrors.error(r.fOffset, "expected function to return '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500707 fCurrentFunction->fReturnType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700708 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700709 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700710 }
711}
712
Ethan Nicholasfc994162019-06-06 10:04:27 -0400713std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
714 SkASSERT(b.fKind == ASTNode::Kind::kBreak);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500715 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700716 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700717 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700718 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
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::convertContinue(const ASTNode& c) {
724 SkASSERT(c.fKind == ASTNode::Kind::kContinue);
ethannicholas22f939e2016-10-13 13:25:34 -0700725 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700726 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700727 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700728 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700729 return nullptr;
730 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700731}
732
Ethan Nicholasfc994162019-06-06 10:04:27 -0400733std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
734 SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700735 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700736}
737
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500738std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400739 Layout invokeLayout;
740 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700741 FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400742 invokeModifiers,
743 "_invoke",
744 std::vector<const Variable*>(),
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400745 *fContext.fVoid_Type,
746 false);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500747 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
748 new FunctionDefinition(-1, *invokeDecl, std::move(main))));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400749 fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
750
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000751 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400752 Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400753 SkASSERT(loopIdx);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700754 std::unique_ptr<Expression> test(new BinaryExpression(-1,
755 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400756 Token::Kind::TK_LT,
John Stilesfbd050b2020-08-03 13:21:46 -0400757 std::make_unique<IntLiteral>(fContext, -1, fInvocations),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400758 *fContext.fBool_Type));
759 std::unique_ptr<Expression> next(new PostfixExpression(
760 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700761 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400762 *loopIdx,
763 VariableReference::kReadWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400764 Token::Kind::TK_PLUSPLUS));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400765 ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400766 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400767 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400768
769 std::vector<std::unique_ptr<Statement>> loopBody;
770 std::vector<std::unique_ptr<Expression>> invokeArgs;
771 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700772 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400773 *invokeDecl,
774 std::vector<std::unique_ptr<Expression>>()))));
775 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700776 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400777 std::move(endPrimitive),
778 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700779 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400780 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx,
781 VariableReference::kWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400782 Token::Kind::TK_EQ,
John Stilesfbd050b2020-08-03 13:21:46 -0400783 std::make_unique<IntLiteral>(fContext, -1, 0),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400784 *fContext.fInt_Type));
785 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
786 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700787 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400788 std::move(initializer),
789 std::move(test),
790 std::move(next),
John Stilesfbd050b2020-08-03 13:21:46 -0400791 std::make_unique<Block>(-1, std::move(loopBody)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400792 fSymbolTable));
793 std::vector<std::unique_ptr<Statement>> children;
794 children.push_back(std::move(loop));
John Stilesfbd050b2020-08-03 13:21:46 -0400795 return std::make_unique<Block>(-1, std::move(children));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400796}
797
Robert Phillipsfe8da172018-01-24 14:52:02 +0000798std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400799 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000800 // 0,
801 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400802 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000803 #define REF(var) std::unique_ptr<Expression>(\
804 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400805 #define WREF(var) std::unique_ptr<Expression>(\
806 new VariableReference(-1, *var, VariableReference::kWrite_RefKind))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000807 #define FIELD(var, idx) std::unique_ptr<Expression>(\
808 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400809 #define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
Robert Phillipsfe8da172018-01-24 14:52:02 +0000810 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
811 #define ADJUST (fRTAdjustInterfaceBlock ? \
812 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
813 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400814 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
815 { __VA_ARGS__ }))
816 #define OP(left, op, right) std::unique_ptr<Expression>( \
817 new BinaryExpression(-1, left, op, right, \
818 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000819 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400820 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 0, 2)),
821 Token::Kind::TK_PLUS,
822 OP(SWIZZLE(POS, 3, 3), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000823 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
824 children.push_back(SWIZZLE(POS, 3));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400825 std::unique_ptr<Expression> result = OP(POS, Token::Kind::TK_EQ,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000826 std::unique_ptr<Expression>(new Constructor(-1,
827 *fContext.fFloat4_Type,
828 std::move(children))));
829 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
830}
831
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400832template<typename T>
833class AutoClear {
834public:
835 AutoClear(T* container)
836 : fContainer(container) {
837 SkASSERT(container->empty());
838 }
839
840 ~AutoClear() {
841 fContainer->clear();
842 }
843
844private:
845 T* fContainer;
846};
847
John Stilesb8e010c2020-08-11 18:05:39 -0400848template <typename T> AutoClear(T* c) -> AutoClear<T>;
849
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400850void IRGenerator::checkModifiers(int offset, const Modifiers& modifiers, int permitted) {
851 int flags = modifiers.fFlags;
852 #define CHECK(flag, name) \
853 if (!flags) return; \
854 if (flags & flag) { \
855 if (!(permitted & flag)) { \
856 fErrors.error(offset, "'" name "' is not permitted here"); \
857 } \
858 flags &= ~flag; \
859 }
860 CHECK(Modifiers::kConst_Flag, "const")
861 CHECK(Modifiers::kIn_Flag, "in")
862 CHECK(Modifiers::kOut_Flag, "out")
863 CHECK(Modifiers::kUniform_Flag, "uniform")
864 CHECK(Modifiers::kFlat_Flag, "flat")
865 CHECK(Modifiers::kNoPerspective_Flag, "noperspective")
866 CHECK(Modifiers::kReadOnly_Flag, "readonly")
867 CHECK(Modifiers::kWriteOnly_Flag, "writeonly")
868 CHECK(Modifiers::kCoherent_Flag, "coherent")
869 CHECK(Modifiers::kVolatile_Flag, "volatile")
870 CHECK(Modifiers::kRestrict_Flag, "restrict")
871 CHECK(Modifiers::kBuffer_Flag, "buffer")
872 CHECK(Modifiers::kHasSideEffects_Flag, "sk_has_side_effects")
873 CHECK(Modifiers::kPLS_Flag, "__pixel_localEXT")
874 CHECK(Modifiers::kPLSIn_Flag, "__pixel_local_inEXT")
875 CHECK(Modifiers::kPLSOut_Flag, "__pixel_local_outEXT")
876 CHECK(Modifiers::kVarying_Flag, "varying")
877 SkASSERT(flags == 0);
878}
879
Ethan Nicholasfc994162019-06-06 10:04:27 -0400880void IRGenerator::convertFunction(const ASTNode& f) {
John Stilesb8e010c2020-08-11 18:05:39 -0400881 AutoClear clear(&fReferencedIntrinsics);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400882 auto iter = f.begin();
883 const Type* returnType = this->convertType(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700884 if (!returnType) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400885 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700886 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400887 auto type_is_allowed = [&](const Type* t) {
888#if defined(SKSL_STANDALONE)
889 return true;
890#else
891 GrSLType unusedSLType;
892 return fKind != Program::kPipelineStage_Kind ||
893 type_to_grsltype(fContext, *t, &unusedSLType);
894#endif
895 };
896 if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type ||
897 !type_is_allowed(returnType)) {
Brian Osman82329002020-07-21 09:39:27 -0400898 fErrors.error(f.fOffset,
899 "functions may not return type '" + returnType->displayName() + "'");
900 return;
901 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400902 const ASTNode::FunctionData& fd = f.getFunctionData();
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400903 this->checkModifiers(f.fOffset, fd.fModifiers, Modifiers::kHasSideEffects_Flag);
ethannicholasd598f792016-07-25 10:08:54 -0700904 std::vector<const Variable*> parameters;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400905 for (size_t i = 0; i < fd.fParameterCount; ++i) {
906 const ASTNode& param = *(iter++);
907 SkASSERT(param.fKind == ASTNode::Kind::kParameter);
908 ASTNode::ParameterData pd = param.getParameterData();
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400909 this->checkModifiers(param.fOffset, pd.fModifiers, Modifiers::kIn_Flag |
910 Modifiers::kOut_Flag);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400911 auto paramIter = param.begin();
912 const Type* type = this->convertType(*(paramIter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700913 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400914 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700915 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400916 for (int j = (int) pd.fSizeCount; j >= 1; j--) {
917 int size = (param.begin() + j)->getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400918 String name = type->name() + "[" + to_string(size) + "]";
John Stiles3ae071e2020-08-05 15:29:29 -0400919 type = fSymbolTable->takeOwnershipOfSymbol(
920 std::make_unique<Type>(std::move(name), Type::kArray_Kind, *type, size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700921 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400922 // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
923 if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
924 !type_is_allowed(type)) {
925 fErrors.error(param.fOffset,
926 "parameters of type '" + type->displayName() + "' not allowed");
927 return;
928 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400929 StringFragment name = pd.fName;
John Stiles3ae071e2020-08-05 15:29:29 -0400930 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
931 param.fOffset, pd.fModifiers, name, *type, Variable::kParameter_Storage));
ethannicholasd598f792016-07-25 10:08:54 -0700932 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700933 }
934
Ethan Nicholasfc994162019-06-06 10:04:27 -0400935 if (fd.fName == "main") {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400936 switch (fKind) {
937 case Program::kPipelineStage_Kind: {
938 bool valid;
939 switch (parameters.size()) {
Brian Osman7353dc52020-02-07 13:37:12 -0500940 case 2:
941 valid = parameters[0]->fType == *fContext.fFloat2_Type &&
Ethan Nicholas0d997662019-04-08 09:46:01 -0400942 parameters[0]->fModifiers.fFlags == 0 &&
Brian Osman7353dc52020-02-07 13:37:12 -0500943 parameters[1]->fType == *fContext.fHalf4_Type &&
944 parameters[1]->fModifiers.fFlags == (Modifiers::kIn_Flag |
Ethan Nicholas0d997662019-04-08 09:46:01 -0400945 Modifiers::kOut_Flag);
946 break;
947 case 1:
948 valid = parameters[0]->fType == *fContext.fHalf4_Type &&
949 parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
950 Modifiers::kOut_Flag);
951 break;
952 default:
953 valid = false;
954 }
955 if (!valid) {
Brian Osman7353dc52020-02-07 13:37:12 -0500956 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(float2, "
957 "inout half4) or main(inout half4)");
Ethan Nicholas0d997662019-04-08 09:46:01 -0400958 return;
959 }
960 break;
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500961 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -0400962 case Program::kFragmentProcessor_Kind: {
963 bool valid = parameters.size() <= 1;
964 if (parameters.size() == 1) {
965 valid = parameters[0]->fType == *fContext.fFloat2_Type &&
966 parameters[0]->fModifiers.fFlags == 0;
967 }
968
969 if (!valid) {
970 fErrors.error(f.fOffset, ".fp 'main' must be declared main() or main(float2)");
971 return;
972 }
973 break;
974 }
Ethan Nicholas746035a2019-04-23 13:31:09 -0400975 case Program::kGeneric_Kind:
Ethan Nicholas0d997662019-04-08 09:46:01 -0400976 break;
Ethan Nicholas0d997662019-04-08 09:46:01 -0400977 default:
978 if (parameters.size()) {
979 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
980 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400981 }
982 }
983
ethannicholasb3058bd2016-07-01 08:22:01 -0700984 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700985 const FunctionDeclaration* decl = nullptr;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400986 auto entry = (*fSymbolTable)[fd.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700987 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700988 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700989 switch (entry->fKind) {
990 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700991 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700992 break;
993 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700994 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700995 break;
996 default:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400997 fErrors.error(f.fOffset, "symbol '" + fd.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400998 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700999 }
1000 for (const auto& other : functions) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001001 SkASSERT(other->fName == fd.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -07001002 if (parameters.size() == other->fParameters.size()) {
1003 bool match = true;
1004 for (size_t i = 0; i < parameters.size(); i++) {
1005 if (parameters[i]->fType != other->fParameters[i]->fType) {
1006 match = false;
1007 break;
1008 }
1009 }
1010 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -07001011 if (*returnType != other->fReturnType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001012 FunctionDeclaration newDecl(f.fOffset, fd.fModifiers, fd.fName, parameters,
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001013 *returnType, fIsBuiltinCode);
1014 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
1015 "' and '" + other->description() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001016 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001017 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001018 }
1019 decl = other;
1020 for (size_t i = 0; i < parameters.size(); i++) {
1021 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001022 fErrors.error(f.fOffset, "modifiers on parameter " +
1023 to_string((uint64_t) i + 1) +
1024 " differ between declaration and "
1025 "definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001026 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001027 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001028 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001029 if (other->fDefinition && !other->fBuiltin) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001030 fErrors.error(f.fOffset, "duplicate definition of " +
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001031 other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -07001032 }
1033 break;
1034 }
1035 }
1036 }
1037 }
1038 if (!decl) {
1039 // couldn't find an existing declaration
John Stiles311dd9d2020-08-13 17:09:29 -04001040 decl = fSymbolTable->add(fd.fName,
1041 std::make_unique<FunctionDeclaration>(f.fOffset,
1042 fd.fModifiers,
1043 fd.fName,
1044 parameters,
1045 *returnType,
1046 fIsBuiltinCode));
ethannicholasb3058bd2016-07-01 08:22:01 -07001047 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001048 if (iter != f.end()) {
1049 // compile body
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001050 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -07001051 fCurrentFunction = decl;
ethannicholasd598f792016-07-25 10:08:54 -07001052 std::shared_ptr<SymbolTable> old = fSymbolTable;
1053 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001054 if (fd.fName == "main" && fKind == Program::kPipelineStage_Kind) {
Brian Osman7353dc52020-02-07 13:37:12 -05001055 if (parameters.size() == 2) {
1056 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1057 parameters[1]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
Ethan Nicholasa70693b2019-03-04 13:07:36 -05001058 } else {
1059 SkASSERT(parameters.size() == 1);
1060 parameters[0]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
1061 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -04001062 } else if (fd.fName == "main" && fKind == Program::kFragmentProcessor_Kind) {
1063 if (parameters.size() == 1) {
1064 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1065 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001066 }
ethannicholasd598f792016-07-25 10:08:54 -07001067 for (size_t i = 0; i < parameters.size(); i++) {
1068 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -07001069 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001070 bool needInvocationIDWorkaround = fInvocations != -1 && fd.fName == "main" &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -06001071 fSettings->fCaps &&
1072 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001073 std::unique_ptr<Block> body = this->convertBlock(*iter);
ethannicholasd598f792016-07-25 10:08:54 -07001074 fCurrentFunction = nullptr;
1075 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001076 return;
1077 }
1078 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001079 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -07001080 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001081 // conservatively assume all user-defined functions have side effects
1082 ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001083 if (Program::kVertex_Kind == fKind && fd.fName == "main" && fRTAdjust) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00001084 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
1085 }
John Stilesb8e010c2020-08-11 18:05:39 -04001086 auto result = std::make_unique<FunctionDefinition>(f.fOffset, *decl, std::move(body),
1087 std::move(fReferencedIntrinsics));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001088 decl->fDefinition = result.get();
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001089 result->fSource = &f;
1090 fProgramElements->push_back(std::move(result));
ethannicholasb3058bd2016-07-01 08:22:01 -07001091 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001092}
1093
Ethan Nicholasfc994162019-06-06 10:04:27 -04001094std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
1095 SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
1096 ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
ethannicholasb3058bd2016-07-01 08:22:01 -07001097 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001098 this->pushSymbolTable();
1099 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001100 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001101 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +00001102 bool foundRTAdjust = false;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001103 auto iter = intf.begin();
1104 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
ethannicholas14fe8cc2016-09-07 13:37:16 -07001105 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04001106 *(iter++),
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001107 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -07001108 if (!decl) {
1109 return nullptr;
1110 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001111 for (const auto& stmt : decl->fVars) {
1112 VarDeclaration& vd = (VarDeclaration&) *stmt;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001113 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001114 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001115 "only the last entry in an interface block may be a runtime-sized "
1116 "array");
1117 }
Robert Phillipsfe8da172018-01-24 14:52:02 +00001118 if (vd.fVar == fRTAdjust) {
1119 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001120 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +00001121 fRTAdjustFieldIndex = fields.size();
1122 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001123 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
1124 &vd.fVar->fType));
1125 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001126 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001127 "initializers are not permitted on interface block fields");
1128 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001129 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
1130 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001131 haveRuntimeArray = true;
1132 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001133 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001134 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001135 this->popSymbolTable();
John Stiles3ae071e2020-08-05 15:29:29 -04001136 const Type* type =
1137 old->takeOwnershipOfSymbol(std::make_unique<Type>(intf.fOffset, id.fTypeName, fields));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001138 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001139 for (size_t i = 0; i < id.fSizeCount; ++i) {
1140 const ASTNode& size = *(iter++);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001141 if (size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001142 std::unique_ptr<Expression> converted = this->convertExpression(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001143 if (!converted) {
1144 return nullptr;
1145 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001146 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001147 int64_t count;
1148 if (converted->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001149 count = converted->as<IntLiteral>().fValue;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001150 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001151 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -04001152 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001153 }
1154 name += "[" + to_string(count) + "]";
1155 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001156 fErrors.error(intf.fOffset, "array size must be specified");
1157 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001158 }
John Stiles3ae071e2020-08-05 15:29:29 -04001159 type = symbols->takeOwnershipOfSymbol(
1160 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001161 sizes.push_back(std::move(converted));
1162 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001163 fErrors.error(intf.fOffset, "array size must be specified");
1164 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001165 }
1166 }
John Stiles3ae071e2020-08-05 15:29:29 -04001167 const Variable* var = old->takeOwnershipOfSymbol(
1168 std::make_unique<Variable>(intf.fOffset,
1169 id.fModifiers,
1170 id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
1171 *type,
1172 Variable::kGlobal_Storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +00001173 if (foundRTAdjust) {
1174 fRTAdjustInterfaceBlock = var;
1175 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001176 if (id.fInstanceName.fLength) {
1177 old->addWithoutOwnership(id.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -07001178 } else {
1179 for (size_t i = 0; i < fields.size(); i++) {
John Stilesfbd050b2020-08-03 13:21:46 -04001180 old->add(fields[i].fName, std::make_unique<Field>(intf.fOffset, *var, (int)i));
ethannicholasb3058bd2016-07-01 08:22:01 -07001181 }
1182 }
John Stilesfbd050b2020-08-03 13:21:46 -04001183 return std::make_unique<InterfaceBlock>(intf.fOffset,
1184 var,
1185 id.fTypeName,
1186 id.fInstanceName,
1187 std::move(sizes),
1188 symbols);
ethannicholasb3058bd2016-07-01 08:22:01 -07001189}
1190
Brian Osman3e3db6c2020-08-14 09:42:12 -04001191bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001192 switch (value.fKind) {
1193 case Expression::kIntLiteral_Kind:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001194 *out = static_cast<const IntLiteral&>(value).fValue;
1195 return true;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001196 case Expression::kVariableReference_Kind: {
Brian Osman3e3db6c2020-08-14 09:42:12 -04001197 const Variable& var = static_cast<const VariableReference&>(value).fVariable;
1198 return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
1199 var.fInitialValue &&
1200 this->getConstantInt(*var.fInitialValue, out);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001201 }
1202 default:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001203 return false;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001204 }
1205}
1206
Ethan Nicholasfc994162019-06-06 10:04:27 -04001207void IRGenerator::convertEnum(const ASTNode& e) {
1208 SkASSERT(e.fKind == ASTNode::Kind::kEnum);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001209 int64_t currentValue = 0;
1210 Layout layout;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001211 ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
1212 ASTNode::TypeData(e.getString(), false, false));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001213 const Type* type = this->convertType(enumType);
1214 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Brian Osman3e3db6c2020-08-14 09:42:12 -04001215 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001216 for (auto iter = e.begin(); iter != e.end(); ++iter) {
1217 const ASTNode& child = *iter;
1218 SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001219 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001220 if (child.begin() != child.end()) {
1221 value = this->convertExpression(*child.begin());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001222 if (!value) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001223 return;
1224 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001225 if (!this->getConstantInt(*value, &currentValue)) {
1226 fErrors.error(value->fOffset, "enum value must be a constant integer");
1227 return;
1228 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001229 }
1230 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
1231 ++currentValue;
Brian Osman3e3db6c2020-08-14 09:42:12 -04001232 fSymbolTable->add(child.getString(),
1233 std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), *type,
1234 Variable::kGlobal_Storage, value.get()));
1235 fSymbolTable->takeOwnershipOfIRNode(std::move(value));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001236 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001237 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
1238 new Enum(e.fOffset, e.getString(), fSymbolTable, fIsBuiltinCode)));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001239}
1240
Ethan Nicholasfc994162019-06-06 10:04:27 -04001241const Type* IRGenerator::convertType(const ASTNode& type) {
1242 ASTNode::TypeData td = type.getTypeData();
1243 const Symbol* result = (*fSymbolTable)[td.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001244 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001245 if (td.fIsNullable) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001246 if (((Type&) *result) == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001247 if (type.begin() != type.end()) {
1248 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001249 "an array");
1250 }
John Stiles3ae071e2020-08-05 15:29:29 -04001251 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1252 String(result->fName) + "?", Type::kNullable_Kind, (const Type&)*result));
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001253 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001254 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001255 }
1256 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001257 for (const auto& size : type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001258 String name(result->fName);
1259 name += "[";
Ethan Nicholasfc994162019-06-06 10:04:27 -04001260 if (size) {
1261 name += to_string(size.getInt());
Ethan Nicholas50afc172017-02-16 14:49:57 -05001262 }
1263 name += "]";
John Stiles3ae071e2020-08-05 15:29:29 -04001264 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1265 name, Type::kArray_Kind, (const Type&)*result, size ? size.getInt() : 0));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001266 }
ethannicholasd598f792016-07-25 10:08:54 -07001267 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001268 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001269 fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001270 return nullptr;
1271}
1272
Ethan Nicholasfc994162019-06-06 10:04:27 -04001273std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001274 switch (expr.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001275 case ASTNode::Kind::kBinary:
1276 return this->convertBinaryExpression(expr);
1277 case ASTNode::Kind::kBool:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001278 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001279 expr.getBool()));
1280 case ASTNode::Kind::kCall:
1281 return this->convertCallExpression(expr);
1282 case ASTNode::Kind::kField:
1283 return this->convertFieldExpression(expr);
1284 case ASTNode::Kind::kFloat:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001285 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001286 expr.getFloat()));
1287 case ASTNode::Kind::kIdentifier:
1288 return this->convertIdentifier(expr);
1289 case ASTNode::Kind::kIndex:
1290 return this->convertIndexExpression(expr);
1291 case ASTNode::Kind::kInt:
1292 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
1293 expr.getInt()));
1294 case ASTNode::Kind::kNull:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001295 return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001296 case ASTNode::Kind::kPostfix:
1297 return this->convertPostfixExpression(expr);
1298 case ASTNode::Kind::kPrefix:
1299 return this->convertPrefixExpression(expr);
1300 case ASTNode::Kind::kTernary:
1301 return this->convertTernaryExpression(expr);
ethannicholasb3058bd2016-07-01 08:22:01 -07001302 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001303#ifdef SK_DEBUG
Ethan Nicholasfc994162019-06-06 10:04:27 -04001304 ABORT("unsupported expression: %s\n", expr.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001305#endif
1306 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001307 }
1308}
1309
Ethan Nicholasfc994162019-06-06 10:04:27 -04001310std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
1311 SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
1312 const Symbol* result = (*fSymbolTable)[identifier.getString()];
ethannicholasb3058bd2016-07-01 08:22:01 -07001313 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001314 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001315 return nullptr;
1316 }
1317 switch (result->fKind) {
1318 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001319 std::vector<const FunctionDeclaration*> f = {
1320 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -07001321 };
John Stilesfbd050b2020-08-03 13:21:46 -04001322 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001323 }
1324 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001325 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001326 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
ethannicholasb3058bd2016-07-01 08:22:01 -07001327 }
1328 case Symbol::kVariable_Kind: {
Ethan Nicholas38657112017-02-09 17:01:22 -05001329 const Variable* var = (const Variable*) result;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001330 switch (var->fModifiers.fLayout.fBuiltin) {
1331 case SK_WIDTH_BUILTIN:
1332 fInputs.fRTWidth = true;
1333 break;
1334 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001335 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001336 break;
1337#ifndef SKSL_STANDALONE
1338 case SK_FRAGCOORD_BUILTIN:
Brian Osman9f313b62019-10-02 12:03:11 -04001339 fInputs.fFlipY = true;
1340 if (fSettings->fFlipY &&
1341 (!fSettings->fCaps ||
1342 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1343 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001344 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001345#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001346 }
Ethan Nicholas33c59ed2019-08-13 10:21:38 -04001347 if (fKind == Program::kFragmentProcessor_Kind &&
1348 (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
1349 !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
1350 !var->fModifiers.fLayout.fKey &&
1351 var->fModifiers.fLayout.fBuiltin == -1 &&
1352 var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
1353 var->fType.kind() != Type::kSampler_Kind) {
1354 bool valid = false;
1355 for (const auto& decl : fFile->root()) {
1356 if (decl.fKind == ASTNode::Kind::kSection) {
1357 ASTNode::SectionData section = decl.getSectionData();
1358 if (section.fName == "setData") {
1359 valid = true;
1360 break;
1361 }
1362 }
1363 }
1364 if (!valid) {
1365 fErrors.error(identifier.fOffset, "'in' variable must be either 'uniform' or "
1366 "'layout(key)', or there must be a custom "
1367 "@setData function");
1368 }
1369 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001370 // default to kRead_RefKind; this will be corrected later if the variable is written to
John Stilesfbd050b2020-08-03 13:21:46 -04001371 return std::make_unique<VariableReference>(identifier.fOffset,
1372 *var,
1373 VariableReference::kRead_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001374 }
1375 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001376 const Field* field = (const Field*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001377 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001378 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001379 return std::unique_ptr<Expression>(new FieldAccess(
1380 std::unique_ptr<Expression>(base),
1381 field->fFieldIndex,
1382 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001383 }
1384 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001385 const Type* t = (const Type*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001386 return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001387 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001388 case Symbol::kExternal_Kind: {
John Stiles534d7992020-08-18 00:06:01 -04001389 const ExternalValue* r = (const ExternalValue*) result;
John Stilesfbd050b2020-08-03 13:21:46 -04001390 return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
Ethan Nicholas91164d12019-05-15 15:29:54 -04001391 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001392 default:
1393 ABORT("unsupported symbol type %d\n", result->fKind);
1394 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001395}
1396
Ethan Nicholasfc994162019-06-06 10:04:27 -04001397std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
1398 ASTNode::SectionData section = s.getSectionData();
John Stilesfbd050b2020-08-03 13:21:46 -04001399 return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument,
1400 section.fText);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001401}
1402
1403
Ethan Nicholas11d53972016-11-28 11:23:23 -05001404std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001405 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001406 if (!expr) {
1407 return nullptr;
1408 }
ethannicholasd598f792016-07-25 10:08:54 -07001409 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001410 return expr;
1411 }
1412 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001413 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001414 return nullptr;
1415 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001416 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001417 fErrors.error(expr->fOffset, "expected '" + type.displayName() + "', but found '" +
1418 expr->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001419 return nullptr;
1420 }
ethannicholasd598f792016-07-25 10:08:54 -07001421 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001422 std::vector<std::unique_ptr<Expression>> args;
1423 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001424 std::unique_ptr<Expression> ctor;
1425 if (type == *fContext.fFloatLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001426 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1427 "float"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001428 } else if (type == *fContext.fIntLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001429 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1430 "int"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001431 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001432 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1433 type.fName));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001434 }
1435 if (!ctor) {
1436 printf("error, null identifier: %s\n", String(type.fName).c_str());
1437 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001438 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001439 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001440 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001441 if (expr->fKind == Expression::kNullLiteral_Kind) {
1442 SkASSERT(type.kind() == Type::kNullable_Kind);
1443 return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
1444 }
ethannicholas5961bc92016-10-12 06:39:56 -07001445 std::vector<std::unique_ptr<Expression>> args;
1446 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001447 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001448}
1449
ethannicholasf789b382016-08-03 12:43:36 -07001450static bool is_matrix_multiply(const Type& left, const Type& right) {
1451 if (left.kind() == Type::kMatrix_Kind) {
1452 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1453 }
1454 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1455}
ethannicholasea4567c2016-10-17 11:24:37 -07001456
ethannicholasb3058bd2016-07-01 08:22:01 -07001457/**
1458 * Determines the operand and result types of a binary expression. Returns true if the expression is
1459 * legal, false otherwise. If false, the values of the out parameters are undefined.
1460 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001461static bool determine_binary_type(const Context& context,
1462 Token::Kind op,
1463 const Type& left,
1464 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001465 const Type** outLeftType,
1466 const Type** outRightType,
1467 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001468 bool tryFlipped) {
1469 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001470 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001471 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001472 case Token::Kind::TK_EQ:
ethannicholasea4567c2016-10-17 11:24:37 -07001473 *outLeftType = &left;
1474 *outRightType = &left;
1475 *outResultType = &left;
1476 return right.canCoerceTo(left);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001477 case Token::Kind::TK_EQEQ: // fall through
1478 case Token::Kind::TK_NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001479 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001480 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001481 *outRightType = &left;
1482 *outResultType = context.fBool_Type.get();
1483 return true;
1484 } if (left.canCoerceTo(right)) {
1485 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001486 *outRightType = &right;
1487 *outResultType = context.fBool_Type.get();
1488 return true;
1489 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001490 return false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001491 case Token::Kind::TK_LT: // fall through
1492 case Token::Kind::TK_GT: // fall through
1493 case Token::Kind::TK_LTEQ: // fall through
1494 case Token::Kind::TK_GTEQ:
ethannicholasb3058bd2016-07-01 08:22:01 -07001495 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001496 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001498 case Token::Kind::TK_LOGICALOR: // fall through
1499 case Token::Kind::TK_LOGICALAND: // fall through
1500 case Token::Kind::TK_LOGICALXOR: // fall through
1501 case Token::Kind::TK_LOGICALOREQ: // fall through
1502 case Token::Kind::TK_LOGICALANDEQ: // fall through
1503 case Token::Kind::TK_LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001504 *outLeftType = context.fBool_Type.get();
1505 *outRightType = context.fBool_Type.get();
1506 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001507 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001508 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001509 case Token::Kind::TK_STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001510 if (left.kind() == Type::kScalar_Kind) {
1511 *outLeftType = &left;
1512 *outRightType = &left;
1513 *outResultType = &left;
1514 return right.canCoerceTo(left);
1515 }
John Stiles30212b72020-06-11 17:55:07 -04001516 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001517 case Token::Kind::TK_STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001518 if (is_matrix_multiply(left, right)) {
1519 // determine final component type
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001520 if (determine_binary_type(context, Token::Kind::TK_STAR, left.componentType(),
ethannicholasf789b382016-08-03 12:43:36 -07001521 right.componentType(), outLeftType, outRightType,
1522 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001523 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001524 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001525 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001526 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001527 int leftColumns = left.columns();
1528 int leftRows = left.rows();
1529 int rightColumns;
1530 int rightRows;
1531 if (right.kind() == Type::kVector_Kind) {
1532 // matrix * vector treats the vector as a column vector, so we need to
1533 // transpose it
1534 rightColumns = right.rows();
1535 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001536 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001537 } else {
1538 rightColumns = right.columns();
1539 rightRows = right.rows();
1540 }
1541 if (rightColumns > 1) {
1542 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1543 leftRows);
1544 } else {
1545 // result was a column vector, transpose it back to a row
1546 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1547 rightColumns);
1548 }
1549 return leftColumns == rightRows;
1550 } else {
1551 return false;
1552 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001553 }
ethannicholasea4567c2016-10-17 11:24:37 -07001554 isLogical = false;
1555 validMatrixOrVectorOp = true;
1556 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001557 case Token::Kind::TK_PLUSEQ:
1558 case Token::Kind::TK_MINUSEQ:
1559 case Token::Kind::TK_SLASHEQ:
1560 case Token::Kind::TK_PERCENTEQ:
1561 case Token::Kind::TK_SHLEQ:
1562 case Token::Kind::TK_SHREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001563 if (left.kind() == Type::kScalar_Kind) {
1564 *outLeftType = &left;
1565 *outRightType = &left;
1566 *outResultType = &left;
1567 return right.canCoerceTo(left);
1568 }
John Stiles30212b72020-06-11 17:55:07 -04001569 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001570 case Token::Kind::TK_PLUS: // fall through
1571 case Token::Kind::TK_MINUS: // fall through
1572 case Token::Kind::TK_SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001573 isLogical = false;
1574 validMatrixOrVectorOp = true;
1575 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001576 case Token::Kind::TK_COMMA:
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001577 *outLeftType = &left;
1578 *outRightType = &right;
1579 *outResultType = &right;
1580 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001581 default:
1582 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001583 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001584 }
ethannicholasea4567c2016-10-17 11:24:37 -07001585 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001586 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1587 right.canCoerceTo(left)) {
1588 if (left.priority() > right.priority()) {
1589 *outLeftType = &left;
1590 *outRightType = &left;
1591 } else {
1592 *outLeftType = &right;
1593 *outRightType = &right;
1594 }
1595 if (isLogical) {
1596 *outResultType = context.fBool_Type.get();
1597 } else {
1598 *outResultType = &left;
1599 }
1600 return true;
1601 }
1602 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001603 *outLeftType = &left;
1604 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001605 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001606 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001607 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001608 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001609 }
1610 return true;
1611 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001612 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001613 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001614 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001615 outRightType, outResultType, false)) {
1616 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001617 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001618 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001619 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001620 }
1621 return true;
1622 }
1623 return false;
1624 }
1625 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001626 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001627 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001628 }
1629 return false;
1630}
1631
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001632static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1633 const Expression& left,
1634 Token::Kind op,
1635 const Expression& right) {
1636 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
1637 bool leftVal = ((BoolLiteral&) left).fValue;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001638 if (op == Token::Kind::TK_LOGICALAND) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001639 // (true && expr) -> (expr) and (false && expr) -> (false)
1640 return leftVal ? right.clone()
1641 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001642 } else if (op == Token::Kind::TK_LOGICALOR) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001643 // (true || expr) -> (true) and (false || expr) -> (expr)
1644 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1645 : right.clone();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001646 } else if (op == Token::Kind::TK_LOGICALXOR) {
Noah Lavine334d0ba2019-12-18 23:03:49 -05001647 // (true ^^ expr) -> !(expr) and (false ^^ expr) -> (expr)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001648 return leftVal ? std::unique_ptr<Expression>(new PrefixExpression(
1649 Token::Kind::TK_LOGICALNOT,
1650 right.clone()))
Noah Lavine334d0ba2019-12-18 23:03:49 -05001651 : right.clone();
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001652 } else {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001653 return nullptr;
1654 }
1655}
1656
ethannicholas08a92112016-11-09 13:26:45 -08001657std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1658 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001659 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001660 // If the left side is a constant boolean literal, the right side does not need to be constant
1661 // for short circuit optimizations to allow the constant to be folded.
Brian Osmanb6b95732020-06-30 11:44:27 -04001662 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001663 return short_circuit_boolean(fContext, left, op, right);
Brian Osmanb6b95732020-06-30 11:44:27 -04001664 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001665 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1666 // (right OP left) for short-circuit optimizations
1667 return short_circuit_boolean(fContext, right, op, left);
1668 }
1669
1670 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Brian Osmanb6b95732020-06-30 11:44:27 -04001671 if (!left.isCompileTimeConstant() || !right.isCompileTimeConstant()) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001672 return nullptr;
1673 }
ethannicholas08a92112016-11-09 13:26:45 -08001674 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1675 // precision to calculate the results and hope the result makes sense. The plan is to move the
1676 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1677 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001678 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001679 right.fKind == Expression::kBoolLiteral_Kind) {
1680 bool leftVal = ((BoolLiteral&) left).fValue;
1681 bool rightVal = ((BoolLiteral&) right).fValue;
1682 bool result;
1683 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001684 case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
1685 case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
1686 case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
ethannicholas08a92112016-11-09 13:26:45 -08001687 default: return nullptr;
1688 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001689 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001690 }
John Stilesfbd050b2020-08-03 13:21:46 -04001691 #define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1692 leftVal op rightVal)
1693 #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1694 (uint32_t) leftVal op \
1695 (uint32_t) rightVal)
ethannicholas08a92112016-11-09 13:26:45 -08001696 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001697 int64_t leftVal = left.as<IntLiteral>().fValue;
1698 int64_t rightVal = right.as<IntLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001699 switch (op) {
Ethan Nicholas66869e92020-04-30 09:27:54 -04001700 case Token::Kind::TK_PLUS: return URESULT(Int, +);
1701 case Token::Kind::TK_MINUS: return URESULT(Int, -);
1702 case Token::Kind::TK_STAR: return URESULT(Int, *);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001703 case Token::Kind::TK_SLASH:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001704 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1705 fErrors.error(right.fOffset, "arithmetic overflow");
1706 return nullptr;
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001707 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001708 if (!rightVal) {
1709 fErrors.error(right.fOffset, "division by zero");
1710 return nullptr;
1711 }
1712 return RESULT(Int, /);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001713 case Token::Kind::TK_PERCENT:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001714 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1715 fErrors.error(right.fOffset, "arithmetic overflow");
1716 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001717 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001718 if (!rightVal) {
1719 fErrors.error(right.fOffset, "division by zero");
1720 return nullptr;
1721 }
1722 return RESULT(Int, %);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001723 case Token::Kind::TK_BITWISEAND: return RESULT(Int, &);
1724 case Token::Kind::TK_BITWISEOR: return RESULT(Int, |);
1725 case Token::Kind::TK_BITWISEXOR: return RESULT(Int, ^);
1726 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1727 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1728 case Token::Kind::TK_GT: return RESULT(Bool, >);
1729 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1730 case Token::Kind::TK_LT: return RESULT(Bool, <);
1731 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1732 case Token::Kind::TK_SHL:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001733 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001734 return URESULT(Int, <<);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001735 }
1736 fErrors.error(right.fOffset, "shift value out of range");
1737 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001738 case Token::Kind::TK_SHR:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001739 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001740 return URESULT(Int, >>);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001741 }
1742 fErrors.error(right.fOffset, "shift value out of range");
1743 return nullptr;
1744
1745 default:
1746 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001747 }
1748 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001749 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001750 right.fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001751 double leftVal = left.as<FloatLiteral>().fValue;
1752 double rightVal = right.as<FloatLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001753 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001754 case Token::Kind::TK_PLUS: return RESULT(Float, +);
1755 case Token::Kind::TK_MINUS: return RESULT(Float, -);
1756 case Token::Kind::TK_STAR: return RESULT(Float, *);
1757 case Token::Kind::TK_SLASH:
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001758 if (rightVal) {
1759 return RESULT(Float, /);
1760 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001761 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001762 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001763 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1764 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1765 case Token::Kind::TK_GT: return RESULT(Bool, >);
1766 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1767 case Token::Kind::TK_LT: return RESULT(Bool, <);
1768 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1769 default: return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001770 }
1771 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001772 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001773 left.fType == right.fType) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001774 std::vector<std::unique_ptr<Expression>> args;
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001775 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1776 for (int i = 0; i < left.fType.columns(); i++) { \
1777 float value = left.getFVecComponent(i) op \
1778 right.getFVecComponent(i); \
1779 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
1780 } \
1781 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001782 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001783 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001784 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001785 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001786 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001787 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001788 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001789 !left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001790 case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1791 case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1792 case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1793 case Token::Kind::TK_SLASH:
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001794 for (int i = 0; i < left.fType.columns(); i++) {
1795 SKSL_FLOAT rvalue = right.getFVecComponent(i);
1796 if (rvalue == 0.0) {
1797 fErrors.error(right.fOffset, "division by zero");
1798 return nullptr;
1799 }
1800 float value = left.getFVecComponent(i) / rvalue;
1801 args.emplace_back(new FloatLiteral(fContext, -1, value));
1802 }
1803 return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
1804 std::move(args)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001805 default: return nullptr;
1806 }
1807 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001808 if (left.fType.kind() == Type::kMatrix_Kind &&
1809 right.fType.kind() == Type::kMatrix_Kind &&
1810 left.fKind == right.fKind) {
1811 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001812 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001813 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001814 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001815 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001816 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001817 !left.compareConstant(fContext, right)));
1818 default:
1819 return nullptr;
1820 }
1821 }
ethannicholas08a92112016-11-09 13:26:45 -08001822 #undef RESULT
1823 return nullptr;
1824}
1825
Ethan Nicholasfc994162019-06-06 10:04:27 -04001826std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
1827 SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
1828 auto iter = expression.begin();
1829 std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001830 if (!left) {
1831 return nullptr;
1832 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001833 Token::Kind op = expression.getToken().fKind;
John Stilesd1c4dac2020-08-11 18:50:50 -04001834 std::unique_ptr<Expression> right;
1835 {
1836 // Can't inline the right side of a short-circuiting boolean, because our inlining
1837 // approach runs things out of order.
1838 AutoDisableInline disableInline(this, /*canInline=*/(op != Token::Kind::TK_LOGICALAND &&
1839 op != Token::Kind::TK_LOGICALOR));
1840 right = this->convertExpression(*(iter++));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001841 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001842 if (!right) {
1843 return nullptr;
1844 }
ethannicholasd598f792016-07-25 10:08:54 -07001845 const Type* leftType;
1846 const Type* rightType;
1847 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001848 const Type* rawLeftType;
1849 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1850 rawLeftType = &right->fType;
1851 } else {
1852 rawLeftType = &left->fType;
1853 }
1854 const Type* rawRightType;
1855 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1856 rawRightType = &left->fType;
1857 } else {
1858 rawRightType = &right->fType;
1859 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001860 if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
1861 &resultType, !Compiler::IsAssignment(op))) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001862 fErrors.error(expression.fOffset, String("type mismatch: '") +
Ethan Nicholasfc994162019-06-06 10:04:27 -04001863 Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001864 "' cannot operate on '" + left->fType.displayName() +
1865 "', '" + right->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001866 return nullptr;
1867 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001868 if (Compiler::IsAssignment(op)) {
Ethan Nicholas4fadce42020-07-30 13:29:30 -04001869 if (!this->setRefKind(*left, op != Token::Kind::TK_EQ
1870 ? VariableReference::kReadWrite_RefKind
1871 : VariableReference::kWrite_RefKind)) {
1872 return nullptr;
1873 }
ethannicholasea4567c2016-10-17 11:24:37 -07001874 }
1875 left = this->coerce(std::move(left), *leftType);
1876 right = this->coerce(std::move(right), *rightType);
1877 if (!left || !right) {
1878 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001879 }
John Stilesa008b0f2020-08-16 08:48:02 -04001880 std::unique_ptr<Expression> result = this->constantFold(*left, op, *right);
ethannicholas08a92112016-11-09 13:26:45 -08001881 if (!result) {
John Stilesd1c4dac2020-08-11 18:50:50 -04001882 result = std::make_unique<BinaryExpression>(expression.fOffset, std::move(left), op,
1883 std::move(right), *resultType);
ethannicholas08a92112016-11-09 13:26:45 -08001884 }
1885 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001886}
1887
Ethan Nicholasfc994162019-06-06 10:04:27 -04001888std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
1889 SkASSERT(node.fKind == ASTNode::Kind::kTernary);
1890 auto iter = node.begin();
1891 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -07001892 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001893 if (!test) {
1894 return nullptr;
1895 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001896 std::unique_ptr<Expression> ifTrue = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001897 if (!ifTrue) {
1898 return nullptr;
1899 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001900 std::unique_ptr<Expression> ifFalse = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001901 if (!ifFalse) {
1902 return nullptr;
1903 }
ethannicholasd598f792016-07-25 10:08:54 -07001904 const Type* trueType;
1905 const Type* falseType;
1906 const Type* resultType;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001907 if (!determine_binary_type(fContext, Token::Kind::TK_EQEQ, ifTrue->fType, ifFalse->fType,
1908 &trueType, &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001909 fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001910 ifTrue->fType.displayName() + "', '" +
1911 ifFalse->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001912 return nullptr;
1913 }
Brian Osman82329002020-07-21 09:39:27 -04001914 if (trueType->nonnullable() == *fContext.fFragmentProcessor_Type) {
1915 fErrors.error(node.fOffset,
1916 "ternary expression of type '" + trueType->displayName() + "' not allowed");
1917 return nullptr;
1918 }
ethannicholasd598f792016-07-25 10:08:54 -07001919 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001920 if (!ifTrue) {
1921 return nullptr;
1922 }
ethannicholasd598f792016-07-25 10:08:54 -07001923 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001924 if (!ifFalse) {
1925 return nullptr;
1926 }
ethannicholas08a92112016-11-09 13:26:45 -08001927 if (test->fKind == Expression::kBoolLiteral_Kind) {
1928 // static boolean test, just return one of the branches
1929 if (((BoolLiteral&) *test).fValue) {
1930 return ifTrue;
1931 } else {
1932 return ifFalse;
1933 }
1934 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001935 return std::unique_ptr<Expression>(new TernaryExpression(node.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001936 std::move(test),
Ethan Nicholas11d53972016-11-28 11:23:23 -05001937 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -07001938 std::move(ifFalse)));
1939}
1940
John Stilesddefaee2020-08-11 15:13:26 -04001941std::unique_ptr<Expression> IRGenerator::inlineExpression(
1942 int offset,
1943 std::unordered_map<const Variable*, const Variable*>* varMap,
1944 const Expression& expression) {
John Stiles4914cbc2020-08-13 18:00:55 -04001945 auto expr = [&](const std::unique_ptr<Expression>& e) -> std::unique_ptr<Expression> {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001946 if (e) {
1947 return this->inlineExpression(offset, varMap, *e);
1948 }
John Stiles4914cbc2020-08-13 18:00:55 -04001949 return nullptr;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001950 };
1951 switch (expression.fKind) {
1952 case Expression::kBinary_Kind: {
1953 const BinaryExpression& b = (const BinaryExpression&) expression;
1954 return std::unique_ptr<Expression>(new BinaryExpression(offset,
1955 expr(b.fLeft),
1956 b.fOperator,
1957 expr(b.fRight),
1958 b.fType));
1959 }
1960 case Expression::kBoolLiteral_Kind:
1961 case Expression::kIntLiteral_Kind:
1962 case Expression::kFloatLiteral_Kind:
1963 case Expression::kNullLiteral_Kind:
1964 return expression.clone();
1965 case Expression::kConstructor_Kind: {
1966 const Constructor& c = (const Constructor&) expression;
1967 std::vector<std::unique_ptr<Expression>> args;
1968 for (const auto& arg : c.fArguments) {
1969 args.push_back(expr(arg));
1970 }
1971 return std::unique_ptr<Expression>(new Constructor(offset, c.fType, std::move(args)));
1972 }
1973 case Expression::kExternalFunctionCall_Kind: {
1974 const ExternalFunctionCall& e = (const ExternalFunctionCall&) expression;
1975 std::vector<std::unique_ptr<Expression>> args;
1976 for (const auto& arg : e.fArguments) {
1977 args.push_back(expr(arg));
1978 }
1979 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, e.fType,
1980 e.fFunction,
1981 std::move(args)));
1982 }
1983 case Expression::kExternalValue_Kind:
1984 return expression.clone();
1985 case Expression::kFieldAccess_Kind: {
1986 const FieldAccess& f = (const FieldAccess&) expression;
1987 return std::unique_ptr<Expression>(new FieldAccess(expr(f.fBase), f.fFieldIndex,
1988 f.fOwnerKind));
1989 }
1990 case Expression::kFunctionCall_Kind: {
1991 const FunctionCall& c = (const FunctionCall&) expression;
1992 std::vector<std::unique_ptr<Expression>> args;
1993 for (const auto& arg : c.fArguments) {
1994 args.push_back(expr(arg));
1995 }
1996 return std::unique_ptr<Expression>(new FunctionCall(offset, c.fType, c.fFunction,
1997 std::move(args)));
1998 }
1999 case Expression::kIndex_Kind: {
2000 const IndexExpression& idx = (const IndexExpression&) expression;
2001 return std::unique_ptr<Expression>(new IndexExpression(fContext, expr(idx.fBase),
2002 expr(idx.fIndex)));
2003 }
2004 case Expression::kPrefix_Kind: {
2005 const PrefixExpression& p = (const PrefixExpression&) expression;
2006 return std::unique_ptr<Expression>(new PrefixExpression(p.fOperator, expr(p.fOperand)));
2007 }
2008 case Expression::kPostfix_Kind: {
2009 const PostfixExpression& p = (const PostfixExpression&) expression;
2010 return std::unique_ptr<Expression>(new PostfixExpression(expr(p.fOperand),
2011 p.fOperator));
2012 }
2013 case Expression::kSetting_Kind:
2014 return expression.clone();
2015 case Expression::kSwizzle_Kind: {
2016 const Swizzle& s = (const Swizzle&) expression;
2017 return std::unique_ptr<Expression>(new Swizzle(fContext, expr(s.fBase), s.fComponents));
2018 }
2019 case Expression::kTernary_Kind: {
2020 const TernaryExpression& t = (const TernaryExpression&) expression;
2021 return std::unique_ptr<Expression>(new TernaryExpression(offset, expr(t.fTest),
2022 expr(t.fIfTrue),
2023 expr(t.fIfFalse)));
2024 }
2025 case Expression::kVariableReference_Kind: {
2026 const VariableReference& v = (const VariableReference&) expression;
2027 auto found = varMap->find(&v.fVariable);
2028 if (found != varMap->end()) {
2029 return std::unique_ptr<Expression>(new VariableReference(offset,
2030 *found->second,
2031 v.fRefKind));
2032 }
2033 return v.clone();
2034 }
2035 default:
2036 SkASSERT(false);
2037 return nullptr;
2038 }
2039}
2040
John Stiles36374402020-08-13 12:16:44 -04002041static const Type* copy_if_needed(const Type* src, SymbolTable& symbolTable) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002042 if (src->kind() == Type::kArray_Kind) {
John Stiles3ae071e2020-08-05 15:29:29 -04002043 return symbolTable.takeOwnershipOfSymbol(std::make_unique<Type>(*src));
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002044 }
2045 return src;
2046}
2047
John Stilesddefaee2020-08-11 15:13:26 -04002048std::unique_ptr<Statement> IRGenerator::inlineStatement(
2049 int offset,
2050 std::unordered_map<const Variable*, const Variable*>* varMap,
2051 const Variable* returnVar,
2052 bool haveEarlyReturns,
2053 const Statement& statement) {
John Stiles4914cbc2020-08-13 18:00:55 -04002054 auto stmt = [&](const std::unique_ptr<Statement>& s) -> std::unique_ptr<Statement> {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002055 if (s) {
2056 return this->inlineStatement(offset, varMap, returnVar, haveEarlyReturns, *s);
2057 }
John Stiles4914cbc2020-08-13 18:00:55 -04002058 return nullptr;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002059 };
2060 auto stmts = [&](const std::vector<std::unique_ptr<Statement>>& ss) {
2061 std::vector<std::unique_ptr<Statement>> result;
2062 for (const auto& s : ss) {
2063 result.push_back(stmt(s));
2064 }
2065 return result;
2066 };
John Stiles4914cbc2020-08-13 18:00:55 -04002067 auto expr = [&](const std::unique_ptr<Expression>& e) -> std::unique_ptr<Expression> {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002068 if (e) {
2069 return this->inlineExpression(offset, varMap, *e);
2070 }
John Stiles4914cbc2020-08-13 18:00:55 -04002071 return nullptr;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002072 };
2073 switch (statement.fKind) {
2074 case Statement::kBlock_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002075 const Block& b = static_cast<const Block&>(statement);
John Stilesfbd050b2020-08-03 13:21:46 -04002076 return std::make_unique<Block>(offset, stmts(b.fStatements), b.fSymbols, b.fIsScope);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002077 }
2078
2079 case Statement::kBreak_Kind:
2080 case Statement::kContinue_Kind:
2081 case Statement::kDiscard_Kind:
2082 return statement.clone();
2083
2084 case Statement::kDo_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002085 const DoStatement& d = static_cast<const DoStatement&>(statement);
John Stilesfbd050b2020-08-03 13:21:46 -04002086 return std::make_unique<DoStatement>(offset, stmt(d.fStatement), expr(d.fTest));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002087 }
2088 case Statement::kExpression_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002089 const ExpressionStatement& e = static_cast<const ExpressionStatement&>(statement);
John Stilesfbd050b2020-08-03 13:21:46 -04002090 return std::make_unique<ExpressionStatement>(expr(e.fExpression));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002091 }
2092 case Statement::kFor_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002093 const ForStatement& f = static_cast<const ForStatement&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002094 // need to ensure initializer is evaluated first so that we've already remapped its
2095 // declarations by the time we evaluate test & next
2096 std::unique_ptr<Statement> initializer = stmt(f.fInitializer);
John Stilesfbd050b2020-08-03 13:21:46 -04002097 return std::make_unique<ForStatement>(offset, std::move(initializer), expr(f.fTest),
2098 expr(f.fNext), stmt(f.fStatement), f.fSymbols);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002099 }
2100 case Statement::kIf_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002101 const IfStatement& i = static_cast<const IfStatement&>(statement);
John Stilesfbd050b2020-08-03 13:21:46 -04002102 return std::make_unique<IfStatement>(offset, i.fIsStatic, expr(i.fTest),
2103 stmt(i.fIfTrue), stmt(i.fIfFalse));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002104 }
2105 case Statement::kNop_Kind:
2106 return statement.clone();
2107 case Statement::kReturn_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002108 const ReturnStatement& r = static_cast<const ReturnStatement&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002109 if (r.fExpression) {
John Stiles48bdf6d2020-08-13 18:02:22 -04002110 auto assignment = std::make_unique<ExpressionStatement>(
John Stilesfbd050b2020-08-03 13:21:46 -04002111 std::make_unique<BinaryExpression>(
2112 offset,
2113 std::make_unique<VariableReference>(offset, *returnVar,
2114 VariableReference::kWrite_RefKind),
2115 Token::Kind::TK_EQ,
2116 expr(r.fExpression),
2117 returnVar->fType));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002118 if (haveEarlyReturns) {
2119 std::vector<std::unique_ptr<Statement>> block;
2120 block.push_back(std::move(assignment));
2121 block.emplace_back(new BreakStatement(offset));
John Stiles48bdf6d2020-08-13 18:02:22 -04002122 return std::make_unique<Block>(offset, std::move(block), /*symbols=*/nullptr,
2123 /*isScope=*/true);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002124 } else {
John Stiles48bdf6d2020-08-13 18:02:22 -04002125 return std::move(assignment);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002126 }
2127 } else {
2128 if (haveEarlyReturns) {
John Stilesfbd050b2020-08-03 13:21:46 -04002129 return std::make_unique<BreakStatement>(offset);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002130 } else {
John Stilesfbd050b2020-08-03 13:21:46 -04002131 return std::make_unique<Nop>();
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002132 }
2133 }
2134 }
2135 case Statement::kSwitch_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002136 const SwitchStatement& ss = static_cast<const SwitchStatement&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002137 std::vector<std::unique_ptr<SwitchCase>> cases;
2138 for (const auto& sc : ss.fCases) {
2139 cases.emplace_back(new SwitchCase(offset, expr(sc->fValue),
2140 stmts(sc->fStatements)));
2141 }
John Stilesfbd050b2020-08-03 13:21:46 -04002142 return std::make_unique<SwitchStatement>(offset, ss.fIsStatic, expr(ss.fValue),
2143 std::move(cases), ss.fSymbols);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002144 }
2145 case Statement::kVarDeclaration_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002146 const VarDeclaration& decl = static_cast<const VarDeclaration&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002147 std::vector<std::unique_ptr<Expression>> sizes;
2148 for (const auto& size : decl.fSizes) {
2149 sizes.push_back(expr(size));
2150 }
2151 std::unique_ptr<Expression> initialValue = expr(decl.fValue);
2152 const Variable* old = decl.fVar;
Ethan Nicholase8ad02c2020-06-03 16:58:20 -04002153 // need to copy the var name in case the originating function is discarded and we lose
2154 // its symbols
2155 std::unique_ptr<String> name(new String(old->fName));
John Stiles3ae071e2020-08-05 15:29:29 -04002156 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002157 const Type* typePtr = copy_if_needed(&old->fType, *fSymbolTable);
John Stiles3ae071e2020-08-05 15:29:29 -04002158 const Variable* clone = fSymbolTable->takeOwnershipOfSymbol(
2159 std::make_unique<Variable>(offset,
2160 old->fModifiers,
2161 namePtr->c_str(),
2162 *typePtr,
2163 old->fStorage,
2164 initialValue.get()));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002165 (*varMap)[old] = clone;
John Stilesfbd050b2020-08-03 13:21:46 -04002166 return std::make_unique<VarDeclaration>(clone, std::move(sizes),
2167 std::move(initialValue));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002168 }
2169 case Statement::kVarDeclarations_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002170 const VarDeclarations& decls =
2171 *static_cast<const VarDeclarationsStatement&>(statement).fDeclaration;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002172 std::vector<std::unique_ptr<VarDeclaration>> vars;
2173 for (const auto& var : decls.fVars) {
2174 vars.emplace_back((VarDeclaration*) stmt(var).release());
2175 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002176 const Type* typePtr = copy_if_needed(&decls.fBaseType, *fSymbolTable);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002177 return std::unique_ptr<Statement>(new VarDeclarationsStatement(
John Stilesfbd050b2020-08-03 13:21:46 -04002178 std::make_unique<VarDeclarations>(offset, typePtr, std::move(vars))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002179 }
2180 case Statement::kWhile_Kind: {
John Stiles48bdf6d2020-08-13 18:02:22 -04002181 const WhileStatement& w = static_cast<const WhileStatement&>(statement);
John Stilesfbd050b2020-08-03 13:21:46 -04002182 return std::make_unique<WhileStatement>(offset, expr(w.fTest), stmt(w.fStatement));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002183 }
2184 default:
2185 SkASSERT(false);
2186 return nullptr;
2187 }
2188}
2189
John Stiles8c91c932020-08-13 14:35:35 -04002190template <bool countTopLevelReturns>
2191static int return_count(const Statement& statement, bool inLoopOrSwitch) {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002192 switch (statement.fKind) {
2193 case Statement::kBlock_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002194 const Block& b = static_cast<const Block&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002195 int result = 0;
John Stiles8c91c932020-08-13 14:35:35 -04002196 for (const std::unique_ptr<Statement>& s : b.fStatements) {
2197 result += return_count<countTopLevelReturns>(*s, inLoopOrSwitch);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002198 }
2199 return result;
2200 }
2201 case Statement::kDo_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002202 const DoStatement& d = static_cast<const DoStatement&>(statement);
2203 return return_count<countTopLevelReturns>(*d.fStatement, /*inLoopOrSwitch=*/true);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002204 }
2205 case Statement::kFor_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002206 const ForStatement& f = static_cast<const ForStatement&>(statement);
2207 return return_count<countTopLevelReturns>(*f.fStatement, /*inLoopOrSwitch=*/true);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002208 }
2209 case Statement::kIf_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002210 const IfStatement& i = static_cast<const IfStatement&>(statement);
2211 int result = return_count<countTopLevelReturns>(*i.fIfTrue, inLoopOrSwitch);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002212 if (i.fIfFalse) {
John Stiles8c91c932020-08-13 14:35:35 -04002213 result += return_count<countTopLevelReturns>(*i.fIfFalse, inLoopOrSwitch);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002214 }
2215 return result;
2216 }
2217 case Statement::kReturn_Kind:
John Stiles8c91c932020-08-13 14:35:35 -04002218 return (countTopLevelReturns || inLoopOrSwitch) ? 1 : 0;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002219 case Statement::kSwitch_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002220 const SwitchStatement& ss = static_cast<const SwitchStatement&>(statement);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002221 int result = 0;
John Stiles8c91c932020-08-13 14:35:35 -04002222 for (const std::unique_ptr<SwitchCase>& sc : ss.fCases) {
2223 for (const std::unique_ptr<Statement>& s : sc->fStatements) {
2224 result += return_count<countTopLevelReturns>(*s, /*inLoopOrSwitch=*/true);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002225 }
2226 }
2227 return result;
2228 }
2229 case Statement::kWhile_Kind: {
John Stiles8c91c932020-08-13 14:35:35 -04002230 const WhileStatement& w = static_cast<const WhileStatement&>(statement);
2231 return return_count<countTopLevelReturns>(*w.fStatement, /*inLoopOrSwitch=*/true);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002232 }
2233 case Statement::kBreak_Kind:
2234 case Statement::kContinue_Kind:
2235 case Statement::kDiscard_Kind:
2236 case Statement::kExpression_Kind:
2237 case Statement::kNop_Kind:
2238 case Statement::kVarDeclaration_Kind:
2239 case Statement::kVarDeclarations_Kind:
2240 return 0;
2241 default:
2242 SkASSERT(false);
2243 return 0;
2244 }
2245}
2246
John Stiles36374402020-08-13 12:16:44 -04002247static bool has_early_return(const FunctionDefinition& f) {
John Stiles8c91c932020-08-13 14:35:35 -04002248 int returnCount =
2249 return_count</*countTopLevelReturns=*/true>(*f.fBody, /*inLoopOrSwitch=*/false);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002250 if (returnCount == 0) {
2251 return false;
2252 }
2253 if (returnCount > 1) {
2254 return true;
2255 }
2256 SkASSERT(f.fBody->fKind == Statement::kBlock_Kind);
John Stiles8c91c932020-08-13 14:35:35 -04002257 return static_cast<Block&>(*f.fBody).fStatements.back()->fKind != Statement::kReturn_Kind;
2258}
2259
2260static bool has_return_in_breakable_construct(const FunctionDefinition& f) {
2261 int returnCount =
2262 return_count</*countTopLevelReturns=*/false>(*f.fBody, /*inLoopOrSwitch=*/false);
2263 return returnCount > 0;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002264}
2265
2266std::unique_ptr<Expression> IRGenerator::inlineCall(
2267 int offset,
2268 const FunctionDefinition& function,
2269 std::vector<std::unique_ptr<Expression>> arguments) {
2270 // Inlining is more complicated here than in a typical compiler, because we have to have a
2271 // high-level IR and can't just drop statements into the middle of an expression or even use
2272 // gotos.
2273 //
2274 // Since we can't insert statements into an expression, we run the inline function as extra
2275 // statements before the statement we're currently processing, relying on a lack of execution
2276 // order guarantees. Since we can't use gotos (which are normally used to replace return
2277 // statements), we wrap the whole function in a loop and use break statements to jump to the
2278 // end.
Brian Osmanb5f0f522020-07-23 13:28:14 -04002279
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002280 // Use unique variable names based on the function signature. Otherwise there are situations in
2281 // which an inlined function is later inlined into another function, and we end up with
2282 // duplicate names like 'inlineResult0' because the counter was reset. (skbug.com/10526)
2283 String raw = function.fDeclaration.description();
2284 String inlineSalt;
2285 for (size_t i = 0; i < raw.length(); ++i) {
2286 char c = raw[i];
2287 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
2288 c == '_') {
2289 inlineSalt += c;
2290 }
Brian Osmanb5f0f522020-07-23 13:28:14 -04002291 }
2292
John Stiles311dd9d2020-08-13 17:09:29 -04002293 const Variable* resultVar = nullptr;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002294 if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
2295 std::unique_ptr<String> name(new String());
Michael Ludwig9861b7c2020-06-23 18:37:17 -04002296 int varIndex = fInlineVarCounter++;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002297 name->appendf("_inlineResult%s%d", inlineSalt.c_str(), varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002298 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
John Stiles311dd9d2020-08-13 17:09:29 -04002299 StringFragment nameFrag{namePtr->c_str(), namePtr->length()};
2300 resultVar = fSymbolTable->add(
2301 nameFrag,
2302 std::make_unique<Variable>(
2303 /*offset=*/-1, Modifiers(), nameFrag, function.fDeclaration.fReturnType,
2304 Variable::kLocal_Storage, /*initialValue=*/nullptr));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002305 std::vector<std::unique_ptr<VarDeclaration>> variables;
2306 variables.emplace_back(new VarDeclaration(resultVar, {}, nullptr));
John Stilesfbd050b2020-08-03 13:21:46 -04002307 fExtraStatements.emplace_back(
2308 new VarDeclarationsStatement(std::make_unique<VarDeclarations>(
2309 offset, &resultVar->fType, std::move(variables))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002310
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002311 }
John Stilesddefaee2020-08-11 15:13:26 -04002312 std::unordered_map<const Variable*, const Variable*> varMap;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002313 // create variables to hold the arguments and assign the arguments to them
Michael Ludwig9861b7c2020-06-23 18:37:17 -04002314 int argIndex = fInlineVarCounter++;
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002315 for (int i = 0; i < (int) arguments.size(); ++i) {
2316 std::unique_ptr<String> argName(new String());
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002317 argName->appendf("_inlineArg%s%d_%d", inlineSalt.c_str(), argIndex, i);
John Stiles3ae071e2020-08-05 15:29:29 -04002318 const String* argNamePtr = fSymbolTable->takeOwnershipOfString(std::move(argName));
John Stiles311dd9d2020-08-13 17:09:29 -04002319 StringFragment argNameFrag{argNamePtr->c_str(), argNamePtr->length()};
2320 const Variable* argVar = fSymbolTable->add(
2321 argNameFrag, std::make_unique<Variable>(
2322 /*offset=*/-1, Modifiers(), argNameFrag, arguments[i]->fType,
2323 Variable::kLocal_Storage, arguments[i].get()));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002324 varMap[function.fDeclaration.fParameters[i]] = argVar;
2325 std::vector<std::unique_ptr<VarDeclaration>> vars;
2326 if (function.fDeclaration.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
2327 vars.emplace_back(new VarDeclaration(argVar, {}, arguments[i]->clone()));
2328 } else {
2329 vars.emplace_back(new VarDeclaration(argVar, {}, std::move(arguments[i])));
2330 }
2331 fExtraStatements.emplace_back(new VarDeclarationsStatement(
John Stiles311dd9d2020-08-13 17:09:29 -04002332 std::make_unique<VarDeclarations>(offset, &argVar->fType, std::move(vars))));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002333 }
2334 SkASSERT(function.fBody->fKind == Statement::kBlock_Kind);
2335 const Block& body = (Block&) *function.fBody;
2336 bool hasEarlyReturn = has_early_return(function);
2337 std::vector<std::unique_ptr<Statement>> inlined;
2338 for (const auto& s : body.fStatements) {
2339 inlined.push_back(this->inlineStatement(offset, &varMap, resultVar, hasEarlyReturn, *s));
2340 }
2341 if (hasEarlyReturn) {
2342 // Since we output to backends that don't have a goto statement (which would normally be
2343 // used to perform an early return), we fake it by wrapping the function in a
2344 // do { } while (false); and then use break statements to jump to the end in order to
2345 // emulate a goto.
2346 fExtraStatements.emplace_back(new DoStatement(-1,
2347 std::unique_ptr<Statement>(new Block(-1, std::move(inlined))),
2348 std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false))));
2349 } else {
2350 // No early returns, so we can just dump the code in. We need to use a block so we don't get
2351 // name conflicts with locals.
2352 fExtraStatements.emplace_back(std::unique_ptr<Statement>(new Block(-1,
2353 std::move(inlined))));
2354 }
2355 // copy the values of out parameters into their destinations
2356 for (size_t i = 0; i < arguments.size(); ++i) {
2357 const Variable* p = function.fDeclaration.fParameters[i];
2358 if (p->fModifiers.fFlags & Modifiers::kOut_Flag) {
2359 std::unique_ptr<Expression> varRef(new VariableReference(offset, *varMap[p]));
2360 fExtraStatements.emplace_back(new ExpressionStatement(
2361 std::unique_ptr<Expression>(new BinaryExpression(offset,
2362 arguments[i]->clone(),
2363 Token::Kind::TK_EQ,
2364 std::move(varRef),
2365 arguments[i]->fType))));
2366 }
2367 }
2368 if (function.fDeclaration.fReturnType != *fContext.fVoid_Type) {
2369 return std::unique_ptr<Expression>(new VariableReference(-1, *resultVar));
2370 } else {
2371 // it's a void function, so it doesn't actually result in anything, but we have to return
2372 // something non-null as a standin
2373 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1, false));
2374 }
2375}
2376
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002377void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
2378 auto found = fIntrinsics->find(function.description());
2379 if (found != fIntrinsics->end() && !found->second.second) {
2380 found->second.second = true;
2381 FunctionDefinition& original = ((FunctionDefinition&) *found->second.first);
2382 for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
2383 this->copyIntrinsicIfNeeded(*f);
2384 }
2385 fProgramElements->push_back(original.clone());
2386 }
2387}
2388
John Stiles8c91c932020-08-13 14:35:35 -04002389bool IRGenerator::isSafeToInline(const FunctionDefinition& functionDef) {
2390 if (!fCanInline) {
2391 // Inlining has been explicitly disabled by the IR generator.
2392 return false;
2393 }
2394 if (functionDef.inlinedFunctionSize() >= fSettings->fInlineThreshold) {
2395 // The function exceeds our maximum inline size.
2396 return false;
2397 }
2398 if (!fSettings->fCaps || !fSettings->fCaps->canUseDoLoops()) {
2399 // We don't have do-while loops. We use do-while loops to simulate early returns, so we
2400 // can't inline functions that have an early return.
2401 return !has_early_return(functionDef);
2402 }
2403 // We have do-while loops, but we don't have any mechanism to simulate early returns within a
2404 // breakable construct (switch/for/do/while), so we can't inline if there's a return inside one.
2405 return !has_return_in_breakable_construct(functionDef);
2406}
2407
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002408std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002409 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07002410 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002411 if (function.fBuiltin) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002412 if (function.fDefinition) {
2413 fReferencedIntrinsics.insert(&function);
2414 }
2415 if (!fIsBuiltinCode) {
2416 this->copyIntrinsicIfNeeded(function);
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002417 }
2418 }
ethannicholasd598f792016-07-25 10:08:54 -07002419 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002420 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05002421 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07002422 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07002423 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002424 msg += "s";
2425 }
ethannicholas5961bc92016-10-12 06:39:56 -07002426 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002427 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07002428 return nullptr;
2429 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002430 if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
Brian Osman5f6b41e2020-03-09 11:53:24 -04002431 String msg = "call to undefined function '" + function.fName + "'";
2432 fErrors.error(offset, msg);
2433 return nullptr;
2434 }
ethannicholas471e8942016-10-28 09:02:46 -07002435 std::vector<const Type*> types;
2436 const Type* returnType;
2437 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002438 String msg = "no match for " + function.fName + "(";
2439 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07002440 for (size_t i = 0; i < arguments.size(); i++) {
2441 msg += separator;
2442 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002443 msg += arguments[i]->fType.displayName();
ethannicholas471e8942016-10-28 09:02:46 -07002444 }
2445 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002446 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07002447 return nullptr;
2448 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002449 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07002450 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07002451 if (!arguments[i]) {
2452 return nullptr;
2453 }
ethannicholasd598f792016-07-25 10:08:54 -07002454 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002455 this->setRefKind(*arguments[i],
2456 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
2457 VariableReference::kReadWrite_RefKind :
2458 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002459 }
2460 }
John Stiles8c91c932020-08-13 14:35:35 -04002461 if (function.fDefinition && this->isSafeToInline(*function.fDefinition)) {
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002462 return this->inlineCall(offset, *function.fDefinition, std::move(arguments));
2463 }
John Stiles8c91c932020-08-13 14:35:35 -04002464
2465 return std::make_unique<FunctionCall>(offset, *returnType, function, std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002466}
2467
2468/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002469 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
2470 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
2471 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07002472 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002473int IRGenerator::callCost(const FunctionDeclaration& function,
2474 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07002475 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002476 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002477 }
2478 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07002479 std::vector<const Type*> types;
2480 const Type* ignored;
2481 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002482 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07002483 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002484 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002485 int cost = arguments[i]->coercionCost(*types[i]);
2486 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002487 total += cost;
2488 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002489 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002490 }
2491 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002492 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07002493}
2494
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002495std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002496 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07002497 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002498 switch (functionValue->fKind) {
2499 case Expression::kTypeReference_Kind:
2500 return this->convertConstructor(offset,
2501 ((TypeReference&) *functionValue).fValue,
2502 std::move(arguments));
2503 case Expression::kExternalValue_Kind: {
John Stiles534d7992020-08-18 00:06:01 -04002504 const ExternalValue* v = ((ExternalValueReference&) *functionValue).fValue;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002505 if (!v->canCall()) {
2506 fErrors.error(offset, "this external value is not a function");
2507 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002508 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002509 int count = v->callParameterCount();
2510 if (count != (int) arguments.size()) {
2511 fErrors.error(offset, "external function expected " + to_string(count) +
2512 " arguments, but found " + to_string((int) arguments.size()));
2513 return nullptr;
2514 }
2515 static constexpr int PARAMETER_MAX = 16;
2516 SkASSERT(count < PARAMETER_MAX);
2517 const Type* types[PARAMETER_MAX];
2518 v->getCallParameterTypes(types);
2519 for (int i = 0; i < count; ++i) {
2520 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
2521 if (!arguments[i]) {
2522 return nullptr;
2523 }
2524 }
2525 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(),
2526 v, std::move(arguments)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002527 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002528 case Expression::kFunctionReference_Kind: {
2529 FunctionReference* ref = (FunctionReference*) functionValue.get();
2530 int bestCost = INT_MAX;
2531 const FunctionDeclaration* best = nullptr;
2532 if (ref->fFunctions.size() > 1) {
2533 for (const auto& f : ref->fFunctions) {
2534 int cost = this->callCost(*f, arguments);
2535 if (cost < bestCost) {
2536 bestCost = cost;
2537 best = f;
2538 }
2539 }
2540 if (best) {
2541 return this->call(offset, *best, std::move(arguments));
2542 }
2543 String msg = "no match for " + ref->fFunctions[0]->fName + "(";
2544 String separator;
2545 for (size_t i = 0; i < arguments.size(); i++) {
2546 msg += separator;
2547 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002548 msg += arguments[i]->fType.displayName();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002549 }
2550 msg += ")";
2551 fErrors.error(offset, msg);
2552 return nullptr;
2553 }
2554 return this->call(offset, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002555 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002556 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002557 fErrors.error(offset, "not a function");
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002558 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002559 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002560}
2561
Ethan Nicholas84645e32017-02-09 13:57:14 -05002562std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002563 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002564 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07002565 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002566 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05002567 if (args.size() != 1) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002568 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002569 "' constructor, (expected exactly 1 argument, but found " +
2570 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07002571 return nullptr;
2572 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002573 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002574 return std::move(args[0]);
2575 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002576 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002577 double value = args[0]->as<FloatLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002578 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002579 }
2580 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002581 int64_t value = args[0]->as<IntLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002582 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002583 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002584 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
2585 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04002586 return std::unique_ptr<Expression>(new IntLiteral(offset,
John Stiles81365af2020-08-18 09:24:00 -04002587 args[0]->as<IntLiteral>().fValue,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002588 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002589 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002590 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002591 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
2592 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002593 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002594 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05002595 this->coerce(std::move(one), type),
2596 this->coerce(std::move(zero),
2597 type)));
2598 }
2599 if (!args[0]->fType.isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002600 fErrors.error(offset, "invalid argument to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002601 "' constructor (expected a number or bool, but found '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002602 args[0]->fType.displayName() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002603 return nullptr;
2604 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002605 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002606}
2607
John Stiles36374402020-08-13 12:16:44 -04002608static int component_count(const Type& type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002609 switch (type.kind()) {
2610 case Type::kVector_Kind:
2611 return type.columns();
2612 case Type::kMatrix_Kind:
2613 return type.columns() * type.rows();
2614 default:
2615 return 1;
2616 }
2617}
2618
2619std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002620 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002621 const Type& type,
2622 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002623 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05002624 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
2625 args[0]->fType.kind() == Type::kMatrix_Kind) {
2626 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002627 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002628 }
2629 int actual = 0;
2630 int expected = type.rows() * type.columns();
2631 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
2632 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07002633 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002634 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002635 if (type.componentType().isNumber() !=
2636 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002637 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2638 "parameter to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002639 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002640 return nullptr;
2641 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002642 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002643 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
2644 actual += 1;
2645 if (type.kind() != Type::kScalar_Kind) {
2646 args[i] = this->coerce(std::move(args[i]), type.componentType());
2647 if (!args[i]) {
2648 return nullptr;
2649 }
2650 }
2651 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002652 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2653 "parameter to '" + type.displayName() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002654 return nullptr;
2655 }
2656 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002657 if (actual != 1 && actual != expected) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002658 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002659 "' constructor (expected " + to_string(expected) +
2660 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002661 return nullptr;
2662 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002663 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002664 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002665}
2666
Ethan Nicholas84645e32017-02-09 13:57:14 -05002667std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002668 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002669 const Type& type,
2670 std::vector<std::unique_ptr<Expression>> args) {
2671 // FIXME: add support for structs
Brian Osman82329002020-07-21 09:39:27 -04002672 if (args.size() == 1 && args[0]->fType == type &&
2673 type.nonnullable() != *fContext.fFragmentProcessor_Type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002674 // argument is already the right type, just return it
2675 return std::move(args[0]);
2676 }
Brian Osman82329002020-07-21 09:39:27 -04002677 Type::Kind kind = type.kind();
Ethan Nicholas84645e32017-02-09 13:57:14 -05002678 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002679 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002680 } else if (kind == Type::kArray_Kind) {
2681 const Type& base = type.componentType();
2682 for (size_t i = 0; i < args.size(); i++) {
2683 args[i] = this->coerce(std::move(args[i]), base);
2684 if (!args[i]) {
2685 return nullptr;
2686 }
2687 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002688 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002689 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002690 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002691 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002692 fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002693 return nullptr;
2694 }
2695}
2696
Ethan Nicholasfc994162019-06-06 10:04:27 -04002697std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
2698 SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
2699 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -07002700 if (!base) {
2701 return nullptr;
2702 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002703 switch (expression.getToken().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002704 case Token::Kind::TK_PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05002705 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
2706 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002707 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002708 "'+' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002709 return nullptr;
2710 }
2711 return base;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002712 case Token::Kind::TK_MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07002713 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002714 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
John Stiles81365af2020-08-18 09:24:00 -04002715 -base->as<IntLiteral>().fValue));
ethannicholasb3058bd2016-07-01 08:22:01 -07002716 }
2717 if (base->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002718 double value = -base->as<FloatLiteral>().fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002719 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002720 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07002721 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05002722 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
2723 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002724 "'-' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholase1f55022019-02-05 17:17:40 -05002725 return nullptr;
2726 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002727 return std::unique_ptr<Expression>(new PrefixExpression(Token::Kind::TK_MINUS,
2728 std::move(base)));
2729 case Token::Kind::TK_PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07002730 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002731 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002732 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002733 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002734 return nullptr;
2735 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002736 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002737 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002738 case Token::Kind::TK_MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07002739 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002740 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002741 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002742 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002743 return nullptr;
2744 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002745 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002746 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002747 case Token::Kind::TK_LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07002748 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002749 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002750 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002751 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002752 return nullptr;
2753 }
ethannicholas08a92112016-11-09 13:26:45 -08002754 if (base->fKind == Expression::kBoolLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002755 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08002756 !((BoolLiteral&) *base).fValue));
2757 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002758 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002759 case Token::Kind::TK_BITWISENOT:
Brian Osman73fb39c2019-09-24 16:22:55 -04002760 if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002761 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002762 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002763 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholas5961bc92016-10-12 06:39:56 -07002764 return nullptr;
2765 }
2766 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002767 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07002768 ABORT("unsupported prefix operator\n");
2769 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002770 return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
ethannicholasb3058bd2016-07-01 08:22:01 -07002771 std::move(base)));
2772}
2773
2774std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002775 const ASTNode& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002776 if (base->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002777 if (index.fKind == ASTNode::Kind::kInt) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002778 const Type& oldType = ((TypeReference&) *base).fValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002779 SKSL_INT size = index.getInt();
John Stiles3ae071e2020-08-05 15:29:29 -04002780 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(
2781 std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]",
2782 Type::kArray_Kind, oldType, size));
2783 return std::make_unique<TypeReference>(fContext, base->fOffset, *newType);
Ethan Nicholas50afc172017-02-16 14:49:57 -05002784
2785 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002786 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05002787 return nullptr;
2788 }
2789 }
ethannicholas5961bc92016-10-12 06:39:56 -07002790 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
2791 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002792 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002793 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002794 return nullptr;
2795 }
2796 std::unique_ptr<Expression> converted = this->convertExpression(index);
2797 if (!converted) {
2798 return nullptr;
2799 }
ethannicholas5961bc92016-10-12 06:39:56 -07002800 if (converted->fType != *fContext.fUInt_Type) {
2801 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
2802 if (!converted) {
2803 return nullptr;
2804 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002805 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05002806 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07002807 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002808}
2809
2810std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002811 StringFragment field) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04002812 if (base->fKind == Expression::kExternalValue_Kind) {
John Stiles534d7992020-08-18 00:06:01 -04002813 const ExternalValue& ev = *((ExternalValueReference&) *base).fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002814 ExternalValue* result = ev.getChild(String(field).c_str());
2815 if (!result) {
2816 fErrors.error(base->fOffset, "external value does not have a child named '" + field +
2817 "'");
2818 return nullptr;
2819 }
2820 return std::unique_ptr<Expression>(new ExternalValueReference(base->fOffset, result));
2821 }
ethannicholasd598f792016-07-25 10:08:54 -07002822 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07002823 for (size_t i = 0; i < fields.size(); i++) {
2824 if (fields[i].fName == field) {
2825 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
2826 }
2827 }
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002828 fErrors.error(base->fOffset, "type '" + base->fType.displayName() + "' does not have a "
Brian Osmanb08cc022020-04-02 11:38:40 -04002829 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07002830 return nullptr;
2831}
2832
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002833// counts the number of chunks of contiguous 'x's in a swizzle, e.g. xxx1 has one and x0xx has two
John Stiles36374402020-08-13 12:16:44 -04002834static int count_contiguous_swizzle_chunks(const std::vector<int>& components) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002835 int chunkCount = 0;
2836 for (size_t i = 0; i < components.size(); ++i) {
2837 SkASSERT(components[i] <= 0);
2838 if (components[i] == 0) {
2839 ++chunkCount;
2840 while (i + 1 < components.size() && components[i + 1] == 0) {
2841 ++i;
2842 }
2843 }
2844 }
2845 return chunkCount;
2846}
2847
ethannicholasb3058bd2016-07-01 08:22:01 -07002848std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002849 StringFragment fields) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002850 if (base->fType.kind() != Type::kVector_Kind && !base->fType.isNumber()) {
2851 fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() +
2852 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002853 return nullptr;
2854 }
2855 std::vector<int> swizzleComponents;
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002856 size_t numLiteralFields = 0;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002857 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05002858 switch (fields[i]) {
Ethan Nicholasac285b12019-02-12 16:05:18 -05002859 case '0':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002860 swizzleComponents.push_back(SKSL_SWIZZLE_0);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002861 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002862 break;
2863 case '1':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002864 swizzleComponents.push_back(SKSL_SWIZZLE_1);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002865 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002866 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002867 case 'x':
2868 case 'r':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002869 case 's':
Ethan Nicholase455f652019-09-13 12:52:55 -04002870 case 'L':
ethannicholasb3058bd2016-07-01 08:22:01 -07002871 swizzleComponents.push_back(0);
2872 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002873 case 'y':
2874 case 'g':
ethannicholasb3058bd2016-07-01 08:22:01 -07002875 case 't':
Ethan Nicholase455f652019-09-13 12:52:55 -04002876 case 'T':
ethannicholasd598f792016-07-25 10:08:54 -07002877 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002878 swizzleComponents.push_back(1);
2879 break;
2880 }
John Stiles30212b72020-06-11 17:55:07 -04002881 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002882 case 'z':
2883 case 'b':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002884 case 'p':
Ethan Nicholase455f652019-09-13 12:52:55 -04002885 case 'R':
ethannicholasd598f792016-07-25 10:08:54 -07002886 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002887 swizzleComponents.push_back(2);
2888 break;
2889 }
John Stiles30212b72020-06-11 17:55:07 -04002890 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002891 case 'w':
2892 case 'a':
ethannicholasb3058bd2016-07-01 08:22:01 -07002893 case 'q':
Ethan Nicholase455f652019-09-13 12:52:55 -04002894 case 'B':
ethannicholasd598f792016-07-25 10:08:54 -07002895 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002896 swizzleComponents.push_back(3);
2897 break;
2898 }
John Stiles30212b72020-06-11 17:55:07 -04002899 [[fallthrough]];
ethannicholasb3058bd2016-07-01 08:22:01 -07002900 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002901 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
2902 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07002903 return nullptr;
2904 }
2905 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002906 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07002907 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002908 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002909 return nullptr;
2910 }
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002911 if (numLiteralFields == swizzleComponents.size()) {
2912 fErrors.error(base->fOffset, "swizzle must refer to base expression");
2913 return nullptr;
2914 }
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002915 if (base->fType.isNumber()) {
2916 // Swizzling a single scalar. Something like foo.x0x1 is equivalent to float4(foo, 0, foo,
2917 // 1)
2918 int offset = base->fOffset;
2919 std::unique_ptr<Expression> expr;
2920 switch (base->fKind) {
2921 case Expression::kVariableReference_Kind:
2922 case Expression::kFloatLiteral_Kind:
2923 case Expression::kIntLiteral_Kind:
2924 // the value being swizzled is just a constant or variable reference, so we can
2925 // safely re-use copies of it without reevaluation concerns
2926 expr = std::move(base);
2927 break;
2928 default:
2929 // It's a value we can't safely re-use multiple times. If it's all in one contiguous
2930 // chunk it's easy (e.g. foo.xxx0 can be turned into half4(half3(x), 0)), but
2931 // for multiple discontiguous chunks we'll need to copy it into a temporary value.
2932 int chunkCount = count_contiguous_swizzle_chunks(swizzleComponents);
2933 if (chunkCount <= 1) {
2934 // no copying needed, so we can just use the value directly
2935 expr = std::move(base);
2936 } else {
2937 // store the value in a temporary variable so we can re-use it
2938 int varIndex = fInlineVarCounter++;
2939 auto name = std::make_unique<String>();
2940 name->appendf("_tmpSwizzle%d", varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002941 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
2942 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
2943 std::make_unique<Variable>(offset,
2944 Modifiers(),
2945 namePtr->c_str(),
2946 base->fType,
2947 Variable::kLocal_Storage,
2948 base.get()));
Ethan Nicholasd2dc2062020-08-03 16:05:04 -04002949 expr = std::make_unique<VariableReference>(offset, *var);
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002950 std::vector<std::unique_ptr<VarDeclaration>> variables;
2951 variables.emplace_back(new VarDeclaration(var, {}, std::move(base)));
2952 fExtraStatements.emplace_back(new VarDeclarationsStatement(
2953 std::make_unique<VarDeclarations>(offset, &expr->fType,
2954 std::move(variables))));
2955 }
2956 }
2957 std::vector<std::unique_ptr<Expression>> args;
2958 for (size_t i = 0; i < swizzleComponents.size(); ++i) {
2959 switch (swizzleComponents[i]) {
2960 case 0: {
2961 args.push_back(expr->clone());
2962 int count = 1;
2963 while (i + 1 < swizzleComponents.size() && swizzleComponents[i + 1] == 0) {
2964 ++i;
2965 ++count;
2966 }
2967 if (count > 1) {
2968 std::vector<std::unique_ptr<Expression>> constructorArgs;
2969 constructorArgs.push_back(std::move(args.back()));
2970 args.pop_back();
2971 args.emplace_back(new Constructor(offset, expr->fType.toCompound(fContext,
2972 count,
2973 1),
2974 std::move(constructorArgs)));
2975 }
2976 break;
2977 }
2978 case SKSL_SWIZZLE_0:
2979 args.emplace_back(new IntLiteral(fContext, offset, 0));
2980 break;
2981 case SKSL_SWIZZLE_1:
2982 args.emplace_back(new IntLiteral(fContext, offset, 1));
2983 break;
2984 }
2985 }
2986 return std::unique_ptr<Expression>(new Constructor(offset,
2987 expr->fType.toCompound(
2988 fContext,
2989 swizzleComponents.size(),
2990 1),
2991 std::move(args)));
2992 }
ethannicholasd598f792016-07-25 10:08:54 -07002993 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07002994}
2995
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002996std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05002997 auto found = fCapsMap.find(name);
2998 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002999 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05003000 return nullptr;
3001 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04003002 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003003 return std::unique_ptr<Expression>(new Setting(offset, fullName,
3004 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04003005}
3006
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003007std::unique_ptr<Expression> IRGenerator::findEnumRef(
3008 int offset,
3009 const Type& type,
3010 StringFragment field,
3011 std::vector<std::unique_ptr<ProgramElement>>& elements) {
3012 for (const auto& e : elements) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003013 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
3014 std::shared_ptr<SymbolTable> old = fSymbolTable;
3015 fSymbolTable = ((Enum&) *e).fSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003016 std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset,
3017 ASTNode::Kind::kIdentifier,
3018 field));
3019 if (result) {
3020 SkASSERT(result->fKind == Expression::kVariableReference_Kind);
3021 const Variable& v = ((VariableReference&) *result).fVariable;
3022 SkASSERT(v.fInitialValue);
3023 SkASSERT(v.fInitialValue->fKind == Expression::kIntLiteral_Kind);
John Stilesfbd050b2020-08-03 13:21:46 -04003024 result = std::make_unique<IntLiteral>(
John Stiles81365af2020-08-18 09:24:00 -04003025 offset, v.fInitialValue->as<IntLiteral>().fValue, &type);
Ethan Nicholas9fdab9f2020-05-01 11:02:15 -04003026 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003027 fSymbolTable = old;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003028 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003029 }
3030 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003031 return nullptr;
3032}
3033
3034std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
3035 StringFragment field) {
3036 std::unique_ptr<Expression> result = this->findEnumRef(offset, type, field, *fProgramElements);
3037 if (fInherited && !result) {
3038 result = this->findEnumRef(offset, type, field, *fInherited);
3039 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003040 if (!result) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05003041 auto found = fIntrinsics->find(type.fName);
3042 if (found != fIntrinsics->end()) {
3043 SkASSERT(!found->second.second);
3044 found->second.second = true;
3045 fProgramElements->push_back(found->second.first->clone());
3046 return this->convertTypeField(offset, type, field);
3047 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003048 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
3049 "'");
3050 }
3051 return result;
3052}
3053
Ethan Nicholasfc994162019-06-06 10:04:27 -04003054std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
3055 SkASSERT(index.fKind == ASTNode::Kind::kIndex);
3056 auto iter = index.begin();
3057 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07003058 if (!base) {
3059 return nullptr;
3060 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003061 if (iter != index.end()) {
3062 return this->convertIndex(std::move(base), *(iter++));
3063 } else if (base->fKind == Expression::kTypeReference_Kind) {
3064 const Type& oldType = ((TypeReference&) *base).fValue;
John Stiles3ae071e2020-08-05 15:29:29 -04003065 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
3066 oldType.name() + "[]", Type::kArray_Kind, oldType, /*columns=*/-1));
Ethan Nicholasfc994162019-06-06 10:04:27 -04003067 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
3068 *newType));
ethannicholasb3058bd2016-07-01 08:22:01 -07003069 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003070 fErrors.error(index.fOffset, "'[]' must follow a type name");
3071 return nullptr;
3072}
3073
3074std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
3075 SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
3076 auto iter = callNode.begin();
3077 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
3078 if (!base) {
3079 return nullptr;
3080 }
3081 std::vector<std::unique_ptr<Expression>> arguments;
3082 for (; iter != callNode.end(); ++iter) {
3083 std::unique_ptr<Expression> converted = this->convertExpression(*iter);
3084 if (!converted) {
3085 return nullptr;
3086 }
3087 arguments.push_back(std::move(converted));
3088 }
3089 return this->call(callNode.fOffset, std::move(base), std::move(arguments));
3090}
3091
3092std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
3093 std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
3094 if (!base) {
3095 return nullptr;
3096 }
3097 StringFragment field = fieldNode.getString();
3098 if (base->fType == *fContext.fSkCaps_Type) {
3099 return this->getCap(fieldNode.fOffset, field);
3100 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003101 if (base->fKind == Expression::kTypeReference_Kind) {
3102 return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
3103 field);
3104 }
3105 if (base->fKind == Expression::kExternalValue_Kind) {
3106 return this->convertField(std::move(base), field);
3107 }
3108 switch (base->fType.kind()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04003109 case Type::kOther_Kind:
3110 case Type::kStruct_Kind:
3111 return this->convertField(std::move(base), field);
3112 default:
Ethan Nicholas7b9da252020-08-03 13:43:50 -04003113 return this->convertSwizzle(std::move(base), field);
Ethan Nicholasfc994162019-06-06 10:04:27 -04003114 }
3115}
3116
3117std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
3118 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
3119 if (!base) {
3120 return nullptr;
3121 }
3122 if (!base->fType.isNumber()) {
3123 fErrors.error(expression.fOffset,
3124 "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003125 "' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04003126 return nullptr;
3127 }
3128 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
3129 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
3130 expression.getToken().fKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07003131}
3132
3133void IRGenerator::checkValid(const Expression& expr) {
3134 switch (expr.fKind) {
3135 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003136 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07003137 break;
3138 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003139 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07003140 break;
3141 default:
ethannicholasea4567c2016-10-17 11:24:37 -07003142 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003143 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07003144 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003145 }
3146}
3147
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003148bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
ethannicholasb3058bd2016-07-01 08:22:01 -07003149 int bits = 0;
3150 for (int idx : swizzle.fComponents) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003151 if (idx < 0) {
3152 fErrors.error(swizzle.fOffset, "cannot write to a swizzle mask containing a constant");
3153 return false;
3154 }
3155 SkASSERT(idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07003156 int bit = 1 << idx;
3157 if (bits & bit) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003158 fErrors.error(swizzle.fOffset,
3159 "cannot write to the same swizzle field more than once");
3160 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003161 }
3162 bits |= bit;
3163 }
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003164 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07003165}
3166
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003167bool IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07003168 switch (expr.fKind) {
3169 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07003170 const Variable& var = ((VariableReference&) expr).fVariable;
Brian Osman3c358422020-03-23 10:44:12 -04003171 if (var.fModifiers.fFlags &
3172 (Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) {
3173 fErrors.error(expr.fOffset, "cannot modify immutable variable '" + var.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003174 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003175 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04003176 ((VariableReference&) expr).setRefKind(kind);
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003177 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07003178 }
3179 case Expression::kFieldAccess_Kind:
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003180 return this->setRefKind(*((FieldAccess&) expr).fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003181 case Expression::kSwizzle_Kind: {
3182 const Swizzle& swizzle = (Swizzle&) expr;
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003183 return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04003184 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003185 case Expression::kIndex_Kind:
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003186 return this->setRefKind(*((IndexExpression&) expr).fBase, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05003187 case Expression::kTernary_Kind: {
3188 TernaryExpression& t = (TernaryExpression&) expr;
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003189 return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05003190 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04003191 case Expression::kExternalValue_Kind: {
3192 const ExternalValue& v = *((ExternalValueReference&) expr).fValue;
3193 if (!v.canWrite()) {
3194 fErrors.error(expr.fOffset,
3195 "cannot modify immutable external value '" + v.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003196 return false;
Ethan Nicholas91164d12019-05-15 15:29:54 -04003197 }
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003198 return true;
Ethan Nicholas91164d12019-05-15 15:29:54 -04003199 }
ethannicholasb3058bd2016-07-01 08:22:01 -07003200 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003201 fErrors.error(expr.fOffset, "cannot assign to this expression");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04003202 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07003203 }
3204}
3205
Robert Phillipsfe8da172018-01-24 14:52:02 +00003206void IRGenerator::convertProgram(Program::Kind kind,
3207 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07003208 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003209 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00003210 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003211 fProgramElements = out;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003212 Parser parser(text, length, *fSymbolTable, fErrors);
Ethan Nicholasfc994162019-06-06 10:04:27 -04003213 fFile = parser.file();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003214 if (fErrors.errorCount()) {
3215 return;
3216 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04003217 this->pushSymbolTable(); // this is popped by Compiler upon completion
Ethan Nicholasfc994162019-06-06 10:04:27 -04003218 SkASSERT(fFile);
3219 for (const auto& decl : fFile->root()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003220 switch (decl.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04003221 case ASTNode::Kind::kVarDeclarations: {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003222 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04003223 decl,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003224 Variable::kGlobal_Storage);
3225 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003226 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003227 }
3228 break;
3229 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003230 case ASTNode::Kind::kEnum: {
3231 this->convertEnum(decl);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003232 break;
3233 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003234 case ASTNode::Kind::kFunction: {
3235 this->convertFunction(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003236 break;
3237 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003238 case ASTNode::Kind::kModifiers: {
3239 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003240 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003241 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003242 }
3243 break;
3244 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003245 case ASTNode::Kind::kInterfaceBlock: {
3246 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003247 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003248 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003249 }
3250 break;
3251 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003252 case ASTNode::Kind::kExtension: {
3253 std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
3254 decl.getString());
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003255 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003256 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003257 }
3258 break;
3259 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04003260 case ASTNode::Kind::kSection: {
3261 std::unique_ptr<Section> s = this->convertSection(decl);
Ethan Nicholas762466e2017-06-29 10:03:38 -04003262 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05003263 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04003264 }
3265 break;
3266 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003267 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003268#ifdef SK_DEBUG
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003269 ABORT("unsupported declaration: %s\n", decl.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05003270#endif
3271 break;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04003272 }
3273 }
3274}
3275
3276
John Stilesa6841be2020-08-06 14:11:56 -04003277} // namespace SkSL