| Index: src/sksl/SkSLIRGenerator.cpp
|
| diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
|
| index 6efaad0d588033707c1c296ddd19186f716d89b6..2cc7eacb4d9ec92bd5e0e57c12c8fb6ecb1a7b64 100644
|
| --- a/src/sksl/SkSLIRGenerator.cpp
|
| +++ b/src/sksl/SkSLIRGenerator.cpp
|
| @@ -68,9 +68,9 @@
|
|
|
| IRGenerator::IRGenerator(std::shared_ptr<SymbolTable> symbolTable,
|
| ErrorReporter& errorReporter)
|
| -: fCurrentFunction(nullptr)
|
| -, fSymbolTable(std::move(symbolTable))
|
| -, fErrors(errorReporter) {}
|
| +: fSymbolTable(std::move(symbolTable))
|
| +, fErrors(errorReporter) {
|
| +}
|
|
|
| void IRGenerator::pushSymbolTable() {
|
| fSymbolTable.reset(new SymbolTable(std::move(fSymbolTable), fErrors));
|
| @@ -123,7 +123,7 @@
|
| }
|
| statements.push_back(std::move(statement));
|
| }
|
| - return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements), fSymbolTable));
|
| + return std::unique_ptr<Block>(new Block(block.fPosition, std::move(statements)));
|
| }
|
|
|
| std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
|
| @@ -141,22 +141,22 @@
|
|
|
| std::unique_ptr<VarDeclaration> IRGenerator::convertVarDeclaration(const ASTVarDeclaration& decl,
|
| Variable::Storage storage) {
|
| - std::vector<const Variable*> variables;
|
| + std::vector<std::shared_ptr<Variable>> variables;
|
| std::vector<std::vector<std::unique_ptr<Expression>>> sizes;
|
| std::vector<std::unique_ptr<Expression>> values;
|
| - const Type* baseType = this->convertType(*decl.fType);
|
| + std::shared_ptr<Type> baseType = this->convertType(*decl.fType);
|
| if (!baseType) {
|
| return nullptr;
|
| }
|
| for (size_t i = 0; i < decl.fNames.size(); i++) {
|
| Modifiers modifiers = this->convertModifiers(decl.fModifiers);
|
| - const Type* type = baseType;
|
| + std::shared_ptr<Type> type = baseType;
|
| ASSERT(type->kind() != Type::kArray_Kind);
|
| std::vector<std::unique_ptr<Expression>> currentVarSizes;
|
| for (size_t j = 0; j < decl.fSizes[i].size(); j++) {
|
| if (decl.fSizes[i][j]) {
|
| ASTExpression& rawSize = *decl.fSizes[i][j];
|
| - auto size = this->coerce(this->convertExpression(rawSize), *kInt_Type);
|
| + auto size = this->coerce(this->convertExpression(rawSize), kInt_Type);
|
| if (!size) {
|
| return nullptr;
|
| }
|
| @@ -172,28 +172,27 @@
|
| count = -1;
|
| name += "[]";
|
| }
|
| - type = new Type(name, Type::kArray_Kind, *type, (int) count);
|
| - fSymbolTable->takeOwnership((Type*) type);
|
| + type = std::shared_ptr<Type>(new Type(name, Type::kArray_Kind, type, (int) count));
|
| currentVarSizes.push_back(std::move(size));
|
| } else {
|
| - type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1);
|
| - fSymbolTable->takeOwnership((Type*) type);
|
| + type = std::shared_ptr<Type>(new Type(type->fName + "[]", Type::kArray_Kind, type,
|
| + -1));
|
| currentVarSizes.push_back(nullptr);
|
| }
|
| }
|
| sizes.push_back(std::move(currentVarSizes));
|
| - auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, decl.fNames[i],
|
| - *type, storage));
|
| + auto var = std::make_shared<Variable>(decl.fPosition, modifiers, decl.fNames[i], type,
|
| + storage);
|
| + variables.push_back(var);
|
| std::unique_ptr<Expression> value;
|
| if (decl.fValues[i]) {
|
| value = this->convertExpression(*decl.fValues[i]);
|
| if (!value) {
|
| return nullptr;
|
| }
|
| - value = this->coerce(std::move(value), *type);
|
| - }
|
| - variables.push_back(var.get());
|
| - fSymbolTable->add(decl.fNames[i], std::move(var));
|
| + value = this->coerce(std::move(value), type);
|
| + }
|
| + fSymbolTable->add(var->fName, var);
|
| values.push_back(std::move(value));
|
| }
|
| return std::unique_ptr<VarDeclaration>(new VarDeclaration(decl.fPosition, std::move(variables),
|
| @@ -201,7 +200,7 @@
|
| }
|
|
|
| std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
|
| - std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest), *kBool_Type);
|
| + std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest), kBool_Type);
|
| if (!test) {
|
| return nullptr;
|
| }
|
| @@ -226,7 +225,7 @@
|
| if (!initializer) {
|
| return nullptr;
|
| }
|
| - std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.fTest), *kBool_Type);
|
| + std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*f.fTest), kBool_Type);
|
| if (!test) {
|
| return nullptr;
|
| }
|
| @@ -241,11 +240,11 @@
|
| }
|
| return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
|
| std::move(test), std::move(next),
|
| - std::move(statement), fSymbolTable));
|
| + std::move(statement)));
|
| }
|
|
|
| std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
|
| - std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest), *kBool_Type);
|
| + std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest), kBool_Type);
|
| if (!test) {
|
| return nullptr;
|
| }
|
| @@ -258,7 +257,7 @@
|
| }
|
|
|
| std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
|
| - std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest), *kBool_Type);
|
| + std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest), kBool_Type);
|
| if (!test) {
|
| return nullptr;
|
| }
|
| @@ -287,7 +286,7 @@
|
| if (!result) {
|
| return nullptr;
|
| }
|
| - if (fCurrentFunction->fReturnType == *kVoid_Type) {
|
| + if (fCurrentFunction->fReturnType == kVoid_Type) {
|
| fErrors.error(result->fPosition, "may not return a value from a void function");
|
| } else {
|
| result = this->coerce(std::move(result), fCurrentFunction->fReturnType);
|
| @@ -297,9 +296,9 @@
|
| }
|
| return std::unique_ptr<Statement>(new ReturnStatement(std::move(result)));
|
| } else {
|
| - if (fCurrentFunction->fReturnType != *kVoid_Type) {
|
| + if (fCurrentFunction->fReturnType != kVoid_Type) {
|
| fErrors.error(r.fPosition, "expected function to return '" +
|
| - fCurrentFunction->fReturnType.description() + "'");
|
| + fCurrentFunction->fReturnType->description() + "'");
|
| }
|
| return std::unique_ptr<Statement>(new ReturnStatement(r.fPosition));
|
| }
|
| @@ -317,74 +316,80 @@
|
| return std::unique_ptr<Statement>(new DiscardStatement(d.fPosition));
|
| }
|
|
|
| -static const Type& expand_generics(const Type& type, int i) {
|
| - if (type.kind() == Type::kGeneric_Kind) {
|
| - return *type.coercibleTypes()[i];
|
| +static std::shared_ptr<Type> expand_generics(std::shared_ptr<Type> type, int i) {
|
| + if (type->kind() == Type::kGeneric_Kind) {
|
| + return type->coercibleTypes()[i];
|
| }
|
| return type;
|
| }
|
|
|
| -static void expand_generics(const FunctionDeclaration& decl,
|
| - std::shared_ptr<SymbolTable> symbolTable) {
|
| +static void expand_generics(FunctionDeclaration& decl,
|
| + SymbolTable& symbolTable) {
|
| for (int i = 0; i < 4; i++) {
|
| - const Type& returnType = expand_generics(decl.fReturnType, i);
|
| - std::vector<const Variable*> parameters;
|
| + std::shared_ptr<Type> returnType = expand_generics(decl.fReturnType, i);
|
| + std::vector<std::shared_ptr<Variable>> arguments;
|
| for (const auto& p : decl.fParameters) {
|
| - Variable* var = new Variable(p->fPosition, Modifiers(p->fModifiers), p->fName,
|
| - expand_generics(p->fType, i),
|
| - Variable::kParameter_Storage);
|
| - symbolTable->takeOwnership(var);
|
| - parameters.push_back(var);
|
| - }
|
| - symbolTable->add(decl.fName, std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(
|
| - decl.fPosition,
|
| - decl.fName,
|
| - std::move(parameters),
|
| - std::move(returnType))));
|
| + arguments.push_back(std::shared_ptr<Variable>(new Variable(
|
| + p->fPosition,
|
| + Modifiers(p->fModifiers),
|
| + p->fName,
|
| + expand_generics(p->fType, i),
|
| + Variable::kParameter_Storage)));
|
| + }
|
| + std::shared_ptr<FunctionDeclaration> expanded(new FunctionDeclaration(
|
| + decl.fPosition,
|
| + decl.fName,
|
| + std::move(arguments),
|
| + std::move(returnType)));
|
| + symbolTable.add(expanded->fName, expanded);
|
| }
|
| }
|
|
|
| std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFunction& f) {
|
| + std::shared_ptr<SymbolTable> old = fSymbolTable;
|
| + AutoSymbolTable table(this);
|
| bool isGeneric;
|
| - const Type* returnType = this->convertType(*f.fReturnType);
|
| + std::shared_ptr<Type> returnType = this->convertType(*f.fReturnType);
|
| if (!returnType) {
|
| return nullptr;
|
| }
|
| isGeneric = returnType->kind() == Type::kGeneric_Kind;
|
| - std::vector<const Variable*> parameters;
|
| + std::vector<std::shared_ptr<Variable>> parameters;
|
| for (const auto& param : f.fParameters) {
|
| - const Type* type = this->convertType(*param->fType);
|
| + std::shared_ptr<Type> type = this->convertType(*param->fType);
|
| if (!type) {
|
| return nullptr;
|
| }
|
| for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
|
| int size = param->fSizes[j];
|
| std::string name = type->name() + "[" + to_string(size) + "]";
|
| - Type* newType = new Type(std::move(name), Type::kArray_Kind, *type, size);
|
| - fSymbolTable->takeOwnership(newType);
|
| - type = newType;
|
| + type = std::shared_ptr<Type>(new Type(std::move(name), Type::kArray_Kind,
|
| + std::move(type), size));
|
| }
|
| std::string name = param->fName;
|
| Modifiers modifiers = this->convertModifiers(param->fModifiers);
|
| Position pos = param->fPosition;
|
| - Variable* var = new Variable(pos, modifiers, std::move(name), *type,
|
| - Variable::kParameter_Storage);
|
| - fSymbolTable->takeOwnership(var);
|
| - parameters.push_back(var);
|
| + std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable(
|
| + pos,
|
| + modifiers,
|
| + std::move(name),
|
| + type,
|
| + Variable::kParameter_Storage));
|
| + parameters.push_back(std::move(var));
|
| isGeneric |= type->kind() == Type::kGeneric_Kind;
|
| }
|
|
|
| // find existing declaration
|
| - const FunctionDeclaration* decl = nullptr;
|
| - auto entry = (*fSymbolTable)[f.fName];
|
| + std::shared_ptr<FunctionDeclaration> decl;
|
| + auto entry = (*old)[f.fName];
|
| if (entry) {
|
| - std::vector<const FunctionDeclaration*> functions;
|
| + std::vector<std::shared_ptr<FunctionDeclaration>> functions;
|
| switch (entry->fKind) {
|
| case Symbol::kUnresolvedFunction_Kind:
|
| - functions = ((UnresolvedFunction*) entry)->fFunctions;
|
| + functions = std::static_pointer_cast<UnresolvedFunction>(entry)->fFunctions;
|
| break;
|
| case Symbol::kFunctionDeclaration_Kind:
|
| - functions.push_back((FunctionDeclaration*) entry);
|
| + functions.push_back(std::static_pointer_cast<FunctionDeclaration>(entry));
|
| break;
|
| default:
|
| fErrors.error(f.fPosition, "symbol '" + f.fName + "' was already defined");
|
| @@ -401,8 +406,11 @@
|
| }
|
| }
|
| if (match) {
|
| - if (*returnType != other->fReturnType) {
|
| - FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType);
|
| + if (returnType != other->fReturnType) {
|
| + FunctionDeclaration newDecl = FunctionDeclaration(f.fPosition,
|
| + f.fName,
|
| + parameters,
|
| + returnType);
|
| fErrors.error(f.fPosition, "functions '" + newDecl.description() +
|
| "' and '" + other->description() +
|
| "' differ only in return type");
|
| @@ -416,6 +424,7 @@
|
| "declaration and definition");
|
| return nullptr;
|
| }
|
| + fSymbolTable->add(parameters[i]->fName, decl->fParameters[i]);
|
| }
|
| if (other->fDefined) {
|
| fErrors.error(f.fPosition, "duplicate definition of " +
|
| @@ -428,36 +437,28 @@
|
| }
|
| if (!decl) {
|
| // couldn't find an existing declaration
|
| - if (isGeneric) {
|
| - ASSERT(!f.fBody);
|
| - expand_generics(FunctionDeclaration(f.fPosition, f.fName, parameters, *returnType),
|
| - fSymbolTable);
|
| - } else {
|
| - auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(
|
| - f.fPosition,
|
| - f.fName,
|
| - parameters,
|
| - *returnType));
|
| - decl = newDecl.get();
|
| - fSymbolTable->add(decl->fName, std::move(newDecl));
|
| - }
|
| - }
|
| - if (f.fBody) {
|
| - ASSERT(!fCurrentFunction);
|
| - fCurrentFunction = decl;
|
| - decl->fDefined = true;
|
| - std::shared_ptr<SymbolTable> old = fSymbolTable;
|
| - AutoSymbolTable table(this);
|
| - for (size_t i = 0; i < parameters.size(); i++) {
|
| - fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
|
| - }
|
| - std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
|
| - fCurrentFunction = nullptr;
|
| - if (!body) {
|
| - return nullptr;
|
| - }
|
| - return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
|
| - std::move(body)));
|
| + decl.reset(new FunctionDeclaration(f.fPosition, f.fName, parameters, returnType));
|
| + for (auto var : parameters) {
|
| + fSymbolTable->add(var->fName, var);
|
| + }
|
| + }
|
| + if (isGeneric) {
|
| + ASSERT(!f.fBody);
|
| + expand_generics(*decl, *old);
|
| + } else {
|
| + old->add(decl->fName, decl);
|
| + if (f.fBody) {
|
| + ASSERT(!fCurrentFunction);
|
| + fCurrentFunction = decl;
|
| + decl->fDefined = true;
|
| + std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
|
| + fCurrentFunction = nullptr;
|
| + if (!body) {
|
| + return nullptr;
|
| + }
|
| + return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, decl,
|
| + std::move(body)));
|
| + }
|
| }
|
| return nullptr;
|
| }
|
| @@ -487,26 +488,28 @@
|
| }
|
| }
|
| }
|
| - Type* type = new Type(intf.fInterfaceName, fields);
|
| - fSymbolTable->takeOwnership(type);
|
| + std::shared_ptr<Type> type = std::shared_ptr<Type>(new Type(intf.fInterfaceName, fields));
|
| std::string name = intf.fValueName.length() > 0 ? intf.fValueName : intf.fInterfaceName;
|
| - Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage);
|
| - fSymbolTable->takeOwnership(var);
|
| + std::shared_ptr<Variable> var = std::shared_ptr<Variable>(new Variable(intf.fPosition, mods,
|
| + name, type,
|
| + Variable::kGlobal_Storage));
|
| if (intf.fValueName.length()) {
|
| - old->addWithoutOwnership(intf.fValueName, var);
|
| + old->add(intf.fValueName, var);
|
| +
|
| } else {
|
| for (size_t i = 0; i < fields.size(); i++) {
|
| - old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
|
| - (int) i)));
|
| - }
|
| - }
|
| - return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, fSymbolTable));
|
| -}
|
| -
|
| -const Type* IRGenerator::convertType(const ASTType& type) {
|
| - const Symbol* result = (*fSymbolTable)[type.fName];
|
| + std::shared_ptr<Field> field = std::shared_ptr<Field>(new Field(intf.fPosition, var,
|
| + (int) i));
|
| + old->add(fields[i].fName, field);
|
| + }
|
| + }
|
| + return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, var));
|
| +}
|
| +
|
| +std::shared_ptr<Type> IRGenerator::convertType(const ASTType& type) {
|
| + std::shared_ptr<Symbol> result = (*fSymbolTable)[type.fName];
|
| if (result && result->fKind == Symbol::kType_Kind) {
|
| - return (const Type*) result;
|
| + return std::static_pointer_cast<Type>(result);
|
| }
|
| fErrors.error(type.fPosition, "unknown type '" + type.fName + "'");
|
| return nullptr;
|
| @@ -539,40 +542,40 @@
|
| }
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
|
| - const Symbol* result = (*fSymbolTable)[identifier.fText];
|
| + std::shared_ptr<Symbol> result = (*fSymbolTable)[identifier.fText];
|
| if (!result) {
|
| fErrors.error(identifier.fPosition, "unknown identifier '" + identifier.fText + "'");
|
| return nullptr;
|
| }
|
| switch (result->fKind) {
|
| case Symbol::kFunctionDeclaration_Kind: {
|
| - std::vector<const FunctionDeclaration*> f = {
|
| - (const FunctionDeclaration*) result
|
| + std::vector<std::shared_ptr<FunctionDeclaration>> f = {
|
| + std::static_pointer_cast<FunctionDeclaration>(result)
|
| };
|
| return std::unique_ptr<FunctionReference>(new FunctionReference(identifier.fPosition,
|
| - f));
|
| + std::move(f)));
|
| }
|
| case Symbol::kUnresolvedFunction_Kind: {
|
| - const UnresolvedFunction* f = (const UnresolvedFunction*) result;
|
| + auto f = std::static_pointer_cast<UnresolvedFunction>(result);
|
| return std::unique_ptr<FunctionReference>(new FunctionReference(identifier.fPosition,
|
| f->fFunctions));
|
| }
|
| case Symbol::kVariable_Kind: {
|
| - const Variable* var = (const Variable*) result;
|
| - this->markReadFrom(*var);
|
| + std::shared_ptr<Variable> var = std::static_pointer_cast<Variable>(result);
|
| + this->markReadFrom(var);
|
| return std::unique_ptr<VariableReference>(new VariableReference(identifier.fPosition,
|
| - *var));
|
| + std::move(var)));
|
| }
|
| case Symbol::kField_Kind: {
|
| - const Field* field = (const Field*) result;
|
| + std::shared_ptr<Field> field = std::static_pointer_cast<Field>(result);
|
| VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner);
|
| return std::unique_ptr<Expression>(new FieldAccess(std::unique_ptr<Expression>(base),
|
| field->fFieldIndex));
|
| }
|
| case Symbol::kType_Kind: {
|
| - const Type* t = (const Type*) result;
|
| + auto t = std::static_pointer_cast<Type>(result);
|
| return std::unique_ptr<TypeReference>(new TypeReference(identifier.fPosition,
|
| - *t));
|
| + std::move(t)));
|
| }
|
| default:
|
| ABORT("unsupported symbol type %d\n", result->fKind);
|
| @@ -581,42 +584,43 @@
|
| }
|
|
|
| std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
|
| - const Type& type) {
|
| + std::shared_ptr<Type> type) {
|
| if (!expr) {
|
| return nullptr;
|
| }
|
| - if (expr->fType == type) {
|
| + if (*expr->fType == *type) {
|
| return expr;
|
| }
|
| this->checkValid(*expr);
|
| - if (expr->fType == *kInvalid_Type) {
|
| - return nullptr;
|
| - }
|
| - if (!expr->fType.canCoerceTo(type)) {
|
| - fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
|
| - expr->fType.description() + "'");
|
| - return nullptr;
|
| - }
|
| - if (type.kind() == Type::kScalar_Kind) {
|
| + if (*expr->fType == *kInvalid_Type) {
|
| + return nullptr;
|
| + }
|
| + if (!expr->fType->canCoerceTo(type)) {
|
| + fErrors.error(expr->fPosition, "expected '" + type->description() + "', but found '" +
|
| + expr->fType->description() + "'");
|
| + return nullptr;
|
| + }
|
| + if (type->kind() == Type::kScalar_Kind) {
|
| std::vector<std::unique_ptr<Expression>> args;
|
| args.push_back(std::move(expr));
|
| - ASTIdentifier id(Position(), type.description());
|
| + ASTIdentifier id(Position(), type->description());
|
| std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
|
| ASSERT(ctor);
|
| return this->call(Position(), std::move(ctor), std::move(args));
|
| }
|
| - ABORT("cannot coerce %s to %s", expr->fType.description().c_str(),
|
| - type.description().c_str());
|
| + ABORT("cannot coerce %s to %s", expr->fType->description().c_str(),
|
| + type->description().c_str());
|
| }
|
|
|
| /**
|
| * Determines the operand and result types of a binary expression. Returns true if the expression is
|
| * legal, false otherwise. If false, the values of the out parameters are undefined.
|
| */
|
| -static bool determine_binary_type(Token::Kind op, const Type& left, const Type& right,
|
| - const Type** outLeftType,
|
| - const Type** outRightType,
|
| - const Type** outResultType,
|
| +static bool determine_binary_type(Token::Kind op, std::shared_ptr<Type> left,
|
| + std::shared_ptr<Type> right,
|
| + std::shared_ptr<Type>* outLeftType,
|
| + std::shared_ptr<Type>* outRightType,
|
| + std::shared_ptr<Type>* outResultType,
|
| bool tryFlipped) {
|
| bool isLogical;
|
| switch (op) {
|
| @@ -637,21 +641,21 @@
|
| *outLeftType = kBool_Type;
|
| *outRightType = kBool_Type;
|
| *outResultType = kBool_Type;
|
| - return left.canCoerceTo(*kBool_Type) && right.canCoerceTo(*kBool_Type);
|
| + return left->canCoerceTo(kBool_Type) && right->canCoerceTo(kBool_Type);
|
| case Token::STAR: // fall through
|
| case Token::STAREQ:
|
| // FIXME need to handle non-square matrices
|
| - if (left.kind() == Type::kMatrix_Kind && right.kind() == Type::kVector_Kind) {
|
| - *outLeftType = &left;
|
| - *outRightType = &right;
|
| - *outResultType = &right;
|
| - return left.rows() == right.columns();
|
| + if (left->kind() == Type::kMatrix_Kind && right->kind() == Type::kVector_Kind) {
|
| + *outLeftType = left;
|
| + *outRightType = right;
|
| + *outResultType = right;
|
| + return left->rows() == right->columns();
|
| }
|
| - if (left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind) {
|
| - *outLeftType = &left;
|
| - *outRightType = &right;
|
| - *outResultType = &left;
|
| - return left.columns() == right.columns();
|
| + if (left->kind() == Type::kVector_Kind && right->kind() == Type::kMatrix_Kind) {
|
| + *outLeftType = left;
|
| + *outRightType = right;
|
| + *outResultType = left;
|
| + return left->columns() == right->columns();
|
| }
|
| // fall through
|
| default:
|
| @@ -660,33 +664,33 @@
|
| // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have
|
| // full support for numbers other than float.
|
| if (left == right) {
|
| - *outLeftType = &left;
|
| - *outRightType = &left;
|
| + *outLeftType = left;
|
| + *outRightType = left;
|
| if (isLogical) {
|
| *outResultType = kBool_Type;
|
| } else {
|
| - *outResultType = &left;
|
| + *outResultType = left;
|
| }
|
| return true;
|
| }
|
| // FIXME: incorrect for shift operations
|
| - if (left.canCoerceTo(right)) {
|
| - *outLeftType = &right;
|
| - *outRightType = &right;
|
| + if (left->canCoerceTo(right)) {
|
| + *outLeftType = right;
|
| + *outRightType = right;
|
| if (isLogical) {
|
| *outResultType = kBool_Type;
|
| } else {
|
| - *outResultType = &right;
|
| + *outResultType = right;
|
| }
|
| return true;
|
| }
|
| - if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
|
| - (right.kind() == Type::kScalar_Kind)) {
|
| - if (determine_binary_type(op, left.componentType(), right, outLeftType, outRightType,
|
| + if ((left->kind() == Type::kVector_Kind || left->kind() == Type::kMatrix_Kind) &&
|
| + (right->kind() == Type::kScalar_Kind)) {
|
| + if (determine_binary_type(op, left->componentType(), right, outLeftType, outRightType,
|
| outResultType, false)) {
|
| - *outLeftType = &(*outLeftType)->toCompound(left.columns(), left.rows());
|
| + *outLeftType = (*outLeftType)->toCompound(left->columns(), left->rows());
|
| if (!isLogical) {
|
| - *outResultType = &(*outResultType)->toCompound(left.columns(), left.rows());
|
| + *outResultType = (*outResultType)->toCompound(left->columns(), left->rows());
|
| }
|
| return true;
|
| }
|
| @@ -709,15 +713,15 @@
|
| if (!right) {
|
| return nullptr;
|
| }
|
| - const Type* leftType;
|
| - const Type* rightType;
|
| - const Type* resultType;
|
| + std::shared_ptr<Type> leftType;
|
| + std::shared_ptr<Type> rightType;
|
| + std::shared_ptr<Type> resultType;
|
| if (!determine_binary_type(expression.fOperator, left->fType, right->fType, &leftType,
|
| &rightType, &resultType, true)) {
|
| fErrors.error(expression.fPosition, "type mismatch: '" +
|
| Token::OperatorName(expression.fOperator) +
|
| - "' cannot operate on '" + left->fType.fName +
|
| - "', '" + right->fType.fName + "'");
|
| + "' cannot operate on '" + left->fType->fName +
|
| + "', '" + right->fType->fName + "'");
|
| return nullptr;
|
| }
|
| switch (expression.fOperator) {
|
| @@ -740,18 +744,17 @@
|
| break;
|
| }
|
| return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
|
| - this->coerce(std::move(left),
|
| - *leftType),
|
| + this->coerce(std::move(left), leftType),
|
| expression.fOperator,
|
| this->coerce(std::move(right),
|
| - *rightType),
|
| - *resultType));
|
| + rightType),
|
| + resultType));
|
| }
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
|
| const ASTTernaryExpression& expression) {
|
| std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
|
| - *kBool_Type);
|
| + kBool_Type);
|
| if (!test) {
|
| return nullptr;
|
| }
|
| @@ -763,33 +766,34 @@
|
| if (!ifFalse) {
|
| return nullptr;
|
| }
|
| - const Type* trueType;
|
| - const Type* falseType;
|
| - const Type* resultType;
|
| + std::shared_ptr<Type> trueType;
|
| + std::shared_ptr<Type> falseType;
|
| + std::shared_ptr<Type> resultType;
|
| if (!determine_binary_type(Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
|
| &falseType, &resultType, true)) {
|
| fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
|
| - ifTrue->fType.fName + "', '" +
|
| - ifFalse->fType.fName + "'");
|
| + ifTrue->fType->fName + "', '" +
|
| + ifFalse->fType->fName + "'");
|
| return nullptr;
|
| }
|
| ASSERT(trueType == falseType);
|
| - ifTrue = this->coerce(std::move(ifTrue), *trueType);
|
| - ifFalse = this->coerce(std::move(ifFalse), *falseType);
|
| + ifTrue = this->coerce(std::move(ifTrue), trueType);
|
| + ifFalse = this->coerce(std::move(ifFalse), falseType);
|
| return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
|
| std::move(test),
|
| std::move(ifTrue),
|
| std::move(ifFalse)));
|
| }
|
|
|
| -std::unique_ptr<Expression> IRGenerator::call(Position position,
|
| - const FunctionDeclaration& function,
|
| - std::vector<std::unique_ptr<Expression>> arguments) {
|
| - if (function.fParameters.size() != arguments.size()) {
|
| - std::string msg = "call to '" + function.fName + "' expected " +
|
| - to_string(function.fParameters.size()) +
|
| +std::unique_ptr<Expression> IRGenerator::call(
|
| + Position position,
|
| + std::shared_ptr<FunctionDeclaration> function,
|
| + std::vector<std::unique_ptr<Expression>> arguments) {
|
| + if (function->fParameters.size() != arguments.size()) {
|
| + std::string msg = "call to '" + function->fName + "' expected " +
|
| + to_string(function->fParameters.size()) +
|
| " argument";
|
| - if (function.fParameters.size() != 1) {
|
| + if (function->fParameters.size() != 1) {
|
| msg += "s";
|
| }
|
| msg += ", but found " + to_string(arguments.size());
|
| @@ -797,12 +801,12 @@
|
| return nullptr;
|
| }
|
| for (size_t i = 0; i < arguments.size(); i++) {
|
| - arguments[i] = this->coerce(std::move(arguments[i]), function.fParameters[i]->fType);
|
| - if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
|
| + arguments[i] = this->coerce(std::move(arguments[i]), function->fParameters[i]->fType);
|
| + if (arguments[i] && (function->fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
|
| this->markWrittenTo(*arguments[i]);
|
| }
|
| }
|
| - return std::unique_ptr<FunctionCall>(new FunctionCall(position, function,
|
| + return std::unique_ptr<FunctionCall>(new FunctionCall(position, std::move(function),
|
| std::move(arguments)));
|
| }
|
|
|
| @@ -811,16 +815,16 @@
|
| * if the cost could be computed, false if the call is not valid. Cost has no particular meaning
|
| * other than "lower costs are preferred".
|
| */
|
| -bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
|
| +bool IRGenerator::determineCallCost(std::shared_ptr<FunctionDeclaration> function,
|
| const std::vector<std::unique_ptr<Expression>>& arguments,
|
| int* outCost) {
|
| - if (function.fParameters.size() != arguments.size()) {
|
| + if (function->fParameters.size() != arguments.size()) {
|
| return false;
|
| }
|
| int total = 0;
|
| for (size_t i = 0; i < arguments.size(); i++) {
|
| int cost;
|
| - if (arguments[i]->fType.determineCoercionCost(function.fParameters[i]->fType, &cost)) {
|
| + if (arguments[i]->fType->determineCoercionCost(function->fParameters[i]->fType, &cost)) {
|
| total += cost;
|
| } else {
|
| return false;
|
| @@ -844,43 +848,43 @@
|
| }
|
| FunctionReference* ref = (FunctionReference*) functionValue.get();
|
| int bestCost = INT_MAX;
|
| - const FunctionDeclaration* best = nullptr;
|
| + std::shared_ptr<FunctionDeclaration> best;
|
| if (ref->fFunctions.size() > 1) {
|
| for (const auto& f : ref->fFunctions) {
|
| int cost;
|
| - if (this->determineCallCost(*f, arguments, &cost) && cost < bestCost) {
|
| + if (this->determineCallCost(f, arguments, &cost) && cost < bestCost) {
|
| bestCost = cost;
|
| best = f;
|
| }
|
| }
|
| if (best) {
|
| - return this->call(position, *best, std::move(arguments));
|
| + return this->call(position, std::move(best), std::move(arguments));
|
| }
|
| std::string msg = "no match for " + ref->fFunctions[0]->fName + "(";
|
| std::string separator = "";
|
| for (size_t i = 0; i < arguments.size(); i++) {
|
| msg += separator;
|
| separator = ", ";
|
| - msg += arguments[i]->fType.description();
|
| + msg += arguments[i]->fType->description();
|
| }
|
| msg += ")";
|
| fErrors.error(position, msg);
|
| return nullptr;
|
| }
|
| - return this->call(position, *ref->fFunctions[0], std::move(arguments));
|
| + return this->call(position, ref->fFunctions[0], std::move(arguments));
|
| }
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
| Position position,
|
| - const Type& type,
|
| + std::shared_ptr<Type> type,
|
| std::vector<std::unique_ptr<Expression>> args) {
|
| // FIXME: add support for structs and arrays
|
| - Type::Kind kind = type.kind();
|
| - if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) {
|
| - fErrors.error(position, "cannot construct '" + type.description() + "'");
|
| - return nullptr;
|
| - }
|
| - if (type == *kFloat_Type && args.size() == 1 &&
|
| + Type::Kind kind = type->kind();
|
| + if (!type->isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) {
|
| + fErrors.error(position, "cannot construct '" + type->description() + "'");
|
| + return nullptr;
|
| + }
|
| + if (type == kFloat_Type && args.size() == 1 &&
|
| args[0]->fKind == Expression::kIntLiteral_Kind) {
|
| int64_t value = ((IntLiteral&) *args[0]).fValue;
|
| return std::unique_ptr<Expression>(new FloatLiteral(position, (double) value));
|
| @@ -889,13 +893,13 @@
|
| // argument is already the right type, just return it
|
| return std::move(args[0]);
|
| }
|
| - if (type.isNumber()) {
|
| + if (type->isNumber()) {
|
| if (args.size() != 1) {
|
| - fErrors.error(position, "invalid arguments to '" + type.description() +
|
| + fErrors.error(position, "invalid arguments to '" + type->description() +
|
| "' constructor, (expected exactly 1 argument, but found " +
|
| to_string(args.size()) + ")");
|
| }
|
| - if (args[0]->fType == *kBool_Type) {
|
| + if (args[0]->fType == kBool_Type) {
|
| std::unique_ptr<IntLiteral> zero(new IntLiteral(position, 0));
|
| std::unique_ptr<IntLiteral> one(new IntLiteral(position, 1));
|
| return std::unique_ptr<Expression>(
|
| @@ -903,38 +907,38 @@
|
| this->coerce(std::move(one), type),
|
| this->coerce(std::move(zero),
|
| type)));
|
| - } else if (!args[0]->fType.isNumber()) {
|
| - fErrors.error(position, "invalid argument to '" + type.description() +
|
| + } else if (!args[0]->fType->isNumber()) {
|
| + fErrors.error(position, "invalid argument to '" + type->description() +
|
| "' constructor (expected a number or bool, but found '" +
|
| - args[0]->fType.description() + "')");
|
| + args[0]->fType->description() + "')");
|
| }
|
| } else {
|
| ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
|
| int actual = 0;
|
| for (size_t i = 0; i < args.size(); i++) {
|
| - if (args[i]->fType.kind() == Type::kVector_Kind ||
|
| - args[i]->fType.kind() == Type::kMatrix_Kind) {
|
| - int columns = args[i]->fType.columns();
|
| - int rows = args[i]->fType.rows();
|
| + if (args[i]->fType->kind() == Type::kVector_Kind ||
|
| + args[i]->fType->kind() == Type::kMatrix_Kind) {
|
| + int columns = args[i]->fType->columns();
|
| + int rows = args[i]->fType->rows();
|
| args[i] = this->coerce(std::move(args[i]),
|
| - type.componentType().toCompound(columns, rows));
|
| - actual += args[i]->fType.rows() * args[i]->fType.columns();
|
| - } else if (args[i]->fType.kind() == Type::kScalar_Kind) {
|
| + type->componentType()->toCompound(columns, rows));
|
| + actual += args[i]->fType->rows() * args[i]->fType->columns();
|
| + } else if (args[i]->fType->kind() == Type::kScalar_Kind) {
|
| actual += 1;
|
| - if (type.kind() != Type::kScalar_Kind) {
|
| - args[i] = this->coerce(std::move(args[i]), type.componentType());
|
| + if (type->kind() != Type::kScalar_Kind) {
|
| + args[i] = this->coerce(std::move(args[i]), type->componentType());
|
| }
|
| } else {
|
| - fErrors.error(position, "'" + args[i]->fType.description() + "' is not a valid "
|
| - "parameter to '" + type.description() + "' constructor");
|
| + fErrors.error(position, "'" + args[i]->fType->description() + "' is not a valid "
|
| + "parameter to '" + type->description() + "' constructor");
|
| return nullptr;
|
| }
|
| }
|
| - int min = type.rows() * type.columns();
|
| - int max = type.columns() > 1 ? INT_MAX : min;
|
| + int min = type->rows() * type->columns();
|
| + int max = type->columns() > 1 ? INT_MAX : min;
|
| if ((actual < min || actual > max) &&
|
| !((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) {
|
| - fErrors.error(position, "invalid arguments to '" + type.description() +
|
| + fErrors.error(position, "invalid arguments to '" + type->description() +
|
| "' constructor (expected " + to_string(min) + " scalar" +
|
| (min == 1 ? "" : "s") + ", but found " + to_string(actual) +
|
| ")");
|
| @@ -952,16 +956,16 @@
|
| }
|
| switch (expression.fOperator) {
|
| case Token::PLUS:
|
| - if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
|
| + if (!base->fType->isNumber() && base->fType->kind() != Type::kVector_Kind) {
|
| fErrors.error(expression.fPosition,
|
| - "'+' cannot operate on '" + base->fType.description() + "'");
|
| + "'+' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| return base;
|
| case Token::MINUS:
|
| - if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
|
| + if (!base->fType->isNumber() && base->fType->kind() != Type::kVector_Kind) {
|
| fErrors.error(expression.fPosition,
|
| - "'-' cannot operate on '" + base->fType.description() + "'");
|
| + "'-' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| if (base->fKind == Expression::kIntLiteral_Kind) {
|
| @@ -974,28 +978,28 @@
|
| }
|
| return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
|
| case Token::PLUSPLUS:
|
| - if (!base->fType.isNumber()) {
|
| + if (!base->fType->isNumber()) {
|
| fErrors.error(expression.fPosition,
|
| "'" + Token::OperatorName(expression.fOperator) +
|
| - "' cannot operate on '" + base->fType.description() + "'");
|
| + "' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| this->markWrittenTo(*base);
|
| break;
|
| case Token::MINUSMINUS:
|
| - if (!base->fType.isNumber()) {
|
| + if (!base->fType->isNumber()) {
|
| fErrors.error(expression.fPosition,
|
| "'" + Token::OperatorName(expression.fOperator) +
|
| - "' cannot operate on '" + base->fType.description() + "'");
|
| + "' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| this->markWrittenTo(*base);
|
| break;
|
| case Token::NOT:
|
| - if (base->fType != *kBool_Type) {
|
| + if (base->fType != kBool_Type) {
|
| fErrors.error(expression.fPosition,
|
| "'" + Token::OperatorName(expression.fOperator) +
|
| - "' cannot operate on '" + base->fType.description() + "'");
|
| + "' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| break;
|
| @@ -1008,8 +1012,8 @@
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
|
| const ASTExpression& index) {
|
| - if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind) {
|
| - fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
|
| + if (base->fType->kind() != Type::kArray_Kind && base->fType->kind() != Type::kMatrix_Kind) {
|
| + fErrors.error(base->fPosition, "expected array, but found '" + base->fType->description() +
|
| "'");
|
| return nullptr;
|
| }
|
| @@ -1017,7 +1021,7 @@
|
| if (!converted) {
|
| return nullptr;
|
| }
|
| - converted = this->coerce(std::move(converted), *kInt_Type);
|
| + converted = this->coerce(std::move(converted), kInt_Type);
|
| if (!converted) {
|
| return nullptr;
|
| }
|
| @@ -1026,21 +1030,21 @@
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
|
| const std::string& field) {
|
| - auto fields = base->fType.fields();
|
| + auto fields = base->fType->fields();
|
| for (size_t i = 0; i < fields.size(); i++) {
|
| if (fields[i].fName == field) {
|
| return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
|
| }
|
| }
|
| - fErrors.error(base->fPosition, "type '" + base->fType.description() + "' does not have a "
|
| + fErrors.error(base->fPosition, "type '" + base->fType->description() + "' does not have a "
|
| "field named '" + field + "");
|
| return nullptr;
|
| }
|
|
|
| std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
|
| const std::string& fields) {
|
| - if (base->fType.kind() != Type::kVector_Kind) {
|
| - fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType.description() + "'");
|
| + if (base->fType->kind() != Type::kVector_Kind) {
|
| + fErrors.error(base->fPosition, "cannot swizzle type '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| std::vector<int> swizzleComponents;
|
| @@ -1054,7 +1058,7 @@
|
| case 'y': // fall through
|
| case 'g': // fall through
|
| case 't':
|
| - if (base->fType.columns() >= 2) {
|
| + if (base->fType->columns() >= 2) {
|
| swizzleComponents.push_back(1);
|
| break;
|
| }
|
| @@ -1062,7 +1066,7 @@
|
| case 'z': // fall through
|
| case 'b': // fall through
|
| case 'p':
|
| - if (base->fType.columns() >= 3) {
|
| + if (base->fType->columns() >= 3) {
|
| swizzleComponents.push_back(2);
|
| break;
|
| }
|
| @@ -1070,7 +1074,7 @@
|
| case 'w': // fall through
|
| case 'a': // fall through
|
| case 'q':
|
| - if (base->fType.columns() >= 4) {
|
| + if (base->fType->columns() >= 4) {
|
| swizzleComponents.push_back(3);
|
| break;
|
| }
|
| @@ -1113,7 +1117,7 @@
|
| return this->call(expression.fPosition, std::move(base), std::move(arguments));
|
| }
|
| case ASTSuffix::kField_Kind: {
|
| - switch (base->fType.kind()) {
|
| + switch (base->fType->kind()) {
|
| case Type::kVector_Kind:
|
| return this->convertSwizzle(std::move(base),
|
| ((ASTFieldSuffix&) *expression.fSuffix).fField);
|
| @@ -1122,23 +1126,23 @@
|
| ((ASTFieldSuffix&) *expression.fSuffix).fField);
|
| default:
|
| fErrors.error(base->fPosition, "cannot swizzle value of type '" +
|
| - base->fType.description() + "'");
|
| + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| }
|
| case ASTSuffix::kPostIncrement_Kind:
|
| - if (!base->fType.isNumber()) {
|
| + if (!base->fType->isNumber()) {
|
| fErrors.error(expression.fPosition,
|
| - "'++' cannot operate on '" + base->fType.description() + "'");
|
| + "'++' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| this->markWrittenTo(*base);
|
| return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
|
| Token::PLUSPLUS));
|
| case ASTSuffix::kPostDecrement_Kind:
|
| - if (!base->fType.isNumber()) {
|
| + if (!base->fType->isNumber()) {
|
| fErrors.error(expression.fPosition,
|
| - "'--' cannot operate on '" + base->fType.description() + "'");
|
| + "'--' cannot operate on '" + base->fType->description() + "'");
|
| return nullptr;
|
| }
|
| this->markWrittenTo(*base);
|
| @@ -1158,13 +1162,13 @@
|
| fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
|
| break;
|
| default:
|
| - ASSERT(expr.fType != *kInvalid_Type);
|
| + ASSERT(expr.fType != kInvalid_Type);
|
| break;
|
| }
|
| }
|
|
|
| -void IRGenerator::markReadFrom(const Variable& var) {
|
| - var.fIsReadFrom = true;
|
| +void IRGenerator::markReadFrom(std::shared_ptr<Variable> var) {
|
| + var->fIsReadFrom = true;
|
| }
|
|
|
| static bool has_duplicates(const Swizzle& swizzle) {
|
| @@ -1183,7 +1187,7 @@
|
| void IRGenerator::markWrittenTo(const Expression& expr) {
|
| switch (expr.fKind) {
|
| case Expression::kVariableReference_Kind: {
|
| - const Variable& var = ((VariableReference&) expr).fVariable;
|
| + const Variable& var = *((VariableReference&) expr).fVariable;
|
| if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
|
| fErrors.error(expr.fPosition,
|
| "cannot modify immutable variable '" + var.fName + "'");
|
|
|