blob: bf017ad2d9fbfd8c49b41682a9bf1f6addb22f09 [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
ethannicholasb3058bd2016-07-01 08:22:01 -07008#include "SkSLIRGenerator.h"
9
10#include "limits.h"
Ethan Nicholasaf197692017-02-27 13:26:45 -050011#include <unordered_set>
ethannicholasb3058bd2016-07-01 08:22:01 -070012
Ethan Nicholas941e7e22016-12-12 15:33:30 -050013#include "SkSLCompiler.h"
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -040014#include "SkSLParser.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070015#include "ast/SkSLASTBoolLiteral.h"
16#include "ast/SkSLASTFieldSuffix.h"
17#include "ast/SkSLASTFloatLiteral.h"
18#include "ast/SkSLASTIndexSuffix.h"
19#include "ast/SkSLASTIntLiteral.h"
Ethan Nicholas26a9aad2018-03-27 14:10:52 -040020#include "ir/SkSLAppendStage.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070021#include "ir/SkSLBinaryExpression.h"
22#include "ir/SkSLBoolLiteral.h"
23#include "ir/SkSLBreakStatement.h"
24#include "ir/SkSLConstructor.h"
25#include "ir/SkSLContinueStatement.h"
26#include "ir/SkSLDiscardStatement.h"
27#include "ir/SkSLDoStatement.h"
Ethan Nicholasaae47c82017-11-10 15:34:03 -050028#include "ir/SkSLEnum.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070029#include "ir/SkSLExpressionStatement.h"
30#include "ir/SkSLField.h"
31#include "ir/SkSLFieldAccess.h"
32#include "ir/SkSLFloatLiteral.h"
33#include "ir/SkSLForStatement.h"
34#include "ir/SkSLFunctionCall.h"
35#include "ir/SkSLFunctionDeclaration.h"
36#include "ir/SkSLFunctionDefinition.h"
37#include "ir/SkSLFunctionReference.h"
38#include "ir/SkSLIfStatement.h"
39#include "ir/SkSLIndexExpression.h"
40#include "ir/SkSLInterfaceBlock.h"
41#include "ir/SkSLIntLiteral.h"
42#include "ir/SkSLLayout.h"
43#include "ir/SkSLPostfixExpression.h"
44#include "ir/SkSLPrefixExpression.h"
45#include "ir/SkSLReturnStatement.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040046#include "ir/SkSLSetting.h"
Ethan Nicholasaf197692017-02-27 13:26:45 -050047#include "ir/SkSLSwitchCase.h"
48#include "ir/SkSLSwitchStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070049#include "ir/SkSLSwizzle.h"
50#include "ir/SkSLTernaryExpression.h"
51#include "ir/SkSLUnresolvedFunction.h"
52#include "ir/SkSLVariable.h"
ethannicholas22f939e2016-10-13 13:25:34 -070053#include "ir/SkSLVarDeclarations.h"
54#include "ir/SkSLVarDeclarationsStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070055#include "ir/SkSLVariableReference.h"
56#include "ir/SkSLWhileStatement.h"
57
58namespace SkSL {
59
60class AutoSymbolTable {
61public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050062 AutoSymbolTable(IRGenerator* ir)
ethannicholasb3058bd2016-07-01 08:22:01 -070063 : fIR(ir)
64 , fPrevious(fIR->fSymbolTable) {
65 fIR->pushSymbolTable();
66 }
67
68 ~AutoSymbolTable() {
69 fIR->popSymbolTable();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -040070 SkASSERT(fPrevious == fIR->fSymbolTable);
ethannicholasb3058bd2016-07-01 08:22:01 -070071 }
72
73 IRGenerator* fIR;
74 std::shared_ptr<SymbolTable> fPrevious;
75};
76
ethannicholas22f939e2016-10-13 13:25:34 -070077class AutoLoopLevel {
78public:
Ethan Nicholas11d53972016-11-28 11:23:23 -050079 AutoLoopLevel(IRGenerator* ir)
ethannicholas22f939e2016-10-13 13:25:34 -070080 : fIR(ir) {
81 fIR->fLoopLevel++;
82 }
83
84 ~AutoLoopLevel() {
85 fIR->fLoopLevel--;
86 }
87
88 IRGenerator* fIR;
89};
90
Ethan Nicholasaf197692017-02-27 13:26:45 -050091class AutoSwitchLevel {
92public:
93 AutoSwitchLevel(IRGenerator* ir)
94 : fIR(ir) {
95 fIR->fSwitchLevel++;
96 }
97
98 ~AutoSwitchLevel() {
99 fIR->fSwitchLevel--;
100 }
101
102 IRGenerator* fIR;
103};
104
Ethan Nicholas11d53972016-11-28 11:23:23 -0500105IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ethannicholasb3058bd2016-07-01 08:22:01 -0700106 ErrorReporter& errorReporter)
ethannicholasd598f792016-07-25 10:08:54 -0700107: fContext(*context)
108, fCurrentFunction(nullptr)
Ethan Nicholas762466e2017-06-29 10:03:38 -0400109, fRootSymbolTable(symbolTable)
110, fSymbolTable(symbolTable)
ethannicholas22f939e2016-10-13 13:25:34 -0700111, fLoopLevel(0)
Ethan Nicholasaf197692017-02-27 13:26:45 -0500112, fSwitchLevel(0)
Ethan Nicholas762466e2017-06-29 10:03:38 -0400113, fTmpCount(0)
ethannicholasd598f792016-07-25 10:08:54 -0700114, fErrors(errorReporter) {}
ethannicholasb3058bd2016-07-01 08:22:01 -0700115
116void IRGenerator::pushSymbolTable() {
Ethan Nicholas8feeff92017-03-30 14:11:58 -0400117 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), &fErrors));
ethannicholasb3058bd2016-07-01 08:22:01 -0700118}
119
120void IRGenerator::popSymbolTable() {
121 fSymbolTable = fSymbolTable->fParent;
122}
123
Ethan Nicholas762466e2017-06-29 10:03:38 -0400124static void fill_caps(const SKSL_CAPS_CLASS& caps,
125 std::unordered_map<String, Program::Settings::Value>* capsMap) {
Brian Salomon23356442018-11-30 15:33:19 -0500126#define CAP(name) \
127 capsMap->insert(std::make_pair(String(#name), Program::Settings::Value(caps.name())))
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500128 CAP(fbFetchSupport);
Brian Salomond4013302018-04-04 13:58:33 +0000129 CAP(fbFetchNeedsCustomOutput);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500130 CAP(dropsTileOnZeroDivide);
131 CAP(flatInterpolationSupport);
132 CAP(noperspectiveInterpolationSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500133 CAP(externalTextureSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500134 CAP(imageLoadStoreSupport);
135 CAP(mustEnableAdvBlendEqs);
136 CAP(mustEnableSpecificAdvBlendEqs);
137 CAP(mustDeclareFragmentShaderOutput);
Michael Ludwig4f94ef62018-09-12 15:22:16 -0400138 CAP(mustDoOpBetweenFloorAndAbs);
Michael Ludwig24d438b2018-09-12 15:22:50 -0400139 CAP(atan2ImplementedAsAtanYOverX);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500140 CAP(canUseAnyFunctionInShader);
Chris Dalton47c8ed32017-11-15 18:27:09 -0700141 CAP(floatIs32Bits);
Ethan Nicholas07990de2017-07-18 09:47:43 -0400142 CAP(integerSupport);
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500143#undef CAP
144}
145
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400146void IRGenerator::start(const Program::Settings* settings,
147 std::vector<std::unique_ptr<ProgramElement>>* inherited) {
Ethan Nicholas00543112018-07-31 09:44:36 -0400148 if (fStarted) {
149 this->popSymbolTable();
150 }
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500151 fSettings = settings;
152 fCapsMap.clear();
153 if (settings->fCaps) {
154 fill_caps(*settings->fCaps, &fCapsMap);
Ethan Nicholas00543112018-07-31 09:44:36 -0400155 } else {
156 fCapsMap.insert(std::make_pair(String("integerSupport"),
157 Program::Settings::Value(true)));
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500158 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500159 this->pushSymbolTable();
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400160 fInvocations = -1;
Ethan Nicholas941e7e22016-12-12 15:33:30 -0500161 fInputs.reset();
Robert Phillipsfe8da172018-01-24 14:52:02 +0000162 fSkPerVertex = nullptr;
163 fRTAdjust = nullptr;
164 fRTAdjustInterfaceBlock = nullptr;
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400165 if (inherited) {
166 for (const auto& e : *inherited) {
167 if (e->fKind == ProgramElement::kInterfaceBlock_Kind) {
168 InterfaceBlock& intf = (InterfaceBlock&) *e;
169 if (intf.fVariable.fName == Compiler::PERVERTEX_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400170 SkASSERT(!fSkPerVertex);
Ethan Nicholas3c6ae622018-04-24 13:06:09 -0400171 fSkPerVertex = &intf.fVariable;
172 }
173 }
174 }
175 }
Ethan Nicholas3605ace2016-11-21 15:59:48 -0500176}
177
ethannicholasb3058bd2016-07-01 08:22:01 -0700178std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700179 return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName));
ethannicholasb3058bd2016-07-01 08:22:01 -0700180}
181
182std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
183 switch (statement.fKind) {
184 case ASTStatement::kBlock_Kind:
185 return this->convertBlock((ASTBlock&) statement);
186 case ASTStatement::kVarDeclaration_Kind:
187 return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000188 case ASTStatement::kExpression_Kind: {
189 std::unique_ptr<Statement> result =
190 this->convertExpressionStatement((ASTExpressionStatement&) statement);
Ethan Nicholase1f55022019-02-05 17:17:40 -0500191 if (!result) {
192 return nullptr;
193 }
Robert Phillipsfe8da172018-01-24 14:52:02 +0000194 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400195 SkASSERT(result->fKind == Statement::kExpression_Kind);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000196 Expression& expr = *((ExpressionStatement&) *result).fExpression;
197 if (expr.fKind == Expression::kFunctionCall_Kind) {
198 FunctionCall& fc = (FunctionCall&) expr;
199 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
200 std::vector<std::unique_ptr<Statement>> statements;
201 statements.push_back(getNormalizeSkPositionCode());
202 statements.push_back(std::move(result));
203 return std::unique_ptr<Block>(new Block(statement.fOffset,
204 std::move(statements),
205 fSymbolTable));
206 }
207 }
208 }
209 return result;
210 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700211 case ASTStatement::kIf_Kind:
212 return this->convertIf((ASTIfStatement&) statement);
213 case ASTStatement::kFor_Kind:
214 return this->convertFor((ASTForStatement&) statement);
215 case ASTStatement::kWhile_Kind:
216 return this->convertWhile((ASTWhileStatement&) statement);
217 case ASTStatement::kDo_Kind:
218 return this->convertDo((ASTDoStatement&) statement);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500219 case ASTStatement::kSwitch_Kind:
220 return this->convertSwitch((ASTSwitchStatement&) statement);
ethannicholasb3058bd2016-07-01 08:22:01 -0700221 case ASTStatement::kReturn_Kind:
222 return this->convertReturn((ASTReturnStatement&) statement);
223 case ASTStatement::kBreak_Kind:
224 return this->convertBreak((ASTBreakStatement&) statement);
225 case ASTStatement::kContinue_Kind:
226 return this->convertContinue((ASTContinueStatement&) statement);
227 case ASTStatement::kDiscard_Kind:
228 return this->convertDiscard((ASTDiscardStatement&) statement);
229 default:
230 ABORT("unsupported statement type: %d\n", statement.fKind);
231 }
232}
233
234std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
235 AutoSymbolTable table(this);
236 std::vector<std::unique_ptr<Statement>> statements;
237 for (size_t i = 0; i < block.fStatements.size(); i++) {
238 std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
239 if (!statement) {
240 return nullptr;
241 }
242 statements.push_back(std::move(statement));
243 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700244 return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700245}
246
247std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
248 const ASTVarDeclarationStatement& s) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700249 auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700250 if (!decl) {
251 return nullptr;
252 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700253 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700254}
255
ethannicholas14fe8cc2016-09-07 13:37:16 -0700256std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
257 Variable::Storage storage) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000258 std::vector<std::unique_ptr<VarDeclaration>> variables;
ethannicholasd598f792016-07-25 10:08:54 -0700259 const Type* baseType = this->convertType(*decl.fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700260 if (!baseType) {
261 return nullptr;
262 }
Ethan Nicholas56b4e3d2019-01-08 09:34:40 -0500263 if (fKind != Program::kFragmentProcessor_Kind &&
264 (decl.fModifiers.fFlags & Modifiers::kIn_Flag) &&
265 baseType->kind() == Type::Kind::kMatrix_Kind) {
266 fErrors.error(decl.fOffset, "'in' variables may not have matrix type");
267 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700268 for (const auto& varDecl : decl.fVars) {
Ethan Nicholas6c942712018-03-16 09:45:11 -0400269 if (decl.fModifiers.fLayout.fLocation == 0 && decl.fModifiers.fLayout.fIndex == 0 &&
270 (decl.fModifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
271 varDecl.fName != "sk_FragColor") {
272 fErrors.error(decl.fOffset,
273 "out location=0, index=0 is reserved for sk_FragColor");
274 }
ethannicholasd598f792016-07-25 10:08:54 -0700275 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700276 std::vector<std::unique_ptr<Expression>> sizes;
277 for (const auto& rawSize : varDecl.fSizes) {
278 if (rawSize) {
279 auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700280 if (!size) {
281 return nullptr;
282 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700283 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500284 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700285 if (size->fKind == Expression::kIntLiteral_Kind) {
286 count = ((IntLiteral&) *size).fValue;
287 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700288 fErrors.error(size->fOffset, "array size must be positive");
ethannicholasb3058bd2016-07-01 08:22:01 -0700289 }
290 name += "[" + to_string(count) + "]";
291 } else {
292 count = -1;
293 name += "[]";
294 }
ethannicholasd598f792016-07-25 10:08:54 -0700295 type = new Type(name, Type::kArray_Kind, *type, (int) count);
296 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700297 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700298 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700299 type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
ethannicholasd598f792016-07-25 10:08:54 -0700300 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700301 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700302 }
303 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000304 auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
305 varDecl.fName, *type, storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000306 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400307 SkASSERT(!fRTAdjust);
308 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000309 fRTAdjust = var.get();
310 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700311 std::unique_ptr<Expression> value;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700312 if (varDecl.fValue) {
313 value = this->convertExpression(*varDecl.fValue);
ethannicholasb3058bd2016-07-01 08:22:01 -0700314 if (!value) {
315 return nullptr;
316 }
ethannicholasd598f792016-07-25 10:08:54 -0700317 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500318 if (!value) {
319 return nullptr;
320 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400321 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500322 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700323 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700324 if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" &&
ethannicholasea4567c2016-10-17 11:24:37 -0700325 (*fSymbolTable)[varDecl.fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700326 // already defined, ignore
ethannicholasea4567c2016-10-17 11:24:37 -0700327 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
328 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
ethannicholas5961bc92016-10-12 06:39:56 -0700329 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700330 // already defined, just update the modifiers
ethannicholas14fe8cc2016-09-07 13:37:16 -0700331 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
ethannicholasf789b382016-08-03 12:43:36 -0700332 old->fModifiers = var->fModifiers;
333 } else {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000334 variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
335 std::move(value)));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700336 fSymbolTable->add(varDecl.fName, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700337 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700338 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700339 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700340 baseType,
341 std::move(variables)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700342}
343
ethannicholas5961bc92016-10-12 06:39:56 -0700344std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
345 const ASTModifiersDeclaration& m) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400346 Modifiers modifiers = m.fModifiers;
347 if (modifiers.fLayout.fInvocations != -1) {
348 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600349 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400350 modifiers.fLayout.fInvocations = -1;
351 Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400352 SkASSERT(invocationId);
Ethan Nicholasd1d52562018-03-20 16:30:34 -0400353 invocationId->fModifiers.fFlags = 0;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400354 invocationId->fModifiers.fLayout.fBuiltin = -1;
355 if (modifiers.fLayout.description() == "") {
356 return nullptr;
357 }
358 }
359 }
360 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600361 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400362 modifiers.fLayout.fMaxVertices *= fInvocations;
363 }
364 return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
ethannicholas5961bc92016-10-12 06:39:56 -0700365}
366
ethannicholasb3058bd2016-07-01 08:22:01 -0700367std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500368 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700369 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700370 if (!test) {
371 return nullptr;
372 }
373 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
374 if (!ifTrue) {
375 return nullptr;
376 }
377 std::unique_ptr<Statement> ifFalse;
378 if (s.fIfFalse) {
379 ifFalse = this->convertStatement(*s.fIfFalse);
380 if (!ifFalse) {
381 return nullptr;
382 }
383 }
ethannicholas08a92112016-11-09 13:26:45 -0800384 if (test->fKind == Expression::kBoolLiteral_Kind) {
385 // static boolean value, fold down to a single branch
386 if (((BoolLiteral&) *test).fValue) {
387 return ifTrue;
388 } else if (s.fIfFalse) {
389 return ifFalse;
390 } else {
391 // False & no else clause. Not an error, so don't return null!
392 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700393 return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800394 fSymbolTable));
395 }
396 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700397 return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700398 std::move(ifTrue), std::move(ifFalse)));
399}
400
401std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
ethannicholas22f939e2016-10-13 13:25:34 -0700402 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700403 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700404 std::unique_ptr<Statement> initializer;
405 if (f.fInitializer) {
406 initializer = this->convertStatement(*f.fInitializer);
407 if (!initializer) {
408 return nullptr;
409 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700410 }
ethannicholas22f939e2016-10-13 13:25:34 -0700411 std::unique_ptr<Expression> test;
412 if (f.fTest) {
413 test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
414 if (!test) {
415 return nullptr;
416 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 }
ethannicholas22f939e2016-10-13 13:25:34 -0700418 std::unique_ptr<Expression> next;
419 if (f.fNext) {
420 next = this->convertExpression(*f.fNext);
421 if (!next) {
422 return nullptr;
423 }
424 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700425 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700426 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
427 if (!statement) {
428 return nullptr;
429 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700430 return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer),
ethannicholasb3058bd2016-07-01 08:22:01 -0700431 std::move(test), std::move(next),
ethannicholasd598f792016-07-25 10:08:54 -0700432 std::move(statement), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700433}
434
435std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
ethannicholas22f939e2016-10-13 13:25:34 -0700436 AutoLoopLevel level(this);
Ethan Nicholas11d53972016-11-28 11:23:23 -0500437 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700438 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700439 if (!test) {
440 return nullptr;
441 }
442 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
443 if (!statement) {
444 return nullptr;
445 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700446 return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700447 std::move(statement)));
448}
449
450std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
ethannicholas22f939e2016-10-13 13:25:34 -0700451 AutoLoopLevel level(this);
ethannicholasd598f792016-07-25 10:08:54 -0700452 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
453 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700454 if (!test) {
455 return nullptr;
456 }
457 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
458 if (!statement) {
459 return nullptr;
460 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700461 return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
ethannicholasb3058bd2016-07-01 08:22:01 -0700462 std::move(test)));
463}
464
Ethan Nicholasaf197692017-02-27 13:26:45 -0500465std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
466 AutoSwitchLevel level(this);
467 std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
468 if (!value) {
469 return nullptr;
470 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500471 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500472 value = this->coerce(std::move(value), *fContext.fInt_Type);
473 if (!value) {
474 return nullptr;
475 }
476 }
477 AutoSymbolTable table(this);
478 std::unordered_set<int> caseValues;
479 std::vector<std::unique_ptr<SwitchCase>> cases;
480 for (const auto& c : s.fCases) {
481 std::unique_ptr<Expression> caseValue;
482 if (c->fValue) {
483 caseValue = this->convertExpression(*c->fValue);
484 if (!caseValue) {
485 return nullptr;
486 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500487 caseValue = this->coerce(std::move(caseValue), value->fType);
488 if (!caseValue) {
489 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500490 }
491 if (!caseValue->isConstant()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700492 fErrors.error(caseValue->fOffset, "case value must be a constant");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500493 return nullptr;
494 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500495 int64_t v;
496 this->getConstantInt(*caseValue, &v);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500497 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700498 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500499 }
500 caseValues.insert(v);
501 }
502 std::vector<std::unique_ptr<Statement>> statements;
503 for (const auto& s : c->fStatements) {
504 std::unique_ptr<Statement> converted = this->convertStatement(*s);
505 if (!converted) {
506 return nullptr;
507 }
508 statements.push_back(std::move(converted));
509 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700510 cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500511 std::move(statements)));
512 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700513 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic,
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400514 std::move(value), std::move(cases),
515 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500516}
517
ethannicholasb3058bd2016-07-01 08:22:01 -0700518std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
519 const ASTExpressionStatement& s) {
520 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
521 if (!e) {
522 return nullptr;
523 }
524 this->checkValid(*e);
525 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
526}
527
528std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400529 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000530 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400531 // 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 +0000532 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400533 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700534 if (r.fExpression) {
535 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
536 if (!result) {
537 return nullptr;
538 }
ethannicholasd598f792016-07-25 10:08:54 -0700539 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700540 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700541 } else {
542 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
543 if (!result) {
544 return nullptr;
545 }
546 }
547 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
548 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700549 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700550 fErrors.error(r.fOffset, "expected function to return '" +
551 fCurrentFunction->fReturnType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700552 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700553 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700554 }
555}
556
557std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500558 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700559 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700560 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700561 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700562 return nullptr;
563 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700564}
565
566std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
ethannicholas22f939e2016-10-13 13:25:34 -0700567 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700568 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700569 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700570 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700571 return nullptr;
572 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700573}
574
575std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700576 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700577}
578
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500579std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400580 Layout invokeLayout;
581 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700582 FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400583 invokeModifiers,
584 "_invoke",
585 std::vector<const Variable*>(),
586 *fContext.fVoid_Type);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500587 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
588 new FunctionDefinition(-1, *invokeDecl, std::move(main))));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400589 fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
590
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000591 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400592 Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400593 SkASSERT(loopIdx);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700594 std::unique_ptr<Expression> test(new BinaryExpression(-1,
595 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400596 Token::LT,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700597 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400598 *fContext.fBool_Type));
599 std::unique_ptr<Expression> next(new PostfixExpression(
600 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700601 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400602 *loopIdx,
603 VariableReference::kReadWrite_RefKind)),
604 Token::PLUSPLUS));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700605 ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400606 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400607 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400608
609 std::vector<std::unique_ptr<Statement>> loopBody;
610 std::vector<std::unique_ptr<Expression>> invokeArgs;
611 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700612 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400613 *invokeDecl,
614 std::vector<std::unique_ptr<Expression>>()))));
615 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700616 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400617 std::move(endPrimitive),
618 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700619 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
620 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400621 Token::EQ,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700622 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400623 *fContext.fInt_Type));
624 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
625 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700626 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400627 std::move(initializer),
628 std::move(test),
629 std::move(next),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700630 std::unique_ptr<Block>(new Block(-1, std::move(loopBody))),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400631 fSymbolTable));
632 std::vector<std::unique_ptr<Statement>> children;
633 children.push_back(std::move(loop));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700634 return std::unique_ptr<Block>(new Block(-1, std::move(children)));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400635}
636
Robert Phillipsfe8da172018-01-24 14:52:02 +0000637std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400638 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000639 // 0,
640 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400641 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000642 #define REF(var) std::unique_ptr<Expression>(\
643 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
644 #define FIELD(var, idx) std::unique_ptr<Expression>(\
645 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
646 #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \
647 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
648 #define ADJUST (fRTAdjustInterfaceBlock ? \
649 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
650 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400651 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
652 { __VA_ARGS__ }))
653 #define OP(left, op, right) std::unique_ptr<Expression>( \
654 new BinaryExpression(-1, left, op, right, \
655 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000656 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400657 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::STAR, SWIZZLE(ADJUST, 0, 2)),
Robert Phillipsfe8da172018-01-24 14:52:02 +0000658 Token::PLUS,
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400659 OP(SWIZZLE(POS, 3, 3), Token::STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000660 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
661 children.push_back(SWIZZLE(POS, 3));
662 std::unique_ptr<Expression> result = OP(POS, Token::EQ,
663 std::unique_ptr<Expression>(new Constructor(-1,
664 *fContext.fFloat4_Type,
665 std::move(children))));
666 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
667}
668
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400669
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500670void IRGenerator::convertFunction(const ASTFunction& f) {
ethannicholasd598f792016-07-25 10:08:54 -0700671 const Type* returnType = this->convertType(*f.fReturnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700672 if (!returnType) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400673 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700674 }
ethannicholasd598f792016-07-25 10:08:54 -0700675 std::vector<const Variable*> parameters;
ethannicholasb3058bd2016-07-01 08:22:01 -0700676 for (const auto& param : f.fParameters) {
ethannicholasd598f792016-07-25 10:08:54 -0700677 const Type* type = this->convertType(*param->fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700678 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400679 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700680 }
681 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
682 int size = param->fSizes[j];
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400683 String name = type->name() + "[" + to_string(size) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700684 Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
685 fSymbolTable->takeOwnership(newType);
686 type = newType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700687 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700688 StringFragment name = param->fName;
689 Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type,
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000690 Variable::kParameter_Storage);
ethannicholasd598f792016-07-25 10:08:54 -0700691 fSymbolTable->takeOwnership(var);
692 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700693 }
694
Ethan Nicholas00543112018-07-31 09:44:36 -0400695 if (f.fName == "main") {
696 if (fKind == Program::kPipelineStage_Kind) {
697 bool valid = parameters.size() == 3 &&
698 parameters[0]->fType == *fContext.fInt_Type &&
699 parameters[0]->fModifiers.fFlags == 0 &&
700 parameters[1]->fType == *fContext.fInt_Type &&
701 parameters[1]->fModifiers.fFlags == 0 &&
702 parameters[2]->fType == *fContext.fHalf4_Type &&
703 parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
704 Modifiers::kOut_Flag);
705 if (!valid) {
706 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
707 "int, inout half4)");
708 return;
709 }
710 } else if (parameters.size()) {
711 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
712 }
713 }
714
ethannicholasb3058bd2016-07-01 08:22:01 -0700715 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700716 const FunctionDeclaration* decl = nullptr;
717 auto entry = (*fSymbolTable)[f.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700718 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700719 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700720 switch (entry->fKind) {
721 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700722 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700723 break;
724 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700725 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700726 break;
727 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700728 fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400729 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700730 }
731 for (const auto& other : functions) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400732 SkASSERT(other->fName == f.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700733 if (parameters.size() == other->fParameters.size()) {
734 bool match = true;
735 for (size_t i = 0; i < parameters.size(); i++) {
736 if (parameters[i]->fType != other->fParameters[i]->fType) {
737 match = false;
738 break;
739 }
740 }
741 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700742 if (*returnType != other->fReturnType) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700743 FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters,
Ethan Nicholascb670962017-04-20 19:31:52 -0400744 *returnType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700745 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
746 "' and '" + other->description() +
747 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400748 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700749 }
750 decl = other;
751 for (size_t i = 0; i < parameters.size(); i++) {
752 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700753 fErrors.error(f.fOffset, "modifiers on parameter " +
754 to_string((uint64_t) i + 1) +
755 " differ between declaration and "
756 "definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400757 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700758 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700759 }
760 if (other->fDefined) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700761 fErrors.error(f.fOffset, "duplicate definition of " +
762 other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700763 }
764 break;
765 }
766 }
767 }
768 }
769 if (!decl) {
770 // couldn't find an existing declaration
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700771 auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -0400772 f.fModifiers,
ethannicholas471e8942016-10-28 09:02:46 -0700773 f.fName,
774 parameters,
775 *returnType));
776 decl = newDecl.get();
777 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -0700778 }
ethannicholasd598f792016-07-25 10:08:54 -0700779 if (f.fBody) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400780 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -0700781 fCurrentFunction = decl;
782 decl->fDefined = true;
783 std::shared_ptr<SymbolTable> old = fSymbolTable;
784 AutoSymbolTable table(this);
Ethan Nicholas00543112018-07-31 09:44:36 -0400785 if (f.fName == "main" && fKind == Program::kPipelineStage_Kind) {
786 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_X_BUILTIN;
787 parameters[1]->fModifiers.fLayout.fBuiltin = SK_MAIN_Y_BUILTIN;
788 parameters[2]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
789 }
ethannicholasd598f792016-07-25 10:08:54 -0700790 for (size_t i = 0; i < parameters.size(); i++) {
791 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -0700792 }
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600793 bool needInvocationIDWorkaround = fInvocations != -1 && f.fName == "main" &&
794 fSettings->fCaps &&
795 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400796 SkASSERT(!fExtraVars.size());
ethannicholasd598f792016-07-25 10:08:54 -0700797 std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400798 for (auto& v : fExtraVars) {
799 body->fStatements.insert(body->fStatements.begin(), std::move(v));
800 }
801 fExtraVars.clear();
ethannicholasd598f792016-07-25 10:08:54 -0700802 fCurrentFunction = nullptr;
803 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400804 return;
805 }
806 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500807 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -0700808 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400809 // conservatively assume all user-defined functions have side effects
810 ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000811 if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) {
812 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
813 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500814 fProgramElements->push_back(std::unique_ptr<FunctionDefinition>(
815 new FunctionDefinition(f.fOffset, *decl, std::move(body))));
ethannicholasb3058bd2016-07-01 08:22:01 -0700816 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700817}
818
819std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
820 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500821 this->pushSymbolTable();
822 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -0700823 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400824 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000825 bool foundRTAdjust = false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700826 for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700827 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholasa7ceb502019-01-11 10:31:48 -0500828 *intf.fDeclarations[i],
829 Variable::kInterfaceBlock_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -0700830 if (!decl) {
831 return nullptr;
832 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000833 for (const auto& stmt : decl->fVars) {
834 VarDeclaration& vd = (VarDeclaration&) *stmt;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400835 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000836 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400837 "only the last entry in an interface block may be a runtime-sized "
838 "array");
839 }
Robert Phillipsfe8da172018-01-24 14:52:02 +0000840 if (vd.fVar == fRTAdjust) {
841 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400842 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000843 fRTAdjustFieldIndex = fields.size();
844 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000845 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
846 &vd.fVar->fType));
847 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700848 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700849 "initializers are not permitted on interface block fields");
850 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000851 if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
852 Modifiers::kOut_Flag |
853 Modifiers::kUniform_Flag |
854 Modifiers::kBuffer_Flag |
855 Modifiers::kConst_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700856 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700857 "interface block fields may not have storage qualifiers");
858 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000859 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
860 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400861 haveRuntimeArray = true;
862 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500863 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700864 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500865 this->popSymbolTable();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700866 Type* type = new Type(intf.fOffset, intf.fTypeName, fields);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500867 old->takeOwnership(type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500868 std::vector<std::unique_ptr<Expression>> sizes;
869 for (const auto& size : intf.fSizes) {
870 if (size) {
871 std::unique_ptr<Expression> converted = this->convertExpression(*size);
872 if (!converted) {
873 return nullptr;
874 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400875 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500876 int64_t count;
877 if (converted->fKind == Expression::kIntLiteral_Kind) {
878 count = ((IntLiteral&) *converted).fValue;
879 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700880 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500881 }
882 name += "[" + to_string(count) + "]";
883 } else {
884 count = -1;
885 name += "[]";
886 }
887 type = new Type(name, Type::kArray_Kind, *type, (int) count);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500888 symbols->takeOwnership((Type*) type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500889 sizes.push_back(std::move(converted));
890 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700891 type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500892 symbols->takeOwnership((Type*) type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500893 sizes.push_back(nullptr);
894 }
895 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700896 Variable* var = new Variable(intf.fOffset, intf.fModifiers,
897 intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000898 *type, Variable::kGlobal_Storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000899 if (foundRTAdjust) {
900 fRTAdjustInterfaceBlock = var;
901 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500902 old->takeOwnership(var);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700903 if (intf.fInstanceName.fLength) {
Ethan Nicholas50afc172017-02-16 14:49:57 -0500904 old->addWithoutOwnership(intf.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700905 } else {
906 for (size_t i = 0; i < fields.size(); i++) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700907 old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
ethannicholasd598f792016-07-25 10:08:54 -0700908 (int) i)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700909 }
910 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700911 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
Ethan Nicholas8feeff92017-03-30 14:11:58 -0400912 var,
Ethan Nicholas50afc172017-02-16 14:49:57 -0500913 intf.fTypeName,
914 intf.fInstanceName,
915 std::move(sizes),
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500916 symbols));
ethannicholasb3058bd2016-07-01 08:22:01 -0700917}
918
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500919void IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
920 switch (value.fKind) {
921 case Expression::kIntLiteral_Kind:
922 *out = ((const IntLiteral&) value).fValue;
923 break;
924 case Expression::kVariableReference_Kind: {
925 const Variable& var = ((VariableReference&) value).fVariable;
926 if ((var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
927 var.fInitialValue) {
928 this->getConstantInt(*var.fInitialValue, out);
929 }
930 break;
931 }
932 default:
933 fErrors.error(value.fOffset, "expected a constant int");
934 }
935}
936
937void IRGenerator::convertEnum(const ASTEnum& e) {
938 std::vector<Variable*> variables;
939 int64_t currentValue = 0;
940 Layout layout;
941 ASTType enumType(e.fOffset, e.fTypeName, ASTType::kIdentifier_Kind, {});
942 const Type* type = this->convertType(enumType);
943 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Ethan Nicholaseace9352018-10-15 20:09:54 +0000944 std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable, &fErrors));
945 fSymbolTable = symbols;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500946 for (size_t i = 0; i < e.fNames.size(); i++) {
947 std::unique_ptr<Expression> value;
948 if (e.fValues[i]) {
949 value = this->convertExpression(*e.fValues[i]);
950 if (!value) {
Ethan Nicholaseace9352018-10-15 20:09:54 +0000951 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500952 return;
953 }
954 this->getConstantInt(*value, &currentValue);
955 }
956 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
957 ++currentValue;
958 auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, e.fNames[i],
959 *type, Variable::kGlobal_Storage,
960 value.get()));
961 variables.push_back(var.get());
962 symbols->add(e.fNames[i], std::move(var));
963 symbols->takeOwnership(value.release());
964 }
965 fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.fTypeName,
966 symbols)));
Ethan Nicholaseace9352018-10-15 20:09:54 +0000967 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500968}
969
ethannicholasd598f792016-07-25 10:08:54 -0700970const Type* IRGenerator::convertType(const ASTType& type) {
971 const Symbol* result = (*fSymbolTable)[type.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700972 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholas50afc172017-02-16 14:49:57 -0500973 for (int size : type.fSizes) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700974 String name(result->fName);
975 name += "[";
Ethan Nicholas50afc172017-02-16 14:49:57 -0500976 if (size != -1) {
977 name += to_string(size);
978 }
979 name += "]";
980 result = new Type(name, Type::kArray_Kind, (const Type&) *result, size);
981 fSymbolTable->takeOwnership((Type*) result);
982 }
ethannicholasd598f792016-07-25 10:08:54 -0700983 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700984 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700985 fErrors.error(type.fOffset, "unknown type '" + type.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700986 return nullptr;
987}
988
989std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
990 switch (expr.fKind) {
991 case ASTExpression::kIdentifier_Kind:
992 return this->convertIdentifier((ASTIdentifier&) expr);
993 case ASTExpression::kBool_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700994 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700995 ((ASTBoolLiteral&) expr).fValue));
996 case ASTExpression::kInt_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700997 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700998 ((ASTIntLiteral&) expr).fValue));
999 case ASTExpression::kFloat_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001000 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001001 ((ASTFloatLiteral&) expr).fValue));
1002 case ASTExpression::kBinary_Kind:
1003 return this->convertBinaryExpression((ASTBinaryExpression&) expr);
1004 case ASTExpression::kPrefix_Kind:
1005 return this->convertPrefixExpression((ASTPrefixExpression&) expr);
1006 case ASTExpression::kSuffix_Kind:
1007 return this->convertSuffixExpression((ASTSuffixExpression&) expr);
1008 case ASTExpression::kTernary_Kind:
1009 return this->convertTernaryExpression((ASTTernaryExpression&) expr);
1010 default:
1011 ABORT("unsupported expression type: %d\n", expr.fKind);
1012 }
1013}
1014
1015std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
ethannicholasd598f792016-07-25 10:08:54 -07001016 const Symbol* result = (*fSymbolTable)[identifier.fText];
ethannicholasb3058bd2016-07-01 08:22:01 -07001017 if (!result) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001018 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001019 return nullptr;
1020 }
1021 switch (result->fKind) {
1022 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001023 std::vector<const FunctionDeclaration*> f = {
1024 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -07001025 };
ethannicholasd598f792016-07-25 10:08:54 -07001026 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001027 identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001028 f));
ethannicholasb3058bd2016-07-01 08:22:01 -07001029 }
1030 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001031 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
1032 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001033 identifier.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001034 f->fFunctions));
1035 }
1036 case Symbol::kVariable_Kind: {
Ethan Nicholas38657112017-02-09 17:01:22 -05001037 const Variable* var = (const Variable*) result;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001038 switch (var->fModifiers.fLayout.fBuiltin) {
1039 case SK_WIDTH_BUILTIN:
1040 fInputs.fRTWidth = true;
1041 break;
1042 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001043 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001044 break;
1045#ifndef SKSL_STANDALONE
1046 case SK_FRAGCOORD_BUILTIN:
1047 if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
1048 fInputs.fFlipY = true;
1049 if (fSettings->fFlipY &&
1050 (!fSettings->fCaps ||
1051 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1052 fInputs.fRTHeight = true;
1053 }
1054 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001055#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001056 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001057 // default to kRead_RefKind; this will be corrected later if the variable is written to
1058 return std::unique_ptr<VariableReference>(new VariableReference(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001059 identifier.fOffset,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001060 *var,
1061 VariableReference::kRead_RefKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001062 }
1063 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001064 const Field* field = (const Field*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001065 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001066 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001067 return std::unique_ptr<Expression>(new FieldAccess(
1068 std::unique_ptr<Expression>(base),
1069 field->fFieldIndex,
1070 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001071 }
1072 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001073 const Type* t = (const Type*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001074 return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001075 *t));
ethannicholasb3058bd2016-07-01 08:22:01 -07001076 }
1077 default:
1078 ABORT("unsupported symbol type %d\n", result->fKind);
1079 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001080}
1081
Ethan Nicholas762466e2017-06-29 10:03:38 -04001082std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001083 return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001084}
1085
1086
Ethan Nicholas11d53972016-11-28 11:23:23 -05001087std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001088 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001089 if (!expr) {
1090 return nullptr;
1091 }
ethannicholasd598f792016-07-25 10:08:54 -07001092 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001093 return expr;
1094 }
1095 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001096 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001097 return nullptr;
1098 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001099 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001100 fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
ethannicholasd598f792016-07-25 10:08:54 -07001101 expr->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001102 return nullptr;
1103 }
ethannicholasd598f792016-07-25 10:08:54 -07001104 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 std::vector<std::unique_ptr<Expression>> args;
1106 args.push_back(std::move(expr));
Ethan Nicholase1f55022019-02-05 17:17:40 -05001107 std::unique_ptr<Expression> ctor;
1108 if (type == *fContext.fFloatLiteral_Type) {
1109 ctor = this->convertIdentifier(ASTIdentifier(-1, "float"));
1110 } else if (type == *fContext.fIntLiteral_Type) {
1111 ctor = this->convertIdentifier(ASTIdentifier(-1, "int"));
1112 } else {
1113 ctor = this->convertIdentifier(ASTIdentifier(-1, type.fName));
1114 }
1115 if (!ctor) {
1116 printf("error, null identifier: %s\n", String(type.fName).c_str());
1117 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001118 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001119 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001120 }
ethannicholas5961bc92016-10-12 06:39:56 -07001121 std::vector<std::unique_ptr<Expression>> args;
1122 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001123 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001124}
1125
ethannicholasf789b382016-08-03 12:43:36 -07001126static bool is_matrix_multiply(const Type& left, const Type& right) {
1127 if (left.kind() == Type::kMatrix_Kind) {
1128 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1129 }
1130 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1131}
ethannicholasea4567c2016-10-17 11:24:37 -07001132
ethannicholasb3058bd2016-07-01 08:22:01 -07001133/**
1134 * Determines the operand and result types of a binary expression. Returns true if the expression is
1135 * legal, false otherwise. If false, the values of the out parameters are undefined.
1136 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001137static bool determine_binary_type(const Context& context,
1138 Token::Kind op,
1139 const Type& left,
1140 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001141 const Type** outLeftType,
1142 const Type** outRightType,
1143 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001144 bool tryFlipped) {
1145 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001146 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001147 switch (op) {
ethannicholasea4567c2016-10-17 11:24:37 -07001148 case Token::EQ:
1149 *outLeftType = &left;
1150 *outRightType = &left;
1151 *outResultType = &left;
1152 return right.canCoerceTo(left);
ethannicholasb3058bd2016-07-01 08:22:01 -07001153 case Token::EQEQ: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001154 case Token::NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001155 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001156 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001157 *outRightType = &left;
1158 *outResultType = context.fBool_Type.get();
1159 return true;
1160 } if (left.canCoerceTo(right)) {
1161 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001162 *outRightType = &right;
1163 *outResultType = context.fBool_Type.get();
1164 return true;
1165 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001166 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001167 case Token::LT: // fall through
1168 case Token::GT: // fall through
1169 case Token::LTEQ: // fall through
1170 case Token::GTEQ:
1171 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001172 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001173 break;
1174 case Token::LOGICALOR: // fall through
1175 case Token::LOGICALAND: // fall through
1176 case Token::LOGICALXOR: // fall through
1177 case Token::LOGICALOREQ: // fall through
1178 case Token::LOGICALANDEQ: // fall through
1179 case Token::LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001180 *outLeftType = context.fBool_Type.get();
1181 *outRightType = context.fBool_Type.get();
1182 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001183 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001184 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas11d53972016-11-28 11:23:23 -05001185 case Token::STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001186 if (left.kind() == Type::kScalar_Kind) {
1187 *outLeftType = &left;
1188 *outRightType = &left;
1189 *outResultType = &left;
1190 return right.canCoerceTo(left);
1191 }
1192 // fall through
1193 case Token::STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001194 if (is_matrix_multiply(left, right)) {
1195 // determine final component type
1196 if (determine_binary_type(context, Token::STAR, left.componentType(),
1197 right.componentType(), outLeftType, outRightType,
1198 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001199 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001200 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001201 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001202 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001203 int leftColumns = left.columns();
1204 int leftRows = left.rows();
1205 int rightColumns;
1206 int rightRows;
1207 if (right.kind() == Type::kVector_Kind) {
1208 // matrix * vector treats the vector as a column vector, so we need to
1209 // transpose it
1210 rightColumns = right.rows();
1211 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001212 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001213 } else {
1214 rightColumns = right.columns();
1215 rightRows = right.rows();
1216 }
1217 if (rightColumns > 1) {
1218 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1219 leftRows);
1220 } else {
1221 // result was a column vector, transpose it back to a row
1222 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1223 rightColumns);
1224 }
1225 return leftColumns == rightRows;
1226 } else {
1227 return false;
1228 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001229 }
ethannicholasea4567c2016-10-17 11:24:37 -07001230 isLogical = false;
1231 validMatrixOrVectorOp = true;
1232 break;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001233 case Token::PLUSEQ:
1234 case Token::MINUSEQ:
1235 case Token::SLASHEQ:
1236 case Token::PERCENTEQ:
1237 case Token::SHLEQ:
1238 case Token::SHREQ:
1239 if (left.kind() == Type::kScalar_Kind) {
1240 *outLeftType = &left;
1241 *outRightType = &left;
1242 *outResultType = &left;
1243 return right.canCoerceTo(left);
1244 }
1245 // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001246 case Token::PLUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001247 case Token::MINUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001248 case Token::SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001249 isLogical = false;
1250 validMatrixOrVectorOp = true;
1251 break;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001252 case Token::COMMA:
1253 *outLeftType = &left;
1254 *outRightType = &right;
1255 *outResultType = &right;
1256 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001257 default:
1258 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001259 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001260 }
ethannicholasea4567c2016-10-17 11:24:37 -07001261 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001262 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1263 right.canCoerceTo(left)) {
1264 if (left.priority() > right.priority()) {
1265 *outLeftType = &left;
1266 *outRightType = &left;
1267 } else {
1268 *outLeftType = &right;
1269 *outRightType = &right;
1270 }
1271 if (isLogical) {
1272 *outResultType = context.fBool_Type.get();
1273 } else {
1274 *outResultType = &left;
1275 }
1276 return true;
1277 }
1278 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001279 *outLeftType = &left;
1280 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001281 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001282 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001283 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001284 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001285 }
1286 return true;
1287 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001288 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001289 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001290 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001291 outRightType, outResultType, false)) {
1292 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001293 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001294 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001295 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001296 }
1297 return true;
1298 }
1299 return false;
1300 }
1301 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001302 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001303 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001304 }
1305 return false;
1306}
1307
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001308static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1309 const Expression& left,
1310 Token::Kind op,
1311 const Expression& right) {
1312 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
1313 bool leftVal = ((BoolLiteral&) left).fValue;
1314 if (op == Token::LOGICALAND) {
1315 // (true && expr) -> (expr) and (false && expr) -> (false)
1316 return leftVal ? right.clone()
1317 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
1318 } else if (op == Token::LOGICALOR) {
1319 // (true || expr) -> (true) and (false || expr) -> (expr)
1320 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1321 : right.clone();
1322 } else {
1323 // Can't short circuit XOR
1324 return nullptr;
1325 }
1326}
1327
ethannicholas08a92112016-11-09 13:26:45 -08001328std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1329 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001330 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001331 // If the left side is a constant boolean literal, the right side does not need to be constant
1332 // for short circuit optimizations to allow the constant to be folded.
1333 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isConstant()) {
1334 return short_circuit_boolean(fContext, left, op, right);
1335 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isConstant()) {
1336 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1337 // (right OP left) for short-circuit optimizations
1338 return short_circuit_boolean(fContext, right, op, left);
1339 }
1340
1341 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Ethan Nicholascb670962017-04-20 19:31:52 -04001342 if (!left.isConstant() || !right.isConstant()) {
1343 return nullptr;
1344 }
ethannicholas08a92112016-11-09 13:26:45 -08001345 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1346 // precision to calculate the results and hope the result makes sense. The plan is to move the
1347 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1348 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001349 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001350 right.fKind == Expression::kBoolLiteral_Kind) {
1351 bool leftVal = ((BoolLiteral&) left).fValue;
1352 bool rightVal = ((BoolLiteral&) right).fValue;
1353 bool result;
1354 switch (op) {
1355 case Token::LOGICALAND: result = leftVal && rightVal; break;
1356 case Token::LOGICALOR: result = leftVal || rightVal; break;
1357 case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
1358 default: return nullptr;
1359 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001360 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001361 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001362 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \
ethannicholas08a92112016-11-09 13:26:45 -08001363 leftVal op rightVal))
1364 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
1365 int64_t leftVal = ((IntLiteral&) left).fValue;
1366 int64_t rightVal = ((IntLiteral&) right).fValue;
1367 switch (op) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001368 case Token::PLUS: return RESULT(Int, +);
1369 case Token::MINUS: return RESULT(Int, -);
1370 case Token::STAR: return RESULT(Int, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001371 case Token::SLASH:
1372 if (rightVal) {
1373 return RESULT(Int, /);
1374 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001375 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001376 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001377 case Token::PERCENT:
1378 if (rightVal) {
1379 return RESULT(Int, %);
1380 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001381 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001382 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001383 case Token::BITWISEAND: return RESULT(Int, &);
1384 case Token::BITWISEOR: return RESULT(Int, |);
1385 case Token::BITWISEXOR: return RESULT(Int, ^);
1386 case Token::SHL: return RESULT(Int, <<);
1387 case Token::SHR: return RESULT(Int, >>);
1388 case Token::EQEQ: return RESULT(Bool, ==);
1389 case Token::NEQ: return RESULT(Bool, !=);
1390 case Token::GT: return RESULT(Bool, >);
1391 case Token::GTEQ: return RESULT(Bool, >=);
1392 case Token::LT: return RESULT(Bool, <);
1393 case Token::LTEQ: return RESULT(Bool, <=);
1394 default: return nullptr;
1395 }
1396 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001397 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001398 right.fKind == Expression::kFloatLiteral_Kind) {
1399 double leftVal = ((FloatLiteral&) left).fValue;
1400 double rightVal = ((FloatLiteral&) right).fValue;
1401 switch (op) {
1402 case Token::PLUS: return RESULT(Float, +);
1403 case Token::MINUS: return RESULT(Float, -);
1404 case Token::STAR: return RESULT(Float, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001405 case Token::SLASH:
1406 if (rightVal) {
1407 return RESULT(Float, /);
1408 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001409 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001410 return nullptr;
Ethan Nicholascb670962017-04-20 19:31:52 -04001411 case Token::EQEQ: return RESULT(Bool, ==);
1412 case Token::NEQ: return RESULT(Bool, !=);
1413 case Token::GT: return RESULT(Bool, >);
1414 case Token::GTEQ: return RESULT(Bool, >=);
1415 case Token::LT: return RESULT(Bool, <);
1416 case Token::LTEQ: return RESULT(Bool, <=);
ethannicholas08a92112016-11-09 13:26:45 -08001417 default: return nullptr;
1418 }
1419 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001420 if (left.fType.kind() == Type::kVector_Kind && left.fType.componentType().isFloat() &&
Ethan Nicholascb670962017-04-20 19:31:52 -04001421 left.fType == right.fType) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001422 SkASSERT(left.fKind == Expression::kConstructor_Kind);
1423 SkASSERT(right.fKind == Expression::kConstructor_Kind);
Ethan Nicholascb670962017-04-20 19:31:52 -04001424 std::vector<std::unique_ptr<Expression>> args;
1425 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1426 for (int i = 0; i < left.fType.columns(); i++) { \
1427 float value = ((Constructor&) left).getFVecComponent(i) op \
1428 ((Constructor&) right).getFVecComponent(i); \
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001429 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
Ethan Nicholascb670962017-04-20 19:31:52 -04001430 } \
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001431 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001432 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001433 switch (op) {
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001434 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001435 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001436 left.compareConstant(fContext, right)));
1437 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001438 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001439 !left.compareConstant(fContext, right)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001440 case Token::PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1441 case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1442 case Token::STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1443 case Token::SLASH: RETURN_VEC_COMPONENTWISE_RESULT(/);
1444 default: return nullptr;
1445 }
1446 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001447 if (left.fType.kind() == Type::kMatrix_Kind &&
1448 right.fType.kind() == Type::kMatrix_Kind &&
1449 left.fKind == right.fKind) {
1450 switch (op) {
1451 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001452 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001453 left.compareConstant(fContext, right)));
1454 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001455 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001456 !left.compareConstant(fContext, right)));
1457 default:
1458 return nullptr;
1459 }
1460 }
ethannicholas08a92112016-11-09 13:26:45 -08001461 #undef RESULT
1462 return nullptr;
1463}
1464
ethannicholasb3058bd2016-07-01 08:22:01 -07001465std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
1466 const ASTBinaryExpression& expression) {
1467 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
1468 if (!left) {
1469 return nullptr;
1470 }
1471 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
1472 if (!right) {
1473 return nullptr;
1474 }
ethannicholasd598f792016-07-25 10:08:54 -07001475 const Type* leftType;
1476 const Type* rightType;
1477 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001478 const Type* rawLeftType;
1479 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1480 rawLeftType = &right->fType;
1481 } else {
1482 rawLeftType = &left->fType;
1483 }
1484 const Type* rawRightType;
1485 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1486 rawRightType = &left->fType;
1487 } else {
1488 rawRightType = &right->fType;
1489 }
1490 if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
1491 &leftType, &rightType, &resultType,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001492 !Compiler::IsAssignment(expression.fOperator))) {
1493 fErrors.error(expression.fOffset, String("type mismatch: '") +
1494 Compiler::OperatorName(expression.fOperator) +
Ethan Nicholase1f55022019-02-05 17:17:40 -05001495 "' cannot operate on '" + left->fType.description() +
1496 "', '" + right->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 return nullptr;
1498 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001499 if (Compiler::IsAssignment(expression.fOperator)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001500 this->setRefKind(*left, expression.fOperator != Token::EQ ?
1501 VariableReference::kReadWrite_RefKind :
1502 VariableReference::kWrite_RefKind);
ethannicholasea4567c2016-10-17 11:24:37 -07001503 }
1504 left = this->coerce(std::move(left), *leftType);
1505 right = this->coerce(std::move(right), *rightType);
1506 if (!left || !right) {
1507 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001508 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001509 std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
ethannicholas08a92112016-11-09 13:26:45 -08001510 *right.get());
1511 if (!result) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001512 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08001513 std::move(left),
1514 expression.fOperator,
1515 std::move(right),
1516 *resultType));
1517 }
1518 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001519}
1520
Ethan Nicholas11d53972016-11-28 11:23:23 -05001521std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
ethannicholasb3058bd2016-07-01 08:22:01 -07001522 const ASTTernaryExpression& expression) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001523 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
ethannicholasd598f792016-07-25 10:08:54 -07001524 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001525 if (!test) {
1526 return nullptr;
1527 }
1528 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
1529 if (!ifTrue) {
1530 return nullptr;
1531 }
1532 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
1533 if (!ifFalse) {
1534 return nullptr;
1535 }
ethannicholasd598f792016-07-25 10:08:54 -07001536 const Type* trueType;
1537 const Type* falseType;
1538 const Type* resultType;
1539 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001540 &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001541 fErrors.error(expression.fOffset, "ternary operator result mismatch: '" +
Ethan Nicholase1f55022019-02-05 17:17:40 -05001542 ifTrue->fType.description() + "', '" +
1543 ifFalse->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001544 return nullptr;
1545 }
ethannicholasd598f792016-07-25 10:08:54 -07001546 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001547 if (!ifTrue) {
1548 return nullptr;
1549 }
ethannicholasd598f792016-07-25 10:08:54 -07001550 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001551 if (!ifFalse) {
1552 return nullptr;
1553 }
ethannicholas08a92112016-11-09 13:26:45 -08001554 if (test->fKind == Expression::kBoolLiteral_Kind) {
1555 // static boolean test, just return one of the branches
1556 if (((BoolLiteral&) *test).fValue) {
1557 return ifTrue;
1558 } else {
1559 return ifFalse;
1560 }
1561 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001562 return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001563 std::move(test),
Ethan Nicholas11d53972016-11-28 11:23:23 -05001564 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -07001565 std::move(ifFalse)));
1566}
1567
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001568std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001569 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07001570 std::vector<std::unique_ptr<Expression>> arguments) {
1571 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001572 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05001573 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07001574 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07001575 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001576 msg += "s";
1577 }
ethannicholas5961bc92016-10-12 06:39:56 -07001578 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001579 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001580 return nullptr;
1581 }
ethannicholas471e8942016-10-28 09:02:46 -07001582 std::vector<const Type*> types;
1583 const Type* returnType;
1584 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001585 String msg = "no match for " + function.fName + "(";
1586 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07001587 for (size_t i = 0; i < arguments.size(); i++) {
1588 msg += separator;
1589 separator = ", ";
1590 msg += arguments[i]->fType.description();
1591 }
1592 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001593 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07001594 return nullptr;
1595 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001596 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07001597 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07001598 if (!arguments[i]) {
1599 return nullptr;
1600 }
ethannicholasd598f792016-07-25 10:08:54 -07001601 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001602 this->setRefKind(*arguments[i],
1603 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
1604 VariableReference::kReadWrite_RefKind :
1605 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001606 }
1607 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001608 return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
ethannicholasb3058bd2016-07-01 08:22:01 -07001609 std::move(arguments)));
1610}
1611
1612/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001613 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
1614 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
1615 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07001616 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001617int IRGenerator::callCost(const FunctionDeclaration& function,
1618 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07001619 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001620 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001621 }
1622 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07001623 std::vector<const Type*> types;
1624 const Type* ignored;
1625 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001626 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07001627 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001628 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001629 int cost = arguments[i]->coercionCost(*types[i]);
1630 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001631 total += cost;
1632 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001633 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001634 }
1635 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001636 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07001637}
1638
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001639std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001640 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07001641 std::vector<std::unique_ptr<Expression>> arguments) {
1642 if (functionValue->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001643 return this->convertConstructor(offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001644 ((TypeReference&) *functionValue).fValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07001645 std::move(arguments));
1646 }
1647 if (functionValue->fKind != Expression::kFunctionReference_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001648 fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
ethannicholasb3058bd2016-07-01 08:22:01 -07001649 return nullptr;
1650 }
1651 FunctionReference* ref = (FunctionReference*) functionValue.get();
1652 int bestCost = INT_MAX;
ethannicholasd598f792016-07-25 10:08:54 -07001653 const FunctionDeclaration* best = nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001654 if (ref->fFunctions.size() > 1) {
1655 for (const auto& f : ref->fFunctions) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001656 int cost = this->callCost(*f, arguments);
1657 if (cost < bestCost) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001658 bestCost = cost;
1659 best = f;
1660 }
1661 }
1662 if (best) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001663 return this->call(offset, *best, std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001664 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001665 String msg = "no match for " + ref->fFunctions[0]->fName + "(";
1666 String separator;
ethannicholasb3058bd2016-07-01 08:22:01 -07001667 for (size_t i = 0; i < arguments.size(); i++) {
1668 msg += separator;
1669 separator = ", ";
ethannicholasd598f792016-07-25 10:08:54 -07001670 msg += arguments[i]->fType.description();
ethannicholasb3058bd2016-07-01 08:22:01 -07001671 }
1672 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001673 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001674 return nullptr;
1675 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001676 return this->call(offset, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001677}
1678
Ethan Nicholas84645e32017-02-09 13:57:14 -05001679std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001680 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001681 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07001682 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001683 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05001684 if (args.size() != 1) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001685 fErrors.error(offset, "invalid arguments to '" + type.description() +
1686 "' constructor, (expected exactly 1 argument, but found " +
1687 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07001688 return nullptr;
1689 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001690 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001691 return std::move(args[0]);
1692 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001693 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
1694 double value = ((FloatLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001695 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001696 }
1697 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001698 int64_t value = ((IntLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001699 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001700 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001701 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
1702 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04001703 return std::unique_ptr<Expression>(new IntLiteral(offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001704 ((IntLiteral&) *args[0]).fValue,
1705 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001706 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001707 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001708 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
1709 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001710 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001711 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05001712 this->coerce(std::move(one), type),
1713 this->coerce(std::move(zero),
1714 type)));
1715 }
1716 if (!args[0]->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001717 fErrors.error(offset, "invalid argument to '" + type.description() +
1718 "' constructor (expected a number or bool, but found '" +
1719 args[0]->fType.description() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05001720 return nullptr;
1721 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001722 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001723}
1724
1725int component_count(const Type& type) {
1726 switch (type.kind()) {
1727 case Type::kVector_Kind:
1728 return type.columns();
1729 case Type::kMatrix_Kind:
1730 return type.columns() * type.rows();
1731 default:
1732 return 1;
1733 }
1734}
1735
1736std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001737 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001738 const Type& type,
1739 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001740 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05001741 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
1742 args[0]->fType.kind() == Type::kMatrix_Kind) {
1743 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001744 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001745 }
1746 int actual = 0;
1747 int expected = type.rows() * type.columns();
1748 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
1749 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07001750 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05001751 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001752 if (type.componentType().isNumber() !=
1753 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001754 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1755 "parameter to '" + type.description() +
1756 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001757 return nullptr;
1758 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001759 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001760 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
1761 actual += 1;
1762 if (type.kind() != Type::kScalar_Kind) {
1763 args[i] = this->coerce(std::move(args[i]), type.componentType());
1764 if (!args[i]) {
1765 return nullptr;
1766 }
1767 }
1768 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001769 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1770 "parameter to '" + type.description() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001771 return nullptr;
1772 }
1773 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001774 if (actual != 1 && actual != expected) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001775 fErrors.error(offset, "invalid arguments to '" + type.description() +
1776 "' constructor (expected " + to_string(expected) +
1777 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001778 return nullptr;
1779 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001780 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001781 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001782}
1783
Ethan Nicholas84645e32017-02-09 13:57:14 -05001784std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001785 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001786 const Type& type,
1787 std::vector<std::unique_ptr<Expression>> args) {
1788 // FIXME: add support for structs
1789 Type::Kind kind = type.kind();
1790 if (args.size() == 1 && args[0]->fType == type) {
1791 // argument is already the right type, just return it
1792 return std::move(args[0]);
1793 }
1794 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001795 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001796 } else if (kind == Type::kArray_Kind) {
1797 const Type& base = type.componentType();
1798 for (size_t i = 0; i < args.size(); i++) {
1799 args[i] = this->coerce(std::move(args[i]), base);
1800 if (!args[i]) {
1801 return nullptr;
1802 }
1803 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001804 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001805 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001806 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001807 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001808 fErrors.error(offset, "cannot construct '" + type.description() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05001809 return nullptr;
1810 }
1811}
1812
ethannicholasb3058bd2016-07-01 08:22:01 -07001813std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1814 const ASTPrefixExpression& expression) {
1815 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1816 if (!base) {
1817 return nullptr;
1818 }
1819 switch (expression.fOperator) {
1820 case Token::PLUS:
Ethan Nicholase1f55022019-02-05 17:17:40 -05001821 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
1822 base->fType != *fContext.fFloatLiteral_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001823 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001824 "'+' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001825 return nullptr;
1826 }
1827 return base;
1828 case Token::MINUS:
ethannicholasb3058bd2016-07-01 08:22:01 -07001829 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001830 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001831 -((IntLiteral&) *base).fValue));
1832 }
1833 if (base->fKind == Expression::kFloatLiteral_Kind) {
1834 double value = -((FloatLiteral&) *base).fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001835 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001836 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07001837 }
Ethan Nicholase1f55022019-02-05 17:17:40 -05001838 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
1839 fErrors.error(expression.fOffset,
1840 "'-' cannot operate on '" + base->fType.description() + "'");
1841 return nullptr;
1842 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001843 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1844 case Token::PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001845 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001846 fErrors.error(expression.fOffset,
1847 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001848 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 return nullptr;
1850 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001851 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001852 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05001853 case Token::MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001854 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001855 fErrors.error(expression.fOffset,
1856 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001857 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001858 return nullptr;
1859 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001860 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001861 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001862 case Token::LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07001863 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001864 fErrors.error(expression.fOffset,
1865 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001866 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001867 return nullptr;
1868 }
ethannicholas08a92112016-11-09 13:26:45 -08001869 if (base->fKind == Expression::kBoolLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001870 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08001871 !((BoolLiteral&) *base).fValue));
1872 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001873 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001874 case Token::BITWISENOT:
1875 if (base->fType != *fContext.fInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001876 fErrors.error(expression.fOffset,
1877 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholas5961bc92016-10-12 06:39:56 -07001878 "' cannot operate on '" + base->fType.description() + "'");
1879 return nullptr;
1880 }
1881 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05001882 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07001883 ABORT("unsupported prefix operator\n");
1884 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001885 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
ethannicholasb3058bd2016-07-01 08:22:01 -07001886 std::move(base)));
1887}
1888
1889std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1890 const ASTExpression& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05001891 if (base->fKind == Expression::kTypeReference_Kind) {
1892 if (index.fKind == ASTExpression::kInt_Kind) {
1893 const Type& oldType = ((TypeReference&) *base).fValue;
1894 int64_t size = ((const ASTIntLiteral&) index).fValue;
1895 Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]",
1896 Type::kArray_Kind, oldType, size);
1897 fSymbolTable->takeOwnership(newType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001898 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
Ethan Nicholas50afc172017-02-16 14:49:57 -05001899 *newType));
1900
1901 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001902 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05001903 return nullptr;
1904 }
1905 }
ethannicholas5961bc92016-10-12 06:39:56 -07001906 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
1907 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001908 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
1909 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001910 return nullptr;
1911 }
1912 std::unique_ptr<Expression> converted = this->convertExpression(index);
1913 if (!converted) {
1914 return nullptr;
1915 }
ethannicholas5961bc92016-10-12 06:39:56 -07001916 if (converted->fType != *fContext.fUInt_Type) {
1917 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
1918 if (!converted) {
1919 return nullptr;
1920 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001921 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001922 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07001923 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001924}
1925
1926std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001927 StringFragment field) {
ethannicholasd598f792016-07-25 10:08:54 -07001928 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07001929 for (size_t i = 0; i < fields.size(); i++) {
1930 if (fields[i].fName == field) {
1931 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1932 }
1933 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001934 fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
1935 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07001936 return nullptr;
1937}
1938
1939std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001940 StringFragment fields) {
ethannicholasd598f792016-07-25 10:08:54 -07001941 if (base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001942 fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001943 return nullptr;
1944 }
1945 std::vector<int> swizzleComponents;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001946 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05001947 switch (fields[i]) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001948 case 'x': // fall through
1949 case 'r': // fall through
Ethan Nicholas11d53972016-11-28 11:23:23 -05001950 case 's':
ethannicholasb3058bd2016-07-01 08:22:01 -07001951 swizzleComponents.push_back(0);
1952 break;
1953 case 'y': // fall through
1954 case 'g': // fall through
1955 case 't':
ethannicholasd598f792016-07-25 10:08:54 -07001956 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001957 swizzleComponents.push_back(1);
1958 break;
1959 }
1960 // fall through
1961 case 'z': // fall through
1962 case 'b': // fall through
Ethan Nicholas11d53972016-11-28 11:23:23 -05001963 case 'p':
ethannicholasd598f792016-07-25 10:08:54 -07001964 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001965 swizzleComponents.push_back(2);
1966 break;
1967 }
1968 // fall through
1969 case 'w': // fall through
1970 case 'a': // fall through
1971 case 'q':
ethannicholasd598f792016-07-25 10:08:54 -07001972 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001973 swizzleComponents.push_back(3);
1974 break;
1975 }
1976 // fall through
1977 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001978 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
1979 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07001980 return nullptr;
1981 }
1982 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001983 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07001984 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001985 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001986 return nullptr;
1987 }
ethannicholasd598f792016-07-25 10:08:54 -07001988 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07001989}
1990
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001991std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001992 auto found = fCapsMap.find(name);
1993 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001994 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001995 return nullptr;
1996 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04001997 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001998 return std::unique_ptr<Expression>(new Setting(offset, fullName,
1999 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002000}
2001
Ethan Nicholas00543112018-07-31 09:44:36 -04002002std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -04002003 auto found = fSettings->fArgs.find(name);
2004 if (found == fSettings->fArgs.end()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04002005 return nullptr;
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002006 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002007 String fullName = "sk_Args." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002008 return std::unique_ptr<Expression>(new Setting(offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -04002009 fullName,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002010 found->second.literal(fContext, offset)));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002011}
2012
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002013std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2014 StringFragment field) {
2015 std::unique_ptr<Expression> result;
2016 for (const auto& e : *fProgramElements) {
2017 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
2018 std::shared_ptr<SymbolTable> old = fSymbolTable;
2019 fSymbolTable = ((Enum&) *e).fSymbols;
2020 result = convertIdentifier(ASTIdentifier(offset, field));
2021 fSymbolTable = old;
2022 }
2023 }
2024 if (!result) {
2025 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2026 "'");
2027 }
2028 return result;
2029}
2030
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002031std::unique_ptr<Expression> IRGenerator::convertAppend(int offset,
2032 const std::vector<std::unique_ptr<ASTExpression>>& args) {
2033#ifndef SKSL_STANDALONE
2034 if (args.size() < 2) {
2035 fErrors.error(offset, "'append' requires at least two arguments");
2036 return nullptr;
2037 }
2038 std::unique_ptr<Expression> pipeline = this->convertExpression(*args[0]);
2039 if (!pipeline) {
2040 return nullptr;
2041 }
2042 if (pipeline->fType != *fContext.fSkRasterPipeline_Type) {
2043 fErrors.error(offset, "first argument of 'append' must have type 'SkRasterPipeline'");
2044 return nullptr;
2045 }
2046 if (ASTExpression::kIdentifier_Kind != args[1]->fKind) {
2047 fErrors.error(offset, "'" + args[1]->description() + "' is not a valid stage");
2048 return nullptr;
2049 }
2050 StringFragment name = ((const ASTIdentifier&) *args[1]).fText;
2051 SkRasterPipeline::StockStage stage = SkRasterPipeline::premul;
2052 std::vector<std::unique_ptr<Expression>> stageArgs;
2053 stageArgs.push_back(std::move(pipeline));
2054 for (size_t i = 2; i < args.size(); ++i) {
2055 std::unique_ptr<Expression> arg = this->convertExpression(*args[i]);
2056 if (!arg) {
2057 return nullptr;
2058 }
2059 stageArgs.push_back(std::move(arg));
2060 }
2061 size_t expectedArgs = 0;
2062 // FIXME use a map
2063 if ("premul" == name) {
2064 stage = SkRasterPipeline::premul;
2065 }
2066 else if ("unpremul" == name) {
2067 stage = SkRasterPipeline::unpremul;
2068 }
2069 else if ("clamp_0" == name) {
2070 stage = SkRasterPipeline::clamp_0;
2071 }
2072 else if ("clamp_1" == name) {
2073 stage = SkRasterPipeline::clamp_1;
2074 }
2075 else if ("matrix_4x5" == name) {
2076 expectedArgs = 1;
2077 stage = SkRasterPipeline::matrix_4x5;
2078 if (1 == stageArgs.size() && stageArgs[0]->fType.fName != "float[20]") {
2079 fErrors.error(offset, "pipeline stage '" + name + "' expected a float[20] argument");
2080 return nullptr;
2081 }
2082 }
2083 else {
2084 bool found = false;
2085 for (const auto& e : *fProgramElements) {
2086 if (ProgramElement::kFunction_Kind == e->fKind) {
2087 const FunctionDefinition& f = (const FunctionDefinition&) *e;
2088 if (f.fDeclaration.fName == name) {
2089 stage = SkRasterPipeline::callback;
2090 std::vector<const FunctionDeclaration*> functions = { &f.fDeclaration };
2091 stageArgs.emplace_back(new FunctionReference(fContext, offset, functions));
2092 found = true;
2093 break;
2094 }
2095 }
2096 }
2097 if (!found) {
2098 fErrors.error(offset, "'" + name + "' is not a valid pipeline stage");
2099 return nullptr;
2100 }
2101 }
2102 if (args.size() != expectedArgs + 2) {
2103 fErrors.error(offset, "pipeline stage '" + name + "' expected an additional argument " +
2104 "count of " + to_string((int) expectedArgs) + ", but found " +
2105 to_string((int) args.size() - 1));
2106 return nullptr;
2107 }
2108 return std::unique_ptr<Expression>(new AppendStage(fContext, offset, stage,
2109 std::move(stageArgs)));
2110#else
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002111 SkASSERT(false);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002112 return nullptr;
2113#endif
2114}
2115
ethannicholasb3058bd2016-07-01 08:22:01 -07002116std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
2117 const ASTSuffixExpression& expression) {
2118 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
2119 if (!base) {
2120 return nullptr;
2121 }
2122 switch (expression.fSuffix->fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -07002123 case ASTSuffix::kIndex_Kind: {
2124 const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
2125 if (expr) {
2126 return this->convertIndex(std::move(base), *expr);
2127 } else if (base->fKind == Expression::kTypeReference_Kind) {
2128 const Type& oldType = ((TypeReference&) *base).fValue;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002129 Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
ethannicholas5961bc92016-10-12 06:39:56 -07002130 -1);
2131 fSymbolTable->takeOwnership(newType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002132 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
ethannicholas5961bc92016-10-12 06:39:56 -07002133 *newType));
2134 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002135 fErrors.error(expression.fOffset, "'[]' must follow a type name");
ethannicholasa54401d2016-10-14 08:37:32 -07002136 return nullptr;
ethannicholas5961bc92016-10-12 06:39:56 -07002137 }
2138 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002139 case ASTSuffix::kCall_Kind: {
2140 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002141 if (Expression::kFunctionReference_Kind == base->fKind &&
2142 "append" == ((const FunctionReference&) *base).fFunctions[0]->fName) {
2143 return convertAppend(expression.fOffset, *rawArguments);
2144 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002145 std::vector<std::unique_ptr<Expression>> arguments;
2146 for (size_t i = 0; i < rawArguments->size(); i++) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05002147 std::unique_ptr<Expression> converted =
ethannicholasb3058bd2016-07-01 08:22:01 -07002148 this->convertExpression(*(*rawArguments)[i]);
2149 if (!converted) {
2150 return nullptr;
2151 }
2152 arguments.push_back(std::move(converted));
2153 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002154 return this->call(expression.fOffset, std::move(base), std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002155 }
2156 case ASTSuffix::kField_Kind: {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002157 StringFragment field = ((ASTFieldSuffix&) *expression.fSuffix).fField;
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002158 if (base->fType == *fContext.fSkCaps_Type) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002159 return this->getCap(expression.fOffset, field);
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002160 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002161 if (base->fType == *fContext.fSkArgs_Type) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002162 return this->getArg(expression.fOffset, field);
2163 }
2164 if (base->fKind == Expression::kTypeReference_Kind) {
2165 return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
2166 field);
Ethan Nicholas762466e2017-06-29 10:03:38 -04002167 }
ethannicholasd598f792016-07-25 10:08:54 -07002168 switch (base->fType.kind()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002169 case Type::kVector_Kind:
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002170 return this->convertSwizzle(std::move(base), field);
Michael Ludwig9094f2c2018-09-07 13:44:21 -04002171 case Type::kOther_Kind:
ethannicholasb3058bd2016-07-01 08:22:01 -07002172 case Type::kStruct_Kind:
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002173 return this->convertField(std::move(base), field);
ethannicholasb3058bd2016-07-01 08:22:01 -07002174 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002175 fErrors.error(base->fOffset, "cannot swizzle value of type '" +
2176 base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002177 return nullptr;
2178 }
2179 }
2180 case ASTSuffix::kPostIncrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07002181 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002182 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002183 "'++' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002184 return nullptr;
2185 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002186 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
Ethan Nicholas11d53972016-11-28 11:23:23 -05002187 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
ethannicholasb3058bd2016-07-01 08:22:01 -07002188 Token::PLUSPLUS));
2189 case ASTSuffix::kPostDecrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07002190 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002191 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002192 "'--' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002193 return nullptr;
2194 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002195 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
Ethan Nicholas11d53972016-11-28 11:23:23 -05002196 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
ethannicholasb3058bd2016-07-01 08:22:01 -07002197 Token::MINUSMINUS));
2198 default:
2199 ABORT("unsupported suffix operator");
2200 }
2201}
2202
2203void IRGenerator::checkValid(const Expression& expr) {
2204 switch (expr.fKind) {
2205 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002206 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07002207 break;
2208 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002209 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07002210 break;
2211 default:
ethannicholasea4567c2016-10-17 11:24:37 -07002212 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002213 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07002214 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002215 }
2216}
2217
ethannicholasb3058bd2016-07-01 08:22:01 -07002218static bool has_duplicates(const Swizzle& swizzle) {
2219 int bits = 0;
2220 for (int idx : swizzle.fComponents) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002221 SkASSERT(idx >= 0 && idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07002222 int bit = 1 << idx;
2223 if (bits & bit) {
2224 return true;
2225 }
2226 bits |= bit;
2227 }
2228 return false;
2229}
2230
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002231void IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002232 switch (expr.fKind) {
2233 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07002234 const Variable& var = ((VariableReference&) expr).fVariable;
ethannicholasb3058bd2016-07-01 08:22:01 -07002235 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002236 fErrors.error(expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002237 "cannot modify immutable variable '" + var.fName + "'");
2238 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002239 ((VariableReference&) expr).setRefKind(kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002240 break;
2241 }
2242 case Expression::kFieldAccess_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002243 this->setRefKind(*((FieldAccess&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002244 break;
2245 case Expression::kSwizzle_Kind:
2246 if (has_duplicates((Swizzle&) expr)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002247 fErrors.error(expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002248 "cannot write to the same swizzle field more than once");
2249 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002250 this->setRefKind(*((Swizzle&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002251 break;
2252 case Expression::kIndex_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002253 this->setRefKind(*((IndexExpression&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002254 break;
Ethan Nicholasa583b812018-01-18 13:32:11 -05002255 case Expression::kTernary_Kind: {
2256 TernaryExpression& t = (TernaryExpression&) expr;
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002257 this->setRefKind(*t.fIfTrue, kind);
2258 this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002259 break;
2260 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002261 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002262 fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002263 break;
2264 }
2265}
2266
Robert Phillipsfe8da172018-01-24 14:52:02 +00002267void IRGenerator::convertProgram(Program::Kind kind,
2268 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002269 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002270 SymbolTable& types,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002271 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00002272 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002273 fProgramElements = out;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002274 Parser parser(text, length, types, fErrors);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002275 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
2276 if (fErrors.errorCount()) {
2277 return;
2278 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002279 for (size_t i = 0; i < parsed.size(); i++) {
2280 ASTDeclaration& decl = *parsed[i];
2281 switch (decl.fKind) {
2282 case ASTDeclaration::kVar_Kind: {
2283 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
2284 (ASTVarDeclarations&) decl,
2285 Variable::kGlobal_Storage);
2286 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002287 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002288 }
2289 break;
2290 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002291 case ASTDeclaration::kEnum_Kind: {
2292 this->convertEnum((ASTEnum&) decl);
2293 break;
2294 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002295 case ASTDeclaration::kFunction_Kind: {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002296 this->convertFunction((ASTFunction&) decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002297 break;
2298 }
2299 case ASTDeclaration::kModifiers_Kind: {
2300 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(
2301 (ASTModifiersDeclaration&) decl);
2302 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002303 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002304 }
2305 break;
2306 }
2307 case ASTDeclaration::kInterfaceBlock_Kind: {
2308 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(
2309 (ASTInterfaceBlock&) decl);
2310 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002311 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002312 }
2313 break;
2314 }
2315 case ASTDeclaration::kExtension_Kind: {
2316 std::unique_ptr<Extension> e = this->convertExtension((ASTExtension&) decl);
2317 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002318 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002319 }
2320 break;
2321 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002322 case ASTDeclaration::kSection_Kind: {
2323 std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl);
2324 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002325 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002326 }
2327 break;
2328 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002329 default:
2330 ABORT("unsupported declaration: %s\n", decl.description().c_str());
2331 }
2332 }
2333}
2334
2335
ethannicholasb3058bd2016-07-01 08:22:01 -07002336}