blob: 1a4c7759982327cc6e99c1e03421d4106b7c2b48 [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 */
7
8#include "SkSLIRGenerator.h"
9
10#include "limits.h"
11
12#include "ast/SkSLASTBoolLiteral.h"
13#include "ast/SkSLASTFieldSuffix.h"
14#include "ast/SkSLASTFloatLiteral.h"
15#include "ast/SkSLASTIndexSuffix.h"
16#include "ast/SkSLASTIntLiteral.h"
17#include "ir/SkSLBinaryExpression.h"
18#include "ir/SkSLBoolLiteral.h"
19#include "ir/SkSLBreakStatement.h"
20#include "ir/SkSLConstructor.h"
21#include "ir/SkSLContinueStatement.h"
22#include "ir/SkSLDiscardStatement.h"
23#include "ir/SkSLDoStatement.h"
24#include "ir/SkSLExpressionStatement.h"
25#include "ir/SkSLField.h"
26#include "ir/SkSLFieldAccess.h"
27#include "ir/SkSLFloatLiteral.h"
28#include "ir/SkSLForStatement.h"
29#include "ir/SkSLFunctionCall.h"
30#include "ir/SkSLFunctionDeclaration.h"
31#include "ir/SkSLFunctionDefinition.h"
32#include "ir/SkSLFunctionReference.h"
33#include "ir/SkSLIfStatement.h"
34#include "ir/SkSLIndexExpression.h"
35#include "ir/SkSLInterfaceBlock.h"
36#include "ir/SkSLIntLiteral.h"
37#include "ir/SkSLLayout.h"
38#include "ir/SkSLPostfixExpression.h"
39#include "ir/SkSLPrefixExpression.h"
40#include "ir/SkSLReturnStatement.h"
41#include "ir/SkSLSwizzle.h"
42#include "ir/SkSLTernaryExpression.h"
43#include "ir/SkSLUnresolvedFunction.h"
44#include "ir/SkSLVariable.h"
ethannicholas22f939e2016-10-13 13:25:34 -070045#include "ir/SkSLVarDeclarations.h"
46#include "ir/SkSLVarDeclarationsStatement.h"
ethannicholasb3058bd2016-07-01 08:22:01 -070047#include "ir/SkSLVariableReference.h"
48#include "ir/SkSLWhileStatement.h"
49
50namespace SkSL {
51
52class AutoSymbolTable {
53public:
54 AutoSymbolTable(IRGenerator* ir)
55 : fIR(ir)
56 , fPrevious(fIR->fSymbolTable) {
57 fIR->pushSymbolTable();
58 }
59
60 ~AutoSymbolTable() {
61 fIR->popSymbolTable();
62 ASSERT(fPrevious == fIR->fSymbolTable);
63 }
64
65 IRGenerator* fIR;
66 std::shared_ptr<SymbolTable> fPrevious;
67};
68
ethannicholas22f939e2016-10-13 13:25:34 -070069class AutoLoopLevel {
70public:
71 AutoLoopLevel(IRGenerator* ir)
72 : fIR(ir) {
73 fIR->fLoopLevel++;
74 }
75
76 ~AutoLoopLevel() {
77 fIR->fLoopLevel--;
78 }
79
80 IRGenerator* fIR;
81};
82
ethannicholasd598f792016-07-25 10:08:54 -070083IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ethannicholasb3058bd2016-07-01 08:22:01 -070084 ErrorReporter& errorReporter)
ethannicholasd598f792016-07-25 10:08:54 -070085: fContext(*context)
86, fCurrentFunction(nullptr)
87, fSymbolTable(std::move(symbolTable))
ethannicholas22f939e2016-10-13 13:25:34 -070088, fLoopLevel(0)
ethannicholasd598f792016-07-25 10:08:54 -070089, fErrors(errorReporter) {}
ethannicholasb3058bd2016-07-01 08:22:01 -070090
91void IRGenerator::pushSymbolTable() {
92 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors));
93}
94
95void IRGenerator::popSymbolTable() {
96 fSymbolTable = fSymbolTable->fParent;
97}
98
99std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
100 return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName));
101}
102
103std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
104 switch (statement.fKind) {
105 case ASTStatement::kBlock_Kind:
106 return this->convertBlock((ASTBlock&) statement);
107 case ASTStatement::kVarDeclaration_Kind:
108 return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
109 case ASTStatement::kExpression_Kind:
110 return this->convertExpressionStatement((ASTExpressionStatement&) statement);
111 case ASTStatement::kIf_Kind:
112 return this->convertIf((ASTIfStatement&) statement);
113 case ASTStatement::kFor_Kind:
114 return this->convertFor((ASTForStatement&) statement);
115 case ASTStatement::kWhile_Kind:
116 return this->convertWhile((ASTWhileStatement&) statement);
117 case ASTStatement::kDo_Kind:
118 return this->convertDo((ASTDoStatement&) statement);
119 case ASTStatement::kReturn_Kind:
120 return this->convertReturn((ASTReturnStatement&) statement);
121 case ASTStatement::kBreak_Kind:
122 return this->convertBreak((ASTBreakStatement&) statement);
123 case ASTStatement::kContinue_Kind:
124 return this->convertContinue((ASTContinueStatement&) statement);
125 case ASTStatement::kDiscard_Kind:
126 return this->convertDiscard((ASTDiscardStatement&) statement);
127 default:
128 ABORT("unsupported statement type: %d\n", statement.fKind);
129 }
130}
131
132std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
133 AutoSymbolTable table(this);
134 std::vector<std::unique_ptr<Statement>> statements;
135 for (size_t i = 0; i < block.fStatements.size(); i++) {
136 std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
137 if (!statement) {
138 return nullptr;
139 }
140 statements.push_back(std::move(statement));
141 }
ethannicholasd598f792016-07-25 10:08:54 -0700142 return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700143}
144
145std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
146 const ASTVarDeclarationStatement& s) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700147 auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
ethannicholasb3058bd2016-07-01 08:22:01 -0700148 if (!decl) {
149 return nullptr;
150 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700151 return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700152}
153
154Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) {
155 return Modifiers(modifiers);
156}
157
ethannicholas14fe8cc2016-09-07 13:37:16 -0700158std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
159 Variable::Storage storage) {
160 std::vector<VarDeclaration> variables;
ethannicholasd598f792016-07-25 10:08:54 -0700161 const Type* baseType = this->convertType(*decl.fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700162 if (!baseType) {
163 return nullptr;
164 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700165 for (const auto& varDecl : decl.fVars) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700166 Modifiers modifiers = this->convertModifiers(decl.fModifiers);
ethannicholasd598f792016-07-25 10:08:54 -0700167 const Type* type = baseType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700168 ASSERT(type->kind() != Type::kArray_Kind);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700169 std::vector<std::unique_ptr<Expression>> sizes;
170 for (const auto& rawSize : varDecl.fSizes) {
171 if (rawSize) {
172 auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700173 if (!size) {
174 return nullptr;
175 }
Greg Daniel792d0f12016-11-20 14:53:35 +0000176 std::string name = type->fName;
ethannicholasb3058bd2016-07-01 08:22:01 -0700177 uint64_t count;
178 if (size->fKind == Expression::kIntLiteral_Kind) {
179 count = ((IntLiteral&) *size).fValue;
180 if (count <= 0) {
181 fErrors.error(size->fPosition, "array size must be positive");
182 }
183 name += "[" + to_string(count) + "]";
184 } else {
185 count = -1;
186 name += "[]";
187 }
ethannicholasd598f792016-07-25 10:08:54 -0700188 type = new Type(name, Type::kArray_Kind, *type, (int) count);
189 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700190 sizes.push_back(std::move(size));
ethannicholasb3058bd2016-07-01 08:22:01 -0700191 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700192 type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
193 fSymbolTable->takeOwnership((Type*) type);
ethannicholas14fe8cc2016-09-07 13:37:16 -0700194 sizes.push_back(nullptr);
ethannicholasb3058bd2016-07-01 08:22:01 -0700195 }
196 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700197 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, varDecl.fName,
ethannicholasd598f792016-07-25 10:08:54 -0700198 *type, storage));
ethannicholasb3058bd2016-07-01 08:22:01 -0700199 std::unique_ptr<Expression> value;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700200 if (varDecl.fValue) {
201 value = this->convertExpression(*varDecl.fValue);
ethannicholasb3058bd2016-07-01 08:22:01 -0700202 if (!value) {
203 return nullptr;
204 }
ethannicholasd598f792016-07-25 10:08:54 -0700205 value = this->coerce(std::move(value), *type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700206 }
Greg Daniel792d0f12016-11-20 14:53:35 +0000207 if (storage == Variable::kGlobal_Storage && "sk_FragColor" == varDecl.fName &&
ethannicholasea4567c2016-10-17 11:24:37 -0700208 (*fSymbolTable)[varDecl.fName]) {
ethannicholas5961bc92016-10-12 06:39:56 -0700209 // already defined, ignore
ethannicholasea4567c2016-10-17 11:24:37 -0700210 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
211 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
ethannicholas5961bc92016-10-12 06:39:56 -0700212 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
ethannicholasf789b382016-08-03 12:43:36 -0700213 // already defined, just update the modifiers
ethannicholas14fe8cc2016-09-07 13:37:16 -0700214 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
ethannicholasf789b382016-08-03 12:43:36 -0700215 old->fModifiers = var->fModifiers;
216 } else {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700217 variables.emplace_back(var.get(), std::move(sizes), std::move(value));
218 fSymbolTable->add(varDecl.fName, std::move(var));
ethannicholasf789b382016-08-03 12:43:36 -0700219 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700220 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700221 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
222 baseType,
223 std::move(variables)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700224}
225
ethannicholas5961bc92016-10-12 06:39:56 -0700226std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
227 const ASTModifiersDeclaration& m) {
228 Modifiers modifiers = this->convertModifiers(m.fModifiers);
229 return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
230}
231
ethannicholasb3058bd2016-07-01 08:22:01 -0700232std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
ethannicholasd598f792016-07-25 10:08:54 -0700233 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
234 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700235 if (!test) {
236 return nullptr;
237 }
238 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
239 if (!ifTrue) {
240 return nullptr;
241 }
242 std::unique_ptr<Statement> ifFalse;
243 if (s.fIfFalse) {
244 ifFalse = this->convertStatement(*s.fIfFalse);
245 if (!ifFalse) {
246 return nullptr;
247 }
248 }
ethannicholas08a92112016-11-09 13:26:45 -0800249 if (test->fKind == Expression::kBoolLiteral_Kind) {
250 // static boolean value, fold down to a single branch
251 if (((BoolLiteral&) *test).fValue) {
252 return ifTrue;
253 } else if (s.fIfFalse) {
254 return ifFalse;
255 } else {
256 // False & no else clause. Not an error, so don't return null!
257 std::vector<std::unique_ptr<Statement>> empty;
258 return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
259 fSymbolTable));
260 }
261 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700262 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
263 std::move(ifTrue), std::move(ifFalse)));
264}
265
266std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
ethannicholas22f939e2016-10-13 13:25:34 -0700267 AutoLoopLevel level(this);
ethannicholasb3058bd2016-07-01 08:22:01 -0700268 AutoSymbolTable table(this);
ethannicholas22f939e2016-10-13 13:25:34 -0700269 std::unique_ptr<Statement> initializer;
270 if (f.fInitializer) {
271 initializer = this->convertStatement(*f.fInitializer);
272 if (!initializer) {
273 return nullptr;
274 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700275 }
ethannicholas22f939e2016-10-13 13:25:34 -0700276 std::unique_ptr<Expression> test;
277 if (f.fTest) {
278 test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
279 if (!test) {
280 return nullptr;
281 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700282 }
ethannicholas22f939e2016-10-13 13:25:34 -0700283 std::unique_ptr<Expression> next;
284 if (f.fNext) {
285 next = this->convertExpression(*f.fNext);
286 if (!next) {
287 return nullptr;
288 }
289 this->checkValid(*next);
ethannicholasb3058bd2016-07-01 08:22:01 -0700290 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700291 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
292 if (!statement) {
293 return nullptr;
294 }
295 return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
296 std::move(test), std::move(next),
ethannicholasd598f792016-07-25 10:08:54 -0700297 std::move(statement), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700298}
299
300std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
ethannicholas22f939e2016-10-13 13:25:34 -0700301 AutoLoopLevel level(this);
ethannicholasd598f792016-07-25 10:08:54 -0700302 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
303 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700304 if (!test) {
305 return nullptr;
306 }
307 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
308 if (!statement) {
309 return nullptr;
310 }
311 return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test),
312 std::move(statement)));
313}
314
315std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
ethannicholas22f939e2016-10-13 13:25:34 -0700316 AutoLoopLevel level(this);
ethannicholasd598f792016-07-25 10:08:54 -0700317 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
318 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700319 if (!test) {
320 return nullptr;
321 }
322 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
323 if (!statement) {
324 return nullptr;
325 }
326 return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
327 std::move(test)));
328}
329
330std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
331 const ASTExpressionStatement& s) {
332 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
333 if (!e) {
334 return nullptr;
335 }
336 this->checkValid(*e);
337 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
338}
339
340std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
341 ASSERT(fCurrentFunction);
342 if (r.fExpression) {
343 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
344 if (!result) {
345 return nullptr;
346 }
ethannicholasd598f792016-07-25 10:08:54 -0700347 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700348 fErrors.error(result->fPosition, "may not return a value from a void function");
349 } else {
350 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
351 if (!result) {
352 return nullptr;
353 }
354 }
355 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
356 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700357 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700358 fErrors.error(r.fPosition, "expected function to return '" +
ethannicholasd598f792016-07-25 10:08:54 -0700359 fCurrentFunction->fReturnType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700360 }
361 return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
362 }
363}
364
365std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
ethannicholas22f939e2016-10-13 13:25:34 -0700366 if (fLoopLevel > 0) {
367 return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
368 } else {
369 fErrors.error(b.fPosition, "break statement must be inside a loop");
370 return nullptr;
371 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700372}
373
374std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
ethannicholas22f939e2016-10-13 13:25:34 -0700375 if (fLoopLevel > 0) {
376 return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition));
377 } else {
378 fErrors.error(c.fPosition, "continue statement must be inside a loop");
379 return nullptr;
380 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700381}
382
383std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
384 return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
385}
386
ethannicholasb3058bd2016-07-01 08:22:01 -0700387std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) {
ethannicholasd598f792016-07-25 10:08:54 -0700388 const Type* returnType = this->convertType(*f.fReturnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700389 if (!returnType) {
390 return nullptr;
391 }
ethannicholasd598f792016-07-25 10:08:54 -0700392 std::vector<const Variable*> parameters;
ethannicholasb3058bd2016-07-01 08:22:01 -0700393 for (const auto& param : f.fParameters) {
ethannicholasd598f792016-07-25 10:08:54 -0700394 const Type* type = this->convertType(*param->fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700395 if (!type) {
396 return nullptr;
397 }
398 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
399 int size = param->fSizes[j];
Greg Daniel792d0f12016-11-20 14:53:35 +0000400 std::string name = type->name() + "[" + to_string(size) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700401 Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
402 fSymbolTable->takeOwnership(newType);
403 type = newType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700404 }
Greg Daniel792d0f12016-11-20 14:53:35 +0000405 std::string name = param->fName;
ethannicholasb3058bd2016-07-01 08:22:01 -0700406 Modifiers modifiers = this->convertModifiers(param->fModifiers);
407 Position pos = param->fPosition;
ethannicholasd598f792016-07-25 10:08:54 -0700408 Variable* var = new Variable(pos, modifiers, std::move(name), *type,
409 Variable::kParameter_Storage);
410 fSymbolTable->takeOwnership(var);
411 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700412 }
413
414 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700415 const FunctionDeclaration* decl = nullptr;
416 auto entry = (*fSymbolTable)[f.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700417 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700418 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700419 switch (entry->fKind) {
420 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700421 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700422 break;
423 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700424 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700425 break;
426 default:
427 fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
428 return nullptr;
429 }
430 for (const auto& other : functions) {
431 ASSERT(other->fName == f.fName);
432 if (parameters.size() == other->fParameters.size()) {
433 bool match = true;
434 for (size_t i = 0; i < parameters.size(); i++) {
435 if (parameters[i]->fType != other->fParameters[i]->fType) {
436 match = false;
437 break;
438 }
439 }
440 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700441 if (*returnType != other->fReturnType) {
442 FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700443 fErrors.error(f.fPosition, "functions '" + newDecl.description() +
444 "' and '" + other->description() +
445 "' differ only in return type");
446 return nullptr;
447 }
448 decl = other;
449 for (size_t i = 0; i < parameters.size(); i++) {
450 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
451 fErrors.error(f.fPosition, "modifiers on parameter " +
ethannicholas5961bc92016-10-12 06:39:56 -0700452 to_string((uint64_t) i + 1) +
453 " differ between declaration and "
454 "definition");
ethannicholasb3058bd2016-07-01 08:22:01 -0700455 return nullptr;
456 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700457 }
458 if (other->fDefined) {
459 fErrors.error(f.fPosition, "duplicate definition of " +
460 other->description());
461 }
462 break;
463 }
464 }
465 }
466 }
467 if (!decl) {
468 // couldn't find an existing declaration
ethannicholas471e8942016-10-28 09:02:46 -0700469 auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fPosition,
470 f.fName,
471 parameters,
472 *returnType));
473 decl = newDecl.get();
474 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -0700475 }
ethannicholasd598f792016-07-25 10:08:54 -0700476 if (f.fBody) {
477 ASSERT(!fCurrentFunction);
478 fCurrentFunction = decl;
479 decl->fDefined = true;
480 std::shared_ptr<SymbolTable> old = fSymbolTable;
481 AutoSymbolTable table(this);
482 for (size_t i = 0; i < parameters.size(); i++) {
483 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -0700484 }
ethannicholasd598f792016-07-25 10:08:54 -0700485 std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
486 fCurrentFunction = nullptr;
487 if (!body) {
488 return nullptr;
489 }
490 return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
491 std::move(body)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700492 }
493 return nullptr;
494}
495
496std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
497 std::shared_ptr<SymbolTable> old = fSymbolTable;
498 AutoSymbolTable table(this);
499 Modifiers mods = this->convertModifiers(intf.fModifiers);
500 std::vector<Type::Field> fields;
501 for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700502 std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
ethannicholasb3058bd2016-07-01 08:22:01 -0700503 *intf.fDeclarations[i],
504 Variable::kGlobal_Storage);
ethannicholas7effa7a2016-10-14 09:56:33 -0700505 if (!decl) {
506 return nullptr;
507 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700508 for (const auto& var : decl->fVars) {
509 fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName,
510 &var.fVar->fType));
511 if (var.fValue) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700512 fErrors.error(decl->fPosition,
513 "initializers are not permitted on interface block fields");
514 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700515 if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
516 Modifiers::kOut_Flag |
517 Modifiers::kUniform_Flag |
518 Modifiers::kConst_Flag)) {
519 fErrors.error(decl->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700520 "interface block fields may not have storage qualifiers");
521 }
522 }
523 }
ethannicholasd598f792016-07-25 10:08:54 -0700524 Type* type = new Type(intf.fInterfaceName, fields);
525 fSymbolTable->takeOwnership(type);
Greg Daniel792d0f12016-11-20 14:53:35 +0000526 std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fInterfaceName;
ethannicholasd598f792016-07-25 10:08:54 -0700527 Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage);
528 fSymbolTable->takeOwnership(var);
Greg Daniel792d0f12016-11-20 14:53:35 +0000529 if (intf.fValueName.length()) {
ethannicholasd598f792016-07-25 10:08:54 -0700530 old->addWithoutOwnership(intf.fValueName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700531 } else {
532 for (size_t i = 0; i < fields.size(); i++) {
ethannicholasd598f792016-07-25 10:08:54 -0700533 old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
534 (int) i)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700535 }
536 }
ethannicholasd598f792016-07-25 10:08:54 -0700537 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700538}
539
ethannicholasd598f792016-07-25 10:08:54 -0700540const Type* IRGenerator::convertType(const ASTType& type) {
541 const Symbol* result = (*fSymbolTable)[type.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700542 if (result && result->fKind == Symbol::kType_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -0700543 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700544 }
545 fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
546 return nullptr;
547}
548
549std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
550 switch (expr.fKind) {
551 case ASTExpression::kIdentifier_Kind:
552 return this->convertIdentifier((ASTIdentifier&) expr);
553 case ASTExpression::kBool_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700554 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700555 ((ASTBoolLiteral&) expr).fValue));
556 case ASTExpression::kInt_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700557 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700558 ((ASTIntLiteral&) expr).fValue));
559 case ASTExpression::kFloat_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700560 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700561 ((ASTFloatLiteral&) expr).fValue));
562 case ASTExpression::kBinary_Kind:
563 return this->convertBinaryExpression((ASTBinaryExpression&) expr);
564 case ASTExpression::kPrefix_Kind:
565 return this->convertPrefixExpression((ASTPrefixExpression&) expr);
566 case ASTExpression::kSuffix_Kind:
567 return this->convertSuffixExpression((ASTSuffixExpression&) expr);
568 case ASTExpression::kTernary_Kind:
569 return this->convertTernaryExpression((ASTTernaryExpression&) expr);
570 default:
571 ABORT("unsupported expression type: %d\n", expr.fKind);
572 }
573}
574
575std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
ethannicholasd598f792016-07-25 10:08:54 -0700576 const Symbol* result = (*fSymbolTable)[identifier.fText];
ethannicholasb3058bd2016-07-01 08:22:01 -0700577 if (!result) {
578 fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'");
579 return nullptr;
580 }
581 switch (result->fKind) {
582 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700583 std::vector<const FunctionDeclaration*> f = {
584 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -0700585 };
ethannicholasd598f792016-07-25 10:08:54 -0700586 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
587 identifier.fPosition,
588 f));
ethannicholasb3058bd2016-07-01 08:22:01 -0700589 }
590 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700591 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
592 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
593 identifier.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700594 f->fFunctions));
595 }
596 case Symbol::kVariable_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700597 const Variable* var = (const Variable*) result;
598 this->markReadFrom(*var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700599 return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -0700600 *var));
ethannicholasb3058bd2016-07-01 08:22:01 -0700601 }
602 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700603 const Field* field = (const Field*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700604 VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner);
ethannicholasf789b382016-08-03 12:43:36 -0700605 return std::unique_ptr<Expression>(new FieldAccess(
606 std::unique_ptr<Expression>(base),
607 field->fFieldIndex,
608 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -0700609 }
610 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700611 const Type* t = (const Type*) result;
612 return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
613 *t));
ethannicholasb3058bd2016-07-01 08:22:01 -0700614 }
615 default:
616 ABORT("unsupported symbol type %d\n", result->fKind);
617 }
618
619}
620
621std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -0700622 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700623 if (!expr) {
624 return nullptr;
625 }
ethannicholasd598f792016-07-25 10:08:54 -0700626 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700627 return expr;
628 }
629 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -0700630 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700631 return nullptr;
632 }
ethannicholasd598f792016-07-25 10:08:54 -0700633 if (!expr->fType.canCoerceTo(type)) {
634 fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
635 expr->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700636 return nullptr;
637 }
ethannicholasd598f792016-07-25 10:08:54 -0700638 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700639 std::vector<std::unique_ptr<Expression>> args;
640 args.push_back(std::move(expr));
ethannicholasd598f792016-07-25 10:08:54 -0700641 ASTIdentifier id(Position(), type.description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700642 std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
643 ASSERT(ctor);
644 return this->call(Position(), std::move(ctor), std::move(args));
645 }
ethannicholas5961bc92016-10-12 06:39:56 -0700646 std::vector<std::unique_ptr<Expression>> args;
647 args.push_back(std::move(expr));
648 return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700649}
650
ethannicholasf789b382016-08-03 12:43:36 -0700651static bool is_matrix_multiply(const Type& left, const Type& right) {
652 if (left.kind() == Type::kMatrix_Kind) {
653 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
654 }
655 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
656}
ethannicholasea4567c2016-10-17 11:24:37 -0700657
658static bool is_assignment(Token::Kind op) {
659 switch (op) {
660 case Token::EQ: // fall through
661 case Token::PLUSEQ: // fall through
662 case Token::MINUSEQ: // fall through
663 case Token::STAREQ: // fall through
664 case Token::SLASHEQ: // fall through
665 case Token::PERCENTEQ: // fall through
666 case Token::SHLEQ: // fall through
667 case Token::SHREQ: // fall through
668 case Token::BITWISEOREQ: // fall through
669 case Token::BITWISEXOREQ: // fall through
670 case Token::BITWISEANDEQ: // fall through
671 case Token::LOGICALOREQ: // fall through
672 case Token::LOGICALXOREQ: // fall through
673 case Token::LOGICALANDEQ:
674 return true;
675 default:
676 return false;
677 }
678}
679
ethannicholasb3058bd2016-07-01 08:22:01 -0700680/**
681 * Determines the operand and result types of a binary expression. Returns true if the expression is
682 * legal, false otherwise. If false, the values of the out parameters are undefined.
683 */
ethannicholasd598f792016-07-25 10:08:54 -0700684static bool determine_binary_type(const Context& context,
685 Token::Kind op,
686 const Type& left,
687 const Type& right,
688 const Type** outLeftType,
689 const Type** outRightType,
690 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -0700691 bool tryFlipped) {
692 bool isLogical;
ethannicholasea4567c2016-10-17 11:24:37 -0700693 bool validMatrixOrVectorOp;
ethannicholasb3058bd2016-07-01 08:22:01 -0700694 switch (op) {
ethannicholasea4567c2016-10-17 11:24:37 -0700695 case Token::EQ:
696 *outLeftType = &left;
697 *outRightType = &left;
698 *outResultType = &left;
699 return right.canCoerceTo(left);
ethannicholasb3058bd2016-07-01 08:22:01 -0700700 case Token::EQEQ: // fall through
ethannicholasea4567c2016-10-17 11:24:37 -0700701 case Token::NEQ:
702 isLogical = true;
703 validMatrixOrVectorOp = true;
704 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700705 case Token::LT: // fall through
706 case Token::GT: // fall through
707 case Token::LTEQ: // fall through
708 case Token::GTEQ:
709 isLogical = true;
ethannicholasea4567c2016-10-17 11:24:37 -0700710 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700711 break;
712 case Token::LOGICALOR: // fall through
713 case Token::LOGICALAND: // fall through
714 case Token::LOGICALXOR: // fall through
715 case Token::LOGICALOREQ: // fall through
716 case Token::LOGICALANDEQ: // fall through
717 case Token::LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -0700718 *outLeftType = context.fBool_Type.get();
719 *outRightType = context.fBool_Type.get();
720 *outResultType = context.fBool_Type.get();
721 return left.canCoerceTo(*context.fBool_Type) &&
722 right.canCoerceTo(*context.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700723 case Token::STAR: // fall through
724 case Token::STAREQ:
ethannicholasf789b382016-08-03 12:43:36 -0700725 if (is_matrix_multiply(left, right)) {
726 // determine final component type
727 if (determine_binary_type(context, Token::STAR, left.componentType(),
728 right.componentType(), outLeftType, outRightType,
729 outResultType, false)) {
730 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
731 left.rows());;
732 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
733 right.rows());;
734 int leftColumns = left.columns();
735 int leftRows = left.rows();
736 int rightColumns;
737 int rightRows;
738 if (right.kind() == Type::kVector_Kind) {
739 // matrix * vector treats the vector as a column vector, so we need to
740 // transpose it
741 rightColumns = right.rows();
742 rightRows = right.columns();
743 ASSERT(rightColumns == 1);
744 } else {
745 rightColumns = right.columns();
746 rightRows = right.rows();
747 }
748 if (rightColumns > 1) {
749 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
750 leftRows);
751 } else {
752 // result was a column vector, transpose it back to a row
753 *outResultType = &(*outResultType)->toCompound(context, leftRows,
754 rightColumns);
755 }
756 return leftColumns == rightRows;
757 } else {
758 return false;
759 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700760 }
ethannicholasea4567c2016-10-17 11:24:37 -0700761 isLogical = false;
762 validMatrixOrVectorOp = true;
763 break;
764 case Token::PLUS: // fall through
765 case Token::PLUSEQ: // fall through
766 case Token::MINUS: // fall through
767 case Token::MINUSEQ: // fall through
768 case Token::SLASH: // fall through
769 case Token::SLASHEQ:
770 isLogical = false;
771 validMatrixOrVectorOp = true;
772 break;
ethannicholasb3058bd2016-07-01 08:22:01 -0700773 default:
774 isLogical = false;
ethannicholasea4567c2016-10-17 11:24:37 -0700775 validMatrixOrVectorOp = false;
ethannicholasb3058bd2016-07-01 08:22:01 -0700776 }
ethannicholasea4567c2016-10-17 11:24:37 -0700777 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
778 // FIXME: incorrect for shift
779 if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
780 (isVectorOrMatrix && validMatrixOrVectorOp))) {
ethannicholasd598f792016-07-25 10:08:54 -0700781 *outLeftType = &left;
782 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -0700783 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -0700784 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700785 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700786 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -0700787 }
788 return true;
789 }
ethannicholasd598f792016-07-25 10:08:54 -0700790 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
791 (right.kind() == Type::kScalar_Kind)) {
792 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
793 outRightType, outResultType, false)) {
794 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -0700795 if (!isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -0700796 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
797 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -0700798 }
799 return true;
800 }
801 return false;
802 }
803 if (tryFlipped) {
ethannicholasd598f792016-07-25 10:08:54 -0700804 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
805 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -0700806 }
807 return false;
808}
809
ethannicholas08a92112016-11-09 13:26:45 -0800810/**
811 * If both operands are compile-time constants and can be folded, returns an expression representing
812 * the folded value. Otherwise, returns null. Note that unlike most other functions here, null does
813 * not represent a compilation error.
814 */
815std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
816 Token::Kind op,
817 const Expression& right) {
818 // Note that we expressly do not worry about precision and overflow here -- we use the maximum
819 // precision to calculate the results and hope the result makes sense. The plan is to move the
820 // Skia caps into SkSL, so we have access to all of them including the precisions of the various
821 // types, which will let us be more intelligent about this.
822 if (left.fKind == Expression::kBoolLiteral_Kind &&
823 right.fKind == Expression::kBoolLiteral_Kind) {
824 bool leftVal = ((BoolLiteral&) left).fValue;
825 bool rightVal = ((BoolLiteral&) right).fValue;
826 bool result;
827 switch (op) {
828 case Token::LOGICALAND: result = leftVal && rightVal; break;
829 case Token::LOGICALOR: result = leftVal || rightVal; break;
830 case Token::LOGICALXOR: result = leftVal ^ rightVal; break;
831 default: return nullptr;
832 }
833 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosition, result));
834 }
835 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \
836 leftVal op rightVal))
837 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression::kIntLiteral_Kind) {
838 int64_t leftVal = ((IntLiteral&) left).fValue;
839 int64_t rightVal = ((IntLiteral&) right).fValue;
840 switch (op) {
841 case Token::PLUS: return RESULT(Int, +);
842 case Token::MINUS: return RESULT(Int, -);
843 case Token::STAR: return RESULT(Int, *);
844 case Token::SLASH: return RESULT(Int, /);
845 case Token::PERCENT: return RESULT(Int, %);
846 case Token::BITWISEAND: return RESULT(Int, &);
847 case Token::BITWISEOR: return RESULT(Int, |);
848 case Token::BITWISEXOR: return RESULT(Int, ^);
849 case Token::SHL: return RESULT(Int, <<);
850 case Token::SHR: return RESULT(Int, >>);
851 case Token::EQEQ: return RESULT(Bool, ==);
852 case Token::NEQ: return RESULT(Bool, !=);
853 case Token::GT: return RESULT(Bool, >);
854 case Token::GTEQ: return RESULT(Bool, >=);
855 case Token::LT: return RESULT(Bool, <);
856 case Token::LTEQ: return RESULT(Bool, <=);
857 default: return nullptr;
858 }
859 }
860 if (left.fKind == Expression::kFloatLiteral_Kind &&
861 right.fKind == Expression::kFloatLiteral_Kind) {
862 double leftVal = ((FloatLiteral&) left).fValue;
863 double rightVal = ((FloatLiteral&) right).fValue;
864 switch (op) {
865 case Token::PLUS: return RESULT(Float, +);
866 case Token::MINUS: return RESULT(Float, -);
867 case Token::STAR: return RESULT(Float, *);
868 case Token::SLASH: return RESULT(Float, /);
869 case Token::EQEQ: return RESULT(Bool, ==);
870 case Token::NEQ: return RESULT(Bool, !=);
871 case Token::GT: return RESULT(Bool, >);
872 case Token::GTEQ: return RESULT(Bool, >=);
873 case Token::LT: return RESULT(Bool, <);
874 case Token::LTEQ: return RESULT(Bool, <=);
875 default: return nullptr;
876 }
877 }
878 #undef RESULT
879 return nullptr;
880}
881
ethannicholasb3058bd2016-07-01 08:22:01 -0700882std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
883 const ASTBinaryExpression& expression) {
884 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
885 if (!left) {
886 return nullptr;
887 }
888 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
889 if (!right) {
890 return nullptr;
891 }
ethannicholasd598f792016-07-25 10:08:54 -0700892 const Type* leftType;
893 const Type* rightType;
894 const Type* resultType;
895 if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
ethannicholasea4567c2016-10-17 11:24:37 -0700896 &rightType, &resultType, !is_assignment(expression.fOperator))) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700897 fErrors.error(expression.fPosition, "type mismatch: '" +
898 Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -0700899 "' cannot operate on '" + left->fType.fName +
900 "', '" + right->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700901 return nullptr;
902 }
ethannicholasea4567c2016-10-17 11:24:37 -0700903 if (is_assignment(expression.fOperator)) {
904 this->markWrittenTo(*left);
905 }
906 left = this->coerce(std::move(left), *leftType);
907 right = this->coerce(std::move(right), *rightType);
908 if (!left || !right) {
909 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700910 }
ethannicholas08a92112016-11-09 13:26:45 -0800911 std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
912 *right.get());
913 if (!result) {
914 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
915 std::move(left),
916 expression.fOperator,
917 std::move(right),
918 *resultType));
919 }
920 return result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700921}
922
923std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
924 const ASTTernaryExpression& expression) {
925 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700926 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700927 if (!test) {
928 return nullptr;
929 }
930 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
931 if (!ifTrue) {
932 return nullptr;
933 }
934 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
935 if (!ifFalse) {
936 return nullptr;
937 }
ethannicholasd598f792016-07-25 10:08:54 -0700938 const Type* trueType;
939 const Type* falseType;
940 const Type* resultType;
941 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
ethannicholasb3058bd2016-07-01 08:22:01 -0700942 &falseType, &resultType, true)) {
943 fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
ethannicholasd598f792016-07-25 10:08:54 -0700944 ifTrue->fType.fName + "', '" +
945 ifFalse->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700946 return nullptr;
947 }
948 ASSERT(trueType == falseType);
ethannicholasd598f792016-07-25 10:08:54 -0700949 ifTrue = this->coerce(std::move(ifTrue), *trueType);
950 ifFalse = this->coerce(std::move(ifFalse), *falseType);
ethannicholas08a92112016-11-09 13:26:45 -0800951 if (test->fKind == Expression::kBoolLiteral_Kind) {
952 // static boolean test, just return one of the branches
953 if (((BoolLiteral&) *test).fValue) {
954 return ifTrue;
955 } else {
956 return ifFalse;
957 }
958 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700959 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
960 std::move(test),
961 std::move(ifTrue),
962 std::move(ifFalse)));
963}
964
ethannicholasd598f792016-07-25 10:08:54 -0700965std::unique_ptr<Expression> IRGenerator::call(Position position,
966 const FunctionDeclaration& function,
967 std::vector<std::unique_ptr<Expression>> arguments) {
968 if (function.fParameters.size() != arguments.size()) {
Greg Daniel792d0f12016-11-20 14:53:35 +0000969 std::string msg = "call to '" + function.fName + "' expected " +
ethannicholas5961bc92016-10-12 06:39:56 -0700970 to_string((uint64_t) function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -0700971 " argument";
ethannicholasd598f792016-07-25 10:08:54 -0700972 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700973 msg += "s";
974 }
ethannicholas5961bc92016-10-12 06:39:56 -0700975 msg += ", but found " + to_string((uint64_t) arguments.size());
ethannicholasb3058bd2016-07-01 08:22:01 -0700976 fErrors.error(position, msg);
977 return nullptr;
978 }
ethannicholas471e8942016-10-28 09:02:46 -0700979 std::vector<const Type*> types;
980 const Type* returnType;
981 if (!function.determineFinalTypes(arguments, &types, &returnType)) {
Greg Daniel792d0f12016-11-20 14:53:35 +0000982 std::string msg = "no match for " + function.fName + "(";
983 std::string separator = "";
ethannicholas471e8942016-10-28 09:02:46 -0700984 for (size_t i = 0; i < arguments.size(); i++) {
985 msg += separator;
986 separator = ", ";
987 msg += arguments[i]->fType.description();
988 }
989 msg += ")";
990 fErrors.error(position, msg);
991 return nullptr;
992 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700993 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholas471e8942016-10-28 09:02:46 -0700994 arguments[i] = this->coerce(std::move(arguments[i]), *types[i]);
ethannicholasea4567c2016-10-17 11:24:37 -0700995 if (!arguments[i]) {
996 return nullptr;
997 }
ethannicholasd598f792016-07-25 10:08:54 -0700998 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700999 this->markWrittenTo(*arguments[i]);
1000 }
1001 }
ethannicholas471e8942016-10-28 09:02:46 -07001002 return std::unique_ptr<FunctionCall>(new FunctionCall(position, *returnType, function,
ethannicholasb3058bd2016-07-01 08:22:01 -07001003 std::move(arguments)));
1004}
1005
1006/**
1007 * Determines the cost of coercing the arguments of a function to the required types. Returns true
1008 * if the cost could be computed, false if the call is not valid. Cost has no particular meaning
1009 * other than "lower costs are preferred".
1010 */
ethannicholasd598f792016-07-25 10:08:54 -07001011bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
ethannicholasb3058bd2016-07-01 08:22:01 -07001012 const std::vector<std::unique_ptr<Expression>>& arguments,
1013 int* outCost) {
ethannicholasd598f792016-07-25 10:08:54 -07001014 if (function.fParameters.size() != arguments.size()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001015 return false;
1016 }
1017 int total = 0;
ethannicholas471e8942016-10-28 09:02:46 -07001018 std::vector<const Type*> types;
1019 const Type* ignored;
1020 if (!function.determineFinalTypes(arguments, &types, &ignored)) {
1021 return false;
1022 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001023 for (size_t i = 0; i < arguments.size(); i++) {
1024 int cost;
ethannicholas471e8942016-10-28 09:02:46 -07001025 if (arguments[i]->fType.determineCoercionCost(*types[i], &cost)) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001026 total += cost;
1027 } else {
1028 return false;
1029 }
1030 }
1031 *outCost = total;
1032 return true;
1033}
1034
1035std::unique_ptr<Expression> IRGenerator::call(Position position,
1036 std::unique_ptr<Expression> functionValue,
1037 std::vector<std::unique_ptr<Expression>> arguments) {
1038 if (functionValue->fKind == Expression::kTypeReference_Kind) {
1039 return this->convertConstructor(position,
1040 ((TypeReference&) *functionValue).fValue,
1041 std::move(arguments));
1042 }
1043 if (functionValue->fKind != Expression::kFunctionReference_Kind) {
1044 fErrors.error(position, "'" + functionValue->description() + "' is not a function");
1045 return nullptr;
1046 }
1047 FunctionReference* ref = (FunctionReference*) functionValue.get();
1048 int bestCost = INT_MAX;
ethannicholasd598f792016-07-25 10:08:54 -07001049 const FunctionDeclaration* best = nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001050 if (ref->fFunctions.size() > 1) {
1051 for (const auto& f : ref->fFunctions) {
1052 int cost;
ethannicholasd598f792016-07-25 10:08:54 -07001053 if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001054 bestCost = cost;
1055 best = f;
1056 }
1057 }
1058 if (best) {
ethannicholasd598f792016-07-25 10:08:54 -07001059 return this->call(position, *best, std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001060 }
Greg Daniel792d0f12016-11-20 14:53:35 +00001061 std::string msg = "no match for " + ref->fFunctions[0]->fName + "(";
1062 std::string separator = "";
ethannicholasb3058bd2016-07-01 08:22:01 -07001063 for (size_t i = 0; i < arguments.size(); i++) {
1064 msg += separator;
1065 separator = ", ";
ethannicholasd598f792016-07-25 10:08:54 -07001066 msg += arguments[i]->fType.description();
ethannicholasb3058bd2016-07-01 08:22:01 -07001067 }
1068 msg += ")";
1069 fErrors.error(position, msg);
1070 return nullptr;
1071 }
ethannicholasd598f792016-07-25 10:08:54 -07001072 return this->call(position, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -07001073}
1074
1075std::unique_ptr<Expression> IRGenerator::convertConstructor(
1076 Position position,
ethannicholasd598f792016-07-25 10:08:54 -07001077 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -07001078 std::vector<std::unique_ptr<Expression>> args) {
1079 // FIXME: add support for structs and arrays
ethannicholasd598f792016-07-25 10:08:54 -07001080 Type::Kind kind = type.kind();
ethannicholas5961bc92016-10-12 06:39:56 -07001081 if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind &&
1082 kind != Type::kArray_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -07001083 fErrors.error(position, "cannot construct '" + type.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001084 return nullptr;
1085 }
ethannicholasd598f792016-07-25 10:08:54 -07001086 if (type == *fContext.fFloat_Type && args.size() == 1 &&
ethannicholasb3058bd2016-07-01 08:22:01 -07001087 args[0]->fKind == Expression::kIntLiteral_Kind) {
1088 int64_t value = ((IntLiteral&) *args[0]).fValue;
ethannicholasd598f792016-07-25 10:08:54 -07001089 return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
ethannicholasb3058bd2016-07-01 08:22:01 -07001090 }
1091 if (args.size() == 1 && args[0]->fType == type) {
1092 // argument is already the right type, just return it
1093 return std::move(args[0]);
1094 }
ethannicholasd598f792016-07-25 10:08:54 -07001095 if (type.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001096 if (args.size() != 1) {
ethannicholasd598f792016-07-25 10:08:54 -07001097 fErrors.error(position, "invalid arguments to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -07001098 "' constructor, (expected exactly 1 argument, but found " +
ethannicholas5961bc92016-10-12 06:39:56 -07001099 to_string((uint64_t) args.size()) + ")");
ethannicholasea4567c2016-10-17 11:24:37 -07001100 return nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -07001101 }
ethannicholasd598f792016-07-25 10:08:54 -07001102 if (args[0]->fType == *fContext.fBool_Type) {
1103 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
1104 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1));
ethannicholasb3058bd2016-07-01 08:22:01 -07001105 return std::unique_ptr<Expression>(
1106 new TernaryExpression(position, std::move(args[0]),
1107 this->coerce(std::move(one), type),
1108 this->coerce(std::move(zero),
1109 type)));
ethannicholasd598f792016-07-25 10:08:54 -07001110 } else if (!args[0]->fType.isNumber()) {
1111 fErrors.error(position, "invalid argument to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -07001112 "' constructor (expected a number or bool, but found '" +
ethannicholasd598f792016-07-25 10:08:54 -07001113 args[0]->fType.description() + "')");
ethannicholasb3058bd2016-07-01 08:22:01 -07001114 }
ethannicholas5961bc92016-10-12 06:39:56 -07001115 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
1116 type == *fContext.fUInt_Type)) {
1117 return std::unique_ptr<Expression>(new IntLiteral(fContext,
1118 position,
1119 ((IntLiteral&) *args[0]).fValue,
1120 &type));
1121 }
1122 } else if (kind == Type::kArray_Kind) {
1123 const Type& base = type.componentType();
1124 for (size_t i = 0; i < args.size(); i++) {
1125 args[i] = this->coerce(std::move(args[i]), base);
ethannicholasea4567c2016-10-17 11:24:37 -07001126 if (!args[i]) {
1127 return nullptr;
1128 }
ethannicholas5961bc92016-10-12 06:39:56 -07001129 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001130 } else {
1131 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
1132 int actual = 0;
1133 for (size_t i = 0; i < args.size(); i++) {
Ethan Nicholas4578a8e2016-11-01 11:57:42 -04001134 if (args[i]->fType.kind() == Type::kVector_Kind ||
ethannicholasd598f792016-07-25 10:08:54 -07001135 args[i]->fType.kind() == Type::kMatrix_Kind) {
Ethan Nicholas4578a8e2016-11-01 11:57:42 -04001136 if (type.componentType().isNumber() !=
1137 args[i]->fType.componentType().isNumber()) {
1138 fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
1139 "parameter to '" + type.description() +
1140 "' constructor");
ethannicholas7effa7a2016-10-14 09:56:33 -07001141 return nullptr;
1142 }
ethannicholasd598f792016-07-25 10:08:54 -07001143 actual += args[i]->fType.rows() * args[i]->fType.columns();
1144 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001145 actual += 1;
ethannicholasd598f792016-07-25 10:08:54 -07001146 if (type.kind() != Type::kScalar_Kind) {
1147 args[i] = this->coerce(std::move(args[i]), type.componentType());
ethannicholas7effa7a2016-10-14 09:56:33 -07001148 if (!args[i]) {
1149 return nullptr;
1150 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001151 }
1152 } else {
ethannicholasd598f792016-07-25 10:08:54 -07001153 fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
1154 "parameter to '" + type.description() + "' constructor");
ethannicholasb3058bd2016-07-01 08:22:01 -07001155 return nullptr;
1156 }
1157 }
ethannicholasd598f792016-07-25 10:08:54 -07001158 int min = type.rows() * type.columns();
1159 int max = type.columns() > 1 ? INT_MAX : min;
ethannicholasb3058bd2016-07-01 08:22:01 -07001160 if ((actual < min || actual > max) &&
1161 !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) {
ethannicholasd598f792016-07-25 10:08:54 -07001162 fErrors.error(position, "invalid arguments to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -07001163 "' constructor (expected " + to_string(min) + " scalar" +
1164 (min == 1 ? "" : "s") + ", but found " + to_string(actual) +
1165 ")");
1166 return nullptr;
1167 }
1168 }
1169 return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
1170}
1171
1172std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1173 const ASTPrefixExpression& expression) {
1174 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1175 if (!base) {
1176 return nullptr;
1177 }
1178 switch (expression.fOperator) {
1179 case Token::PLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001180 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001181 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001182 "'+' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001183 return nullptr;
1184 }
1185 return base;
1186 case Token::MINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001187 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001188 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001189 "'-' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001190 return nullptr;
1191 }
1192 if (base->fKind == Expression::kIntLiteral_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -07001193 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001194 -((IntLiteral&) *base).fValue));
1195 }
1196 if (base->fKind == Expression::kFloatLiteral_Kind) {
1197 double value = -((FloatLiteral&) *base).fValue;
ethannicholasd598f792016-07-25 10:08:54 -07001198 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
1199 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07001200 }
1201 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1202 case Token::PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001203 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001204 fErrors.error(expression.fPosition,
1205 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001206 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001207 return nullptr;
1208 }
1209 this->markWrittenTo(*base);
1210 break;
1211 case Token::MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001212 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001213 fErrors.error(expression.fPosition,
1214 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001215 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001216 return nullptr;
1217 }
1218 this->markWrittenTo(*base);
1219 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001220 case Token::LOGICALNOT:
ethannicholasd598f792016-07-25 10:08:54 -07001221 if (base->fType != *fContext.fBool_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001222 fErrors.error(expression.fPosition,
1223 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001224 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001225 return nullptr;
1226 }
ethannicholas08a92112016-11-09 13:26:45 -08001227 if (base->fKind == Expression::kBoolLiteral_Kind) {
1228 return std::unique_ptr<Expression>(new BoolLiteral(fContext, base->fPosition,
1229 !((BoolLiteral&) *base).fValue));
1230 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001231 break;
ethannicholas5961bc92016-10-12 06:39:56 -07001232 case Token::BITWISENOT:
1233 if (base->fType != *fContext.fInt_Type) {
1234 fErrors.error(expression.fPosition,
1235 "'" + Token::OperatorName(expression.fOperator) +
1236 "' cannot operate on '" + base->fType.description() + "'");
1237 return nullptr;
1238 }
1239 break;
ethannicholasb3058bd2016-07-01 08:22:01 -07001240 default:
1241 ABORT("unsupported prefix operator\n");
1242 }
1243 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
1244 std::move(base)));
1245}
1246
1247std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1248 const ASTExpression& index) {
ethannicholas5961bc92016-10-12 06:39:56 -07001249 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
1250 base->fType.kind() != Type::kVector_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -07001251 fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -07001252 "'");
1253 return nullptr;
1254 }
1255 std::unique_ptr<Expression> converted = this->convertExpression(index);
1256 if (!converted) {
1257 return nullptr;
1258 }
ethannicholas5961bc92016-10-12 06:39:56 -07001259 if (converted->fType != *fContext.fUInt_Type) {
1260 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
1261 if (!converted) {
1262 return nullptr;
1263 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001264 }
ethannicholasd598f792016-07-25 10:08:54 -07001265 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
1266 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001267}
1268
1269std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
Greg Daniel792d0f12016-11-20 14:53:35 +00001270 const std::string& field) {
ethannicholasd598f792016-07-25 10:08:54 -07001271 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07001272 for (size_t i = 0; i < fields.size(); i++) {
1273 if (fields[i].fName == field) {
1274 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1275 }
1276 }
ethannicholasd598f792016-07-25 10:08:54 -07001277 fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a "
ethannicholasb3058bd2016-07-01 08:22:01 -07001278 "field named '" + field + "");
1279 return nullptr;
1280}
1281
1282std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
Greg Daniel792d0f12016-11-20 14:53:35 +00001283 const std::string& fields) {
ethannicholasd598f792016-07-25 10:08:54 -07001284 if (base->fType.kind() != Type::kVector_Kind) {
1285 fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001286 return nullptr;
1287 }
1288 std::vector<int> swizzleComponents;
Greg Daniel792d0f12016-11-20 14:53:35 +00001289 for (char c : fields) {
1290 switch (c) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001291 case 'x': // fall through
1292 case 'r': // fall through
1293 case 's':
1294 swizzleComponents.push_back(0);
1295 break;
1296 case 'y': // fall through
1297 case 'g': // fall through
1298 case 't':
ethannicholasd598f792016-07-25 10:08:54 -07001299 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001300 swizzleComponents.push_back(1);
1301 break;
1302 }
1303 // fall through
1304 case 'z': // fall through
1305 case 'b': // fall through
1306 case 'p':
ethannicholasd598f792016-07-25 10:08:54 -07001307 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001308 swizzleComponents.push_back(2);
1309 break;
1310 }
1311 // fall through
1312 case 'w': // fall through
1313 case 'a': // fall through
1314 case 'q':
ethannicholasd598f792016-07-25 10:08:54 -07001315 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001316 swizzleComponents.push_back(3);
1317 break;
1318 }
1319 // fall through
1320 default:
Greg Daniel792d0f12016-11-20 14:53:35 +00001321 fErrors.error(base->fPosition, "invalid swizzle component '" + std::string(1, c) +
1322 "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001323 return nullptr;
1324 }
1325 }
1326 ASSERT(swizzleComponents.size() > 0);
1327 if (swizzleComponents.size() > 4) {
1328 fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'");
1329 return nullptr;
1330 }
ethannicholasd598f792016-07-25 10:08:54 -07001331 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07001332}
1333
1334std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1335 const ASTSuffixExpression& expression) {
1336 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
1337 if (!base) {
1338 return nullptr;
1339 }
1340 switch (expression.fSuffix->fKind) {
ethannicholas5961bc92016-10-12 06:39:56 -07001341 case ASTSuffix::kIndex_Kind: {
1342 const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
1343 if (expr) {
1344 return this->convertIndex(std::move(base), *expr);
1345 } else if (base->fKind == Expression::kTypeReference_Kind) {
1346 const Type& oldType = ((TypeReference&) *base).fValue;
1347 Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
1348 -1);
1349 fSymbolTable->takeOwnership(newType);
1350 return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
1351 *newType));
1352 } else {
1353 fErrors.error(expression.fPosition, "'[]' must follow a type name");
ethannicholasa54401d2016-10-14 08:37:32 -07001354 return nullptr;
ethannicholas5961bc92016-10-12 06:39:56 -07001355 }
1356 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001357 case ASTSuffix::kCall_Kind: {
1358 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
1359 std::vector<std::unique_ptr<Expression>> arguments;
1360 for (size_t i = 0; i < rawArguments->size(); i++) {
1361 std::unique_ptr<Expression> converted =
1362 this->convertExpression(*(*rawArguments)[i]);
1363 if (!converted) {
1364 return nullptr;
1365 }
1366 arguments.push_back(std::move(converted));
1367 }
1368 return this->call(expression.fPosition, std::move(base), std::move(arguments));
1369 }
1370 case ASTSuffix::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001371 switch (base->fType.kind()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001372 case Type::kVector_Kind:
1373 return this->convertSwizzle(std::move(base),
1374 ((ASTFieldSuffix&) *expression.fSuffix).fField);
1375 case Type::kStruct_Kind:
1376 return this->convertField(std::move(base),
1377 ((ASTFieldSuffix&) *expression.fSuffix).fField);
1378 default:
1379 fErrors.error(base->fPosition, "cannot swizzle value of type '" +
ethannicholasd598f792016-07-25 10:08:54 -07001380 base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001381 return nullptr;
1382 }
1383 }
1384 case ASTSuffix::kPostIncrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07001385 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001386 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001387 "'++' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001388 return nullptr;
1389 }
1390 this->markWrittenTo(*base);
1391 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1392 Token::PLUSPLUS));
1393 case ASTSuffix::kPostDecrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07001394 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001395 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001396 "'--' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001397 return nullptr;
1398 }
1399 this->markWrittenTo(*base);
1400 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1401 Token::MINUSMINUS));
1402 default:
1403 ABORT("unsupported suffix operator");
1404 }
1405}
1406
1407void IRGenerator::checkValid(const Expression& expr) {
1408 switch (expr.fKind) {
1409 case Expression::kFunctionReference_Kind:
1410 fErrors.error(expr.fPosition, "expected '(' to begin function call");
1411 break;
1412 case Expression::kTypeReference_Kind:
1413 fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
1414 break;
1415 default:
ethannicholasea4567c2016-10-17 11:24:37 -07001416 if (expr.fType == *fContext.fInvalid_Type) {
1417 fErrors.error(expr.fPosition, "invalid expression");
1418 }
ethannicholasb3058bd2016-07-01 08:22:01 -07001419 }
1420}
1421
ethannicholasd598f792016-07-25 10:08:54 -07001422void IRGenerator::markReadFrom(const Variable& var) {
1423 var.fIsReadFrom = true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001424}
1425
1426static bool has_duplicates(const Swizzle& swizzle) {
1427 int bits = 0;
1428 for (int idx : swizzle.fComponents) {
1429 ASSERT(idx >= 0 && idx <= 3);
1430 int bit = 1 << idx;
1431 if (bits & bit) {
1432 return true;
1433 }
1434 bits |= bit;
1435 }
1436 return false;
1437}
1438
1439void IRGenerator::markWrittenTo(const Expression& expr) {
1440 switch (expr.fKind) {
1441 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001442 const Variable& var = ((VariableReference&) expr).fVariable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001443 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
1444 fErrors.error(expr.fPosition,
1445 "cannot modify immutable variable '" + var.fName + "'");
1446 }
1447 var.fIsWrittenTo = true;
1448 break;
1449 }
1450 case Expression::kFieldAccess_Kind:
1451 this->markWrittenTo(*((FieldAccess&) expr).fBase);
1452 break;
1453 case Expression::kSwizzle_Kind:
1454 if (has_duplicates((Swizzle&) expr)) {
1455 fErrors.error(expr.fPosition,
1456 "cannot write to the same swizzle field more than once");
1457 }
1458 this->markWrittenTo(*((Swizzle&) expr).fBase);
1459 break;
1460 case Expression::kIndex_Kind:
1461 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1462 break;
1463 default:
1464 fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'");
1465 break;
1466 }
1467}
1468
1469}