blob: f9d40985032de27214238e3c9b4e0f9802c0979f [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);
191 if (fRTAdjust && Program::kGeometry_Kind == fKind) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400192 SkASSERT(result->fKind == Statement::kExpression_Kind);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000193 Expression& expr = *((ExpressionStatement&) *result).fExpression;
194 if (expr.fKind == Expression::kFunctionCall_Kind) {
195 FunctionCall& fc = (FunctionCall&) expr;
196 if (fc.fFunction.fBuiltin && fc.fFunction.fName == "EmitVertex") {
197 std::vector<std::unique_ptr<Statement>> statements;
198 statements.push_back(getNormalizeSkPositionCode());
199 statements.push_back(std::move(result));
200 return std::unique_ptr<Block>(new Block(statement.fOffset,
201 std::move(statements),
202 fSymbolTable));
203 }
204 }
205 }
206 return result;
207 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700208 case ASTStatement::kIf_Kind:
209 return this->convertIf((ASTIfStatement&) statement);
210 case ASTStatement::kFor_Kind:
211 return this->convertFor((ASTForStatement&) statement);
212 case ASTStatement::kWhile_Kind:
213 return this->convertWhile((ASTWhileStatement&) statement);
214 case ASTStatement::kDo_Kind:
215 return this->convertDo((ASTDoStatement&) statement);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500216 case ASTStatement::kSwitch_Kind:
217 return this->convertSwitch((ASTSwitchStatement&) statement);
ethannicholasb3058bd2016-07-01 08:22:01 -0700218 case ASTStatement::kReturn_Kind:
219 return this->convertReturn((ASTReturnStatement&) statement);
220 case ASTStatement::kBreak_Kind:
221 return this->convertBreak((ASTBreakStatement&) statement);
222 case ASTStatement::kContinue_Kind:
223 return this->convertContinue((ASTContinueStatement&) statement);
224 case ASTStatement::kDiscard_Kind:
225 return this->convertDiscard((ASTDiscardStatement&) statement);
226 default:
227 ABORT("unsupported statement type: %d\n", statement.fKind);
228 }
229}
230
231std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
232 AutoSymbolTable table(this);
233 std::vector<std::unique_ptr<Statement>> statements;
234 for (size_t i = 0; i < block.fStatements.size(); i++) {
235 std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
236 if (!statement) {
237 return nullptr;
238 }
239 statements.push_back(std::move(statement));
240 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700241 return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700242}
243
244std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
245 const ASTVarDeclarationStatement& s) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700246 auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700247 if (!decl) {
248 return nullptr;
249 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700250 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700251}
252
ethannicholas14fe8cc2016-09-07 13:37:16 -0700253std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
254 Variable::Storage storage) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000255 std::vector<std::unique_ptr<VarDeclaration>> variables;
ethannicholasd598f792016-07-25 10:08:54 -0700256 const Type* baseType = this->convertType(*decl.fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700257 if (!baseType) {
258 return nullptr;
259 }
Ethan Nicholas56b4e3d2019-01-08 09:34:40 -0500260 if (fKind != Program::kFragmentProcessor_Kind &&
261 (decl.fModifiers.fFlags & Modifiers::kIn_Flag) &&
262 baseType->kind() == Type::Kind::kMatrix_Kind) {
263 fErrors.error(decl.fOffset, "'in' variables may not have matrix type");
264 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700265 for (const auto& varDecl : decl.fVars) {
Ethan Nicholas6c942712018-03-16 09:45:11 -0400266 if (decl.fModifiers.fLayout.fLocation == 0 && decl.fModifiers.fLayout.fIndex == 0 &&
267 (decl.fModifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
268 varDecl.fName != "sk_FragColor") {
269 fErrors.error(decl.fOffset,
270 "out location=0, index=0 is reserved for sk_FragColor");
271 }
ethannicholasd598f792016-07-25 10:08:54 -0700272 const Type* type = baseType;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700273 std::vector<std::unique_ptr<Expression>> sizes;
274 for (const auto& rawSize : varDecl.fSizes) {
275 if (rawSize) {
276 auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700277 if (!size) {
278 return nullptr;
279 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700280 String name(type->fName);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500281 int64_t count;
ethannicholasb3058bd2016-07-01 08:22:01 -0700282 if (size->fKind == Expression::kIntLiteral_Kind) {
283 count = ((IntLiteral&) *size).fValue;
284 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700285 fErrors.error(size->fOffset, "array size must be positive");
ethannicholasb3058bd2016-07-01 08:22:01 -0700286 }
287 name += "[" + to_string(count) + "]";
288 } else {
289 count = -1;
290 name += "[]";
291 }
ethannicholasd598f792016-07-25 10:08:54 -0700292 type = new Type(name, Type::kArray_Kind, *type, (int) count);
293 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700294 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700295 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700296 type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
ethannicholasd598f792016-07-25 10:08:54 -0700297 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700298 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700299 }
300 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000301 auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
302 varDecl.fName, *type, storage));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000303 if (var->fName == Compiler::RTADJUST_NAME) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400304 SkASSERT(!fRTAdjust);
305 SkASSERT(var->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000306 fRTAdjust = var.get();
307 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700308 std::unique_ptr<Expression> value;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700309 if (varDecl.fValue) {
310 value = this->convertExpression(*varDecl.fValue);
ethannicholasb3058bd2016-07-01 08:22:01 -0700311 if (!value) {
312 return nullptr;
313 }
ethannicholasd598f792016-07-25 10:08:54 -0700314 value = this->coerce(std::move(value), *type);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500315 if (!value) {
316 return nullptr;
317 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400318 var->fWriteCount = 1;
Ethan Nicholas8f6c2ab2018-01-17 13:51:52 -0500319 var->fInitialValue = value.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700320 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700321 if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" &&
ethannicholasea4567c2016-10-17 11:24:37 -0700322 (*fSymbolTable)[varDecl.fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700323 // already defined, ignore
ethannicholasea4567c2016-10-17 11:24:37 -0700324 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
325 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
ethannicholas5961bc92016-10-12 06:39:56 -0700326 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700327 // already defined, just update the modifiers
ethannicholas14fe8cc2016-09-07 13:37:16 -0700328 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
ethannicholasf789b382016-08-03 12:43:36 -0700329 old->fModifiers = var->fModifiers;
330 } else {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000331 variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
332 std::move(value)));
ethannicholas14fe8cc2016-09-07 13:37:16 -0700333 fSymbolTable->add(varDecl.fName, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700334 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700335 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700336 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset,
ethannicholas14fe8cc2016-09-07 13:37:16 -0700337 baseType,
338 std::move(variables)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700339}
340
ethannicholas5961bc92016-10-12 06:39:56 -0700341std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
342 const ASTModifiersDeclaration& m) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400343 Modifiers modifiers = m.fModifiers;
344 if (modifiers.fLayout.fInvocations != -1) {
345 fInvocations = modifiers.fLayout.fInvocations;
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600346 if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400347 modifiers.fLayout.fInvocations = -1;
348 Variable* invocationId = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400349 SkASSERT(invocationId);
Ethan Nicholasd1d52562018-03-20 16:30:34 -0400350 invocationId->fModifiers.fFlags = 0;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400351 invocationId->fModifiers.fLayout.fBuiltin = -1;
352 if (modifiers.fLayout.description() == "") {
353 return nullptr;
354 }
355 }
356 }
357 if (modifiers.fLayout.fMaxVertices != -1 && fInvocations > 0 && fSettings->fCaps &&
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600358 !fSettings->fCaps->gsInvocationsSupport()) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400359 modifiers.fLayout.fMaxVertices *= fInvocations;
360 }
361 return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
ethannicholas5961bc92016-10-12 06:39:56 -0700362}
363
ethannicholasb3058bd2016-07-01 08:22:01 -0700364std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
Ethan Nicholas11d53972016-11-28 11:23:23 -0500365 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700366 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700367 if (!test) {
368 return nullptr;
369 }
370 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
371 if (!ifTrue) {
372 return nullptr;
373 }
374 std::unique_ptr<Statement> ifFalse;
375 if (s.fIfFalse) {
376 ifFalse = this->convertStatement(*s.fIfFalse);
377 if (!ifFalse) {
378 return nullptr;
379 }
380 }
ethannicholas08a92112016-11-09 13:26:45 -0800381 if (test->fKind == Expression::kBoolLiteral_Kind) {
382 // static boolean value, fold down to a single branch
383 if (((BoolLiteral&) *test).fValue) {
384 return ifTrue;
385 } else if (s.fIfFalse) {
386 return ifFalse;
387 } else {
388 // False & no else clause. Not an error, so don't return null!
389 std::vector<std::unique_ptr<Statement>> empty;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700390 return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty),
ethannicholas08a92112016-11-09 13:26:45 -0800391 fSymbolTable));
392 }
393 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700394 return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700395 std::move(ifTrue), std::move(ifFalse)));
396}
397
398std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
ethannicholas22f939e2016-10-13 13:25:34 -0700399 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700400 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700401 std::unique_ptr<Statement> initializer;
402 if (f.fInitializer) {
403 initializer = this->convertStatement(*f.fInitializer);
404 if (!initializer) {
405 return nullptr;
406 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700407 }
ethannicholas22f939e2016-10-13 13:25:34 -0700408 std::unique_ptr<Expression> test;
409 if (f.fTest) {
410 test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
411 if (!test) {
412 return nullptr;
413 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700414 }
ethannicholas22f939e2016-10-13 13:25:34 -0700415 std::unique_ptr<Expression> next;
416 if (f.fNext) {
417 next = this->convertExpression(*f.fNext);
418 if (!next) {
419 return nullptr;
420 }
421 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700423 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
424 if (!statement) {
425 return nullptr;
426 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700427 return std::unique_ptr<Statement>(new ForStatement(f.fOffset, std::move(initializer),
ethannicholasb3058bd2016-07-01 08:22:01 -0700428 std::move(test), std::move(next),
ethannicholasd598f792016-07-25 10:08:54 -0700429 std::move(statement), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700430}
431
432std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
ethannicholas22f939e2016-10-13 13:25:34 -0700433 AutoLoopLevel level(this);
Ethan Nicholas11d53972016-11-28 11:23:23 -0500434 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700435 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700436 if (!test) {
437 return nullptr;
438 }
439 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
440 if (!statement) {
441 return nullptr;
442 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700443 return std::unique_ptr<Statement>(new WhileStatement(w.fOffset, std::move(test),
ethannicholasb3058bd2016-07-01 08:22:01 -0700444 std::move(statement)));
445}
446
447std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
ethannicholas22f939e2016-10-13 13:25:34 -0700448 AutoLoopLevel level(this);
ethannicholasd598f792016-07-25 10:08:54 -0700449 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
450 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700451 if (!test) {
452 return nullptr;
453 }
454 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
455 if (!statement) {
456 return nullptr;
457 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700458 return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
ethannicholasb3058bd2016-07-01 08:22:01 -0700459 std::move(test)));
460}
461
Ethan Nicholasaf197692017-02-27 13:26:45 -0500462std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
463 AutoSwitchLevel level(this);
464 std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
465 if (!value) {
466 return nullptr;
467 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500468 if (value->fType != *fContext.fUInt_Type && value->fType.kind() != Type::kEnum_Kind) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500469 value = this->coerce(std::move(value), *fContext.fInt_Type);
470 if (!value) {
471 return nullptr;
472 }
473 }
474 AutoSymbolTable table(this);
475 std::unordered_set<int> caseValues;
476 std::vector<std::unique_ptr<SwitchCase>> cases;
477 for (const auto& c : s.fCases) {
478 std::unique_ptr<Expression> caseValue;
479 if (c->fValue) {
480 caseValue = this->convertExpression(*c->fValue);
481 if (!caseValue) {
482 return nullptr;
483 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500484 caseValue = this->coerce(std::move(caseValue), value->fType);
485 if (!caseValue) {
486 return nullptr;
Ethan Nicholasaf197692017-02-27 13:26:45 -0500487 }
488 if (!caseValue->isConstant()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700489 fErrors.error(caseValue->fOffset, "case value must be a constant");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500490 return nullptr;
491 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500492 int64_t v;
493 this->getConstantInt(*caseValue, &v);
Ethan Nicholasaf197692017-02-27 13:26:45 -0500494 if (caseValues.find(v) != caseValues.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700495 fErrors.error(caseValue->fOffset, "duplicate case value");
Ethan Nicholasaf197692017-02-27 13:26:45 -0500496 }
497 caseValues.insert(v);
498 }
499 std::vector<std::unique_ptr<Statement>> statements;
500 for (const auto& s : c->fStatements) {
501 std::unique_ptr<Statement> converted = this->convertStatement(*s);
502 if (!converted) {
503 return nullptr;
504 }
505 statements.push_back(std::move(converted));
506 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700507 cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue),
Ethan Nicholasaf197692017-02-27 13:26:45 -0500508 std::move(statements)));
509 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700510 return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic,
Ethan Nicholasc432b0c2017-07-18 13:22:37 -0400511 std::move(value), std::move(cases),
512 fSymbolTable));
Ethan Nicholasaf197692017-02-27 13:26:45 -0500513}
514
ethannicholasb3058bd2016-07-01 08:22:01 -0700515std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
516 const ASTExpressionStatement& s) {
517 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
518 if (!e) {
519 return nullptr;
520 }
521 this->checkValid(*e);
522 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
523}
524
525std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400526 SkASSERT(fCurrentFunction);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000527 // early returns from a vertex main function will bypass the sk_Position normalization, so
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400528 // 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 +0000529 // normalization before each return, but it will probably never actually be necessary.
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400530 SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700531 if (r.fExpression) {
532 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
533 if (!result) {
534 return nullptr;
535 }
ethannicholasd598f792016-07-25 10:08:54 -0700536 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700537 fErrors.error(result->fOffset, "may not return a value from a void function");
ethannicholasb3058bd2016-07-01 08:22:01 -0700538 } else {
539 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
540 if (!result) {
541 return nullptr;
542 }
543 }
544 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
545 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700546 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700547 fErrors.error(r.fOffset, "expected function to return '" +
548 fCurrentFunction->fReturnType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700549 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700550 return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700551 }
552}
553
554std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
Ethan Nicholasaf197692017-02-27 13:26:45 -0500555 if (fLoopLevel > 0 || fSwitchLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700556 return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700557 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700558 fErrors.error(b.fOffset, "break statement must be inside a loop or switch");
ethannicholas22f939e2016-10-13 13:25:34 -0700559 return nullptr;
560 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700561}
562
563std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
ethannicholas22f939e2016-10-13 13:25:34 -0700564 if (fLoopLevel > 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700565 return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
ethannicholas22f939e2016-10-13 13:25:34 -0700566 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700567 fErrors.error(c.fOffset, "continue statement must be inside a loop");
ethannicholas22f939e2016-10-13 13:25:34 -0700568 return nullptr;
569 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700570}
571
572std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700573 return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
ethannicholasb3058bd2016-07-01 08:22:01 -0700574}
575
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500576std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<Block> main) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400577 Layout invokeLayout;
578 Modifiers invokeModifiers(invokeLayout, Modifiers::kHasSideEffects_Flag);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700579 FunctionDeclaration* invokeDecl = new FunctionDeclaration(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400580 invokeModifiers,
581 "_invoke",
582 std::vector<const Variable*>(),
583 *fContext.fVoid_Type);
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500584 fProgramElements->push_back(std::unique_ptr<ProgramElement>(
585 new FunctionDefinition(-1, *invokeDecl, std::move(main))));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400586 fSymbolTable->add(invokeDecl->fName, std::unique_ptr<FunctionDeclaration>(invokeDecl));
587
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000588 std::vector<std::unique_ptr<VarDeclaration>> variables;
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400589 Variable* loopIdx = (Variable*) (*fSymbolTable)["sk_InvocationID"];
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400590 SkASSERT(loopIdx);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700591 std::unique_ptr<Expression> test(new BinaryExpression(-1,
592 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400593 Token::LT,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700594 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, fInvocations)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400595 *fContext.fBool_Type));
596 std::unique_ptr<Expression> next(new PostfixExpression(
597 std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700598 new VariableReference(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400599 *loopIdx,
600 VariableReference::kReadWrite_RefKind)),
601 Token::PLUSPLUS));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700602 ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400603 std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400604 SkASSERT(endPrimitive);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400605
606 std::vector<std::unique_ptr<Statement>> loopBody;
607 std::vector<std::unique_ptr<Expression>> invokeArgs;
608 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700609 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400610 *invokeDecl,
611 std::vector<std::unique_ptr<Expression>>()))));
612 loopBody.push_back(std::unique_ptr<Statement>(new ExpressionStatement(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700613 this->call(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400614 std::move(endPrimitive),
615 std::vector<std::unique_ptr<Expression>>()))));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700616 std::unique_ptr<Expression> assignment(new BinaryExpression(-1,
617 std::unique_ptr<Expression>(new VariableReference(-1, *loopIdx)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400618 Token::EQ,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700619 std::unique_ptr<IntLiteral>(new IntLiteral(fContext, -1, 0)),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400620 *fContext.fInt_Type));
621 std::unique_ptr<Statement> initializer(new ExpressionStatement(std::move(assignment)));
622 std::unique_ptr<Statement> loop = std::unique_ptr<Statement>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700623 new ForStatement(-1,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400624 std::move(initializer),
625 std::move(test),
626 std::move(next),
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700627 std::unique_ptr<Block>(new Block(-1, std::move(loopBody))),
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400628 fSymbolTable));
629 std::vector<std::unique_ptr<Statement>> children;
630 children.push_back(std::move(loop));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700631 return std::unique_ptr<Block>(new Block(-1, std::move(children)));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400632}
633
Robert Phillipsfe8da172018-01-24 14:52:02 +0000634std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400635 // sk_Position = float4(sk_Position.xy * rtAdjust.xz + sk_Position.ww * rtAdjust.yw,
Robert Phillipsfe8da172018-01-24 14:52:02 +0000636 // 0,
637 // sk_Position.w);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400638 SkASSERT(fSkPerVertex && fRTAdjust);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000639 #define REF(var) std::unique_ptr<Expression>(\
640 new VariableReference(-1, *var, VariableReference::kRead_RefKind))
641 #define FIELD(var, idx) std::unique_ptr<Expression>(\
642 new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
643 #define POS std::unique_ptr<Expression>(new FieldAccess(REF(fSkPerVertex), 0, \
644 FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
645 #define ADJUST (fRTAdjustInterfaceBlock ? \
646 FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
647 REF(fRTAdjust))
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400648 #define SWIZZLE(expr, ...) std::unique_ptr<Expression>(new Swizzle(fContext, expr, \
649 { __VA_ARGS__ }))
650 #define OP(left, op, right) std::unique_ptr<Expression>( \
651 new BinaryExpression(-1, left, op, right, \
652 *fContext.fFloat2_Type))
Robert Phillipsfe8da172018-01-24 14:52:02 +0000653 std::vector<std::unique_ptr<Expression>> children;
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400654 children.push_back(OP(OP(SWIZZLE(POS, 0, 1), Token::STAR, SWIZZLE(ADJUST, 0, 2)),
Robert Phillipsfe8da172018-01-24 14:52:02 +0000655 Token::PLUS,
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400656 OP(SWIZZLE(POS, 3, 3), Token::STAR, SWIZZLE(ADJUST, 1, 3))));
Robert Phillipsfe8da172018-01-24 14:52:02 +0000657 children.push_back(std::unique_ptr<Expression>(new FloatLiteral(fContext, -1, 0.0)));
658 children.push_back(SWIZZLE(POS, 3));
659 std::unique_ptr<Expression> result = OP(POS, Token::EQ,
660 std::unique_ptr<Expression>(new Constructor(-1,
661 *fContext.fFloat4_Type,
662 std::move(children))));
663 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
664}
665
Ethan Nicholasb809efb2018-04-12 14:39:21 -0400666
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500667void IRGenerator::convertFunction(const ASTFunction& f) {
ethannicholasd598f792016-07-25 10:08:54 -0700668 const Type* returnType = this->convertType(*f.fReturnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700669 if (!returnType) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400670 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700671 }
ethannicholasd598f792016-07-25 10:08:54 -0700672 std::vector<const Variable*> parameters;
ethannicholasb3058bd2016-07-01 08:22:01 -0700673 for (const auto& param : f.fParameters) {
ethannicholasd598f792016-07-25 10:08:54 -0700674 const Type* type = this->convertType(*param->fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700675 if (!type) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400676 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700677 }
678 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
679 int size = param->fSizes[j];
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400680 String name = type->name() + "[" + to_string(size) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700681 Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
682 fSymbolTable->takeOwnership(newType);
683 type = newType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700684 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700685 StringFragment name = param->fName;
686 Variable* var = new Variable(param->fOffset, param->fModifiers, name, *type,
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000687 Variable::kParameter_Storage);
ethannicholasd598f792016-07-25 10:08:54 -0700688 fSymbolTable->takeOwnership(var);
689 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700690 }
691
Ethan Nicholas00543112018-07-31 09:44:36 -0400692 if (f.fName == "main") {
693 if (fKind == Program::kPipelineStage_Kind) {
694 bool valid = parameters.size() == 3 &&
695 parameters[0]->fType == *fContext.fInt_Type &&
696 parameters[0]->fModifiers.fFlags == 0 &&
697 parameters[1]->fType == *fContext.fInt_Type &&
698 parameters[1]->fModifiers.fFlags == 0 &&
699 parameters[2]->fType == *fContext.fHalf4_Type &&
700 parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
701 Modifiers::kOut_Flag);
702 if (!valid) {
703 fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
704 "int, inout half4)");
705 return;
706 }
707 } else if (parameters.size()) {
708 fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
709 }
710 }
711
ethannicholasb3058bd2016-07-01 08:22:01 -0700712 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700713 const FunctionDeclaration* decl = nullptr;
714 auto entry = (*fSymbolTable)[f.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700715 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700716 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700717 switch (entry->fKind) {
718 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700719 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700720 break;
721 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700722 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700723 break;
724 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700725 fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400726 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700727 }
728 for (const auto& other : functions) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400729 SkASSERT(other->fName == f.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -0700730 if (parameters.size() == other->fParameters.size()) {
731 bool match = true;
732 for (size_t i = 0; i < parameters.size(); i++) {
733 if (parameters[i]->fType != other->fParameters[i]->fType) {
734 match = false;
735 break;
736 }
737 }
738 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700739 if (*returnType != other->fReturnType) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700740 FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters,
Ethan Nicholascb670962017-04-20 19:31:52 -0400741 *returnType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700742 fErrors.error(f.fOffset, "functions '" + newDecl.description() +
743 "' and '" + other->description() +
744 "' differ only in return type");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400745 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700746 }
747 decl = other;
748 for (size_t i = 0; i < parameters.size(); i++) {
749 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700750 fErrors.error(f.fOffset, "modifiers on parameter " +
751 to_string((uint64_t) i + 1) +
752 " differ between declaration and "
753 "definition");
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400754 return;
ethannicholasb3058bd2016-07-01 08:22:01 -0700755 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700756 }
757 if (other->fDefined) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700758 fErrors.error(f.fOffset, "duplicate definition of " +
759 other->description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700760 }
761 break;
762 }
763 }
764 }
765 }
766 if (!decl) {
767 // couldn't find an existing declaration
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700768 auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
Ethan Nicholascb670962017-04-20 19:31:52 -0400769 f.fModifiers,
ethannicholas471e8942016-10-28 09:02:46 -0700770 f.fName,
771 parameters,
772 *returnType));
773 decl = newDecl.get();
774 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -0700775 }
ethannicholasd598f792016-07-25 10:08:54 -0700776 if (f.fBody) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400777 SkASSERT(!fCurrentFunction);
ethannicholasd598f792016-07-25 10:08:54 -0700778 fCurrentFunction = decl;
779 decl->fDefined = true;
780 std::shared_ptr<SymbolTable> old = fSymbolTable;
781 AutoSymbolTable table(this);
Ethan Nicholas00543112018-07-31 09:44:36 -0400782 if (f.fName == "main" && fKind == Program::kPipelineStage_Kind) {
783 parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_X_BUILTIN;
784 parameters[1]->fModifiers.fLayout.fBuiltin = SK_MAIN_Y_BUILTIN;
785 parameters[2]->fModifiers.fLayout.fBuiltin = SK_OUTCOLOR_BUILTIN;
786 }
ethannicholasd598f792016-07-25 10:08:54 -0700787 for (size_t i = 0; i < parameters.size(); i++) {
788 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -0700789 }
Chris Daltonf1b47bb2017-10-06 11:57:51 -0600790 bool needInvocationIDWorkaround = fInvocations != -1 && f.fName == "main" &&
791 fSettings->fCaps &&
792 !fSettings->fCaps->gsInvocationsSupport();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400793 SkASSERT(!fExtraVars.size());
ethannicholasd598f792016-07-25 10:08:54 -0700794 std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
Ethan Nicholas762466e2017-06-29 10:03:38 -0400795 for (auto& v : fExtraVars) {
796 body->fStatements.insert(body->fStatements.begin(), std::move(v));
797 }
798 fExtraVars.clear();
ethannicholasd598f792016-07-25 10:08:54 -0700799 fCurrentFunction = nullptr;
800 if (!body) {
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -0400801 return;
802 }
803 if (needInvocationIDWorkaround) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500804 body = this->applyInvocationIDWorkaround(std::move(body));
ethannicholasd598f792016-07-25 10:08:54 -0700805 }
Ethan Nicholascb670962017-04-20 19:31:52 -0400806 // conservatively assume all user-defined functions have side effects
807 ((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000808 if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) {
809 body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
810 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500811 fProgramElements->push_back(std::unique_ptr<FunctionDefinition>(
812 new FunctionDefinition(f.fOffset, *decl, std::move(body))));
ethannicholasb3058bd2016-07-01 08:22:01 -0700813 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700814}
815
816std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
817 std::shared_ptr<SymbolTable> old = fSymbolTable;
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500818 this->pushSymbolTable();
819 std::shared_ptr<SymbolTable> symbols = fSymbolTable;
ethannicholasb3058bd2016-07-01 08:22:01 -0700820 std::vector<Type::Field> fields;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400821 bool haveRuntimeArray = false;
Robert Phillipsfe8da172018-01-24 14:52:02 +0000822 bool foundRTAdjust = false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700823 for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700824 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
Ethan Nicholas11d53972016-11-28 11:23:23 -0500825 *intf.fDeclarations[i],
ethannicholasb3058bd2016-07-01 08:22:01 -0700826 Variable::kGlobal_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -0700827 if (!decl) {
828 return nullptr;
829 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000830 for (const auto& stmt : decl->fVars) {
831 VarDeclaration& vd = (VarDeclaration&) *stmt;
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400832 if (haveRuntimeArray) {
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000833 fErrors.error(decl->fOffset,
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400834 "only the last entry in an interface block may be a runtime-sized "
835 "array");
836 }
Robert Phillipsfe8da172018-01-24 14:52:02 +0000837 if (vd.fVar == fRTAdjust) {
838 foundRTAdjust = true;
Ethan Nicholasd9d33c32018-06-12 11:05:59 -0400839 SkASSERT(vd.fVar->fType == *fContext.fFloat4_Type);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000840 fRTAdjustFieldIndex = fields.size();
841 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000842 fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->fName,
843 &vd.fVar->fType));
844 if (vd.fValue) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700845 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700846 "initializers are not permitted on interface block fields");
847 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000848 if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
849 Modifiers::kOut_Flag |
850 Modifiers::kUniform_Flag |
851 Modifiers::kBuffer_Flag |
852 Modifiers::kConst_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700853 fErrors.error(decl->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700854 "interface block fields may not have storage qualifiers");
855 }
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000856 if (vd.fVar->fType.kind() == Type::kArray_Kind &&
857 vd.fVar->fType.columns() == -1) {
Ethan Nicholas0dd30d92017-05-01 16:57:07 -0400858 haveRuntimeArray = true;
859 }
Ethan Nicholas11d53972016-11-28 11:23:23 -0500860 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700861 }
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500862 this->popSymbolTable();
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700863 Type* type = new Type(intf.fOffset, intf.fTypeName, fields);
Ethan Nicholas86a43402017-01-19 13:32:00 -0500864 old->takeOwnership(type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500865 std::vector<std::unique_ptr<Expression>> sizes;
866 for (const auto& size : intf.fSizes) {
867 if (size) {
868 std::unique_ptr<Expression> converted = this->convertExpression(*size);
869 if (!converted) {
870 return nullptr;
871 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -0400872 String name = type->fName;
Ethan Nicholas50afc172017-02-16 14:49:57 -0500873 int64_t count;
874 if (converted->fKind == Expression::kIntLiteral_Kind) {
875 count = ((IntLiteral&) *converted).fValue;
876 if (count <= 0) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700877 fErrors.error(converted->fOffset, "array size must be positive");
Ethan Nicholas50afc172017-02-16 14:49:57 -0500878 }
879 name += "[" + to_string(count) + "]";
880 } else {
881 count = -1;
882 name += "[]";
883 }
884 type = new Type(name, Type::kArray_Kind, *type, (int) count);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500885 symbols->takeOwnership((Type*) type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500886 sizes.push_back(std::move(converted));
887 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700888 type = new Type(type->name() + "[]", Type::kArray_Kind, *type, -1);
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500889 symbols->takeOwnership((Type*) type);
Ethan Nicholas50afc172017-02-16 14:49:57 -0500890 sizes.push_back(nullptr);
891 }
892 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700893 Variable* var = new Variable(intf.fOffset, intf.fModifiers,
894 intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
Ethan Nicholas82a62d22017-11-07 14:42:10 +0000895 *type, Variable::kGlobal_Storage);
Robert Phillipsfe8da172018-01-24 14:52:02 +0000896 if (foundRTAdjust) {
897 fRTAdjustInterfaceBlock = var;
898 }
Ethan Nicholas86a43402017-01-19 13:32:00 -0500899 old->takeOwnership(var);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700900 if (intf.fInstanceName.fLength) {
Ethan Nicholas50afc172017-02-16 14:49:57 -0500901 old->addWithoutOwnership(intf.fInstanceName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700902 } else {
903 for (size_t i = 0; i < fields.size(); i++) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700904 old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
ethannicholasd598f792016-07-25 10:08:54 -0700905 (int) i)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700906 }
907 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700908 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
Ethan Nicholas8feeff92017-03-30 14:11:58 -0400909 var,
Ethan Nicholas50afc172017-02-16 14:49:57 -0500910 intf.fTypeName,
911 intf.fInstanceName,
912 std::move(sizes),
Ethan Nicholas68dd2c12018-03-01 15:05:17 -0500913 symbols));
ethannicholasb3058bd2016-07-01 08:22:01 -0700914}
915
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500916void IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
917 switch (value.fKind) {
918 case Expression::kIntLiteral_Kind:
919 *out = ((const IntLiteral&) value).fValue;
920 break;
921 case Expression::kVariableReference_Kind: {
922 const Variable& var = ((VariableReference&) value).fVariable;
923 if ((var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
924 var.fInitialValue) {
925 this->getConstantInt(*var.fInitialValue, out);
926 }
927 break;
928 }
929 default:
930 fErrors.error(value.fOffset, "expected a constant int");
931 }
932}
933
934void IRGenerator::convertEnum(const ASTEnum& e) {
935 std::vector<Variable*> variables;
936 int64_t currentValue = 0;
937 Layout layout;
938 ASTType enumType(e.fOffset, e.fTypeName, ASTType::kIdentifier_Kind, {});
939 const Type* type = this->convertType(enumType);
940 Modifiers modifiers(layout, Modifiers::kConst_Flag);
Ethan Nicholaseace9352018-10-15 20:09:54 +0000941 std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable, &fErrors));
942 fSymbolTable = symbols;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500943 for (size_t i = 0; i < e.fNames.size(); i++) {
944 std::unique_ptr<Expression> value;
945 if (e.fValues[i]) {
946 value = this->convertExpression(*e.fValues[i]);
947 if (!value) {
Ethan Nicholaseace9352018-10-15 20:09:54 +0000948 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500949 return;
950 }
951 this->getConstantInt(*value, &currentValue);
952 }
953 value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
954 ++currentValue;
955 auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, e.fNames[i],
956 *type, Variable::kGlobal_Storage,
957 value.get()));
958 variables.push_back(var.get());
959 symbols->add(e.fNames[i], std::move(var));
960 symbols->takeOwnership(value.release());
961 }
962 fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.fTypeName,
963 symbols)));
Ethan Nicholaseace9352018-10-15 20:09:54 +0000964 fSymbolTable = symbols->fParent;
Ethan Nicholasaae47c82017-11-10 15:34:03 -0500965}
966
ethannicholasd598f792016-07-25 10:08:54 -0700967const Type* IRGenerator::convertType(const ASTType& type) {
968 const Symbol* result = (*fSymbolTable)[type.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700969 if (result && result->fKind == Symbol::kType_Kind) {
Ethan Nicholas50afc172017-02-16 14:49:57 -0500970 for (int size : type.fSizes) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700971 String name(result->fName);
972 name += "[";
Ethan Nicholas50afc172017-02-16 14:49:57 -0500973 if (size != -1) {
974 name += to_string(size);
975 }
976 name += "]";
977 result = new Type(name, Type::kArray_Kind, (const Type&) *result, size);
978 fSymbolTable->takeOwnership((Type*) result);
979 }
ethannicholasd598f792016-07-25 10:08:54 -0700980 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700981 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700982 fErrors.error(type.fOffset, "unknown type '" + type.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700983 return nullptr;
984}
985
986std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
987 switch (expr.fKind) {
988 case ASTExpression::kIdentifier_Kind:
989 return this->convertIdentifier((ASTIdentifier&) expr);
990 case ASTExpression::kBool_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700991 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700992 ((ASTBoolLiteral&) expr).fValue));
993 case ASTExpression::kInt_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700994 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700995 ((ASTIntLiteral&) expr).fValue));
996 case ASTExpression::kFloat_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -0700997 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -0700998 ((ASTFloatLiteral&) expr).fValue));
999 case ASTExpression::kBinary_Kind:
1000 return this->convertBinaryExpression((ASTBinaryExpression&) expr);
1001 case ASTExpression::kPrefix_Kind:
1002 return this->convertPrefixExpression((ASTPrefixExpression&) expr);
1003 case ASTExpression::kSuffix_Kind:
1004 return this->convertSuffixExpression((ASTSuffixExpression&) expr);
1005 case ASTExpression::kTernary_Kind:
1006 return this->convertTernaryExpression((ASTTernaryExpression&) expr);
1007 default:
1008 ABORT("unsupported expression type: %d\n", expr.fKind);
1009 }
1010}
1011
1012std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
ethannicholasd598f792016-07-25 10:08:54 -07001013 const Symbol* result = (*fSymbolTable)[identifier.fText];
ethannicholasb3058bd2016-07-01 08:22:01 -07001014 if (!result) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001015 fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001016 return nullptr;
1017 }
1018 switch (result->fKind) {
1019 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001020 std::vector<const FunctionDeclaration*> f = {
1021 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -07001022 };
ethannicholasd598f792016-07-25 10:08:54 -07001023 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001024 identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001025 f));
ethannicholasb3058bd2016-07-01 08:22:01 -07001026 }
1027 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001028 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
1029 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001030 identifier.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001031 f->fFunctions));
1032 }
1033 case Symbol::kVariable_Kind: {
Ethan Nicholas38657112017-02-09 17:01:22 -05001034 const Variable* var = (const Variable*) result;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001035 switch (var->fModifiers.fLayout.fBuiltin) {
1036 case SK_WIDTH_BUILTIN:
1037 fInputs.fRTWidth = true;
1038 break;
1039 case SK_HEIGHT_BUILTIN:
Greg Daniele6ab9982018-08-22 13:56:32 +00001040 fInputs.fRTHeight = true;
Ethan Nicholascd700e92018-08-24 16:43:57 -04001041 break;
1042#ifndef SKSL_STANDALONE
1043 case SK_FRAGCOORD_BUILTIN:
1044 if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
1045 fInputs.fFlipY = true;
1046 if (fSettings->fFlipY &&
1047 (!fSettings->fCaps ||
1048 !fSettings->fCaps->fragCoordConventionsExtensionString())) {
1049 fInputs.fRTHeight = true;
1050 }
1051 }
Greg Daniele6ab9982018-08-22 13:56:32 +00001052#endif
Ethan Nicholascd700e92018-08-24 16:43:57 -04001053 }
Ethan Nicholas86a43402017-01-19 13:32:00 -05001054 // default to kRead_RefKind; this will be corrected later if the variable is written to
1055 return std::unique_ptr<VariableReference>(new VariableReference(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001056 identifier.fOffset,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001057 *var,
1058 VariableReference::kRead_RefKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001059 }
1060 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001061 const Field* field = (const Field*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001062 VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001063 VariableReference::kRead_RefKind);
ethannicholasf789b382016-08-03 12:43:36 -07001064 return std::unique_ptr<Expression>(new FieldAccess(
1065 std::unique_ptr<Expression>(base),
1066 field->fFieldIndex,
1067 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -07001068 }
1069 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001070 const Type* t = (const Type*) result;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001071 return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001072 *t));
ethannicholasb3058bd2016-07-01 08:22:01 -07001073 }
1074 default:
1075 ABORT("unsupported symbol type %d\n", result->fKind);
1076 }
Ethan Nicholasc0709392017-06-27 11:20:22 -04001077}
1078
Ethan Nicholas762466e2017-06-29 10:03:38 -04001079std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001080 return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001081}
1082
1083
Ethan Nicholas11d53972016-11-28 11:23:23 -05001084std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -07001085 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001086 if (!expr) {
1087 return nullptr;
1088 }
ethannicholasd598f792016-07-25 10:08:54 -07001089 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001090 return expr;
1091 }
1092 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -07001093 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001094 return nullptr;
1095 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001096 if (expr->coercionCost(type) == INT_MAX) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001097 fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
ethannicholasd598f792016-07-25 10:08:54 -07001098 expr->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001099 return nullptr;
1100 }
ethannicholasd598f792016-07-25 10:08:54 -07001101 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001102 std::vector<std::unique_ptr<Expression>> args;
1103 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001104 ASTIdentifier id(-1, type.fName);
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001106 SkASSERT(ctor);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001107 return this->call(-1, std::move(ctor), std::move(args));
ethannicholasb3058bd2016-07-01 08:22:01 -07001108 }
ethannicholas5961bc92016-10-12 06:39:56 -07001109 std::vector<std::unique_ptr<Expression>> args;
1110 args.push_back(std::move(expr));
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001111 return std::unique_ptr<Expression>(new Constructor(-1, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001112}
1113
ethannicholasf789b382016-08-03 12:43:36 -07001114static bool is_matrix_multiply(const Type& left, const Type& right) {
1115 if (left.kind() == Type::kMatrix_Kind) {
1116 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
1117 }
1118 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
1119}
ethannicholasea4567c2016-10-17 11:24:37 -07001120
ethannicholasb3058bd2016-07-01 08:22:01 -07001121/**
1122 * Determines the operand and result types of a binary expression. Returns true if the expression is
1123 * legal, false otherwise. If false, the values of the out parameters are undefined.
1124 */
Ethan Nicholas11d53972016-11-28 11:23:23 -05001125static bool determine_binary_type(const Context& context,
1126 Token::Kind op,
1127 const Type& left,
1128 const Type& right,
ethannicholasd598f792016-07-25 10:08:54 -07001129 const Type** outLeftType,
1130 const Type** outRightType,
1131 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -07001132 bool tryFlipped) {
1133 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -07001134 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -07001135 switch (op) {
ethannicholasea4567c2016-10-17 11:24:37 -07001136 case Token::EQ:
1137 *outLeftType = &left;
1138 *outRightType = &left;
1139 *outResultType = &left;
1140 return right.canCoerceTo(left);
ethannicholasb3058bd2016-07-01 08:22:01 -07001141 case Token::EQEQ: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001142 case Token::NEQ:
Ethan Nicholas23463002018-03-28 15:16:15 -04001143 if (right.canCoerceTo(left)) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001144 *outLeftType = &left;
Ethan Nicholas23463002018-03-28 15:16:15 -04001145 *outRightType = &left;
1146 *outResultType = context.fBool_Type.get();
1147 return true;
1148 } if (left.canCoerceTo(right)) {
1149 *outLeftType = &right;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05001150 *outRightType = &right;
1151 *outResultType = context.fBool_Type.get();
1152 return true;
1153 }
Ethan Nicholas23463002018-03-28 15:16:15 -04001154 return false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001155 case Token::LT: // fall through
1156 case Token::GT: // fall through
1157 case Token::LTEQ: // fall through
1158 case Token::GTEQ:
1159 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -07001160 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001161 break;
1162 case Token::LOGICALOR: // fall through
1163 case Token::LOGICALAND: // fall through
1164 case Token::LOGICALXOR: // fall through
1165 case Token::LOGICALOREQ: // fall through
1166 case Token::LOGICALANDEQ: // fall through
1167 case Token::LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -07001168 *outLeftType = context.fBool_Type.get();
1169 *outRightType = context.fBool_Type.get();
1170 *outResultType = context.fBool_Type.get();
Ethan Nicholas11d53972016-11-28 11:23:23 -05001171 return left.canCoerceTo(*context.fBool_Type) &&
ethannicholasd598f792016-07-25 10:08:54 -07001172 right.canCoerceTo(*context.fBool_Type);
Ethan Nicholas11d53972016-11-28 11:23:23 -05001173 case Token::STAREQ:
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001174 if (left.kind() == Type::kScalar_Kind) {
1175 *outLeftType = &left;
1176 *outRightType = &left;
1177 *outResultType = &left;
1178 return right.canCoerceTo(left);
1179 }
1180 // fall through
1181 case Token::STAR:
ethannicholasf789b382016-08-03 12:43:36 -07001182 if (is_matrix_multiply(left, right)) {
1183 // determine final component type
1184 if (determine_binary_type(context, Token::STAR, left.componentType(),
1185 right.componentType(), outLeftType, outRightType,
1186 outResultType, false)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001187 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001188 left.rows());
Ethan Nicholas11d53972016-11-28 11:23:23 -05001189 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
Brian Salomon23356442018-11-30 15:33:19 -05001190 right.rows());
ethannicholasf789b382016-08-03 12:43:36 -07001191 int leftColumns = left.columns();
1192 int leftRows = left.rows();
1193 int rightColumns;
1194 int rightRows;
1195 if (right.kind() == Type::kVector_Kind) {
1196 // matrix * vector treats the vector as a column vector, so we need to
1197 // transpose it
1198 rightColumns = right.rows();
1199 rightRows = right.columns();
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001200 SkASSERT(rightColumns == 1);
ethannicholasf789b382016-08-03 12:43:36 -07001201 } else {
1202 rightColumns = right.columns();
1203 rightRows = right.rows();
1204 }
1205 if (rightColumns > 1) {
1206 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
1207 leftRows);
1208 } else {
1209 // result was a column vector, transpose it back to a row
1210 *outResultType = &(*outResultType)->toCompound(context, leftRows,
1211 rightColumns);
1212 }
1213 return leftColumns == rightRows;
1214 } else {
1215 return false;
1216 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001217 }
ethannicholasea4567c2016-10-17 11:24:37 -07001218 isLogical = false;
1219 validMatrixOrVectorOp = true;
1220 break;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001221 case Token::PLUSEQ:
1222 case Token::MINUSEQ:
1223 case Token::SLASHEQ:
1224 case Token::PERCENTEQ:
1225 case Token::SHLEQ:
1226 case Token::SHREQ:
1227 if (left.kind() == Type::kScalar_Kind) {
1228 *outLeftType = &left;
1229 *outRightType = &left;
1230 *outResultType = &left;
1231 return right.canCoerceTo(left);
1232 }
1233 // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001234 case Token::PLUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001235 case Token::MINUS: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001236 case Token::SLASH: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -07001237 isLogical = false;
1238 validMatrixOrVectorOp = true;
1239 break;
Ethan Nicholas4b330df2017-05-17 10:52:55 -04001240 case Token::COMMA:
1241 *outLeftType = &left;
1242 *outRightType = &right;
1243 *outResultType = &right;
1244 return true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001245 default:
1246 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -07001247 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -07001248 }
ethannicholasea4567c2016-10-17 11:24:37 -07001249 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001250 if (left.kind() == Type::kScalar_Kind && right.kind() == Type::kScalar_Kind &&
1251 right.canCoerceTo(left)) {
1252 if (left.priority() > right.priority()) {
1253 *outLeftType = &left;
1254 *outRightType = &left;
1255 } else {
1256 *outLeftType = &right;
1257 *outRightType = &right;
1258 }
1259 if (isLogical) {
1260 *outResultType = context.fBool_Type.get();
1261 } else {
1262 *outResultType = &left;
1263 }
1264 return true;
1265 }
1266 if (right.canCoerceTo(left) && isVectorOrMatrix && validMatrixOrVectorOp) {
ethannicholasd598f792016-07-25 10:08:54 -07001267 *outLeftType = &left;
1268 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001269 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -07001270 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -07001271 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001272 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -07001273 }
1274 return true;
1275 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001276 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
ethannicholasd598f792016-07-25 10:08:54 -07001277 (right.kind() == Type::kScalar_Kind)) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001278 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001279 outRightType, outResultType, false)) {
1280 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001281 if (!isLogical) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001282 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
ethannicholasd598f792016-07-25 10:08:54 -07001283 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -07001284 }
1285 return true;
1286 }
1287 return false;
1288 }
1289 if (tryFlipped) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001290 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
ethannicholasd598f792016-07-25 10:08:54 -07001291 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -07001292 }
1293 return false;
1294}
1295
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001296static std::unique_ptr<Expression> short_circuit_boolean(const Context& context,
1297 const Expression& left,
1298 Token::Kind op,
1299 const Expression& right) {
1300 SkASSERT(left.fKind == Expression::kBoolLiteral_Kind);
1301 bool leftVal = ((BoolLiteral&) left).fValue;
1302 if (op == Token::LOGICALAND) {
1303 // (true && expr) -> (expr) and (false && expr) -> (false)
1304 return leftVal ? right.clone()
1305 : std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, false));
1306 } else if (op == Token::LOGICALOR) {
1307 // (true || expr) -> (true) and (false || expr) -> (expr)
1308 return leftVal ? std::unique_ptr<Expression>(new BoolLiteral(context, left.fOffset, true))
1309 : right.clone();
1310 } else {
1311 // Can't short circuit XOR
1312 return nullptr;
1313 }
1314}
1315
ethannicholas08a92112016-11-09 13:26:45 -08001316std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
1317 Token::Kind op,
Ethan Nicholas86a43402017-01-19 13:32:00 -05001318 const Expression& right) const {
Michael Ludwig7b429ae2018-09-06 17:01:38 -04001319 // If the left side is a constant boolean literal, the right side does not need to be constant
1320 // for short circuit optimizations to allow the constant to be folded.
1321 if (left.fKind == Expression::kBoolLiteral_Kind && !right.isConstant()) {
1322 return short_circuit_boolean(fContext, left, op, right);
1323 } else if (right.fKind == Expression::kBoolLiteral_Kind && !left.isConstant()) {
1324 // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
1325 // (right OP left) for short-circuit optimizations
1326 return short_circuit_boolean(fContext, right, op, left);
1327 }
1328
1329 // Other than the short-circuit cases above, constant folding requires both sides to be constant
Ethan Nicholascb670962017-04-20 19:31:52 -04001330 if (!left.isConstant() || !right.isConstant()) {
1331 return nullptr;
1332 }
ethannicholas08a92112016-11-09 13:26:45 -08001333 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
1334 // precision to calculate the results and hope the result makes sense. The plan is to move the
1335 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
1336 // types, which will let us be more intelligent about this.
Ethan Nicholas11d53972016-11-28 11:23:23 -05001337 if (left.fKind == Expression::kBoolLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001338 right.fKind == Expression::kBoolLiteral_Kind) {
1339 bool leftVal = ((BoolLiteral&) left).fValue;
1340 bool rightVal = ((BoolLiteral&) right).fValue;
1341 bool result;
1342 switch (op) {
1343 case Token::LOGICALAND: result = leftVal && rightVal; break;
1344 case Token::LOGICALOR: result = leftVal || rightVal; break;
1345 case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
1346 default: return nullptr;
1347 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001348 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
ethannicholas08a92112016-11-09 13:26:45 -08001349 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001350 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fOffset, \
ethannicholas08a92112016-11-09 13:26:45 -08001351 leftVal op rightVal))
1352 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
1353 int64_t leftVal = ((IntLiteral&) left).fValue;
1354 int64_t rightVal = ((IntLiteral&) right).fValue;
1355 switch (op) {
Ethan Nicholascb670962017-04-20 19:31:52 -04001356 case Token::PLUS: return RESULT(Int, +);
1357 case Token::MINUS: return RESULT(Int, -);
1358 case Token::STAR: return RESULT(Int, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001359 case Token::SLASH:
1360 if (rightVal) {
1361 return RESULT(Int, /);
1362 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001363 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001364 return nullptr;
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001365 case Token::PERCENT:
1366 if (rightVal) {
1367 return RESULT(Int, %);
1368 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001369 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas2503ab62017-01-05 10:44:25 -05001370 return nullptr;
ethannicholas08a92112016-11-09 13:26:45 -08001371 case Token::BITWISEAND: return RESULT(Int, &);
1372 case Token::BITWISEOR: return RESULT(Int, |);
1373 case Token::BITWISEXOR: return RESULT(Int, ^);
1374 case Token::SHL: return RESULT(Int, <<);
1375 case Token::SHR: return RESULT(Int, >>);
1376 case Token::EQEQ: return RESULT(Bool, ==);
1377 case Token::NEQ: return RESULT(Bool, !=);
1378 case Token::GT: return RESULT(Bool, >);
1379 case Token::GTEQ: return RESULT(Bool, >=);
1380 case Token::LT: return RESULT(Bool, <);
1381 case Token::LTEQ: return RESULT(Bool, <=);
1382 default: return nullptr;
1383 }
1384 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001385 if (left.fKind == Expression::kFloatLiteral_Kind &&
ethannicholas08a92112016-11-09 13:26:45 -08001386 right.fKind == Expression::kFloatLiteral_Kind) {
1387 double leftVal = ((FloatLiteral&) left).fValue;
1388 double rightVal = ((FloatLiteral&) right).fValue;
1389 switch (op) {
1390 case Token::PLUS: return RESULT(Float, +);
1391 case Token::MINUS: return RESULT(Float, -);
1392 case Token::STAR: return RESULT(Float, *);
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001393 case Token::SLASH:
1394 if (rightVal) {
1395 return RESULT(Float, /);
1396 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001397 fErrors.error(right.fOffset, "division by zero");
Ethan Nicholas9a5610e2017-01-03 15:16:29 -05001398 return nullptr;
Ethan Nicholascb670962017-04-20 19:31:52 -04001399 case Token::EQEQ: return RESULT(Bool, ==);
1400 case Token::NEQ: return RESULT(Bool, !=);
1401 case Token::GT: return RESULT(Bool, >);
1402 case Token::GTEQ: return RESULT(Bool, >=);
1403 case Token::LT: return RESULT(Bool, <);
1404 case Token::LTEQ: return RESULT(Bool, <=);
ethannicholas08a92112016-11-09 13:26:45 -08001405 default: return nullptr;
1406 }
1407 }
Ethan Nicholascb670962017-04-20 19:31:52 -04001408 if (left.fType.kind() == Type::kVector_Kind &&
1409 left.fType.componentType() == *fContext.fFloat_Type &&
1410 left.fType == right.fType) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001411 SkASSERT(left.fKind == Expression::kConstructor_Kind);
1412 SkASSERT(right.fKind == Expression::kConstructor_Kind);
Ethan Nicholascb670962017-04-20 19:31:52 -04001413 std::vector<std::unique_ptr<Expression>> args;
1414 #define RETURN_VEC_COMPONENTWISE_RESULT(op) \
1415 for (int i = 0; i < left.fType.columns(); i++) { \
1416 float value = ((Constructor&) left).getFVecComponent(i) op \
1417 ((Constructor&) right).getFVecComponent(i); \
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001418 args.emplace_back(new FloatLiteral(fContext, -1, value)); \
Ethan Nicholascb670962017-04-20 19:31:52 -04001419 } \
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001420 return std::unique_ptr<Expression>(new Constructor(-1, left.fType, \
Brian Salomon23356442018-11-30 15:33:19 -05001421 std::move(args)))
Ethan Nicholascb670962017-04-20 19:31:52 -04001422 switch (op) {
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001423 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001424 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001425 left.compareConstant(fContext, right)));
1426 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001427 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001428 !left.compareConstant(fContext, right)));
Ethan Nicholascb670962017-04-20 19:31:52 -04001429 case Token::PLUS: RETURN_VEC_COMPONENTWISE_RESULT(+);
1430 case Token::MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
1431 case Token::STAR: RETURN_VEC_COMPONENTWISE_RESULT(*);
1432 case Token::SLASH: RETURN_VEC_COMPONENTWISE_RESULT(/);
1433 default: return nullptr;
1434 }
1435 }
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001436 if (left.fType.kind() == Type::kMatrix_Kind &&
1437 right.fType.kind() == Type::kMatrix_Kind &&
1438 left.fKind == right.fKind) {
1439 switch (op) {
1440 case Token::EQEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001441 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001442 left.compareConstant(fContext, right)));
1443 case Token::NEQ:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001444 return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
Ethan Nicholas3deaeb22017-04-25 14:42:11 -04001445 !left.compareConstant(fContext, right)));
1446 default:
1447 return nullptr;
1448 }
1449 }
ethannicholas08a92112016-11-09 13:26:45 -08001450 #undef RESULT
1451 return nullptr;
1452}
1453
ethannicholasb3058bd2016-07-01 08:22:01 -07001454std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
1455 const ASTBinaryExpression& expression) {
1456 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
1457 if (!left) {
1458 return nullptr;
1459 }
1460 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
1461 if (!right) {
1462 return nullptr;
1463 }
ethannicholasd598f792016-07-25 10:08:54 -07001464 const Type* leftType;
1465 const Type* rightType;
1466 const Type* resultType;
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001467 const Type* rawLeftType;
1468 if (left->fKind == Expression::kIntLiteral_Kind && right->fType.isInteger()) {
1469 rawLeftType = &right->fType;
1470 } else {
1471 rawLeftType = &left->fType;
1472 }
1473 const Type* rawRightType;
1474 if (right->fKind == Expression::kIntLiteral_Kind && left->fType.isInteger()) {
1475 rawRightType = &left->fType;
1476 } else {
1477 rawRightType = &right->fType;
1478 }
1479 if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
1480 &leftType, &rightType, &resultType,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001481 !Compiler::IsAssignment(expression.fOperator))) {
1482 fErrors.error(expression.fOffset, String("type mismatch: '") +
1483 Compiler::OperatorName(expression.fOperator) +
1484 "' cannot operate on '" + left->fType.fName +
1485 "', '" + right->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001486 return nullptr;
1487 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001488 if (Compiler::IsAssignment(expression.fOperator)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001489 this->setRefKind(*left, expression.fOperator != Token::EQ ?
1490 VariableReference::kReadWrite_RefKind :
1491 VariableReference::kWrite_RefKind);
ethannicholasea4567c2016-10-17 11:24:37 -07001492 }
1493 left = this->coerce(std::move(left), *leftType);
1494 right = this->coerce(std::move(right), *rightType);
1495 if (!left || !right) {
1496 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001497 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001498 std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
ethannicholas08a92112016-11-09 13:26:45 -08001499 *right.get());
1500 if (!result) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001501 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08001502 std::move(left),
1503 expression.fOperator,
1504 std::move(right),
1505 *resultType));
1506 }
1507 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -07001508}
1509
Ethan Nicholas11d53972016-11-28 11:23:23 -05001510std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
ethannicholasb3058bd2016-07-01 08:22:01 -07001511 const ASTTernaryExpression& expression) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05001512 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
ethannicholasd598f792016-07-25 10:08:54 -07001513 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001514 if (!test) {
1515 return nullptr;
1516 }
1517 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
1518 if (!ifTrue) {
1519 return nullptr;
1520 }
1521 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
1522 if (!ifFalse) {
1523 return nullptr;
1524 }
ethannicholasd598f792016-07-25 10:08:54 -07001525 const Type* trueType;
1526 const Type* falseType;
1527 const Type* resultType;
1528 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001529 &falseType, &resultType, true) || trueType != falseType) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001530 fErrors.error(expression.fOffset, "ternary operator result mismatch: '" +
1531 ifTrue->fType.fName + "', '" +
1532 ifFalse->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001533 return nullptr;
1534 }
ethannicholasd598f792016-07-25 10:08:54 -07001535 ifTrue = this->coerce(std::move(ifTrue), *trueType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001536 if (!ifTrue) {
1537 return nullptr;
1538 }
ethannicholasd598f792016-07-25 10:08:54 -07001539 ifFalse = this->coerce(std::move(ifFalse), *falseType);
Ethan Nicholas2be687a2017-01-03 16:44:39 -05001540 if (!ifFalse) {
1541 return nullptr;
1542 }
ethannicholas08a92112016-11-09 13:26:45 -08001543 if (test->fKind == Expression::kBoolLiteral_Kind) {
1544 // static boolean test, just return one of the branches
1545 if (((BoolLiteral&) *test).fValue) {
1546 return ifTrue;
1547 } else {
1548 return ifFalse;
1549 }
1550 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001551 return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001552 std::move(test),
Ethan Nicholas11d53972016-11-28 11:23:23 -05001553 std::move(ifTrue),
ethannicholasb3058bd2016-07-01 08:22:01 -07001554 std::move(ifFalse)));
1555}
1556
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001557std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001558 const FunctionDeclaration& function,
ethannicholasd598f792016-07-25 10:08:54 -07001559 std::vector<std::unique_ptr<Expression>> arguments) {
1560 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001561 String msg = "call to '" + function.fName + "' expected " +
Ethan Nicholas11d53972016-11-28 11:23:23 -05001562 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -07001563 " argument";
ethannicholasd598f792016-07-25 10:08:54 -07001564 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001565 msg += "s";
1566 }
ethannicholas5961bc92016-10-12 06:39:56 -07001567 msg += ", but found " + to_string((uint64_t) arguments.size());
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001568 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001569 return nullptr;
1570 }
ethannicholas471e8942016-10-28 09:02:46 -07001571 std::vector<const Type*> types;
1572 const Type* returnType;
1573 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001574 String msg = "no match for " + function.fName + "(";
1575 String separator;
ethannicholas471e8942016-10-28 09:02:46 -07001576 for (size_t i = 0; i < arguments.size(); i++) {
1577 msg += separator;
1578 separator = ", ";
1579 msg += arguments[i]->fType.description();
1580 }
1581 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001582 fErrors.error(offset, msg);
ethannicholas471e8942016-10-28 09:02:46 -07001583 return nullptr;
1584 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001585 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -07001586 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -07001587 if (!arguments[i]) {
1588 return nullptr;
1589 }
ethannicholasd598f792016-07-25 10:08:54 -07001590 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001591 this->setRefKind(*arguments[i],
1592 function.fParameters[i]->fModifiers.fFlags & Modifiers::kIn_Flag ?
1593 VariableReference::kReadWrite_RefKind :
1594 VariableReference::kPointer_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001595 }
1596 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001597 return std::unique_ptr<FunctionCall>(new FunctionCall(offset, *returnType, function,
ethannicholasb3058bd2016-07-01 08:22:01 -07001598 std::move(arguments)));
1599}
1600
1601/**
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001602 * Determines the cost of coercing the arguments of a function to the required types. Cost has no
1603 * particular meaning other than "lower costs are preferred". Returns INT_MAX if the call is not
1604 * valid.
ethannicholasb3058bd2016-07-01 08:22:01 -07001605 */
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001606int IRGenerator::callCost(const FunctionDeclaration& function,
1607 const std::vector<std::unique_ptr<Expression>>& arguments) {
ethannicholasd598f792016-07-25 10:08:54 -07001608 if (function.fParameters.size() != arguments.size()) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001609 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001610 }
1611 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07001612 std::vector<const Type*> types;
1613 const Type* ignored;
1614 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001615 return INT_MAX;
ethannicholas471e8942016-10-28 09:02:46 -07001616 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001617 for (size_t i = 0; i < arguments.size(); i++) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001618 int cost = arguments[i]->coercionCost(*types[i]);
1619 if (cost != INT_MAX) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001620 total += cost;
1621 } else {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001622 return INT_MAX;
ethannicholasb3058bd2016-07-01 08:22:01 -07001623 }
1624 }
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001625 return total;
ethannicholasb3058bd2016-07-01 08:22:01 -07001626}
1627
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001628std::unique_ptr<Expression> IRGenerator::call(int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001629 std::unique_ptr<Expression> functionValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07001630 std::vector<std::unique_ptr<Expression>> arguments) {
1631 if (functionValue->fKind == Expression::kTypeReference_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001632 return this->convertConstructor(offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001633 ((TypeReference&) *functionValue).fValue,
ethannicholasb3058bd2016-07-01 08:22:01 -07001634 std::move(arguments));
1635 }
1636 if (functionValue->fKind != Expression::kFunctionReference_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001637 fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
ethannicholasb3058bd2016-07-01 08:22:01 -07001638 return nullptr;
1639 }
1640 FunctionReference* ref = (FunctionReference*) functionValue.get();
1641 int bestCost = INT_MAX;
ethannicholasd598f792016-07-25 10:08:54 -07001642 const FunctionDeclaration* best = nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001643 if (ref->fFunctions.size() > 1) {
1644 for (const auto& f : ref->fFunctions) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001645 int cost = this->callCost(*f, arguments);
1646 if (cost < bestCost) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001647 bestCost = cost;
1648 best = f;
1649 }
1650 }
1651 if (best) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001652 return this->call(offset, *best, std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001653 }
Ethan Nicholas0df1b042017-03-31 13:56:23 -04001654 String msg = "no match for " + ref->fFunctions[0]->fName + "(";
1655 String separator;
ethannicholasb3058bd2016-07-01 08:22:01 -07001656 for (size_t i = 0; i < arguments.size(); i++) {
1657 msg += separator;
1658 separator = ", ";
ethannicholasd598f792016-07-25 10:08:54 -07001659 msg += arguments[i]->fType.description();
ethannicholasb3058bd2016-07-01 08:22:01 -07001660 }
1661 msg += ")";
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001662 fErrors.error(offset, msg);
ethannicholasb3058bd2016-07-01 08:22:01 -07001663 return nullptr;
1664 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001665 return this->call(offset, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001666}
1667
Ethan Nicholas84645e32017-02-09 13:57:14 -05001668std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001669 int offset,
Ethan Nicholas11d53972016-11-28 11:23:23 -05001670 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07001671 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001672 SkASSERT(type.isNumber());
Ethan Nicholas84645e32017-02-09 13:57:14 -05001673 if (args.size() != 1) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001674 fErrors.error(offset, "invalid arguments to '" + type.description() +
1675 "' constructor, (expected exactly 1 argument, but found " +
1676 to_string((uint64_t) args.size()) + ")");
ethannicholasb3058bd2016-07-01 08:22:01 -07001677 return nullptr;
1678 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001679 if (type == args[0]->fType) {
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001680 return std::move(args[0]);
1681 }
Ethan Nicholasf7b88202017-09-18 14:10:39 -04001682 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kFloatLiteral_Kind) {
1683 double value = ((FloatLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001684 return std::unique_ptr<Expression>(new FloatLiteral(offset, value, &type));
Ethan Nicholasdcba08e2017-08-02 10:52:54 -04001685 }
1686 if (type.isFloat() && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001687 int64_t value = ((IntLiteral&) *args[0]).fValue;
Ethan Nicholas00543112018-07-31 09:44:36 -04001688 return std::unique_ptr<Expression>(new FloatLiteral(offset, (double) value, &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001689 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001690 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
1691 type == *fContext.fUInt_Type)) {
Ethan Nicholas00543112018-07-31 09:44:36 -04001692 return std::unique_ptr<Expression>(new IntLiteral(offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001693 ((IntLiteral&) *args[0]).fValue,
1694 &type));
ethannicholasb3058bd2016-07-01 08:22:01 -07001695 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001696 if (args[0]->fType == *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001697 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, offset, 0));
1698 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, offset, 1));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001699 return std::unique_ptr<Expression>(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001700 new TernaryExpression(offset, std::move(args[0]),
Ethan Nicholas84645e32017-02-09 13:57:14 -05001701 this->coerce(std::move(one), type),
1702 this->coerce(std::move(zero),
1703 type)));
1704 }
1705 if (!args[0]->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001706 fErrors.error(offset, "invalid argument to '" + type.description() +
1707 "' constructor (expected a number or bool, but found '" +
1708 args[0]->fType.description() + "')");
Ethan Nicholas84645e32017-02-09 13:57:14 -05001709 return nullptr;
1710 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001711 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001712}
1713
1714int component_count(const Type& type) {
1715 switch (type.kind()) {
1716 case Type::kVector_Kind:
1717 return type.columns();
1718 case Type::kMatrix_Kind:
1719 return type.columns() * type.rows();
1720 default:
1721 return 1;
1722 }
1723}
1724
1725std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001726 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001727 const Type& type,
1728 std::vector<std::unique_ptr<Expression>> args) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001729 SkASSERT(type.kind() == Type::kVector_Kind || type.kind() == Type::kMatrix_Kind);
Ethan Nicholas84645e32017-02-09 13:57:14 -05001730 if (type.kind() == Type::kMatrix_Kind && args.size() == 1 &&
1731 args[0]->fType.kind() == Type::kMatrix_Kind) {
1732 // matrix from matrix is always legal
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001733 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001734 }
1735 int actual = 0;
1736 int expected = type.rows() * type.columns();
1737 if (args.size() != 1 || expected != component_count(args[0]->fType) ||
1738 type.componentType().isNumber() != args[0]->fType.componentType().isNumber()) {
ethannicholas5961bc92016-10-12 06:39:56 -07001739 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas84645e32017-02-09 13:57:14 -05001740 if (args[i]->fType.kind() == Type::kVector_Kind) {
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001741 if (type.componentType().isNumber() !=
1742 args[i]->fType.componentType().isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001743 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1744 "parameter to '" + type.description() +
1745 "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001746 return nullptr;
1747 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001748 actual += args[i]->fType.columns();
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001749 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
1750 actual += 1;
1751 if (type.kind() != Type::kScalar_Kind) {
1752 args[i] = this->coerce(std::move(args[i]), type.componentType());
1753 if (!args[i]) {
1754 return nullptr;
1755 }
1756 }
1757 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001758 fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
1759 "parameter to '" + type.description() + "' constructor");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001760 return nullptr;
1761 }
1762 }
Ethan Nicholas84645e32017-02-09 13:57:14 -05001763 if (actual != 1 && actual != expected) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001764 fErrors.error(offset, "invalid arguments to '" + type.description() +
1765 "' constructor (expected " + to_string(expected) +
1766 " scalars, but found " + to_string(actual) + ")");
Ethan Nicholas49a36ba2017-02-09 17:04:23 +00001767 return nullptr;
1768 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001769 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001770 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001771}
1772
Ethan Nicholas84645e32017-02-09 13:57:14 -05001773std::unique_ptr<Expression> IRGenerator::convertConstructor(
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001774 int offset,
Ethan Nicholas84645e32017-02-09 13:57:14 -05001775 const Type& type,
1776 std::vector<std::unique_ptr<Expression>> args) {
1777 // FIXME: add support for structs
1778 Type::Kind kind = type.kind();
1779 if (args.size() == 1 && args[0]->fType == type) {
1780 // argument is already the right type, just return it
1781 return std::move(args[0]);
1782 }
1783 if (type.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001784 return this->convertNumberConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001785 } else if (kind == Type::kArray_Kind) {
1786 const Type& base = type.componentType();
1787 for (size_t i = 0; i < args.size(); i++) {
1788 args[i] = this->coerce(std::move(args[i]), base);
1789 if (!args[i]) {
1790 return nullptr;
1791 }
1792 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001793 return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001794 } else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001795 return this->convertCompoundConstructor(offset, type, std::move(args));
Ethan Nicholas84645e32017-02-09 13:57:14 -05001796 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001797 fErrors.error(offset, "cannot construct '" + type.description() + "'");
Ethan Nicholas84645e32017-02-09 13:57:14 -05001798 return nullptr;
1799 }
1800}
1801
ethannicholasb3058bd2016-07-01 08:22:01 -07001802std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1803 const ASTPrefixExpression& expression) {
1804 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1805 if (!base) {
1806 return nullptr;
1807 }
1808 switch (expression.fOperator) {
1809 case Token::PLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001810 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001811 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001812 "'+' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001813 return nullptr;
1814 }
1815 return base;
1816 case Token::MINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001817 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001818 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001819 "'-' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001820 return nullptr;
1821 }
1822 if (base->fKind == Expression::kIntLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001823 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07001824 -((IntLiteral&) *base).fValue));
1825 }
1826 if (base->fKind == Expression::kFloatLiteral_Kind) {
1827 double value = -((FloatLiteral&) *base).fValue;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001828 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07001829 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07001830 }
1831 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1832 case Token::PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001833 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001834 fErrors.error(expression.fOffset,
1835 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001836 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001837 return nullptr;
1838 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001839 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001840 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05001841 case Token::MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001842 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001843 fErrors.error(expression.fOffset,
1844 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001845 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001846 return nullptr;
1847 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04001848 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
ethannicholasb3058bd2016-07-01 08:22:01 -07001849 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001850 case Token::LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07001851 if (base->fType != *fContext.fBool_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001852 fErrors.error(expression.fOffset,
1853 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001854 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001855 return nullptr;
1856 }
ethannicholas08a92112016-11-09 13:26:45 -08001857 if (base->fKind == Expression::kBoolLiteral_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001858 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fOffset,
ethannicholas08a92112016-11-09 13:26:45 -08001859 !((BoolLiteral&) *base).fValue));
1860 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001861 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001862 case Token::BITWISENOT:
1863 if (base->fType != *fContext.fInt_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001864 fErrors.error(expression.fOffset,
1865 String("'") + Compiler::OperatorName(expression.fOperator) +
ethannicholas5961bc92016-10-12 06:39:56 -07001866 "' cannot operate on '" + base->fType.description() + "'");
1867 return nullptr;
1868 }
1869 break;
Ethan Nicholas11d53972016-11-28 11:23:23 -05001870 default:
ethannicholasb3058bd2016-07-01 08:22:01 -07001871 ABORT("unsupported prefix operator\n");
1872 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001873 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
ethannicholasb3058bd2016-07-01 08:22:01 -07001874 std::move(base)));
1875}
1876
1877std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1878 const ASTExpression& index) {
Ethan Nicholas50afc172017-02-16 14:49:57 -05001879 if (base->fKind == Expression::kTypeReference_Kind) {
1880 if (index.fKind == ASTExpression::kInt_Kind) {
1881 const Type& oldType = ((TypeReference&) *base).fValue;
1882 int64_t size = ((const ASTIntLiteral&) index).fValue;
1883 Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]",
1884 Type::kArray_Kind, oldType, size);
1885 fSymbolTable->takeOwnership(newType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001886 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
Ethan Nicholas50afc172017-02-16 14:49:57 -05001887 *newType));
1888
1889 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001890 fErrors.error(base->fOffset, "array size must be a constant");
Ethan Nicholas50afc172017-02-16 14:49:57 -05001891 return nullptr;
1892 }
1893 }
ethannicholas5961bc92016-10-12 06:39:56 -07001894 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
1895 base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001896 fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
1897 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001898 return nullptr;
1899 }
1900 std::unique_ptr<Expression> converted = this->convertExpression(index);
1901 if (!converted) {
1902 return nullptr;
1903 }
ethannicholas5961bc92016-10-12 06:39:56 -07001904 if (converted->fType != *fContext.fUInt_Type) {
1905 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
1906 if (!converted) {
1907 return nullptr;
1908 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001909 }
Ethan Nicholas11d53972016-11-28 11:23:23 -05001910 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
ethannicholasd598f792016-07-25 10:08:54 -07001911 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001912}
1913
1914std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001915 StringFragment field) {
ethannicholasd598f792016-07-25 10:08:54 -07001916 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07001917 for (size_t i = 0; i < fields.size(); i++) {
1918 if (fields[i].fName == field) {
1919 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1920 }
1921 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001922 fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
1923 "field named '" + field + "");
ethannicholasb3058bd2016-07-01 08:22:01 -07001924 return nullptr;
1925}
1926
1927std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001928 StringFragment fields) {
ethannicholasd598f792016-07-25 10:08:54 -07001929 if (base->fType.kind() != Type::kVector_Kind) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001930 fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001931 return nullptr;
1932 }
1933 std::vector<int> swizzleComponents;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001934 for (size_t i = 0; i < fields.fLength; i++) {
Ethan Nicholas9e1138d2016-11-21 10:39:35 -05001935 switch (fields[i]) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001936 case 'x': // fall through
1937 case 'r': // fall through
Ethan Nicholas11d53972016-11-28 11:23:23 -05001938 case 's':
ethannicholasb3058bd2016-07-01 08:22:01 -07001939 swizzleComponents.push_back(0);
1940 break;
1941 case 'y': // fall through
1942 case 'g': // fall through
1943 case 't':
ethannicholasd598f792016-07-25 10:08:54 -07001944 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001945 swizzleComponents.push_back(1);
1946 break;
1947 }
1948 // fall through
1949 case 'z': // fall through
1950 case 'b': // fall through
Ethan Nicholas11d53972016-11-28 11:23:23 -05001951 case 'p':
ethannicholasd598f792016-07-25 10:08:54 -07001952 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001953 swizzleComponents.push_back(2);
1954 break;
1955 }
1956 // fall through
1957 case 'w': // fall through
1958 case 'a': // fall through
1959 case 'q':
ethannicholasd598f792016-07-25 10:08:54 -07001960 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001961 swizzleComponents.push_back(3);
1962 break;
1963 }
1964 // fall through
1965 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001966 fErrors.error(base->fOffset, String::printf("invalid swizzle component '%c'",
1967 fields[i]));
ethannicholasb3058bd2016-07-01 08:22:01 -07001968 return nullptr;
1969 }
1970 }
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04001971 SkASSERT(swizzleComponents.size() > 0);
ethannicholasb3058bd2016-07-01 08:22:01 -07001972 if (swizzleComponents.size() > 4) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001973 fErrors.error(base->fOffset, "too many components in swizzle mask '" + fields + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001974 return nullptr;
1975 }
ethannicholasd598f792016-07-25 10:08:54 -07001976 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07001977}
1978
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001979std::unique_ptr<Expression> IRGenerator::getCap(int offset, String name) {
Ethan Nicholas941e7e22016-12-12 15:33:30 -05001980 auto found = fCapsMap.find(name);
1981 if (found == fCapsMap.end()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001982 fErrors.error(offset, "unknown capability flag '" + name + "'");
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001983 return nullptr;
1984 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04001985 String fullName = "sk_Caps." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001986 return std::unique_ptr<Expression>(new Setting(offset, fullName,
1987 found->second.literal(fContext, offset)));
Ethan Nicholas762466e2017-06-29 10:03:38 -04001988}
1989
Ethan Nicholas00543112018-07-31 09:44:36 -04001990std::unique_ptr<Expression> IRGenerator::getArg(int offset, String name) const {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001991 auto found = fSettings->fArgs.find(name);
1992 if (found == fSettings->fArgs.end()) {
Ethan Nicholas762466e2017-06-29 10:03:38 -04001993 return nullptr;
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001994 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04001995 String fullName = "sk_Args." + name;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001996 return std::unique_ptr<Expression>(new Setting(offset,
Ethan Nicholas762466e2017-06-29 10:03:38 -04001997 fullName,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07001998 found->second.literal(fContext, offset)));
Ethan Nicholas3605ace2016-11-21 15:59:48 -05001999}
2000
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002001std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type& type,
2002 StringFragment field) {
2003 std::unique_ptr<Expression> result;
2004 for (const auto& e : *fProgramElements) {
2005 if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
2006 std::shared_ptr<SymbolTable> old = fSymbolTable;
2007 fSymbolTable = ((Enum&) *e).fSymbols;
2008 result = convertIdentifier(ASTIdentifier(offset, field));
2009 fSymbolTable = old;
2010 }
2011 }
2012 if (!result) {
2013 fErrors.error(offset, "type '" + type.fName + "' does not have a field named '" + field +
2014 "'");
2015 }
2016 return result;
2017}
2018
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002019std::unique_ptr<Expression> IRGenerator::convertAppend(int offset,
2020 const std::vector<std::unique_ptr<ASTExpression>>& args) {
2021#ifndef SKSL_STANDALONE
2022 if (args.size() < 2) {
2023 fErrors.error(offset, "'append' requires at least two arguments");
2024 return nullptr;
2025 }
2026 std::unique_ptr<Expression> pipeline = this->convertExpression(*args[0]);
2027 if (!pipeline) {
2028 return nullptr;
2029 }
2030 if (pipeline->fType != *fContext.fSkRasterPipeline_Type) {
2031 fErrors.error(offset, "first argument of 'append' must have type 'SkRasterPipeline'");
2032 return nullptr;
2033 }
2034 if (ASTExpression::kIdentifier_Kind != args[1]->fKind) {
2035 fErrors.error(offset, "'" + args[1]->description() + "' is not a valid stage");
2036 return nullptr;
2037 }
2038 StringFragment name = ((const ASTIdentifier&) *args[1]).fText;
2039 SkRasterPipeline::StockStage stage = SkRasterPipeline::premul;
2040 std::vector<std::unique_ptr<Expression>> stageArgs;
2041 stageArgs.push_back(std::move(pipeline));
2042 for (size_t i = 2; i < args.size(); ++i) {
2043 std::unique_ptr<Expression> arg = this->convertExpression(*args[i]);
2044 if (!arg) {
2045 return nullptr;
2046 }
2047 stageArgs.push_back(std::move(arg));
2048 }
2049 size_t expectedArgs = 0;
2050 // FIXME use a map
2051 if ("premul" == name) {
2052 stage = SkRasterPipeline::premul;
2053 }
2054 else if ("unpremul" == name) {
2055 stage = SkRasterPipeline::unpremul;
2056 }
2057 else if ("clamp_0" == name) {
2058 stage = SkRasterPipeline::clamp_0;
2059 }
2060 else if ("clamp_1" == name) {
2061 stage = SkRasterPipeline::clamp_1;
2062 }
2063 else if ("matrix_4x5" == name) {
2064 expectedArgs = 1;
2065 stage = SkRasterPipeline::matrix_4x5;
2066 if (1 == stageArgs.size() && stageArgs[0]->fType.fName != "float[20]") {
2067 fErrors.error(offset, "pipeline stage '" + name + "' expected a float[20] argument");
2068 return nullptr;
2069 }
2070 }
2071 else {
2072 bool found = false;
2073 for (const auto& e : *fProgramElements) {
2074 if (ProgramElement::kFunction_Kind == e->fKind) {
2075 const FunctionDefinition& f = (const FunctionDefinition&) *e;
2076 if (f.fDeclaration.fName == name) {
2077 stage = SkRasterPipeline::callback;
2078 std::vector<const FunctionDeclaration*> functions = { &f.fDeclaration };
2079 stageArgs.emplace_back(new FunctionReference(fContext, offset, functions));
2080 found = true;
2081 break;
2082 }
2083 }
2084 }
2085 if (!found) {
2086 fErrors.error(offset, "'" + name + "' is not a valid pipeline stage");
2087 return nullptr;
2088 }
2089 }
2090 if (args.size() != expectedArgs + 2) {
2091 fErrors.error(offset, "pipeline stage '" + name + "' expected an additional argument " +
2092 "count of " + to_string((int) expectedArgs) + ", but found " +
2093 to_string((int) args.size() - 1));
2094 return nullptr;
2095 }
2096 return std::unique_ptr<Expression>(new AppendStage(fContext, offset, stage,
2097 std::move(stageArgs)));
2098#else
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002099 SkASSERT(false);
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002100 return nullptr;
2101#endif
2102}
2103
ethannicholasb3058bd2016-07-01 08:22:01 -07002104std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
2105 const ASTSuffixExpression& expression) {
2106 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
2107 if (!base) {
2108 return nullptr;
2109 }
2110 switch (expression.fSuffix->fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -07002111 case ASTSuffix::kIndex_Kind: {
2112 const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
2113 if (expr) {
2114 return this->convertIndex(std::move(base), *expr);
2115 } else if (base->fKind == Expression::kTypeReference_Kind) {
2116 const Type& oldType = ((TypeReference&) *base).fValue;
Ethan Nicholas11d53972016-11-28 11:23:23 -05002117 Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
ethannicholas5961bc92016-10-12 06:39:56 -07002118 -1);
2119 fSymbolTable->takeOwnership(newType);
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002120 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
ethannicholas5961bc92016-10-12 06:39:56 -07002121 *newType));
2122 } else {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002123 fErrors.error(expression.fOffset, "'[]' must follow a type name");
ethannicholasa54401d2016-10-14 08:37:32 -07002124 return nullptr;
ethannicholas5961bc92016-10-12 06:39:56 -07002125 }
2126 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002127 case ASTSuffix::kCall_Kind: {
2128 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
Ethan Nicholas26a9aad2018-03-27 14:10:52 -04002129 if (Expression::kFunctionReference_Kind == base->fKind &&
2130 "append" == ((const FunctionReference&) *base).fFunctions[0]->fName) {
2131 return convertAppend(expression.fOffset, *rawArguments);
2132 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002133 std::vector<std::unique_ptr<Expression>> arguments;
2134 for (size_t i = 0; i < rawArguments->size(); i++) {
Ethan Nicholas11d53972016-11-28 11:23:23 -05002135 std::unique_ptr<Expression> converted =
ethannicholasb3058bd2016-07-01 08:22:01 -07002136 this->convertExpression(*(*rawArguments)[i]);
2137 if (!converted) {
2138 return nullptr;
2139 }
2140 arguments.push_back(std::move(converted));
2141 }
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002142 return this->call(expression.fOffset, std::move(base), std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07002143 }
2144 case ASTSuffix::kField_Kind: {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002145 StringFragment field = ((ASTFieldSuffix&) *expression.fSuffix).fField;
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002146 if (base->fType == *fContext.fSkCaps_Type) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002147 return this->getCap(expression.fOffset, field);
Ethan Nicholas3605ace2016-11-21 15:59:48 -05002148 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002149 if (base->fType == *fContext.fSkArgs_Type) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002150 return this->getArg(expression.fOffset, field);
2151 }
2152 if (base->fKind == Expression::kTypeReference_Kind) {
2153 return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
2154 field);
Ethan Nicholas762466e2017-06-29 10:03:38 -04002155 }
ethannicholasd598f792016-07-25 10:08:54 -07002156 switch (base->fType.kind()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002157 case Type::kVector_Kind:
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002158 return this->convertSwizzle(std::move(base), field);
Michael Ludwig9094f2c2018-09-07 13:44:21 -04002159 case Type::kOther_Kind:
ethannicholasb3058bd2016-07-01 08:22:01 -07002160 case Type::kStruct_Kind:
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002161 return this->convertField(std::move(base), field);
ethannicholasb3058bd2016-07-01 08:22:01 -07002162 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002163 fErrors.error(base->fOffset, "cannot swizzle value of type '" +
2164 base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002165 return nullptr;
2166 }
2167 }
2168 case ASTSuffix::kPostIncrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07002169 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002170 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002171 "'++' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002172 return nullptr;
2173 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002174 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
Ethan Nicholas11d53972016-11-28 11:23:23 -05002175 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
ethannicholasb3058bd2016-07-01 08:22:01 -07002176 Token::PLUSPLUS));
2177 case ASTSuffix::kPostDecrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07002178 if (!base->fType.isNumber()) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002179 fErrors.error(expression.fOffset,
ethannicholasd598f792016-07-25 10:08:54 -07002180 "'--' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002181 return nullptr;
2182 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002183 this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
Ethan Nicholas11d53972016-11-28 11:23:23 -05002184 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
ethannicholasb3058bd2016-07-01 08:22:01 -07002185 Token::MINUSMINUS));
2186 default:
2187 ABORT("unsupported suffix operator");
2188 }
2189}
2190
2191void IRGenerator::checkValid(const Expression& expr) {
2192 switch (expr.fKind) {
2193 case Expression::kFunctionReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002194 fErrors.error(expr.fOffset, "expected '(' to begin function call");
ethannicholasb3058bd2016-07-01 08:22:01 -07002195 break;
2196 case Expression::kTypeReference_Kind:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002197 fErrors.error(expr.fOffset, "expected '(' to begin constructor invocation");
ethannicholasb3058bd2016-07-01 08:22:01 -07002198 break;
2199 default:
ethannicholasea4567c2016-10-17 11:24:37 -07002200 if (expr.fType == *fContext.fInvalid_Type) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002201 fErrors.error(expr.fOffset, "invalid expression");
ethannicholasea4567c2016-10-17 11:24:37 -07002202 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002203 }
2204}
2205
ethannicholasb3058bd2016-07-01 08:22:01 -07002206static bool has_duplicates(const Swizzle& swizzle) {
2207 int bits = 0;
2208 for (int idx : swizzle.fComponents) {
Ethan Nicholasd9d33c32018-06-12 11:05:59 -04002209 SkASSERT(idx >= 0 && idx <= 3);
ethannicholasb3058bd2016-07-01 08:22:01 -07002210 int bit = 1 << idx;
2211 if (bits & bit) {
2212 return true;
2213 }
2214 bits |= bit;
2215 }
2216 return false;
2217}
2218
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002219void IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07002220 switch (expr.fKind) {
2221 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07002222 const Variable& var = ((VariableReference&) expr).fVariable;
ethannicholasb3058bd2016-07-01 08:22:01 -07002223 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002224 fErrors.error(expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002225 "cannot modify immutable variable '" + var.fName + "'");
2226 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002227 ((VariableReference&) expr).setRefKind(kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002228 break;
2229 }
2230 case Expression::kFieldAccess_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002231 this->setRefKind(*((FieldAccess&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002232 break;
2233 case Expression::kSwizzle_Kind:
2234 if (has_duplicates((Swizzle&) expr)) {
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002235 fErrors.error(expr.fOffset,
ethannicholasb3058bd2016-07-01 08:22:01 -07002236 "cannot write to the same swizzle field more than once");
2237 }
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002238 this->setRefKind(*((Swizzle&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002239 break;
2240 case Expression::kIndex_Kind:
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002241 this->setRefKind(*((IndexExpression&) expr).fBase, kind);
ethannicholasb3058bd2016-07-01 08:22:01 -07002242 break;
Ethan Nicholasa583b812018-01-18 13:32:11 -05002243 case Expression::kTernary_Kind: {
2244 TernaryExpression& t = (TernaryExpression&) expr;
Ethan Nicholas8f7e28f2018-03-26 14:24:27 -04002245 this->setRefKind(*t.fIfTrue, kind);
2246 this->setRefKind(*t.fIfFalse, kind);
Ethan Nicholasa583b812018-01-18 13:32:11 -05002247 break;
2248 }
ethannicholasb3058bd2016-07-01 08:22:01 -07002249 default:
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002250 fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07002251 break;
2252 }
2253}
2254
Robert Phillipsfe8da172018-01-24 14:52:02 +00002255void IRGenerator::convertProgram(Program::Kind kind,
2256 const char* text,
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002257 size_t length,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002258 SymbolTable& types,
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002259 std::vector<std::unique_ptr<ProgramElement>>* out) {
Robert Phillipsfe8da172018-01-24 14:52:02 +00002260 fKind = kind;
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002261 fProgramElements = out;
Ethan Nicholas5b5f0962017-09-11 13:50:14 -07002262 Parser parser(text, length, types, fErrors);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002263 std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
2264 if (fErrors.errorCount()) {
2265 return;
2266 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002267 for (size_t i = 0; i < parsed.size(); i++) {
2268 ASTDeclaration& decl = *parsed[i];
2269 switch (decl.fKind) {
2270 case ASTDeclaration::kVar_Kind: {
2271 std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
2272 (ASTVarDeclarations&) decl,
2273 Variable::kGlobal_Storage);
2274 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002275 fProgramElements->push_back(std::move(s));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002276 }
2277 break;
2278 }
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002279 case ASTDeclaration::kEnum_Kind: {
2280 this->convertEnum((ASTEnum&) decl);
2281 break;
2282 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002283 case ASTDeclaration::kFunction_Kind: {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002284 this->convertFunction((ASTFunction&) decl);
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002285 break;
2286 }
2287 case ASTDeclaration::kModifiers_Kind: {
2288 std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(
2289 (ASTModifiersDeclaration&) decl);
2290 if (f) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002291 fProgramElements->push_back(std::move(f));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002292 }
2293 break;
2294 }
2295 case ASTDeclaration::kInterfaceBlock_Kind: {
2296 std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(
2297 (ASTInterfaceBlock&) decl);
2298 if (i) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002299 fProgramElements->push_back(std::move(i));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002300 }
2301 break;
2302 }
2303 case ASTDeclaration::kExtension_Kind: {
2304 std::unique_ptr<Extension> e = this->convertExtension((ASTExtension&) decl);
2305 if (e) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002306 fProgramElements->push_back(std::move(e));
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002307 }
2308 break;
2309 }
Ethan Nicholas762466e2017-06-29 10:03:38 -04002310 case ASTDeclaration::kSection_Kind: {
2311 std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl);
2312 if (s) {
Ethan Nicholasaae47c82017-11-10 15:34:03 -05002313 fProgramElements->push_back(std::move(s));
Ethan Nicholas762466e2017-06-29 10:03:38 -04002314 }
2315 break;
2316 }
Ethan Nicholas7da6dfa2017-06-21 11:25:18 -04002317 default:
2318 ABORT("unsupported declaration: %s\n", decl.description().c_str());
2319 }
2320 }
2321}
2322
2323
ethannicholasb3058bd2016-07-01 08:22:01 -07002324}