Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/sksl/SkSLIRGenerator.cpp

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

Powered by Google App Engine
This is Rietveld 408576698