blob: 8bc6fe044e4f2b44034e2938db513fe4671dcd48 [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 Stiles44e96be2020-08-31 13:16:04 -040011#include <iterator>
John Stilesfbd050b2020-08-03 13:21:46 -040012#include <memory>
Ethan Nicholasaf197692017-02-27 13:26:45 -050013#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070014
Ethan Nicholas6e0fa402020-08-20 14:08:23 -040015#include "src/sksl/SkSLAnalysis.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/sksl/SkSLCompiler.h"
17#include "src/sksl/SkSLParser.h"
Brian Osman3000d6b2020-07-31 15:57:28 -040018#include "src/sksl/SkSLUtil.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/sksl/ir/SkSLBinaryExpression.h"
20#include "src/sksl/ir/SkSLBoolLiteral.h"
21#include "src/sksl/ir/SkSLBreakStatement.h"
22#include "src/sksl/ir/SkSLConstructor.h"
23#include "src/sksl/ir/SkSLContinueStatement.h"
24#include "src/sksl/ir/SkSLDiscardStatement.h"
25#include "src/sksl/ir/SkSLDoStatement.h"
26#include "src/sksl/ir/SkSLEnum.h"
27#include "src/sksl/ir/SkSLExpressionStatement.h"
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040028#include "src/sksl/ir/SkSLExternalFunctionCall.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040029#include "src/sksl/ir/SkSLExternalValueReference.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/sksl/ir/SkSLField.h"
31#include "src/sksl/ir/SkSLFieldAccess.h"
32#include "src/sksl/ir/SkSLFloatLiteral.h"
33#include "src/sksl/ir/SkSLForStatement.h"
34#include "src/sksl/ir/SkSLFunctionCall.h"
35#include "src/sksl/ir/SkSLFunctionDeclaration.h"
36#include "src/sksl/ir/SkSLFunctionDefinition.h"
37#include "src/sksl/ir/SkSLFunctionReference.h"
38#include "src/sksl/ir/SkSLIfStatement.h"
39#include "src/sksl/ir/SkSLIndexExpression.h"
40#include "src/sksl/ir/SkSLIntLiteral.h"
41#include "src/sksl/ir/SkSLInterfaceBlock.h"
42#include "src/sksl/ir/SkSLLayout.h"
Chris Daltonb0fd4b12019-10-29 13:41:22 -060043#include "src/sksl/ir/SkSLNop.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050044#include "src/sksl/ir/SkSLNullLiteral.h"
45#include "src/sksl/ir/SkSLPostfixExpression.h"
46#include "src/sksl/ir/SkSLPrefixExpression.h"
47#include "src/sksl/ir/SkSLReturnStatement.h"
48#include "src/sksl/ir/SkSLSetting.h"
49#include "src/sksl/ir/SkSLSwitchCase.h"
50#include "src/sksl/ir/SkSLSwitchStatement.h"
51#include "src/sksl/ir/SkSLSwizzle.h"
52#include "src/sksl/ir/SkSLTernaryExpression.h"
53#include "src/sksl/ir/SkSLUnresolvedFunction.h"
54#include "src/sksl/ir/SkSLVarDeclarations.h"
55#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
56#include "src/sksl/ir/SkSLVariable.h"
57#include "src/sksl/ir/SkSLVariableReference.h"
58#include "src/sksl/ir/SkSLWhileStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070059
60namespace SkSL {
61
62class AutoSymbolTable {
63public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050064 AutoSymbolTable(IRGenerator* ir)
ethannicholasb3058bd2016-07-01 08:22:01 -070065 : fIR(ir)
66 , fPrevious(fIR->fSymbolTable) {
67 fIR->pushSymbolTable();
68 }
69
70 ~AutoSymbolTable() {
71 fIR->popSymbolTable();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040072 SkASSERT(fPrevious == fIR->fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -070073 }
74
75 IRGenerator* fIR;
76 std::shared_ptr<SymbolTable> fPrevious;
77};
78
ethannicholas22f939e2016-10-13 13:25:34 -070079class AutoLoopLevel {
80public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050081 AutoLoopLevel(IRGenerator* ir)
ethannicholas22f939e2016-10-13 13:25:34 -070082 : fIR(ir) {
83 fIR->fLoopLevel++;
84 }
85
86 ~AutoLoopLevel() {
87 fIR->fLoopLevel--;
88 }
89
90 IRGenerator* fIR;
91};
92
Ethan Nicholasaf197692017-02-27 13:26:45 -050093class AutoSwitchLevel {
94public:
95 AutoSwitchLevel(IRGenerator* ir)
96 : fIR(ir) {
97 fIR->fSwitchLevel++;
98 }
99
100 ~AutoSwitchLevel() {
101 fIR->fSwitchLevel--;
102 }
103
104 IRGenerator* fIR;
105};
106
John Stilesd1c4dac2020-08-11 18:50:50 -0400107class AutoDisableInline {
108public:
109 AutoDisableInline(IRGenerator* ir, bool canInline = false)
110 : fIR(ir) {
111 fOldCanInline = ir->fCanInline;
John Stiles46d17582020-08-12 11:48:48 -0400112 fIR->fCanInline &= canInline;
John Stilesd1c4dac2020-08-11 18:50:50 -0400113 }
114
115 ~AutoDisableInline() {
116 fIR->fCanInline = fOldCanInline;
117 }
118
119 IRGenerator* fIR;
120 bool fOldCanInline;
121};
122
John Stiles7b463002020-08-31 17:29:21 -0400123IRGenerator::IRGenerator(const Context* context, Inliner* inliner,
124 std::shared_ptr<SymbolTable> symbolTable, ErrorReporter& errorReporter)
125 : fContext(*context)
126 , fInliner(inliner)
127 , fCurrentFunction(nullptr)
128 , fRootSymbolTable(symbolTable)
129 , fSymbolTable(symbolTable)
130 , fLoopLevel(0)
131 , fSwitchLevel(0)
132 , fErrors(errorReporter) {
133 SkASSERT(fInliner);
134}
ethannicholasb3058bd2016-07-01 08:22:01 -0700135
136void IRGenerator::pushSymbolTable() {
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400137 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700138}
139
140void IRGenerator::popSymbolTable() {
141 fSymbolTable = fSymbolTable->fParent;
142}
143
Ethan Nicholas762466e2017-06-29 10:03:38 -0400144static void fill_caps(const SKSL_CAPS_CLASS& caps,
145 std::unordered_map<String, Program::Settings::Value>* capsMap) {
Brian Salomon23356442018-11-30 15:33:19 -0500146#define CAP(name) \
147 capsMap->insert(std::make_pair(String(#name), Program::Settings::Value(caps.name())))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500148 CAP(fbFetchSupport);
Brian Salomond4013302018-04-04 13:58:33 +0000149 CAP(fbFetchNeedsCustomOutput);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500150 CAP(flatInterpolationSupport);
151 CAP(noperspectiveInterpolationSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500152 CAP(externalTextureSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500153 CAP(mustEnableAdvBlendEqs);
154 CAP(mustEnableSpecificAdvBlendEqs);
155 CAP(mustDeclareFragmentShaderOutput);
Michael Ludwig4f94ef62018-09-12 15:22:16 -0400156 CAP(mustDoOpBetweenFloorAndAbs);
Brian Salomonf8c187c2019-12-19 14:41:57 -0500157 CAP(mustGuardDivisionEvenAfterExplicitZeroCheck);
158 CAP(inBlendModesFailRandomlyForAllZeroVec);
Michael Ludwig24d438b2018-09-12 15:22:50 -0400159 CAP(atan2ImplementedAsAtanYOverX);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500160 CAP(canUseAnyFunctionInShader);
Chris Dalton47c8ed32017-11-15 18:27:09 -0700161 CAP(floatIs32Bits);
Ethan Nicholas07990de2017-07-18 09:47:43 -0400162 CAP(integerSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500163#undef CAP
164}
165
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400166void IRGenerator::start(const Program::Settings* settings,
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400167 std::vector<std::unique_ptr<ProgramElement>>* inherited,
168 bool isBuiltinCode) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500169 fSettings = settings;
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400170 fInherited = inherited;
171 fIsBuiltinCode = isBuiltinCode;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500172 fCapsMap.clear();
173 if (settings->fCaps) {
174 fill_caps(*settings->fCaps, &fCapsMap);
Ethan Nicholas00543112018-07-31 09:44:36 -0400175 } else {
176 fCapsMap.insert(std::make_pair(String("integerSupport"),
177 Program::Settings::Value(true)));
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500178 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500179 this->pushSymbolTable();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400180 fInvocations = -1;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500181 fInputs.reset();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000182 fSkPerVertex = nullptr;
183 fRTAdjust = nullptr;
184 fRTAdjustInterfaceBlock = nullptr;
John Stiles44e96be2020-08-31 13:16:04 -0400185 fTmpSwizzleCounter = 0;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400186 if (inherited) {
187 for (const auto& e : *inherited) {
188 if (e->fKind == ProgramElement::kInterfaceBlock_Kind) {
John Stiles403a3632020-08-20 12:11:48 -0400189 InterfaceBlock& intf = e->as<InterfaceBlock>();
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400190 if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400191 SkASSERT(!fSkPerVertex);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400192 fSkPerVertex = &intf.fVariable;
193 }
194 }
195 }
196 }
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500197 SkASSERT(fIntrinsics);
198 for (auto& pair : *fIntrinsics) {
John Stiles810c8cf2020-08-26 19:46:27 -0400199 pair.second.fAlreadyIncluded = false;
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500200 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500201}
202
Ethan Nicholasfc994162019-06-06 10:04:27 -0400203std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragment name) {
Brian Osman16f376f2020-09-02 12:30:59 -0400204 if (fKind != Program::kFragment_Kind &&
205 fKind != Program::kVertex_Kind &&
206 fKind != Program::kGeometry_Kind) {
207 fErrors.error(offset, "extensions are not allowed here");
208 return nullptr;
209 }
210
John Stilesfbd050b2020-08-03 13:21:46 -0400211 return std::make_unique<Extension>(offset, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700212}
213
Ethan Nicholasfc994162019-06-06 10:04:27 -0400214void IRGenerator::finish() {
215 this->popSymbolTable();
216 fSettings = nullptr;
217}
218
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400219std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700220 switch (statement.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400221 case ASTNode::Kind::kBlock:
222 return this->convertBlock(statement);
223 case ASTNode::Kind::kVarDeclarations:
224 return this->convertVarDeclarationStatement(statement);
225 case ASTNode::Kind::kIf:
226 return this->convertIf(statement);
227 case ASTNode::Kind::kFor:
228 return this->convertFor(statement);
229 case ASTNode::Kind::kWhile:
230 return this->convertWhile(statement);
231 case ASTNode::Kind::kDo:
232 return this->convertDo(statement);
233 case ASTNode::Kind::kSwitch:
234 return this->convertSwitch(statement);
235 case ASTNode::Kind::kReturn:
236 return this->convertReturn(statement);
237 case ASTNode::Kind::kBreak:
238 return this->convertBreak(statement);
239 case ASTNode::Kind::kContinue:
240 return this->convertContinue(statement);
241 case ASTNode::Kind::kDiscard:
242 return this->convertDiscard(statement);
243 default:
244 // it's an expression
245 std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000246 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400247 SkASSERT(result->fKind == Statement::kExpression_Kind);
John Stiles403a3632020-08-20 12:11:48 -0400248 Expression& expr = *result->as<ExpressionStatement>().fExpression;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000249 if (expr.fKind == Expression::kFunctionCall_Kind) {
John Stiles403a3632020-08-20 12:11:48 -0400250 FunctionCall& fc = expr.as<FunctionCall>();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000251 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
252 std::vector<std::unique_ptr<Statement>> statements;
253 statements.push_back(getNormalizeSkPositionCode());
254 statements.push_back(std::move(result));
John Stilesfbd050b2020-08-03 13:21:46 -0400255 return std::make_unique<Block>(statement.fOffset, std::move(statements),
256 fSymbolTable);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000257 }
258 }
259 }
260 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700261 }
262}
263
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400264std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
265 std::vector<std::unique_ptr<Statement>> oldExtraStatements = std::move(fExtraStatements);
266 std::unique_ptr<Statement> result = this->convertSingleStatement(statement);
267 if (!result) {
268 fExtraStatements = std::move(oldExtraStatements);
269 return nullptr;
270 }
271 if (fExtraStatements.size()) {
272 fExtraStatements.push_back(std::move(result));
273 std::unique_ptr<Statement> block(new Block(-1, std::move(fExtraStatements), nullptr,
274 false));
275 fExtraStatements = std::move(oldExtraStatements);
276 return block;
277 }
278 fExtraStatements = std::move(oldExtraStatements);
279 return result;
280}
281
Ethan Nicholasfc994162019-06-06 10:04:27 -0400282std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
283 SkASSERT(block.fKind == ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -0700284 AutoSymbolTable table(this);
285 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400286 for (const auto& child : block) {
287 std::unique_ptr<Statement> statement = this->convertStatement(child);
ethannicholasb3058bd2016-07-01 08:22:01 -0700288 if (!statement) {
289 return nullptr;
290 }
291 statements.push_back(std::move(statement));
292 }
John Stilesfbd050b2020-08-03 13:21:46 -0400293 return std::make_unique<Block>(block.fOffset, std::move(statements), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700294}
295
Ethan Nicholasfc994162019-06-06 10:04:27 -0400296std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
297 SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
298 auto decl = this->convertVarDeclarations(s, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700299 if (!decl) {
300 return nullptr;
301 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700302 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700303}
304
Ethan Nicholasfc994162019-06-06 10:04:27 -0400305std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNode& decls,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700306 Variable::Storage storage) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400307 SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
John Stilesf621e232020-08-25 13:33:02 -0400308 auto declarationsIter = decls.begin();
309 const Modifiers& modifiers = declarationsIter++->getModifiers();
310 const ASTNode& rawType = *(declarationsIter++);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000311 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400312 const Type* baseType = this->convertType(rawType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700313 if (!baseType) {
314 return nullptr;
315 }
Brian Osman82329002020-07-21 09:39:27 -0400316 if (baseType->nonnullable() == *fContext.fFragmentProcessor_Type &&
317 storage != Variable::kGlobal_Storage) {
318 fErrors.error(decls.fOffset,
319 "variables of type '" + baseType->displayName() + "' must be global");
320 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500321 if (fKind != Program::kFragmentProcessor_Kind) {
322 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
323 baseType->kind() == Type::Kind::kMatrix_Kind) {
324 fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
325 }
Brian Osman088913a2019-12-19 15:44:56 -0500326 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
327 (modifiers.fFlags & Modifiers::kUniform_Flag)) {
328 fErrors.error(decls.fOffset,
329 "'in uniform' variables only permitted within fragment processors");
330 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500331 if (modifiers.fLayout.fWhen.fLength) {
332 fErrors.error(decls.fOffset, "'when' is only permitted within fragment processors");
333 }
334 if (modifiers.fLayout.fFlags & Layout::kTracked_Flag) {
335 fErrors.error(decls.fOffset, "'tracked' is only permitted within fragment processors");
336 }
337 if (modifiers.fLayout.fCType != Layout::CType::kDefault) {
338 fErrors.error(decls.fOffset, "'ctype' is only permitted within fragment processors");
339 }
340 if (modifiers.fLayout.fKey) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400341 fErrors.error(decls.fOffset, "'key' is only permitted within fragment processors");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400342 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500343 }
Brian Osmana4b91692020-08-10 14:26:16 -0400344 if (fKind == Program::kPipelineStage_Kind) {
345 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
346 baseType->nonnullable() != *fContext.fFragmentProcessor_Type) {
347 fErrors.error(decls.fOffset, "'in' variables not permitted in runtime effects");
348 }
349 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500350 if (modifiers.fLayout.fKey && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
351 fErrors.error(decls.fOffset, "'key' is not permitted on 'uniform' variables");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400352 }
Brian Osmanf59a9612020-04-15 14:18:13 -0400353 if (modifiers.fLayout.fMarker.fLength) {
354 if (fKind != Program::kPipelineStage_Kind) {
355 fErrors.error(decls.fOffset, "'marker' is only permitted in runtime effects");
356 }
357 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
358 fErrors.error(decls.fOffset, "'marker' is only permitted on 'uniform' variables");
359 }
360 if (*baseType != *fContext.fFloat4x4_Type) {
361 fErrors.error(decls.fOffset, "'marker' is only permitted on float4x4 variables");
362 }
363 }
Brian Osmanb32d66b2020-04-30 17:12:03 -0400364 if (modifiers.fLayout.fFlags & Layout::kSRGBUnpremul_Flag) {
365 if (fKind != Program::kPipelineStage_Kind) {
366 fErrors.error(decls.fOffset, "'srgb_unpremul' is only permitted in runtime effects");
367 }
368 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
369 fErrors.error(decls.fOffset,
370 "'srgb_unpremul' is only permitted on 'uniform' variables");
371 }
372 auto validColorXformType = [](const Type& t) {
373 return t.kind() == Type::kVector_Kind && t.componentType().isFloat() &&
374 (t.columns() == 3 || t.columns() == 4);
375 };
376 if (!validColorXformType(*baseType) && !(baseType->kind() == Type::kArray_Kind &&
377 validColorXformType(baseType->componentType()))) {
378 fErrors.error(decls.fOffset,
379 "'srgb_unpremul' is only permitted on half3, half4, float3, or float4 "
380 "variables");
381 }
382 }
Brian Osman3c358422020-03-23 10:44:12 -0400383 if (modifiers.fFlags & Modifiers::kVarying_Flag) {
384 if (fKind != Program::kPipelineStage_Kind) {
385 fErrors.error(decls.fOffset, "'varying' is only permitted in runtime effects");
386 }
387 if (!baseType->isFloat() &&
388 !(baseType->kind() == Type::kVector_Kind && baseType->componentType().isFloat())) {
389 fErrors.error(decls.fOffset, "'varying' must be float scalar or vector");
390 }
391 }
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400392 int permitted = Modifiers::kConst_Flag;
393 if (storage == Variable::kGlobal_Storage) {
394 permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
395 Modifiers::kFlat_Flag | Modifiers::kVarying_Flag |
396 Modifiers::kNoPerspective_Flag | Modifiers::kPLS_Flag |
397 Modifiers::kPLSIn_Flag | Modifiers::kPLSOut_Flag |
398 Modifiers::kRestrict_Flag | Modifiers::kVolatile_Flag |
399 Modifiers::kReadOnly_Flag | Modifiers::kWriteOnly_Flag |
400 Modifiers::kCoherent_Flag | Modifiers::kBuffer_Flag;
401 }
402 this->checkModifiers(decls.fOffset, modifiers, permitted);
John Stilesf621e232020-08-25 13:33:02 -0400403 for (; declarationsIter != decls.end(); ++declarationsIter) {
404 const ASTNode& varDecl = *declarationsIter;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400405 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
406 (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
407 varDecl.getVarData().fName != "sk_FragColor") {
408 fErrors.error(varDecl.fOffset,
Ethan Nicholas6c942712018-03-16 09:45:11 -0400409 "out location=0, index=0 is reserved for sk_FragColor");
410 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400411 const ASTNode::VarData& varData = varDecl.getVarData();
ethannicholasd598f792016-07-25 10:08:54 -0700412 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700413 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400414 auto iter = varDecl.begin();
415 for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
416 const ASTNode& rawSize = *iter;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700417 if (rawSize) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400418 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700419 if (!size) {
420 return nullptr;
421 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700422 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500423 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700424 if (size->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -0400425 count = size->as<IntLiteral>().fValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700426 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700427 fErrors.error(size->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400428 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700429 }
430 name += "[" + to_string(count) + "]";
431 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400432 fErrors.error(size->fOffset, "array size must be specified");
433 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700434 }
John Stiles3ae071e2020-08-05 15:29:29 -0400435 type = fSymbolTable->takeOwnershipOfSymbol(
436 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700437 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700438 } else {
John Stiles3ae071e2020-08-05 15:29:29 -0400439 type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
440 type->name() + "[]", Type::kArray_Kind, *type, /*columns=*/-1));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700441 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700442 }
443 }
John Stilesfbd050b2020-08-03 13:21:46 -0400444 auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, *type,
445 storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000446 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400447 SkASSERT(!fRTAdjust);
448 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000449 fRTAdjust = var.get();
450 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700451 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400452 if (iter != varDecl.end()) {
453 value = this->convertExpression(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700454 if (!value) {
455 return nullptr;
456 }
ethannicholasd598f792016-07-25 10:08:54 -0700457 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500458 if (!value) {
459 return nullptr;
460 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400461 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500462 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700463 }
John Stilesce591b72020-08-27 11:47:30 -0400464 const Symbol* symbol = (*fSymbolTable)[var->fName];
465 if (symbol && storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor") {
466 // Already defined, ignore.
467 } else if (symbol && storage == Variable::kGlobal_Storage &&
468 symbol->fKind == Symbol::kVariable_Kind &&
469 symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) {
470 // Already defined, just update the modifiers.
471 symbol->as<Variable>().fModifiers = var->fModifiers;
ethannicholasf789b382016-08-03 12:43:36 -0700472 } else {
John Stilesce591b72020-08-27 11:47:30 -0400473 variables.emplace_back(std::make_unique<VarDeclaration>(var.get(), std::move(sizes),
474 std::move(value)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400475 StringFragment name = var->fName;
476 fSymbolTable->add(name, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700477 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700478 }
John Stilesfbd050b2020-08-03 13:21:46 -0400479 return std::make_unique<VarDeclarations>(decls.fOffset, baseType, std::move(variables));
ethannicholasb3058bd2016-07-01 08:22:01 -0700480}
481
Ethan Nicholasfc994162019-06-06 10:04:27 -0400482std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
Brian Osman16f376f2020-09-02 12:30:59 -0400483 if (fKind != Program::kFragment_Kind &&
484 fKind != Program::kVertex_Kind &&
485 fKind != Program::kGeometry_Kind) {
486 fErrors.error(m.fOffset, "layout qualifiers are not allowed here");
487 return nullptr;
488 }
489
Ethan Nicholasfc994162019-06-06 10:04:27 -0400490 SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
491 Modifiers modifiers = m.getModifiers();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400492 if (modifiers.fLayout.fInvocations != -1) {
Ethan Nicholasf06576b2019-04-03 15:45:25 -0400493 if (fKind != Program::kGeometry_Kind) {
494 fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
495 return nullptr;
496 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400497 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600498 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400499 modifiers.fLayout.fInvocations = -1;
John Stilesce591b72020-08-27 11:47:30 -0400500 const Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
501 invocationId.fModifiers.fFlags = 0;
502 invocationId.fModifiers.fLayout.fBuiltin = -1;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400503 if (modifiers.fLayout.description() == "") {
504 return nullptr;
505 }
506 }
507 }
508 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600509 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400510 modifiers.fLayout.fMaxVertices *= fInvocations;
511 }
John Stilesfbd050b2020-08-03 13:21:46 -0400512 return std::make_unique<ModifiersDeclaration>(modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700513}
514
John Stilesc0dd06d2020-09-02 12:45:22 -0400515static void ensure_scoped_blocks(Statement* stmt) {
516 // No changes necessary if this statement isn't actually a block.
517 if (stmt->fKind != Statement::kBlock_Kind) {
518 return;
519 }
520
521 Block& block = stmt->as<Block>();
522
523 // Occasionally, IR generation can lead to Blocks containing multiple statements, but no scope.
524 // If this block is used as the statement for a while/if/for, this isn't actually possible to
525 // represent textually; a scope must be added for the generated code to match the intent. In the
526 // case of Blocks nested inside other Blocks, we add the scope to the outermost block if needed.
527 // Zero-statement blocks have similar issues--if we don't represent the Block textually somehow,
528 // we run the risk of accidentally absorbing the following statement into our loop--so we also
529 // add a scope to these.
530 for (Block* nestedBlock = &block;; ) {
531 if (nestedBlock->fIsScope) {
532 // We found an explicit scope; all is well.
533 return;
534 }
535 if (nestedBlock->fStatements.size() != 1) {
536 // We found a block with multiple (or zero) statements, but no scope? Let's add a scope
537 // to the outermost block.
538 block.fIsScope = true;
539 return;
540 }
541 if (nestedBlock->fStatements[0]->fKind != Statement::kBlock_Kind) {
542 // This block has exactly one thing inside, and it's not another block. No need to scope
543 // it.
544 return;
545 }
546 // We have to go deeper.
547 nestedBlock = &nestedBlock->fStatements[0]->as<Block>();
548 }
549}
550
John Stilesad2319f2020-09-02 15:01:47 -0400551std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
552 SkASSERT(n.fKind == ASTNode::Kind::kIf);
553 auto iter = n.begin();
554 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
555 *fContext.fBool_Type);
556 if (!test) {
557 return nullptr;
558 }
559 std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
560 if (!ifTrue) {
561 return nullptr;
562 }
563 ensure_scoped_blocks(ifTrue.get());
564 std::unique_ptr<Statement> ifFalse;
565 if (iter != n.end()) {
566 ifFalse = this->convertStatement(*(iter++));
567 if (!ifFalse) {
568 return nullptr;
569 }
570 ensure_scoped_blocks(ifFalse.get());
571 }
572 if (test->fKind == Expression::kBoolLiteral_Kind) {
573 // static boolean value, fold down to a single branch
574 if (test->as<BoolLiteral>().fValue) {
575 return ifTrue;
576 } else if (ifFalse) {
577 return ifFalse;
578 } else {
579 // False & no else clause. Not an error, so don't return null!
John Stiles2ff97062020-09-02 15:02:01 -0400580 return std::make_unique<Nop>();
John Stilesad2319f2020-09-02 15:01:47 -0400581 }
582 }
583 return std::make_unique<IfStatement>(n.fOffset, n.getBool(),
584 std::move(test), std::move(ifTrue), std::move(ifFalse));
585}
586
Ethan Nicholasfc994162019-06-06 10:04:27 -0400587std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
588 SkASSERT(f.fKind == ASTNode::Kind::kFor);
ethannicholas22f939e2016-10-13 13:25:34 -0700589 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700590 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700591 std::unique_ptr<Statement> initializer;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400592 auto iter = f.begin();
593 if (*iter) {
594 initializer = this->convertStatement(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700595 if (!initializer) {
596 return nullptr;
597 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700598 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400599 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700600 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400601 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400602 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400603 test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
ethannicholas22f939e2016-10-13 13:25:34 -0700604 if (!test) {
605 return nullptr;
606 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400607
ethannicholasb3058bd2016-07-01 08:22:01 -0700608 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400609 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700610 std::unique_ptr<Expression> next;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400611 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400612 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400613 next = this->convertExpression(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700614 if (!next) {
615 return nullptr;
616 }
617 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700618 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400619 ++iter;
620 std::unique_ptr<Statement> statement = this->convertStatement(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700621 if (!statement) {
622 return nullptr;
623 }
John Stilesc0dd06d2020-09-02 12:45:22 -0400624 ensure_scoped_blocks(statement.get());
John Stilesd1c4dac2020-08-11 18:50:50 -0400625 return std::make_unique<ForStatement>(f.fOffset, std::move(initializer), std::move(test),
626 std::move(next), std::move(statement), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700627}
628
Ethan Nicholasfc994162019-06-06 10:04:27 -0400629std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
630 SkASSERT(w.fKind == ASTNode::Kind::kWhile);
ethannicholas22f939e2016-10-13 13:25:34 -0700631 AutoLoopLevel level(this);
John Stilesd1c4dac2020-08-11 18:50:50 -0400632 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400633 auto iter = w.begin();
John Stilesd1c4dac2020-08-11 18:50:50 -0400634 {
635 AutoDisableInline disableInline(this);
636 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
637 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700638 if (!test) {
639 return nullptr;
640 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400641 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700642 if (!statement) {
643 return nullptr;
644 }
John Stilesc0dd06d2020-09-02 12:45:22 -0400645 ensure_scoped_blocks(statement.get());
John Stilesd1c4dac2020-08-11 18:50:50 -0400646 return std::make_unique<WhileStatement>(w.fOffset, std::move(test), std::move(statement));
ethannicholasb3058bd2016-07-01 08:22:01 -0700647}
648
Ethan Nicholasfc994162019-06-06 10:04:27 -0400649std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
650 SkASSERT(d.fKind == ASTNode::Kind::kDo);
ethannicholas22f939e2016-10-13 13:25:34 -0700651 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400652 auto iter = d.begin();
653 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
654 if (!statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700655 return nullptr;
656 }
John Stilesc0dd06d2020-09-02 12:45:22 -0400657 ensure_scoped_blocks(statement.get());
John Stilesd1c4dac2020-08-11 18:50:50 -0400658 std::unique_ptr<Expression> test;
659 {
660 AutoDisableInline disableInline(this);
661 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
662 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400663 if (!test) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700664 return nullptr;
665 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400666 return std::make_unique<DoStatement>(d.fOffset, std::move(statement), std::move(test));
ethannicholasb3058bd2016-07-01 08:22:01 -0700667}
668
Ethan Nicholasfc994162019-06-06 10:04:27 -0400669std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
670 SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500671 AutoSwitchLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400672 auto iter = s.begin();
673 std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500674 if (!value) {
675 return nullptr;
676 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500677 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500678 value = this->coerce(std::move(value), *fContext.fInt_Type);
679 if (!value) {
680 return nullptr;
681 }
682 }
683 AutoSymbolTable table(this);
684 std::unordered_set<int> caseValues;
685 std::vector<std::unique_ptr<SwitchCase>> cases;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400686 for (; iter != s.end(); ++iter) {
687 const ASTNode& c = *iter;
688 SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500689 std::unique_ptr<Expression> caseValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400690 auto childIter = c.begin();
691 if (*childIter) {
692 caseValue = this->convertExpression(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500693 if (!caseValue) {
694 return nullptr;
695 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500696 caseValue = this->coerce(std::move(caseValue), value->fType);
697 if (!caseValue) {
698 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500699 }
Brian Osman3e3db6c2020-08-14 09:42:12 -0400700 int64_t v = 0;
701 if (!this->getConstantInt(*caseValue, &v)) {
702 fErrors.error(caseValue->fOffset, "case value must be a constant integer");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500703 return nullptr;
704 }
Ethan Nicholasaf197692017-02-27 13:26:45 -0500705 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700706 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500707 }
708 caseValues.insert(v);
709 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400710 ++childIter;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500711 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400712 for (; childIter != c.end(); ++childIter) {
713 std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500714 if (!converted) {
715 return nullptr;
716 }
717 statements.push_back(std::move(converted));
718 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400719 cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500720 std::move(statements)));
721 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400722 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400723 std::move(value), std::move(cases),
724 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500725}
726
Ethan Nicholasfc994162019-06-06 10:04:27 -0400727std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
728 std::unique_ptr<Expression> e = this->convertExpression(s);
ethannicholasb3058bd2016-07-01 08:22:01 -0700729 if (!e) {
730 return nullptr;
731 }
732 this->checkValid(*e);
733 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
734}
735
Ethan Nicholasfc994162019-06-06 10:04:27 -0400736std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
737 SkASSERT(r.fKind == ASTNode::Kind::kReturn);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400738 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000739 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400740 // 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 +0000741 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400742 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400743 if (r.begin() != r.end()) {
744 std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -0700745 if (!result) {
746 return nullptr;
747 }
ethannicholasd598f792016-07-25 10:08:54 -0700748 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700749 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700750 } else {
751 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
752 if (!result) {
753 return nullptr;
754 }
755 }
756 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
757 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700758 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700759 fErrors.error(r.fOffset, "expected function to return '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500760 fCurrentFunction->fReturnType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700761 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700762 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700763 }
764}
765
Ethan Nicholasfc994162019-06-06 10:04:27 -0400766std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
767 SkASSERT(b.fKind == ASTNode::Kind::kBreak);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500768 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700769 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700770 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700771 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700772 return nullptr;
773 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700774}
775
Ethan Nicholasfc994162019-06-06 10:04:27 -0400776std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
777 SkASSERT(c.fKind == ASTNode::Kind::kContinue);
ethannicholas22f939e2016-10-13 13:25:34 -0700778 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700779 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700780 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700781 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700782 return nullptr;
783 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700784}
785
Ethan Nicholasfc994162019-06-06 10:04:27 -0400786std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
787 SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700788 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700789}
790
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500791std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400792 Layout invokeLayout;
793 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
John Stilesb9af7232020-08-20 15:57:48 -0400794 const FunctionDeclaration* invokeDecl = fSymbolTable->add(
795 "_invoke", std::make_unique<FunctionDeclaration>(/*offset=*/-1,
796 invokeModifiers,
797 "_invoke",
798 std::vector<const Variable*>(),
799 *fContext.fVoid_Type,
800 /*builtin=*/false));
801 fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
802 *invokeDecl,
803 std::move(main)));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400804
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000805 std::vector<std::unique_ptr<VarDeclaration>> variables;
John Stilesb9af7232020-08-20 15:57:48 -0400806 const Variable* loopIdx = &(*fSymbolTable)["sk_InvocationID"]->as<Variable>();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700807 std::unique_ptr<Expression> test(new BinaryExpression(-1,
808 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400809 Token::Kind::TK_LT,
John Stilesfbd050b2020-08-03 13:21:46 -0400810 std::make_unique<IntLiteral>(fContext, -1, fInvocations),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400811 *fContext.fBool_Type));
812 std::unique_ptr<Expression> next(new PostfixExpression(
813 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700814 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400815 *loopIdx,
816 VariableReference::kReadWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400817 Token::Kind::TK_PLUSPLUS));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400818 ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400819 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400820 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400821
822 std::vector<std::unique_ptr<Statement>> loopBody;
823 std::vector<std::unique_ptr<Expression>> invokeArgs;
824 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700825 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400826 *invokeDecl,
827 std::vector<std::unique_ptr<Expression>>()))));
828 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700829 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400830 std::move(endPrimitive),
831 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700832 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400833 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx,
834 VariableReference::kWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400835 Token::Kind::TK_EQ,
John Stilesfbd050b2020-08-03 13:21:46 -0400836 std::make_unique<IntLiteral>(fContext, -1, 0),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400837 *fContext.fInt_Type));
838 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
839 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700840 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400841 std::move(initializer),
842 std::move(test),
843 std::move(next),
John Stilesfbd050b2020-08-03 13:21:46 -0400844 std::make_unique<Block>(-1, std::move(loopBody)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400845 fSymbolTable));
846 std::vector<std::unique_ptr<Statement>> children;
847 children.push_back(std::move(loop));
John Stilesfbd050b2020-08-03 13:21:46 -0400848 return std::make_unique<Block>(-1, std::move(children));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400849}
850
Robert Phillipsfe8da172018-01-24 14:52:02 +0000851std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400852 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000853 // 0,
854 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400855 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000856 #define REF(var) std::unique_ptr<Expression>(\
857 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400858 #define WREF(var) std::unique_ptr<Expression>(\
859 new VariableReference(-1, *var, VariableReference::kWrite_RefKind))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000860 #define FIELD(var, idx) std::unique_ptr<Expression>(\
861 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400862 #define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
Robert Phillipsfe8da172018-01-24 14:52:02 +0000863 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
864 #define ADJUST (fRTAdjustInterfaceBlock ? \
865 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
866 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400867 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
868 { __VA_ARGS__ }))
869 #define OP(left, op, right) std::unique_ptr<Expression>( \
870 new BinaryExpression(-1, left, op, right, \
871 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000872 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400873 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 0, 2)),
874 Token::Kind::TK_PLUS,
875 OP(SWIZZLE(POS, 3, 3), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000876 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
877 children.push_back(SWIZZLE(POS, 3));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400878 std::unique_ptr<Expression> result = OP(POS, Token::Kind::TK_EQ,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000879 std::unique_ptr<Expression>(new Constructor(-1,
880 *fContext.fFloat4_Type,
881 std::move(children))));
882 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
883}
884
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400885template<typename T>
886class AutoClear {
887public:
888 AutoClear(T* container)
889 : fContainer(container) {
890 SkASSERT(container->empty());
891 }
892
893 ~AutoClear() {
894 fContainer->clear();
895 }
896
897private:
898 T* fContainer;
899};
900
John Stilesb8e010c2020-08-11 18:05:39 -0400901template <typename T> AutoClear(T* c) -> AutoClear<T>;
902
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400903void IRGenerator::checkModifiers(int offset, const Modifiers& modifiers, int permitted) {
904 int flags = modifiers.fFlags;
905 #define CHECK(flag, name) \
906 if (!flags) return; \
907 if (flags & flag) { \
908 if (!(permitted & flag)) { \
909 fErrors.error(offset, "'" name "' is not permitted here"); \
910 } \
911 flags &= ~flag; \
912 }
913 CHECK(Modifiers::kConst_Flag, "const")
914 CHECK(Modifiers::kIn_Flag, "in")
915 CHECK(Modifiers::kOut_Flag, "out")
916 CHECK(Modifiers::kUniform_Flag, "uniform")
917 CHECK(Modifiers::kFlat_Flag, "flat")
918 CHECK(Modifiers::kNoPerspective_Flag, "noperspective")
919 CHECK(Modifiers::kReadOnly_Flag, "readonly")
920 CHECK(Modifiers::kWriteOnly_Flag, "writeonly")
921 CHECK(Modifiers::kCoherent_Flag, "coherent")
922 CHECK(Modifiers::kVolatile_Flag, "volatile")
923 CHECK(Modifiers::kRestrict_Flag, "restrict")
924 CHECK(Modifiers::kBuffer_Flag, "buffer")
925 CHECK(Modifiers::kHasSideEffects_Flag, "sk_has_side_effects")
926 CHECK(Modifiers::kPLS_Flag, "__pixel_localEXT")
927 CHECK(Modifiers::kPLSIn_Flag, "__pixel_local_inEXT")
928 CHECK(Modifiers::kPLSOut_Flag, "__pixel_local_outEXT")
929 CHECK(Modifiers::kVarying_Flag, "varying")
Ethan Nicholasf3c8f5d2020-08-20 13:09:14 +0000930 CHECK(Modifiers::kInline_Flag, "inline")
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400931 SkASSERT(flags == 0);
932}
933
Ethan Nicholasfc994162019-06-06 10:04:27 -0400934void IRGenerator::convertFunction(const ASTNode& f) {
John Stilesb8e010c2020-08-11 18:05:39 -0400935 AutoClear clear(&fReferencedIntrinsics);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400936 auto iter = f.begin();
937 const Type* returnType = this->convertType(*(iter++));
John Stilesb9af7232020-08-20 15:57:48 -0400938 if (returnType == nullptr) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400939 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700940 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400941 auto type_is_allowed = [&](const Type* t) {
942#if defined(SKSL_STANDALONE)
943 return true;
944#else
945 GrSLType unusedSLType;
946 return fKind != Program::kPipelineStage_Kind ||
947 type_to_grsltype(fContext, *t, &unusedSLType);
948#endif
949 };
950 if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type ||
951 !type_is_allowed(returnType)) {
Brian Osman82329002020-07-21 09:39:27 -0400952 fErrors.error(f.fOffset,
953 "functions may not return type '" + returnType->displayName() + "'");
954 return;
955 }
John Stilesb9af7232020-08-20 15:57:48 -0400956 const ASTNode::FunctionData& funcData = f.getFunctionData();
957 this->checkModifiers(f.fOffset, funcData.fModifiers, Modifiers::kHasSideEffects_Flag |
958 Modifiers::kInline_Flag);
ethannicholasd598f792016-07-25 10:08:54 -0700959 std::vector<const Variable*> parameters;
John Stilesb9af7232020-08-20 15:57:48 -0400960 for (size_t i = 0; i < funcData.fParameterCount; ++i) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400961 const ASTNode& param = *(iter++);
962 SkASSERT(param.fKind == ASTNode::Kind::kParameter);
963 ASTNode::ParameterData pd = param.getParameterData();
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400964 this->checkModifiers(param.fOffset, pd.fModifiers, Modifiers::kIn_Flag |
965 Modifiers::kOut_Flag);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400966 auto paramIter = param.begin();
967 const Type* type = this->convertType(*(paramIter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700968 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400969 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700970 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400971 for (int j = (int) pd.fSizeCount; j >= 1; j--) {
972 int size = (param.begin() + j)->getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400973 String name = type->name() + "[" + to_string(size) + "]";
John Stiles3ae071e2020-08-05 15:29:29 -0400974 type = fSymbolTable->takeOwnershipOfSymbol(
975 std::make_unique<Type>(std::move(name), Type::kArray_Kind, *type, size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700976 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400977 // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
978 if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
979 !type_is_allowed(type)) {
980 fErrors.error(param.fOffset,
981 "parameters of type '" + type->displayName() + "' not allowed");
982 return;
983 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400984 StringFragment name = pd.fName;
John Stiles3ae071e2020-08-05 15:29:29 -0400985 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
986 param.fOffset, pd.fModifiers, name, *type, Variable::kParameter_Storage));
ethannicholasd598f792016-07-25 10:08:54 -0700987 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700988 }
989
Brian Osman767f4442020-08-13 16:59:48 -0400990 auto paramIsCoords = [&](int idx) {
991 return parameters[idx]->fType == *fContext.fFloat2_Type &&
992 parameters[idx]->fModifiers.fFlags == 0;
993 };
Brian Osman767f4442020-08-13 16:59:48 -0400994
John Stilesb9af7232020-08-20 15:57:48 -0400995 if (funcData.fName == "main") {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400996 switch (fKind) {
997 case Program::kPipelineStage_Kind: {
Brian Osman767f4442020-08-13 16:59:48 -0400998 // half4 main() -or- half4 main(float2)
999 bool valid = (*returnType == *fContext.fHalf4_Type) &&
1000 ((parameters.size() == 0) ||
1001 (parameters.size() == 1 && paramIsCoords(0)));
1002 if (!valid) {
1003 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared "
1004 "half4 main() or half4 main(float2)");
1005 return;
1006 }
1007 break;
Brian Osman44820a92020-08-26 09:27:39 -04001008 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -04001009 case Program::kFragmentProcessor_Kind: {
Brian Osman44820a92020-08-26 09:27:39 -04001010 bool valid = (parameters.size() == 0) ||
1011 (parameters.size() == 1 && paramIsCoords(0));
Michael Ludwigfc2fdf02020-06-29 17:20:13 -04001012 if (!valid) {
1013 fErrors.error(f.fOffset, ".fp 'main' must be declared main() or main(float2)");
1014 return;
1015 }
1016 break;
1017 }
Ethan Nicholas746035a2019-04-23 13:31:09 -04001018 case Program::kGeneric_Kind:
Ethan Nicholas0d997662019-04-08 09:46:01 -04001019 break;
Ethan Nicholas0d997662019-04-08 09:46:01 -04001020 default:
1021 if (parameters.size()) {
1022 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
1023 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001024 }
1025 }
1026
ethannicholasb3058bd2016-07-01 08:22:01 -07001027 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -07001028 const FunctionDeclaration* decl = nullptr;
John Stilesb9af7232020-08-20 15:57:48 -04001029 const Symbol* entry = (*fSymbolTable)[funcData.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001030 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -07001031 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -07001032 switch (entry->fKind) {
1033 case Symbol::kUnresolvedFunction_Kind:
John Stiles17c5b702020-08-18 10:40:03 -04001034 functions = entry->as<UnresolvedFunction>().fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -07001035 break;
1036 case Symbol::kFunctionDeclaration_Kind:
John Stiles17c5b702020-08-18 10:40:03 -04001037 functions.push_back(&entry->as<FunctionDeclaration>());
ethannicholasb3058bd2016-07-01 08:22:01 -07001038 break;
1039 default:
John Stilesb9af7232020-08-20 15:57:48 -04001040 fErrors.error(f.fOffset, "symbol '" + funcData.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001041 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001042 }
John Stilesb9af7232020-08-20 15:57:48 -04001043 for (const FunctionDeclaration* other : functions) {
1044 SkASSERT(other->fName == funcData.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -07001045 if (parameters.size() == other->fParameters.size()) {
1046 bool match = true;
1047 for (size_t i = 0; i < parameters.size(); i++) {
1048 if (parameters[i]->fType != other->fParameters[i]->fType) {
1049 match = false;
1050 break;
1051 }
1052 }
1053 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -07001054 if (*returnType != other->fReturnType) {
John Stilesb9af7232020-08-20 15:57:48 -04001055 FunctionDeclaration newDecl(f.fOffset, funcData.fModifiers, funcData.fName,
1056 parameters, *returnType, fIsBuiltinCode);
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001057 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
1058 "' and '" + other->description() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001059 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001060 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001061 }
1062 decl = other;
1063 for (size_t i = 0; i < parameters.size(); i++) {
1064 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001065 fErrors.error(f.fOffset, "modifiers on parameter " +
1066 to_string((uint64_t) i + 1) +
John Stilesb9af7232020-08-20 15:57:48 -04001067 " differ between declaration and definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001068 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001069 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001070 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001071 if (other->fDefinition && !other->fBuiltin) {
John Stilesb9af7232020-08-20 15:57:48 -04001072 fErrors.error(f.fOffset, "duplicate definition of " + other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -07001073 }
1074 break;
1075 }
1076 }
1077 }
1078 }
1079 if (!decl) {
John Stilesb9af7232020-08-20 15:57:48 -04001080 // Conservatively assume all user-defined functions have side effects.
1081 Modifiers declModifiers = funcData.fModifiers;
1082 if (!fIsBuiltinCode) {
1083 declModifiers.fFlags |= Modifiers::kHasSideEffects_Flag;
1084 }
1085
1086 // Create a new declaration.
1087 decl = fSymbolTable->add(funcData.fName,
John Stiles311dd9d2020-08-13 17:09:29 -04001088 std::make_unique<FunctionDeclaration>(f.fOffset,
John Stilesb9af7232020-08-20 15:57:48 -04001089 declModifiers,
1090 funcData.fName,
John Stiles311dd9d2020-08-13 17:09:29 -04001091 parameters,
1092 *returnType,
1093 fIsBuiltinCode));
ethannicholasb3058bd2016-07-01 08:22:01 -07001094 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001095 if (iter != f.end()) {
1096 // compile body
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001097 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -07001098 fCurrentFunction = decl;
ethannicholasd598f792016-07-25 10:08:54 -07001099 std::shared_ptr<SymbolTable> old = fSymbolTable;
1100 AutoSymbolTable table(this);
Brian Osman44820a92020-08-26 09:27:39 -04001101 if (funcData.fName == "main" && (fKind == Program::kPipelineStage_Kind ||
1102 fKind == Program::kFragmentProcessor_Kind)) {
Brian Osman767f4442020-08-13 16:59:48 -04001103 if (parameters.size() == 1) {
1104 SkASSERT(paramIsCoords(0));
1105 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1106 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001107 }
ethannicholasd598f792016-07-25 10:08:54 -07001108 for (size_t i = 0; i < parameters.size(); i++) {
1109 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -07001110 }
John Stilesb9af7232020-08-20 15:57:48 -04001111 bool needInvocationIDWorkaround = fInvocations != -1 && funcData.fName == "main" &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -06001112 fSettings->fCaps &&
1113 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001114 std::unique_ptr<Block> body = this->convertBlock(*iter);
ethannicholasd598f792016-07-25 10:08:54 -07001115 fCurrentFunction = nullptr;
1116 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001117 return;
1118 }
1119 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001120 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -07001121 }
John Stilesb9af7232020-08-20 15:57:48 -04001122 if (Program::kVertex_Kind == fKind && funcData.fName == "main" && fRTAdjust) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00001123 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
1124 }
John Stilesb8e010c2020-08-11 18:05:39 -04001125 auto result = std::make_unique<FunctionDefinition>(f.fOffset, *decl, std::move(body),
1126 std::move(fReferencedIntrinsics));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001127 decl->fDefinition = result.get();
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001128 result->fSource = &f;
1129 fProgramElements->push_back(std::move(result));
ethannicholasb3058bd2016-07-01 08:22:01 -07001130 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001131}
1132
Ethan Nicholasfc994162019-06-06 10:04:27 -04001133std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
Brian Osman16f376f2020-09-02 12:30:59 -04001134 if (fKind != Program::kFragment_Kind &&
1135 fKind != Program::kVertex_Kind &&
1136 fKind != Program::kGeometry_Kind) {
1137 fErrors.error(intf.fOffset, "interface block is not allowed here");
1138 return nullptr;
1139 }
1140
Ethan Nicholasfc994162019-06-06 10:04:27 -04001141 SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
1142 ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
ethannicholasb3058bd2016-07-01 08:22:01 -07001143 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001144 this->pushSymbolTable();
1145 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001146 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001147 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +00001148 bool foundRTAdjust = false;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001149 auto iter = intf.begin();
1150 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
ethannicholas14fe8cc2016-09-07 13:37:16 -07001151 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04001152 *(iter++),
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001153 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -07001154 if (!decl) {
1155 return nullptr;
1156 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001157 for (const auto& stmt : decl->fVars) {
John Stiles403a3632020-08-20 12:11:48 -04001158 VarDeclaration& vd = stmt->as<VarDeclaration>();
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001159 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001160 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001161 "only the last entry in an interface block may be a runtime-sized "
1162 "array");
1163 }
Robert Phillipsfe8da172018-01-24 14:52:02 +00001164 if (vd.fVar == fRTAdjust) {
1165 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001166 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +00001167 fRTAdjustFieldIndex = fields.size();
1168 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001169 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
1170 &vd.fVar->fType));
1171 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001172 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001173 "initializers are not permitted on interface block fields");
1174 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001175 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
1176 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001177 haveRuntimeArray = true;
1178 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001179 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001180 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001181 this->popSymbolTable();
John Stiles3ae071e2020-08-05 15:29:29 -04001182 const Type* type =
1183 old->takeOwnershipOfSymbol(std::make_unique<Type>(intf.fOffset, id.fTypeName, fields));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001184 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001185 for (size_t i = 0; i < id.fSizeCount; ++i) {
1186 const ASTNode& size = *(iter++);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001187 if (size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001188 std::unique_ptr<Expression> converted = this->convertExpression(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001189 if (!converted) {
1190 return nullptr;
1191 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001192 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001193 int64_t count;
1194 if (converted->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001195 count = converted->as<IntLiteral>().fValue;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001196 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001197 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -04001198 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001199 }
1200 name += "[" + to_string(count) + "]";
1201 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001202 fErrors.error(intf.fOffset, "array size must be specified");
1203 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001204 }
John Stiles3ae071e2020-08-05 15:29:29 -04001205 type = symbols->takeOwnershipOfSymbol(
1206 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001207 sizes.push_back(std::move(converted));
1208 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001209 fErrors.error(intf.fOffset, "array size must be specified");
1210 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001211 }
1212 }
John Stiles3ae071e2020-08-05 15:29:29 -04001213 const Variable* var = old->takeOwnershipOfSymbol(
1214 std::make_unique<Variable>(intf.fOffset,
1215 id.fModifiers,
1216 id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
1217 *type,
1218 Variable::kGlobal_Storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +00001219 if (foundRTAdjust) {
1220 fRTAdjustInterfaceBlock = var;
1221 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001222 if (id.fInstanceName.fLength) {
1223 old->addWithoutOwnership(id.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -07001224 } else {
1225 for (size_t i = 0; i < fields.size(); i++) {
John Stilesfbd050b2020-08-03 13:21:46 -04001226 old->add(fields[i].fName, std::make_unique<Field>(intf.fOffset, *var, (int)i));
ethannicholasb3058bd2016-07-01 08:22:01 -07001227 }
1228 }
John Stilesfbd050b2020-08-03 13:21:46 -04001229 return std::make_unique<InterfaceBlock>(intf.fOffset,
1230 var,
1231 id.fTypeName,
1232 id.fInstanceName,
1233 std::move(sizes),
1234 symbols);
ethannicholasb3058bd2016-07-01 08:22:01 -07001235}
1236
Brian Osman3e3db6c2020-08-14 09:42:12 -04001237bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001238 switch (value.fKind) {
1239 case Expression::kIntLiteral_Kind:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001240 *out = static_cast<const IntLiteral&>(value).fValue;
1241 return true;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001242 case Expression::kVariableReference_Kind: {
Brian Osman3e3db6c2020-08-14 09:42:12 -04001243 const Variable& var = static_cast<const VariableReference&>(value).fVariable;
1244 return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
1245 var.fInitialValue &&
1246 this->getConstantInt(*var.fInitialValue, out);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001247 }
1248 default:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001249 return false;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001250 }
1251}
1252
Ethan Nicholasfc994162019-06-06 10:04:27 -04001253void IRGenerator::convertEnum(const ASTNode& e) {
Brian Osman16f376f2020-09-02 12:30:59 -04001254 if (fKind == Program::kPipelineStage_Kind) {
1255 fErrors.error(e.fOffset, "enum is not allowed here");
1256 return;
1257 }
1258
Ethan Nicholasfc994162019-06-06 10:04:27 -04001259 SkASSERT(e.fKind == ASTNode::Kind::kEnum);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001260 int64_t currentValue = 0;
1261 Layout layout;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001262 ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
1263 ASTNode::TypeData(e.getString(), false, false));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001264 const Type* type = this->convertType(enumType);
1265 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Brian Osman3e3db6c2020-08-14 09:42:12 -04001266 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001267 for (auto iter = e.begin(); iter != e.end(); ++iter) {
1268 const ASTNode& child = *iter;
1269 SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001270 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001271 if (child.begin() != child.end()) {
1272 value = this->convertExpression(*child.begin());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001273 if (!value) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001274 return;
1275 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001276 if (!this->getConstantInt(*value, &currentValue)) {
1277 fErrors.error(value->fOffset, "enum value must be a constant integer");
1278 return;
1279 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001280 }
1281 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
1282 ++currentValue;
Brian Osman3e3db6c2020-08-14 09:42:12 -04001283 fSymbolTable->add(child.getString(),
1284 std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), *type,
1285 Variable::kGlobal_Storage, value.get()));
1286 fSymbolTable->takeOwnershipOfIRNode(std::move(value));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001287 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001288 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
1289 new Enum(e.fOffset, e.getString(), fSymbolTable, fIsBuiltinCode)));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001290}
1291
Ethan Nicholasfc994162019-06-06 10:04:27 -04001292const Type* IRGenerator::convertType(const ASTNode& type) {
1293 ASTNode::TypeData td = type.getTypeData();
1294 const Symbol* result = (*fSymbolTable)[td.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001295 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001296 if (td.fIsNullable) {
John Stiles17c5b702020-08-18 10:40:03 -04001297 if (result->as<Type>() == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001298 if (type.begin() != type.end()) {
1299 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001300 "an array");
1301 }
John Stiles3ae071e2020-08-05 15:29:29 -04001302 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
John Stiles17c5b702020-08-18 10:40:03 -04001303 String(result->fName) + "?", Type::kNullable_Kind, result->as<Type>()));
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001304 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001305 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001306 }
1307 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001308 for (const auto& size : type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001309 String name(result->fName);
1310 name += "[";
Ethan Nicholasfc994162019-06-06 10:04:27 -04001311 if (size) {
1312 name += to_string(size.getInt());
Ethan Nicholas50afc172017-02-16 14:49:57 -05001313 }
1314 name += "]";
John Stiles3ae071e2020-08-05 15:29:29 -04001315 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
John Stiles17c5b702020-08-18 10:40:03 -04001316 name, Type::kArray_Kind, result->as<Type>(), size ? size.getInt() : 0));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001317 }
John Stiles17c5b702020-08-18 10:40:03 -04001318 return &result->as<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -07001319 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001320 fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001321 return nullptr;
1322}
1323
Ethan Nicholasfc994162019-06-06 10:04:27 -04001324std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001325 switch (expr.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001326 case ASTNode::Kind::kBinary:
1327 return this->convertBinaryExpression(expr);
1328 case ASTNode::Kind::kBool:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001329 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001330 expr.getBool()));
1331 case ASTNode::Kind::kCall:
1332 return this->convertCallExpression(expr);
1333 case ASTNode::Kind::kField:
1334 return this->convertFieldExpression(expr);
1335 case ASTNode::Kind::kFloat:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001336 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001337 expr.getFloat()));
1338 case ASTNode::Kind::kIdentifier:
1339 return this->convertIdentifier(expr);
1340 case ASTNode::Kind::kIndex:
1341 return this->convertIndexExpression(expr);
1342 case ASTNode::Kind::kInt:
1343 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
1344 expr.getInt()));
1345 case ASTNode::Kind::kNull:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001346 return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001347 case ASTNode::Kind::kPostfix:
1348 return this->convertPostfixExpression(expr);
1349 case ASTNode::Kind::kPrefix:
1350 return this->convertPrefixExpression(expr);
1351 case ASTNode::Kind::kTernary:
1352 return this->convertTernaryExpression(expr);
ethannicholasb3058bd2016-07-01 08:22:01 -07001353 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001354#ifdef SK_DEBUG
Ethan Nicholasfc994162019-06-06 10:04:27 -04001355 ABORT("unsupported expression: %s\n", expr.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001356#endif
1357 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001358 }
1359}
1360
Ethan Nicholasfc994162019-06-06 10:04:27 -04001361std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
1362 SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
1363 const Symbol* result = (*fSymbolTable)[identifier.getString()];
ethannicholasb3058bd2016-07-01 08:22:01 -07001364 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001365 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001366 return nullptr;
1367 }
1368 switch (result->fKind) {
1369 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001370 std::vector<const FunctionDeclaration*> f = {
John Stiles17c5b702020-08-18 10:40:03 -04001371 &result->as<FunctionDeclaration>()
ethannicholasb3058bd2016-07-01 08:22:01 -07001372 };
John Stilesfbd050b2020-08-03 13:21:46 -04001373 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001374 }
1375 case Symbol::kUnresolvedFunction_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001376 const UnresolvedFunction* f = &result->as<UnresolvedFunction>();
John Stilesfbd050b2020-08-03 13:21:46 -04001377 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
ethannicholasb3058bd2016-07-01 08:22:01 -07001378 }
1379 case Symbol::kVariable_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001380 const Variable* var = &result->as<Variable>();
Ethan Nicholascd700e92018-08-24 16:43:57 -04001381 switch (var->fModifiers.fLayout.fBuiltin) {
1382 case SK_WIDTH_BUILTIN:
1383 fInputs.fRTWidth = true;
1384 break;
1385 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001386 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001387 break;
1388#ifndef SKSL_STANDALONE
1389 case SK_FRAGCOORD_BUILTIN:
Brian Osman9f313b62019-10-02 12:03:11 -04001390 fInputs.fFlipY = true;
1391 if (fSettings->fFlipY &&
1392 (!fSettings->fCaps ||
1393 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1394 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001395 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001396#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001397 }
Ethan Nicholas33c59ed2019-08-13 10:21:38 -04001398 if (fKind == Program::kFragmentProcessor_Kind &&
1399 (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
1400 !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
1401 !var->fModifiers.fLayout.fKey &&
1402 var->fModifiers.fLayout.fBuiltin == -1 &&
1403 var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
1404 var->fType.kind() != Type::kSampler_Kind) {
1405 bool valid = false;
1406 for (const auto& decl : fFile->root()) {
1407 if (decl.fKind == ASTNode::Kind::kSection) {
1408 ASTNode::SectionData section = decl.getSectionData();
1409 if (section.fName == "setData") {
1410 valid = true;
1411 break;
1412 }
1413 }
1414 }
1415 if (!valid) {
1416 fErrors.error(identifier.fOffset, "'in' variable must be either 'uniform' or "
1417 "'layout(key)', or there must be a custom "
1418 "@setData function");
1419 }
1420 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001421 // default to kRead_RefKind; this will be corrected later if the variable is written to
John Stilesfbd050b2020-08-03 13:21:46 -04001422 return std::make_unique<VariableReference>(identifier.fOffset,
1423 *var,
1424 VariableReference::kRead_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001425 }
1426 case Symbol::kField_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001427 const Field* field = &result->as<Field>();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001428 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001429 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001430 return std::unique_ptr<Expression>(new FieldAccess(
1431 std::unique_ptr<Expression>(base),
1432 field->fFieldIndex,
1433 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001434 }
1435 case Symbol::kType_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001436 const Type* t = &result->as<Type>();
John Stilesfbd050b2020-08-03 13:21:46 -04001437 return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001438 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001439 case Symbol::kExternal_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001440 const ExternalValue* r = &result->as<ExternalValue>();
John Stilesfbd050b2020-08-03 13:21:46 -04001441 return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
Ethan Nicholas91164d12019-05-15 15:29:54 -04001442 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001443 default:
1444 ABORT("unsupported symbol type %d\n", result->fKind);
1445 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001446}
1447
Ethan Nicholasfc994162019-06-06 10:04:27 -04001448std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
Brian Osman16f376f2020-09-02 12:30:59 -04001449 if (fKind != Program::kFragmentProcessor_Kind) {
1450 fErrors.error(s.fOffset, "syntax error");
1451 return nullptr;
1452 }
1453
Ethan Nicholasfc994162019-06-06 10:04:27 -04001454 ASTNode::SectionData section = s.getSectionData();
John Stilesfbd050b2020-08-03 13:21:46 -04001455 return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument,
1456 section.fText);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001457}
1458
1459
Ethan Nicholas11d53972016-11-28 11:23:23 -05001460std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001461 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001462 if (!expr) {
1463 return nullptr;
1464 }
ethannicholasd598f792016-07-25 10:08:54 -07001465 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001466 return expr;
1467 }
1468 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001469 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001470 return nullptr;
1471 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001472 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001473 fErrors.error(expr->fOffset, "expected '" + type.displayName() + "', but found '" +
1474 expr->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001475 return nullptr;
1476 }
ethannicholasd598f792016-07-25 10:08:54 -07001477 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001478 std::vector<std::unique_ptr<Expression>> args;
1479 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001480 std::unique_ptr<Expression> ctor;
1481 if (type == *fContext.fFloatLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001482 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1483 "float"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001484 } else if (type == *fContext.fIntLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001485 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1486 "int"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001487 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001488 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1489 type.fName));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001490 }
1491 if (!ctor) {
1492 printf("error, null identifier: %s\n", String(type.fName).c_str());
1493 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001494 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001495 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001496 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001497 if (expr->fKind == Expression::kNullLiteral_Kind) {
1498 SkASSERT(type.kind() == Type::kNullable_Kind);
1499 return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
1500 }
ethannicholas5961bc92016-10-12 06:39:56 -07001501 std::vector<std::unique_ptr<Expression>> args;
1502 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001503 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001504}
1505
ethannicholasf789b382016-08-03 12:43:36 -07001506static bool is_matrix_multiply(const Type& left, const Type& right) {
1507 if (left.kind() == Type::kMatrix_Kind) {
1508 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1509 }
1510 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1511}
ethannicholasea4567c2016-10-17 11:24:37 -07001512
ethannicholasb3058bd2016-07-01 08:22:01 -07001513/**
1514 * Determines the operand and result types of a binary expression. Returns true if the expression is
1515 * legal, false otherwise. If false, the values of the out parameters are undefined.
1516 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001517static bool determine_binary_type(const Context& context,
1518 Token::Kind op,
1519 const Type& left,
1520 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001521 const Type** outLeftType,
1522 const Type** outRightType,
1523 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001524 bool tryFlipped) {
1525 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001526 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001527 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001528 case Token::Kind::TK_EQ:
ethannicholasea4567c2016-10-17 11:24:37 -07001529 *outLeftType = &left;
1530 *outRightType = &left;
1531 *outResultType = &left;
1532 return right.canCoerceTo(left);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001533 case Token::Kind::TK_EQEQ: // fall through
1534 case Token::Kind::TK_NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001535 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001536 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001537 *outRightType = &left;
1538 *outResultType = context.fBool_Type.get();
1539 return true;
1540 } if (left.canCoerceTo(right)) {
1541 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001542 *outRightType = &right;
1543 *outResultType = context.fBool_Type.get();
1544 return true;
1545 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001546 return false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001547 case Token::Kind::TK_LT: // fall through
1548 case Token::Kind::TK_GT: // fall through
1549 case Token::Kind::TK_LTEQ: // fall through
1550 case Token::Kind::TK_GTEQ:
ethannicholasb3058bd2016-07-01 08:22:01 -07001551 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001552 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001553 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001554 case Token::Kind::TK_LOGICALOR: // fall through
1555 case Token::Kind::TK_LOGICALAND: // fall through
1556 case Token::Kind::TK_LOGICALXOR: // fall through
1557 case Token::Kind::TK_LOGICALOREQ: // fall through
1558 case Token::Kind::TK_LOGICALANDEQ: // fall through
1559 case Token::Kind::TK_LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001560 *outLeftType = context.fBool_Type.get();
1561 *outRightType = context.fBool_Type.get();
1562 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001563 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001564 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001565 case Token::Kind::TK_STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001566 if (left.kind() == Type::kScalar_Kind) {
1567 *outLeftType = &left;
1568 *outRightType = &left;
1569 *outResultType = &left;
1570 return right.canCoerceTo(left);
1571 }
John Stiles30212b72020-06-11 17:55:07 -04001572 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001573 case Token::Kind::TK_STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001574 if (is_matrix_multiply(left, right)) {
1575 // determine final component type
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001576 if (determine_binary_type(context, Token::Kind::TK_STAR, left.componentType(),
ethannicholasf789b382016-08-03 12:43:36 -07001577 right.componentType(), outLeftType, outRightType,
1578 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001579 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001580 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001581 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001582 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001583 int leftColumns = left.columns();
1584 int leftRows = left.rows();
1585 int rightColumns;
1586 int rightRows;
1587 if (right.kind() == Type::kVector_Kind) {
1588 // matrix * vector treats the vector as a column vector, so we need to
1589 // transpose it
1590 rightColumns = right.rows();
1591 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001592 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001593 } else {
1594 rightColumns = right.columns();
1595 rightRows = right.rows();
1596 }
1597 if (rightColumns > 1) {
1598 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1599 leftRows);
1600 } else {
1601 // result was a column vector, transpose it back to a row
1602 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1603 rightColumns);
1604 }
1605 return leftColumns == rightRows;
1606 } else {
1607 return false;
1608 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001609 }
ethannicholasea4567c2016-10-17 11:24:37 -07001610 isLogical = false;
1611 validMatrixOrVectorOp = true;
1612 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001613 case Token::Kind::TK_PLUSEQ:
1614 case Token::Kind::TK_MINUSEQ:
1615 case Token::Kind::TK_SLASHEQ:
1616 case Token::Kind::TK_PERCENTEQ:
1617 case Token::Kind::TK_SHLEQ:
1618 case Token::Kind::TK_SHREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001619 if (left.kind() == Type::kScalar_Kind) {
1620 *outLeftType = &left;
1621 *outRightType = &left;
1622 *outResultType = &left;
1623 return right.canCoerceTo(left);
1624 }
John Stiles30212b72020-06-11 17:55:07 -04001625 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001626 case Token::Kind::TK_PLUS: // fall through
1627 case Token::Kind::TK_MINUS: // fall through
1628 case Token::Kind::TK_SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001629 isLogical = false;
1630 validMatrixOrVectorOp = true;
1631 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001632 case Token::Kind::TK_COMMA:
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001633 *outLeftType = &left;
1634 *outRightType = &right;
1635 *outResultType = &right;
1636 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001637 default:
1638 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001639 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001640 }
ethannicholasea4567c2016-10-17 11:24:37 -07001641 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001642 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1643 right.canCoerceTo(left)) {
1644 if (left.priority() > right.priority()) {
1645 *outLeftType = &left;
1646 *outRightType = &left;
1647 } else {
1648 *outLeftType = &right;
1649 *outRightType = &right;
1650 }
1651 if (isLogical) {
1652 *outResultType = context.fBool_Type.get();
1653 } else {
1654 *outResultType = &left;
1655 }
1656 return true;
1657 }
1658 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001659 *outLeftType = &left;
1660 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001661 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001662 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001663 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001664 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001665 }
1666 return true;
1667 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001668 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001669 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001670 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001671 outRightType, outResultType, false)) {
1672 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001673 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001674 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001675 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001676 }
1677 return true;
1678 }
1679 return false;
1680 }
1681 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001682 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001683 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001684 }
1685 return false;
1686}
1687
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001688static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1689 const Expression& left,
1690 Token::Kind op,
1691 const Expression& right) {
1692 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
John Stiles403a3632020-08-20 12:11:48 -04001693 bool leftVal = left.as<BoolLiteral>().fValue;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001694 if (op == Token::Kind::TK_LOGICALAND) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001695 // (true && expr) -> (expr) and (false && expr) -> (false)
1696 return leftVal ? right.clone()
1697 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001698 } else if (op == Token::Kind::TK_LOGICALOR) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001699 // (true || expr) -> (true) and (false || expr) -> (expr)
1700 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1701 : right.clone();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001702 } else if (op == Token::Kind::TK_LOGICALXOR) {
Noah Lavine334d0ba2019-12-18 23:03:49 -05001703 // (true ^^ expr) -> !(expr) and (false ^^ expr) -> (expr)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001704 return leftVal ? std::unique_ptr<Expression>(new PrefixExpression(
1705 Token::Kind::TK_LOGICALNOT,
1706 right.clone()))
Noah Lavine334d0ba2019-12-18 23:03:49 -05001707 : right.clone();
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001708 } else {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001709 return nullptr;
1710 }
1711}
1712
ethannicholas08a92112016-11-09 13:26:45 -08001713std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1714 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001715 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001716 // If the left side is a constant boolean literal, the right side does not need to be constant
1717 // for short circuit optimizations to allow the constant to be folded.
Brian Osmanb6b95732020-06-30 11:44:27 -04001718 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001719 return short_circuit_boolean(fContext, left, op, right);
Brian Osmanb6b95732020-06-30 11:44:27 -04001720 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001721 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1722 // (right OP left) for short-circuit optimizations
1723 return short_circuit_boolean(fContext, right, op, left);
1724 }
1725
1726 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Brian Osmanb6b95732020-06-30 11:44:27 -04001727 if (!left.isCompileTimeConstant() || !right.isCompileTimeConstant()) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001728 return nullptr;
1729 }
ethannicholas08a92112016-11-09 13:26:45 -08001730 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1731 // precision to calculate the results and hope the result makes sense. The plan is to move the
1732 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1733 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001734 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001735 right.fKind == Expression::kBoolLiteral_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04001736 bool leftVal = left.as<BoolLiteral>().fValue;
1737 bool rightVal = right.as<BoolLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001738 bool result;
1739 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001740 case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
1741 case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
1742 case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
ethannicholas08a92112016-11-09 13:26:45 -08001743 default: return nullptr;
1744 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001745 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001746 }
John Stilesfbd050b2020-08-03 13:21:46 -04001747 #define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1748 leftVal op rightVal)
1749 #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1750 (uint32_t) leftVal op \
1751 (uint32_t) rightVal)
ethannicholas08a92112016-11-09 13:26:45 -08001752 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001753 int64_t leftVal = left.as<IntLiteral>().fValue;
1754 int64_t rightVal = right.as<IntLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001755 switch (op) {
Ethan Nicholas66869e92020-04-30 09:27:54 -04001756 case Token::Kind::TK_PLUS: return URESULT(Int, +);
1757 case Token::Kind::TK_MINUS: return URESULT(Int, -);
1758 case Token::Kind::TK_STAR: return URESULT(Int, *);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001759 case Token::Kind::TK_SLASH:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001760 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1761 fErrors.error(right.fOffset, "arithmetic overflow");
1762 return nullptr;
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001763 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001764 if (!rightVal) {
1765 fErrors.error(right.fOffset, "division by zero");
1766 return nullptr;
1767 }
1768 return RESULT(Int, /);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001769 case Token::Kind::TK_PERCENT:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001770 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1771 fErrors.error(right.fOffset, "arithmetic overflow");
1772 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001773 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001774 if (!rightVal) {
1775 fErrors.error(right.fOffset, "division by zero");
1776 return nullptr;
1777 }
1778 return RESULT(Int, %);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001779 case Token::Kind::TK_BITWISEAND: return RESULT(Int, &);
1780 case Token::Kind::TK_BITWISEOR: return RESULT(Int, |);
1781 case Token::Kind::TK_BITWISEXOR: return RESULT(Int, ^);
1782 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1783 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1784 case Token::Kind::TK_GT: return RESULT(Bool, >);
1785 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1786 case Token::Kind::TK_LT: return RESULT(Bool, <);
1787 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1788 case Token::Kind::TK_SHL:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001789 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001790 return URESULT(Int, <<);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001791 }
1792 fErrors.error(right.fOffset, "shift value out of range");
1793 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001794 case Token::Kind::TK_SHR:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001795 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001796 return URESULT(Int, >>);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001797 }
1798 fErrors.error(right.fOffset, "shift value out of range");
1799 return nullptr;
1800
1801 default:
1802 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001803 }
1804 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001805 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001806 right.fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001807 double leftVal = left.as<FloatLiteral>().fValue;
1808 double rightVal = right.as<FloatLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001809 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001810 case Token::Kind::TK_PLUS: return RESULT(Float, +);
1811 case Token::Kind::TK_MINUS: return RESULT(Float, -);
1812 case Token::Kind::TK_STAR: return RESULT(Float, *);
1813 case Token::Kind::TK_SLASH:
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001814 if (rightVal) {
1815 return RESULT(Float, /);
1816 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001817 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001818 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001819 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1820 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1821 case Token::Kind::TK_GT: return RESULT(Bool, >);
1822 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1823 case Token::Kind::TK_LT: return RESULT(Bool, <);
1824 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1825 default: return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001826 }
1827 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001828 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001829 left.fType == right.fType) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001830 std::vector<std::unique_ptr<Expression>> args;
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001831 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1832 for (int i = 0; i < left.fType.columns(); i++) { \
1833 float value = left.getFVecComponent(i) op \
1834 right.getFVecComponent(i); \
1835 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
1836 } \
1837 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001838 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001839 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001840 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001841 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001842 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001843 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001844 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001845 !left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001846 case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1847 case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1848 case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1849 case Token::Kind::TK_SLASH:
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001850 for (int i = 0; i < left.fType.columns(); i++) {
1851 SKSL_FLOAT rvalue = right.getFVecComponent(i);
1852 if (rvalue == 0.0) {
1853 fErrors.error(right.fOffset, "division by zero");
1854 return nullptr;
1855 }
1856 float value = left.getFVecComponent(i) / rvalue;
1857 args.emplace_back(new FloatLiteral(fContext, -1, value));
1858 }
1859 return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
1860 std::move(args)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001861 default: return nullptr;
1862 }
1863 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001864 if (left.fType.kind() == Type::kMatrix_Kind &&
1865 right.fType.kind() == Type::kMatrix_Kind &&
1866 left.fKind == right.fKind) {
1867 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001868 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001869 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001870 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001871 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001872 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001873 !left.compareConstant(fContext, right)));
1874 default:
1875 return nullptr;
1876 }
1877 }
ethannicholas08a92112016-11-09 13:26:45 -08001878 #undef RESULT
1879 return nullptr;
1880}
1881
Ethan Nicholasfc994162019-06-06 10:04:27 -04001882std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
1883 SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
1884 auto iter = expression.begin();
1885 std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001886 if (!left) {
1887 return nullptr;
1888 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001889 Token::Kind op = expression.getToken().fKind;
John Stilesd1c4dac2020-08-11 18:50:50 -04001890 std::unique_ptr<Expression> right;
1891 {
1892 // Can't inline the right side of a short-circuiting boolean, because our inlining
1893 // approach runs things out of order.
1894 AutoDisableInline disableInline(this, /*canInline=*/(op != Token::Kind::TK_LOGICALAND &&
1895 op != Token::Kind::TK_LOGICALOR));
1896 right = this->convertExpression(*(iter++));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001897 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001898 if (!right) {
1899 return nullptr;
1900 }
ethannicholasd598f792016-07-25 10:08:54 -07001901 const Type* leftType;
1902 const Type* rightType;
1903 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001904 const Type* rawLeftType;
1905 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1906 rawLeftType = &right->fType;
1907 } else {
1908 rawLeftType = &left->fType;
1909 }
1910 const Type* rawRightType;
1911 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1912 rawRightType = &left->fType;
1913 } else {
1914 rawRightType = &right->fType;
1915 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001916 if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
1917 &resultType, !Compiler::IsAssignment(op))) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001918 fErrors.error(expression.fOffset, String("type mismatch: '") +
Ethan Nicholasfc994162019-06-06 10:04:27 -04001919 Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001920 "' cannot operate on '" + left->fType.displayName() +
1921 "', '" + right->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001922 return nullptr;
1923 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001924 if (Compiler::IsAssignment(op)) {
Ethan Nicholas4fadce42020-07-30 13:29:30 -04001925 if (!this->setRefKind(*left, op != Token::Kind::TK_EQ
1926 ? VariableReference::kReadWrite_RefKind
1927 : VariableReference::kWrite_RefKind)) {
1928 return nullptr;
1929 }
ethannicholasea4567c2016-10-17 11:24:37 -07001930 }
1931 left = this->coerce(std::move(left), *leftType);
1932 right = this->coerce(std::move(right), *rightType);
1933 if (!left || !right) {
1934 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001935 }
John Stilesa008b0f2020-08-16 08:48:02 -04001936 std::unique_ptr<Expression> result = this->constantFold(*left, op, *right);
ethannicholas08a92112016-11-09 13:26:45 -08001937 if (!result) {
John Stilesd1c4dac2020-08-11 18:50:50 -04001938 result = std::make_unique<BinaryExpression>(expression.fOffset, std::move(left), op,
1939 std::move(right), *resultType);
ethannicholas08a92112016-11-09 13:26:45 -08001940 }
1941 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001942}
1943
Ethan Nicholasfc994162019-06-06 10:04:27 -04001944std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
1945 SkASSERT(node.fKind == ASTNode::Kind::kTernary);
1946 auto iter = node.begin();
1947 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -07001948 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001949 if (!test) {
1950 return nullptr;
1951 }
John Stiles8fa3b4e2020-09-02 11:27:23 -04001952 std::unique_ptr<Expression> ifTrue;
1953 std::unique_ptr<Expression> ifFalse;
1954 {
1955 AutoDisableInline disableInline(this);
1956 ifTrue = this->convertExpression(*(iter++));
1957 if (!ifTrue) {
1958 return nullptr;
1959 }
1960 ifFalse = this->convertExpression(*(iter++));
1961 if (!ifFalse) {
1962 return nullptr;
1963 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001964 }
ethannicholasd598f792016-07-25 10:08:54 -07001965 const Type* trueType;
1966 const Type* falseType;
1967 const Type* resultType;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001968 if (!determine_binary_type(fContext, Token::Kind::TK_EQEQ, ifTrue->fType, ifFalse->fType,
1969 &trueType, &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001970 fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001971 ifTrue->fType.displayName() + "', '" +
1972 ifFalse->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001973 return nullptr;
1974 }
Brian Osman82329002020-07-21 09:39:27 -04001975 if (trueType->nonnullable() == *fContext.fFragmentProcessor_Type) {
1976 fErrors.error(node.fOffset,
1977 "ternary expression of type '" + trueType->displayName() + "' not allowed");
1978 return nullptr;
1979 }
ethannicholasd598f792016-07-25 10:08:54 -07001980 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001981 if (!ifTrue) {
1982 return nullptr;
1983 }
ethannicholasd598f792016-07-25 10:08:54 -07001984 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001985 if (!ifFalse) {
1986 return nullptr;
1987 }
ethannicholas08a92112016-11-09 13:26:45 -08001988 if (test->fKind == Expression::kBoolLiteral_Kind) {
1989 // static boolean test, just return one of the branches
John Stiles403a3632020-08-20 12:11:48 -04001990 if (test->as<BoolLiteral>().fValue) {
ethannicholas08a92112016-11-09 13:26:45 -08001991 return ifTrue;
1992 } else {
1993 return ifFalse;
1994 }
1995 }
John Stiles8fa3b4e2020-09-02 11:27:23 -04001996 return std::make_unique<TernaryExpression>(node.fOffset,
1997 std::move(test),
1998 std::move(ifTrue),
1999 std::move(ifFalse));
ethannicholasb3058bd2016-07-01 08:22:01 -07002000}
2001
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002002void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
2003 auto found = fIntrinsics->find(function.description());
John Stiles810c8cf2020-08-26 19:46:27 -04002004 if (found != fIntrinsics->end() && !found->second.fAlreadyIncluded) {
2005 found->second.fAlreadyIncluded = true;
2006 FunctionDefinition& original = found->second.fIntrinsic->as<FunctionDefinition>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002007 for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
2008 this->copyIntrinsicIfNeeded(*f);
2009 }
2010 fProgramElements->push_back(original.clone());
2011 }
2012}
2013
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002014std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002015 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07002016 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002017 if (function.fBuiltin) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002018 if (function.fDefinition) {
2019 fReferencedIntrinsics.insert(&function);
2020 }
2021 if (!fIsBuiltinCode) {
2022 this->copyIntrinsicIfNeeded(function);
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002023 }
2024 }
ethannicholasd598f792016-07-25 10:08:54 -07002025 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002026 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05002027 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07002028 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07002029 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002030 msg += "s";
2031 }
ethannicholas5961bc92016-10-12 06:39:56 -07002032 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002033 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07002034 return nullptr;
2035 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002036 if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
Brian Osman5f6b41e2020-03-09 11:53:24 -04002037 String msg = "call to undefined function '" + function.fName + "'";
2038 fErrors.error(offset, msg);
2039 return nullptr;
2040 }
ethannicholas471e8942016-10-28 09:02:46 -07002041 std::vector<const Type*> types;
2042 const Type* returnType;
2043 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04002044 String msg = "no match for " + function.fName + "(";
2045 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07002046 for (size_t i = 0; i < arguments.size(); i++) {
2047 msg += separator;
2048 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002049 msg += arguments[i]->fType.displayName();
ethannicholas471e8942016-10-28 09:02:46 -07002050 }
2051 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002052 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07002053 return nullptr;
2054 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002055 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07002056 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07002057 if (!arguments[i]) {
2058 return nullptr;
2059 }
ethannicholasd598f792016-07-25 10:08:54 -07002060 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002061 this->setRefKind(*arguments[i],
2062 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
2063 VariableReference::kReadWrite_RefKind :
2064 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002065 }
2066 }
John Stilesea9ab822020-08-31 09:55:04 -04002067
2068 auto funcCall = std::make_unique<FunctionCall>(offset, *returnType, function,
2069 std::move(arguments));
John Stiles7b463002020-08-31 17:29:21 -04002070 if (fCanInline && fInliner->isSafeToInline(*funcCall, fSettings->fInlineThreshold)) {
2071 Inliner::InlinedCall inlinedCall = fInliner->inlineCall(std::move(funcCall),
2072 fSymbolTable.get());
John Stiles39616ec2020-08-31 14:16:06 -04002073 if (inlinedCall.fInlinedBody) {
2074 fExtraStatements.push_back(std::move(inlinedCall.fInlinedBody));
2075 }
John Stiles44e96be2020-08-31 13:16:04 -04002076 return std::move(inlinedCall.fReplacementExpr);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002077 }
John Stiles8c91c932020-08-13 14:35:35 -04002078
John Stilesea9ab822020-08-31 09:55:04 -04002079 return std::move(funcCall);
ethannicholasb3058bd2016-07-01 08:22:01 -07002080}
2081
2082/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002083 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
2084 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
2085 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07002086 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002087int IRGenerator::callCost(const FunctionDeclaration& function,
2088 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07002089 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002090 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002091 }
2092 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07002093 std::vector<const Type*> types;
2094 const Type* ignored;
2095 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002096 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07002097 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002098 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002099 int cost = arguments[i]->coercionCost(*types[i]);
2100 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002101 total += cost;
2102 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002103 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002104 }
2105 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002106 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07002107}
2108
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002109std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002110 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07002111 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002112 switch (functionValue->fKind) {
2113 case Expression::kTypeReference_Kind:
2114 return this->convertConstructor(offset,
John Stiles403a3632020-08-20 12:11:48 -04002115 functionValue->as<TypeReference>().fValue,
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002116 std::move(arguments));
2117 case Expression::kExternalValue_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04002118 const ExternalValue* v = functionValue->as<ExternalValueReference>().fValue;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002119 if (!v->canCall()) {
2120 fErrors.error(offset, "this external value is not a function");
2121 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002122 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002123 int count = v->callParameterCount();
2124 if (count != (int) arguments.size()) {
2125 fErrors.error(offset, "external function expected " + to_string(count) +
2126 " arguments, but found " + to_string((int) arguments.size()));
2127 return nullptr;
2128 }
2129 static constexpr int PARAMETER_MAX = 16;
2130 SkASSERT(count < PARAMETER_MAX);
2131 const Type* types[PARAMETER_MAX];
2132 v->getCallParameterTypes(types);
2133 for (int i = 0; i < count; ++i) {
2134 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
2135 if (!arguments[i]) {
2136 return nullptr;
2137 }
2138 }
2139 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(),
2140 v, std::move(arguments)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002141 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002142 case Expression::kFunctionReference_Kind: {
John Stilesce591b72020-08-27 11:47:30 -04002143 const FunctionReference& ref = functionValue->as<FunctionReference>();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002144 int bestCost = INT_MAX;
2145 const FunctionDeclaration* best = nullptr;
John Stilesce591b72020-08-27 11:47:30 -04002146 if (ref.fFunctions.size() > 1) {
2147 for (const auto& f : ref.fFunctions) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002148 int cost = this->callCost(*f, arguments);
2149 if (cost < bestCost) {
2150 bestCost = cost;
2151 best = f;
2152 }
2153 }
2154 if (best) {
2155 return this->call(offset, *best, std::move(arguments));
2156 }
John Stilesce591b72020-08-27 11:47:30 -04002157 String msg = "no match for " + ref.fFunctions[0]->fName + "(";
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002158 String separator;
2159 for (size_t i = 0; i < arguments.size(); i++) {
2160 msg += separator;
2161 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002162 msg += arguments[i]->fType.displayName();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002163 }
2164 msg += ")";
2165 fErrors.error(offset, msg);
2166 return nullptr;
2167 }
John Stilesce591b72020-08-27 11:47:30 -04002168 return this->call(offset, *ref.fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002169 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002170 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002171 fErrors.error(offset, "not a function");
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002172 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002173 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002174}
2175
Ethan Nicholas84645e32017-02-09 13:57:14 -05002176std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002177 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002178 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07002179 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002180 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05002181 if (args.size() != 1) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002182 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002183 "' constructor, (expected exactly 1 argument, but found " +
2184 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07002185 return nullptr;
2186 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002187 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002188 return std::move(args[0]);
2189 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002190 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002191 double value = args[0]->as<FloatLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002192 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002193 }
2194 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002195 int64_t value = args[0]->as<IntLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002196 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002197 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002198 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
2199 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04002200 return std::unique_ptr<Expression>(new IntLiteral(offset,
John Stiles81365af2020-08-18 09:24:00 -04002201 args[0]->as<IntLiteral>().fValue,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002202 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002203 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002204 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002205 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
2206 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002207 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002208 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05002209 this->coerce(std::move(one), type),
2210 this->coerce(std::move(zero),
2211 type)));
2212 }
2213 if (!args[0]->fType.isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002214 fErrors.error(offset, "invalid argument to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002215 "' constructor (expected a number or bool, but found '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002216 args[0]->fType.displayName() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002217 return nullptr;
2218 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002219 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002220}
2221
John Stiles36374402020-08-13 12:16:44 -04002222static int component_count(const Type& type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002223 switch (type.kind()) {
2224 case Type::kVector_Kind:
2225 return type.columns();
2226 case Type::kMatrix_Kind:
2227 return type.columns() * type.rows();
2228 default:
2229 return 1;
2230 }
2231}
2232
2233std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002234 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002235 const Type& type,
2236 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002237 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05002238 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
2239 args[0]->fType.kind() == Type::kMatrix_Kind) {
2240 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002241 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002242 }
2243 int actual = 0;
2244 int expected = type.rows() * type.columns();
2245 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
2246 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07002247 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002248 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002249 if (type.componentType().isNumber() !=
2250 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002251 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2252 "parameter to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002253 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002254 return nullptr;
2255 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002256 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002257 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
2258 actual += 1;
2259 if (type.kind() != Type::kScalar_Kind) {
2260 args[i] = this->coerce(std::move(args[i]), type.componentType());
2261 if (!args[i]) {
2262 return nullptr;
2263 }
2264 }
2265 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002266 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2267 "parameter to '" + type.displayName() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002268 return nullptr;
2269 }
2270 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002271 if (actual != 1 && actual != expected) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002272 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002273 "' constructor (expected " + to_string(expected) +
2274 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002275 return nullptr;
2276 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002277 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002278 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002279}
2280
Ethan Nicholas84645e32017-02-09 13:57:14 -05002281std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002282 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002283 const Type& type,
2284 std::vector<std::unique_ptr<Expression>> args) {
2285 // FIXME: add support for structs
Brian Osman82329002020-07-21 09:39:27 -04002286 if (args.size() == 1 && args[0]->fType == type &&
2287 type.nonnullable() != *fContext.fFragmentProcessor_Type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002288 // argument is already the right type, just return it
2289 return std::move(args[0]);
2290 }
Brian Osman82329002020-07-21 09:39:27 -04002291 Type::Kind kind = type.kind();
Ethan Nicholas84645e32017-02-09 13:57:14 -05002292 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002293 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002294 } else if (kind == Type::kArray_Kind) {
2295 const Type& base = type.componentType();
2296 for (size_t i = 0; i < args.size(); i++) {
2297 args[i] = this->coerce(std::move(args[i]), base);
2298 if (!args[i]) {
2299 return nullptr;
2300 }
2301 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002302 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002303 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002304 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002305 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002306 fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002307 return nullptr;
2308 }
2309}
2310
Ethan Nicholasfc994162019-06-06 10:04:27 -04002311std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
2312 SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
2313 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -07002314 if (!base) {
2315 return nullptr;
2316 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002317 switch (expression.getToken().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002318 case Token::Kind::TK_PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05002319 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
2320 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002321 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002322 "'+' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002323 return nullptr;
2324 }
2325 return base;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002326 case Token::Kind::TK_MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07002327 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002328 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
John Stiles81365af2020-08-18 09:24:00 -04002329 -base->as<IntLiteral>().fValue));
ethannicholasb3058bd2016-07-01 08:22:01 -07002330 }
2331 if (base->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002332 double value = -base->as<FloatLiteral>().fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002333 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002334 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07002335 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05002336 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
2337 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002338 "'-' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholase1f55022019-02-05 17:17:40 -05002339 return nullptr;
2340 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002341 return std::unique_ptr<Expression>(new PrefixExpression(Token::Kind::TK_MINUS,
2342 std::move(base)));
2343 case Token::Kind::TK_PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07002344 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002345 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002346 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002347 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002348 return nullptr;
2349 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002350 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002351 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002352 case Token::Kind::TK_MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07002353 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002354 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002355 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002356 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002357 return nullptr;
2358 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002359 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002360 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002361 case Token::Kind::TK_LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07002362 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002363 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002364 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002365 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002366 return nullptr;
2367 }
ethannicholas08a92112016-11-09 13:26:45 -08002368 if (base->fKind == Expression::kBoolLiteral_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002369 return std::unique_ptr<Expression>(
2370 new BoolLiteral(fContext, base->fOffset, !base->as<BoolLiteral>().fValue));
ethannicholas08a92112016-11-09 13:26:45 -08002371 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002372 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002373 case Token::Kind::TK_BITWISENOT:
Brian Osman73fb39c2019-09-24 16:22:55 -04002374 if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002375 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002376 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002377 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholas5961bc92016-10-12 06:39:56 -07002378 return nullptr;
2379 }
2380 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002381 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07002382 ABORT("unsupported prefix operator\n");
2383 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002384 return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
ethannicholasb3058bd2016-07-01 08:22:01 -07002385 std::move(base)));
2386}
2387
2388std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002389 const ASTNode& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002390 if (base->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002391 if (index.fKind == ASTNode::Kind::kInt) {
John Stiles403a3632020-08-20 12:11:48 -04002392 const Type& oldType = base->as<TypeReference>().fValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002393 SKSL_INT size = index.getInt();
John Stiles3ae071e2020-08-05 15:29:29 -04002394 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(
2395 std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]",
2396 Type::kArray_Kind, oldType, size));
2397 return std::make_unique<TypeReference>(fContext, base->fOffset, *newType);
Ethan Nicholas50afc172017-02-16 14:49:57 -05002398
2399 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002400 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05002401 return nullptr;
2402 }
2403 }
ethannicholas5961bc92016-10-12 06:39:56 -07002404 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
2405 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002406 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002407 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002408 return nullptr;
2409 }
2410 std::unique_ptr<Expression> converted = this->convertExpression(index);
2411 if (!converted) {
2412 return nullptr;
2413 }
ethannicholas5961bc92016-10-12 06:39:56 -07002414 if (converted->fType != *fContext.fUInt_Type) {
2415 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
2416 if (!converted) {
2417 return nullptr;
2418 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002419 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05002420 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07002421 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002422}
2423
2424std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002425 StringFragment field) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04002426 if (base->fKind == Expression::kExternalValue_Kind) {
John Stiles17c5b702020-08-18 10:40:03 -04002427 const ExternalValue& ev = *base->as<ExternalValueReference>().fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002428 ExternalValue* result = ev.getChild(String(field).c_str());
2429 if (!result) {
2430 fErrors.error(base->fOffset, "external value does not have a child named '" + field +
2431 "'");
2432 return nullptr;
2433 }
2434 return std::unique_ptr<Expression>(new ExternalValueReference(base->fOffset, result));
2435 }
ethannicholasd598f792016-07-25 10:08:54 -07002436 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07002437 for (size_t i = 0; i < fields.size(); i++) {
2438 if (fields[i].fName == field) {
2439 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
2440 }
2441 }
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002442 fErrors.error(base->fOffset, "type '" + base->fType.displayName() + "' does not have a "
Brian Osmanb08cc022020-04-02 11:38:40 -04002443 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07002444 return nullptr;
2445}
2446
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002447// 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 -04002448static int count_contiguous_swizzle_chunks(const std::vector<int>& components) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002449 int chunkCount = 0;
2450 for (size_t i = 0; i < components.size(); ++i) {
2451 SkASSERT(components[i] <= 0);
2452 if (components[i] == 0) {
2453 ++chunkCount;
2454 while (i + 1 < components.size() && components[i + 1] == 0) {
2455 ++i;
2456 }
2457 }
2458 }
2459 return chunkCount;
2460}
2461
ethannicholasb3058bd2016-07-01 08:22:01 -07002462std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002463 StringFragment fields) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002464 if (base->fType.kind() != Type::kVector_Kind && !base->fType.isNumber()) {
2465 fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() +
2466 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002467 return nullptr;
2468 }
2469 std::vector<int> swizzleComponents;
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002470 size_t numLiteralFields = 0;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002471 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05002472 switch (fields[i]) {
Ethan Nicholasac285b12019-02-12 16:05:18 -05002473 case '0':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002474 swizzleComponents.push_back(SKSL_SWIZZLE_0);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002475 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002476 break;
2477 case '1':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002478 swizzleComponents.push_back(SKSL_SWIZZLE_1);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002479 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002480 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002481 case 'x':
2482 case 'r':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002483 case 's':
Ethan Nicholase455f652019-09-13 12:52:55 -04002484 case 'L':
ethannicholasb3058bd2016-07-01 08:22:01 -07002485 swizzleComponents.push_back(0);
2486 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002487 case 'y':
2488 case 'g':
ethannicholasb3058bd2016-07-01 08:22:01 -07002489 case 't':
Ethan Nicholase455f652019-09-13 12:52:55 -04002490 case 'T':
ethannicholasd598f792016-07-25 10:08:54 -07002491 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002492 swizzleComponents.push_back(1);
2493 break;
2494 }
John Stiles30212b72020-06-11 17:55:07 -04002495 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002496 case 'z':
2497 case 'b':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002498 case 'p':
Ethan Nicholase455f652019-09-13 12:52:55 -04002499 case 'R':
ethannicholasd598f792016-07-25 10:08:54 -07002500 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002501 swizzleComponents.push_back(2);
2502 break;
2503 }
John Stiles30212b72020-06-11 17:55:07 -04002504 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002505 case 'w':
2506 case 'a':
ethannicholasb3058bd2016-07-01 08:22:01 -07002507 case 'q':
Ethan Nicholase455f652019-09-13 12:52:55 -04002508 case 'B':
ethannicholasd598f792016-07-25 10:08:54 -07002509 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002510 swizzleComponents.push_back(3);
2511 break;
2512 }
John Stiles30212b72020-06-11 17:55:07 -04002513 [[fallthrough]];
ethannicholasb3058bd2016-07-01 08:22:01 -07002514 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002515 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
2516 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07002517 return nullptr;
2518 }
2519 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002520 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07002521 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002522 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002523 return nullptr;
2524 }
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002525 if (numLiteralFields == swizzleComponents.size()) {
2526 fErrors.error(base->fOffset, "swizzle must refer to base expression");
2527 return nullptr;
2528 }
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002529 if (base->fType.isNumber()) {
2530 // Swizzling a single scalar. Something like foo.x0x1 is equivalent to float4(foo, 0, foo,
2531 // 1)
2532 int offset = base->fOffset;
2533 std::unique_ptr<Expression> expr;
2534 switch (base->fKind) {
2535 case Expression::kVariableReference_Kind:
2536 case Expression::kFloatLiteral_Kind:
2537 case Expression::kIntLiteral_Kind:
2538 // the value being swizzled is just a constant or variable reference, so we can
2539 // safely re-use copies of it without reevaluation concerns
2540 expr = std::move(base);
2541 break;
2542 default:
2543 // It's a value we can't safely re-use multiple times. If it's all in one contiguous
2544 // chunk it's easy (e.g. foo.xxx0 can be turned into half4(half3(x), 0)), but
2545 // for multiple discontiguous chunks we'll need to copy it into a temporary value.
2546 int chunkCount = count_contiguous_swizzle_chunks(swizzleComponents);
2547 if (chunkCount <= 1) {
2548 // no copying needed, so we can just use the value directly
2549 expr = std::move(base);
2550 } else {
2551 // store the value in a temporary variable so we can re-use it
John Stiles44e96be2020-08-31 13:16:04 -04002552 int varIndex = fTmpSwizzleCounter++;
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002553 auto name = std::make_unique<String>();
2554 name->appendf("_tmpSwizzle%d", varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002555 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
2556 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
2557 std::make_unique<Variable>(offset,
2558 Modifiers(),
2559 namePtr->c_str(),
2560 base->fType,
2561 Variable::kLocal_Storage,
2562 base.get()));
Ethan Nicholasd2dc2062020-08-03 16:05:04 -04002563 expr = std::make_unique<VariableReference>(offset, *var);
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002564 std::vector<std::unique_ptr<VarDeclaration>> variables;
2565 variables.emplace_back(new VarDeclaration(var, {}, std::move(base)));
2566 fExtraStatements.emplace_back(new VarDeclarationsStatement(
2567 std::make_unique<VarDeclarations>(offset, &expr->fType,
2568 std::move(variables))));
2569 }
2570 }
2571 std::vector<std::unique_ptr<Expression>> args;
2572 for (size_t i = 0; i < swizzleComponents.size(); ++i) {
2573 switch (swizzleComponents[i]) {
2574 case 0: {
2575 args.push_back(expr->clone());
2576 int count = 1;
2577 while (i + 1 < swizzleComponents.size() && swizzleComponents[i + 1] == 0) {
2578 ++i;
2579 ++count;
2580 }
2581 if (count > 1) {
2582 std::vector<std::unique_ptr<Expression>> constructorArgs;
2583 constructorArgs.push_back(std::move(args.back()));
2584 args.pop_back();
2585 args.emplace_back(new Constructor(offset, expr->fType.toCompound(fContext,
2586 count,
2587 1),
2588 std::move(constructorArgs)));
2589 }
2590 break;
2591 }
2592 case SKSL_SWIZZLE_0:
2593 args.emplace_back(new IntLiteral(fContext, offset, 0));
2594 break;
2595 case SKSL_SWIZZLE_1:
2596 args.emplace_back(new IntLiteral(fContext, offset, 1));
2597 break;
2598 }
2599 }
2600 return std::unique_ptr<Expression>(new Constructor(offset,
2601 expr->fType.toCompound(
2602 fContext,
2603 swizzleComponents.size(),
2604 1),
2605 std::move(args)));
2606 }
ethannicholasd598f792016-07-25 10:08:54 -07002607 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07002608}
2609
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002610std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05002611 auto found = fCapsMap.find(name);
2612 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002613 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002614 return nullptr;
2615 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002616 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002617 return std::unique_ptr<Expression>(new Setting(offset, fullName,
2618 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002619}
2620
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002621std::unique_ptr<Expression> IRGenerator::findEnumRef(
2622 int offset,
2623 const Type& type,
2624 StringFragment field,
2625 std::vector<std::unique_ptr<ProgramElement>>& elements) {
2626 for (const auto& e : elements) {
John Stiles403a3632020-08-20 12:11:48 -04002627 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == e->as<Enum>().fTypeName) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002628 std::shared_ptr<SymbolTable> old = fSymbolTable;
John Stiles403a3632020-08-20 12:11:48 -04002629 fSymbolTable = e->as<Enum>().fSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002630 std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset,
2631 ASTNode::Kind::kIdentifier,
2632 field));
2633 if (result) {
John Stiles403a3632020-08-20 12:11:48 -04002634 const Variable& v = result->as<VariableReference>().fVariable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002635 SkASSERT(v.fInitialValue);
John Stilesfbd050b2020-08-03 13:21:46 -04002636 result = std::make_unique<IntLiteral>(
John Stiles81365af2020-08-18 09:24:00 -04002637 offset, v.fInitialValue->as<IntLiteral>().fValue, &type);
Ethan Nicholas9fdab9f2020-05-01 11:02:15 -04002638 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002639 fSymbolTable = old;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002640 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002641 }
2642 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002643 return nullptr;
2644}
2645
2646std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2647 StringFragment field) {
2648 std::unique_ptr<Expression> result = this->findEnumRef(offset, type, field, *fProgramElements);
2649 if (fInherited && !result) {
2650 result = this->findEnumRef(offset, type, field, *fInherited);
2651 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002652 if (!result) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002653 auto found = fIntrinsics->find(type.fName);
2654 if (found != fIntrinsics->end()) {
John Stiles810c8cf2020-08-26 19:46:27 -04002655 SkASSERT(!found->second.fAlreadyIncluded);
2656 found->second.fAlreadyIncluded = true;
2657 fProgramElements->push_back(found->second.fIntrinsic->clone());
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002658 return this->convertTypeField(offset, type, field);
2659 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002660 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2661 "'");
2662 }
2663 return result;
2664}
2665
Ethan Nicholasfc994162019-06-06 10:04:27 -04002666std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
2667 SkASSERT(index.fKind == ASTNode::Kind::kIndex);
2668 auto iter = index.begin();
2669 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07002670 if (!base) {
2671 return nullptr;
2672 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002673 if (iter != index.end()) {
2674 return this->convertIndex(std::move(base), *(iter++));
2675 } else if (base->fKind == Expression::kTypeReference_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002676 const Type& oldType = base->as<TypeReference>().fValue;
John Stiles3ae071e2020-08-05 15:29:29 -04002677 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
2678 oldType.name() + "[]", Type::kArray_Kind, oldType, /*columns=*/-1));
Ethan Nicholasfc994162019-06-06 10:04:27 -04002679 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
2680 *newType));
ethannicholasb3058bd2016-07-01 08:22:01 -07002681 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002682 fErrors.error(index.fOffset, "'[]' must follow a type name");
2683 return nullptr;
2684}
2685
2686std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
2687 SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
2688 auto iter = callNode.begin();
2689 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
2690 if (!base) {
2691 return nullptr;
2692 }
2693 std::vector<std::unique_ptr<Expression>> arguments;
2694 for (; iter != callNode.end(); ++iter) {
2695 std::unique_ptr<Expression> converted = this->convertExpression(*iter);
2696 if (!converted) {
2697 return nullptr;
2698 }
2699 arguments.push_back(std::move(converted));
2700 }
2701 return this->call(callNode.fOffset, std::move(base), std::move(arguments));
2702}
2703
2704std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
2705 std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
2706 if (!base) {
2707 return nullptr;
2708 }
2709 StringFragment field = fieldNode.getString();
2710 if (base->fType == *fContext.fSkCaps_Type) {
2711 return this->getCap(fieldNode.fOffset, field);
2712 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002713 if (base->fKind == Expression::kTypeReference_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002714 return this->convertTypeField(base->fOffset, base->as<TypeReference>().fValue,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002715 field);
2716 }
2717 if (base->fKind == Expression::kExternalValue_Kind) {
2718 return this->convertField(std::move(base), field);
2719 }
2720 switch (base->fType.kind()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002721 case Type::kOther_Kind:
2722 case Type::kStruct_Kind:
2723 return this->convertField(std::move(base), field);
2724 default:
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002725 return this->convertSwizzle(std::move(base), field);
Ethan Nicholasfc994162019-06-06 10:04:27 -04002726 }
2727}
2728
2729std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
2730 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
2731 if (!base) {
2732 return nullptr;
2733 }
2734 if (!base->fType.isNumber()) {
2735 fErrors.error(expression.fOffset,
2736 "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002737 "' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002738 return nullptr;
2739 }
2740 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
2741 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
2742 expression.getToken().fKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07002743}
2744
2745void IRGenerator::checkValid(const Expression& expr) {
2746 switch (expr.fKind) {
2747 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002748 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07002749 break;
2750 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002751 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07002752 break;
2753 default:
ethannicholasea4567c2016-10-17 11:24:37 -07002754 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002755 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07002756 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002757 }
2758}
2759
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002760bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002761 int bits = 0;
2762 for (int idx : swizzle.fComponents) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002763 if (idx < 0) {
2764 fErrors.error(swizzle.fOffset, "cannot write to a swizzle mask containing a constant");
2765 return false;
2766 }
2767 SkASSERT(idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07002768 int bit = 1 << idx;
2769 if (bits & bit) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002770 fErrors.error(swizzle.fOffset,
2771 "cannot write to the same swizzle field more than once");
2772 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002773 }
2774 bits |= bit;
2775 }
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002776 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002777}
2778
John Stiles403a3632020-08-20 12:11:48 -04002779bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002780 switch (expr.fKind) {
2781 case Expression::kVariableReference_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002782 const Variable& var = expr.as<VariableReference>().fVariable;
Brian Osman3c358422020-03-23 10:44:12 -04002783 if (var.fModifiers.fFlags &
2784 (Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) {
2785 fErrors.error(expr.fOffset, "cannot modify immutable variable '" + var.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002786 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002787 }
John Stiles403a3632020-08-20 12:11:48 -04002788 expr.as<VariableReference>().setRefKind(kind);
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002789 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002790 }
2791 case Expression::kFieldAccess_Kind:
John Stiles403a3632020-08-20 12:11:48 -04002792 return this->setRefKind(*expr.as<FieldAccess>().fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002793 case Expression::kSwizzle_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002794 const Swizzle& swizzle = expr.as<Swizzle>();
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002795 return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002796 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002797 case Expression::kIndex_Kind:
John Stiles403a3632020-08-20 12:11:48 -04002798 return this->setRefKind(*expr.as<IndexExpression>().fBase, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002799 case Expression::kTernary_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002800 const TernaryExpression& t = expr.as<TernaryExpression>();
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002801 return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002802 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04002803 case Expression::kExternalValue_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002804 const ExternalValue& v = *expr.as<ExternalValueReference>().fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002805 if (!v.canWrite()) {
2806 fErrors.error(expr.fOffset,
2807 "cannot modify immutable external value '" + v.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002808 return false;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002809 }
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002810 return true;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002811 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002812 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002813 fErrors.error(expr.fOffset, "cannot assign to this expression");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002814 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002815 }
2816}
2817
Robert Phillipsfe8da172018-01-24 14:52:02 +00002818void IRGenerator::convertProgram(Program::Kind kind,
2819 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002820 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002821 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00002822 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002823 fProgramElements = out;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002824 Parser parser(text, length, *fSymbolTable, fErrors);
Ethan Nicholasfc994162019-06-06 10:04:27 -04002825 fFile = parser.file();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002826 if (fErrors.errorCount()) {
2827 return;
2828 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002829 this->pushSymbolTable(); // this is popped by Compiler upon completion
Ethan Nicholasfc994162019-06-06 10:04:27 -04002830 SkASSERT(fFile);
2831 for (const auto& decl : fFile->root()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002832 switch (decl.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002833 case ASTNode::Kind::kVarDeclarations: {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002834 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04002835 decl,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002836 Variable::kGlobal_Storage);
2837 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002838 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002839 }
2840 break;
2841 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002842 case ASTNode::Kind::kEnum: {
2843 this->convertEnum(decl);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002844 break;
2845 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002846 case ASTNode::Kind::kFunction: {
2847 this->convertFunction(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002848 break;
2849 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002850 case ASTNode::Kind::kModifiers: {
2851 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002852 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002853 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002854 }
2855 break;
2856 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002857 case ASTNode::Kind::kInterfaceBlock: {
2858 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002859 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002860 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002861 }
2862 break;
2863 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002864 case ASTNode::Kind::kExtension: {
2865 std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
2866 decl.getString());
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002867 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002868 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002869 }
2870 break;
2871 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002872 case ASTNode::Kind::kSection: {
2873 std::unique_ptr<Section> s = this->convertSection(decl);
Ethan Nicholas762466e2017-06-29 10:03:38 -04002874 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002875 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002876 }
2877 break;
2878 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002879 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002880#ifdef SK_DEBUG
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002881 ABORT("unsupported declaration: %s\n", decl.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002882#endif
2883 break;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002884 }
2885 }
2886}
2887
2888
John Stilesa6841be2020-08-06 14:11:56 -04002889} // namespace SkSL