blob: ff0988dc331e0b1a8ccf4c8e604da2e1126f221c [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) {
John Stilesfbd050b2020-08-03 13:21:46 -0400204 return std::make_unique<Extension>(offset, name);
ethannicholasb3058bd2016-07-01 08:22:01 -0700205}
206
Ethan Nicholasfc994162019-06-06 10:04:27 -0400207void IRGenerator::finish() {
208 this->popSymbolTable();
209 fSettings = nullptr;
210}
211
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400212std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700213 switch (statement.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400214 case ASTNode::Kind::kBlock:
215 return this->convertBlock(statement);
216 case ASTNode::Kind::kVarDeclarations:
217 return this->convertVarDeclarationStatement(statement);
218 case ASTNode::Kind::kIf:
219 return this->convertIf(statement);
220 case ASTNode::Kind::kFor:
221 return this->convertFor(statement);
222 case ASTNode::Kind::kWhile:
223 return this->convertWhile(statement);
224 case ASTNode::Kind::kDo:
225 return this->convertDo(statement);
226 case ASTNode::Kind::kSwitch:
227 return this->convertSwitch(statement);
228 case ASTNode::Kind::kReturn:
229 return this->convertReturn(statement);
230 case ASTNode::Kind::kBreak:
231 return this->convertBreak(statement);
232 case ASTNode::Kind::kContinue:
233 return this->convertContinue(statement);
234 case ASTNode::Kind::kDiscard:
235 return this->convertDiscard(statement);
236 default:
237 // it's an expression
238 std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000239 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400240 SkASSERT(result->fKind == Statement::kExpression_Kind);
John Stiles403a3632020-08-20 12:11:48 -0400241 Expression& expr = *result->as<ExpressionStatement>().fExpression;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000242 if (expr.fKind == Expression::kFunctionCall_Kind) {
John Stiles403a3632020-08-20 12:11:48 -0400243 FunctionCall& fc = expr.as<FunctionCall>();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000244 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
245 std::vector<std::unique_ptr<Statement>> statements;
246 statements.push_back(getNormalizeSkPositionCode());
247 statements.push_back(std::move(result));
John Stilesfbd050b2020-08-03 13:21:46 -0400248 return std::make_unique<Block>(statement.fOffset, std::move(statements),
249 fSymbolTable);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000250 }
251 }
252 }
253 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700254 }
255}
256
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400257std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
258 std::vector<std::unique_ptr<Statement>> oldExtraStatements = std::move(fExtraStatements);
259 std::unique_ptr<Statement> result = this->convertSingleStatement(statement);
260 if (!result) {
261 fExtraStatements = std::move(oldExtraStatements);
262 return nullptr;
263 }
264 if (fExtraStatements.size()) {
265 fExtraStatements.push_back(std::move(result));
266 std::unique_ptr<Statement> block(new Block(-1, std::move(fExtraStatements), nullptr,
267 false));
268 fExtraStatements = std::move(oldExtraStatements);
269 return block;
270 }
271 fExtraStatements = std::move(oldExtraStatements);
272 return result;
273}
274
Ethan Nicholasfc994162019-06-06 10:04:27 -0400275std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
276 SkASSERT(block.fKind == ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -0700277 AutoSymbolTable table(this);
278 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400279 for (const auto& child : block) {
280 std::unique_ptr<Statement> statement = this->convertStatement(child);
ethannicholasb3058bd2016-07-01 08:22:01 -0700281 if (!statement) {
282 return nullptr;
283 }
284 statements.push_back(std::move(statement));
285 }
John Stilesfbd050b2020-08-03 13:21:46 -0400286 return std::make_unique<Block>(block.fOffset, std::move(statements), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700287}
288
Ethan Nicholasfc994162019-06-06 10:04:27 -0400289std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
290 SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
291 auto decl = this->convertVarDeclarations(s, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700292 if (!decl) {
293 return nullptr;
294 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700295 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700296}
297
Ethan Nicholasfc994162019-06-06 10:04:27 -0400298std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNode& decls,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700299 Variable::Storage storage) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400300 SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
John Stilesf621e232020-08-25 13:33:02 -0400301 auto declarationsIter = decls.begin();
302 const Modifiers& modifiers = declarationsIter++->getModifiers();
303 const ASTNode& rawType = *(declarationsIter++);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000304 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400305 const Type* baseType = this->convertType(rawType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700306 if (!baseType) {
307 return nullptr;
308 }
Brian Osman82329002020-07-21 09:39:27 -0400309 if (baseType->nonnullable() == *fContext.fFragmentProcessor_Type &&
310 storage != Variable::kGlobal_Storage) {
311 fErrors.error(decls.fOffset,
312 "variables of type '" + baseType->displayName() + "' must be global");
313 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500314 if (fKind != Program::kFragmentProcessor_Kind) {
315 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
316 baseType->kind() == Type::Kind::kMatrix_Kind) {
317 fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
318 }
Brian Osman088913a2019-12-19 15:44:56 -0500319 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
320 (modifiers.fFlags & Modifiers::kUniform_Flag)) {
321 fErrors.error(decls.fOffset,
322 "'in uniform' variables only permitted within fragment processors");
323 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500324 if (modifiers.fLayout.fWhen.fLength) {
325 fErrors.error(decls.fOffset, "'when' is only permitted within fragment processors");
326 }
327 if (modifiers.fLayout.fFlags & Layout::kTracked_Flag) {
328 fErrors.error(decls.fOffset, "'tracked' is only permitted within fragment processors");
329 }
330 if (modifiers.fLayout.fCType != Layout::CType::kDefault) {
331 fErrors.error(decls.fOffset, "'ctype' is only permitted within fragment processors");
332 }
333 if (modifiers.fLayout.fKey) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400334 fErrors.error(decls.fOffset, "'key' is only permitted within fragment processors");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400335 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500336 }
Brian Osmana4b91692020-08-10 14:26:16 -0400337 if (fKind == Program::kPipelineStage_Kind) {
338 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
339 baseType->nonnullable() != *fContext.fFragmentProcessor_Type) {
340 fErrors.error(decls.fOffset, "'in' variables not permitted in runtime effects");
341 }
342 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500343 if (modifiers.fLayout.fKey && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
344 fErrors.error(decls.fOffset, "'key' is not permitted on 'uniform' variables");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400345 }
Brian Osmanf59a9612020-04-15 14:18:13 -0400346 if (modifiers.fLayout.fMarker.fLength) {
347 if (fKind != Program::kPipelineStage_Kind) {
348 fErrors.error(decls.fOffset, "'marker' is only permitted in runtime effects");
349 }
350 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
351 fErrors.error(decls.fOffset, "'marker' is only permitted on 'uniform' variables");
352 }
353 if (*baseType != *fContext.fFloat4x4_Type) {
354 fErrors.error(decls.fOffset, "'marker' is only permitted on float4x4 variables");
355 }
356 }
Brian Osmanb32d66b2020-04-30 17:12:03 -0400357 if (modifiers.fLayout.fFlags & Layout::kSRGBUnpremul_Flag) {
358 if (fKind != Program::kPipelineStage_Kind) {
359 fErrors.error(decls.fOffset, "'srgb_unpremul' is only permitted in runtime effects");
360 }
361 if (!(modifiers.fFlags & Modifiers::kUniform_Flag)) {
362 fErrors.error(decls.fOffset,
363 "'srgb_unpremul' is only permitted on 'uniform' variables");
364 }
365 auto validColorXformType = [](const Type& t) {
366 return t.kind() == Type::kVector_Kind && t.componentType().isFloat() &&
367 (t.columns() == 3 || t.columns() == 4);
368 };
369 if (!validColorXformType(*baseType) && !(baseType->kind() == Type::kArray_Kind &&
370 validColorXformType(baseType->componentType()))) {
371 fErrors.error(decls.fOffset,
372 "'srgb_unpremul' is only permitted on half3, half4, float3, or float4 "
373 "variables");
374 }
375 }
Brian Osman3c358422020-03-23 10:44:12 -0400376 if (modifiers.fFlags & Modifiers::kVarying_Flag) {
377 if (fKind != Program::kPipelineStage_Kind) {
378 fErrors.error(decls.fOffset, "'varying' is only permitted in runtime effects");
379 }
380 if (!baseType->isFloat() &&
381 !(baseType->kind() == Type::kVector_Kind && baseType->componentType().isFloat())) {
382 fErrors.error(decls.fOffset, "'varying' must be float scalar or vector");
383 }
384 }
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400385 int permitted = Modifiers::kConst_Flag;
386 if (storage == Variable::kGlobal_Storage) {
387 permitted |= Modifiers::kIn_Flag | Modifiers::kOut_Flag | Modifiers::kUniform_Flag |
388 Modifiers::kFlat_Flag | Modifiers::kVarying_Flag |
389 Modifiers::kNoPerspective_Flag | Modifiers::kPLS_Flag |
390 Modifiers::kPLSIn_Flag | Modifiers::kPLSOut_Flag |
391 Modifiers::kRestrict_Flag | Modifiers::kVolatile_Flag |
392 Modifiers::kReadOnly_Flag | Modifiers::kWriteOnly_Flag |
393 Modifiers::kCoherent_Flag | Modifiers::kBuffer_Flag;
394 }
395 this->checkModifiers(decls.fOffset, modifiers, permitted);
John Stilesf621e232020-08-25 13:33:02 -0400396 for (; declarationsIter != decls.end(); ++declarationsIter) {
397 const ASTNode& varDecl = *declarationsIter;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400398 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
399 (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
400 varDecl.getVarData().fName != "sk_FragColor") {
401 fErrors.error(varDecl.fOffset,
Ethan Nicholas6c942712018-03-16 09:45:11 -0400402 "out location=0, index=0 is reserved for sk_FragColor");
403 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400404 const ASTNode::VarData& varData = varDecl.getVarData();
ethannicholasd598f792016-07-25 10:08:54 -0700405 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700406 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400407 auto iter = varDecl.begin();
408 for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
409 const ASTNode& rawSize = *iter;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700410 if (rawSize) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400411 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700412 if (!size) {
413 return nullptr;
414 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700415 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500416 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 if (size->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -0400418 count = size->as<IntLiteral>().fValue;
ethannicholasb3058bd2016-07-01 08:22:01 -0700419 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700420 fErrors.error(size->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400421 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 }
423 name += "[" + to_string(count) + "]";
424 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400425 fErrors.error(size->fOffset, "array size must be specified");
426 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700427 }
John Stiles3ae071e2020-08-05 15:29:29 -0400428 type = fSymbolTable->takeOwnershipOfSymbol(
429 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700430 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700431 } else {
John Stiles3ae071e2020-08-05 15:29:29 -0400432 type = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
433 type->name() + "[]", Type::kArray_Kind, *type, /*columns=*/-1));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700434 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700435 }
436 }
John Stilesfbd050b2020-08-03 13:21:46 -0400437 auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, *type,
438 storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000439 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400440 SkASSERT(!fRTAdjust);
441 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000442 fRTAdjust = var.get();
443 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700444 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400445 if (iter != varDecl.end()) {
446 value = this->convertExpression(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700447 if (!value) {
448 return nullptr;
449 }
ethannicholasd598f792016-07-25 10:08:54 -0700450 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500451 if (!value) {
452 return nullptr;
453 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400454 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500455 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700456 }
John Stilesce591b72020-08-27 11:47:30 -0400457 const Symbol* symbol = (*fSymbolTable)[var->fName];
458 if (symbol && storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor") {
459 // Already defined, ignore.
460 } else if (symbol && storage == Variable::kGlobal_Storage &&
461 symbol->fKind == Symbol::kVariable_Kind &&
462 symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) {
463 // Already defined, just update the modifiers.
464 symbol->as<Variable>().fModifiers = var->fModifiers;
ethannicholasf789b382016-08-03 12:43:36 -0700465 } else {
John Stilesce591b72020-08-27 11:47:30 -0400466 variables.emplace_back(std::make_unique<VarDeclaration>(var.get(), std::move(sizes),
467 std::move(value)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400468 StringFragment name = var->fName;
469 fSymbolTable->add(name, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700470 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700471 }
John Stilesfbd050b2020-08-03 13:21:46 -0400472 return std::make_unique<VarDeclarations>(decls.fOffset, baseType, std::move(variables));
ethannicholasb3058bd2016-07-01 08:22:01 -0700473}
474
Ethan Nicholasfc994162019-06-06 10:04:27 -0400475std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
476 SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
477 Modifiers modifiers = m.getModifiers();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400478 if (modifiers.fLayout.fInvocations != -1) {
Ethan Nicholasf06576b2019-04-03 15:45:25 -0400479 if (fKind != Program::kGeometry_Kind) {
480 fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
481 return nullptr;
482 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400483 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600484 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400485 modifiers.fLayout.fInvocations = -1;
John Stilesce591b72020-08-27 11:47:30 -0400486 const Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
487 invocationId.fModifiers.fFlags = 0;
488 invocationId.fModifiers.fLayout.fBuiltin = -1;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400489 if (modifiers.fLayout.description() == "") {
490 return nullptr;
491 }
492 }
493 }
494 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600495 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400496 modifiers.fLayout.fMaxVertices *= fInvocations;
497 }
John Stilesfbd050b2020-08-03 13:21:46 -0400498 return std::make_unique<ModifiersDeclaration>(modifiers);
ethannicholas5961bc92016-10-12 06:39:56 -0700499}
500
Ethan Nicholasfc994162019-06-06 10:04:27 -0400501std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
502 SkASSERT(n.fKind == ASTNode::Kind::kIf);
503 auto iter = n.begin();
504 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -0700505 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700506 if (!test) {
507 return nullptr;
508 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400509 std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700510 if (!ifTrue) {
511 return nullptr;
512 }
513 std::unique_ptr<Statement> ifFalse;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400514 if (iter != n.end()) {
515 ifFalse = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700516 if (!ifFalse) {
517 return nullptr;
518 }
519 }
ethannicholas08a92112016-11-09 13:26:45 -0800520 if (test->fKind == Expression::kBoolLiteral_Kind) {
521 // static boolean value, fold down to a single branch
John Stiles403a3632020-08-20 12:11:48 -0400522 if (test->as<BoolLiteral>().fValue) {
ethannicholas08a92112016-11-09 13:26:45 -0800523 return ifTrue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400524 } else if (ifFalse) {
ethannicholas08a92112016-11-09 13:26:45 -0800525 return ifFalse;
526 } else {
527 // False & no else clause. Not an error, so don't return null!
528 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400529 return std::unique_ptr<Statement>(new Block(n.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800530 fSymbolTable));
531 }
532 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400533 return std::unique_ptr<Statement>(new IfStatement(n.fOffset, n.getBool(), std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700534 std::move(ifTrue), std::move(ifFalse)));
535}
536
Ethan Nicholasfc994162019-06-06 10:04:27 -0400537std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
538 SkASSERT(f.fKind == ASTNode::Kind::kFor);
ethannicholas22f939e2016-10-13 13:25:34 -0700539 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700540 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700541 std::unique_ptr<Statement> initializer;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400542 auto iter = f.begin();
543 if (*iter) {
544 initializer = this->convertStatement(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700545 if (!initializer) {
546 return nullptr;
547 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700548 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400549 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700550 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400551 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400552 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400553 test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
ethannicholas22f939e2016-10-13 13:25:34 -0700554 if (!test) {
555 return nullptr;
556 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -0400557
ethannicholasb3058bd2016-07-01 08:22:01 -0700558 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400559 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700560 std::unique_ptr<Expression> next;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400561 if (*iter) {
John Stilesd1c4dac2020-08-11 18:50:50 -0400562 AutoDisableInline disableInline(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400563 next = this->convertExpression(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700564 if (!next) {
565 return nullptr;
566 }
567 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700568 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400569 ++iter;
570 std::unique_ptr<Statement> statement = this->convertStatement(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700571 if (!statement) {
572 return nullptr;
573 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400574 return std::make_unique<ForStatement>(f.fOffset, std::move(initializer), std::move(test),
575 std::move(next), std::move(statement), fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -0700576}
577
Ethan Nicholasfc994162019-06-06 10:04:27 -0400578std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
579 SkASSERT(w.fKind == ASTNode::Kind::kWhile);
ethannicholas22f939e2016-10-13 13:25:34 -0700580 AutoLoopLevel level(this);
John Stilesd1c4dac2020-08-11 18:50:50 -0400581 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400582 auto iter = w.begin();
John Stilesd1c4dac2020-08-11 18:50:50 -0400583 {
584 AutoDisableInline disableInline(this);
585 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
586 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700587 if (!test) {
588 return nullptr;
589 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400590 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700591 if (!statement) {
592 return nullptr;
593 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400594 return std::make_unique<WhileStatement>(w.fOffset, std::move(test), std::move(statement));
ethannicholasb3058bd2016-07-01 08:22:01 -0700595}
596
Ethan Nicholasfc994162019-06-06 10:04:27 -0400597std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
598 SkASSERT(d.fKind == ASTNode::Kind::kDo);
ethannicholas22f939e2016-10-13 13:25:34 -0700599 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400600 auto iter = d.begin();
601 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
602 if (!statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 return nullptr;
604 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400605 std::unique_ptr<Expression> test;
606 {
607 AutoDisableInline disableInline(this);
608 test = this->coerce(this->convertExpression(*(iter++)), *fContext.fBool_Type);
609 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400610 if (!test) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700611 return nullptr;
612 }
John Stilesd1c4dac2020-08-11 18:50:50 -0400613 return std::make_unique<DoStatement>(d.fOffset, std::move(statement), std::move(test));
ethannicholasb3058bd2016-07-01 08:22:01 -0700614}
615
Ethan Nicholasfc994162019-06-06 10:04:27 -0400616std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
617 SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500618 AutoSwitchLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400619 auto iter = s.begin();
620 std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500621 if (!value) {
622 return nullptr;
623 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500624 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500625 value = this->coerce(std::move(value), *fContext.fInt_Type);
626 if (!value) {
627 return nullptr;
628 }
629 }
630 AutoSymbolTable table(this);
631 std::unordered_set<int> caseValues;
632 std::vector<std::unique_ptr<SwitchCase>> cases;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400633 for (; iter != s.end(); ++iter) {
634 const ASTNode& c = *iter;
635 SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500636 std::unique_ptr<Expression> caseValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400637 auto childIter = c.begin();
638 if (*childIter) {
639 caseValue = this->convertExpression(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500640 if (!caseValue) {
641 return nullptr;
642 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500643 caseValue = this->coerce(std::move(caseValue), value->fType);
644 if (!caseValue) {
645 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500646 }
Brian Osman3e3db6c2020-08-14 09:42:12 -0400647 int64_t v = 0;
648 if (!this->getConstantInt(*caseValue, &v)) {
649 fErrors.error(caseValue->fOffset, "case value must be a constant integer");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500650 return nullptr;
651 }
Ethan Nicholasaf197692017-02-27 13:26:45 -0500652 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700653 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500654 }
655 caseValues.insert(v);
656 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400657 ++childIter;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500658 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400659 for (; childIter != c.end(); ++childIter) {
660 std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500661 if (!converted) {
662 return nullptr;
663 }
664 statements.push_back(std::move(converted));
665 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400666 cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500667 std::move(statements)));
668 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400669 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400670 std::move(value), std::move(cases),
671 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500672}
673
Ethan Nicholasfc994162019-06-06 10:04:27 -0400674std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
675 std::unique_ptr<Expression> e = this->convertExpression(s);
ethannicholasb3058bd2016-07-01 08:22:01 -0700676 if (!e) {
677 return nullptr;
678 }
679 this->checkValid(*e);
680 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
681}
682
Ethan Nicholasfc994162019-06-06 10:04:27 -0400683std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
684 SkASSERT(r.fKind == ASTNode::Kind::kReturn);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400685 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000686 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400687 // SkASSERT that we aren't doing that. It is of course possible to fix this by adding a
Robert Phillipsfe8da172018-01-24 14:52:02 +0000688 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400689 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400690 if (r.begin() != r.end()) {
691 std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -0700692 if (!result) {
693 return nullptr;
694 }
ethannicholasd598f792016-07-25 10:08:54 -0700695 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700696 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700697 } else {
698 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
699 if (!result) {
700 return nullptr;
701 }
702 }
703 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
704 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700705 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700706 fErrors.error(r.fOffset, "expected function to return '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -0500707 fCurrentFunction->fReturnType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700708 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700709 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700710 }
711}
712
Ethan Nicholasfc994162019-06-06 10:04:27 -0400713std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
714 SkASSERT(b.fKind == ASTNode::Kind::kBreak);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500715 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700716 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700717 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700718 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700719 return nullptr;
720 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700721}
722
Ethan Nicholasfc994162019-06-06 10:04:27 -0400723std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
724 SkASSERT(c.fKind == ASTNode::Kind::kContinue);
ethannicholas22f939e2016-10-13 13:25:34 -0700725 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700726 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700727 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700728 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700729 return nullptr;
730 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700731}
732
Ethan Nicholasfc994162019-06-06 10:04:27 -0400733std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
734 SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700735 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700736}
737
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500738std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400739 Layout invokeLayout;
740 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
John Stilesb9af7232020-08-20 15:57:48 -0400741 const FunctionDeclaration* invokeDecl = fSymbolTable->add(
742 "_invoke", std::make_unique<FunctionDeclaration>(/*offset=*/-1,
743 invokeModifiers,
744 "_invoke",
745 std::vector<const Variable*>(),
746 *fContext.fVoid_Type,
747 /*builtin=*/false));
748 fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
749 *invokeDecl,
750 std::move(main)));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400751
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000752 std::vector<std::unique_ptr<VarDeclaration>> variables;
John Stilesb9af7232020-08-20 15:57:48 -0400753 const Variable* loopIdx = &(*fSymbolTable)["sk_InvocationID"]->as<Variable>();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700754 std::unique_ptr<Expression> test(new BinaryExpression(-1,
755 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400756 Token::Kind::TK_LT,
John Stilesfbd050b2020-08-03 13:21:46 -0400757 std::make_unique<IntLiteral>(fContext, -1, fInvocations),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400758 *fContext.fBool_Type));
759 std::unique_ptr<Expression> next(new PostfixExpression(
760 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700761 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400762 *loopIdx,
763 VariableReference::kReadWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400764 Token::Kind::TK_PLUSPLUS));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400765 ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400766 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400767 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400768
769 std::vector<std::unique_ptr<Statement>> loopBody;
770 std::vector<std::unique_ptr<Expression>> invokeArgs;
771 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700772 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400773 *invokeDecl,
774 std::vector<std::unique_ptr<Expression>>()))));
775 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700776 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400777 std::move(endPrimitive),
778 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700779 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400780 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx,
781 VariableReference::kWrite_RefKind)),
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400782 Token::Kind::TK_EQ,
John Stilesfbd050b2020-08-03 13:21:46 -0400783 std::make_unique<IntLiteral>(fContext, -1, 0),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400784 *fContext.fInt_Type));
785 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
786 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700787 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400788 std::move(initializer),
789 std::move(test),
790 std::move(next),
John Stilesfbd050b2020-08-03 13:21:46 -0400791 std::make_unique<Block>(-1, std::move(loopBody)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400792 fSymbolTable));
793 std::vector<std::unique_ptr<Statement>> children;
794 children.push_back(std::move(loop));
John Stilesfbd050b2020-08-03 13:21:46 -0400795 return std::make_unique<Block>(-1, std::move(children));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400796}
797
Robert Phillipsfe8da172018-01-24 14:52:02 +0000798std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400799 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000800 // 0,
801 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400802 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000803 #define REF(var) std::unique_ptr<Expression>(\
804 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400805 #define WREF(var) std::unique_ptr<Expression>(\
806 new VariableReference(-1, *var, VariableReference::kWrite_RefKind))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000807 #define FIELD(var, idx) std::unique_ptr<Expression>(\
808 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
Ethan Nicholas4fadce42020-07-30 13:29:30 -0400809 #define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
Robert Phillipsfe8da172018-01-24 14:52:02 +0000810 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
811 #define ADJUST (fRTAdjustInterfaceBlock ? \
812 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
813 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400814 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
815 { __VA_ARGS__ }))
816 #define OP(left, op, right) std::unique_ptr<Expression>( \
817 new BinaryExpression(-1, left, op, right, \
818 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000819 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400820 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 0, 2)),
821 Token::Kind::TK_PLUS,
822 OP(SWIZZLE(POS, 3, 3), Token::Kind::TK_STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000823 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
824 children.push_back(SWIZZLE(POS, 3));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -0400825 std::unique_ptr<Expression> result = OP(POS, Token::Kind::TK_EQ,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000826 std::unique_ptr<Expression>(new Constructor(-1,
827 *fContext.fFloat4_Type,
828 std::move(children))));
829 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
830}
831
Ethan Nicholasc18bb512020-07-28 14:46:53 -0400832template<typename T>
833class AutoClear {
834public:
835 AutoClear(T* container)
836 : fContainer(container) {
837 SkASSERT(container->empty());
838 }
839
840 ~AutoClear() {
841 fContainer->clear();
842 }
843
844private:
845 T* fContainer;
846};
847
John Stilesb8e010c2020-08-11 18:05:39 -0400848template <typename T> AutoClear(T* c) -> AutoClear<T>;
849
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400850void IRGenerator::checkModifiers(int offset, const Modifiers& modifiers, int permitted) {
851 int flags = modifiers.fFlags;
852 #define CHECK(flag, name) \
853 if (!flags) return; \
854 if (flags & flag) { \
855 if (!(permitted & flag)) { \
856 fErrors.error(offset, "'" name "' is not permitted here"); \
857 } \
858 flags &= ~flag; \
859 }
860 CHECK(Modifiers::kConst_Flag, "const")
861 CHECK(Modifiers::kIn_Flag, "in")
862 CHECK(Modifiers::kOut_Flag, "out")
863 CHECK(Modifiers::kUniform_Flag, "uniform")
864 CHECK(Modifiers::kFlat_Flag, "flat")
865 CHECK(Modifiers::kNoPerspective_Flag, "noperspective")
866 CHECK(Modifiers::kReadOnly_Flag, "readonly")
867 CHECK(Modifiers::kWriteOnly_Flag, "writeonly")
868 CHECK(Modifiers::kCoherent_Flag, "coherent")
869 CHECK(Modifiers::kVolatile_Flag, "volatile")
870 CHECK(Modifiers::kRestrict_Flag, "restrict")
871 CHECK(Modifiers::kBuffer_Flag, "buffer")
872 CHECK(Modifiers::kHasSideEffects_Flag, "sk_has_side_effects")
873 CHECK(Modifiers::kPLS_Flag, "__pixel_localEXT")
874 CHECK(Modifiers::kPLSIn_Flag, "__pixel_local_inEXT")
875 CHECK(Modifiers::kPLSOut_Flag, "__pixel_local_outEXT")
876 CHECK(Modifiers::kVarying_Flag, "varying")
Ethan Nicholasf3c8f5d2020-08-20 13:09:14 +0000877 CHECK(Modifiers::kInline_Flag, "inline")
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400878 SkASSERT(flags == 0);
879}
880
Ethan Nicholasfc994162019-06-06 10:04:27 -0400881void IRGenerator::convertFunction(const ASTNode& f) {
John Stilesb8e010c2020-08-11 18:05:39 -0400882 AutoClear clear(&fReferencedIntrinsics);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400883 auto iter = f.begin();
884 const Type* returnType = this->convertType(*(iter++));
John Stilesb9af7232020-08-20 15:57:48 -0400885 if (returnType == nullptr) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400886 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700887 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400888 auto type_is_allowed = [&](const Type* t) {
889#if defined(SKSL_STANDALONE)
890 return true;
891#else
892 GrSLType unusedSLType;
893 return fKind != Program::kPipelineStage_Kind ||
894 type_to_grsltype(fContext, *t, &unusedSLType);
895#endif
896 };
897 if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type ||
898 !type_is_allowed(returnType)) {
Brian Osman82329002020-07-21 09:39:27 -0400899 fErrors.error(f.fOffset,
900 "functions may not return type '" + returnType->displayName() + "'");
901 return;
902 }
John Stilesb9af7232020-08-20 15:57:48 -0400903 const ASTNode::FunctionData& funcData = f.getFunctionData();
904 this->checkModifiers(f.fOffset, funcData.fModifiers, Modifiers::kHasSideEffects_Flag |
905 Modifiers::kInline_Flag);
ethannicholasd598f792016-07-25 10:08:54 -0700906 std::vector<const Variable*> parameters;
John Stilesb9af7232020-08-20 15:57:48 -0400907 for (size_t i = 0; i < funcData.fParameterCount; ++i) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400908 const ASTNode& param = *(iter++);
909 SkASSERT(param.fKind == ASTNode::Kind::kParameter);
910 ASTNode::ParameterData pd = param.getParameterData();
Ethan Nicholas63d7ee32020-08-17 10:57:12 -0400911 this->checkModifiers(param.fOffset, pd.fModifiers, Modifiers::kIn_Flag |
912 Modifiers::kOut_Flag);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400913 auto paramIter = param.begin();
914 const Type* type = this->convertType(*(paramIter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700915 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400916 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700917 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400918 for (int j = (int) pd.fSizeCount; j >= 1; j--) {
919 int size = (param.begin() + j)->getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400920 String name = type->name() + "[" + to_string(size) + "]";
John Stiles3ae071e2020-08-05 15:29:29 -0400921 type = fSymbolTable->takeOwnershipOfSymbol(
922 std::make_unique<Type>(std::move(name), Type::kArray_Kind, *type, size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700923 }
Brian Osman3000d6b2020-07-31 15:57:28 -0400924 // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
925 if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
926 !type_is_allowed(type)) {
927 fErrors.error(param.fOffset,
928 "parameters of type '" + type->displayName() + "' not allowed");
929 return;
930 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400931 StringFragment name = pd.fName;
John Stiles3ae071e2020-08-05 15:29:29 -0400932 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
933 param.fOffset, pd.fModifiers, name, *type, Variable::kParameter_Storage));
ethannicholasd598f792016-07-25 10:08:54 -0700934 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700935 }
936
Brian Osman767f4442020-08-13 16:59:48 -0400937 auto paramIsCoords = [&](int idx) {
938 return parameters[idx]->fType == *fContext.fFloat2_Type &&
939 parameters[idx]->fModifiers.fFlags == 0;
940 };
Brian Osman767f4442020-08-13 16:59:48 -0400941
John Stilesb9af7232020-08-20 15:57:48 -0400942 if (funcData.fName == "main") {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400943 switch (fKind) {
944 case Program::kPipelineStage_Kind: {
Brian Osman767f4442020-08-13 16:59:48 -0400945 // half4 main() -or- half4 main(float2)
946 bool valid = (*returnType == *fContext.fHalf4_Type) &&
947 ((parameters.size() == 0) ||
948 (parameters.size() == 1 && paramIsCoords(0)));
949 if (!valid) {
950 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared "
951 "half4 main() or half4 main(float2)");
952 return;
953 }
954 break;
Brian Osman44820a92020-08-26 09:27:39 -0400955 }
Michael Ludwigfc2fdf02020-06-29 17:20:13 -0400956 case Program::kFragmentProcessor_Kind: {
Brian Osman44820a92020-08-26 09:27:39 -0400957 bool valid = (parameters.size() == 0) ||
958 (parameters.size() == 1 && paramIsCoords(0));
Michael Ludwigfc2fdf02020-06-29 17:20:13 -0400959 if (!valid) {
960 fErrors.error(f.fOffset, ".fp 'main' must be declared main() or main(float2)");
961 return;
962 }
963 break;
964 }
Ethan Nicholas746035a2019-04-23 13:31:09 -0400965 case Program::kGeneric_Kind:
Ethan Nicholas0d997662019-04-08 09:46:01 -0400966 break;
Ethan Nicholas0d997662019-04-08 09:46:01 -0400967 default:
968 if (parameters.size()) {
969 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
970 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400971 }
972 }
973
ethannicholasb3058bd2016-07-01 08:22:01 -0700974 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700975 const FunctionDeclaration* decl = nullptr;
John Stilesb9af7232020-08-20 15:57:48 -0400976 const Symbol* entry = (*fSymbolTable)[funcData.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700977 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700978 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700979 switch (entry->fKind) {
980 case Symbol::kUnresolvedFunction_Kind:
John Stiles17c5b702020-08-18 10:40:03 -0400981 functions = entry->as<UnresolvedFunction>().fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700982 break;
983 case Symbol::kFunctionDeclaration_Kind:
John Stiles17c5b702020-08-18 10:40:03 -0400984 functions.push_back(&entry->as<FunctionDeclaration>());
ethannicholasb3058bd2016-07-01 08:22:01 -0700985 break;
986 default:
John Stilesb9af7232020-08-20 15:57:48 -0400987 fErrors.error(f.fOffset, "symbol '" + funcData.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400988 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700989 }
John Stilesb9af7232020-08-20 15:57:48 -0400990 for (const FunctionDeclaration* other : functions) {
991 SkASSERT(other->fName == funcData.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700992 if (parameters.size() == other->fParameters.size()) {
993 bool match = true;
994 for (size_t i = 0; i < parameters.size(); i++) {
995 if (parameters[i]->fType != other->fParameters[i]->fType) {
996 match = false;
997 break;
998 }
999 }
1000 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -07001001 if (*returnType != other->fReturnType) {
John Stilesb9af7232020-08-20 15:57:48 -04001002 FunctionDeclaration newDecl(f.fOffset, funcData.fModifiers, funcData.fName,
1003 parameters, *returnType, fIsBuiltinCode);
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001004 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
1005 "' and '" + other->description() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001006 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001007 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001008 }
1009 decl = other;
1010 for (size_t i = 0; i < parameters.size(); i++) {
1011 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001012 fErrors.error(f.fOffset, "modifiers on parameter " +
1013 to_string((uint64_t) i + 1) +
John Stilesb9af7232020-08-20 15:57:48 -04001014 " differ between declaration and definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001015 return;
ethannicholasb3058bd2016-07-01 08:22:01 -07001016 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001017 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001018 if (other->fDefinition && !other->fBuiltin) {
John Stilesb9af7232020-08-20 15:57:48 -04001019 fErrors.error(f.fOffset, "duplicate definition of " + other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -07001020 }
1021 break;
1022 }
1023 }
1024 }
1025 }
1026 if (!decl) {
John Stilesb9af7232020-08-20 15:57:48 -04001027 // Conservatively assume all user-defined functions have side effects.
1028 Modifiers declModifiers = funcData.fModifiers;
1029 if (!fIsBuiltinCode) {
1030 declModifiers.fFlags |= Modifiers::kHasSideEffects_Flag;
1031 }
1032
1033 // Create a new declaration.
1034 decl = fSymbolTable->add(funcData.fName,
John Stiles311dd9d2020-08-13 17:09:29 -04001035 std::make_unique<FunctionDeclaration>(f.fOffset,
John Stilesb9af7232020-08-20 15:57:48 -04001036 declModifiers,
1037 funcData.fName,
John Stiles311dd9d2020-08-13 17:09:29 -04001038 parameters,
1039 *returnType,
1040 fIsBuiltinCode));
ethannicholasb3058bd2016-07-01 08:22:01 -07001041 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001042 if (iter != f.end()) {
1043 // compile body
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001044 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -07001045 fCurrentFunction = decl;
ethannicholasd598f792016-07-25 10:08:54 -07001046 std::shared_ptr<SymbolTable> old = fSymbolTable;
1047 AutoSymbolTable table(this);
Brian Osman44820a92020-08-26 09:27:39 -04001048 if (funcData.fName == "main" && (fKind == Program::kPipelineStage_Kind ||
1049 fKind == Program::kFragmentProcessor_Kind)) {
Brian Osman767f4442020-08-13 16:59:48 -04001050 if (parameters.size() == 1) {
1051 SkASSERT(paramIsCoords(0));
1052 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
1053 }
Ethan Nicholas00543112018-07-31 09:44:36 -04001054 }
ethannicholasd598f792016-07-25 10:08:54 -07001055 for (size_t i = 0; i < parameters.size(); i++) {
1056 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -07001057 }
John Stilesb9af7232020-08-20 15:57:48 -04001058 bool needInvocationIDWorkaround = fInvocations != -1 && funcData.fName == "main" &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -06001059 fSettings->fCaps &&
1060 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasfc994162019-06-06 10:04:27 -04001061 std::unique_ptr<Block> body = this->convertBlock(*iter);
ethannicholasd598f792016-07-25 10:08:54 -07001062 fCurrentFunction = nullptr;
1063 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04001064 return;
1065 }
1066 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001067 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -07001068 }
John Stilesb9af7232020-08-20 15:57:48 -04001069 if (Program::kVertex_Kind == fKind && funcData.fName == "main" && fRTAdjust) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00001070 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
1071 }
John Stilesb8e010c2020-08-11 18:05:39 -04001072 auto result = std::make_unique<FunctionDefinition>(f.fOffset, *decl, std::move(body),
1073 std::move(fReferencedIntrinsics));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001074 decl->fDefinition = result.get();
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001075 result->fSource = &f;
1076 fProgramElements->push_back(std::move(result));
ethannicholasb3058bd2016-07-01 08:22:01 -07001077 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001078}
1079
Ethan Nicholasfc994162019-06-06 10:04:27 -04001080std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
1081 SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
1082 ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
ethannicholasb3058bd2016-07-01 08:22:01 -07001083 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001084 this->pushSymbolTable();
1085 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001086 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001087 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +00001088 bool foundRTAdjust = false;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001089 auto iter = intf.begin();
1090 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
ethannicholas14fe8cc2016-09-07 13:37:16 -07001091 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04001092 *(iter++),
Ethan Nicholasa7ceb502019-01-11 10:31:48 -05001093 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -07001094 if (!decl) {
1095 return nullptr;
1096 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001097 for (const auto& stmt : decl->fVars) {
John Stiles403a3632020-08-20 12:11:48 -04001098 VarDeclaration& vd = stmt->as<VarDeclaration>();
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001099 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001100 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001101 "only the last entry in an interface block may be a runtime-sized "
1102 "array");
1103 }
Robert Phillipsfe8da172018-01-24 14:52:02 +00001104 if (vd.fVar == fRTAdjust) {
1105 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001106 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +00001107 fRTAdjustFieldIndex = fields.size();
1108 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001109 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
1110 &vd.fVar->fType));
1111 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001112 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001113 "initializers are not permitted on interface block fields");
1114 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +00001115 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
1116 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -04001117 haveRuntimeArray = true;
1118 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001119 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001120 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001121 this->popSymbolTable();
John Stiles3ae071e2020-08-05 15:29:29 -04001122 const Type* type =
1123 old->takeOwnershipOfSymbol(std::make_unique<Type>(intf.fOffset, id.fTypeName, fields));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001124 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001125 for (size_t i = 0; i < id.fSizeCount; ++i) {
1126 const ASTNode& size = *(iter++);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001127 if (size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001128 std::unique_ptr<Expression> converted = this->convertExpression(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -05001129 if (!converted) {
1130 return nullptr;
1131 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001132 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001133 int64_t count;
1134 if (converted->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001135 count = converted->as<IntLiteral>().fValue;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001136 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001137 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -04001138 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001139 }
1140 name += "[" + to_string(count) + "]";
1141 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001142 fErrors.error(intf.fOffset, "array size must be specified");
1143 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001144 }
John Stiles3ae071e2020-08-05 15:29:29 -04001145 type = symbols->takeOwnershipOfSymbol(
1146 std::make_unique<Type>(name, Type::kArray_Kind, *type, (int)count));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001147 sizes.push_back(std::move(converted));
1148 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -04001149 fErrors.error(intf.fOffset, "array size must be specified");
1150 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -05001151 }
1152 }
John Stiles3ae071e2020-08-05 15:29:29 -04001153 const Variable* var = old->takeOwnershipOfSymbol(
1154 std::make_unique<Variable>(intf.fOffset,
1155 id.fModifiers,
1156 id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
1157 *type,
1158 Variable::kGlobal_Storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +00001159 if (foundRTAdjust) {
1160 fRTAdjustInterfaceBlock = var;
1161 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001162 if (id.fInstanceName.fLength) {
1163 old->addWithoutOwnership(id.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -07001164 } else {
1165 for (size_t i = 0; i < fields.size(); i++) {
John Stilesfbd050b2020-08-03 13:21:46 -04001166 old->add(fields[i].fName, std::make_unique<Field>(intf.fOffset, *var, (int)i));
ethannicholasb3058bd2016-07-01 08:22:01 -07001167 }
1168 }
John Stilesfbd050b2020-08-03 13:21:46 -04001169 return std::make_unique<InterfaceBlock>(intf.fOffset,
1170 var,
1171 id.fTypeName,
1172 id.fInstanceName,
1173 std::move(sizes),
1174 symbols);
ethannicholasb3058bd2016-07-01 08:22:01 -07001175}
1176
Brian Osman3e3db6c2020-08-14 09:42:12 -04001177bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001178 switch (value.fKind) {
1179 case Expression::kIntLiteral_Kind:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001180 *out = static_cast<const IntLiteral&>(value).fValue;
1181 return true;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001182 case Expression::kVariableReference_Kind: {
Brian Osman3e3db6c2020-08-14 09:42:12 -04001183 const Variable& var = static_cast<const VariableReference&>(value).fVariable;
1184 return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
1185 var.fInitialValue &&
1186 this->getConstantInt(*var.fInitialValue, out);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001187 }
1188 default:
Brian Osman3e3db6c2020-08-14 09:42:12 -04001189 return false;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001190 }
1191}
1192
Ethan Nicholasfc994162019-06-06 10:04:27 -04001193void IRGenerator::convertEnum(const ASTNode& e) {
1194 SkASSERT(e.fKind == ASTNode::Kind::kEnum);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001195 int64_t currentValue = 0;
1196 Layout layout;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001197 ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
1198 ASTNode::TypeData(e.getString(), false, false));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001199 const Type* type = this->convertType(enumType);
1200 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Brian Osman3e3db6c2020-08-14 09:42:12 -04001201 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -04001202 for (auto iter = e.begin(); iter != e.end(); ++iter) {
1203 const ASTNode& child = *iter;
1204 SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001205 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001206 if (child.begin() != child.end()) {
1207 value = this->convertExpression(*child.begin());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001208 if (!value) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001209 return;
1210 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001211 if (!this->getConstantInt(*value, &currentValue)) {
1212 fErrors.error(value->fOffset, "enum value must be a constant integer");
1213 return;
1214 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001215 }
1216 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
1217 ++currentValue;
Brian Osman3e3db6c2020-08-14 09:42:12 -04001218 fSymbolTable->add(child.getString(),
1219 std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), *type,
1220 Variable::kGlobal_Storage, value.get()));
1221 fSymbolTable->takeOwnershipOfIRNode(std::move(value));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001222 }
Brian Osman3e3db6c2020-08-14 09:42:12 -04001223 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
1224 new Enum(e.fOffset, e.getString(), fSymbolTable, fIsBuiltinCode)));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001225}
1226
Ethan Nicholasfc994162019-06-06 10:04:27 -04001227const Type* IRGenerator::convertType(const ASTNode& type) {
1228 ASTNode::TypeData td = type.getTypeData();
1229 const Symbol* result = (*fSymbolTable)[td.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001230 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001231 if (td.fIsNullable) {
John Stiles17c5b702020-08-18 10:40:03 -04001232 if (result->as<Type>() == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001233 if (type.begin() != type.end()) {
1234 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001235 "an array");
1236 }
John Stiles3ae071e2020-08-05 15:29:29 -04001237 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
John Stiles17c5b702020-08-18 10:40:03 -04001238 String(result->fName) + "?", Type::kNullable_Kind, result->as<Type>()));
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001239 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001240 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001241 }
1242 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001243 for (const auto& size : type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001244 String name(result->fName);
1245 name += "[";
Ethan Nicholasfc994162019-06-06 10:04:27 -04001246 if (size) {
1247 name += to_string(size.getInt());
Ethan Nicholas50afc172017-02-16 14:49:57 -05001248 }
1249 name += "]";
John Stiles3ae071e2020-08-05 15:29:29 -04001250 result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
John Stiles17c5b702020-08-18 10:40:03 -04001251 name, Type::kArray_Kind, result->as<Type>(), size ? size.getInt() : 0));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001252 }
John Stiles17c5b702020-08-18 10:40:03 -04001253 return &result->as<Type>();
ethannicholasb3058bd2016-07-01 08:22:01 -07001254 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001255 fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001256 return nullptr;
1257}
1258
Ethan Nicholasfc994162019-06-06 10:04:27 -04001259std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001260 switch (expr.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001261 case ASTNode::Kind::kBinary:
1262 return this->convertBinaryExpression(expr);
1263 case ASTNode::Kind::kBool:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001264 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001265 expr.getBool()));
1266 case ASTNode::Kind::kCall:
1267 return this->convertCallExpression(expr);
1268 case ASTNode::Kind::kField:
1269 return this->convertFieldExpression(expr);
1270 case ASTNode::Kind::kFloat:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001271 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001272 expr.getFloat()));
1273 case ASTNode::Kind::kIdentifier:
1274 return this->convertIdentifier(expr);
1275 case ASTNode::Kind::kIndex:
1276 return this->convertIndexExpression(expr);
1277 case ASTNode::Kind::kInt:
1278 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
1279 expr.getInt()));
1280 case ASTNode::Kind::kNull:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001281 return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001282 case ASTNode::Kind::kPostfix:
1283 return this->convertPostfixExpression(expr);
1284 case ASTNode::Kind::kPrefix:
1285 return this->convertPrefixExpression(expr);
1286 case ASTNode::Kind::kTernary:
1287 return this->convertTernaryExpression(expr);
ethannicholasb3058bd2016-07-01 08:22:01 -07001288 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001289#ifdef SK_DEBUG
Ethan Nicholasfc994162019-06-06 10:04:27 -04001290 ABORT("unsupported expression: %s\n", expr.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001291#endif
1292 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001293 }
1294}
1295
Ethan Nicholasfc994162019-06-06 10:04:27 -04001296std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
1297 SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
1298 const Symbol* result = (*fSymbolTable)[identifier.getString()];
ethannicholasb3058bd2016-07-01 08:22:01 -07001299 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001300 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001301 return nullptr;
1302 }
1303 switch (result->fKind) {
1304 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001305 std::vector<const FunctionDeclaration*> f = {
John Stiles17c5b702020-08-18 10:40:03 -04001306 &result->as<FunctionDeclaration>()
ethannicholasb3058bd2016-07-01 08:22:01 -07001307 };
John Stilesfbd050b2020-08-03 13:21:46 -04001308 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
ethannicholasb3058bd2016-07-01 08:22:01 -07001309 }
1310 case Symbol::kUnresolvedFunction_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001311 const UnresolvedFunction* f = &result->as<UnresolvedFunction>();
John Stilesfbd050b2020-08-03 13:21:46 -04001312 return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
ethannicholasb3058bd2016-07-01 08:22:01 -07001313 }
1314 case Symbol::kVariable_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001315 const Variable* var = &result->as<Variable>();
Ethan Nicholascd700e92018-08-24 16:43:57 -04001316 switch (var->fModifiers.fLayout.fBuiltin) {
1317 case SK_WIDTH_BUILTIN:
1318 fInputs.fRTWidth = true;
1319 break;
1320 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001321 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001322 break;
1323#ifndef SKSL_STANDALONE
1324 case SK_FRAGCOORD_BUILTIN:
Brian Osman9f313b62019-10-02 12:03:11 -04001325 fInputs.fFlipY = true;
1326 if (fSettings->fFlipY &&
1327 (!fSettings->fCaps ||
1328 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1329 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001330 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001331#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001332 }
Ethan Nicholas33c59ed2019-08-13 10:21:38 -04001333 if (fKind == Program::kFragmentProcessor_Kind &&
1334 (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
1335 !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
1336 !var->fModifiers.fLayout.fKey &&
1337 var->fModifiers.fLayout.fBuiltin == -1 &&
1338 var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
1339 var->fType.kind() != Type::kSampler_Kind) {
1340 bool valid = false;
1341 for (const auto& decl : fFile->root()) {
1342 if (decl.fKind == ASTNode::Kind::kSection) {
1343 ASTNode::SectionData section = decl.getSectionData();
1344 if (section.fName == "setData") {
1345 valid = true;
1346 break;
1347 }
1348 }
1349 }
1350 if (!valid) {
1351 fErrors.error(identifier.fOffset, "'in' variable must be either 'uniform' or "
1352 "'layout(key)', or there must be a custom "
1353 "@setData function");
1354 }
1355 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001356 // default to kRead_RefKind; this will be corrected later if the variable is written to
John Stilesfbd050b2020-08-03 13:21:46 -04001357 return std::make_unique<VariableReference>(identifier.fOffset,
1358 *var,
1359 VariableReference::kRead_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001360 }
1361 case Symbol::kField_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001362 const Field* field = &result->as<Field>();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001363 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001364 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001365 return std::unique_ptr<Expression>(new FieldAccess(
1366 std::unique_ptr<Expression>(base),
1367 field->fFieldIndex,
1368 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001369 }
1370 case Symbol::kType_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001371 const Type* t = &result->as<Type>();
John Stilesfbd050b2020-08-03 13:21:46 -04001372 return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t);
ethannicholasb3058bd2016-07-01 08:22:01 -07001373 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001374 case Symbol::kExternal_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04001375 const ExternalValue* r = &result->as<ExternalValue>();
John Stilesfbd050b2020-08-03 13:21:46 -04001376 return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
Ethan Nicholas91164d12019-05-15 15:29:54 -04001377 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001378 default:
1379 ABORT("unsupported symbol type %d\n", result->fKind);
1380 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001381}
1382
Ethan Nicholasfc994162019-06-06 10:04:27 -04001383std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
1384 ASTNode::SectionData section = s.getSectionData();
John Stilesfbd050b2020-08-03 13:21:46 -04001385 return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument,
1386 section.fText);
Ethan Nicholas762466e2017-06-29 10:03:38 -04001387}
1388
1389
Ethan Nicholas11d53972016-11-28 11:23:23 -05001390std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001391 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001392 if (!expr) {
1393 return nullptr;
1394 }
ethannicholasd598f792016-07-25 10:08:54 -07001395 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001396 return expr;
1397 }
1398 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001399 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001400 return nullptr;
1401 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001402 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001403 fErrors.error(expr->fOffset, "expected '" + type.displayName() + "', but found '" +
1404 expr->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001405 return nullptr;
1406 }
ethannicholasd598f792016-07-25 10:08:54 -07001407 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001408 std::vector<std::unique_ptr<Expression>> args;
1409 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001410 std::unique_ptr<Expression> ctor;
1411 if (type == *fContext.fFloatLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001412 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1413 "float"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001414 } else if (type == *fContext.fIntLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001415 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1416 "int"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001417 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001418 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1419 type.fName));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001420 }
1421 if (!ctor) {
1422 printf("error, null identifier: %s\n", String(type.fName).c_str());
1423 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001424 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001425 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001426 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001427 if (expr->fKind == Expression::kNullLiteral_Kind) {
1428 SkASSERT(type.kind() == Type::kNullable_Kind);
1429 return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
1430 }
ethannicholas5961bc92016-10-12 06:39:56 -07001431 std::vector<std::unique_ptr<Expression>> args;
1432 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001433 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001434}
1435
ethannicholasf789b382016-08-03 12:43:36 -07001436static bool is_matrix_multiply(const Type& left, const Type& right) {
1437 if (left.kind() == Type::kMatrix_Kind) {
1438 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1439 }
1440 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1441}
ethannicholasea4567c2016-10-17 11:24:37 -07001442
ethannicholasb3058bd2016-07-01 08:22:01 -07001443/**
1444 * Determines the operand and result types of a binary expression. Returns true if the expression is
1445 * legal, false otherwise. If false, the values of the out parameters are undefined.
1446 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001447static bool determine_binary_type(const Context& context,
1448 Token::Kind op,
1449 const Type& left,
1450 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001451 const Type** outLeftType,
1452 const Type** outRightType,
1453 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001454 bool tryFlipped) {
1455 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001456 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001457 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001458 case Token::Kind::TK_EQ:
ethannicholasea4567c2016-10-17 11:24:37 -07001459 *outLeftType = &left;
1460 *outRightType = &left;
1461 *outResultType = &left;
1462 return right.canCoerceTo(left);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001463 case Token::Kind::TK_EQEQ: // fall through
1464 case Token::Kind::TK_NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001465 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001466 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001467 *outRightType = &left;
1468 *outResultType = context.fBool_Type.get();
1469 return true;
1470 } if (left.canCoerceTo(right)) {
1471 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001472 *outRightType = &right;
1473 *outResultType = context.fBool_Type.get();
1474 return true;
1475 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001476 return false;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001477 case Token::Kind::TK_LT: // fall through
1478 case Token::Kind::TK_GT: // fall through
1479 case Token::Kind::TK_LTEQ: // fall through
1480 case Token::Kind::TK_GTEQ:
ethannicholasb3058bd2016-07-01 08:22:01 -07001481 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001482 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001483 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001484 case Token::Kind::TK_LOGICALOR: // fall through
1485 case Token::Kind::TK_LOGICALAND: // fall through
1486 case Token::Kind::TK_LOGICALXOR: // fall through
1487 case Token::Kind::TK_LOGICALOREQ: // fall through
1488 case Token::Kind::TK_LOGICALANDEQ: // fall through
1489 case Token::Kind::TK_LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001490 *outLeftType = context.fBool_Type.get();
1491 *outRightType = context.fBool_Type.get();
1492 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001493 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001494 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001495 case Token::Kind::TK_STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001496 if (left.kind() == Type::kScalar_Kind) {
1497 *outLeftType = &left;
1498 *outRightType = &left;
1499 *outResultType = &left;
1500 return right.canCoerceTo(left);
1501 }
John Stiles30212b72020-06-11 17:55:07 -04001502 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001503 case Token::Kind::TK_STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001504 if (is_matrix_multiply(left, right)) {
1505 // determine final component type
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001506 if (determine_binary_type(context, Token::Kind::TK_STAR, left.componentType(),
ethannicholasf789b382016-08-03 12:43:36 -07001507 right.componentType(), outLeftType, outRightType,
1508 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001509 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001510 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001511 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001512 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001513 int leftColumns = left.columns();
1514 int leftRows = left.rows();
1515 int rightColumns;
1516 int rightRows;
1517 if (right.kind() == Type::kVector_Kind) {
1518 // matrix * vector treats the vector as a column vector, so we need to
1519 // transpose it
1520 rightColumns = right.rows();
1521 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001522 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001523 } else {
1524 rightColumns = right.columns();
1525 rightRows = right.rows();
1526 }
1527 if (rightColumns > 1) {
1528 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1529 leftRows);
1530 } else {
1531 // result was a column vector, transpose it back to a row
1532 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1533 rightColumns);
1534 }
1535 return leftColumns == rightRows;
1536 } else {
1537 return false;
1538 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001539 }
ethannicholasea4567c2016-10-17 11:24:37 -07001540 isLogical = false;
1541 validMatrixOrVectorOp = true;
1542 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001543 case Token::Kind::TK_PLUSEQ:
1544 case Token::Kind::TK_MINUSEQ:
1545 case Token::Kind::TK_SLASHEQ:
1546 case Token::Kind::TK_PERCENTEQ:
1547 case Token::Kind::TK_SHLEQ:
1548 case Token::Kind::TK_SHREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001549 if (left.kind() == Type::kScalar_Kind) {
1550 *outLeftType = &left;
1551 *outRightType = &left;
1552 *outResultType = &left;
1553 return right.canCoerceTo(left);
1554 }
John Stiles30212b72020-06-11 17:55:07 -04001555 [[fallthrough]];
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001556 case Token::Kind::TK_PLUS: // fall through
1557 case Token::Kind::TK_MINUS: // fall through
1558 case Token::Kind::TK_SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001559 isLogical = false;
1560 validMatrixOrVectorOp = true;
1561 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001562 case Token::Kind::TK_COMMA:
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001563 *outLeftType = &left;
1564 *outRightType = &right;
1565 *outResultType = &right;
1566 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001567 default:
1568 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001569 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001570 }
ethannicholasea4567c2016-10-17 11:24:37 -07001571 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001572 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1573 right.canCoerceTo(left)) {
1574 if (left.priority() > right.priority()) {
1575 *outLeftType = &left;
1576 *outRightType = &left;
1577 } else {
1578 *outLeftType = &right;
1579 *outRightType = &right;
1580 }
1581 if (isLogical) {
1582 *outResultType = context.fBool_Type.get();
1583 } else {
1584 *outResultType = &left;
1585 }
1586 return true;
1587 }
1588 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001589 *outLeftType = &left;
1590 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001591 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001592 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001593 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001594 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001595 }
1596 return true;
1597 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001598 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001599 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001600 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001601 outRightType, outResultType, false)) {
1602 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001603 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001604 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001605 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001606 }
1607 return true;
1608 }
1609 return false;
1610 }
1611 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001612 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001613 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001614 }
1615 return false;
1616}
1617
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001618static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1619 const Expression& left,
1620 Token::Kind op,
1621 const Expression& right) {
1622 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
John Stiles403a3632020-08-20 12:11:48 -04001623 bool leftVal = left.as<BoolLiteral>().fValue;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001624 if (op == Token::Kind::TK_LOGICALAND) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001625 // (true && expr) -> (expr) and (false && expr) -> (false)
1626 return leftVal ? right.clone()
1627 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001628 } else if (op == Token::Kind::TK_LOGICALOR) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001629 // (true || expr) -> (true) and (false || expr) -> (expr)
1630 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1631 : right.clone();
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001632 } else if (op == Token::Kind::TK_LOGICALXOR) {
Noah Lavine334d0ba2019-12-18 23:03:49 -05001633 // (true ^^ expr) -> !(expr) and (false ^^ expr) -> (expr)
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001634 return leftVal ? std::unique_ptr<Expression>(new PrefixExpression(
1635 Token::Kind::TK_LOGICALNOT,
1636 right.clone()))
Noah Lavine334d0ba2019-12-18 23:03:49 -05001637 : right.clone();
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001638 } else {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001639 return nullptr;
1640 }
1641}
1642
ethannicholas08a92112016-11-09 13:26:45 -08001643std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1644 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001645 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001646 // If the left side is a constant boolean literal, the right side does not need to be constant
1647 // for short circuit optimizations to allow the constant to be folded.
Brian Osmanb6b95732020-06-30 11:44:27 -04001648 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001649 return short_circuit_boolean(fContext, left, op, right);
Brian Osmanb6b95732020-06-30 11:44:27 -04001650 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isCompileTimeConstant()) {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001651 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1652 // (right OP left) for short-circuit optimizations
1653 return short_circuit_boolean(fContext, right, op, left);
1654 }
1655
1656 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Brian Osmanb6b95732020-06-30 11:44:27 -04001657 if (!left.isCompileTimeConstant() || !right.isCompileTimeConstant()) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001658 return nullptr;
1659 }
ethannicholas08a92112016-11-09 13:26:45 -08001660 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1661 // precision to calculate the results and hope the result makes sense. The plan is to move the
1662 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1663 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001664 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001665 right.fKind == Expression::kBoolLiteral_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04001666 bool leftVal = left.as<BoolLiteral>().fValue;
1667 bool rightVal = right.as<BoolLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001668 bool result;
1669 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001670 case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
1671 case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
1672 case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
ethannicholas08a92112016-11-09 13:26:45 -08001673 default: return nullptr;
1674 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001675 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001676 }
John Stilesfbd050b2020-08-03 13:21:46 -04001677 #define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1678 leftVal op rightVal)
1679 #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
1680 (uint32_t) leftVal op \
1681 (uint32_t) rightVal)
ethannicholas08a92112016-11-09 13:26:45 -08001682 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001683 int64_t leftVal = left.as<IntLiteral>().fValue;
1684 int64_t rightVal = right.as<IntLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001685 switch (op) {
Ethan Nicholas66869e92020-04-30 09:27:54 -04001686 case Token::Kind::TK_PLUS: return URESULT(Int, +);
1687 case Token::Kind::TK_MINUS: return URESULT(Int, -);
1688 case Token::Kind::TK_STAR: return URESULT(Int, *);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001689 case Token::Kind::TK_SLASH:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001690 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1691 fErrors.error(right.fOffset, "arithmetic overflow");
1692 return nullptr;
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001693 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001694 if (!rightVal) {
1695 fErrors.error(right.fOffset, "division by zero");
1696 return nullptr;
1697 }
1698 return RESULT(Int, /);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001699 case Token::Kind::TK_PERCENT:
Ethan Nicholas66869e92020-04-30 09:27:54 -04001700 if (leftVal == std::numeric_limits<int64_t>::min() && rightVal == -1) {
1701 fErrors.error(right.fOffset, "arithmetic overflow");
1702 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001703 }
Ethan Nicholas66869e92020-04-30 09:27:54 -04001704 if (!rightVal) {
1705 fErrors.error(right.fOffset, "division by zero");
1706 return nullptr;
1707 }
1708 return RESULT(Int, %);
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001709 case Token::Kind::TK_BITWISEAND: return RESULT(Int, &);
1710 case Token::Kind::TK_BITWISEOR: return RESULT(Int, |);
1711 case Token::Kind::TK_BITWISEXOR: return RESULT(Int, ^);
1712 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1713 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1714 case Token::Kind::TK_GT: return RESULT(Bool, >);
1715 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1716 case Token::Kind::TK_LT: return RESULT(Bool, <);
1717 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1718 case Token::Kind::TK_SHL:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001719 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001720 return URESULT(Int, <<);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001721 }
1722 fErrors.error(right.fOffset, "shift value out of range");
1723 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001724 case Token::Kind::TK_SHR:
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001725 if (rightVal >= 0 && rightVal <= 31) {
Ethan Nicholase4489002020-04-29 14:00:14 -04001726 return URESULT(Int, >>);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001727 }
1728 fErrors.error(right.fOffset, "shift value out of range");
1729 return nullptr;
1730
1731 default:
1732 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001733 }
1734 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001735 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001736 right.fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04001737 double leftVal = left.as<FloatLiteral>().fValue;
1738 double rightVal = right.as<FloatLiteral>().fValue;
ethannicholas08a92112016-11-09 13:26:45 -08001739 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001740 case Token::Kind::TK_PLUS: return RESULT(Float, +);
1741 case Token::Kind::TK_MINUS: return RESULT(Float, -);
1742 case Token::Kind::TK_STAR: return RESULT(Float, *);
1743 case Token::Kind::TK_SLASH:
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001744 if (rightVal) {
1745 return RESULT(Float, /);
1746 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001747 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001748 return nullptr;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001749 case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
1750 case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
1751 case Token::Kind::TK_GT: return RESULT(Bool, >);
1752 case Token::Kind::TK_GTEQ: return RESULT(Bool, >=);
1753 case Token::Kind::TK_LT: return RESULT(Bool, <);
1754 case Token::Kind::TK_LTEQ: return RESULT(Bool, <=);
1755 default: return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001756 }
1757 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001758 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001759 left.fType == right.fType) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001760 std::vector<std::unique_ptr<Expression>> args;
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001761 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1762 for (int i = 0; i < left.fType.columns(); i++) { \
1763 float value = left.getFVecComponent(i) op \
1764 right.getFVecComponent(i); \
1765 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
1766 } \
1767 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001768 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001769 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001770 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001771 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001772 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001773 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001774 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001775 !left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001776 case Token::Kind::TK_PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1777 case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1778 case Token::Kind::TK_STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1779 case Token::Kind::TK_SLASH:
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001780 for (int i = 0; i < left.fType.columns(); i++) {
1781 SKSL_FLOAT rvalue = right.getFVecComponent(i);
1782 if (rvalue == 0.0) {
1783 fErrors.error(right.fOffset, "division by zero");
1784 return nullptr;
1785 }
1786 float value = left.getFVecComponent(i) / rvalue;
1787 args.emplace_back(new FloatLiteral(fContext, -1, value));
1788 }
1789 return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
1790 std::move(args)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001791 default: return nullptr;
1792 }
1793 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001794 if (left.fType.kind() == Type::kMatrix_Kind &&
1795 right.fType.kind() == Type::kMatrix_Kind &&
1796 left.fKind == right.fKind) {
1797 switch (op) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001798 case Token::Kind::TK_EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001799 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001800 left.compareConstant(fContext, right)));
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001801 case Token::Kind::TK_NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001802 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001803 !left.compareConstant(fContext, right)));
1804 default:
1805 return nullptr;
1806 }
1807 }
ethannicholas08a92112016-11-09 13:26:45 -08001808 #undef RESULT
1809 return nullptr;
1810}
1811
Ethan Nicholasfc994162019-06-06 10:04:27 -04001812std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
1813 SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
1814 auto iter = expression.begin();
1815 std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001816 if (!left) {
1817 return nullptr;
1818 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001819 Token::Kind op = expression.getToken().fKind;
John Stilesd1c4dac2020-08-11 18:50:50 -04001820 std::unique_ptr<Expression> right;
1821 {
1822 // Can't inline the right side of a short-circuiting boolean, because our inlining
1823 // approach runs things out of order.
1824 AutoDisableInline disableInline(this, /*canInline=*/(op != Token::Kind::TK_LOGICALAND &&
1825 op != Token::Kind::TK_LOGICALOR));
1826 right = this->convertExpression(*(iter++));
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001827 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001828 if (!right) {
1829 return nullptr;
1830 }
ethannicholasd598f792016-07-25 10:08:54 -07001831 const Type* leftType;
1832 const Type* rightType;
1833 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001834 const Type* rawLeftType;
1835 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1836 rawLeftType = &right->fType;
1837 } else {
1838 rawLeftType = &left->fType;
1839 }
1840 const Type* rawRightType;
1841 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1842 rawRightType = &left->fType;
1843 } else {
1844 rawRightType = &right->fType;
1845 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001846 if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
1847 &resultType, !Compiler::IsAssignment(op))) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001848 fErrors.error(expression.fOffset, String("type mismatch: '") +
Ethan Nicholasfc994162019-06-06 10:04:27 -04001849 Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001850 "' cannot operate on '" + left->fType.displayName() +
1851 "', '" + right->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001852 return nullptr;
1853 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001854 if (Compiler::IsAssignment(op)) {
Ethan Nicholas4fadce42020-07-30 13:29:30 -04001855 if (!this->setRefKind(*left, op != Token::Kind::TK_EQ
1856 ? VariableReference::kReadWrite_RefKind
1857 : VariableReference::kWrite_RefKind)) {
1858 return nullptr;
1859 }
ethannicholasea4567c2016-10-17 11:24:37 -07001860 }
1861 left = this->coerce(std::move(left), *leftType);
1862 right = this->coerce(std::move(right), *rightType);
1863 if (!left || !right) {
1864 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001865 }
John Stilesa008b0f2020-08-16 08:48:02 -04001866 std::unique_ptr<Expression> result = this->constantFold(*left, op, *right);
ethannicholas08a92112016-11-09 13:26:45 -08001867 if (!result) {
John Stilesd1c4dac2020-08-11 18:50:50 -04001868 result = std::make_unique<BinaryExpression>(expression.fOffset, std::move(left), op,
1869 std::move(right), *resultType);
ethannicholas08a92112016-11-09 13:26:45 -08001870 }
1871 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001872}
1873
Ethan Nicholasfc994162019-06-06 10:04:27 -04001874std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
1875 SkASSERT(node.fKind == ASTNode::Kind::kTernary);
1876 auto iter = node.begin();
1877 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -07001878 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001879 if (!test) {
1880 return nullptr;
1881 }
John Stiles8fa3b4e2020-09-02 11:27:23 -04001882 std::unique_ptr<Expression> ifTrue;
1883 std::unique_ptr<Expression> ifFalse;
1884 {
1885 AutoDisableInline disableInline(this);
1886 ifTrue = this->convertExpression(*(iter++));
1887 if (!ifTrue) {
1888 return nullptr;
1889 }
1890 ifFalse = this->convertExpression(*(iter++));
1891 if (!ifFalse) {
1892 return nullptr;
1893 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001894 }
ethannicholasd598f792016-07-25 10:08:54 -07001895 const Type* trueType;
1896 const Type* falseType;
1897 const Type* resultType;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04001898 if (!determine_binary_type(fContext, Token::Kind::TK_EQEQ, ifTrue->fType, ifFalse->fType,
1899 &trueType, &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001900 fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001901 ifTrue->fType.displayName() + "', '" +
1902 ifFalse->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001903 return nullptr;
1904 }
Brian Osman82329002020-07-21 09:39:27 -04001905 if (trueType->nonnullable() == *fContext.fFragmentProcessor_Type) {
1906 fErrors.error(node.fOffset,
1907 "ternary expression of type '" + trueType->displayName() + "' not allowed");
1908 return nullptr;
1909 }
ethannicholasd598f792016-07-25 10:08:54 -07001910 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001911 if (!ifTrue) {
1912 return nullptr;
1913 }
ethannicholasd598f792016-07-25 10:08:54 -07001914 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001915 if (!ifFalse) {
1916 return nullptr;
1917 }
ethannicholas08a92112016-11-09 13:26:45 -08001918 if (test->fKind == Expression::kBoolLiteral_Kind) {
1919 // static boolean test, just return one of the branches
John Stiles403a3632020-08-20 12:11:48 -04001920 if (test->as<BoolLiteral>().fValue) {
ethannicholas08a92112016-11-09 13:26:45 -08001921 return ifTrue;
1922 } else {
1923 return ifFalse;
1924 }
1925 }
John Stiles8fa3b4e2020-09-02 11:27:23 -04001926 return std::make_unique<TernaryExpression>(node.fOffset,
1927 std::move(test),
1928 std::move(ifTrue),
1929 std::move(ifFalse));
ethannicholasb3058bd2016-07-01 08:22:01 -07001930}
1931
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001932void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
1933 auto found = fIntrinsics->find(function.description());
John Stiles810c8cf2020-08-26 19:46:27 -04001934 if (found != fIntrinsics->end() && !found->second.fAlreadyIncluded) {
1935 found->second.fAlreadyIncluded = true;
1936 FunctionDefinition& original = found->second.fIntrinsic->as<FunctionDefinition>();
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001937 for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
1938 this->copyIntrinsicIfNeeded(*f);
1939 }
1940 fProgramElements->push_back(original.clone());
1941 }
1942}
1943
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001944std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001945 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07001946 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001947 if (function.fBuiltin) {
Ethan Nicholasc18bb512020-07-28 14:46:53 -04001948 if (function.fDefinition) {
1949 fReferencedIntrinsics.insert(&function);
1950 }
1951 if (!fIsBuiltinCode) {
1952 this->copyIntrinsicIfNeeded(function);
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001953 }
1954 }
ethannicholasd598f792016-07-25 10:08:54 -07001955 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001956 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05001957 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07001958 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07001959 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001960 msg += "s";
1961 }
ethannicholas5961bc92016-10-12 06:39:56 -07001962 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001963 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001964 return nullptr;
1965 }
Ethan Nicholas70728ef2020-05-28 07:09:00 -04001966 if (fKind == Program::kPipelineStage_Kind && !function.fDefinition && !function.fBuiltin) {
Brian Osman5f6b41e2020-03-09 11:53:24 -04001967 String msg = "call to undefined function '" + function.fName + "'";
1968 fErrors.error(offset, msg);
1969 return nullptr;
1970 }
ethannicholas471e8942016-10-28 09:02:46 -07001971 std::vector<const Type*> types;
1972 const Type* returnType;
1973 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001974 String msg = "no match for " + function.fName + "(";
1975 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07001976 for (size_t i = 0; i < arguments.size(); i++) {
1977 msg += separator;
1978 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05001979 msg += arguments[i]->fType.displayName();
ethannicholas471e8942016-10-28 09:02:46 -07001980 }
1981 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001982 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07001983 return nullptr;
1984 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001985 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07001986 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07001987 if (!arguments[i]) {
1988 return nullptr;
1989 }
ethannicholasd598f792016-07-25 10:08:54 -07001990 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001991 this->setRefKind(*arguments[i],
1992 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
1993 VariableReference::kReadWrite_RefKind :
1994 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001995 }
1996 }
John Stilesea9ab822020-08-31 09:55:04 -04001997
1998 auto funcCall = std::make_unique<FunctionCall>(offset, *returnType, function,
1999 std::move(arguments));
John Stiles7b463002020-08-31 17:29:21 -04002000 if (fCanInline && fInliner->isSafeToInline(*funcCall, fSettings->fInlineThreshold)) {
2001 Inliner::InlinedCall inlinedCall = fInliner->inlineCall(std::move(funcCall),
2002 fSymbolTable.get());
John Stiles39616ec2020-08-31 14:16:06 -04002003 if (inlinedCall.fInlinedBody) {
2004 fExtraStatements.push_back(std::move(inlinedCall.fInlinedBody));
2005 }
John Stiles44e96be2020-08-31 13:16:04 -04002006 return std::move(inlinedCall.fReplacementExpr);
Ethan Nicholas70728ef2020-05-28 07:09:00 -04002007 }
John Stiles8c91c932020-08-13 14:35:35 -04002008
John Stilesea9ab822020-08-31 09:55:04 -04002009 return std::move(funcCall);
ethannicholasb3058bd2016-07-01 08:22:01 -07002010}
2011
2012/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002013 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
2014 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
2015 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07002016 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002017int IRGenerator::callCost(const FunctionDeclaration& function,
2018 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07002019 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002020 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002021 }
2022 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07002023 std::vector<const Type*> types;
2024 const Type* ignored;
2025 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002026 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07002027 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002028 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002029 int cost = arguments[i]->coercionCost(*types[i]);
2030 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002031 total += cost;
2032 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002033 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07002034 }
2035 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002036 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07002037}
2038
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002039std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002040 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07002041 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002042 switch (functionValue->fKind) {
2043 case Expression::kTypeReference_Kind:
2044 return this->convertConstructor(offset,
John Stiles403a3632020-08-20 12:11:48 -04002045 functionValue->as<TypeReference>().fValue,
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002046 std::move(arguments));
2047 case Expression::kExternalValue_Kind: {
John Stiles17c5b702020-08-18 10:40:03 -04002048 const ExternalValue* v = functionValue->as<ExternalValueReference>().fValue;
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002049 if (!v->canCall()) {
2050 fErrors.error(offset, "this external value is not a function");
2051 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002052 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002053 int count = v->callParameterCount();
2054 if (count != (int) arguments.size()) {
2055 fErrors.error(offset, "external function expected " + to_string(count) +
2056 " arguments, but found " + to_string((int) arguments.size()));
2057 return nullptr;
2058 }
2059 static constexpr int PARAMETER_MAX = 16;
2060 SkASSERT(count < PARAMETER_MAX);
2061 const Type* types[PARAMETER_MAX];
2062 v->getCallParameterTypes(types);
2063 for (int i = 0; i < count; ++i) {
2064 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
2065 if (!arguments[i]) {
2066 return nullptr;
2067 }
2068 }
2069 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(),
2070 v, std::move(arguments)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002071 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002072 case Expression::kFunctionReference_Kind: {
John Stilesce591b72020-08-27 11:47:30 -04002073 const FunctionReference& ref = functionValue->as<FunctionReference>();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002074 int bestCost = INT_MAX;
2075 const FunctionDeclaration* best = nullptr;
John Stilesce591b72020-08-27 11:47:30 -04002076 if (ref.fFunctions.size() > 1) {
2077 for (const auto& f : ref.fFunctions) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002078 int cost = this->callCost(*f, arguments);
2079 if (cost < bestCost) {
2080 bestCost = cost;
2081 best = f;
2082 }
2083 }
2084 if (best) {
2085 return this->call(offset, *best, std::move(arguments));
2086 }
John Stilesce591b72020-08-27 11:47:30 -04002087 String msg = "no match for " + ref.fFunctions[0]->fName + "(";
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002088 String separator;
2089 for (size_t i = 0; i < arguments.size(); i++) {
2090 msg += separator;
2091 separator = ", ";
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002092 msg += arguments[i]->fType.displayName();
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002093 }
2094 msg += ")";
2095 fErrors.error(offset, msg);
2096 return nullptr;
2097 }
John Stilesce591b72020-08-27 11:47:30 -04002098 return this->call(offset, *ref.fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002099 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002100 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002101 fErrors.error(offset, "not a function");
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04002102 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07002103 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002104}
2105
Ethan Nicholas84645e32017-02-09 13:57:14 -05002106std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002107 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05002108 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07002109 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002110 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05002111 if (args.size() != 1) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002112 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002113 "' constructor, (expected exactly 1 argument, but found " +
2114 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07002115 return nullptr;
2116 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002117 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002118 return std::move(args[0]);
2119 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04002120 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002121 double value = args[0]->as<FloatLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002122 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04002123 }
2124 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002125 int64_t value = args[0]->as<IntLiteral>().fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04002126 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002127 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002128 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
2129 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04002130 return std::unique_ptr<Expression>(new IntLiteral(offset,
John Stiles81365af2020-08-18 09:24:00 -04002131 args[0]->as<IntLiteral>().fValue,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002132 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07002133 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002134 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002135 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
2136 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002137 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002138 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05002139 this->coerce(std::move(one), type),
2140 this->coerce(std::move(zero),
2141 type)));
2142 }
2143 if (!args[0]->fType.isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002144 fErrors.error(offset, "invalid argument to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002145 "' constructor (expected a number or bool, but found '" +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002146 args[0]->fType.displayName() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002147 return nullptr;
2148 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002149 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002150}
2151
John Stiles36374402020-08-13 12:16:44 -04002152static int component_count(const Type& type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002153 switch (type.kind()) {
2154 case Type::kVector_Kind:
2155 return type.columns();
2156 case Type::kMatrix_Kind:
2157 return type.columns() * type.rows();
2158 default:
2159 return 1;
2160 }
2161}
2162
2163std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002164 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002165 const Type& type,
2166 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002167 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05002168 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
2169 args[0]->fType.kind() == Type::kMatrix_Kind) {
2170 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002171 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002172 }
2173 int actual = 0;
2174 int expected = type.rows() * type.columns();
2175 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
2176 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07002177 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002178 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002179 if (type.componentType().isNumber() !=
2180 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002181 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2182 "parameter to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002183 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002184 return nullptr;
2185 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002186 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002187 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
2188 actual += 1;
2189 if (type.kind() != Type::kScalar_Kind) {
2190 args[i] = this->coerce(std::move(args[i]), type.componentType());
2191 if (!args[i]) {
2192 return nullptr;
2193 }
2194 }
2195 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002196 fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
2197 "parameter to '" + type.displayName() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002198 return nullptr;
2199 }
2200 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002201 if (actual != 1 && actual != expected) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002202 fErrors.error(offset, "invalid arguments to '" + type.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002203 "' constructor (expected " + to_string(expected) +
2204 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002205 return nullptr;
2206 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002207 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002208 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002209}
2210
Ethan Nicholas84645e32017-02-09 13:57:14 -05002211std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002212 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002213 const Type& type,
2214 std::vector<std::unique_ptr<Expression>> args) {
2215 // FIXME: add support for structs
Brian Osman82329002020-07-21 09:39:27 -04002216 if (args.size() == 1 && args[0]->fType == type &&
2217 type.nonnullable() != *fContext.fFragmentProcessor_Type) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05002218 // argument is already the right type, just return it
2219 return std::move(args[0]);
2220 }
Brian Osman82329002020-07-21 09:39:27 -04002221 Type::Kind kind = type.kind();
Ethan Nicholas84645e32017-02-09 13:57:14 -05002222 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002223 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002224 } else if (kind == Type::kArray_Kind) {
2225 const Type& base = type.componentType();
2226 for (size_t i = 0; i < args.size(); i++) {
2227 args[i] = this->coerce(std::move(args[i]), base);
2228 if (!args[i]) {
2229 return nullptr;
2230 }
2231 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002232 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002233 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002234 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002235 } else {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002236 fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002237 return nullptr;
2238 }
2239}
2240
Ethan Nicholasfc994162019-06-06 10:04:27 -04002241std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
2242 SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
2243 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -07002244 if (!base) {
2245 return nullptr;
2246 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002247 switch (expression.getToken().fKind) {
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002248 case Token::Kind::TK_PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05002249 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
2250 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002251 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002252 "'+' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002253 return nullptr;
2254 }
2255 return base;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002256 case Token::Kind::TK_MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07002257 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002258 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
John Stiles81365af2020-08-18 09:24:00 -04002259 -base->as<IntLiteral>().fValue));
ethannicholasb3058bd2016-07-01 08:22:01 -07002260 }
2261 if (base->fKind == Expression::kFloatLiteral_Kind) {
John Stiles81365af2020-08-18 09:24:00 -04002262 double value = -base->as<FloatLiteral>().fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002263 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002264 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07002265 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05002266 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
2267 fErrors.error(expression.fOffset,
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002268 "'-' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholase1f55022019-02-05 17:17:40 -05002269 return nullptr;
2270 }
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002271 return std::unique_ptr<Expression>(new PrefixExpression(Token::Kind::TK_MINUS,
2272 std::move(base)));
2273 case Token::Kind::TK_PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07002274 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002275 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002276 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002277 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002278 return nullptr;
2279 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002280 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002281 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002282 case Token::Kind::TK_MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07002283 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002284 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002285 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002286 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002287 return nullptr;
2288 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002289 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002290 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002291 case Token::Kind::TK_LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07002292 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002293 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002294 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002295 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002296 return nullptr;
2297 }
ethannicholas08a92112016-11-09 13:26:45 -08002298 if (base->fKind == Expression::kBoolLiteral_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002299 return std::unique_ptr<Expression>(
2300 new BoolLiteral(fContext, base->fOffset, !base->as<BoolLiteral>().fValue));
ethannicholas08a92112016-11-09 13:26:45 -08002301 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002302 break;
Ethan Nicholas5a9e7fb2020-04-17 12:45:51 -04002303 case Token::Kind::TK_BITWISENOT:
Brian Osman73fb39c2019-09-24 16:22:55 -04002304 if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002305 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002306 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002307 "' cannot operate on '" + base->fType.displayName() + "'");
ethannicholas5961bc92016-10-12 06:39:56 -07002308 return nullptr;
2309 }
2310 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002311 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07002312 ABORT("unsupported prefix operator\n");
2313 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002314 return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
ethannicholasb3058bd2016-07-01 08:22:01 -07002315 std::move(base)));
2316}
2317
2318std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002319 const ASTNode& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002320 if (base->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002321 if (index.fKind == ASTNode::Kind::kInt) {
John Stiles403a3632020-08-20 12:11:48 -04002322 const Type& oldType = base->as<TypeReference>().fValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002323 SKSL_INT size = index.getInt();
John Stiles3ae071e2020-08-05 15:29:29 -04002324 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(
2325 std::make_unique<Type>(oldType.name() + "[" + to_string(size) + "]",
2326 Type::kArray_Kind, oldType, size));
2327 return std::make_unique<TypeReference>(fContext, base->fOffset, *newType);
Ethan Nicholas50afc172017-02-16 14:49:57 -05002328
2329 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002330 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05002331 return nullptr;
2332 }
2333 }
ethannicholas5961bc92016-10-12 06:39:56 -07002334 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
2335 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002336 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002337 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002338 return nullptr;
2339 }
2340 std::unique_ptr<Expression> converted = this->convertExpression(index);
2341 if (!converted) {
2342 return nullptr;
2343 }
ethannicholas5961bc92016-10-12 06:39:56 -07002344 if (converted->fType != *fContext.fUInt_Type) {
2345 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
2346 if (!converted) {
2347 return nullptr;
2348 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002349 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05002350 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07002351 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002352}
2353
2354std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002355 StringFragment field) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04002356 if (base->fKind == Expression::kExternalValue_Kind) {
John Stiles17c5b702020-08-18 10:40:03 -04002357 const ExternalValue& ev = *base->as<ExternalValueReference>().fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002358 ExternalValue* result = ev.getChild(String(field).c_str());
2359 if (!result) {
2360 fErrors.error(base->fOffset, "external value does not have a child named '" + field +
2361 "'");
2362 return nullptr;
2363 }
2364 return std::unique_ptr<Expression>(new ExternalValueReference(base->fOffset, result));
2365 }
ethannicholasd598f792016-07-25 10:08:54 -07002366 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07002367 for (size_t i = 0; i < fields.size(); i++) {
2368 if (fields[i].fName == field) {
2369 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
2370 }
2371 }
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002372 fErrors.error(base->fOffset, "type '" + base->fType.displayName() + "' does not have a "
Brian Osmanb08cc022020-04-02 11:38:40 -04002373 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07002374 return nullptr;
2375}
2376
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002377// 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 -04002378static int count_contiguous_swizzle_chunks(const std::vector<int>& components) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002379 int chunkCount = 0;
2380 for (size_t i = 0; i < components.size(); ++i) {
2381 SkASSERT(components[i] <= 0);
2382 if (components[i] == 0) {
2383 ++chunkCount;
2384 while (i + 1 < components.size() && components[i + 1] == 0) {
2385 ++i;
2386 }
2387 }
2388 }
2389 return chunkCount;
2390}
2391
ethannicholasb3058bd2016-07-01 08:22:01 -07002392std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002393 StringFragment fields) {
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002394 if (base->fType.kind() != Type::kVector_Kind && !base->fType.isNumber()) {
2395 fErrors.error(base->fOffset, "cannot swizzle value of type '" + base->fType.displayName() +
2396 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002397 return nullptr;
2398 }
2399 std::vector<int> swizzleComponents;
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002400 size_t numLiteralFields = 0;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002401 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05002402 switch (fields[i]) {
Ethan Nicholasac285b12019-02-12 16:05:18 -05002403 case '0':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002404 swizzleComponents.push_back(SKSL_SWIZZLE_0);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002405 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002406 break;
2407 case '1':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002408 swizzleComponents.push_back(SKSL_SWIZZLE_1);
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002409 numLiteralFields++;
Ethan Nicholasac285b12019-02-12 16:05:18 -05002410 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002411 case 'x':
2412 case 'r':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002413 case 's':
Ethan Nicholase455f652019-09-13 12:52:55 -04002414 case 'L':
ethannicholasb3058bd2016-07-01 08:22:01 -07002415 swizzleComponents.push_back(0);
2416 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002417 case 'y':
2418 case 'g':
ethannicholasb3058bd2016-07-01 08:22:01 -07002419 case 't':
Ethan Nicholase455f652019-09-13 12:52:55 -04002420 case 'T':
ethannicholasd598f792016-07-25 10:08:54 -07002421 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002422 swizzleComponents.push_back(1);
2423 break;
2424 }
John Stiles30212b72020-06-11 17:55:07 -04002425 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002426 case 'z':
2427 case 'b':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002428 case 'p':
Ethan Nicholase455f652019-09-13 12:52:55 -04002429 case 'R':
ethannicholasd598f792016-07-25 10:08:54 -07002430 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002431 swizzleComponents.push_back(2);
2432 break;
2433 }
John Stiles30212b72020-06-11 17:55:07 -04002434 [[fallthrough]];
Ethan Nicholase455f652019-09-13 12:52:55 -04002435 case 'w':
2436 case 'a':
ethannicholasb3058bd2016-07-01 08:22:01 -07002437 case 'q':
Ethan Nicholase455f652019-09-13 12:52:55 -04002438 case 'B':
ethannicholasd598f792016-07-25 10:08:54 -07002439 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002440 swizzleComponents.push_back(3);
2441 break;
2442 }
John Stiles30212b72020-06-11 17:55:07 -04002443 [[fallthrough]];
ethannicholasb3058bd2016-07-01 08:22:01 -07002444 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002445 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
2446 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07002447 return nullptr;
2448 }
2449 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002450 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07002451 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002452 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002453 return nullptr;
2454 }
Brian Osmanb65dc4a2020-08-14 11:27:28 -04002455 if (numLiteralFields == swizzleComponents.size()) {
2456 fErrors.error(base->fOffset, "swizzle must refer to base expression");
2457 return nullptr;
2458 }
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002459 if (base->fType.isNumber()) {
2460 // Swizzling a single scalar. Something like foo.x0x1 is equivalent to float4(foo, 0, foo,
2461 // 1)
2462 int offset = base->fOffset;
2463 std::unique_ptr<Expression> expr;
2464 switch (base->fKind) {
2465 case Expression::kVariableReference_Kind:
2466 case Expression::kFloatLiteral_Kind:
2467 case Expression::kIntLiteral_Kind:
2468 // the value being swizzled is just a constant or variable reference, so we can
2469 // safely re-use copies of it without reevaluation concerns
2470 expr = std::move(base);
2471 break;
2472 default:
2473 // It's a value we can't safely re-use multiple times. If it's all in one contiguous
2474 // chunk it's easy (e.g. foo.xxx0 can be turned into half4(half3(x), 0)), but
2475 // for multiple discontiguous chunks we'll need to copy it into a temporary value.
2476 int chunkCount = count_contiguous_swizzle_chunks(swizzleComponents);
2477 if (chunkCount <= 1) {
2478 // no copying needed, so we can just use the value directly
2479 expr = std::move(base);
2480 } else {
2481 // store the value in a temporary variable so we can re-use it
John Stiles44e96be2020-08-31 13:16:04 -04002482 int varIndex = fTmpSwizzleCounter++;
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002483 auto name = std::make_unique<String>();
2484 name->appendf("_tmpSwizzle%d", varIndex);
John Stiles3ae071e2020-08-05 15:29:29 -04002485 const String* namePtr = fSymbolTable->takeOwnershipOfString(std::move(name));
2486 const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
2487 std::make_unique<Variable>(offset,
2488 Modifiers(),
2489 namePtr->c_str(),
2490 base->fType,
2491 Variable::kLocal_Storage,
2492 base.get()));
Ethan Nicholasd2dc2062020-08-03 16:05:04 -04002493 expr = std::make_unique<VariableReference>(offset, *var);
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002494 std::vector<std::unique_ptr<VarDeclaration>> variables;
2495 variables.emplace_back(new VarDeclaration(var, {}, std::move(base)));
2496 fExtraStatements.emplace_back(new VarDeclarationsStatement(
2497 std::make_unique<VarDeclarations>(offset, &expr->fType,
2498 std::move(variables))));
2499 }
2500 }
2501 std::vector<std::unique_ptr<Expression>> args;
2502 for (size_t i = 0; i < swizzleComponents.size(); ++i) {
2503 switch (swizzleComponents[i]) {
2504 case 0: {
2505 args.push_back(expr->clone());
2506 int count = 1;
2507 while (i + 1 < swizzleComponents.size() && swizzleComponents[i + 1] == 0) {
2508 ++i;
2509 ++count;
2510 }
2511 if (count > 1) {
2512 std::vector<std::unique_ptr<Expression>> constructorArgs;
2513 constructorArgs.push_back(std::move(args.back()));
2514 args.pop_back();
2515 args.emplace_back(new Constructor(offset, expr->fType.toCompound(fContext,
2516 count,
2517 1),
2518 std::move(constructorArgs)));
2519 }
2520 break;
2521 }
2522 case SKSL_SWIZZLE_0:
2523 args.emplace_back(new IntLiteral(fContext, offset, 0));
2524 break;
2525 case SKSL_SWIZZLE_1:
2526 args.emplace_back(new IntLiteral(fContext, offset, 1));
2527 break;
2528 }
2529 }
2530 return std::unique_ptr<Expression>(new Constructor(offset,
2531 expr->fType.toCompound(
2532 fContext,
2533 swizzleComponents.size(),
2534 1),
2535 std::move(args)));
2536 }
ethannicholasd598f792016-07-25 10:08:54 -07002537 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07002538}
2539
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002540std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05002541 auto found = fCapsMap.find(name);
2542 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002543 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002544 return nullptr;
2545 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002546 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002547 return std::unique_ptr<Expression>(new Setting(offset, fullName,
2548 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002549}
2550
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002551std::unique_ptr<Expression> IRGenerator::findEnumRef(
2552 int offset,
2553 const Type& type,
2554 StringFragment field,
2555 std::vector<std::unique_ptr<ProgramElement>>& elements) {
2556 for (const auto& e : elements) {
John Stiles403a3632020-08-20 12:11:48 -04002557 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == e->as<Enum>().fTypeName) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002558 std::shared_ptr<SymbolTable> old = fSymbolTable;
John Stiles403a3632020-08-20 12:11:48 -04002559 fSymbolTable = e->as<Enum>().fSymbols;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002560 std::unique_ptr<Expression> result = convertIdentifier(ASTNode(&fFile->fNodes, offset,
2561 ASTNode::Kind::kIdentifier,
2562 field));
2563 if (result) {
John Stiles403a3632020-08-20 12:11:48 -04002564 const Variable& v = result->as<VariableReference>().fVariable;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002565 SkASSERT(v.fInitialValue);
John Stilesfbd050b2020-08-03 13:21:46 -04002566 result = std::make_unique<IntLiteral>(
John Stiles81365af2020-08-18 09:24:00 -04002567 offset, v.fInitialValue->as<IntLiteral>().fValue, &type);
Ethan Nicholas9fdab9f2020-05-01 11:02:15 -04002568 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002569 fSymbolTable = old;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002570 return result;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002571 }
2572 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002573 return nullptr;
2574}
2575
2576std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2577 StringFragment field) {
2578 std::unique_ptr<Expression> result = this->findEnumRef(offset, type, field, *fProgramElements);
2579 if (fInherited && !result) {
2580 result = this->findEnumRef(offset, type, field, *fInherited);
2581 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002582 if (!result) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002583 auto found = fIntrinsics->find(type.fName);
2584 if (found != fIntrinsics->end()) {
John Stiles810c8cf2020-08-26 19:46:27 -04002585 SkASSERT(!found->second.fAlreadyIncluded);
2586 found->second.fAlreadyIncluded = true;
2587 fProgramElements->push_back(found->second.fIntrinsic->clone());
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002588 return this->convertTypeField(offset, type, field);
2589 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002590 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2591 "'");
2592 }
2593 return result;
2594}
2595
Ethan Nicholasfc994162019-06-06 10:04:27 -04002596std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
2597 SkASSERT(index.fKind == ASTNode::Kind::kIndex);
2598 auto iter = index.begin();
2599 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07002600 if (!base) {
2601 return nullptr;
2602 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002603 if (iter != index.end()) {
2604 return this->convertIndex(std::move(base), *(iter++));
2605 } else if (base->fKind == Expression::kTypeReference_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002606 const Type& oldType = base->as<TypeReference>().fValue;
John Stiles3ae071e2020-08-05 15:29:29 -04002607 const Type* newType = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
2608 oldType.name() + "[]", Type::kArray_Kind, oldType, /*columns=*/-1));
Ethan Nicholasfc994162019-06-06 10:04:27 -04002609 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
2610 *newType));
ethannicholasb3058bd2016-07-01 08:22:01 -07002611 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002612 fErrors.error(index.fOffset, "'[]' must follow a type name");
2613 return nullptr;
2614}
2615
2616std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
2617 SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
2618 auto iter = callNode.begin();
2619 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
2620 if (!base) {
2621 return nullptr;
2622 }
2623 std::vector<std::unique_ptr<Expression>> arguments;
2624 for (; iter != callNode.end(); ++iter) {
2625 std::unique_ptr<Expression> converted = this->convertExpression(*iter);
2626 if (!converted) {
2627 return nullptr;
2628 }
2629 arguments.push_back(std::move(converted));
2630 }
2631 return this->call(callNode.fOffset, std::move(base), std::move(arguments));
2632}
2633
2634std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
2635 std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
2636 if (!base) {
2637 return nullptr;
2638 }
2639 StringFragment field = fieldNode.getString();
2640 if (base->fType == *fContext.fSkCaps_Type) {
2641 return this->getCap(fieldNode.fOffset, field);
2642 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002643 if (base->fKind == Expression::kTypeReference_Kind) {
John Stiles403a3632020-08-20 12:11:48 -04002644 return this->convertTypeField(base->fOffset, base->as<TypeReference>().fValue,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002645 field);
2646 }
2647 if (base->fKind == Expression::kExternalValue_Kind) {
2648 return this->convertField(std::move(base), field);
2649 }
2650 switch (base->fType.kind()) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002651 case Type::kOther_Kind:
2652 case Type::kStruct_Kind:
2653 return this->convertField(std::move(base), field);
2654 default:
Ethan Nicholas7b9da252020-08-03 13:43:50 -04002655 return this->convertSwizzle(std::move(base), field);
Ethan Nicholasfc994162019-06-06 10:04:27 -04002656 }
2657}
2658
2659std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
2660 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
2661 if (!base) {
2662 return nullptr;
2663 }
2664 if (!base->fType.isNumber()) {
2665 fErrors.error(expression.fOffset,
2666 "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002667 "' cannot operate on '" + base->fType.displayName() + "'");
Ethan Nicholasfc994162019-06-06 10:04:27 -04002668 return nullptr;
2669 }
2670 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
2671 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
2672 expression.getToken().fKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07002673}
2674
2675void IRGenerator::checkValid(const Expression& expr) {
2676 switch (expr.fKind) {
2677 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002678 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07002679 break;
2680 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002681 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07002682 break;
2683 default:
ethannicholasea4567c2016-10-17 11:24:37 -07002684 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002685 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07002686 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002687 }
2688}
2689
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002690bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002691 int bits = 0;
2692 for (int idx : swizzle.fComponents) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002693 if (idx < 0) {
2694 fErrors.error(swizzle.fOffset, "cannot write to a swizzle mask containing a constant");
2695 return false;
2696 }
2697 SkASSERT(idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07002698 int bit = 1 << idx;
2699 if (bits & bit) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002700 fErrors.error(swizzle.fOffset,
2701 "cannot write to the same swizzle field more than once");
2702 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002703 }
2704 bits |= bit;
2705 }
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002706 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002707}
2708
John Stiles403a3632020-08-20 12:11:48 -04002709bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002710 switch (expr.fKind) {
2711 case Expression::kVariableReference_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002712 const Variable& var = expr.as<VariableReference>().fVariable;
Brian Osman3c358422020-03-23 10:44:12 -04002713 if (var.fModifiers.fFlags &
2714 (Modifiers::kConst_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag)) {
2715 fErrors.error(expr.fOffset, "cannot modify immutable variable '" + var.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002716 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002717 }
John Stiles403a3632020-08-20 12:11:48 -04002718 expr.as<VariableReference>().setRefKind(kind);
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002719 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002720 }
2721 case Expression::kFieldAccess_Kind:
John Stiles403a3632020-08-20 12:11:48 -04002722 return this->setRefKind(*expr.as<FieldAccess>().fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002723 case Expression::kSwizzle_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002724 const Swizzle& swizzle = expr.as<Swizzle>();
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002725 return this->checkSwizzleWrite(swizzle) && this->setRefKind(*swizzle.fBase, kind);
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002726 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002727 case Expression::kIndex_Kind:
John Stiles403a3632020-08-20 12:11:48 -04002728 return this->setRefKind(*expr.as<IndexExpression>().fBase, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002729 case Expression::kTernary_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002730 const TernaryExpression& t = expr.as<TernaryExpression>();
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002731 return this->setRefKind(*t.fIfTrue, kind) && this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002732 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04002733 case Expression::kExternalValue_Kind: {
John Stiles403a3632020-08-20 12:11:48 -04002734 const ExternalValue& v = *expr.as<ExternalValueReference>().fValue;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002735 if (!v.canWrite()) {
2736 fErrors.error(expr.fOffset,
2737 "cannot modify immutable external value '" + v.fName + "'");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002738 return false;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002739 }
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002740 return true;
Ethan Nicholas91164d12019-05-15 15:29:54 -04002741 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002742 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002743 fErrors.error(expr.fOffset, "cannot assign to this expression");
Ethan Nicholas4fadce42020-07-30 13:29:30 -04002744 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002745 }
2746}
2747
Robert Phillipsfe8da172018-01-24 14:52:02 +00002748void IRGenerator::convertProgram(Program::Kind kind,
2749 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002750 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002751 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00002752 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002753 fProgramElements = out;
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002754 Parser parser(text, length, *fSymbolTable, fErrors);
Ethan Nicholasfc994162019-06-06 10:04:27 -04002755 fFile = parser.file();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002756 if (fErrors.errorCount()) {
2757 return;
2758 }
Ethan Nicholasc18bb512020-07-28 14:46:53 -04002759 this->pushSymbolTable(); // this is popped by Compiler upon completion
Ethan Nicholasfc994162019-06-06 10:04:27 -04002760 SkASSERT(fFile);
2761 for (const auto& decl : fFile->root()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002762 switch (decl.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002763 case ASTNode::Kind::kVarDeclarations: {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002764 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04002765 decl,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002766 Variable::kGlobal_Storage);
2767 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002768 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002769 }
2770 break;
2771 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002772 case ASTNode::Kind::kEnum: {
2773 this->convertEnum(decl);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002774 break;
2775 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002776 case ASTNode::Kind::kFunction: {
2777 this->convertFunction(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002778 break;
2779 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002780 case ASTNode::Kind::kModifiers: {
2781 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002782 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002783 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002784 }
2785 break;
2786 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002787 case ASTNode::Kind::kInterfaceBlock: {
2788 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002789 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002790 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002791 }
2792 break;
2793 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002794 case ASTNode::Kind::kExtension: {
2795 std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
2796 decl.getString());
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002797 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002798 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002799 }
2800 break;
2801 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002802 case ASTNode::Kind::kSection: {
2803 std::unique_ptr<Section> s = this->convertSection(decl);
Ethan Nicholas762466e2017-06-29 10:03:38 -04002804 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002805 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002806 }
2807 break;
2808 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002809 default:
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002810#ifdef SK_DEBUG
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002811 ABORT("unsupported declaration: %s\n", decl.description().c_str());
Ethan Nicholas2a099da2020-01-02 14:40:54 -05002812#endif
2813 break;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002814 }
2815 }
2816}
2817
2818
John Stilesa6841be2020-08-06 14:11:56 -04002819} // namespace SkSL