blob: c416db63c3957b6b2aa4a1477c7173a8d23129d3 [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"
Ethan Nicholasaf197692017-02-27 13:26:45 -050011#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070012
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/sksl/SkSLCompiler.h"
14#include "src/sksl/SkSLParser.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/sksl/ir/SkSLBinaryExpression.h"
16#include "src/sksl/ir/SkSLBoolLiteral.h"
17#include "src/sksl/ir/SkSLBreakStatement.h"
18#include "src/sksl/ir/SkSLConstructor.h"
19#include "src/sksl/ir/SkSLContinueStatement.h"
20#include "src/sksl/ir/SkSLDiscardStatement.h"
21#include "src/sksl/ir/SkSLDoStatement.h"
22#include "src/sksl/ir/SkSLEnum.h"
23#include "src/sksl/ir/SkSLExpressionStatement.h"
Ethan Nicholas9e6a3932019-05-17 16:31:21 -040024#include "src/sksl/ir/SkSLExternalFunctionCall.h"
Ethan Nicholas91164d12019-05-15 15:29:54 -040025#include "src/sksl/ir/SkSLExternalValueReference.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/sksl/ir/SkSLField.h"
27#include "src/sksl/ir/SkSLFieldAccess.h"
28#include "src/sksl/ir/SkSLFloatLiteral.h"
29#include "src/sksl/ir/SkSLForStatement.h"
30#include "src/sksl/ir/SkSLFunctionCall.h"
31#include "src/sksl/ir/SkSLFunctionDeclaration.h"
32#include "src/sksl/ir/SkSLFunctionDefinition.h"
33#include "src/sksl/ir/SkSLFunctionReference.h"
34#include "src/sksl/ir/SkSLIfStatement.h"
35#include "src/sksl/ir/SkSLIndexExpression.h"
36#include "src/sksl/ir/SkSLIntLiteral.h"
37#include "src/sksl/ir/SkSLInterfaceBlock.h"
38#include "src/sksl/ir/SkSLLayout.h"
Chris Daltonb0fd4b12019-10-29 13:41:22 -060039#include "src/sksl/ir/SkSLNop.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/sksl/ir/SkSLNullLiteral.h"
41#include "src/sksl/ir/SkSLPostfixExpression.h"
42#include "src/sksl/ir/SkSLPrefixExpression.h"
43#include "src/sksl/ir/SkSLReturnStatement.h"
44#include "src/sksl/ir/SkSLSetting.h"
45#include "src/sksl/ir/SkSLSwitchCase.h"
46#include "src/sksl/ir/SkSLSwitchStatement.h"
47#include "src/sksl/ir/SkSLSwizzle.h"
48#include "src/sksl/ir/SkSLTernaryExpression.h"
49#include "src/sksl/ir/SkSLUnresolvedFunction.h"
50#include "src/sksl/ir/SkSLVarDeclarations.h"
51#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
52#include "src/sksl/ir/SkSLVariable.h"
53#include "src/sksl/ir/SkSLVariableReference.h"
54#include "src/sksl/ir/SkSLWhileStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070055
56namespace SkSL {
57
58class AutoSymbolTable {
59public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050060 AutoSymbolTable(IRGenerator* ir)
ethannicholasb3058bd2016-07-01 08:22:01 -070061 : fIR(ir)
62 , fPrevious(fIR->fSymbolTable) {
63 fIR->pushSymbolTable();
64 }
65
66 ~AutoSymbolTable() {
67 fIR->popSymbolTable();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040068 SkASSERT(fPrevious == fIR->fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -070069 }
70
71 IRGenerator* fIR;
72 std::shared_ptr<SymbolTable> fPrevious;
73};
74
ethannicholas22f939e2016-10-13 13:25:34 -070075class AutoLoopLevel {
76public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050077 AutoLoopLevel(IRGenerator* ir)
ethannicholas22f939e2016-10-13 13:25:34 -070078 : fIR(ir) {
79 fIR->fLoopLevel++;
80 }
81
82 ~AutoLoopLevel() {
83 fIR->fLoopLevel--;
84 }
85
86 IRGenerator* fIR;
87};
88
Ethan Nicholasaf197692017-02-27 13:26:45 -050089class AutoSwitchLevel {
90public:
91 AutoSwitchLevel(IRGenerator* ir)
92 : fIR(ir) {
93 fIR->fSwitchLevel++;
94 }
95
96 ~AutoSwitchLevel() {
97 fIR->fSwitchLevel--;
98 }
99
100 IRGenerator* fIR;
101};
102
Ethan Nicholas11d53972016-11-28 11:23:23 -0500103IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ethannicholasb3058bd2016-07-01 08:22:01 -0700104 ErrorReporter& errorReporter)
ethannicholasd598f792016-07-25 10:08:54 -0700105: fContext(*context)
106, fCurrentFunction(nullptr)
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107, fRootSymbolTable(symbolTable)
108, fSymbolTable(symbolTable)
ethannicholas22f939e2016-10-13 13:25:34 -0700109, fLoopLevel(0)
Ethan Nicholasaf197692017-02-27 13:26:45 -0500110, fSwitchLevel(0)
Ethan Nicholas762466e2017-06-29 10:03:38 -0400111, fTmpCount(0)
ethannicholasd598f792016-07-25 10:08:54 -0700112, fErrors(errorReporter) {}
ethannicholasb3058bd2016-07-01 08:22:01 -0700113
114void IRGenerator::pushSymbolTable() {
Ethan Nicholas8feeff92017-03-30 14:11:58 -0400115 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), &fErrors));
ethannicholasb3058bd2016-07-01 08:22:01 -0700116}
117
118void IRGenerator::popSymbolTable() {
119 fSymbolTable = fSymbolTable->fParent;
120}
121
Ethan Nicholas762466e2017-06-29 10:03:38 -0400122static void fill_caps(const SKSL_CAPS_CLASS& caps,
123 std::unordered_map<String, Program::Settings::Value>* capsMap) {
Brian Salomon23356442018-11-30 15:33:19 -0500124#define CAP(name) \
125 capsMap->insert(std::make_pair(String(#name), Program::Settings::Value(caps.name())))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500126 CAP(fbFetchSupport);
Brian Salomond4013302018-04-04 13:58:33 +0000127 CAP(fbFetchNeedsCustomOutput);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500128 CAP(flatInterpolationSupport);
129 CAP(noperspectiveInterpolationSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500130 CAP(externalTextureSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500131 CAP(mustEnableAdvBlendEqs);
132 CAP(mustEnableSpecificAdvBlendEqs);
133 CAP(mustDeclareFragmentShaderOutput);
Michael Ludwig4f94ef62018-09-12 15:22:16 -0400134 CAP(mustDoOpBetweenFloorAndAbs);
Brian Salomonf8c187c2019-12-19 14:41:57 -0500135 CAP(mustGuardDivisionEvenAfterExplicitZeroCheck);
136 CAP(inBlendModesFailRandomlyForAllZeroVec);
Michael Ludwig24d438b2018-09-12 15:22:50 -0400137 CAP(atan2ImplementedAsAtanYOverX);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500138 CAP(canUseAnyFunctionInShader);
Chris Dalton47c8ed32017-11-15 18:27:09 -0700139 CAP(floatIs32Bits);
Ethan Nicholas07990de2017-07-18 09:47:43 -0400140 CAP(integerSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500141#undef CAP
142}
143
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400144void IRGenerator::start(const Program::Settings* settings,
145 std::vector<std::unique_ptr<ProgramElement>>* inherited) {
Ethan Nicholas00543112018-07-31 09:44:36 -0400146 if (fStarted) {
147 this->popSymbolTable();
148 }
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500149 fSettings = settings;
150 fCapsMap.clear();
151 if (settings->fCaps) {
152 fill_caps(*settings->fCaps, &fCapsMap);
Ethan Nicholas00543112018-07-31 09:44:36 -0400153 } else {
154 fCapsMap.insert(std::make_pair(String("integerSupport"),
155 Program::Settings::Value(true)));
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500156 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500157 this->pushSymbolTable();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400158 fInvocations = -1;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500159 fInputs.reset();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000160 fSkPerVertex = nullptr;
161 fRTAdjust = nullptr;
162 fRTAdjustInterfaceBlock = nullptr;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400163 if (inherited) {
164 for (const auto& e : *inherited) {
165 if (e->fKind == ProgramElement::kInterfaceBlock_Kind) {
166 InterfaceBlock& intf = (InterfaceBlock&) *e;
167 if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400168 SkASSERT(!fSkPerVertex);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400169 fSkPerVertex = &intf.fVariable;
170 }
171 }
172 }
173 }
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500174 SkASSERT(fIntrinsics);
175 for (auto& pair : *fIntrinsics) {
176 pair.second.second = false;
177 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500178}
179
Ethan Nicholasfc994162019-06-06 10:04:27 -0400180std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragment name) {
181 return std::unique_ptr<Extension>(new Extension(offset, name));
ethannicholasb3058bd2016-07-01 08:22:01 -0700182}
183
Ethan Nicholasfc994162019-06-06 10:04:27 -0400184void IRGenerator::finish() {
185 this->popSymbolTable();
186 fSettings = nullptr;
187}
188
189std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700190 switch (statement.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400191 case ASTNode::Kind::kBlock:
192 return this->convertBlock(statement);
193 case ASTNode::Kind::kVarDeclarations:
194 return this->convertVarDeclarationStatement(statement);
195 case ASTNode::Kind::kIf:
196 return this->convertIf(statement);
197 case ASTNode::Kind::kFor:
198 return this->convertFor(statement);
199 case ASTNode::Kind::kWhile:
200 return this->convertWhile(statement);
201 case ASTNode::Kind::kDo:
202 return this->convertDo(statement);
203 case ASTNode::Kind::kSwitch:
204 return this->convertSwitch(statement);
205 case ASTNode::Kind::kReturn:
206 return this->convertReturn(statement);
207 case ASTNode::Kind::kBreak:
208 return this->convertBreak(statement);
209 case ASTNode::Kind::kContinue:
210 return this->convertContinue(statement);
211 case ASTNode::Kind::kDiscard:
212 return this->convertDiscard(statement);
213 default:
214 // it's an expression
215 std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000216 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400217 SkASSERT(result->fKind == Statement::kExpression_Kind);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000218 Expression& expr = *((ExpressionStatement&) *result).fExpression;
219 if (expr.fKind == Expression::kFunctionCall_Kind) {
220 FunctionCall& fc = (FunctionCall&) expr;
221 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
222 std::vector<std::unique_ptr<Statement>> statements;
223 statements.push_back(getNormalizeSkPositionCode());
224 statements.push_back(std::move(result));
225 return std::unique_ptr<Block>(new Block(statement.fOffset,
226 std::move(statements),
227 fSymbolTable));
228 }
229 }
230 }
231 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700232 }
233}
234
Ethan Nicholasfc994162019-06-06 10:04:27 -0400235std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
236 SkASSERT(block.fKind == ASTNode::Kind::kBlock);
ethannicholasb3058bd2016-07-01 08:22:01 -0700237 AutoSymbolTable table(this);
238 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400239 for (const auto& child : block) {
240 std::unique_ptr<Statement> statement = this->convertStatement(child);
ethannicholasb3058bd2016-07-01 08:22:01 -0700241 if (!statement) {
242 return nullptr;
243 }
244 statements.push_back(std::move(statement));
245 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700246 return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700247}
248
Ethan Nicholasfc994162019-06-06 10:04:27 -0400249std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
250 SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
251 auto decl = this->convertVarDeclarations(s, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700252 if (!decl) {
253 return nullptr;
254 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700255 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700256}
257
Ethan Nicholasfc994162019-06-06 10:04:27 -0400258std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNode& decls,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700259 Variable::Storage storage) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400260 SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
261 auto iter = decls.begin();
262 const Modifiers& modifiers = iter++->getModifiers();
263 const ASTNode& rawType = *(iter++);
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000264 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400265 const Type* baseType = this->convertType(rawType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700266 if (!baseType) {
267 return nullptr;
268 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500269 if (fKind != Program::kFragmentProcessor_Kind) {
270 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
271 baseType->kind() == Type::Kind::kMatrix_Kind) {
272 fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
273 }
274 if (modifiers.fLayout.fWhen.fLength) {
275 fErrors.error(decls.fOffset, "'when' is only permitted within fragment processors");
276 }
277 if (modifiers.fLayout.fFlags & Layout::kTracked_Flag) {
278 fErrors.error(decls.fOffset, "'tracked' is only permitted within fragment processors");
279 }
280 if (modifiers.fLayout.fCType != Layout::CType::kDefault) {
281 fErrors.error(decls.fOffset, "'ctype' is only permitted within fragment processors");
282 }
283 if (modifiers.fLayout.fKey) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400284 fErrors.error(decls.fOffset, "'key' is only permitted within fragment processors");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400285 }
Brian Osman2fe83fe2019-12-16 13:17:59 -0500286 }
287 if (modifiers.fLayout.fKey && (modifiers.fFlags & Modifiers::kUniform_Flag)) {
288 fErrors.error(decls.fOffset, "'key' is not permitted on 'uniform' variables");
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400289 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400290 for (; iter != decls.end(); ++iter) {
291 const ASTNode& varDecl = *iter;
292 if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
293 (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
294 varDecl.getVarData().fName != "sk_FragColor") {
295 fErrors.error(varDecl.fOffset,
Ethan Nicholas6c942712018-03-16 09:45:11 -0400296 "out location=0, index=0 is reserved for sk_FragColor");
297 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400298 const ASTNode::VarData& varData = varDecl.getVarData();
ethannicholasd598f792016-07-25 10:08:54 -0700299 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700300 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400301 auto iter = varDecl.begin();
302 for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
303 const ASTNode& rawSize = *iter;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700304 if (rawSize) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400305 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700306 if (!size) {
307 return nullptr;
308 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700309 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500310 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700311 if (size->fKind == Expression::kIntLiteral_Kind) {
312 count = ((IntLiteral&) *size).fValue;
313 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700314 fErrors.error(size->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400315 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700316 }
317 name += "[" + to_string(count) + "]";
318 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400319 fErrors.error(size->fOffset, "array size must be specified");
320 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700321 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400322 type = (Type*) fSymbolTable->takeOwnership(
323 std::unique_ptr<Symbol>(new Type(name,
324 Type::kArray_Kind,
325 *type,
326 (int) count)));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700327 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700328 } else {
Ethan Nicholas91164d12019-05-15 15:29:54 -0400329 type = (Type*) fSymbolTable->takeOwnership(
330 std::unique_ptr<Symbol>(new Type(type->name() + "[]",
331 Type::kArray_Kind,
332 *type,
333 -1)));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700334 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700335 }
336 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400337 auto var = std::unique_ptr<Variable>(new Variable(varDecl.fOffset, modifiers,
338 varData.fName, *type, storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000339 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400340 SkASSERT(!fRTAdjust);
341 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000342 fRTAdjust = var.get();
343 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700344 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400345 if (iter != varDecl.end()) {
346 value = this->convertExpression(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700347 if (!value) {
348 return nullptr;
349 }
ethannicholasd598f792016-07-25 10:08:54 -0700350 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500351 if (!value) {
352 return nullptr;
353 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400354 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500355 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700356 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400357 if (storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor" &&
358 (*fSymbolTable)[var->fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700359 // already defined, ignore
Ethan Nicholasfc994162019-06-06 10:04:27 -0400360 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[var->fName] &&
361 (*fSymbolTable)[var->fName]->fKind == Symbol::kVariable_Kind &&
362 ((Variable*) (*fSymbolTable)[var->fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700363 // already defined, just update the modifiers
Ethan Nicholasfc994162019-06-06 10:04:27 -0400364 Variable* old = (Variable*) (*fSymbolTable)[var->fName];
ethannicholasf789b382016-08-03 12:43:36 -0700365 old->fModifiers = var->fModifiers;
366 } else {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000367 variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
368 std::move(value)));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400369 StringFragment name = var->fName;
370 fSymbolTable->add(name, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700371 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700372 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400373 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decls.fOffset,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700374 baseType,
375 std::move(variables)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700376}
377
Ethan Nicholasfc994162019-06-06 10:04:27 -0400378std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
379 SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
380 Modifiers modifiers = m.getModifiers();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400381 if (modifiers.fLayout.fInvocations != -1) {
Ethan Nicholasf06576b2019-04-03 15:45:25 -0400382 if (fKind != Program::kGeometry_Kind) {
383 fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
384 return nullptr;
385 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400386 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600387 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400388 modifiers.fLayout.fInvocations = -1;
389 Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400390 SkASSERT(invocationId);
Ethan Nicholasd1d52562018-03-20 16:30:34 -0400391 invocationId->fModifiers.fFlags = 0;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400392 invocationId->fModifiers.fLayout.fBuiltin = -1;
393 if (modifiers.fLayout.description() == "") {
394 return nullptr;
395 }
396 }
397 }
398 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600399 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400400 modifiers.fLayout.fMaxVertices *= fInvocations;
401 }
402 return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
ethannicholas5961bc92016-10-12 06:39:56 -0700403}
404
Ethan Nicholasfc994162019-06-06 10:04:27 -0400405std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
406 SkASSERT(n.fKind == ASTNode::Kind::kIf);
407 auto iter = n.begin();
408 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -0700409 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700410 if (!test) {
411 return nullptr;
412 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400413 std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700414 if (!ifTrue) {
415 return nullptr;
416 }
417 std::unique_ptr<Statement> ifFalse;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400418 if (iter != n.end()) {
419 ifFalse = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 if (!ifFalse) {
421 return nullptr;
422 }
423 }
ethannicholas08a92112016-11-09 13:26:45 -0800424 if (test->fKind == Expression::kBoolLiteral_Kind) {
425 // static boolean value, fold down to a single branch
426 if (((BoolLiteral&) *test).fValue) {
427 return ifTrue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400428 } else if (ifFalse) {
ethannicholas08a92112016-11-09 13:26:45 -0800429 return ifFalse;
430 } else {
431 // False & no else clause. Not an error, so don't return null!
432 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400433 return std::unique_ptr<Statement>(new Block(n.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800434 fSymbolTable));
435 }
436 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400437 return std::unique_ptr<Statement>(new IfStatement(n.fOffset, n.getBool(), std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700438 std::move(ifTrue), std::move(ifFalse)));
439}
440
Ethan Nicholasfc994162019-06-06 10:04:27 -0400441std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
442 SkASSERT(f.fKind == ASTNode::Kind::kFor);
ethannicholas22f939e2016-10-13 13:25:34 -0700443 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700444 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700445 std::unique_ptr<Statement> initializer;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400446 auto iter = f.begin();
447 if (*iter) {
448 initializer = this->convertStatement(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700449 if (!initializer) {
450 return nullptr;
451 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700452 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400453 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700454 std::unique_ptr<Expression> test;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400455 if (*iter) {
456 test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
ethannicholas22f939e2016-10-13 13:25:34 -0700457 if (!test) {
458 return nullptr;
459 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700460 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400461 ++iter;
ethannicholas22f939e2016-10-13 13:25:34 -0700462 std::unique_ptr<Expression> next;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400463 if (*iter) {
464 next = this->convertExpression(*iter);
ethannicholas22f939e2016-10-13 13:25:34 -0700465 if (!next) {
466 return nullptr;
467 }
468 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700469 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400470 ++iter;
471 std::unique_ptr<Statement> statement = this->convertStatement(*iter);
ethannicholasb3058bd2016-07-01 08:22:01 -0700472 if (!statement) {
473 return nullptr;
474 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700475 return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer),
ethannicholasb3058bd2016-07-01 08:22:01 -0700476 std::move(test), std::move(next),
ethannicholasd598f792016-07-25 10:08:54 -0700477 std::move(statement), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700478}
479
Ethan Nicholasfc994162019-06-06 10:04:27 -0400480std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
481 SkASSERT(w.fKind == ASTNode::Kind::kWhile);
ethannicholas22f939e2016-10-13 13:25:34 -0700482 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400483 auto iter = w.begin();
484 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -0700485 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700486 if (!test) {
487 return nullptr;
488 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400489 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700490 if (!statement) {
491 return nullptr;
492 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700493 return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700494 std::move(statement)));
495}
496
Ethan Nicholasfc994162019-06-06 10:04:27 -0400497std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
498 SkASSERT(d.fKind == ASTNode::Kind::kDo);
ethannicholas22f939e2016-10-13 13:25:34 -0700499 AutoLoopLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400500 auto iter = d.begin();
501 std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
502 if (!statement) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700503 return nullptr;
504 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400505 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
506 *fContext.fBool_Type);
507 if (!test) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700508 return nullptr;
509 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700510 return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
ethannicholasb3058bd2016-07-01 08:22:01 -0700511 std::move(test)));
512}
513
Ethan Nicholasfc994162019-06-06 10:04:27 -0400514std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
515 SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500516 AutoSwitchLevel level(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400517 auto iter = s.begin();
518 std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500519 if (!value) {
520 return nullptr;
521 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500522 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500523 value = this->coerce(std::move(value), *fContext.fInt_Type);
524 if (!value) {
525 return nullptr;
526 }
527 }
528 AutoSymbolTable table(this);
529 std::unordered_set<int> caseValues;
530 std::vector<std::unique_ptr<SwitchCase>> cases;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400531 for (; iter != s.end(); ++iter) {
532 const ASTNode& c = *iter;
533 SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500534 std::unique_ptr<Expression> caseValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400535 auto childIter = c.begin();
536 if (*childIter) {
537 caseValue = this->convertExpression(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500538 if (!caseValue) {
539 return nullptr;
540 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500541 caseValue = this->coerce(std::move(caseValue), value->fType);
542 if (!caseValue) {
543 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500544 }
545 if (!caseValue->isConstant()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700546 fErrors.error(caseValue->fOffset, "case value must be a constant");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500547 return nullptr;
548 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500549 int64_t v;
550 this->getConstantInt(*caseValue, &v);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500551 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700552 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500553 }
554 caseValues.insert(v);
555 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400556 ++childIter;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500557 std::vector<std::unique_ptr<Statement>> statements;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400558 for (; childIter != c.end(); ++childIter) {
559 std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500560 if (!converted) {
561 return nullptr;
562 }
563 statements.push_back(std::move(converted));
564 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400565 cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500566 std::move(statements)));
567 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400568 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400569 std::move(value), std::move(cases),
570 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500571}
572
Ethan Nicholasfc994162019-06-06 10:04:27 -0400573std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
574 std::unique_ptr<Expression> e = this->convertExpression(s);
ethannicholasb3058bd2016-07-01 08:22:01 -0700575 if (!e) {
576 return nullptr;
577 }
578 this->checkValid(*e);
579 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
580}
581
Ethan Nicholasfc994162019-06-06 10:04:27 -0400582std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
583 SkASSERT(r.fKind == ASTNode::Kind::kReturn);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400584 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000585 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400586 // 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 +0000587 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400588 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400589 if (r.begin() != r.end()) {
590 std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -0700591 if (!result) {
592 return nullptr;
593 }
ethannicholasd598f792016-07-25 10:08:54 -0700594 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700595 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700596 } else {
597 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
598 if (!result) {
599 return nullptr;
600 }
601 }
602 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
603 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700604 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700605 fErrors.error(r.fOffset, "expected function to return '" +
606 fCurrentFunction->fReturnType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700607 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700608 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700609 }
610}
611
Ethan Nicholasfc994162019-06-06 10:04:27 -0400612std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
613 SkASSERT(b.fKind == ASTNode::Kind::kBreak);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500614 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700615 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700616 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700617 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700618 return nullptr;
619 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700620}
621
Ethan Nicholasfc994162019-06-06 10:04:27 -0400622std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
623 SkASSERT(c.fKind == ASTNode::Kind::kContinue);
ethannicholas22f939e2016-10-13 13:25:34 -0700624 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700625 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700626 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700627 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700628 return nullptr;
629 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700630}
631
Ethan Nicholasfc994162019-06-06 10:04:27 -0400632std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
633 SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700634 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700635}
636
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500637std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400638 Layout invokeLayout;
639 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700640 FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400641 invokeModifiers,
642 "_invoke",
643 std::vector<const Variable*>(),
644 *fContext.fVoid_Type);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500645 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
646 new FunctionDefinition(-1, *invokeDecl, std::move(main))));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400647 fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
648
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000649 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400650 Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400651 SkASSERT(loopIdx);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700652 std::unique_ptr<Expression> test(new BinaryExpression(-1,
653 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400654 Token::LT,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700655 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400656 *fContext.fBool_Type));
657 std::unique_ptr<Expression> next(new PostfixExpression(
658 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700659 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400660 *loopIdx,
661 VariableReference::kReadWrite_RefKind)),
662 Token::PLUSPLUS));
Ethan Nicholasfc994162019-06-06 10:04:27 -0400663 ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400664 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400665 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400666
667 std::vector<std::unique_ptr<Statement>> loopBody;
668 std::vector<std::unique_ptr<Expression>> invokeArgs;
669 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700670 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400671 *invokeDecl,
672 std::vector<std::unique_ptr<Expression>>()))));
673 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700674 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400675 std::move(endPrimitive),
676 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700677 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
678 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400679 Token::EQ,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700680 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400681 *fContext.fInt_Type));
682 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
683 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700684 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400685 std::move(initializer),
686 std::move(test),
687 std::move(next),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700688 std::unique_ptr<Block>(new Block(-1, std::move(loopBody))),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400689 fSymbolTable));
690 std::vector<std::unique_ptr<Statement>> children;
691 children.push_back(std::move(loop));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700692 return std::unique_ptr<Block>(new Block(-1, std::move(children)));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400693}
694
Robert Phillipsfe8da172018-01-24 14:52:02 +0000695std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400696 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000697 // 0,
698 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400699 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000700 #define REF(var) std::unique_ptr<Expression>(\
701 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
702 #define FIELD(var, idx) std::unique_ptr<Expression>(\
703 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
704 #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \
705 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
706 #define ADJUST (fRTAdjustInterfaceBlock ? \
707 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
708 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400709 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
710 { __VA_ARGS__ }))
711 #define OP(left, op, right) std::unique_ptr<Expression>( \
712 new BinaryExpression(-1, left, op, right, \
713 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000714 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400715 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::STAR, SWIZZLE(ADJUST, 0, 2)),
Robert Phillipsfe8da172018-01-24 14:52:02 +0000716 Token::PLUS,
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400717 OP(SWIZZLE(POS, 3, 3), Token::STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000718 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
719 children.push_back(SWIZZLE(POS, 3));
720 std::unique_ptr<Expression> result = OP(POS, Token::EQ,
721 std::unique_ptr<Expression>(new Constructor(-1,
722 *fContext.fFloat4_Type,
723 std::move(children))));
724 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
725}
726
Ethan Nicholasfc994162019-06-06 10:04:27 -0400727void IRGenerator::convertFunction(const ASTNode& f) {
728 auto iter = f.begin();
729 const Type* returnType = this->convertType(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700730 if (!returnType) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400731 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700732 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400733 const ASTNode::FunctionData& fd = f.getFunctionData();
ethannicholasd598f792016-07-25 10:08:54 -0700734 std::vector<const Variable*> parameters;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400735 for (size_t i = 0; i < fd.fParameterCount; ++i) {
736 const ASTNode& param = *(iter++);
737 SkASSERT(param.fKind == ASTNode::Kind::kParameter);
738 ASTNode::ParameterData pd = param.getParameterData();
739 auto paramIter = param.begin();
740 const Type* type = this->convertType(*(paramIter++));
ethannicholasb3058bd2016-07-01 08:22:01 -0700741 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400742 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700743 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400744 for (int j = (int) pd.fSizeCount; j >= 1; j--) {
745 int size = (param.begin() + j)->getInt();
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400746 String name = type->name() + "[" + to_string(size) + "]";
Ethan Nicholas91164d12019-05-15 15:29:54 -0400747 type = (Type*) fSymbolTable->takeOwnership(
748 std::unique_ptr<Symbol>(new Type(std::move(name),
749 Type::kArray_Kind,
750 *type,
751 size)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700752 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400753 StringFragment name = pd.fName;
Ethan Nicholas91164d12019-05-15 15:29:54 -0400754 Variable* var = (Variable*) fSymbolTable->takeOwnership(
Ethan Nicholasfc994162019-06-06 10:04:27 -0400755 std::unique_ptr<Symbol>(new Variable(param.fOffset,
756 pd.fModifiers,
Ethan Nicholas91164d12019-05-15 15:29:54 -0400757 name,
758 *type,
759 Variable::kParameter_Storage)));
ethannicholasd598f792016-07-25 10:08:54 -0700760 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700761 }
762
Ethan Nicholasfc994162019-06-06 10:04:27 -0400763 if (fd.fName == "main") {
Ethan Nicholas0d997662019-04-08 09:46:01 -0400764 switch (fKind) {
765 case Program::kPipelineStage_Kind: {
766 bool valid;
767 switch (parameters.size()) {
768 case 3:
Mike Reed8c31f2b2019-07-16 16:50:14 -0400769 valid = parameters[0]->fType == *fContext.fFloat_Type &&
Ethan Nicholas0d997662019-04-08 09:46:01 -0400770 parameters[0]->fModifiers.fFlags == 0 &&
Mike Reed8c31f2b2019-07-16 16:50:14 -0400771 parameters[1]->fType == *fContext.fFloat_Type &&
Ethan Nicholas0d997662019-04-08 09:46:01 -0400772 parameters[1]->fModifiers.fFlags == 0 &&
773 parameters[2]->fType == *fContext.fHalf4_Type &&
774 parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
775 Modifiers::kOut_Flag);
776 break;
777 case 1:
778 valid = parameters[0]->fType == *fContext.fHalf4_Type &&
779 parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
780 Modifiers::kOut_Flag);
781 break;
782 default:
783 valid = false;
784 }
785 if (!valid) {
Mike Reed8c31f2b2019-07-16 16:50:14 -0400786 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(float, "
787 "float, inout half4) or main(inout half4)");
Ethan Nicholas0d997662019-04-08 09:46:01 -0400788 return;
789 }
790 break;
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500791 }
Ethan Nicholas746035a2019-04-23 13:31:09 -0400792 case Program::kGeneric_Kind:
Ethan Nicholas0d997662019-04-08 09:46:01 -0400793 break;
Ethan Nicholas0d997662019-04-08 09:46:01 -0400794 default:
795 if (parameters.size()) {
796 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
797 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400798 }
799 }
800
ethannicholasb3058bd2016-07-01 08:22:01 -0700801 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700802 const FunctionDeclaration* decl = nullptr;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400803 auto entry = (*fSymbolTable)[fd.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700804 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700805 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700806 switch (entry->fKind) {
807 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700808 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700809 break;
810 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700811 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700812 break;
813 default:
Ethan Nicholasfc994162019-06-06 10:04:27 -0400814 fErrors.error(f.fOffset, "symbol '" + fd.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400815 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700816 }
817 for (const auto& other : functions) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400818 SkASSERT(other->fName == fd.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700819 if (parameters.size() == other->fParameters.size()) {
820 bool match = true;
821 for (size_t i = 0; i < parameters.size(); i++) {
822 if (parameters[i]->fType != other->fParameters[i]->fType) {
823 match = false;
824 break;
825 }
826 }
827 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700828 if (*returnType != other->fReturnType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400829 FunctionDeclaration newDecl(f.fOffset, fd.fModifiers, fd.fName, parameters,
Ethan Nicholascb670962017-04-20 19:31:52 -0400830 *returnType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700831 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
832 "' and '" + other->description() +
833 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400834 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700835 }
836 decl = other;
837 for (size_t i = 0; i < parameters.size(); i++) {
838 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700839 fErrors.error(f.fOffset, "modifiers on parameter " +
840 to_string((uint64_t) i + 1) +
841 " differ between declaration and "
842 "definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400843 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700844 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700845 }
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500846 if (other->fDefined && !other->fBuiltin) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700847 fErrors.error(f.fOffset, "duplicate definition of " +
848 other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700849 }
850 break;
851 }
852 }
853 }
854 }
855 if (!decl) {
856 // couldn't find an existing declaration
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700857 auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -0400858 fd.fModifiers,
859 fd.fName,
ethannicholas471e8942016-10-28 09:02:46 -0700860 parameters,
861 *returnType));
862 decl = newDecl.get();
863 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -0700864 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400865 if (iter != f.end()) {
866 // compile body
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400867 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -0700868 fCurrentFunction = decl;
869 decl->fDefined = true;
870 std::shared_ptr<SymbolTable> old = fSymbolTable;
871 AutoSymbolTable table(this);
Ethan Nicholasfc994162019-06-06 10:04:27 -0400872 if (fd.fName == "main" && fKind == Program::kPipelineStage_Kind) {
Ethan Nicholasa70693b2019-03-04 13:07:36 -0500873 if (parameters.size() == 3) {
874 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_X_BUILTIN;
875 parameters[1]->fModifiers.fLayout.fBuiltin = SK_MAIN_Y_BUILTIN;
876 parameters[2]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
877 } else {
878 SkASSERT(parameters.size() == 1);
879 parameters[0]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
880 }
Ethan Nicholas00543112018-07-31 09:44:36 -0400881 }
ethannicholasd598f792016-07-25 10:08:54 -0700882 for (size_t i = 0; i < parameters.size(); i++) {
883 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -0700884 }
Ethan Nicholasfc994162019-06-06 10:04:27 -0400885 bool needInvocationIDWorkaround = fInvocations != -1 && fd.fName == "main" &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600886 fSettings->fCaps &&
887 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400888 SkASSERT(!fExtraVars.size());
Ethan Nicholasfc994162019-06-06 10:04:27 -0400889 std::unique_ptr<Block> body = this->convertBlock(*iter);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400890 for (auto& v : fExtraVars) {
891 body->fStatements.insert(body->fStatements.begin(), std::move(v));
892 }
893 fExtraVars.clear();
ethannicholasd598f792016-07-25 10:08:54 -0700894 fCurrentFunction = nullptr;
895 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400896 return;
897 }
898 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500899 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -0700900 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400901 // conservatively assume all user-defined functions have side effects
902 ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400903 if (Program::kVertex_Kind == fKind && fd.fName == "main" && fRTAdjust) {
Robert Phillipsfe8da172018-01-24 14:52:02 +0000904 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
905 }
Ethan Nicholasdb80f692019-11-22 14:06:12 -0500906 std::unique_ptr<FunctionDefinition> result(new FunctionDefinition(f.fOffset, *decl,
907 std::move(body)));
908 result->fSource = &f;
909 fProgramElements->push_back(std::move(result));
ethannicholasb3058bd2016-07-01 08:22:01 -0700910 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700911}
912
Ethan Nicholasfc994162019-06-06 10:04:27 -0400913std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
914 SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
915 ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
ethannicholasb3058bd2016-07-01 08:22:01 -0700916 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500917 this->pushSymbolTable();
918 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -0700919 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400920 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000921 bool foundRTAdjust = false;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400922 auto iter = intf.begin();
923 for (size_t i = 0; i < id.fDeclarationCount; ++i) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700924 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -0400925 *(iter++),
Ethan Nicholasa7ceb502019-01-11 10:31:48 -0500926 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -0700927 if (!decl) {
928 return nullptr;
929 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000930 for (const auto& stmt : decl->fVars) {
931 VarDeclaration& vd = (VarDeclaration&) *stmt;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400932 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000933 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400934 "only the last entry in an interface block may be a runtime-sized "
935 "array");
936 }
Robert Phillipsfe8da172018-01-24 14:52:02 +0000937 if (vd.fVar == fRTAdjust) {
938 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400939 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000940 fRTAdjustFieldIndex = fields.size();
941 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000942 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
943 &vd.fVar->fType));
944 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700945 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700946 "initializers are not permitted on interface block fields");
947 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000948 if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
Ethan Nicholasfc994162019-06-06 10:04:27 -0400949 Modifiers::kOut_Flag |
950 Modifiers::kUniform_Flag |
951 Modifiers::kBuffer_Flag |
952 Modifiers::kConst_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700953 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700954 "interface block fields may not have storage qualifiers");
955 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000956 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
957 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400958 haveRuntimeArray = true;
959 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500960 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700961 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500962 this->popSymbolTable();
Ethan Nicholas91164d12019-05-15 15:29:54 -0400963 Type* type = (Type*) old->takeOwnership(std::unique_ptr<Symbol>(new Type(intf.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -0400964 id.fTypeName,
Ethan Nicholas91164d12019-05-15 15:29:54 -0400965 fields)));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500966 std::vector<std::unique_ptr<Expression>> sizes;
Ethan Nicholasfc994162019-06-06 10:04:27 -0400967 for (size_t i = 0; i < id.fSizeCount; ++i) {
968 const ASTNode& size = *(iter++);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500969 if (size) {
Ethan Nicholasfc994162019-06-06 10:04:27 -0400970 std::unique_ptr<Expression> converted = this->convertExpression(size);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500971 if (!converted) {
972 return nullptr;
973 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400974 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500975 int64_t count;
976 if (converted->fKind == Expression::kIntLiteral_Kind) {
977 count = ((IntLiteral&) *converted).fValue;
978 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700979 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas66d80062019-09-09 14:50:51 -0400980 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500981 }
982 name += "[" + to_string(count) + "]";
983 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400984 fErrors.error(intf.fOffset, "array size must be specified");
985 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500986 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400987 type = (Type*) symbols->takeOwnership(std::unique_ptr<Symbol>(
988 new Type(name,
989 Type::kArray_Kind,
990 *type,
991 (int) count)));
Ethan Nicholas50afc172017-02-16 14:49:57 -0500992 sizes.push_back(std::move(converted));
993 } else {
Ethan Nicholas66d80062019-09-09 14:50:51 -0400994 fErrors.error(intf.fOffset, "array size must be specified");
995 return nullptr;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500996 }
997 }
Ethan Nicholas91164d12019-05-15 15:29:54 -0400998 Variable* var = (Variable*) old->takeOwnership(std::unique_ptr<Symbol>(
999 new Variable(intf.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001000 id.fModifiers,
1001 id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
Ethan Nicholas91164d12019-05-15 15:29:54 -04001002 *type,
1003 Variable::kGlobal_Storage)));
Robert Phillipsfe8da172018-01-24 14:52:02 +00001004 if (foundRTAdjust) {
1005 fRTAdjustInterfaceBlock = var;
1006 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001007 if (id.fInstanceName.fLength) {
1008 old->addWithoutOwnership(id.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -07001009 } else {
1010 for (size_t i = 0; i < fields.size(); i++) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001011 old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
ethannicholasd598f792016-07-25 10:08:54 -07001012 (int) i)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001013 }
1014 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001015 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
Ethan Nicholas8feeff92017-03-30 14:11:58 -04001016 var,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001017 id.fTypeName,
1018 id.fInstanceName,
Ethan Nicholas50afc172017-02-16 14:49:57 -05001019 std::move(sizes),
Ethan Nicholas68dd2c12018-03-01 15:05:17 -05001020 symbols));
ethannicholasb3058bd2016-07-01 08:22:01 -07001021}
1022
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001023void IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
1024 switch (value.fKind) {
1025 case Expression::kIntLiteral_Kind:
1026 *out = ((const IntLiteral&) value).fValue;
1027 break;
1028 case Expression::kVariableReference_Kind: {
1029 const Variable& var = ((VariableReference&) value).fVariable;
1030 if ((var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
1031 var.fInitialValue) {
1032 this->getConstantInt(*var.fInitialValue, out);
1033 }
1034 break;
1035 }
1036 default:
1037 fErrors.error(value.fOffset, "expected a constant int");
1038 }
1039}
1040
Ethan Nicholasfc994162019-06-06 10:04:27 -04001041void IRGenerator::convertEnum(const ASTNode& e) {
1042 SkASSERT(e.fKind == ASTNode::Kind::kEnum);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001043 std::vector<Variable*> variables;
1044 int64_t currentValue = 0;
1045 Layout layout;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001046 ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
1047 ASTNode::TypeData(e.getString(), false, false));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001048 const Type* type = this->convertType(enumType);
1049 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Ethan Nicholaseace9352018-10-15 20:09:54 +00001050 std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable, &fErrors));
1051 fSymbolTable = symbols;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001052 for (auto iter = e.begin(); iter != e.end(); ++iter) {
1053 const ASTNode& child = *iter;
1054 SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001055 std::unique_ptr<Expression> value;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001056 if (child.begin() != child.end()) {
1057 value = this->convertExpression(*child.begin());
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001058 if (!value) {
Ethan Nicholaseace9352018-10-15 20:09:54 +00001059 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001060 return;
1061 }
1062 this->getConstantInt(*value, &currentValue);
1063 }
1064 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
1065 ++currentValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04001066 auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, child.getString(),
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001067 *type, Variable::kGlobal_Storage,
1068 value.get()));
1069 variables.push_back(var.get());
Ethan Nicholasfc994162019-06-06 10:04:27 -04001070 symbols->add(child.getString(), std::move(var));
Ethan Nicholas91164d12019-05-15 15:29:54 -04001071 symbols->takeOwnership(std::move(value));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001072 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001073 fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.getString(),
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001074 symbols)));
Ethan Nicholaseace9352018-10-15 20:09:54 +00001075 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001076}
1077
Ethan Nicholasfc994162019-06-06 10:04:27 -04001078const Type* IRGenerator::convertType(const ASTNode& type) {
1079 ASTNode::TypeData td = type.getTypeData();
1080 const Symbol* result = (*fSymbolTable)[td.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -07001081 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001082 if (td.fIsNullable) {
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001083 if (((Type&) *result) == *fContext.fFragmentProcessor_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001084 if (type.begin() != type.end()) {
1085 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001086 "an array");
1087 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001088 result = fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
1089 new Type(String(result->fName) + "?",
1090 Type::kNullable_Kind,
1091 (const Type&) *result)));
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001092 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001093 fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001094 }
1095 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001096 for (const auto& size : type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001097 String name(result->fName);
1098 name += "[";
Ethan Nicholasfc994162019-06-06 10:04:27 -04001099 if (size) {
1100 name += to_string(size.getInt());
Ethan Nicholas50afc172017-02-16 14:49:57 -05001101 }
1102 name += "]";
Ethan Nicholas91164d12019-05-15 15:29:54 -04001103 result = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
1104 new Type(name,
1105 Type::kArray_Kind,
1106 (const Type&) *result,
Brian Osmanb9416ca2019-06-12 16:18:32 -04001107 size ? size.getInt()
1108 : 0)));
Ethan Nicholas50afc172017-02-16 14:49:57 -05001109 }
ethannicholasd598f792016-07-25 10:08:54 -07001110 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001111 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001112 fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001113 return nullptr;
1114}
1115
Ethan Nicholasfc994162019-06-06 10:04:27 -04001116std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001117 switch (expr.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001118 case ASTNode::Kind::kBinary:
1119 return this->convertBinaryExpression(expr);
1120 case ASTNode::Kind::kBool:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001121 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001122 expr.getBool()));
1123 case ASTNode::Kind::kCall:
1124 return this->convertCallExpression(expr);
1125 case ASTNode::Kind::kField:
1126 return this->convertFieldExpression(expr);
1127 case ASTNode::Kind::kFloat:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001128 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04001129 expr.getFloat()));
1130 case ASTNode::Kind::kIdentifier:
1131 return this->convertIdentifier(expr);
1132 case ASTNode::Kind::kIndex:
1133 return this->convertIndexExpression(expr);
1134 case ASTNode::Kind::kInt:
1135 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
1136 expr.getInt()));
1137 case ASTNode::Kind::kNull:
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001138 return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
Ethan Nicholasfc994162019-06-06 10:04:27 -04001139 case ASTNode::Kind::kPostfix:
1140 return this->convertPostfixExpression(expr);
1141 case ASTNode::Kind::kPrefix:
1142 return this->convertPrefixExpression(expr);
1143 case ASTNode::Kind::kTernary:
1144 return this->convertTernaryExpression(expr);
ethannicholasb3058bd2016-07-01 08:22:01 -07001145 default:
Ethan Nicholasfc994162019-06-06 10:04:27 -04001146 ABORT("unsupported expression: %s\n", expr.description().c_str());
ethannicholasb3058bd2016-07-01 08:22:01 -07001147 }
1148}
1149
Ethan Nicholasfc994162019-06-06 10:04:27 -04001150std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
1151 SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
1152 const Symbol* result = (*fSymbolTable)[identifier.getString()];
ethannicholasb3058bd2016-07-01 08:22:01 -07001153 if (!result) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001154 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001155 return nullptr;
1156 }
1157 switch (result->fKind) {
1158 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001159 std::vector<const FunctionDeclaration*> f = {
1160 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -07001161 };
ethannicholasd598f792016-07-25 10:08:54 -07001162 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001163 identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001164 f));
ethannicholasb3058bd2016-07-01 08:22:01 -07001165 }
1166 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001167 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
1168 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001169 identifier.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001170 f->fFunctions));
1171 }
1172 case Symbol::kVariable_Kind: {
Ethan Nicholas38657112017-02-09 17:01:22 -05001173 const Variable* var = (const Variable*) result;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001174 switch (var->fModifiers.fLayout.fBuiltin) {
1175 case SK_WIDTH_BUILTIN:
1176 fInputs.fRTWidth = true;
1177 break;
1178 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001179 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001180 break;
1181#ifndef SKSL_STANDALONE
1182 case SK_FRAGCOORD_BUILTIN:
Brian Osman9f313b62019-10-02 12:03:11 -04001183 fInputs.fFlipY = true;
1184 if (fSettings->fFlipY &&
1185 (!fSettings->fCaps ||
1186 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1187 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001188 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001189#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001190 }
Ethan Nicholas33c59ed2019-08-13 10:21:38 -04001191 if (fKind == Program::kFragmentProcessor_Kind &&
1192 (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
1193 !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
1194 !var->fModifiers.fLayout.fKey &&
1195 var->fModifiers.fLayout.fBuiltin == -1 &&
1196 var->fType.nonnullable() != *fContext.fFragmentProcessor_Type &&
1197 var->fType.kind() != Type::kSampler_Kind) {
1198 bool valid = false;
1199 for (const auto& decl : fFile->root()) {
1200 if (decl.fKind == ASTNode::Kind::kSection) {
1201 ASTNode::SectionData section = decl.getSectionData();
1202 if (section.fName == "setData") {
1203 valid = true;
1204 break;
1205 }
1206 }
1207 }
1208 if (!valid) {
1209 fErrors.error(identifier.fOffset, "'in' variable must be either 'uniform' or "
1210 "'layout(key)', or there must be a custom "
1211 "@setData function");
1212 }
1213 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001214 // default to kRead_RefKind; this will be corrected later if the variable is written to
1215 return std::unique_ptr<VariableReference>(new VariableReference(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001216 identifier.fOffset,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001217 *var,
1218 VariableReference::kRead_RefKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001219 }
1220 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001221 const Field* field = (const Field*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001222 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001223 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001224 return std::unique_ptr<Expression>(new FieldAccess(
1225 std::unique_ptr<Expression>(base),
1226 field->fFieldIndex,
1227 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001228 }
1229 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001230 const Type* t = (const Type*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001231 return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001232 *t));
ethannicholasb3058bd2016-07-01 08:22:01 -07001233 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04001234 case Symbol::kExternal_Kind: {
1235 ExternalValue* r = (ExternalValue*) result;
1236 return std::unique_ptr<ExternalValueReference>(
1237 new ExternalValueReference(identifier.fOffset, r));
1238 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001239 default:
1240 ABORT("unsupported symbol type %d\n", result->fKind);
1241 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001242}
1243
Ethan Nicholasfc994162019-06-06 10:04:27 -04001244std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
1245 ASTNode::SectionData section = s.getSectionData();
1246 return std::unique_ptr<Section>(new Section(s.fOffset, section.fName, section.fArgument,
1247 section.fText));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001248}
1249
1250
Ethan Nicholas11d53972016-11-28 11:23:23 -05001251std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001252 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001253 if (!expr) {
1254 return nullptr;
1255 }
ethannicholasd598f792016-07-25 10:08:54 -07001256 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001257 return expr;
1258 }
1259 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001260 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001261 return nullptr;
1262 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001263 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001264 fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
ethannicholasd598f792016-07-25 10:08:54 -07001265 expr->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001266 return nullptr;
1267 }
ethannicholasd598f792016-07-25 10:08:54 -07001268 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001269 std::vector<std::unique_ptr<Expression>> args;
1270 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001271 std::unique_ptr<Expression> ctor;
1272 if (type == *fContext.fFloatLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001273 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1274 "float"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001275 } else if (type == *fContext.fIntLiteral_Type) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001276 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1277 "int"));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001278 } else {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001279 ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
1280 type.fName));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001281 }
1282 if (!ctor) {
1283 printf("error, null identifier: %s\n", String(type.fName).c_str());
1284 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001285 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001286 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001287 }
Ethan Nicholasee1c8a72019-02-22 10:50:47 -05001288 if (expr->fKind == Expression::kNullLiteral_Kind) {
1289 SkASSERT(type.kind() == Type::kNullable_Kind);
1290 return std::unique_ptr<Expression>(new NullLiteral(expr->fOffset, type));
1291 }
ethannicholas5961bc92016-10-12 06:39:56 -07001292 std::vector<std::unique_ptr<Expression>> args;
1293 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001294 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001295}
1296
ethannicholasf789b382016-08-03 12:43:36 -07001297static bool is_matrix_multiply(const Type& left, const Type& right) {
1298 if (left.kind() == Type::kMatrix_Kind) {
1299 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1300 }
1301 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1302}
ethannicholasea4567c2016-10-17 11:24:37 -07001303
ethannicholasb3058bd2016-07-01 08:22:01 -07001304/**
1305 * Determines the operand and result types of a binary expression. Returns true if the expression is
1306 * legal, false otherwise. If false, the values of the out parameters are undefined.
1307 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001308static bool determine_binary_type(const Context& context,
1309 Token::Kind op,
1310 const Type& left,
1311 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001312 const Type** outLeftType,
1313 const Type** outRightType,
1314 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001315 bool tryFlipped) {
1316 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001317 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001318 switch (op) {
ethannicholasea4567c2016-10-17 11:24:37 -07001319 case Token::EQ:
1320 *outLeftType = &left;
1321 *outRightType = &left;
1322 *outResultType = &left;
1323 return right.canCoerceTo(left);
ethannicholasb3058bd2016-07-01 08:22:01 -07001324 case Token::EQEQ: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001325 case Token::NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001326 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001327 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001328 *outRightType = &left;
1329 *outResultType = context.fBool_Type.get();
1330 return true;
1331 } if (left.canCoerceTo(right)) {
1332 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001333 *outRightType = &right;
1334 *outResultType = context.fBool_Type.get();
1335 return true;
1336 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001337 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001338 case Token::LT: // fall through
1339 case Token::GT: // fall through
1340 case Token::LTEQ: // fall through
1341 case Token::GTEQ:
1342 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001343 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001344 break;
1345 case Token::LOGICALOR: // fall through
1346 case Token::LOGICALAND: // fall through
1347 case Token::LOGICALXOR: // fall through
1348 case Token::LOGICALOREQ: // fall through
1349 case Token::LOGICALANDEQ: // fall through
1350 case Token::LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001351 *outLeftType = context.fBool_Type.get();
1352 *outRightType = context.fBool_Type.get();
1353 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001354 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001355 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas11d53972016-11-28 11:23:23 -05001356 case Token::STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001357 if (left.kind() == Type::kScalar_Kind) {
1358 *outLeftType = &left;
1359 *outRightType = &left;
1360 *outResultType = &left;
1361 return right.canCoerceTo(left);
1362 }
1363 // fall through
1364 case Token::STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001365 if (is_matrix_multiply(left, right)) {
1366 // determine final component type
1367 if (determine_binary_type(context, Token::STAR, left.componentType(),
1368 right.componentType(), outLeftType, outRightType,
1369 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001370 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001371 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001372 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001373 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001374 int leftColumns = left.columns();
1375 int leftRows = left.rows();
1376 int rightColumns;
1377 int rightRows;
1378 if (right.kind() == Type::kVector_Kind) {
1379 // matrix * vector treats the vector as a column vector, so we need to
1380 // transpose it
1381 rightColumns = right.rows();
1382 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001383 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001384 } else {
1385 rightColumns = right.columns();
1386 rightRows = right.rows();
1387 }
1388 if (rightColumns > 1) {
1389 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1390 leftRows);
1391 } else {
1392 // result was a column vector, transpose it back to a row
1393 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1394 rightColumns);
1395 }
1396 return leftColumns == rightRows;
1397 } else {
1398 return false;
1399 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001400 }
ethannicholasea4567c2016-10-17 11:24:37 -07001401 isLogical = false;
1402 validMatrixOrVectorOp = true;
1403 break;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001404 case Token::PLUSEQ:
1405 case Token::MINUSEQ:
1406 case Token::SLASHEQ:
1407 case Token::PERCENTEQ:
1408 case Token::SHLEQ:
1409 case Token::SHREQ:
1410 if (left.kind() == Type::kScalar_Kind) {
1411 *outLeftType = &left;
1412 *outRightType = &left;
1413 *outResultType = &left;
1414 return right.canCoerceTo(left);
1415 }
1416 // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001417 case Token::PLUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001418 case Token::MINUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001419 case Token::SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001420 isLogical = false;
1421 validMatrixOrVectorOp = true;
1422 break;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001423 case Token::COMMA:
1424 *outLeftType = &left;
1425 *outRightType = &right;
1426 *outResultType = &right;
1427 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001428 default:
1429 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001430 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001431 }
ethannicholasea4567c2016-10-17 11:24:37 -07001432 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001433 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1434 right.canCoerceTo(left)) {
1435 if (left.priority() > right.priority()) {
1436 *outLeftType = &left;
1437 *outRightType = &left;
1438 } else {
1439 *outLeftType = &right;
1440 *outRightType = &right;
1441 }
1442 if (isLogical) {
1443 *outResultType = context.fBool_Type.get();
1444 } else {
1445 *outResultType = &left;
1446 }
1447 return true;
1448 }
1449 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001450 *outLeftType = &left;
1451 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001452 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001453 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001454 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001455 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001456 }
1457 return true;
1458 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001459 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001460 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001461 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001462 outRightType, outResultType, false)) {
1463 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001464 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001465 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001466 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001467 }
1468 return true;
1469 }
1470 return false;
1471 }
1472 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001473 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001474 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001475 }
1476 return false;
1477}
1478
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001479static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1480 const Expression& left,
1481 Token::Kind op,
1482 const Expression& right) {
1483 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
1484 bool leftVal = ((BoolLiteral&) left).fValue;
1485 if (op == Token::LOGICALAND) {
1486 // (true && expr) -> (expr) and (false && expr) -> (false)
1487 return leftVal ? right.clone()
1488 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
1489 } else if (op == Token::LOGICALOR) {
1490 // (true || expr) -> (true) and (false || expr) -> (expr)
1491 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1492 : right.clone();
1493 } else {
1494 // Can't short circuit XOR
1495 return nullptr;
1496 }
1497}
1498
ethannicholas08a92112016-11-09 13:26:45 -08001499std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1500 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001501 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001502 // If the left side is a constant boolean literal, the right side does not need to be constant
1503 // for short circuit optimizations to allow the constant to be folded.
1504 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isConstant()) {
1505 return short_circuit_boolean(fContext, left, op, right);
1506 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isConstant()) {
1507 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1508 // (right OP left) for short-circuit optimizations
1509 return short_circuit_boolean(fContext, right, op, left);
1510 }
1511
1512 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Ethan Nicholascb670962017-04-20 19:31:52 -04001513 if (!left.isConstant() || !right.isConstant()) {
1514 return nullptr;
1515 }
ethannicholas08a92112016-11-09 13:26:45 -08001516 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1517 // precision to calculate the results and hope the result makes sense. The plan is to move the
1518 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1519 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001520 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001521 right.fKind == Expression::kBoolLiteral_Kind) {
1522 bool leftVal = ((BoolLiteral&) left).fValue;
1523 bool rightVal = ((BoolLiteral&) right).fValue;
1524 bool result;
1525 switch (op) {
1526 case Token::LOGICALAND: result = leftVal && rightVal; break;
1527 case Token::LOGICALOR: result = leftVal || rightVal; break;
1528 case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
1529 default: return nullptr;
1530 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001531 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001532 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001533 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \
ethannicholas08a92112016-11-09 13:26:45 -08001534 leftVal op rightVal))
1535 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
1536 int64_t leftVal = ((IntLiteral&) left).fValue;
1537 int64_t rightVal = ((IntLiteral&) right).fValue;
1538 switch (op) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001539 case Token::PLUS: return RESULT(Int, +);
1540 case Token::MINUS: return RESULT(Int, -);
1541 case Token::STAR: return RESULT(Int, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001542 case Token::SLASH:
1543 if (rightVal) {
1544 return RESULT(Int, /);
1545 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001546 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001547 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001548 case Token::PERCENT:
1549 if (rightVal) {
1550 return RESULT(Int, %);
1551 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001552 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001553 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001554 case Token::BITWISEAND: return RESULT(Int, &);
1555 case Token::BITWISEOR: return RESULT(Int, |);
1556 case Token::BITWISEXOR: return RESULT(Int, ^);
ethannicholas08a92112016-11-09 13:26:45 -08001557 case Token::EQEQ: return RESULT(Bool, ==);
1558 case Token::NEQ: return RESULT(Bool, !=);
1559 case Token::GT: return RESULT(Bool, >);
1560 case Token::GTEQ: return RESULT(Bool, >=);
1561 case Token::LT: return RESULT(Bool, <);
1562 case Token::LTEQ: return RESULT(Bool, <=);
Ethan Nicholasfeba68a2019-06-10 09:56:29 -04001563 case Token::SHL:
1564 if (rightVal >= 0 && rightVal <= 31) {
1565 return RESULT(Int, <<);
1566 }
1567 fErrors.error(right.fOffset, "shift value out of range");
1568 return nullptr;
1569 case Token::SHR:
1570 if (rightVal >= 0 && rightVal <= 31) {
1571 return RESULT(Int, >>);
1572 }
1573 fErrors.error(right.fOffset, "shift value out of range");
1574 return nullptr;
1575
1576 default:
1577 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001578 }
1579 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001580 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001581 right.fKind == Expression::kFloatLiteral_Kind) {
1582 double leftVal = ((FloatLiteral&) left).fValue;
1583 double rightVal = ((FloatLiteral&) right).fValue;
1584 switch (op) {
1585 case Token::PLUS: return RESULT(Float, +);
1586 case Token::MINUS: return RESULT(Float, -);
1587 case Token::STAR: return RESULT(Float, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001588 case Token::SLASH:
1589 if (rightVal) {
1590 return RESULT(Float, /);
1591 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001592 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001593 return nullptr;
Ethan Nicholascb670962017-04-20 19:31:52 -04001594 case Token::EQEQ: return RESULT(Bool, ==);
1595 case Token::NEQ: return RESULT(Bool, !=);
1596 case Token::GT: return RESULT(Bool, >);
1597 case Token::GTEQ: return RESULT(Bool, >=);
1598 case Token::LT: return RESULT(Bool, <);
1599 case Token::LTEQ: return RESULT(Bool, <=);
ethannicholas08a92112016-11-09 13:26:45 -08001600 default: return nullptr;
1601 }
1602 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001603 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001604 left.fType == right.fType) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001605 std::vector<std::unique_ptr<Expression>> args;
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001606 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1607 for (int i = 0; i < left.fType.columns(); i++) { \
1608 float value = left.getFVecComponent(i) op \
1609 right.getFVecComponent(i); \
1610 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
1611 } \
1612 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001613 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001614 switch (op) {
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001615 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001616 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001617 left.compareConstant(fContext, right)));
1618 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001619 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001620 !left.compareConstant(fContext, right)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001621 case Token::PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1622 case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1623 case Token::STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
Ethan Nicholas4cf5fd92019-06-10 16:15:56 -04001624 case Token::SLASH:
1625 for (int i = 0; i < left.fType.columns(); i++) {
1626 SKSL_FLOAT rvalue = right.getFVecComponent(i);
1627 if (rvalue == 0.0) {
1628 fErrors.error(right.fOffset, "division by zero");
1629 return nullptr;
1630 }
1631 float value = left.getFVecComponent(i) / rvalue;
1632 args.emplace_back(new FloatLiteral(fContext, -1, value));
1633 }
1634 return std::unique_ptr<Expression>(new Constructor(-1, left.fType,
1635 std::move(args)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001636 default: return nullptr;
1637 }
1638 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001639 if (left.fType.kind() == Type::kMatrix_Kind &&
1640 right.fType.kind() == Type::kMatrix_Kind &&
1641 left.fKind == right.fKind) {
1642 switch (op) {
1643 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001644 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001645 left.compareConstant(fContext, right)));
1646 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001647 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001648 !left.compareConstant(fContext, right)));
1649 default:
1650 return nullptr;
1651 }
1652 }
ethannicholas08a92112016-11-09 13:26:45 -08001653 #undef RESULT
1654 return nullptr;
1655}
1656
Ethan Nicholasfc994162019-06-06 10:04:27 -04001657std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
1658 SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
1659 auto iter = expression.begin();
1660 std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001661 if (!left) {
1662 return nullptr;
1663 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001664 std::unique_ptr<Expression> right = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001665 if (!right) {
1666 return nullptr;
1667 }
ethannicholasd598f792016-07-25 10:08:54 -07001668 const Type* leftType;
1669 const Type* rightType;
1670 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001671 const Type* rawLeftType;
1672 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1673 rawLeftType = &right->fType;
1674 } else {
1675 rawLeftType = &left->fType;
1676 }
1677 const Type* rawRightType;
1678 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1679 rawRightType = &left->fType;
1680 } else {
1681 rawRightType = &right->fType;
1682 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001683 Token::Kind op = expression.getToken().fKind;
1684 if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
1685 &resultType, !Compiler::IsAssignment(op))) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001686 fErrors.error(expression.fOffset, String("type mismatch: '") +
Ethan Nicholasfc994162019-06-06 10:04:27 -04001687 Compiler::OperatorName(expression.getToken().fKind) +
Ethan Nicholase1f55022019-02-05 17:17:40 -05001688 "' cannot operate on '" + left->fType.description() +
1689 "', '" + right->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001690 return nullptr;
1691 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001692 if (Compiler::IsAssignment(op)) {
1693 this->setRefKind(*left, op != Token::EQ ? VariableReference::kReadWrite_RefKind :
1694 VariableReference::kWrite_RefKind);
ethannicholasea4567c2016-10-17 11:24:37 -07001695 }
1696 left = this->coerce(std::move(left), *leftType);
1697 right = this->coerce(std::move(right), *rightType);
1698 if (!left || !right) {
1699 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001700 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001701 std::unique_ptr<Expression> result = this->constantFold(*left.get(), op, *right.get());
ethannicholas08a92112016-11-09 13:26:45 -08001702 if (!result) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001703 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08001704 std::move(left),
Ethan Nicholasfc994162019-06-06 10:04:27 -04001705 op,
ethannicholas08a92112016-11-09 13:26:45 -08001706 std::move(right),
1707 *resultType));
1708 }
1709 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001710}
1711
Ethan Nicholasfc994162019-06-06 10:04:27 -04001712std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
1713 SkASSERT(node.fKind == ASTNode::Kind::kTernary);
1714 auto iter = node.begin();
1715 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
ethannicholasd598f792016-07-25 10:08:54 -07001716 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001717 if (!test) {
1718 return nullptr;
1719 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001720 std::unique_ptr<Expression> ifTrue = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001721 if (!ifTrue) {
1722 return nullptr;
1723 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001724 std::unique_ptr<Expression> ifFalse = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07001725 if (!ifFalse) {
1726 return nullptr;
1727 }
ethannicholasd598f792016-07-25 10:08:54 -07001728 const Type* trueType;
1729 const Type* falseType;
1730 const Type* resultType;
1731 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001732 &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04001733 fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
1734 ifTrue->fType.description() + "', '" +
1735 ifFalse->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001736 return nullptr;
1737 }
ethannicholasd598f792016-07-25 10:08:54 -07001738 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001739 if (!ifTrue) {
1740 return nullptr;
1741 }
ethannicholasd598f792016-07-25 10:08:54 -07001742 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001743 if (!ifFalse) {
1744 return nullptr;
1745 }
ethannicholas08a92112016-11-09 13:26:45 -08001746 if (test->fKind == Expression::kBoolLiteral_Kind) {
1747 // static boolean test, just return one of the branches
1748 if (((BoolLiteral&) *test).fValue) {
1749 return ifTrue;
1750 } else {
1751 return ifFalse;
1752 }
1753 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04001754 return std::unique_ptr<Expression>(new TernaryExpression(node.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001755 std::move(test),
Ethan Nicholas11d53972016-11-28 11:23:23 -05001756 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -07001757 std::move(ifFalse)));
1758}
1759
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001760std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001761 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07001762 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05001763 if (function.fBuiltin) {
1764 auto found = fIntrinsics->find(function.fName);
1765 if (found != fIntrinsics->end() && !found->second.second) {
1766 found->second.second = true;
1767 const FunctionDeclaration* old = fCurrentFunction;
1768 fCurrentFunction = nullptr;
1769 this->convertFunction(*((FunctionDefinition&) *found->second.first).fSource);
1770 fCurrentFunction = old;
1771 }
1772 }
ethannicholasd598f792016-07-25 10:08:54 -07001773 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001774 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05001775 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07001776 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07001777 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001778 msg += "s";
1779 }
ethannicholas5961bc92016-10-12 06:39:56 -07001780 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001781 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001782 return nullptr;
1783 }
ethannicholas471e8942016-10-28 09:02:46 -07001784 std::vector<const Type*> types;
1785 const Type* returnType;
1786 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001787 String msg = "no match for " + function.fName + "(";
1788 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07001789 for (size_t i = 0; i < arguments.size(); i++) {
1790 msg += separator;
1791 separator = ", ";
1792 msg += arguments[i]->fType.description();
1793 }
1794 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001795 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07001796 return nullptr;
1797 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001798 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07001799 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07001800 if (!arguments[i]) {
1801 return nullptr;
1802 }
ethannicholasd598f792016-07-25 10:08:54 -07001803 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001804 this->setRefKind(*arguments[i],
1805 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
1806 VariableReference::kReadWrite_RefKind :
1807 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001808 }
1809 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001810 return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
ethannicholasb3058bd2016-07-01 08:22:01 -07001811 std::move(arguments)));
1812}
1813
1814/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001815 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
1816 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
1817 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07001818 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001819int IRGenerator::callCost(const FunctionDeclaration& function,
1820 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07001821 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001822 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001823 }
1824 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07001825 std::vector<const Type*> types;
1826 const Type* ignored;
1827 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001828 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07001829 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001830 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001831 int cost = arguments[i]->coercionCost(*types[i]);
1832 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001833 total += cost;
1834 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001835 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001836 }
1837 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001838 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07001839}
1840
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001841std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001842 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07001843 std::vector<std::unique_ptr<Expression>> arguments) {
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04001844 switch (functionValue->fKind) {
1845 case Expression::kTypeReference_Kind:
1846 return this->convertConstructor(offset,
1847 ((TypeReference&) *functionValue).fValue,
1848 std::move(arguments));
1849 case Expression::kExternalValue_Kind: {
1850 ExternalValue* v = ((ExternalValueReference&) *functionValue).fValue;
1851 if (!v->canCall()) {
1852 fErrors.error(offset, "this external value is not a function");
1853 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001854 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04001855 int count = v->callParameterCount();
1856 if (count != (int) arguments.size()) {
1857 fErrors.error(offset, "external function expected " + to_string(count) +
1858 " arguments, but found " + to_string((int) arguments.size()));
1859 return nullptr;
1860 }
1861 static constexpr int PARAMETER_MAX = 16;
1862 SkASSERT(count < PARAMETER_MAX);
1863 const Type* types[PARAMETER_MAX];
1864 v->getCallParameterTypes(types);
1865 for (int i = 0; i < count; ++i) {
1866 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
1867 if (!arguments[i]) {
1868 return nullptr;
1869 }
1870 }
1871 return std::unique_ptr<Expression>(new ExternalFunctionCall(offset, v->callReturnType(),
1872 v, std::move(arguments)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001873 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04001874 case Expression::kFunctionReference_Kind: {
1875 FunctionReference* ref = (FunctionReference*) functionValue.get();
1876 int bestCost = INT_MAX;
1877 const FunctionDeclaration* best = nullptr;
1878 if (ref->fFunctions.size() > 1) {
1879 for (const auto& f : ref->fFunctions) {
1880 int cost = this->callCost(*f, arguments);
1881 if (cost < bestCost) {
1882 bestCost = cost;
1883 best = f;
1884 }
1885 }
1886 if (best) {
1887 return this->call(offset, *best, std::move(arguments));
1888 }
1889 String msg = "no match for " + ref->fFunctions[0]->fName + "(";
1890 String separator;
1891 for (size_t i = 0; i < arguments.size(); i++) {
1892 msg += separator;
1893 separator = ", ";
1894 msg += arguments[i]->fType.description();
1895 }
1896 msg += ")";
1897 fErrors.error(offset, msg);
1898 return nullptr;
1899 }
1900 return this->call(offset, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001901 }
Ethan Nicholas9e6a3932019-05-17 16:31:21 -04001902 default:
1903 fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
1904 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001905 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001906}
1907
Ethan Nicholas84645e32017-02-09 13:57:14 -05001908std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001909 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001910 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07001911 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001912 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05001913 if (args.size() != 1) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001914 fErrors.error(offset, "invalid arguments to '" + type.description() +
1915 "' constructor, (expected exactly 1 argument, but found " +
1916 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07001917 return nullptr;
1918 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001919 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001920 return std::move(args[0]);
1921 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001922 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
1923 double value = ((FloatLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001924 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001925 }
1926 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001927 int64_t value = ((IntLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001928 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001929 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001930 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
1931 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04001932 return std::unique_ptr<Expression>(new IntLiteral(offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001933 ((IntLiteral&) *args[0]).fValue,
1934 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001935 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001936 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001937 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
1938 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001939 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001940 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05001941 this->coerce(std::move(one), type),
1942 this->coerce(std::move(zero),
1943 type)));
1944 }
1945 if (!args[0]->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001946 fErrors.error(offset, "invalid argument to '" + type.description() +
1947 "' constructor (expected a number or bool, but found '" +
1948 args[0]->fType.description() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05001949 return nullptr;
1950 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001951 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001952}
1953
1954int component_count(const Type& type) {
1955 switch (type.kind()) {
1956 case Type::kVector_Kind:
1957 return type.columns();
1958 case Type::kMatrix_Kind:
1959 return type.columns() * type.rows();
1960 default:
1961 return 1;
1962 }
1963}
1964
1965std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001966 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001967 const Type& type,
1968 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001969 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05001970 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
1971 args[0]->fType.kind() == Type::kMatrix_Kind) {
1972 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001973 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001974 }
1975 int actual = 0;
1976 int expected = type.rows() * type.columns();
1977 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
1978 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07001979 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05001980 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001981 if (type.componentType().isNumber() !=
1982 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001983 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1984 "parameter to '" + type.description() +
1985 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001986 return nullptr;
1987 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001988 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001989 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
1990 actual += 1;
1991 if (type.kind() != Type::kScalar_Kind) {
1992 args[i] = this->coerce(std::move(args[i]), type.componentType());
1993 if (!args[i]) {
1994 return nullptr;
1995 }
1996 }
1997 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001998 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1999 "parameter to '" + type.description() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002000 return nullptr;
2001 }
2002 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05002003 if (actual != 1 && actual != expected) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002004 fErrors.error(offset, "invalid arguments to '" + type.description() +
2005 "' constructor (expected " + to_string(expected) +
2006 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00002007 return nullptr;
2008 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002009 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002010 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002011}
2012
Ethan Nicholas84645e32017-02-09 13:57:14 -05002013std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002014 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05002015 const Type& type,
2016 std::vector<std::unique_ptr<Expression>> args) {
2017 // FIXME: add support for structs
2018 Type::Kind kind = type.kind();
2019 if (args.size() == 1 && args[0]->fType == type) {
2020 // argument is already the right type, just return it
2021 return std::move(args[0]);
2022 }
2023 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002024 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002025 } else if (kind == Type::kArray_Kind) {
2026 const Type& base = type.componentType();
2027 for (size_t i = 0; i < args.size(); i++) {
2028 args[i] = this->coerce(std::move(args[i]), base);
2029 if (!args[i]) {
2030 return nullptr;
2031 }
2032 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002033 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002034 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002035 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05002036 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002037 fErrors.error(offset, "cannot construct '" + type.description() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05002038 return nullptr;
2039 }
2040}
2041
Ethan Nicholasfc994162019-06-06 10:04:27 -04002042std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
2043 SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
2044 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
ethannicholasb3058bd2016-07-01 08:22:01 -07002045 if (!base) {
2046 return nullptr;
2047 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002048 switch (expression.getToken().fKind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002049 case Token::PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05002050 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
2051 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002052 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002053 "'+' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002054 return nullptr;
2055 }
2056 return base;
2057 case Token::MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07002058 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002059 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002060 -((IntLiteral&) *base).fValue));
2061 }
2062 if (base->fKind == Expression::kFloatLiteral_Kind) {
2063 double value = -((FloatLiteral&) *base).fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002064 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002065 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07002066 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05002067 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
2068 fErrors.error(expression.fOffset,
2069 "'-' cannot operate on '" + base->fType.description() + "'");
2070 return nullptr;
2071 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002072 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
2073 case Token::PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07002074 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002075 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002076 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
ethannicholasd598f792016-07-25 10:08:54 -07002077 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002078 return nullptr;
2079 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002080 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002081 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002082 case Token::MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07002083 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002084 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002085 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
ethannicholasd598f792016-07-25 10:08:54 -07002086 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002087 return nullptr;
2088 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002089 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002090 break;
ethannicholas5961bc92016-10-12 06:39:56 -07002091 case Token::LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07002092 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002093 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002094 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
ethannicholasd598f792016-07-25 10:08:54 -07002095 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002096 return nullptr;
2097 }
ethannicholas08a92112016-11-09 13:26:45 -08002098 if (base->fKind == Expression::kBoolLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002099 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08002100 !((BoolLiteral&) *base).fValue));
2101 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002102 break;
ethannicholas5961bc92016-10-12 06:39:56 -07002103 case Token::BITWISENOT:
Brian Osman73fb39c2019-09-24 16:22:55 -04002104 if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002105 fErrors.error(expression.fOffset,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002106 String("'") + Compiler::OperatorName(expression.getToken().fKind) +
ethannicholas5961bc92016-10-12 06:39:56 -07002107 "' cannot operate on '" + base->fType.description() + "'");
2108 return nullptr;
2109 }
2110 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002111 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07002112 ABORT("unsupported prefix operator\n");
2113 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002114 return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
ethannicholasb3058bd2016-07-01 08:22:01 -07002115 std::move(base)));
2116}
2117
2118std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
Ethan Nicholasfc994162019-06-06 10:04:27 -04002119 const ASTNode& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002120 if (base->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002121 if (index.fKind == ASTNode::Kind::kInt) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05002122 const Type& oldType = ((TypeReference&) *base).fValue;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002123 SKSL_INT size = index.getInt();
Ethan Nicholas91164d12019-05-15 15:29:54 -04002124 Type* newType = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
2125 new Type(oldType.name() + "[" + to_string(size) + "]",
Ethan Nicholasfc994162019-06-06 10:04:27 -04002126 Type::kArray_Kind, oldType, size)));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002127 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
Ethan Nicholas50afc172017-02-16 14:49:57 -05002128 *newType));
2129
2130 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002131 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05002132 return nullptr;
2133 }
2134 }
ethannicholas5961bc92016-10-12 06:39:56 -07002135 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
2136 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002137 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
2138 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002139 return nullptr;
2140 }
2141 std::unique_ptr<Expression> converted = this->convertExpression(index);
2142 if (!converted) {
2143 return nullptr;
2144 }
ethannicholas5961bc92016-10-12 06:39:56 -07002145 if (converted->fType != *fContext.fUInt_Type) {
2146 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
2147 if (!converted) {
2148 return nullptr;
2149 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002150 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05002151 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07002152 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07002153}
2154
2155std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002156 StringFragment field) {
Ethan Nicholas91164d12019-05-15 15:29:54 -04002157 if (base->fKind == Expression::kExternalValue_Kind) {
2158 ExternalValue& ev = *((ExternalValueReference&) *base).fValue;
2159 ExternalValue* result = ev.getChild(String(field).c_str());
2160 if (!result) {
2161 fErrors.error(base->fOffset, "external value does not have a child named '" + field +
2162 "'");
2163 return nullptr;
2164 }
2165 return std::unique_ptr<Expression>(new ExternalValueReference(base->fOffset, result));
2166 }
ethannicholasd598f792016-07-25 10:08:54 -07002167 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07002168 for (size_t i = 0; i < fields.size(); i++) {
2169 if (fields[i].fName == field) {
2170 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
2171 }
2172 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002173 fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
2174 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07002175 return nullptr;
2176}
2177
2178std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002179 StringFragment fields) {
ethannicholasd598f792016-07-25 10:08:54 -07002180 if (base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002181 fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002182 return nullptr;
2183 }
2184 std::vector<int> swizzleComponents;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002185 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05002186 switch (fields[i]) {
Ethan Nicholasac285b12019-02-12 16:05:18 -05002187 case '0':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002188 swizzleComponents.push_back(SKSL_SWIZZLE_0);
2189 break;
2190 case '1':
Ethan Nicholasac285b12019-02-12 16:05:18 -05002191 swizzleComponents.push_back(SKSL_SWIZZLE_1);
2192 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002193 case 'x':
2194 case 'r':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002195 case 's':
Ethan Nicholase455f652019-09-13 12:52:55 -04002196 case 'L':
ethannicholasb3058bd2016-07-01 08:22:01 -07002197 swizzleComponents.push_back(0);
2198 break;
Ethan Nicholase455f652019-09-13 12:52:55 -04002199 case 'y':
2200 case 'g':
ethannicholasb3058bd2016-07-01 08:22:01 -07002201 case 't':
Ethan Nicholase455f652019-09-13 12:52:55 -04002202 case 'T':
ethannicholasd598f792016-07-25 10:08:54 -07002203 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002204 swizzleComponents.push_back(1);
2205 break;
2206 }
2207 // fall through
Ethan Nicholase455f652019-09-13 12:52:55 -04002208 case 'z':
2209 case 'b':
Ethan Nicholas11d53972016-11-28 11:23:23 -05002210 case 'p':
Ethan Nicholase455f652019-09-13 12:52:55 -04002211 case 'R':
ethannicholasd598f792016-07-25 10:08:54 -07002212 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002213 swizzleComponents.push_back(2);
2214 break;
2215 }
2216 // fall through
Ethan Nicholase455f652019-09-13 12:52:55 -04002217 case 'w':
2218 case 'a':
ethannicholasb3058bd2016-07-01 08:22:01 -07002219 case 'q':
Ethan Nicholase455f652019-09-13 12:52:55 -04002220 case 'B':
ethannicholasd598f792016-07-25 10:08:54 -07002221 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002222 swizzleComponents.push_back(3);
2223 break;
2224 }
2225 // fall through
2226 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002227 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
2228 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07002229 return nullptr;
2230 }
2231 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002232 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07002233 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002234 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002235 return nullptr;
2236 }
ethannicholasd598f792016-07-25 10:08:54 -07002237 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07002238}
2239
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002240std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05002241 auto found = fCapsMap.find(name);
2242 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002243 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002244 return nullptr;
2245 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002246 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002247 return std::unique_ptr<Expression>(new Setting(offset, fullName,
2248 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002249}
2250
Ethan Nicholas00543112018-07-31 09:44:36 -04002251std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -04002252 auto found = fSettings->fArgs.find(name);
2253 if (found == fSettings->fArgs.end()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04002254 return nullptr;
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002255 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002256 String fullName = "sk_Args." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002257 return std::unique_ptr<Expression>(new Setting(offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -04002258 fullName,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002259 found->second.literal(fContext, offset)));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002260}
2261
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002262std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2263 StringFragment field) {
2264 std::unique_ptr<Expression> result;
2265 for (const auto& e : *fProgramElements) {
2266 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
2267 std::shared_ptr<SymbolTable> old = fSymbolTable;
2268 fSymbolTable = ((Enum&) *e).fSymbols;
Ethan Nicholasfc994162019-06-06 10:04:27 -04002269 result = convertIdentifier(ASTNode(&fFile->fNodes, offset, ASTNode::Kind::kIdentifier,
2270 field));
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002271 SkASSERT(result->fKind == Expression::kVariableReference_Kind);
2272 const Variable& v = ((VariableReference&) *result).fVariable;
2273 SkASSERT(v.fInitialValue);
2274 SkASSERT(v.fInitialValue->fKind == Expression::kIntLiteral_Kind);
2275 result.reset(new IntLiteral(offset, ((IntLiteral&) *v.fInitialValue).fValue, &type));
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002276 fSymbolTable = old;
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002277 break;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002278 }
2279 }
2280 if (!result) {
Ethan Nicholasdb80f692019-11-22 14:06:12 -05002281 auto found = fIntrinsics->find(type.fName);
2282 if (found != fIntrinsics->end()) {
2283 SkASSERT(!found->second.second);
2284 found->second.second = true;
2285 fProgramElements->push_back(found->second.first->clone());
2286 return this->convertTypeField(offset, type, field);
2287 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002288 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2289 "'");
2290 }
2291 return result;
2292}
2293
Ethan Nicholasfc994162019-06-06 10:04:27 -04002294std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
2295 SkASSERT(index.fKind == ASTNode::Kind::kIndex);
2296 auto iter = index.begin();
2297 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
ethannicholasb3058bd2016-07-01 08:22:01 -07002298 if (!base) {
2299 return nullptr;
2300 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002301 if (iter != index.end()) {
2302 return this->convertIndex(std::move(base), *(iter++));
2303 } else if (base->fKind == Expression::kTypeReference_Kind) {
2304 const Type& oldType = ((TypeReference&) *base).fValue;
2305 Type* newType = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
Ethan Nicholas91164d12019-05-15 15:29:54 -04002306 new Type(oldType.name() + "[]",
2307 Type::kArray_Kind,
2308 oldType,
2309 -1)));
Ethan Nicholasfc994162019-06-06 10:04:27 -04002310 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
2311 *newType));
ethannicholasb3058bd2016-07-01 08:22:01 -07002312 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002313 fErrors.error(index.fOffset, "'[]' must follow a type name");
2314 return nullptr;
2315}
2316
2317std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
2318 SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
2319 auto iter = callNode.begin();
2320 std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
2321 if (!base) {
2322 return nullptr;
2323 }
2324 std::vector<std::unique_ptr<Expression>> arguments;
2325 for (; iter != callNode.end(); ++iter) {
2326 std::unique_ptr<Expression> converted = this->convertExpression(*iter);
2327 if (!converted) {
2328 return nullptr;
2329 }
2330 arguments.push_back(std::move(converted));
2331 }
2332 return this->call(callNode.fOffset, std::move(base), std::move(arguments));
2333}
2334
2335std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
2336 std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
2337 if (!base) {
2338 return nullptr;
2339 }
2340 StringFragment field = fieldNode.getString();
2341 if (base->fType == *fContext.fSkCaps_Type) {
2342 return this->getCap(fieldNode.fOffset, field);
2343 }
2344 if (base->fType == *fContext.fSkArgs_Type) {
2345 return this->getArg(fieldNode.fOffset, field);
2346 }
2347 if (base->fKind == Expression::kTypeReference_Kind) {
2348 return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
2349 field);
2350 }
2351 if (base->fKind == Expression::kExternalValue_Kind) {
2352 return this->convertField(std::move(base), field);
2353 }
2354 switch (base->fType.kind()) {
2355 case Type::kVector_Kind:
2356 return this->convertSwizzle(std::move(base), field);
2357 case Type::kOther_Kind:
2358 case Type::kStruct_Kind:
2359 return this->convertField(std::move(base), field);
2360 default:
2361 fErrors.error(base->fOffset, "cannot swizzle value of type '" +
2362 base->fType.description() + "'");
2363 return nullptr;
2364 }
2365}
2366
2367std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
2368 std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
2369 if (!base) {
2370 return nullptr;
2371 }
2372 if (!base->fType.isNumber()) {
2373 fErrors.error(expression.fOffset,
2374 "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
2375 "' cannot operate on '" + base->fType.description() + "'");
2376 return nullptr;
2377 }
2378 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
2379 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
2380 expression.getToken().fKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07002381}
2382
2383void IRGenerator::checkValid(const Expression& expr) {
2384 switch (expr.fKind) {
2385 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002386 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07002387 break;
2388 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002389 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07002390 break;
2391 default:
ethannicholasea4567c2016-10-17 11:24:37 -07002392 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002393 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07002394 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002395 }
2396}
2397
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002398bool IRGenerator::checkSwizzleWrite(const Swizzle& swizzle) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002399 int bits = 0;
2400 for (int idx : swizzle.fComponents) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002401 if (idx < 0) {
2402 fErrors.error(swizzle.fOffset, "cannot write to a swizzle mask containing a constant");
2403 return false;
2404 }
2405 SkASSERT(idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07002406 int bit = 1 << idx;
2407 if (bits & bit) {
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002408 fErrors.error(swizzle.fOffset,
2409 "cannot write to the same swizzle field more than once");
2410 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07002411 }
2412 bits |= bit;
2413 }
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002414 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07002415}
2416
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002417void IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002418 switch (expr.fKind) {
2419 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07002420 const Variable& var = ((VariableReference&) expr).fVariable;
ethannicholasb3058bd2016-07-01 08:22:01 -07002421 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002422 fErrors.error(expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002423 "cannot modify immutable variable '" + var.fName + "'");
2424 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002425 ((VariableReference&) expr).setRefKind(kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002426 break;
2427 }
2428 case Expression::kFieldAccess_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002429 this->setRefKind(*((FieldAccess&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002430 break;
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002431 case Expression::kSwizzle_Kind: {
2432 const Swizzle& swizzle = (Swizzle&) expr;
2433 this->checkSwizzleWrite(swizzle);
2434 this->setRefKind(*swizzle.fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002435 break;
Ethan Nicholascb0f4092019-04-19 11:26:50 -04002436 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002437 case Expression::kIndex_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002438 this->setRefKind(*((IndexExpression&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002439 break;
Ethan Nicholasa583b812018-01-18 13:32:11 -05002440 case Expression::kTernary_Kind: {
2441 TernaryExpression& t = (TernaryExpression&) expr;
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002442 this->setRefKind(*t.fIfTrue, kind);
2443 this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002444 break;
2445 }
Ethan Nicholas91164d12019-05-15 15:29:54 -04002446 case Expression::kExternalValue_Kind: {
2447 const ExternalValue& v = *((ExternalValueReference&) expr).fValue;
2448 if (!v.canWrite()) {
2449 fErrors.error(expr.fOffset,
2450 "cannot modify immutable external value '" + v.fName + "'");
2451 }
2452 break;
2453 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002454 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002455 fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002456 break;
2457 }
2458}
2459
Robert Phillipsfe8da172018-01-24 14:52:02 +00002460void IRGenerator::convertProgram(Program::Kind kind,
2461 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002462 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002463 SymbolTable& types,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002464 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00002465 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002466 fProgramElements = out;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002467 Parser parser(text, length, types, fErrors);
Ethan Nicholasfc994162019-06-06 10:04:27 -04002468 fFile = parser.file();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002469 if (fErrors.errorCount()) {
2470 return;
2471 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002472 SkASSERT(fFile);
2473 for (const auto& decl : fFile->root()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002474 switch (decl.fKind) {
Ethan Nicholasfc994162019-06-06 10:04:27 -04002475 case ASTNode::Kind::kVarDeclarations: {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002476 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
Ethan Nicholasfc994162019-06-06 10:04:27 -04002477 decl,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002478 Variable::kGlobal_Storage);
2479 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002480 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002481 }
2482 break;
2483 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002484 case ASTNode::Kind::kEnum: {
2485 this->convertEnum(decl);
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002486 break;
2487 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002488 case ASTNode::Kind::kFunction: {
2489 this->convertFunction(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002490 break;
2491 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002492 case ASTNode::Kind::kModifiers: {
2493 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002494 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002495 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002496 }
2497 break;
2498 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002499 case ASTNode::Kind::kInterfaceBlock: {
2500 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002501 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002502 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002503 }
2504 break;
2505 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002506 case ASTNode::Kind::kExtension: {
2507 std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
2508 decl.getString());
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002509 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002510 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002511 }
2512 break;
2513 }
Ethan Nicholasfc994162019-06-06 10:04:27 -04002514 case ASTNode::Kind::kSection: {
2515 std::unique_ptr<Section> s = this->convertSection(decl);
Ethan Nicholas762466e2017-06-29 10:03:38 -04002516 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002517 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002518 }
2519 break;
2520 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002521 default:
2522 ABORT("unsupported declaration: %s\n", decl.description().c_str());
2523 }
2524 }
2525}
2526
2527
ethannicholasb3058bd2016-07-01 08:22:01 -07002528}