OLD | NEW |
---|---|
(Empty) | |
1 /* | |
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 | |
50 namespace SkSL { | |
51 | |
52 class AutoSymbolTable { | |
53 public: | |
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 | |
69 IRGenerator::IRGenerator(std::shared_ptr<SymbolTable> symbolTable, | |
70 ErrorReporter& errorReporter) | |
71 : fSymbolTable(std::move(symbolTable)) | |
72 , fErrors(errorReporter) { | |
73 } | |
74 | |
75 void IRGenerator::pushSymbolTable() { | |
76 fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors)); | |
77 } | |
78 | |
79 void IRGenerator::popSymbolTable() { | |
80 fSymbolTable = fSymbolTable->fParent; | |
81 } | |
82 | |
83 std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& ext ension) { | |
84 return std::unique_ptr<Extension>(new Extension(extension.fPosition, extensi on.fName)); | |
85 } | |
86 | |
87 std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& sta tement) { | |
88 switch (statement.fKind) { | |
89 case ASTStatement::kBlock_Kind: | |
90 return this->convertBlock((ASTBlock&) statement); | |
91 case ASTStatement::kVarDeclaration_Kind: | |
92 return this->convertVarDeclarationStatement((ASTVarDeclarationStatem ent&) statement); | |
93 case ASTStatement::kExpression_Kind: | |
94 return this->convertExpressionStatement((ASTExpressionStatement&) st atement); | |
95 case ASTStatement::kIf_Kind: | |
96 return this->convertIf((ASTIfStatement&) statement); | |
97 case ASTStatement::kFor_Kind: | |
98 return this->convertFor((ASTForStatement&) statement); | |
99 case ASTStatement::kWhile_Kind: | |
100 return this->convertWhile((ASTWhileStatement&) statement); | |
101 case ASTStatement::kDo_Kind: | |
102 return this->convertDo((ASTDoStatement&) statement); | |
103 case ASTStatement::kReturn_Kind: | |
104 return this->convertReturn((ASTReturnStatement&) statement); | |
105 case ASTStatement::kBreak_Kind: | |
106 return this->convertBreak((ASTBreakStatement&) statement); | |
107 case ASTStatement::kContinue_Kind: | |
108 return this->convertContinue((ASTContinueStatement&) statement); | |
109 case ASTStatement::kDiscard_Kind: | |
110 return this->convertDiscard((ASTDiscardStatement&) statement); | |
111 default: | |
112 ABORT("unsupported statement type: %d\n", statement.fKind); | |
113 } | |
114 } | |
115 | |
116 std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) { | |
117 AutoSymbolTable table(this); | |
118 std::vector<std::unique_ptr<Statement>> statements; | |
119 for (size_t i = 0; i < block.fStatements.size(); i++) { | |
120 std::unique_ptr<Statement> statement = this->convertStatement(*block.fSt atements[i]); | |
121 if (!statement) { | |
122 return nullptr; | |
123 } | |
124 statements.push_back(std::move(statement)); | |
125 } | |
126 return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statement s))); | |
127 } | |
128 | |
129 std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement( | |
130 const ASTVarDeclar ationStatement& s) { | |
131 auto decl = this->convertVarDeclaration(*s.fDeclaration, Variable::kLocal_St orage); | |
132 if (!decl) { | |
133 return nullptr; | |
134 } | |
135 return std::unique_ptr<Statement>(new VarDeclarationStatement(std::move(decl ))); | |
136 } | |
137 | |
138 Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) { | |
139 return Modifiers(modifiers); | |
140 } | |
141 | |
142 std::unique_ptr<VarDeclaration> IRGenerator::convertVarDeclaration(const ASTVarD eclaration& decl, | |
143 Variable::Sto rage storage) { | |
144 std::vector<std::shared_ptr<Variable>> variables; | |
145 std::vector<std::vector<std::unique_ptr<Expression>>> sizes; | |
146 std::vector<std::unique_ptr<Expression>> values; | |
147 std::shared_ptr<Type> baseType = this->convertType(*decl.fType); | |
148 if (!baseType) { | |
149 return nullptr; | |
150 } | |
151 for (size_t i = 0; i < decl.fNames.size(); i++) { | |
152 Modifiers modifiers = this->convertModifiers(decl.fModifiers); | |
153 std::shared_ptr<Type> type = baseType; | |
154 ASSERT(type->kind() != Type::kArray_Kind); | |
155 std::vector<std::unique_ptr<Expression>> currentVarSizes; | |
156 for (size_t j = 0; j < decl.fSizes[i].size(); j++) { | |
157 if (decl.fSizes[i][j]) { | |
158 ASTExpression& rawSize = *decl.fSizes[i][j]; | |
159 auto size = this->coerce(this->convertExpression(rawSize), kInt_ Type); | |
160 if (!size) { | |
161 return nullptr; | |
162 } | |
163 std::string name = type->fName; | |
164 uint64_t count; | |
165 if (size->fKind == Expression::kIntLiteral_Kind) { | |
166 count = ((IntLiteral&) *size).fValue; | |
167 if (count <= 0) { | |
168 fErrors.error(size->fPosition, "array size must be posit ive"); | |
169 } | |
170 name += "[" + to_string(count) + "]"; | |
171 } else { | |
172 count = -1; | |
173 name += "[]"; | |
174 } | |
175 type = std::shared_ptr<Type>(new Type(name, Type::kArray_Kind, t ype, (int) count)); | |
176 currentVarSizes.push_back(std::move(size)); | |
177 } else { | |
178 type = std::shared_ptr<Type>(new Type(type->fName + "[]", Type:: kArray_Kind, type, | |
179 -1)); | |
180 currentVarSizes.push_back(nullptr); | |
181 } | |
182 } | |
183 sizes.push_back(std::move(currentVarSizes)); | |
184 auto var = std::make_shared<Variable>(decl.fPosition, modifiers, decl.fN ames[i], type, | |
185 storage); | |
186 variables.push_back(var); | |
187 std::unique_ptr<Expression> value; | |
188 if (decl.fValues[i]) { | |
189 value = this->convertExpression(*decl.fValues[i]); | |
190 if (!value) { | |
191 return nullptr; | |
192 } | |
193 value = this->coerce(std::move(value), type); | |
194 } | |
195 fSymbolTable->add(var->fName, var); | |
196 values.push_back(std::move(value)); | |
197 } | |
198 return std::unique_ptr<VarDeclaration>(new VarDeclaration(decl.fPosition, st d::move(variables), | |
199 std::move(sizes), std::move(values))); | |
200 } | |
201 | |
202 std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) { | |
203 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.f Test), kBool_Type); | |
204 if (!test) { | |
205 return nullptr; | |
206 } | |
207 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue); | |
208 if (!ifTrue) { | |
209 return nullptr; | |
210 } | |
211 std::unique_ptr<Statement> ifFalse; | |
212 if (s.fIfFalse) { | |
213 ifFalse = this->convertStatement(*s.fIfFalse); | |
214 if (!ifFalse) { | |
215 return nullptr; | |
216 } | |
217 } | |
218 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t), | |
219 std::move(ifTrue), std::mo ve(ifFalse))); | |
220 } | |
221 | |
222 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { | |
223 AutoSymbolTable table(this); | |
224 std::unique_ptr<Statement> initializer = this->convertStatement(*f.fInitiali zer); | |
225 if (!initializer) { | |
226 return nullptr; | |
227 } | |
228 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.f Test), kBool_Type); | |
229 if (!test) { | |
230 return nullptr; | |
231 } | |
232 std::unique_ptr<Expression> next = this->convertExpression(*f.fNext); | |
233 if (!next) { | |
234 return nullptr; | |
235 } | |
236 this->checkValid(*next); | |
237 std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement) ; | |
238 if (!statement) { | |
239 return nullptr; | |
240 } | |
241 return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(in itializer), | |
242 std::move(test), std::mov e(next), | |
243 std::move(statement))); | |
244 } | |
245 | |
246 std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) { | |
247 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.f Test), kBool_Type); | |
248 if (!test) { | |
249 return nullptr; | |
250 } | |
251 std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement) ; | |
252 if (!statement) { | |
253 return nullptr; | |
254 } | |
255 return std::unique_ptr<Statement>(new WhileStatement(w.fPosition, std::move( test), | |
256 std::move(statement))); | |
257 } | |
258 | |
259 std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) { | |
260 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.f Test), kBool_Type); | |
261 if (!test) { | |
262 return nullptr; | |
263 } | |
264 std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement) ; | |
265 if (!statement) { | |
266 return nullptr; | |
267 } | |
268 return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(sta tement), | |
269 std::move(test))); | |
270 } | |
271 | |
272 std::unique_ptr<Statement> IRGenerator::convertExpressionStatement( | |
273 const ASTExpre ssionStatement& s) { | |
274 std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression); | |
275 if (!e) { | |
276 return nullptr; | |
277 } | |
278 this->checkValid(*e); | |
279 return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e))); | |
280 } | |
281 | |
282 std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) { | |
283 ASSERT(fCurrentFunction); | |
284 if (r.fExpression) { | |
285 std::unique_ptr<Expression> result = this->convertExpression(*r.fExpress ion); | |
286 if (!result) { | |
287 return nullptr; | |
288 } | |
289 if (fCurrentFunction->fReturnType == kVoid_Type) { | |
290 fErrors.error(result->fPosition, "may not return a value from a void function"); | |
291 } else { | |
292 result = this->coerce(std::move(result), fCurrentFunction->fReturnTy pe); | |
293 if (!result) { | |
294 return nullptr; | |
295 } | |
296 } | |
297 return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)) ); | |
298 } else { | |
299 if (fCurrentFunction->fReturnType != kVoid_Type) { | |
300 fErrors.error(r.fPosition, "expected function to return '" + | |
301 fCurrentFunction->fReturnType->descriptio n() + "'"); | |
302 } | |
303 return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition)); | |
304 } | |
305 } | |
306 | |
307 std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) { | |
308 return std::unique_ptr<Statement>(new BreakStatement(b.fPosition)); | |
309 } | |
310 | |
311 std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStateme nt& c) { | |
312 return std::unique_ptr<Statement>(new ContinueStatement(c.fPosition)); | |
313 } | |
314 | |
315 std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement & d) { | |
316 return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition)); | |
317 } | |
318 | |
319 static std::shared_ptr<Type> expand_generics(std::shared_ptr<Type> type, int i) { | |
320 if (type->kind() == Type::kGeneric_Kind) { | |
321 return type->coercibleTypes()[i]; | |
322 } | |
323 return type; | |
324 } | |
325 | |
326 static void expand_generics(FunctionDeclaration& decl, | |
327 SymbolTable& symbolTable) { | |
328 for (int i = 0; i < 4; i++) { | |
329 std::shared_ptr<Type> returnType = expand_generics(decl.fReturnType, i); | |
330 std::vector<std::shared_ptr<Variable>> arguments; | |
331 for (const auto& p : decl.fParameters) { | |
332 arguments.push_back(std::shared_ptr<Variable>(new Variable( | |
333 p->fPosition , | |
334 Modifiers(p- >fModifiers), | |
335 p->fName, | |
336 expand_gener ics(p->fType, i), | |
337 Variable::kP arameter_Storage))); | |
338 } | |
339 std::shared_ptr<FunctionDeclaration> expanded(new FunctionDeclaration( | |
340 decl .fPosition, | |
341 decl .fName, | |
342 std: :move(arguments), | |
343 std: :move(returnType))); | |
344 symbolTable.add(expanded->fName, expanded); | |
345 } | |
346 } | |
347 | |
348 std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti on& f) { | |
349 std::shared_ptr<SymbolTable> old = fSymbolTable; | |
350 AutoSymbolTable table(this); | |
351 bool isGeneric; | |
352 std::shared_ptr<Type> returnType = this->convertType(*f.fReturnType); | |
353 if (!returnType) { | |
354 return nullptr; | |
355 } | |
356 isGeneric = returnType->kind() == Type::kGeneric_Kind; | |
357 std::vector<std::shared_ptr<Variable>> parameters; | |
358 for (const auto& param : f.fParameters) { | |
359 std::shared_ptr<Type> type = this->convertType(*param->fType); | |
360 if (!type) { | |
361 return nullptr; | |
362 } | |
363 for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) { | |
364 int size = param->fSizes[j]; | |
365 std::string name = type->name() + "[" + to_string(size) + "]"; | |
366 type = std::shared_ptr<Type>(new Type(std::move(name), Type::kArray_ Kind, | |
367 std::move(type), size)); | |
368 } | |
369 std::string name = param->fName; | |
370 Modifiers modifiers = this->convertModifiers(param->fModifiers); | |
371 Position pos = param->fPosition; | |
372 std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable( | |
373 pos, | |
374 modifiers, | |
375 std::move(n ame), | |
376 type, | |
377 Variable::k Parameter_Storage)); | |
378 parameters.push_back(std::move(var)); | |
379 isGeneric |= type->kind() == Type::kGeneric_Kind; | |
380 } | |
381 | |
382 // find existing declaration | |
383 std::shared_ptr<FunctionDeclaration> decl; | |
384 auto entry = (*old)[f.fName]; | |
385 if (entry) { | |
386 std::vector<std::shared_ptr<FunctionDeclaration>> functions; | |
387 switch (entry->fKind) { | |
388 case Symbol::kUnresolvedFunction_Kind: | |
389 functions = std::static_pointer_cast<UnresolvedFunction>(entry)- >fFunctions; | |
390 break; | |
391 case Symbol::kFunctionDeclaration_Kind: | |
392 functions.push_back(std::static_pointer_cast<FunctionDeclaration >(entry)); | |
393 break; | |
394 default: | |
395 fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined"); | |
396 return nullptr; | |
397 } | |
398 for (const auto& other : functions) { | |
399 ASSERT(other->fName == f.fName); | |
400 if (parameters.size() == other->fParameters.size()) { | |
401 bool match = true; | |
402 for (size_t i = 0; i < parameters.size(); i++) { | |
403 if (parameters[i]->fType != other->fParameters[i]->fType) { | |
404 match = false; | |
405 break; | |
406 } | |
407 } | |
408 if (match) { | |
409 if (returnType != other->fReturnType) { | |
410 FunctionDeclaration newDecl = FunctionDeclaration(f.fPos ition, | |
411 f.fNam e, | |
412 parame ters, | |
413 return Type); | |
414 fErrors.error(f.fPosition, "functions '" + newDecl.descr iption() + | |
415 "' and '" + other->descriptio n() + | |
416 "' differ only in return type "); | |
417 return nullptr; | |
418 } | |
419 decl = other; | |
420 for (size_t i = 0; i < parameters.size(); i++) { | |
421 if (parameters[i]->fModifiers != other->fParameters[i]-> fModifiers) { | |
422 fErrors.error(f.fPosition, "modifiers on parameter " + | |
423 to_string(i + 1) + " diff er between " + | |
424 "declaration and definiti on"); | |
425 return nullptr; | |
426 } | |
427 fSymbolTable->add(parameters[i]->fName, decl->fParameter s[i]); | |
428 } | |
429 if (other->fDefined) { | |
430 fErrors.error(f.fPosition, "duplicate definition of " + | |
431 other->description()); | |
432 } | |
433 break; | |
434 } | |
435 } | |
436 } | |
437 } | |
438 if (!decl) { | |
439 // couldn't find an existing declaration | |
440 decl.reset(new FunctionDeclaration(f.fPosition, f.fName, parameters, ret urnType)); | |
441 for (auto var : parameters) { | |
442 fSymbolTable->add(var->fName, var); | |
443 } | |
444 } | |
445 if (isGeneric) { | |
446 ASSERT(!f.fBody); | |
447 expand_generics(*decl, *old); | |
448 } else { | |
449 old->add(decl->fName, decl); | |
450 if (f.fBody) { | |
451 ASSERT(!fCurrentFunction); | |
452 fCurrentFunction = decl; | |
453 decl->fDefined = true; | |
454 std::unique_ptr<Block> body = this->convertBlock(*f.fBody); | |
455 fCurrentFunction = nullptr; | |
456 if (!body) { | |
457 return nullptr; | |
458 } | |
459 return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f. fPosition, decl, | |
460 st d::move(body))); | |
461 } | |
462 } | |
463 return nullptr; | |
464 } | |
465 | |
466 std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte rfaceBlock& intf) { | |
467 std::shared_ptr<SymbolTable> old = fSymbolTable; | |
468 AutoSymbolTable table(this); | |
469 Modifiers mods = this->convertModifiers(intf.fModifiers); | |
470 std::vector<Type::Field> fields; | |
471 for (size_t i = 0; i < intf.fDeclarations.size(); i++) { | |
472 std::unique_ptr<VarDeclaration> decl = this->convertVarDeclaration( | |
473 *intf.f Declarations[i], | |
474 Variabl e::kGlobal_Storage); | |
475 for (size_t j = 0; j < decl->fVars.size(); j++) { | |
476 fields.push_back(Type::Field(decl->fVars[j]->fModifiers, decl->fVars [j]->fName, | |
477 decl->fVars[j]->fType)); | |
478 if (decl->fValues[j]) { | |
479 fErrors.error(decl->fPosition, "initializers are not permitted o n interface block " | |
480 "fields"); | |
481 } | |
482 } | |
483 } | |
484 std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(intf.fInterfaceN ame, fields)); | |
485 std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fIn terfaceName; | |
486 std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable(intf. fPosition, mods, | |
487 name, type, | |
488 Variable::kGloba l_Storage)); | |
489 if (intf.fValueName.length()) { | |
490 old->add(intf.fValueName, var); | |
491 | |
492 } else { | |
493 for (size_t i = 0; i < fields.size(); i++) { | |
494 std::shared_ptr<Field> field = std::shared_ptr<Field>(new Field(intf .fPosition, var, | |
495 (int ) i)); | |
496 old->add(fields[i].fName, field); | |
497 } | |
498 } | |
499 return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, va r)); | |
500 } | |
501 | |
502 std::shared_ptr<Type> IRGenerator::convertType(const ASTType& type) { | |
503 std::shared_ptr<Symbol> result = (*fSymbolTable)[type.fName]; | |
504 if (result && result->fKind == Symbol::kType_Kind) { | |
505 return std::static_pointer_cast<Type>(result); | |
506 } | |
507 fErrors.error(type.fPosition, "unknown type '" + type.fName + "'"); | |
508 return nullptr; | |
509 } | |
510 | |
511 std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) { | |
512 switch (expr.fKind) { | |
513 case ASTExpression::kIdentifier_Kind: | |
514 return this->convertIdentifier((ASTIdentifier&) expr); | |
515 case ASTExpression::kBool_Kind: | |
516 return std::unique_ptr<Expression>(new BoolLiteral(expr.fPosition, | |
517 ((ASTBoolLiteral& ) expr).fValue)); | |
518 case ASTExpression::kInt_Kind: | |
519 return std::unique_ptr<Expression>(new IntLiteral(expr.fPosition, | |
520 ((ASTIntLiteral&) expr).fValue)); | |
521 case ASTExpression::kFloat_Kind: | |
522 return std::unique_ptr<Expression>(new FloatLiteral(expr.fPosition, | |
523 ((ASTFloatLitera l&) expr).fValue)); | |
524 case ASTExpression::kBinary_Kind: | |
525 return this->convertBinaryExpression((ASTBinaryExpression&) expr); | |
526 case ASTExpression::kPrefix_Kind: | |
527 return this->convertPrefixExpression((ASTPrefixExpression&) expr); | |
528 case ASTExpression::kSuffix_Kind: | |
529 return this->convertSuffixExpression((ASTSuffixExpression&) expr); | |
530 case ASTExpression::kTernary_Kind: | |
531 return this->convertTernaryExpression((ASTTernaryExpression&) expr); | |
532 default: | |
533 ABORT("unsupported expression type: %d\n", expr.fKind); | |
534 } | |
535 } | |
536 | |
537 std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) { | |
538 std::shared_ptr<Symbol> result = (*fSymbolTable)[identifier.fText]; | |
539 if (!result) { | |
540 fErrors.error(identifier.fPosition, "unknown identifier '" + identifier. fText + "'"); | |
541 return nullptr; | |
542 } | |
543 switch (result->fKind) { | |
544 case Symbol::kFunctionDeclaration_Kind: { | |
545 std::vector<std::shared_ptr<FunctionDeclaration>> f = { | |
546 std::static_pointer_cast<FunctionDeclaration>(std::move(result)) | |
dogben
2016/06/28 02:14:54
Sorry, my mistake. std::move doesn't do anything i
| |
547 }; | |
548 return std::unique_ptr<FunctionReference>(new FunctionReference(iden tifier.fPosition, | |
549 std: :move(f))); | |
550 } | |
551 case Symbol::kUnresolvedFunction_Kind: { | |
552 auto f = std::static_pointer_cast<UnresolvedFunction>(result); | |
553 return std::unique_ptr<FunctionReference>(new FunctionReference(iden tifier.fPosition, | |
554 f->f Functions)); | |
555 } | |
556 case Symbol::kVariable_Kind: { | |
557 std::shared_ptr<Variable> var = std::static_pointer_cast<Variable>(r esult); | |
558 this->markReadFrom(var); | |
559 return std::unique_ptr<VariableReference>(new VariableReference(iden tifier.fPosition, | |
560 std: :move(var))); | |
561 } | |
562 case Symbol::kField_Kind: { | |
563 std::shared_ptr<Field> field = std::static_pointer_cast<Field>(resul t); | |
564 VariableReference* base = new VariableReference(identifier.fPosition , field->fOwner); | |
565 return std::unique_ptr<Expression>(new FieldAccess(std::unique_ptr<E xpression>(base), | |
566 field->fFieldInde x)); | |
567 } | |
568 case Symbol::kType_Kind: { | |
569 auto t = std::static_pointer_cast<Type>(result); | |
570 return std::unique_ptr<TypeReference>(new TypeReference(identifier.f Position, | |
571 std::move(t) )); | |
572 } | |
573 default: | |
574 ABORT("unsupported symbol type %d\n", result->fKind); | |
575 } | |
576 | |
577 } | |
578 | |
579 std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr , | |
580 std::shared_ptr<Type> type) { | |
581 if (!expr) { | |
582 return nullptr; | |
583 } | |
584 if (*expr->fType == *type) { | |
585 return expr; | |
586 } | |
587 this->checkValid(*expr); | |
588 if (!expr->fType->canCoerceTo(type)) { | |
589 fErrors.error(expr->fPosition, "expected '" + type->description() + "', but found '" + | |
590 expr->fType->description() + "'"); | |
591 return nullptr; | |
592 } | |
593 if (type->kind() == Type::kScalar_Kind) { | |
594 std::vector<std::unique_ptr<Expression>> args; | |
595 args.push_back(std::move(expr)); | |
596 ASTIdentifier id(Position(), type->description()); | |
597 std::unique_ptr<Expression> ctor = this->convertIdentifier(id); | |
598 ASSERT(ctor); | |
599 return this->call(Position(), std::move(ctor), std::move(args)); | |
600 } | |
601 ABORT("cannot coerce %s to %s", expr->fType->description().c_str(), | |
602 type->description().c_str()); | |
603 } | |
604 | |
605 /** | |
606 * Determines the operand and result types of a binary expression. Returns true if the expression is | |
607 * legal, false otherwise. If false, the values of the out parameters are undefi ned. | |
608 */ | |
609 static bool determine_binary_type(Token::Kind op, std::shared_ptr<Type> left, | |
610 std::shared_ptr<Type> right, | |
611 std::shared_ptr<Type>* outLeftType, | |
612 std::shared_ptr<Type>* outRightType, | |
613 std::shared_ptr<Type>* outResultType, | |
614 bool tryFlipped) { | |
615 if (op == Token::STAR || op == Token::STAREQ) { | |
616 // FIXME need to handle non-square matrices | |
617 if (left->kind() == Type::kMatrix_Kind && right->kind() == Type::kVector _Kind) { | |
618 *outLeftType = left; | |
619 *outRightType = right; | |
620 *outResultType = right; | |
621 return left->rows() == right->columns(); | |
622 } | |
623 if (left->kind() == Type::kVector_Kind && right->kind() == Type::kMatrix _Kind) { | |
624 *outLeftType = left; | |
625 *outRightType = right; | |
626 *outResultType = left; | |
627 return left->columns() == right->columns(); | |
628 } | |
629 } | |
630 bool isLogical; | |
631 switch (op) { | |
632 case Token::EQEQ: // fall through | |
633 case Token::NEQ: // fall through | |
634 case Token::LT: // fall through | |
635 case Token::GT: // fall through | |
636 case Token::LTEQ: // fall through | |
637 case Token::GTEQ: | |
638 isLogical = true; | |
639 break; | |
640 default: | |
641 isLogical = false; | |
642 } | |
643 // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have | |
644 // full support for numbers other than float. | |
645 if (left == right) { | |
646 *outLeftType = left; | |
647 *outRightType = left; | |
648 if (isLogical) { | |
649 *outResultType = kBool_Type; | |
650 } else { | |
651 *outResultType = left; | |
652 } | |
653 return true; | |
654 } | |
655 // FIXME: incorrect for shift operations | |
656 if (left->canCoerceTo(right)) { | |
657 *outLeftType = right; | |
658 *outRightType = right; | |
659 if (isLogical) { | |
660 *outResultType = kBool_Type; | |
661 } else { | |
662 *outResultType = right; | |
663 } | |
664 return true; | |
665 } | |
666 if ((left->kind() == Type::kVector_Kind || left->kind() == Type::kMatrix_Kin d) && | |
667 (right->kind() == Type::kScalar_Kind)) { | |
668 if (determine_binary_type(op, left->componentType(), right, outLeftType, outRightType, | |
669 outResultType, false)) { | |
670 *outLeftType = (*outLeftType)->toCompound(left->columns(), left->row s()); | |
671 if (!isLogical) { | |
672 *outResultType = (*outResultType)->toCompound(left->columns(), l eft->rows()); | |
673 } | |
674 return true; | |
675 } | |
676 return false; | |
677 } | |
678 if (tryFlipped) { | |
679 return determine_binary_type(op, right, left, outRightType, outLeftType, outResultType, | |
680 false); | |
681 } | |
682 return false; | |
683 } | |
684 | |
685 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( | |
686 const ASTBinaryExpre ssion& expression) { | |
687 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft ); | |
688 if (!left) { | |
689 return nullptr; | |
690 } | |
691 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht); | |
692 if (!right) { | |
693 return nullptr; | |
694 } | |
695 std::shared_ptr<Type> leftType; | |
696 std::shared_ptr<Type> rightType; | |
697 std::shared_ptr<Type> resultType; | |
698 if (!determine_binary_type(expression.fOperator, left->fType, right->fType, &leftType, | |
699 &rightType, &resultType, true)) { | |
700 fErrors.error(expression.fPosition, "type mismatch: '" + | |
701 Token::OperatorName(expression.fOper ator) + | |
702 "' cannot operate on '" + left->fTyp e->fName + | |
703 "', '" + right->fType->fName + "'"); | |
704 return nullptr; | |
705 } | |
706 switch (expression.fOperator) { | |
707 case Token::EQ: // fall through | |
708 case Token::PLUSEQ: // fall through | |
709 case Token::MINUSEQ: // fall through | |
710 case Token::STAREQ: // fall through | |
711 case Token::SLASHEQ: // fall through | |
712 case Token::PERCENTEQ: // fall through | |
713 case Token::SHLEQ: // fall through | |
714 case Token::SHREQ: // fall through | |
715 case Token::BITWISEOREQ: // fall through | |
716 case Token::BITWISEXOREQ: // fall through | |
717 case Token::BITWISEANDEQ: // fall through | |
718 case Token::LOGICALOREQ: // fall through | |
719 case Token::LOGICALXOREQ: // fall through | |
720 case Token::LOGICALANDEQ: | |
721 this->markWrittenTo(*left); | |
722 default: | |
723 break; | |
724 } | |
725 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , | |
726 this->coerce(std::mo ve(left), leftType), | |
727 expression.fOperator , | |
728 this->coerce(std::mo ve(right), | |
729 rightTy pe), | |
730 resultType)); | |
731 } | |
732 | |
733 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( | |
734 const ASTTernaryExpre ssion& expression) { | |
735 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), | |
736 kBool_Type); | |
737 if (!test) { | |
738 return nullptr; | |
739 } | |
740 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True); | |
741 if (!ifTrue) { | |
742 return nullptr; | |
743 } | |
744 std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fI fFalse); | |
745 if (!ifFalse) { | |
746 return nullptr; | |
747 } | |
748 std::shared_ptr<Type> trueType; | |
749 std::shared_ptr<Type> falseType; | |
750 std::shared_ptr<Type> resultType; | |
751 if (!determine_binary_type(Token::EQEQ, ifTrue->fType, ifFalse->fType, &true Type, | |
752 &falseType, &resultType, true)) { | |
753 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " + | |
754 ifTrue->fType->fName + "', '" + | |
755 ifFalse->fType->fName + "'"); | |
756 return nullptr; | |
757 } | |
758 ASSERT(trueType == falseType); | |
759 ifTrue = this->coerce(std::move(ifTrue), trueType); | |
760 ifFalse = this->coerce(std::move(ifFalse), falseType); | |
761 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n, | |
762 std::move(test), | |
763 std::move(ifTrue), | |
764 std::move(ifFalse)) ); | |
765 } | |
766 | |
767 std::unique_ptr<Expression> IRGenerator::call( | |
768 Position position, | |
769 std::shared_ptr<FunctionDeclaration> fu nction, | |
770 std::vector<std::unique_ptr<Expression> > arguments) { | |
771 if (function->fParameters.size() != arguments.size()) { | |
772 std::string msg = "call to '" + function->fName + "' expected " + | |
773 to_string(function->fParameters.size()) + | |
774 " argument"; | |
775 if (function->fParameters.size() != 1) { | |
776 msg += "s"; | |
777 } | |
778 msg += ", but found " + to_string(arguments.size()); | |
779 fErrors.error(position, msg); | |
780 return nullptr; | |
781 } | |
782 for (size_t i = 0; i < arguments.size(); i++) { | |
783 arguments[i] = this->coerce(std::move(arguments[i]), function->fParamete rs[i]->fType); | |
784 if (arguments[i] && (function->fParameters[i]->fModifiers.fFlags & Modif iers::kOut_Flag)) { | |
785 this->markWrittenTo(*arguments[i]); | |
786 } | |
787 } | |
788 return std::unique_ptr<FunctionCall>(new FunctionCall(position, std::move(fu nction), | |
789 std::move(arguments))) ; | |
790 } | |
791 | |
792 /** | |
793 * Determines the cost of coercing the arguments of a function to the required t ypes. Returns true | |
794 * if the cost could be computed, false if the call is not valid. Cost has no pa rticular meaning | |
795 * other than "lower costs are preferred". | |
796 */ | |
797 bool IRGenerator::determineCallCost(std::shared_ptr<FunctionDeclaration> functio n, | |
798 const std::vector<std::unique_ptr<Expression >>& arguments, | |
799 int* outCost) { | |
800 if (function->fParameters.size() != arguments.size()) { | |
801 return false; | |
802 } | |
803 int total = 0; | |
804 for (size_t i = 0; i < arguments.size(); i++) { | |
805 int cost; | |
806 if (arguments[i]->fType->determineCoercionCost(function->fParameters[i]- >fType, &cost)) { | |
807 total += cost; | |
808 } else { | |
809 return false; | |
810 } | |
811 } | |
812 *outCost = total; | |
813 return true; | |
814 } | |
815 | |
816 std::unique_ptr<Expression> IRGenerator::call(Position position, | |
817 std::unique_ptr<Expression> functi onValue, | |
818 std::vector<std::unique_ptr<Expres sion>> arguments) { | |
819 if (functionValue->fKind == Expression::kTypeReference_Kind) { | |
820 return this->convertConstructor(position, | |
821 ((TypeReference&) *functionValue).fValue , | |
822 std::move(arguments)); | |
823 } | |
824 if (functionValue->fKind != Expression::kFunctionReference_Kind) { | |
825 fErrors.error(position, "'" + functionValue->description() + "' is not a function"); | |
826 return nullptr; | |
827 } | |
828 FunctionReference* ref = (FunctionReference*) functionValue.get(); | |
829 int bestCost = INT_MAX; | |
830 std::shared_ptr<FunctionDeclaration> best; | |
831 if (ref->fFunctions.size() > 1) { | |
832 for (const auto& f : ref->fFunctions) { | |
833 int cost; | |
834 if (this->determineCallCost(f, arguments, &cost) && cost < bestCost) { | |
835 bestCost = cost; | |
836 best = f; | |
837 } | |
838 } | |
839 if (best) { | |
840 return this->call(position, std::move(best), std::move(arguments)); | |
841 } | |
842 std::string msg = "no match for " + ref->fFunctions[0]->fName + "("; | |
843 std::string separator = ""; | |
844 for (size_t i = 0; i < arguments.size(); i++) { | |
845 msg += separator; | |
846 separator = ", "; | |
847 msg += arguments[i]->fType->description(); | |
848 } | |
849 msg += ")"; | |
850 fErrors.error(position, msg); | |
851 return nullptr; | |
852 } | |
853 return this->call(position, ref->fFunctions[0], std::move(arguments)); | |
854 } | |
855 | |
856 std::unique_ptr<Expression> IRGenerator::convertConstructor( | |
857 Position position, | |
858 std::shared_ptr<Type> type, | |
859 std::vector<std::unique_ptr< Expression>> args) { | |
860 // FIXME: add support for structs | |
861 if (type == kFloat_Type && args.size() == 1 && | |
862 args[0]->fKind == Expression::kIntLiteral_Kind) { | |
863 int64_t value = ((IntLiteral&) *args[0]).fValue; | |
864 return std::unique_ptr<Expression>(new FloatLiteral(position, (double) v alue)); | |
865 } | |
866 int min = type->rows() * type->columns(); | |
867 int max = type->columns() > 1 ? INT_MAX : min; | |
868 int actual = 0; | |
869 for (size_t i = 0; i < args.size(); i++) { | |
870 if (args[i]->fType->kind() == Type::kScalar_Kind) { | |
871 actual += 1; | |
872 if (type->kind() != Type::kScalar_Kind) { | |
873 args[i] = this->coerce(std::move(args[i]), type->componentType() ); | |
874 } | |
875 } else { | |
876 actual += args[i]->fType->rows() * args[i]->fType->columns(); | |
877 } | |
878 } | |
879 Type::Kind kind = type->kind(); | |
880 if ((actual < min || actual > max) && | |
881 !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) { | |
882 fErrors.error(position, "invalid arguments to '" + type->description() + | |
883 "' constructor (expected " + to_string(min) + " scalars, " + | |
884 "but found " + to_string(actual) + ")"); | |
885 return nullptr; | |
886 } | |
887 if (type->isNumber()) { | |
888 ASSERT(args.size() == 1); | |
889 if (args[0]->fType == kBool_Type) { | |
890 std::unique_ptr<IntLiteral> zero(new IntLiteral(position, 0)); | |
891 std::unique_ptr<IntLiteral> one(new IntLiteral(position, 1)); | |
892 return std::unique_ptr<Expression>( | |
893 new TernaryExpression(position, std::mo ve(args[0]), | |
894 this->coerce(std: :move(one), type), | |
895 this->coerce(std: :move(zero), | |
896 type ))); | |
897 } | |
898 } | |
899 if (args.size() == 1 && args[0]->fType == type) { | |
900 // argument is already the right type, just return it | |
901 return std::move(args[0]); | |
902 } | |
903 return std::unique_ptr<Expression>(new Constructor(position, std::move(type) , std::move(args))); | |
904 } | |
905 | |
906 std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( | |
907 const ASTPrefixExpre ssion& expression) { | |
908 std::unique_ptr<Expression> base = this->convertExpression(*expression.fOper and); | |
909 if (!base) { | |
910 return nullptr; | |
911 } | |
912 switch (expression.fOperator) { | |
913 case Token::PLUS: | |
914 if (!base->fType->isNumber() && base->fType->kind() != Type::kVector _Kind) { | |
915 fErrors.error(expression.fPosition, | |
916 "'+' cannot operate on '" + base->fType->descripti on() + "'"); | |
917 return nullptr; | |
918 } | |
919 return base; | |
920 case Token::MINUS: | |
921 if (!base->fType->isNumber() && base->fType->kind() != Type::kVector _Kind) { | |
922 fErrors.error(expression.fPosition, | |
923 "'-' cannot operate on '" + base->fType->descripti on() + "'"); | |
924 return nullptr; | |
925 } | |
926 if (base->fKind == Expression::kIntLiteral_Kind) { | |
927 return std::unique_ptr<Expression>(new IntLiteral(base->fPositio n, | |
928 -((IntLiteral& ) *base).fValue)); | |
929 } | |
930 if (base->fKind == Expression::kFloatLiteral_Kind) { | |
931 double value = -((FloatLiteral&) *base).fValue; | |
932 return std::unique_ptr<Expression>(new FloatLiteral(base->fPosit ion, value)); | |
933 } | |
934 return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS , std::move(base))); | |
935 case Token::PLUSPLUS: | |
936 if (!base->fType->isNumber()) { | |
937 fErrors.error(expression.fPosition, | |
938 "'" + Token::OperatorName(expression.fOperator) + | |
939 "' cannot operate on '" + base->fType->description () + "'"); | |
940 return nullptr; | |
941 } | |
942 this->markWrittenTo(*base); | |
943 break; | |
944 case Token::MINUSMINUS: | |
945 if (!base->fType->isNumber()) { | |
946 fErrors.error(expression.fPosition, | |
947 "'" + Token::OperatorName(expression.fOperator) + | |
948 "' cannot operate on '" + base->fType->description () + "'"); | |
949 return nullptr; | |
950 } | |
951 this->markWrittenTo(*base); | |
952 break; | |
953 case Token::NOT: | |
954 if (base->fType != kBool_Type) { | |
955 fErrors.error(expression.fPosition, | |
956 "'" + Token::OperatorName(expression.fOperator) + | |
957 "' cannot operate on '" + base->fType->description () + "'"); | |
958 return nullptr; | |
959 } | |
960 break; | |
961 default: | |
962 ABORT("unsupported prefix operator\n"); | |
963 } | |
964 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator , | |
965 std::move(base))); | |
966 } | |
967 | |
968 std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression > base, | |
969 const ASTExpression& index ) { | |
970 if (base->fType->kind() != Type::kArray_Kind && base->fType->kind() != Type: :kMatrix_Kind && | |
971 base->fType->kind() != Type::kVector_Kind) { | |
972 fErrors.error(base->fPosition, "expected array, but found '" + base->fTy pe->description() + | |
973 "'"); | |
974 return nullptr; | |
975 } | |
976 std::unique_ptr<Expression> converted = this->convertExpression(index); | |
977 if (!converted) { | |
978 return nullptr; | |
979 } | |
980 converted = this->coerce(std::move(converted), kInt_Type); | |
981 if (!converted) { | |
982 return nullptr; | |
983 } | |
984 return std::unique_ptr<Expression>(new IndexExpression(std::move(base), std: :move(converted))); | |
985 } | |
986 | |
987 std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression > base, | |
988 const std::string& field) { | |
989 auto fields = base->fType->fields(); | |
990 for (size_t i = 0; i < fields.size(); i++) { | |
991 if (fields[i].fName == field) { | |
992 return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i)); | |
993 } | |
994 } | |
995 fErrors.error(base->fPosition, "type '" + base->fType->description() + "' do es not have a " | |
996 "field named '" + field + ""); | |
997 return nullptr; | |
998 } | |
999 | |
1000 std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi on> base, | |
1001 const std::string& field s) { | |
1002 if (base->fType->kind() != Type::kVector_Kind) { | |
1003 fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType->de scription() + "'"); | |
1004 return nullptr; | |
1005 } | |
1006 std::vector<int> swizzleComponents; | |
1007 for (char c : fields) { | |
1008 switch (c) { | |
1009 case 'x': // fall through | |
1010 case 'r': // fall through | |
1011 case 's': | |
1012 swizzleComponents.push_back(0); | |
1013 break; | |
1014 case 'y': // fall through | |
1015 case 'g': // fall through | |
1016 case 't': | |
1017 if (base->fType->columns() >= 2) { | |
1018 swizzleComponents.push_back(1); | |
1019 break; | |
1020 } | |
1021 // fall through | |
1022 case 'z': // fall through | |
1023 case 'b': // fall through | |
1024 case 'p': | |
1025 if (base->fType->columns() >= 3) { | |
1026 swizzleComponents.push_back(2); | |
1027 break; | |
1028 } | |
1029 // fall through | |
1030 case 'w': // fall through | |
1031 case 'a': // fall through | |
1032 case 'q': | |
1033 if (base->fType->columns() >= 4) { | |
1034 swizzleComponents.push_back(3); | |
1035 break; | |
1036 } | |
1037 // fall through | |
1038 default: | |
1039 fErrors.error(base->fPosition, "invalid swizzle component '" + s td::string(1, c) + | |
1040 "'"); | |
1041 return nullptr; | |
1042 } | |
1043 } | |
1044 ASSERT(swizzleComponents.size() > 0); | |
1045 if (swizzleComponents.size() > 4) { | |
1046 fErrors.error(base->fPosition, "too many components in swizzle mask '" + fields + "'"); | |
1047 return nullptr; | |
1048 } | |
1049 return std::unique_ptr<Expression>(new Swizzle(std::move(base), swizzleCompo nents)); | |
1050 } | |
1051 | |
1052 std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( | |
1053 const ASTSuffixExpre ssion& expression) { | |
1054 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase ); | |
1055 if (!base) { | |
1056 return nullptr; | |
1057 } | |
1058 switch (expression.fSuffix->fKind) { | |
1059 case ASTSuffix::kIndex_Kind: | |
1060 return this->convertIndex(std::move(base), | |
1061 *((ASTIndexSuffix&) *expression.fSuffix).f Expression); | |
1062 case ASTSuffix::kCall_Kind: { | |
1063 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArgumen ts; | |
1064 std::vector<std::unique_ptr<Expression>> arguments; | |
1065 for (size_t i = 0; i < rawArguments->size(); i++) { | |
1066 std::unique_ptr<Expression> converted = | |
1067 this->convertExpression(*(*rawArguments)[i]); | |
1068 if (!converted) { | |
1069 return nullptr; | |
1070 } | |
1071 arguments.push_back(std::move(converted)); | |
1072 } | |
1073 return this->call(expression.fPosition, std::move(base), std::move(a rguments)); | |
1074 } | |
1075 case ASTSuffix::kField_Kind: { | |
1076 switch (base->fType->kind()) { | |
1077 case Type::kVector_Kind: | |
1078 return this->convertSwizzle(std::move(base), | |
1079 ((ASTFieldSuffix&) *expression.f Suffix).fField); | |
1080 case Type::kStruct_Kind: | |
1081 return this->convertField(std::move(base), | |
1082 ((ASTFieldSuffix&) *expression.fSu ffix).fField); | |
1083 default: | |
1084 fErrors.error(base->fPosition, "cannot swizzle value of type '" + | |
1085 base->fType->description() + "'"); | |
1086 return nullptr; | |
1087 } | |
1088 } | |
1089 case ASTSuffix::kPostIncrement_Kind: | |
1090 if (!base->fType->isNumber()) { | |
1091 fErrors.error(expression.fPosition, | |
1092 "'++' cannot operate on '" + base->fType->descript ion() + "'"); | |
1093 return nullptr; | |
1094 } | |
1095 this->markWrittenTo(*base); | |
1096 return std::unique_ptr<Expression>(new PostfixExpression(std::move(b ase), | |
1097 Token::PLUS PLUS)); | |
1098 case ASTSuffix::kPostDecrement_Kind: | |
1099 if (!base->fType->isNumber()) { | |
1100 fErrors.error(expression.fPosition, | |
1101 "'--' cannot operate on '" + base->fType->descript ion() + "'"); | |
1102 return nullptr; | |
1103 } | |
1104 this->markWrittenTo(*base); | |
1105 return std::unique_ptr<Expression>(new PostfixExpression(std::move(b ase), | |
1106 Token::MINU SMINUS)); | |
1107 default: | |
1108 ABORT("unsupported suffix operator"); | |
1109 } | |
1110 } | |
1111 | |
1112 void IRGenerator::checkValid(const Expression& expr) { | |
1113 switch (expr.fKind) { | |
1114 case Expression::kFunctionReference_Kind: | |
1115 fErrors.error(expr.fPosition, "expected '(' to begin function call") ; | |
1116 break; | |
1117 case Expression::kTypeReference_Kind: | |
1118 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation"); | |
1119 break; | |
1120 default: | |
1121 break; | |
1122 } | |
1123 } | |
1124 | |
1125 void IRGenerator::markReadFrom(std::shared_ptr<Variable> var) { | |
1126 var->fIsReadFrom = true; | |
1127 } | |
1128 | |
1129 void IRGenerator::markWrittenTo(const Expression& expr) { | |
1130 switch (expr.fKind) { | |
1131 case Expression::kVariableReference_Kind: | |
1132 ((VariableReference&) expr).fVariable->fIsWrittenTo = true; | |
1133 break; | |
1134 case Expression::kFieldAccess_Kind: | |
1135 this->markWrittenTo(*((FieldAccess&) expr).fBase); | |
1136 break; | |
1137 case Expression::kSwizzle_Kind: | |
1138 this->markWrittenTo(*((Swizzle&) expr).fBase); | |
1139 break; | |
1140 case Expression::kIndex_Kind: | |
1141 this->markWrittenTo(*((IndexExpression&) expr).fBase); | |
1142 break; | |
1143 default: | |
1144 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); | |
1145 break; | |
1146 } | |
1147 } | |
1148 | |
1149 } | |
OLD | NEW |