blob: db033d63b99836ee598a55cb8bc63b7213dc0f13 [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"
45#include "ir/SkSLVarDeclaration.h"
46#include "ir/SkSLVarDeclarationStatement.h"
47#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
ethannicholasd598f792016-07-25 10:08:54 -070069IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ethannicholasb3058bd2016-07-01 08:22:01 -070070 ErrorReporter& errorReporter)
ethannicholasd598f792016-07-25 10:08:54 -070071: fContext(*context)
72, fCurrentFunction(nullptr)
73, fSymbolTable(std::move(symbolTable))
74, fErrors(errorReporter) {}
ethannicholasb3058bd2016-07-01 08:22:01 -070075
76void IRGenerator::pushSymbolTable() {
77 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors));
78}
79
80void IRGenerator::popSymbolTable() {
81 fSymbolTable = fSymbolTable->fParent;
82}
83
84std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
85 return std::unique_ptr<Extension>(new Extension(extension.fPosition, extension.fName));
86}
87
88std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
89 switch (statement.fKind) {
90 case ASTStatement::kBlock_Kind:
91 return this->convertBlock((ASTBlock&) statement);
92 case ASTStatement::kVarDeclaration_Kind:
93 return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
94 case ASTStatement::kExpression_Kind:
95 return this->convertExpressionStatement((ASTExpressionStatement&) statement);
96 case ASTStatement::kIf_Kind:
97 return this->convertIf((ASTIfStatement&) statement);
98 case ASTStatement::kFor_Kind:
99 return this->convertFor((ASTForStatement&) statement);
100 case ASTStatement::kWhile_Kind:
101 return this->convertWhile((ASTWhileStatement&) statement);
102 case ASTStatement::kDo_Kind:
103 return this->convertDo((ASTDoStatement&) statement);
104 case ASTStatement::kReturn_Kind:
105 return this->convertReturn((ASTReturnStatement&) statement);
106 case ASTStatement::kBreak_Kind:
107 return this->convertBreak((ASTBreakStatement&) statement);
108 case ASTStatement::kContinue_Kind:
109 return this->convertContinue((ASTContinueStatement&) statement);
110 case ASTStatement::kDiscard_Kind:
111 return this->convertDiscard((ASTDiscardStatement&) statement);
112 default:
113 ABORT("unsupported statement type: %d\n", statement.fKind);
114 }
115}
116
117std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
118 AutoSymbolTable table(this);
119 std::vector<std::unique_ptr<Statement>> statements;
120 for (size_t i = 0; i < block.fStatements.size(); i++) {
121 std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
122 if (!statement) {
123 return nullptr;
124 }
125 statements.push_back(std::move(statement));
126 }
ethannicholasd598f792016-07-25 10:08:54 -0700127 return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700128}
129
130std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
131 const ASTVarDeclarationStatement& s) {
132 auto decl = this->convertVarDeclaration(*s.fDeclaration, Variable::kLocal_Storage);
133 if (!decl) {
134 return nullptr;
135 }
136 return std::unique_ptr<Statement>(new VarDeclarationStatement(std::move(decl)));
137}
138
139Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) {
140 return Modifiers(modifiers);
141}
142
143std::unique_ptr<VarDeclaration> IRGenerator::convertVarDeclaration(const ASTVarDeclaration& decl,
144 Variable::Storage storage) {
ethannicholasd598f792016-07-25 10:08:54 -0700145 std::vector<const Variable*> variables;
ethannicholasb3058bd2016-07-01 08:22:01 -0700146 std::vector<std::vector<std::unique_ptr<Expression>>> sizes;
147 std::vector<std::unique_ptr<Expression>> values;
ethannicholasd598f792016-07-25 10:08:54 -0700148 const Type* baseType = this->convertType(*decl.fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700149 if (!baseType) {
150 return nullptr;
151 }
152 for (size_t i = 0; i < decl.fNames.size(); i++) {
153 Modifiers modifiers = this->convertModifiers(decl.fModifiers);
ethannicholasd598f792016-07-25 10:08:54 -0700154 const Type* type = baseType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700155 ASSERT(type->kind() != Type::kArray_Kind);
156 std::vector<std::unique_ptr<Expression>> currentVarSizes;
157 for (size_t j = 0; j < decl.fSizes[i].size(); j++) {
158 if (decl.fSizes[i][j]) {
159 ASTExpression& rawSize = *decl.fSizes[i][j];
ethannicholasd598f792016-07-25 10:08:54 -0700160 auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700161 if (!size) {
162 return nullptr;
163 }
164 std::string name = type->fName;
165 uint64_t count;
166 if (size->fKind == Expression::kIntLiteral_Kind) {
167 count = ((IntLiteral&) *size).fValue;
168 if (count <= 0) {
169 fErrors.error(size->fPosition, "array size must be positive");
170 }
171 name += "[" + to_string(count) + "]";
172 } else {
173 count = -1;
174 name += "[]";
175 }
ethannicholasd598f792016-07-25 10:08:54 -0700176 type = new Type(name, Type::kArray_Kind, *type, (int) count);
177 fSymbolTable->takeOwnership((Type*) type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700178 currentVarSizes.push_back(std::move(size));
179 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700180 type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
181 fSymbolTable->takeOwnership((Type*) type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700182 currentVarSizes.push_back(nullptr);
183 }
184 }
ethannicholasd598f792016-07-25 10:08:54 -0700185 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, decl.fNames[i],
186 *type, storage));
ethannicholasb3058bd2016-07-01 08:22:01 -0700187 std::unique_ptr<Expression> value;
188 if (decl.fValues[i]) {
189 value = this->convertExpression(*decl.fValues[i]);
190 if (!value) {
191 return nullptr;
192 }
ethannicholasd598f792016-07-25 10:08:54 -0700193 value = this->coerce(std::move(value), *type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700194 }
ethannicholasf789b382016-08-03 12:43:36 -0700195 if ("gl_FragCoord" == decl.fNames[i] && (*fSymbolTable)[decl.fNames[i]]) {
196 // already defined, just update the modifiers
197 Variable* old = (Variable*) (*fSymbolTable)[decl.fNames[i]];
198 old->fModifiers = var->fModifiers;
199 } else {
200 variables.push_back(var.get());
201 fSymbolTable->add(decl.fNames[i], std::move(var));
202 values.push_back(std::move(value));
203 sizes.push_back(std::move(currentVarSizes));
204 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700205 }
ethannicholasf789b382016-08-03 12:43:36 -0700206 return std::unique_ptr<VarDeclaration>(new VarDeclaration(decl.fPosition,
207 baseType,
208 std::move(variables),
209 std::move(sizes),
210 std::move(values)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700211}
212
213std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
ethannicholasd598f792016-07-25 10:08:54 -0700214 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
215 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700216 if (!test) {
217 return nullptr;
218 }
219 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
220 if (!ifTrue) {
221 return nullptr;
222 }
223 std::unique_ptr<Statement> ifFalse;
224 if (s.fIfFalse) {
225 ifFalse = this->convertStatement(*s.fIfFalse);
226 if (!ifFalse) {
227 return nullptr;
228 }
229 }
230 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
231 std::move(ifTrue), std::move(ifFalse)));
232}
233
234std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
235 AutoSymbolTable table(this);
236 std::unique_ptr<Statement> initializer = this->convertStatement(*f.fInitializer);
237 if (!initializer) {
238 return nullptr;
239 }
ethannicholasd598f792016-07-25 10:08:54 -0700240 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.fTest),
241 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700242 if (!test) {
243 return nullptr;
244 }
245 std::unique_ptr<Expression> next = this->convertExpression(*f.fNext);
246 if (!next) {
247 return nullptr;
248 }
249 this->checkValid(*next);
250 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
251 if (!statement) {
252 return nullptr;
253 }
254 return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
255 std::move(test), std::move(next),
ethannicholasd598f792016-07-25 10:08:54 -0700256 std::move(statement), fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700257}
258
259std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
ethannicholasd598f792016-07-25 10:08:54 -0700260 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
261 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700262 if (!test) {
263 return nullptr;
264 }
265 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
266 if (!statement) {
267 return nullptr;
268 }
269 return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move(test),
270 std::move(statement)));
271}
272
273std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
ethannicholasd598f792016-07-25 10:08:54 -0700274 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
275 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700276 if (!test) {
277 return nullptr;
278 }
279 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
280 if (!statement) {
281 return nullptr;
282 }
283 return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
284 std::move(test)));
285}
286
287std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
288 const ASTExpressionStatement& s) {
289 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
290 if (!e) {
291 return nullptr;
292 }
293 this->checkValid(*e);
294 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
295}
296
297std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
298 ASSERT(fCurrentFunction);
299 if (r.fExpression) {
300 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
301 if (!result) {
302 return nullptr;
303 }
ethannicholasd598f792016-07-25 10:08:54 -0700304 if (fCurrentFunction->fReturnType == *fContext.fVoid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700305 fErrors.error(result->fPosition, "may not return a value from a void function");
306 } else {
307 result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
308 if (!result) {
309 return nullptr;
310 }
311 }
312 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
313 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700314 if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700315 fErrors.error(r.fPosition, "expected function to return '" +
ethannicholasd598f792016-07-25 10:08:54 -0700316 fCurrentFunction->fReturnType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700317 }
318 return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
319 }
320}
321
322std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
323 return std::unique_ptr<Statement>(new BreakStatement(b.fPosition));
324}
325
326std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
327 return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition));
328}
329
330std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
331 return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
332}
333
ethannicholasd598f792016-07-25 10:08:54 -0700334static const Type& expand_generics(const Type& type, int i) {
335 if (type.kind() == Type::kGeneric_Kind) {
336 return *type.coercibleTypes()[i];
ethannicholasb3058bd2016-07-01 08:22:01 -0700337 }
338 return type;
339}
340
ethannicholasd598f792016-07-25 10:08:54 -0700341static void expand_generics(const FunctionDeclaration& decl,
342 std::shared_ptr<SymbolTable> symbolTable) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700343 for (int i = 0; i < 4; i++) {
ethannicholasd598f792016-07-25 10:08:54 -0700344 const Type& returnType = expand_generics(decl.fReturnType, i);
345 std::vector<const Variable*> parameters;
ethannicholasb3058bd2016-07-01 08:22:01 -0700346 for (const auto& p : decl.fParameters) {
ethannicholasd598f792016-07-25 10:08:54 -0700347 Variable* var = new Variable(p->fPosition, Modifiers(p->fModifiers), p->fName,
348 expand_generics(p->fType, i),
349 Variable::kParameter_Storage);
350 symbolTable->takeOwnership(var);
351 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700352 }
ethannicholasd598f792016-07-25 10:08:54 -0700353 symbolTable->add(decl.fName, std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(
354 decl.fPosition,
355 decl.fName,
356 std::move(parameters),
357 std::move(returnType))));
ethannicholasb3058bd2016-07-01 08:22:01 -0700358 }
359}
360
361std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700362 bool isGeneric;
ethannicholasd598f792016-07-25 10:08:54 -0700363 const Type* returnType = this->convertType(*f.fReturnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700364 if (!returnType) {
365 return nullptr;
366 }
367 isGeneric = returnType->kind() == Type::kGeneric_Kind;
ethannicholasd598f792016-07-25 10:08:54 -0700368 std::vector<const Variable*> parameters;
ethannicholasb3058bd2016-07-01 08:22:01 -0700369 for (const auto& param : f.fParameters) {
ethannicholasd598f792016-07-25 10:08:54 -0700370 const Type* type = this->convertType(*param->fType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700371 if (!type) {
372 return nullptr;
373 }
374 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
375 int size = param->fSizes[j];
376 std::string name = type->name() + "[" + to_string(size) + "]";
ethannicholasd598f792016-07-25 10:08:54 -0700377 Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
378 fSymbolTable->takeOwnership(newType);
379 type = newType;
ethannicholasb3058bd2016-07-01 08:22:01 -0700380 }
381 std::string name = param->fName;
382 Modifiers modifiers = this->convertModifiers(param->fModifiers);
383 Position pos = param->fPosition;
ethannicholasd598f792016-07-25 10:08:54 -0700384 Variable* var = new Variable(pos, modifiers, std::move(name), *type,
385 Variable::kParameter_Storage);
386 fSymbolTable->takeOwnership(var);
387 parameters.push_back(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700388 isGeneric |= type->kind() == Type::kGeneric_Kind;
389 }
390
391 // find existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700392 const FunctionDeclaration* decl = nullptr;
393 auto entry = (*fSymbolTable)[f.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700394 if (entry) {
ethannicholasd598f792016-07-25 10:08:54 -0700395 std::vector<const FunctionDeclaration*> functions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700396 switch (entry->fKind) {
397 case Symbol::kUnresolvedFunction_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700398 functions = ((UnresolvedFunction*) entry)->fFunctions;
ethannicholasb3058bd2016-07-01 08:22:01 -0700399 break;
400 case Symbol::kFunctionDeclaration_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700401 functions.push_back((FunctionDeclaration*) entry);
ethannicholasb3058bd2016-07-01 08:22:01 -0700402 break;
403 default:
404 fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
405 return nullptr;
406 }
407 for (const auto& other : functions) {
408 ASSERT(other->fName == f.fName);
409 if (parameters.size() == other->fParameters.size()) {
410 bool match = true;
411 for (size_t i = 0; i < parameters.size(); i++) {
412 if (parameters[i]->fType != other->fParameters[i]->fType) {
413 match = false;
414 break;
415 }
416 }
417 if (match) {
ethannicholasd598f792016-07-25 10:08:54 -0700418 if (*returnType != other->fReturnType) {
419 FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700420 fErrors.error(f.fPosition, "functions '" + newDecl.description() +
421 "' and '" + other->description() +
422 "' differ only in return type");
423 return nullptr;
424 }
425 decl = other;
426 for (size_t i = 0; i < parameters.size(); i++) {
427 if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
428 fErrors.error(f.fPosition, "modifiers on parameter " +
429 to_string(i + 1) + " differ between " +
430 "declaration and definition");
431 return nullptr;
432 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700433 }
434 if (other->fDefined) {
435 fErrors.error(f.fPosition, "duplicate definition of " +
436 other->description());
437 }
438 break;
439 }
440 }
441 }
442 }
443 if (!decl) {
444 // couldn't find an existing declaration
ethannicholasd598f792016-07-25 10:08:54 -0700445 if (isGeneric) {
446 ASSERT(!f.fBody);
447 expand_generics(FunctionDeclaration(f.fPosition, f.fName, parameters, *returnType),
448 fSymbolTable);
449 } else {
450 auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(
451 f.fPosition,
452 f.fName,
453 parameters,
454 *returnType));
455 decl = newDecl.get();
456 fSymbolTable->add(decl->fName, std::move(newDecl));
ethannicholasb3058bd2016-07-01 08:22:01 -0700457 }
458 }
ethannicholasd598f792016-07-25 10:08:54 -0700459 if (f.fBody) {
460 ASSERT(!fCurrentFunction);
461 fCurrentFunction = decl;
462 decl->fDefined = true;
463 std::shared_ptr<SymbolTable> old = fSymbolTable;
464 AutoSymbolTable table(this);
465 for (size_t i = 0; i < parameters.size(); i++) {
466 fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
ethannicholasb3058bd2016-07-01 08:22:01 -0700467 }
ethannicholasd598f792016-07-25 10:08:54 -0700468 std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
469 fCurrentFunction = nullptr;
470 if (!body) {
471 return nullptr;
472 }
473 return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
474 std::move(body)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700475 }
476 return nullptr;
477}
478
479std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
480 std::shared_ptr<SymbolTable> old = fSymbolTable;
481 AutoSymbolTable table(this);
482 Modifiers mods = this->convertModifiers(intf.fModifiers);
483 std::vector<Type::Field> fields;
484 for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
485 std::unique_ptr<VarDeclaration> decl = this->convertVarDeclaration(
486 *intf.fDeclarations[i],
487 Variable::kGlobal_Storage);
488 for (size_t j = 0; j < decl->fVars.size(); j++) {
489 fields.push_back(Type::Field(decl->fVars[j]->fModifiers, decl->fVars[j]->fName,
490 decl->fVars[j]->fType));
491 if (decl->fValues[j]) {
492 fErrors.error(decl->fPosition,
493 "initializers are not permitted on interface block fields");
494 }
495 if (decl->fVars[j]->fModifiers.fFlags & (Modifiers::kIn_Flag |
496 Modifiers::kOut_Flag |
497 Modifiers::kUniform_Flag |
498 Modifiers::kConst_Flag)) {
499 fErrors.error(decl->fPosition,
500 "interface block fields may not have storage qualifiers");
501 }
502 }
503 }
ethannicholasd598f792016-07-25 10:08:54 -0700504 Type* type = new Type(intf.fInterfaceName, fields);
505 fSymbolTable->takeOwnership(type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700506 std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fInterfaceName;
ethannicholasd598f792016-07-25 10:08:54 -0700507 Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage);
508 fSymbolTable->takeOwnership(var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700509 if (intf.fValueName.length()) {
ethannicholasd598f792016-07-25 10:08:54 -0700510 old->addWithoutOwnership(intf.fValueName, var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700511 } else {
512 for (size_t i = 0; i < fields.size(); i++) {
ethannicholasd598f792016-07-25 10:08:54 -0700513 old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
514 (int) i)));
ethannicholasb3058bd2016-07-01 08:22:01 -0700515 }
516 }
ethannicholasd598f792016-07-25 10:08:54 -0700517 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, fSymbolTable));
ethannicholasb3058bd2016-07-01 08:22:01 -0700518}
519
ethannicholasd598f792016-07-25 10:08:54 -0700520const Type* IRGenerator::convertType(const ASTType& type) {
521 const Symbol* result = (*fSymbolTable)[type.fName];
ethannicholasb3058bd2016-07-01 08:22:01 -0700522 if (result && result->fKind == Symbol::kType_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -0700523 return (const Type*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700524 }
525 fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
526 return nullptr;
527}
528
529std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
530 switch (expr.fKind) {
531 case ASTExpression::kIdentifier_Kind:
532 return this->convertIdentifier((ASTIdentifier&) expr);
533 case ASTExpression::kBool_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700534 return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700535 ((ASTBoolLiteral&) expr).fValue));
536 case ASTExpression::kInt_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700537 return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700538 ((ASTIntLiteral&) expr).fValue));
539 case ASTExpression::kFloat_Kind:
ethannicholasd598f792016-07-25 10:08:54 -0700540 return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700541 ((ASTFloatLiteral&) expr).fValue));
542 case ASTExpression::kBinary_Kind:
543 return this->convertBinaryExpression((ASTBinaryExpression&) expr);
544 case ASTExpression::kPrefix_Kind:
545 return this->convertPrefixExpression((ASTPrefixExpression&) expr);
546 case ASTExpression::kSuffix_Kind:
547 return this->convertSuffixExpression((ASTSuffixExpression&) expr);
548 case ASTExpression::kTernary_Kind:
549 return this->convertTernaryExpression((ASTTernaryExpression&) expr);
550 default:
551 ABORT("unsupported expression type: %d\n", expr.fKind);
552 }
553}
554
555std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
ethannicholasd598f792016-07-25 10:08:54 -0700556 const Symbol* result = (*fSymbolTable)[identifier.fText];
ethannicholasb3058bd2016-07-01 08:22:01 -0700557 if (!result) {
558 fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'");
559 return nullptr;
560 }
561 switch (result->fKind) {
562 case Symbol::kFunctionDeclaration_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700563 std::vector<const FunctionDeclaration*> f = {
564 (const FunctionDeclaration*) result
ethannicholasb3058bd2016-07-01 08:22:01 -0700565 };
ethannicholasd598f792016-07-25 10:08:54 -0700566 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
567 identifier.fPosition,
568 f));
ethannicholasb3058bd2016-07-01 08:22:01 -0700569 }
570 case Symbol::kUnresolvedFunction_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700571 const UnresolvedFunction* f = (const UnresolvedFunction*) result;
572 return std::unique_ptr<FunctionReference>(new FunctionReference(fContext,
573 identifier.fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -0700574 f->fFunctions));
575 }
576 case Symbol::kVariable_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700577 const Variable* var = (const Variable*) result;
578 this->markReadFrom(*var);
ethannicholasb3058bd2016-07-01 08:22:01 -0700579 return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -0700580 *var));
ethannicholasb3058bd2016-07-01 08:22:01 -0700581 }
582 case Symbol::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700583 const Field* field = (const Field*) result;
ethannicholasb3058bd2016-07-01 08:22:01 -0700584 VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner);
ethannicholasf789b382016-08-03 12:43:36 -0700585 return std::unique_ptr<Expression>(new FieldAccess(
586 std::unique_ptr<Expression>(base),
587 field->fFieldIndex,
588 FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
ethannicholasb3058bd2016-07-01 08:22:01 -0700589 }
590 case Symbol::kType_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -0700591 const Type* t = (const Type*) result;
592 return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
593 *t));
ethannicholasb3058bd2016-07-01 08:22:01 -0700594 }
595 default:
596 ABORT("unsupported symbol type %d\n", result->fKind);
597 }
598
599}
600
601std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
ethannicholasd598f792016-07-25 10:08:54 -0700602 const Type& type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700603 if (!expr) {
604 return nullptr;
605 }
ethannicholasd598f792016-07-25 10:08:54 -0700606 if (expr->fType == type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700607 return expr;
608 }
609 this->checkValid(*expr);
ethannicholasd598f792016-07-25 10:08:54 -0700610 if (expr->fType == *fContext.fInvalid_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700611 return nullptr;
612 }
ethannicholasd598f792016-07-25 10:08:54 -0700613 if (!expr->fType.canCoerceTo(type)) {
614 fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
615 expr->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700616 return nullptr;
617 }
ethannicholasd598f792016-07-25 10:08:54 -0700618 if (type.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700619 std::vector<std::unique_ptr<Expression>> args;
620 args.push_back(std::move(expr));
ethannicholasd598f792016-07-25 10:08:54 -0700621 ASTIdentifier id(Position(), type.description());
ethannicholasb3058bd2016-07-01 08:22:01 -0700622 std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
623 ASSERT(ctor);
624 return this->call(Position(), std::move(ctor), std::move(args));
625 }
ethannicholasd598f792016-07-25 10:08:54 -0700626 ABORT("cannot coerce %s to %s", expr->fType.description().c_str(),
627 type.description().c_str());
ethannicholasb3058bd2016-07-01 08:22:01 -0700628}
629
ethannicholasf789b382016-08-03 12:43:36 -0700630static bool is_matrix_multiply(const Type& left, const Type& right) {
631 if (left.kind() == Type::kMatrix_Kind) {
632 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind;
633 }
634 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
635}
ethannicholasb3058bd2016-07-01 08:22:01 -0700636/**
637 * Determines the operand and result types of a binary expression. Returns true if the expression is
638 * legal, false otherwise. If false, the values of the out parameters are undefined.
639 */
ethannicholasd598f792016-07-25 10:08:54 -0700640static bool determine_binary_type(const Context& context,
641 Token::Kind op,
642 const Type& left,
643 const Type& right,
644 const Type** outLeftType,
645 const Type** outRightType,
646 const Type** outResultType,
ethannicholasb3058bd2016-07-01 08:22:01 -0700647 bool tryFlipped) {
648 bool isLogical;
649 switch (op) {
650 case Token::EQEQ: // fall through
651 case Token::NEQ: // fall through
652 case Token::LT: // fall through
653 case Token::GT: // fall through
654 case Token::LTEQ: // fall through
655 case Token::GTEQ:
656 isLogical = true;
657 break;
658 case Token::LOGICALOR: // fall through
659 case Token::LOGICALAND: // fall through
660 case Token::LOGICALXOR: // fall through
661 case Token::LOGICALOREQ: // fall through
662 case Token::LOGICALANDEQ: // fall through
663 case Token::LOGICALXOREQ:
ethannicholasd598f792016-07-25 10:08:54 -0700664 *outLeftType = context.fBool_Type.get();
665 *outRightType = context.fBool_Type.get();
666 *outResultType = context.fBool_Type.get();
667 return left.canCoerceTo(*context.fBool_Type) &&
668 right.canCoerceTo(*context.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700669 case Token::STAR: // fall through
670 case Token::STAREQ:
ethannicholasf789b382016-08-03 12:43:36 -0700671 if (is_matrix_multiply(left, right)) {
672 // determine final component type
673 if (determine_binary_type(context, Token::STAR, left.componentType(),
674 right.componentType(), outLeftType, outRightType,
675 outResultType, false)) {
676 *outLeftType = &(*outResultType)->toCompound(context, left.columns(),
677 left.rows());;
678 *outRightType = &(*outResultType)->toCompound(context, right.columns(),
679 right.rows());;
680 int leftColumns = left.columns();
681 int leftRows = left.rows();
682 int rightColumns;
683 int rightRows;
684 if (right.kind() == Type::kVector_Kind) {
685 // matrix * vector treats the vector as a column vector, so we need to
686 // transpose it
687 rightColumns = right.rows();
688 rightRows = right.columns();
689 ASSERT(rightColumns == 1);
690 } else {
691 rightColumns = right.columns();
692 rightRows = right.rows();
693 }
694 if (rightColumns > 1) {
695 *outResultType = &(*outResultType)->toCompound(context, rightColumns,
696 leftRows);
697 } else {
698 // result was a column vector, transpose it back to a row
699 *outResultType = &(*outResultType)->toCompound(context, leftRows,
700 rightColumns);
701 }
702 return leftColumns == rightRows;
703 } else {
704 return false;
705 }
ethannicholasb3058bd2016-07-01 08:22:01 -0700706 }
707 // fall through
708 default:
709 isLogical = false;
710 }
711 // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have
712 // full support for numbers other than float.
713 if (left == right) {
ethannicholasd598f792016-07-25 10:08:54 -0700714 *outLeftType = &left;
715 *outRightType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -0700716 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -0700717 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700718 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700719 *outResultType = &left;
ethannicholasb3058bd2016-07-01 08:22:01 -0700720 }
721 return true;
722 }
723 // FIXME: incorrect for shift operations
ethannicholasd598f792016-07-25 10:08:54 -0700724 if (left.canCoerceTo(right)) {
725 *outLeftType = &right;
726 *outRightType = &right;
ethannicholasb3058bd2016-07-01 08:22:01 -0700727 if (isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -0700728 *outResultType = context.fBool_Type.get();
ethannicholasb3058bd2016-07-01 08:22:01 -0700729 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700730 *outResultType = &right;
ethannicholasb3058bd2016-07-01 08:22:01 -0700731 }
732 return true;
733 }
ethannicholasd598f792016-07-25 10:08:54 -0700734 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
735 (right.kind() == Type::kScalar_Kind)) {
736 if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
737 outRightType, outResultType, false)) {
738 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -0700739 if (!isLogical) {
ethannicholasd598f792016-07-25 10:08:54 -0700740 *outResultType = &(*outResultType)->toCompound(context, left.columns(),
741 left.rows());
ethannicholasb3058bd2016-07-01 08:22:01 -0700742 }
743 return true;
744 }
745 return false;
746 }
747 if (tryFlipped) {
ethannicholasd598f792016-07-25 10:08:54 -0700748 return determine_binary_type(context, op, right, left, outRightType, outLeftType,
749 outResultType, false);
ethannicholasb3058bd2016-07-01 08:22:01 -0700750 }
751 return false;
752}
753
754std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
755 const ASTBinaryExpression& expression) {
756 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
757 if (!left) {
758 return nullptr;
759 }
760 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
761 if (!right) {
762 return nullptr;
763 }
ethannicholasd598f792016-07-25 10:08:54 -0700764 const Type* leftType;
765 const Type* rightType;
766 const Type* resultType;
767 if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
ethannicholasb3058bd2016-07-01 08:22:01 -0700768 &rightType, &resultType, true)) {
769 fErrors.error(expression.fPosition, "type mismatch: '" +
770 Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -0700771 "' cannot operate on '" + left->fType.fName +
772 "', '" + right->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700773 return nullptr;
774 }
775 switch (expression.fOperator) {
776 case Token::EQ: // fall through
777 case Token::PLUSEQ: // fall through
778 case Token::MINUSEQ: // fall through
779 case Token::STAREQ: // fall through
780 case Token::SLASHEQ: // fall through
781 case Token::PERCENTEQ: // fall through
782 case Token::SHLEQ: // fall through
783 case Token::SHREQ: // fall through
784 case Token::BITWISEOREQ: // fall through
785 case Token::BITWISEXOREQ: // fall through
786 case Token::BITWISEANDEQ: // fall through
787 case Token::LOGICALOREQ: // fall through
788 case Token::LOGICALXOREQ: // fall through
789 case Token::LOGICALANDEQ:
790 this->markWrittenTo(*left);
791 default:
792 break;
793 }
794 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -0700795 this->coerce(std::move(left),
796 *leftType),
ethannicholasb3058bd2016-07-01 08:22:01 -0700797 expression.fOperator,
798 this->coerce(std::move(right),
ethannicholasd598f792016-07-25 10:08:54 -0700799 *rightType),
800 *resultType));
ethannicholasb3058bd2016-07-01 08:22:01 -0700801}
802
803std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
804 const ASTTernaryExpression& expression) {
805 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
ethannicholasd598f792016-07-25 10:08:54 -0700806 *fContext.fBool_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -0700807 if (!test) {
808 return nullptr;
809 }
810 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
811 if (!ifTrue) {
812 return nullptr;
813 }
814 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
815 if (!ifFalse) {
816 return nullptr;
817 }
ethannicholasd598f792016-07-25 10:08:54 -0700818 const Type* trueType;
819 const Type* falseType;
820 const Type* resultType;
821 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
ethannicholasb3058bd2016-07-01 08:22:01 -0700822 &falseType, &resultType, true)) {
823 fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
ethannicholasd598f792016-07-25 10:08:54 -0700824 ifTrue->fType.fName + "', '" +
825 ifFalse->fType.fName + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700826 return nullptr;
827 }
828 ASSERT(trueType == falseType);
ethannicholasd598f792016-07-25 10:08:54 -0700829 ifTrue = this->coerce(std::move(ifTrue), *trueType);
830 ifFalse = this->coerce(std::move(ifFalse), *falseType);
ethannicholasb3058bd2016-07-01 08:22:01 -0700831 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
832 std::move(test),
833 std::move(ifTrue),
834 std::move(ifFalse)));
835}
836
ethannicholasd598f792016-07-25 10:08:54 -0700837std::unique_ptr<Expression> IRGenerator::call(Position position,
838 const FunctionDeclaration& function,
839 std::vector<std::unique_ptr<Expression>> arguments) {
840 if (function.fParameters.size() != arguments.size()) {
841 std::string msg = "call to '" + function.fName + "' expected " +
842 to_string(function.fParameters.size()) +
ethannicholasb3058bd2016-07-01 08:22:01 -0700843 " argument";
ethannicholasd598f792016-07-25 10:08:54 -0700844 if (function.fParameters.size() != 1) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700845 msg += "s";
846 }
847 msg += ", but found " + to_string(arguments.size());
848 fErrors.error(position, msg);
849 return nullptr;
850 }
851 for (size_t i = 0; i < arguments.size(); i++) {
ethannicholasd598f792016-07-25 10:08:54 -0700852 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameters[i]->fType);
853 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700854 this->markWrittenTo(*arguments[i]);
855 }
856 }
ethannicholasd598f792016-07-25 10:08:54 -0700857 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function,
ethannicholasb3058bd2016-07-01 08:22:01 -0700858 std::move(arguments)));
859}
860
861/**
862 * Determines the cost of coercing the arguments of a function to the required types. Returns true
863 * if the cost could be computed, false if the call is not valid. Cost has no particular meaning
864 * other than "lower costs are preferred".
865 */
ethannicholasd598f792016-07-25 10:08:54 -0700866bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
ethannicholasb3058bd2016-07-01 08:22:01 -0700867 const std::vector<std::unique_ptr<Expression>>& arguments,
868 int* outCost) {
ethannicholasd598f792016-07-25 10:08:54 -0700869 if (function.fParameters.size() != arguments.size()) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700870 return false;
871 }
872 int total = 0;
873 for (size_t i = 0; i < arguments.size(); i++) {
874 int cost;
ethannicholasd598f792016-07-25 10:08:54 -0700875 if (arguments[i]->fType.determineCoercionCost(function.fParameters[i]->fType, &cost)) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700876 total += cost;
877 } else {
878 return false;
879 }
880 }
881 *outCost = total;
882 return true;
883}
884
885std::unique_ptr<Expression> IRGenerator::call(Position position,
886 std::unique_ptr<Expression> functionValue,
887 std::vector<std::unique_ptr<Expression>> arguments) {
888 if (functionValue->fKind == Expression::kTypeReference_Kind) {
889 return this->convertConstructor(position,
890 ((TypeReference&) *functionValue).fValue,
891 std::move(arguments));
892 }
893 if (functionValue->fKind != Expression::kFunctionReference_Kind) {
894 fErrors.error(position, "'" + functionValue->description() + "' is not a function");
895 return nullptr;
896 }
897 FunctionReference* ref = (FunctionReference*) functionValue.get();
898 int bestCost = INT_MAX;
ethannicholasd598f792016-07-25 10:08:54 -0700899 const FunctionDeclaration* best = nullptr;
ethannicholasb3058bd2016-07-01 08:22:01 -0700900 if (ref->fFunctions.size() > 1) {
901 for (const auto& f : ref->fFunctions) {
902 int cost;
ethannicholasd598f792016-07-25 10:08:54 -0700903 if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700904 bestCost = cost;
905 best = f;
906 }
907 }
908 if (best) {
ethannicholasd598f792016-07-25 10:08:54 -0700909 return this->call(position, *best, std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -0700910 }
911 std::string msg = "no match for " + ref->fFunctions[0]->fName + "(";
912 std::string separator = "";
913 for (size_t i = 0; i < arguments.size(); i++) {
914 msg += separator;
915 separator = ", ";
ethannicholasd598f792016-07-25 10:08:54 -0700916 msg += arguments[i]->fType.description();
ethannicholasb3058bd2016-07-01 08:22:01 -0700917 }
918 msg += ")";
919 fErrors.error(position, msg);
920 return nullptr;
921 }
ethannicholasd598f792016-07-25 10:08:54 -0700922 return this->call(position, *ref->fFunctions[0], std::move(arguments));
ethannicholasb3058bd2016-07-01 08:22:01 -0700923}
924
925std::unique_ptr<Expression> IRGenerator::convertConstructor(
926 Position position,
ethannicholasd598f792016-07-25 10:08:54 -0700927 const Type& type,
ethannicholasb3058bd2016-07-01 08:22:01 -0700928 std::vector<std::unique_ptr<Expression>> args) {
929 // FIXME: add support for structs and arrays
ethannicholasd598f792016-07-25 10:08:54 -0700930 Type::Kind kind = type.kind();
931 if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) {
932 fErrors.error(position, "cannot construct '" + type.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -0700933 return nullptr;
934 }
ethannicholasd598f792016-07-25 10:08:54 -0700935 if (type == *fContext.fFloat_Type && args.size() == 1 &&
ethannicholasb3058bd2016-07-01 08:22:01 -0700936 args[0]->fKind == Expression::kIntLiteral_Kind) {
937 int64_t value = ((IntLiteral&) *args[0]).fValue;
ethannicholasd598f792016-07-25 10:08:54 -0700938 return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
ethannicholasb3058bd2016-07-01 08:22:01 -0700939 }
940 if (args.size() == 1 && args[0]->fType == type) {
941 // argument is already the right type, just return it
942 return std::move(args[0]);
943 }
ethannicholasd598f792016-07-25 10:08:54 -0700944 if (type.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700945 if (args.size() != 1) {
ethannicholasd598f792016-07-25 10:08:54 -0700946 fErrors.error(position, "invalid arguments to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -0700947 "' constructor, (expected exactly 1 argument, but found " +
948 to_string(args.size()) + ")");
949 }
ethannicholasd598f792016-07-25 10:08:54 -0700950 if (args[0]->fType == *fContext.fBool_Type) {
951 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
952 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1));
ethannicholasb3058bd2016-07-01 08:22:01 -0700953 return std::unique_ptr<Expression>(
954 new TernaryExpression(position, std::move(args[0]),
955 this->coerce(std::move(one), type),
956 this->coerce(std::move(zero),
957 type)));
ethannicholasd598f792016-07-25 10:08:54 -0700958 } else if (!args[0]->fType.isNumber()) {
959 fErrors.error(position, "invalid argument to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -0700960 "' constructor (expected a number or bool, but found '" +
ethannicholasd598f792016-07-25 10:08:54 -0700961 args[0]->fType.description() + "')");
ethannicholasb3058bd2016-07-01 08:22:01 -0700962 }
963 } else {
964 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
965 int actual = 0;
966 for (size_t i = 0; i < args.size(); i++) {
ethannicholasd598f792016-07-25 10:08:54 -0700967 if (args[i]->fType.kind() == Type::kVector_Kind ||
968 args[i]->fType.kind() == Type::kMatrix_Kind) {
969 int columns = args[i]->fType.columns();
970 int rows = args[i]->fType.rows();
ethannicholasb3058bd2016-07-01 08:22:01 -0700971 args[i] = this->coerce(std::move(args[i]),
ethannicholasd598f792016-07-25 10:08:54 -0700972 type.componentType().toCompound(fContext, columns, rows));
973 actual += args[i]->fType.rows() * args[i]->fType.columns();
974 } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -0700975 actual += 1;
ethannicholasd598f792016-07-25 10:08:54 -0700976 if (type.kind() != Type::kScalar_Kind) {
977 args[i] = this->coerce(std::move(args[i]), type.componentType());
ethannicholasb3058bd2016-07-01 08:22:01 -0700978 }
979 } else {
ethannicholasd598f792016-07-25 10:08:54 -0700980 fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
981 "parameter to '" + type.description() + "' constructor");
ethannicholasb3058bd2016-07-01 08:22:01 -0700982 return nullptr;
983 }
984 }
ethannicholasd598f792016-07-25 10:08:54 -0700985 int min = type.rows() * type.columns();
986 int max = type.columns() > 1 ? INT_MAX : min;
ethannicholasb3058bd2016-07-01 08:22:01 -0700987 if ((actual < min || actual > max) &&
988 !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) {
ethannicholasd598f792016-07-25 10:08:54 -0700989 fErrors.error(position, "invalid arguments to '" + type.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -0700990 "' constructor (expected " + to_string(min) + " scalar" +
991 (min == 1 ? "" : "s") + ", but found " + to_string(actual) +
992 ")");
993 return nullptr;
994 }
995 }
996 return std::unique_ptr<Expression>(new Constructor(position, std::move(type), std::move(args)));
997}
998
999std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
1000 const ASTPrefixExpression& expression) {
1001 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
1002 if (!base) {
1003 return nullptr;
1004 }
1005 switch (expression.fOperator) {
1006 case Token::PLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001007 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001008 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001009 "'+' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001010 return nullptr;
1011 }
1012 return base;
1013 case Token::MINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001014 if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001015 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001016 "'-' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001017 return nullptr;
1018 }
1019 if (base->fKind == Expression::kIntLiteral_Kind) {
ethannicholasd598f792016-07-25 10:08:54 -07001020 return std::unique_ptr<Expression>(new IntLiteral(fContext, base->fPosition,
ethannicholasb3058bd2016-07-01 08:22:01 -07001021 -((IntLiteral&) *base).fValue));
1022 }
1023 if (base->fKind == Expression::kFloatLiteral_Kind) {
1024 double value = -((FloatLiteral&) *base).fValue;
ethannicholasd598f792016-07-25 10:08:54 -07001025 return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
1026 value));
ethannicholasb3058bd2016-07-01 08:22:01 -07001027 }
1028 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
1029 case Token::PLUSPLUS:
ethannicholasd598f792016-07-25 10:08:54 -07001030 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001031 fErrors.error(expression.fPosition,
1032 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001033 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001034 return nullptr;
1035 }
1036 this->markWrittenTo(*base);
1037 break;
1038 case Token::MINUSMINUS:
ethannicholasd598f792016-07-25 10:08:54 -07001039 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001040 fErrors.error(expression.fPosition,
1041 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001042 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001043 return nullptr;
1044 }
1045 this->markWrittenTo(*base);
1046 break;
1047 case Token::NOT:
ethannicholasd598f792016-07-25 10:08:54 -07001048 if (base->fType != *fContext.fBool_Type) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001049 fErrors.error(expression.fPosition,
1050 "'" + Token::OperatorName(expression.fOperator) +
ethannicholasd598f792016-07-25 10:08:54 -07001051 "' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001052 return nullptr;
1053 }
1054 break;
1055 default:
1056 ABORT("unsupported prefix operator\n");
1057 }
1058 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
1059 std::move(base)));
1060}
1061
1062std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
1063 const ASTExpression& index) {
ethannicholasd598f792016-07-25 10:08:54 -07001064 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind) {
1065 fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
ethannicholasb3058bd2016-07-01 08:22:01 -07001066 "'");
1067 return nullptr;
1068 }
1069 std::unique_ptr<Expression> converted = this->convertExpression(index);
1070 if (!converted) {
1071 return nullptr;
1072 }
ethannicholasd598f792016-07-25 10:08:54 -07001073 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001074 if (!converted) {
1075 return nullptr;
1076 }
ethannicholasd598f792016-07-25 10:08:54 -07001077 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
1078 std::move(converted)));
ethannicholasb3058bd2016-07-01 08:22:01 -07001079}
1080
1081std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
1082 const std::string& field) {
ethannicholasd598f792016-07-25 10:08:54 -07001083 auto fields = base->fType.fields();
ethannicholasb3058bd2016-07-01 08:22:01 -07001084 for (size_t i = 0; i < fields.size(); i++) {
1085 if (fields[i].fName == field) {
1086 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
1087 }
1088 }
ethannicholasd598f792016-07-25 10:08:54 -07001089 fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a "
ethannicholasb3058bd2016-07-01 08:22:01 -07001090 "field named '" + field + "");
1091 return nullptr;
1092}
1093
1094std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
1095 const std::string& fields) {
ethannicholasd598f792016-07-25 10:08:54 -07001096 if (base->fType.kind() != Type::kVector_Kind) {
1097 fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001098 return nullptr;
1099 }
1100 std::vector<int> swizzleComponents;
1101 for (char c : fields) {
1102 switch (c) {
1103 case 'x': // fall through
1104 case 'r': // fall through
1105 case 's':
1106 swizzleComponents.push_back(0);
1107 break;
1108 case 'y': // fall through
1109 case 'g': // fall through
1110 case 't':
ethannicholasd598f792016-07-25 10:08:54 -07001111 if (base->fType.columns() >= 2) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001112 swizzleComponents.push_back(1);
1113 break;
1114 }
1115 // fall through
1116 case 'z': // fall through
1117 case 'b': // fall through
1118 case 'p':
ethannicholasd598f792016-07-25 10:08:54 -07001119 if (base->fType.columns() >= 3) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001120 swizzleComponents.push_back(2);
1121 break;
1122 }
1123 // fall through
1124 case 'w': // fall through
1125 case 'a': // fall through
1126 case 'q':
ethannicholasd598f792016-07-25 10:08:54 -07001127 if (base->fType.columns() >= 4) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001128 swizzleComponents.push_back(3);
1129 break;
1130 }
1131 // fall through
1132 default:
1133 fErrors.error(base->fPosition, "invalid swizzle component '" + std::string(1, c) +
1134 "'");
1135 return nullptr;
1136 }
1137 }
1138 ASSERT(swizzleComponents.size() > 0);
1139 if (swizzleComponents.size() > 4) {
1140 fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'");
1141 return nullptr;
1142 }
ethannicholasd598f792016-07-25 10:08:54 -07001143 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), swizzleComponents));
ethannicholasb3058bd2016-07-01 08:22:01 -07001144}
1145
1146std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1147 const ASTSuffixExpression& expression) {
1148 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
1149 if (!base) {
1150 return nullptr;
1151 }
1152 switch (expression.fSuffix->fKind) {
1153 case ASTSuffix::kIndex_Kind:
1154 return this->convertIndex(std::move(base),
1155 *((ASTIndexSuffix&) *expression.fSuffix).fExpression);
1156 case ASTSuffix::kCall_Kind: {
1157 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
1158 std::vector<std::unique_ptr<Expression>> arguments;
1159 for (size_t i = 0; i < rawArguments->size(); i++) {
1160 std::unique_ptr<Expression> converted =
1161 this->convertExpression(*(*rawArguments)[i]);
1162 if (!converted) {
1163 return nullptr;
1164 }
1165 arguments.push_back(std::move(converted));
1166 }
1167 return this->call(expression.fPosition, std::move(base), std::move(arguments));
1168 }
1169 case ASTSuffix::kField_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001170 switch (base->fType.kind()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001171 case Type::kVector_Kind:
1172 return this->convertSwizzle(std::move(base),
1173 ((ASTFieldSuffix&) *expression.fSuffix).fField);
1174 case Type::kStruct_Kind:
1175 return this->convertField(std::move(base),
1176 ((ASTFieldSuffix&) *expression.fSuffix).fField);
1177 default:
1178 fErrors.error(base->fPosition, "cannot swizzle value of type '" +
ethannicholasd598f792016-07-25 10:08:54 -07001179 base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001180 return nullptr;
1181 }
1182 }
1183 case ASTSuffix::kPostIncrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07001184 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001185 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001186 "'++' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001187 return nullptr;
1188 }
1189 this->markWrittenTo(*base);
1190 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1191 Token::PLUSPLUS));
1192 case ASTSuffix::kPostDecrement_Kind:
ethannicholasd598f792016-07-25 10:08:54 -07001193 if (!base->fType.isNumber()) {
ethannicholasb3058bd2016-07-01 08:22:01 -07001194 fErrors.error(expression.fPosition,
ethannicholasd598f792016-07-25 10:08:54 -07001195 "'--' cannot operate on '" + base->fType.description() + "'");
ethannicholasb3058bd2016-07-01 08:22:01 -07001196 return nullptr;
1197 }
1198 this->markWrittenTo(*base);
1199 return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
1200 Token::MINUSMINUS));
1201 default:
1202 ABORT("unsupported suffix operator");
1203 }
1204}
1205
1206void IRGenerator::checkValid(const Expression& expr) {
1207 switch (expr.fKind) {
1208 case Expression::kFunctionReference_Kind:
1209 fErrors.error(expr.fPosition, "expected '(' to begin function call");
1210 break;
1211 case Expression::kTypeReference_Kind:
1212 fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
1213 break;
1214 default:
ethannicholasd598f792016-07-25 10:08:54 -07001215 ASSERT(expr.fType != *fContext.fInvalid_Type);
ethannicholasb3058bd2016-07-01 08:22:01 -07001216 break;
1217 }
1218}
1219
ethannicholasd598f792016-07-25 10:08:54 -07001220void IRGenerator::markReadFrom(const Variable& var) {
1221 var.fIsReadFrom = true;
ethannicholasb3058bd2016-07-01 08:22:01 -07001222}
1223
1224static bool has_duplicates(const Swizzle& swizzle) {
1225 int bits = 0;
1226 for (int idx : swizzle.fComponents) {
1227 ASSERT(idx >= 0 && idx <= 3);
1228 int bit = 1 << idx;
1229 if (bits & bit) {
1230 return true;
1231 }
1232 bits |= bit;
1233 }
1234 return false;
1235}
1236
1237void IRGenerator::markWrittenTo(const Expression& expr) {
1238 switch (expr.fKind) {
1239 case Expression::kVariableReference_Kind: {
ethannicholasd598f792016-07-25 10:08:54 -07001240 const Variable& var = ((VariableReference&) expr).fVariable;
ethannicholasb3058bd2016-07-01 08:22:01 -07001241 if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
1242 fErrors.error(expr.fPosition,
1243 "cannot modify immutable variable '" + var.fName + "'");
1244 }
1245 var.fIsWrittenTo = true;
1246 break;
1247 }
1248 case Expression::kFieldAccess_Kind:
1249 this->markWrittenTo(*((FieldAccess&) expr).fBase);
1250 break;
1251 case Expression::kSwizzle_Kind:
1252 if (has_duplicates((Swizzle&) expr)) {
1253 fErrors.error(expr.fPosition,
1254 "cannot write to the same swizzle field more than once");
1255 }
1256 this->markWrittenTo(*((Swizzle&) expr).fBase);
1257 break;
1258 case Expression::kIndex_Kind:
1259 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1260 break;
1261 default:
1262 fErrors.error(expr.fPosition, "cannot assign to '" + expr.description() + "'");
1263 break;
1264 }
1265}
1266
1267}