From 11d53974317fa29cc516075382e658ddd45fc151 Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Mon, 28 Nov 2016 11:23:23 -0500 Subject: [PATCH] unified ASTLayout/Layout and ASTModifiers/Modifiers BUG=skia: Change-Id: Ib4c2c94401e586e93e926776e13c0f7c12212f7e Reviewed-on: https://skia-review.googlesource.com/5268 Reviewed-by: Brian Salomon Commit-Queue: Ethan Nicholas --- src/sksl/SkSLIRGenerator.cpp | 229 ++++++++++----------- src/sksl/SkSLIRGenerator.h | 27 ++- src/sksl/SkSLParser.cpp | 149 +++++++------- src/sksl/SkSLParser.h | 28 +-- src/sksl/ast/SkSLASTInterfaceBlock.h | 11 +- src/sksl/ast/SkSLASTLayout.h | 164 --------------- src/sksl/ast/SkSLASTModifiers.h | 78 ------- src/sksl/ast/SkSLASTModifiersDeclaration.h | 8 +- src/sksl/ast/SkSLASTParameter.h | 10 +- src/sksl/ast/SkSLASTVarDeclaration.h | 14 +- src/sksl/ir/SkSLLayout.h | 84 ++++++-- src/sksl/ir/SkSLModifiers.h | 29 ++- 12 files changed, 313 insertions(+), 518 deletions(-) delete mode 100644 src/sksl/ast/SkSLASTLayout.h delete mode 100644 src/sksl/ast/SkSLASTModifiers.h diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index aec4aab81f..882464a09f 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #include "SkSLIRGenerator.h" #include "limits.h" @@ -51,7 +51,7 @@ namespace SkSL { class AutoSymbolTable { public: - AutoSymbolTable(IRGenerator* ir) + AutoSymbolTable(IRGenerator* ir) : fIR(ir) , fPrevious(fIR->fSymbolTable) { fIR->pushSymbolTable(); @@ -68,7 +68,7 @@ public: class AutoLoopLevel { public: - AutoLoopLevel(IRGenerator* ir) + AutoLoopLevel(IRGenerator* ir) : fIR(ir) { fIR->fLoopLevel++; } @@ -80,7 +80,7 @@ public: IRGenerator* fIR; }; -IRGenerator::IRGenerator(const Context* context, std::shared_ptr symbolTable, +IRGenerator::IRGenerator(const Context* context, std::shared_ptr symbolTable, ErrorReporter& errorReporter) : fContext(*context) , fCurrentFunction(nullptr) @@ -162,10 +162,6 @@ std::unique_ptr IRGenerator::convertVarDeclarationStatement( return std::unique_ptr(new VarDeclarationsStatement(std::move(decl))); } -Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) { - return Modifiers(modifiers); -} - std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl, Variable::Storage storage) { std::vector variables; @@ -174,7 +170,6 @@ std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVa return nullptr; } for (const auto& varDecl : decl.fVars) { - Modifiers modifiers = this->convertModifiers(decl.fModifiers); const Type* type = baseType; ASSERT(type->kind() != Type::kArray_Kind); std::vector> sizes; @@ -205,8 +200,8 @@ std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVa sizes.push_back(nullptr); } } - auto var = std::unique_ptr(new Variable(decl.fPosition, modifiers, varDecl.fName, - *type, storage)); + auto var = std::unique_ptr(new Variable(decl.fPosition, decl.fModifiers, + varDecl.fName, *type, storage)); std::unique_ptr value; if (varDecl.fValue) { value = this->convertExpression(*varDecl.fValue); @@ -215,7 +210,7 @@ std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVa } value = this->coerce(std::move(value), *type); } - if (storage == Variable::kGlobal_Storage && varDecl.fName == SkString("sk_FragColor") && + if (storage == Variable::kGlobal_Storage && varDecl.fName == SkString("sk_FragColor") && (*fSymbolTable)[varDecl.fName]) { // already defined, ignore } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] && @@ -229,19 +224,18 @@ std::unique_ptr IRGenerator::convertVarDeclarations(const ASTVa fSymbolTable->add(varDecl.fName, std::move(var)); } } - return std::unique_ptr(new VarDeclarations(decl.fPosition, + return std::unique_ptr(new VarDeclarations(decl.fPosition, baseType, std::move(variables))); } std::unique_ptr IRGenerator::convertModifiersDeclaration( const ASTModifiersDeclaration& m) { - Modifiers modifiers = this->convertModifiers(m.fModifiers); - return std::unique_ptr(new ModifiersDeclaration(modifiers)); + return std::unique_ptr(new ModifiersDeclaration(m.fModifiers)); } std::unique_ptr IRGenerator::convertIf(const ASTIfStatement& s) { - std::unique_ptr test = this->coerce(this->convertExpression(*s.fTest), + std::unique_ptr test = this->coerce(this->convertExpression(*s.fTest), *fContext.fBool_Type); if (!test) { return nullptr; @@ -266,11 +260,11 @@ std::unique_ptr IRGenerator::convertIf(const ASTIfStatement& s) { } else { // False & no else clause. Not an error, so don't return null! std::vector> empty; - return std::unique_ptr(new Block(s.fPosition, std::move(empty), + return std::unique_ptr(new Block(s.fPosition, std::move(empty), fSymbolTable)); } } - return std::unique_ptr(new IfStatement(s.fPosition, std::move(test), + return std::unique_ptr(new IfStatement(s.fPosition, std::move(test), std::move(ifTrue), std::move(ifFalse))); } @@ -303,14 +297,14 @@ std::unique_ptr IRGenerator::convertFor(const ASTForStatement& f) { if (!statement) { return nullptr; } - return std::unique_ptr(new ForStatement(f.fPosition, std::move(initializer), + return std::unique_ptr(new ForStatement(f.fPosition, std::move(initializer), std::move(test), std::move(next), std::move(statement), fSymbolTable)); } std::unique_ptr IRGenerator::convertWhile(const ASTWhileStatement& w) { AutoLoopLevel level(this); - std::unique_ptr test = this->coerce(this->convertExpression(*w.fTest), + std::unique_ptr test = this->coerce(this->convertExpression(*w.fTest), *fContext.fBool_Type); if (!test) { return nullptr; @@ -334,7 +328,7 @@ std::unique_ptr IRGenerator::convertDo(const ASTDoStatement& d) { if (!statement) { return nullptr; } - return std::unique_ptr(new DoStatement(d.fPosition, std::move(statement), + return std::unique_ptr(new DoStatement(d.fPosition, std::move(statement), std::move(test))); } @@ -414,9 +408,8 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti type = newType; } SkString name = param->fName; - Modifiers modifiers = this->convertModifiers(param->fModifiers); Position pos = param->fPosition; - Variable* var = new Variable(pos, modifiers, std::move(name), *type, + Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type, Variable::kParameter_Storage); fSymbolTable->takeOwnership(var); parameters.push_back(var); @@ -452,22 +445,22 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti if (*returnType != other->fReturnType) { FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType); fErrors.error(f.fPosition, "functions '" + newDecl.description() + - "' and '" + other->description() + + "' and '" + other->description() + "' differ only in return type"); return nullptr; } decl = other; for (size_t i = 0; i < parameters.size(); i++) { if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) { - fErrors.error(f.fPosition, "modifiers on parameter " + - to_string((uint64_t) i + 1) + + fErrors.error(f.fPosition, "modifiers on parameter " + + to_string((uint64_t) i + 1) + " differ between declaration and " "definition"); return nullptr; } } if (other->fDefined) { - fErrors.error(f.fPosition, "duplicate definition of " + + fErrors.error(f.fPosition, "duplicate definition of " + other->description()); } break; @@ -498,7 +491,7 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti if (!body) { return nullptr; } - return std::unique_ptr(new FunctionDefinition(f.fPosition, *decl, + return std::unique_ptr(new FunctionDefinition(f.fPosition, *decl, std::move(body))); } return nullptr; @@ -507,20 +500,19 @@ std::unique_ptr IRGenerator::convertFunction(const ASTFuncti std::unique_ptr IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) { std::shared_ptr old = fSymbolTable; AutoSymbolTable table(this); - Modifiers mods = this->convertModifiers(intf.fModifiers); std::vector fields; for (size_t i = 0; i < intf.fDeclarations.size(); i++) { std::unique_ptr decl = this->convertVarDeclarations( - *intf.fDeclarations[i], + *intf.fDeclarations[i], Variable::kGlobal_Storage); if (!decl) { return nullptr; } for (const auto& var : decl->fVars) { - fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName, + fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName, &var.fVar->fType)); if (var.fValue) { - fErrors.error(decl->fPosition, + fErrors.error(decl->fPosition, "initializers are not permitted on interface block fields"); } if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag | @@ -530,18 +522,19 @@ std::unique_ptr IRGenerator::convertInterfaceBlock(const ASTInte fErrors.error(decl->fPosition, "interface block fields may not have storage qualifiers"); } - } + } } Type* type = new Type(intf.fInterfaceName, fields); fSymbolTable->takeOwnership(type); SkString name = intf.fValueName.size() > 0 ? intf.fValueName : intf.fInterfaceName; - Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage); + Variable* var = new Variable(intf.fPosition, intf.fModifiers, name, *type, + Variable::kGlobal_Storage); fSymbolTable->takeOwnership(var); if (intf.fValueName.size()) { old->addWithoutOwnership(intf.fValueName, var); } else { for (size_t i = 0; i < fields.size(); i++) { - old->add(fields[i].fName, std::unique_ptr(new Field(intf.fPosition, *var, + old->add(fields[i].fName, std::unique_ptr(new Field(intf.fPosition, *var, (int) i))); } } @@ -620,7 +613,7 @@ std::unique_ptr IRGenerator::convertIdentifier(const ASTIdentifier& } case Symbol::kType_Kind: { const Type* t = (const Type*) result; - return std::unique_ptr(new TypeReference(fContext, identifier.fPosition, + return std::unique_ptr(new TypeReference(fContext, identifier.fPosition, *t)); } default: @@ -629,7 +622,7 @@ std::unique_ptr IRGenerator::convertIdentifier(const ASTIdentifier& } -std::unique_ptr IRGenerator::coerce(std::unique_ptr expr, +std::unique_ptr IRGenerator::coerce(std::unique_ptr expr, const Type& type) { if (!expr) { return nullptr; @@ -642,7 +635,7 @@ std::unique_ptr IRGenerator::coerce(std::unique_ptr expr return nullptr; } if (!expr->fType.canCoerceTo(type)) { - fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" + + fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" + expr->fType.description() + "'"); return nullptr; } @@ -681,7 +674,7 @@ static bool is_assignment(Token::Kind op) { case Token::BITWISEANDEQ: // fall through case Token::LOGICALOREQ: // fall through case Token::LOGICALXOREQ: // fall through - case Token::LOGICALANDEQ: + case Token::LOGICALANDEQ: return true; default: return false; @@ -692,10 +685,10 @@ static bool is_assignment(Token::Kind op) { * 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(const Context& context, - Token::Kind op, - const Type& left, - const Type& right, +static bool determine_binary_type(const Context& context, + Token::Kind op, + const Type& left, + const Type& right, const Type** outLeftType, const Type** outRightType, const Type** outResultType, @@ -729,18 +722,18 @@ static bool determine_binary_type(const Context& context, *outLeftType = context.fBool_Type.get(); *outRightType = context.fBool_Type.get(); *outResultType = context.fBool_Type.get(); - return left.canCoerceTo(*context.fBool_Type) && + return left.canCoerceTo(*context.fBool_Type) && right.canCoerceTo(*context.fBool_Type); case Token::STAR: // fall through - case Token::STAREQ: + case Token::STAREQ: if (is_matrix_multiply(left, right)) { // determine final component type if (determine_binary_type(context, Token::STAR, left.componentType(), right.componentType(), outLeftType, outRightType, outResultType, false)) { - *outLeftType = &(*outResultType)->toCompound(context, left.columns(), + *outLeftType = &(*outResultType)->toCompound(context, left.columns(), left.rows());; - *outRightType = &(*outResultType)->toCompound(context, right.columns(), + *outRightType = &(*outResultType)->toCompound(context, right.columns(), right.rows());; int leftColumns = left.columns(); int leftRows = left.rows(); @@ -787,7 +780,7 @@ static bool determine_binary_type(const Context& context, } bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind; // FIXME: incorrect for shift - if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind || + if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind || (isVectorOrMatrix && validMatrixOrVectorOp))) { *outLeftType = &left; *outRightType = &left; @@ -798,13 +791,13 @@ static bool determine_binary_type(const Context& context, } return true; } - if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && + if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && (right.kind() == Type::kScalar_Kind)) { - if (determine_binary_type(context, op, left.componentType(), right, outLeftType, + if (determine_binary_type(context, op, left.componentType(), right, outLeftType, outRightType, outResultType, false)) { *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows()); if (!isLogical) { - *outResultType = &(*outResultType)->toCompound(context, left.columns(), + *outResultType = &(*outResultType)->toCompound(context, left.columns(), left.rows()); } return true; @@ -812,7 +805,7 @@ static bool determine_binary_type(const Context& context, return false; } if (tryFlipped) { - return determine_binary_type(context, op, right, left, outRightType, outLeftType, + return determine_binary_type(context, op, right, left, outRightType, outLeftType, outResultType, false); } return false; @@ -830,7 +823,7 @@ std::unique_ptr IRGenerator::constantFold(const Expression& left, // precision to calculate the results and hope the result makes sense. The plan is to move the // Skia caps into SkSL, so we have access to all of them including the precisions of the various // types, which will let us be more intelligent about this. - if (left.fKind == Expression::kBoolLiteral_Kind && + if (left.fKind == Expression::kBoolLiteral_Kind && right.fKind == Expression::kBoolLiteral_Kind) { bool leftVal = ((BoolLiteral&) left).fValue; bool rightVal = ((BoolLiteral&) right).fValue; @@ -868,7 +861,7 @@ std::unique_ptr IRGenerator::constantFold(const Expression& left, default: return nullptr; } } - if (left.fKind == Expression::kFloatLiteral_Kind && + if (left.fKind == Expression::kFloatLiteral_Kind && right.fKind == Expression::kFloatLiteral_Kind) { double leftVal = ((FloatLiteral&) left).fValue; double rightVal = ((FloatLiteral&) right).fValue; @@ -905,9 +898,9 @@ std::unique_ptr IRGenerator::convertBinaryExpression( const Type* resultType; if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType, &rightType, &resultType, !is_assignment(expression.fOperator))) { - fErrors.error(expression.fPosition, "type mismatch: '" + - Token::OperatorName(expression.fOperator) + - "' cannot operate on '" + left->fType.fName + + fErrors.error(expression.fPosition, "type mismatch: '" + + Token::OperatorName(expression.fOperator) + + "' cannot operate on '" + left->fType.fName + "', '" + right->fType.fName + "'"); return nullptr; } @@ -919,7 +912,7 @@ std::unique_ptr IRGenerator::convertBinaryExpression( if (!left || !right) { return nullptr; } - std::unique_ptr result = this->constantFold(*left.get(), expression.fOperator, + std::unique_ptr result = this->constantFold(*left.get(), expression.fOperator, *right.get()); if (!result) { result = std::unique_ptr(new BinaryExpression(expression.fPosition, @@ -931,9 +924,9 @@ std::unique_ptr IRGenerator::convertBinaryExpression( return result; } -std::unique_ptr IRGenerator::convertTernaryExpression( +std::unique_ptr IRGenerator::convertTernaryExpression( const ASTTernaryExpression& expression) { - std::unique_ptr test = this->coerce(this->convertExpression(*expression.fTest), + std::unique_ptr test = this->coerce(this->convertExpression(*expression.fTest), *fContext.fBool_Type); if (!test) { return nullptr; @@ -951,8 +944,8 @@ std::unique_ptr IRGenerator::convertTernaryExpression( const Type* resultType; if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType, &falseType, &resultType, true)) { - fErrors.error(expression.fPosition, "ternary operator result mismatch: '" + - ifTrue->fType.fName + "', '" + + fErrors.error(expression.fPosition, "ternary operator result mismatch: '" + + ifTrue->fType.fName + "', '" + ifFalse->fType.fName + "'"); return nullptr; } @@ -967,18 +960,18 @@ std::unique_ptr IRGenerator::convertTernaryExpression( return ifFalse; } } - return std::unique_ptr(new TernaryExpression(expression.fPosition, + return std::unique_ptr(new TernaryExpression(expression.fPosition, std::move(test), - std::move(ifTrue), + std::move(ifTrue), std::move(ifFalse))); } -std::unique_ptr IRGenerator::call(Position position, - const FunctionDeclaration& function, +std::unique_ptr IRGenerator::call(Position position, + const FunctionDeclaration& function, std::vector> arguments) { if (function.fParameters.size() != arguments.size()) { - SkString msg = "call to '" + function.fName + "' expected " + - to_string((uint64_t) function.fParameters.size()) + + SkString msg = "call to '" + function.fName + "' expected " + + to_string((uint64_t) function.fParameters.size()) + " argument"; if (function.fParameters.size() != 1) { msg += "s"; @@ -1015,11 +1008,11 @@ std::unique_ptr IRGenerator::call(Position position, } /** - * Determines the cost of coercing the arguments of a function to the required types. Returns true - * if the cost could be computed, false if the call is not valid. Cost has no particular meaning + * Determines the cost of coercing the arguments of a function to the required types. Returns true + * 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(const FunctionDeclaration& function, const std::vector>& arguments, int* outCost) { if (function.fParameters.size() != arguments.size()) { @@ -1043,12 +1036,12 @@ bool IRGenerator::determineCallCost(const FunctionDeclaration& function, return true; } -std::unique_ptr IRGenerator::call(Position position, - std::unique_ptr functionValue, +std::unique_ptr IRGenerator::call(Position position, + std::unique_ptr functionValue, std::vector> arguments) { if (functionValue->fKind == Expression::kTypeReference_Kind) { - return this->convertConstructor(position, - ((TypeReference&) *functionValue).fValue, + return this->convertConstructor(position, + ((TypeReference&) *functionValue).fValue, std::move(arguments)); } if (functionValue->fKind != Expression::kFunctionReference_Kind) { @@ -1084,17 +1077,17 @@ std::unique_ptr IRGenerator::call(Position position, } std::unique_ptr IRGenerator::convertConstructor( - Position position, - const Type& type, + Position position, + const Type& type, std::vector> args) { // FIXME: add support for structs and arrays Type::Kind kind = type.kind(); - if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind && + if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind && kind != Type::kArray_Kind) { fErrors.error(position, "cannot construct '" + type.description() + "'"); return nullptr; } - if (type == *fContext.fFloat_Type && args.size() == 1 && + if (type == *fContext.fFloat_Type && args.size() == 1 && args[0]->fKind == Expression::kIntLiteral_Kind) { int64_t value = ((IntLiteral&) *args[0]).fValue; return std::unique_ptr(new FloatLiteral(fContext, position, (double) value)); @@ -1105,7 +1098,7 @@ std::unique_ptr IRGenerator::convertConstructor( } 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((uint64_t) args.size()) + ")"); return nullptr; @@ -1116,17 +1109,17 @@ std::unique_ptr IRGenerator::convertConstructor( return std::unique_ptr( new TernaryExpression(position, std::move(args[0]), this->coerce(std::move(one), type), - this->coerce(std::move(zero), + this->coerce(std::move(zero), type))); } else if (!args[0]->fType.isNumber()) { - fErrors.error(position, "invalid argument to '" + type.description() + + fErrors.error(position, "invalid argument to '" + type.description() + "' constructor (expected a number or bool, but found '" + args[0]->fType.description() + "')"); } - if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || + if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || type == *fContext.fUInt_Type)) { - return std::unique_ptr(new IntLiteral(fContext, - position, + return std::unique_ptr(new IntLiteral(fContext, + position, ((IntLiteral&) *args[0]).fValue, &type)); } @@ -1170,9 +1163,9 @@ std::unique_ptr IRGenerator::convertConstructor( 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() + - "' constructor (expected " + to_string(min) + " scalar" + - (min == 1 ? "" : "s") + ", but found " + to_string(actual) + + fErrors.error(position, "invalid arguments to '" + type.description() + + "' constructor (expected " + to_string(min) + " scalar" + + (min == 1 ? "" : "s") + ", but found " + to_string(actual) + ")"); return nullptr; } @@ -1189,14 +1182,14 @@ std::unique_ptr IRGenerator::convertPrefixExpression( switch (expression.fOperator) { case Token::PLUS: if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fPosition, "'+' cannot operate on '" + base->fType.description() + "'"); return nullptr; } return base; case Token::MINUS: if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fPosition, "'-' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1206,23 +1199,23 @@ std::unique_ptr IRGenerator::convertPrefixExpression( } if (base->fKind == Expression::kFloatLiteral_Kind) { double value = -((FloatLiteral&) *base).fValue; - return std::unique_ptr(new FloatLiteral(fContext, base->fPosition, + return std::unique_ptr(new FloatLiteral(fContext, base->fPosition, value)); } return std::unique_ptr(new PrefixExpression(Token::MINUS, std::move(base))); case Token::PLUSPLUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } this->markWrittenTo(*base); break; - case Token::MINUSMINUS: + case Token::MINUSMINUS: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1230,8 +1223,8 @@ std::unique_ptr IRGenerator::convertPrefixExpression( break; case Token::LOGICALNOT: if (base->fType != *fContext.fBool_Type) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } @@ -1242,16 +1235,16 @@ std::unique_ptr IRGenerator::convertPrefixExpression( break; case Token::BITWISENOT: if (base->fType != *fContext.fInt_Type) { - fErrors.error(expression.fPosition, - "'" + Token::OperatorName(expression.fOperator) + + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + "' cannot operate on '" + base->fType.description() + "'"); return nullptr; } break; - default: + default: ABORT("unsupported prefix operator\n"); } - return std::unique_ptr(new PrefixExpression(expression.fOperator, + return std::unique_ptr(new PrefixExpression(expression.fOperator, std::move(base))); } @@ -1259,7 +1252,7 @@ std::unique_ptr IRGenerator::convertIndex(std::unique_ptrfType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && base->fType.kind() != Type::kVector_Kind) { - fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + + fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + "'"); return nullptr; } @@ -1273,7 +1266,7 @@ std::unique_ptr IRGenerator::convertIndex(std::unique_ptr(new IndexExpression(fContext, std::move(base), + return std::unique_ptr(new IndexExpression(fContext, std::move(base), std::move(converted))); } @@ -1301,7 +1294,7 @@ std::unique_ptr IRGenerator::convertSwizzle(std::unique_ptr IRGenerator::convertSwizzle(std::unique_ptrfType.columns() >= 3) { swizzleComponents.push_back(2); break; @@ -1354,7 +1347,7 @@ std::unique_ptr IRGenerator::getCap(Position position, SkString name return std::unique_ptr(new BoolLiteral(fContext, position, (bool) found->second.fValue)); case CapValue::kInt_Kind: - return std::unique_ptr(new IntLiteral(fContext, position, + return std::unique_ptr(new IntLiteral(fContext, position, found->second.fValue)); } ASSERT(false); @@ -1374,10 +1367,10 @@ std::unique_ptr IRGenerator::convertSuffixExpression( return this->convertIndex(std::move(base), *expr); } else if (base->fKind == Expression::kTypeReference_Kind) { const Type& oldType = ((TypeReference&) *base).fValue; - Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType, + Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType, -1); fSymbolTable->takeOwnership(newType); - return std::unique_ptr(new TypeReference(fContext, base->fPosition, + return std::unique_ptr(new TypeReference(fContext, base->fPosition, *newType)); } else { fErrors.error(expression.fPosition, "'[]' must follow a type name"); @@ -1388,7 +1381,7 @@ std::unique_ptr IRGenerator::convertSuffixExpression( auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments; std::vector> arguments; for (size_t i = 0; i < rawArguments->size(); i++) { - std::unique_ptr converted = + std::unique_ptr converted = this->convertExpression(*(*rawArguments)[i]); if (!converted) { return nullptr; @@ -1404,34 +1397,34 @@ std::unique_ptr IRGenerator::convertSuffixExpression( } switch (base->fType.kind()) { case Type::kVector_Kind: - return this->convertSwizzle(std::move(base), + return this->convertSwizzle(std::move(base), ((ASTFieldSuffix&) *expression.fSuffix).fField); case Type::kStruct_Kind: return this->convertField(std::move(base), ((ASTFieldSuffix&) *expression.fSuffix).fField); default: - fErrors.error(base->fPosition, "cannot swizzle value of type '" + + fErrors.error(base->fPosition, "cannot swizzle value of type '" + base->fType.description() + "'"); return nullptr; } } case ASTSuffix::kPostIncrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fPosition, "'++' cannot operate on '" + base->fType.description() + "'"); return nullptr; } this->markWrittenTo(*base); - return std::unique_ptr(new PostfixExpression(std::move(base), + return std::unique_ptr(new PostfixExpression(std::move(base), Token::PLUSPLUS)); case ASTSuffix::kPostDecrement_Kind: if (!base->fType.isNumber()) { - fErrors.error(expression.fPosition, + fErrors.error(expression.fPosition, "'--' cannot operate on '" + base->fType.description() + "'"); return nullptr; } this->markWrittenTo(*base); - return std::unique_ptr(new PostfixExpression(std::move(base), + return std::unique_ptr(new PostfixExpression(std::move(base), Token::MINUSMINUS)); default: ABORT("unsupported suffix operator"); @@ -1475,7 +1468,7 @@ void IRGenerator::markWrittenTo(const Expression& expr) { case Expression::kVariableReference_Kind: { const Variable& var = ((VariableReference&) expr).fVariable; if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) { - fErrors.error(expr.fPosition, + fErrors.error(expr.fPosition, "cannot modify immutable variable '" + var.fName + "'"); } var.fIsWrittenTo = true; @@ -1486,7 +1479,7 @@ void IRGenerator::markWrittenTo(const Expression& expr) { break; case Expression::kSwizzle_Kind: if (has_duplicates((Swizzle&) expr)) { - fErrors.error(expr.fPosition, + fErrors.error(expr.fPosition, "cannot write to the same swizzle field more than once"); } this->markWrittenTo(*((Swizzle&) expr).fBase); diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 5b56689517..ade6150089 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_IRGENERATOR #define SKSL_IRGENERATOR @@ -24,7 +24,6 @@ #include "ast/SkSLASTIdentifier.h" #include "ast/SkSLASTIfStatement.h" #include "ast/SkSLASTInterfaceBlock.h" -#include "ast/SkSLASTModifiers.h" #include "ast/SkSLASTModifiersDeclaration.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" @@ -72,15 +71,15 @@ struct CapValue { }; /** - * Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding + * Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding * (unoptimized) intermediate representation (IR). */ class IRGenerator { public: - IRGenerator(const Context* context, std::shared_ptr root, + IRGenerator(const Context* context, std::shared_ptr root, ErrorReporter& errorReporter); - std::unique_ptr convertVarDeclarations(const ASTVarDeclarations& decl, + std::unique_ptr convertVarDeclarations(const ASTVarDeclarations& decl, Variable::Storage storage); std::unique_ptr convertFunction(const ASTFunction& f); std::unique_ptr convertStatement(const ASTStatement& statement); @@ -104,25 +103,25 @@ private: void popSymbolTable(); const Type* convertType(const ASTType& type); - std::unique_ptr call(Position position, - const FunctionDeclaration& function, + std::unique_ptr call(Position position, + const FunctionDeclaration& function, std::vector> arguments); - bool determineCallCost(const FunctionDeclaration& function, + bool determineCallCost(const FunctionDeclaration& function, const std::vector>& arguments, int* outCost); - std::unique_ptr call(Position position, std::unique_ptr function, + std::unique_ptr call(Position position, std::unique_ptr function, std::vector> arguments); std::unique_ptr coerce(std::unique_ptr expr, const Type& type); std::unique_ptr convertBlock(const ASTBlock& block); std::unique_ptr convertBreak(const ASTBreakStatement& b); - std::unique_ptr convertConstructor(Position position, - const Type& type, + std::unique_ptr convertConstructor(Position position, + const Type& type, std::vector> params); std::unique_ptr convertContinue(const ASTContinueStatement& c); std::unique_ptr convertDiscard(const ASTDiscardStatement& d); std::unique_ptr convertDo(const ASTDoStatement& d); std::unique_ptr convertBinaryExpression(const ASTBinaryExpression& expression); - // Returns null if it cannot fold the expression. Note that unlike most other functions here, a + // Returns null if it cannot fold the expression. Note that unlike most other functions here, a // null return does not represent a compilation error. std::unique_ptr constantFold(const Expression& left, Token::Kind op, @@ -135,12 +134,12 @@ private: std::unique_ptr convertIndex(std::unique_ptr base, const ASTExpression& index); std::unique_ptr convertInterfaceBlock(const ASTInterfaceBlock& s); - Modifiers convertModifiers(const ASTModifiers& m); + Modifiers convertModifiers(const Modifiers& m); std::unique_ptr convertPrefixExpression(const ASTPrefixExpression& expression); std::unique_ptr convertReturn(const ASTReturnStatement& r); std::unique_ptr getCap(Position position, SkString name); std::unique_ptr convertSuffixExpression(const ASTSuffixExpression& expression); - std::unique_ptr convertField(std::unique_ptr base, + std::unique_ptr convertField(std::unique_ptr base, const SkString& field); std::unique_ptr convertSwizzle(std::unique_ptr base, const SkString& fields); diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index 80ef870a48..1b7cd9d725 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #include "stdio.h" #include "SkSLParser.h" #include "SkSLToken.h" @@ -69,6 +69,7 @@ #include "ast/SkSLASTVarDeclarationStatement.h" #include "ast/SkSLASTWhileStatement.h" #include "ir/SkSLSymbolTable.h" +#include "ir/SkSLModifiers.h" #include "ir/SkSLType.h" namespace SkSL { @@ -98,7 +99,7 @@ private: Parser* fParser; }; -Parser::Parser(SkString text, SymbolTable& types, ErrorReporter& errors) +Parser::Parser(SkString text, SymbolTable& types, ErrorReporter& errors) : fPushback(Position(-1, -1), Token::INVALID_TOKEN, SkString()) , fTypes(types) , fErrors(errors) { @@ -229,7 +230,7 @@ std::unique_ptr Parser::precision() { result = Modifiers::kHighp_Flag; break; default: - this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + + this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + p.fText + "'"); return nullptr; } @@ -241,7 +242,7 @@ std::unique_ptr Parser::precision() { return std::unique_ptr(new ASTPrecision(p.fPosition, result)); } -/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | +/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */ std::unique_ptr Parser::directive() { Token start; @@ -269,7 +270,7 @@ std::unique_ptr Parser::directive() { if (!this->expect(Token::IDENTIFIER, "an identifier")) { return nullptr; } - return std::unique_ptr(new ASTExtension(start.fPosition, + return std::unique_ptr(new ASTExtension(start.fPosition, std::move(name.fText))); } else { this->error(start.fPosition, "unsupported directive '" + start.fText + "'"); @@ -277,10 +278,10 @@ std::unique_ptr Parser::directive() { } } -/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter +/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter (COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */ std::unique_ptr Parser::declaration() { - ASTModifiers modifiers = this->modifiers(); + Modifiers modifiers = this->modifiers(); Token lookahead = this->peek(); if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) { // we have an identifier that's not a type, could be the start of an interface block @@ -330,9 +331,9 @@ std::unique_ptr Parser::declaration() { return nullptr; } } - return std::unique_ptr(new ASTFunction(name.fPosition, std::move(type), - std::move(name.fText), - std::move(parameters), + return std::unique_ptr(new ASTFunction(name.fPosition, std::move(type), + std::move(name.fText), + std::move(parameters), std::move(body))); } else { return this->varDeclarationEnd(modifiers, std::move(type), name.fText); @@ -341,7 +342,7 @@ std::unique_ptr Parser::declaration() { /* modifiers type IDENTIFIER varDeclarationEnd */ std::unique_ptr Parser::varDeclarations() { - ASTModifiers modifiers = this->modifiers(); + Modifiers modifiers = this->modifiers(); std::unique_ptr type(this->type()); if (!type) { return nullptr; @@ -393,25 +394,25 @@ std::unique_ptr Parser::structDeclaration() { return nullptr; } fTypes.add(name.fText, std::unique_ptr(new Type(name.fText, fields))); - return std::unique_ptr(new ASTType(name.fPosition, name.fText, + return std::unique_ptr(new ASTType(name.fPosition, name.fText, ASTType::kStruct_Kind)); } /* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */ -std::unique_ptr Parser::structVarDeclaration(ASTModifiers modifiers) { +std::unique_ptr Parser::structVarDeclaration(Modifiers modifiers) { std::unique_ptr type = this->structDeclaration(); if (!type) { return nullptr; } if (peek().fKind == Token::IDENTIFIER) { Token name = this->nextToken(); - std::unique_ptr result = this->varDeclarationEnd(modifiers, - std::move(type), + std::unique_ptr result = this->varDeclarationEnd(modifiers, + std::move(type), std::move(name.fText)); if (result) { for (const auto& var : result->fVars) { if (var.fValue) { - this->error(var.fValue->fPosition, + this->error(var.fValue->fPosition, "struct variables cannot be initialized"); } } @@ -422,9 +423,9 @@ std::unique_ptr Parser::structVarDeclaration(ASTModifiers mo return nullptr; } -/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER +/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER (LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */ -std::unique_ptr Parser::varDeclarationEnd(ASTModifiers mods, +std::unique_ptr Parser::varDeclarationEnd(Modifiers mods, std::unique_ptr type, SkString name) { std::vector vars; @@ -497,7 +498,7 @@ std::unique_ptr Parser::varDeclarationEnd(ASTModifiers mods, /* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */ std::unique_ptr Parser::parameter() { - ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag); + Modifiers modifiers = this->modifiersWithDefaults(Modifiers::kIn_Flag); std::unique_ptr type = this->type(); if (!type) { return nullptr; @@ -518,8 +519,8 @@ std::unique_ptr Parser::parameter() { return nullptr; } } - return std::unique_ptr(new ASTParameter(name.fPosition, modifiers, - std::move(type), name.fText, + return std::unique_ptr(new ASTParameter(name.fPosition, modifiers, + std::move(type), name.fText, std::move(sizes))); } @@ -536,7 +537,7 @@ int Parser::layoutInt() { } /* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */ -ASTLayout Parser::layout() { +Layout Parser::layout() { int location = -1; int binding = -1; int index = -1; @@ -546,14 +547,14 @@ ASTLayout Parser::layout() { bool originUpperLeft = false; bool overrideCoverage = false; bool blendSupportAllEquations = false; - ASTLayout::Format format = ASTLayout::Format::kUnspecified; + Layout::Format format = Layout::Format::kUnspecified; bool pushConstant = false; if (this->peek().fKind == Token::LAYOUT) { this->nextToken(); if (!this->expect(Token::LPAREN, "'('")) { - return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, - originUpperLeft, overrideCoverage, blendSupportAllEquations, format, - pushConstant); + return Layout(location, binding, index, set, builtin, inputAttachmentIndex, + originUpperLeft, overrideCoverage, blendSupportAllEquations, format, + pushConstant); } for (;;) { Token t = this->nextToken(); @@ -575,7 +576,7 @@ ASTLayout Parser::layout() { overrideCoverage = true; } else if (t.fText == "blend_support_all_equations") { blendSupportAllEquations = true; - } else if (ASTLayout::ReadFormat(t.fText, &format)) { + } else if (Layout::ReadFormat(t.fText, &format)) { // AST::ReadFormat stored the result in 'format'. } else if (t.fText == "push_constant") { pushConstant = true; @@ -592,68 +593,68 @@ ASTLayout Parser::layout() { } } } - return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, + return Layout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft, overrideCoverage, blendSupportAllEquations, format, pushConstant); } /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */ -ASTModifiers Parser::modifiers() { - ASTLayout layout = this->layout(); +Modifiers Parser::modifiers() { + Layout layout = this->layout(); int flags = 0; for (;;) { // TODO: handle duplicate / incompatible flags switch (peek().fKind) { case Token::UNIFORM: this->nextToken(); - flags |= ASTModifiers::kUniform_Flag; + flags |= Modifiers::kUniform_Flag; break; case Token::CONST: this->nextToken(); - flags |= ASTModifiers::kConst_Flag; + flags |= Modifiers::kConst_Flag; break; case Token::IN: this->nextToken(); - flags |= ASTModifiers::kIn_Flag; + flags |= Modifiers::kIn_Flag; break; case Token::OUT: this->nextToken(); - flags |= ASTModifiers::kOut_Flag; + flags |= Modifiers::kOut_Flag; break; case Token::INOUT: this->nextToken(); - flags |= ASTModifiers::kIn_Flag; - flags |= ASTModifiers::kOut_Flag; + flags |= Modifiers::kIn_Flag; + flags |= Modifiers::kOut_Flag; break; case Token::LOWP: this->nextToken(); - flags |= ASTModifiers::kLowp_Flag; + flags |= Modifiers::kLowp_Flag; break; case Token::MEDIUMP: this->nextToken(); - flags |= ASTModifiers::kMediump_Flag; + flags |= Modifiers::kMediump_Flag; break; case Token::HIGHP: this->nextToken(); - flags |= ASTModifiers::kHighp_Flag; + flags |= Modifiers::kHighp_Flag; break; case Token::FLAT: this->nextToken(); - flags |= ASTModifiers::kFlat_Flag; + flags |= Modifiers::kFlat_Flag; break; case Token::NOPERSPECTIVE: this->nextToken(); - flags |= ASTModifiers::kNoPerspective_Flag; + flags |= Modifiers::kNoPerspective_Flag; break; default: - return ASTModifiers(layout, flags); + return Modifiers(layout, flags); } } } -ASTModifiers Parser::modifiersWithDefaults(int defaultFlags) { - ASTModifiers result = this->modifiers(); +Modifiers Parser::modifiersWithDefaults(int defaultFlags) { + Modifiers result = this->modifiers(); if (!result.fFlags) { - return ASTModifiers(result.fLayout, defaultFlags); + return Modifiers(result.fLayout, defaultFlags); } return result; } @@ -681,8 +682,8 @@ std::unique_ptr Parser::statement() { case Token::LBRACE: return this->block(); case Token::SEMICOLON: - this->nextToken(); - return std::unique_ptr(new ASTBlock(start.fPosition, + this->nextToken(); + return std::unique_ptr(new ASTBlock(start.fPosition, std::vector>())); case Token::CONST: // fall through case Token::HIGHP: // fall through @@ -706,7 +707,7 @@ std::unique_ptr Parser::statement() { // fall through default: return this->expressionStatement(); - } + } } /* IDENTIFIER(type) */ @@ -719,25 +720,25 @@ std::unique_ptr Parser::type() { this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str()); return nullptr; } - return std::unique_ptr(new ASTType(type.fPosition, std::move(type.fText), + return std::unique_ptr(new ASTType(type.fPosition, std::move(type.fText), ASTType::kIdentifier_Kind)); } /* IDENTIFIER LBRACE varDeclaration* RBRACE */ -std::unique_ptr Parser::interfaceBlock(ASTModifiers mods) { +std::unique_ptr Parser::interfaceBlock(Modifiers mods) { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { return nullptr; } if (peek().fKind != Token::LBRACE) { // we only get into interfaceBlock if we found a top-level identifier which was not a type. - // 99% of the time, the user was not actually intending to create an interface block, so + // 99% of the time, the user was not actually intending to create an interface block, so // it's better to report it as an unknown type this->error(name.fPosition, "no type named '" + name.fText + "'"); return nullptr; } this->nextToken(); - std::vector> decls; + std::vector> decls; while (this->peek().fKind != Token::RBRACE) { std::unique_ptr decl = this->varDeclarations(); if (!decl) { @@ -751,7 +752,7 @@ std::unique_ptr Parser::interfaceBlock(ASTModifiers mods) { valueName = this->nextToken().fText; } this->expect(Token::SEMICOLON, "';'"); - return std::unique_ptr(new ASTInterfaceBlock(name.fPosition, mods, + return std::unique_ptr(new ASTInterfaceBlock(name.fPosition, mods, name.fText, std::move(valueName), std::move(decls))); } @@ -784,8 +785,8 @@ std::unique_ptr Parser::ifStatement() { return nullptr; } } - return std::unique_ptr(new ASTIfStatement(start.fPosition, std::move(test), - std::move(ifTrue), + return std::unique_ptr(new ASTIfStatement(start.fPosition, std::move(test), + std::move(ifTrue), std::move(ifFalse))); } @@ -815,7 +816,7 @@ std::unique_ptr Parser::doStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr(new ASTDoStatement(start.fPosition, + return std::unique_ptr(new ASTDoStatement(start.fPosition, std::move(statement), std::move(test))); } @@ -840,12 +841,12 @@ std::unique_ptr Parser::whileStatement() { if (!statement) { return nullptr; } - return std::unique_ptr(new ASTWhileStatement(start.fPosition, - std::move(test), + return std::unique_ptr(new ASTWhileStatement(start.fPosition, + std::move(test), std::move(statement))); } -/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN +/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN STATEMENT */ std::unique_ptr Parser::forStatement() { Token start; @@ -858,7 +859,7 @@ std::unique_ptr Parser::forStatement() { std::unique_ptr initializer; Token nextToken = this->peek(); switch (nextToken.fKind) { - case Token::SEMICOLON: + case Token::SEMICOLON: this->nextToken(); break; case Token::CONST: { @@ -908,7 +909,7 @@ std::unique_ptr Parser::forStatement() { if (!statement) { return nullptr; } - return std::unique_ptr(new ASTForStatement(start.fPosition, + return std::unique_ptr(new ASTForStatement(start.fPosition, std::move(initializer), std::move(test), std::move(next), std::move(statement))); @@ -930,7 +931,7 @@ std::unique_ptr Parser::returnStatement() { if (!this->expect(Token::SEMICOLON, "';'")) { return nullptr; } - return std::unique_ptr(new ASTReturnStatement(start.fPosition, + return std::unique_ptr(new ASTReturnStatement(start.fPosition, std::move(expression))); } @@ -983,11 +984,11 @@ std::unique_ptr Parser::block() { std::vector> statements; for (;;) { switch (this->peek().fKind) { - case Token::RBRACE: + case Token::RBRACE: this->nextToken(); - return std::unique_ptr(new ASTBlock(start.fPosition, + return std::unique_ptr(new ASTBlock(start.fPosition, std::move(statements))); - case Token::END_OF_FILE: + case Token::END_OF_FILE: this->error(this->peek().fPosition, "expected '}', but found end of file"); return nullptr; default: { @@ -1052,8 +1053,8 @@ std::unique_ptr Parser::assignmentExpression() { if (!right) { return nullptr; } - result = std::unique_ptr(new ASTBinaryExpression(std::move(result), - t, + result = std::unique_ptr(new ASTBinaryExpression(std::move(result), + t, std::move(right))); } default: @@ -1076,8 +1077,8 @@ std::unique_ptr Parser::ternaryExpression() { } if (this->expect(Token::COLON, "':'")) { std::unique_ptr falseExpr = this->assignmentExpression(); - return std::unique_ptr(new ASTTernaryExpression(std::move(result), - std::move(trueExpr), + return std::unique_ptr(new ASTTernaryExpression(std::move(result), + std::move(trueExpr), std::move(falseExpr))); } return nullptr; @@ -1357,7 +1358,7 @@ std::unique_ptr Parser::postfixExpression() { } } -/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | +/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | PLUSPLUS | MINUSMINUS */ std::unique_ptr Parser::suffix() { Token next = this->nextToken(); @@ -1398,17 +1399,17 @@ std::unique_ptr Parser::suffix() { } } this->expect(Token::RPAREN, "')' to complete function parameters"); - return std::unique_ptr(new ASTCallSuffix(next.fPosition, + return std::unique_ptr(new ASTCallSuffix(next.fPosition, std::move(parameters))); } case Token::PLUSPLUS: - return std::unique_ptr(new ASTSuffix(next.fPosition, + return std::unique_ptr(new ASTSuffix(next.fPosition, ASTSuffix::kPostIncrement_Kind)); case Token::MINUSMINUS: return std::unique_ptr(new ASTSuffix(next.fPosition, ASTSuffix::kPostDecrement_Kind)); default: { - this->error(next.fPosition, "expected expression suffix, but found '" + next.fText + + this->error(next.fPosition, "expected expression suffix, but found '" + next.fText + "'\n"); return nullptr; } @@ -1505,7 +1506,7 @@ bool Parser::boolLiteral(bool* dest) { bool Parser::identifier(SkString* dest) { Token t; if (this->expect(Token::IDENTIFIER, "identifier", &t)) { - *dest = t.fText; + *dest = t.fText; return true; } return false; diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index f2b6fb87bb..75532e6238 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_PARSER #define SKSL_PARSER @@ -31,8 +31,6 @@ struct ASTExpressionStatement; struct ASTForStatement; struct ASTIfStatement; struct ASTInterfaceBlock; -struct ASTLayout; -struct ASTModifiers; struct ASTParameter; struct ASTPrecision; struct ASTReturnStatement; @@ -41,6 +39,8 @@ struct ASTSuffix; struct ASTType; struct ASTWhileStatement; struct ASTVarDeclarations; +struct Layout; +struct Modifiers; class SymbolTable; /** @@ -73,7 +73,7 @@ private: void pushback(Token t); /** - * Returns the next token without consuming it from the stream. + * Returns the next token without consuming it from the stream. */ Token peek(); @@ -91,7 +91,7 @@ private: void error(Position p, const char* msg); void error(Position p, SkString msg); - + /** * Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will * always return true. @@ -112,27 +112,27 @@ private: std::unique_ptr structDeclaration(); - std::unique_ptr structVarDeclaration(ASTModifiers modifiers); + std::unique_ptr structVarDeclaration(Modifiers modifiers); - std::unique_ptr varDeclarationEnd(ASTModifiers modifiers, - std::unique_ptr type, + std::unique_ptr varDeclarationEnd(Modifiers modifiers, + std::unique_ptr type, SkString name); std::unique_ptr parameter(); int layoutInt(); - - ASTLayout layout(); + + Layout layout(); - ASTModifiers modifiers(); + Modifiers modifiers(); - ASTModifiers modifiersWithDefaults(int defaultFlags); + Modifiers modifiersWithDefaults(int defaultFlags); std::unique_ptr statement(); std::unique_ptr type(); - std::unique_ptr interfaceBlock(ASTModifiers mods); + std::unique_ptr interfaceBlock(Modifiers mods); std::unique_ptr ifStatement(); @@ -157,7 +157,7 @@ private: std::unique_ptr expression(); std::unique_ptr assignmentExpression(); - + std::unique_ptr ternaryExpression(); std::unique_ptr logicalOrExpression(); diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h index 8d86c7c4f1..9cd99d5a9d 100644 --- a/src/sksl/ast/SkSLASTInterfaceBlock.h +++ b/src/sksl/ast/SkSLASTInterfaceBlock.h @@ -4,11 +4,12 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_ASTINTERFACEBLOCK #define SKSL_ASTINTERFACEBLOCK #include "SkSLASTVarDeclaration.h" +#include "../ir/SkSLModifiers.h" namespace SkSL { @@ -23,9 +24,9 @@ namespace SkSL { struct ASTInterfaceBlock : public ASTDeclaration { // valueName is empty when it was not present in the source ASTInterfaceBlock(Position position, - ASTModifiers modifiers, - SkString interfaceName, - SkString valueName, + Modifiers modifiers, + SkString interfaceName, + SkString valueName, std::vector> declarations) : INHERITED(position, kInterfaceBlock_Kind) , fModifiers(modifiers) @@ -45,7 +46,7 @@ struct ASTInterfaceBlock : public ASTDeclaration { return result + ";"; } - const ASTModifiers fModifiers; + const Modifiers fModifiers; const SkString fInterfaceName; const SkString fValueName; const std::vector> fDeclarations; diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h deleted file mode 100644 index 4c36af46a1..0000000000 --- a/src/sksl/ast/SkSLASTLayout.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SKSL_ASTLAYOUT -#define SKSL_ASTLAYOUT - -#include "SkSLASTNode.h" -#include "SkSLUtil.h" - -namespace SkSL { - -/** - * Represents a layout block appearing before a variable declaration, as in: - * - * layout (location = 0) int x; - */ -struct ASTLayout : public ASTNode { - // These are used by images in GLSL. We only support a subset of what GL supports. - enum class Format { - kUnspecified = -1, - kRGBA32F, - kR32F, - kRGBA16F, - kR16F, - kRGBA8, - kR8, - kRGBA8I, - kR8I, - }; - - static const char* FormatToStr(Format format) { - switch (format) { - case Format::kUnspecified: return ""; - case Format::kRGBA32F: return "rgba32f"; - case Format::kR32F: return "r32f"; - case Format::kRGBA16F: return "rgba16f"; - case Format::kR16F: return "r16f"; - case Format::kRGBA8: return "rgba8"; - case Format::kR8: return "r8"; - case Format::kRGBA8I: return "rgba8i"; - case Format::kR8I: return "r8i"; - } - SkFAIL("Unexpected format"); - return ""; - } - - static bool ReadFormat(SkString str, Format* format) { - if (str == "rgba32f") { - *format = Format::kRGBA32F; - return true; - } else if (str == "r32f") { - *format = Format::kR32F; - return true; - } else if (str == "rgba16f") { - *format = Format::kRGBA16F; - return true; - } else if (str == "r16f") { - *format = Format::kR16F; - return true; - } else if (str == "rgba8") { - *format = Format::kRGBA8; - return true; - } else if (str == "r8") { - *format = Format::kR8; - return true; - } else if (str == "rgba8i") { - *format = Format::kRGBA8I; - return true; - } else if (str == "r8i") { - *format = Format::kR8I; - return true; - } - return false; - } - - // For int parameters, a -1 means no value - ASTLayout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex, - bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations, - Format format, bool pushConstant) - : fLocation(location) - , fBinding(binding) - , fIndex(index) - , fSet(set) - , fBuiltin(builtin) - , fInputAttachmentIndex(inputAttachmentIndex) - , fOriginUpperLeft(originUpperLeft) - , fOverrideCoverage(overrideCoverage) - , fBlendSupportAllEquations(blendSupportAllEquations) - , fFormat(format) - , fPushConstant(pushConstant) {} - - SkString description() const { - SkString result; - SkString separator; - if (fLocation >= 0) { - result += separator + "location = " + to_string(fLocation); - separator = ", "; - } - if (fBinding >= 0) { - result += separator + "binding = " + to_string(fBinding); - separator = ", "; - } - if (fIndex >= 0) { - result += separator + "index = " + to_string(fIndex); - separator = ", "; - } - if (fSet >= 0) { - result += separator + "set = " + to_string(fSet); - separator = ", "; - } - if (fBuiltin >= 0) { - result += separator + "builtin = " + to_string(fBuiltin); - separator = ", "; - } - if (fInputAttachmentIndex >= 0) { - result += separator + "input_attachment_index = " + to_string(fBuiltin); - separator = ", "; - } - if (fOriginUpperLeft) { - result += separator + "origin_upper_left"; - separator = ", "; - } - if (fOverrideCoverage) { - result += separator + "override_coverage"; - separator = ", "; - } - if (fBlendSupportAllEquations) { - result += separator + "blend_support_all_equations"; - separator = ", "; - } - if (fFormat != Format::kUnspecified) { - result += separator + FormatToStr(fFormat); - separator = ", "; - } - if (fPushConstant) { - result += separator + "push_constant"; - separator = ", "; - } - if (result.size() > 0) { - result = "layout (" + result + ")"; - } - return result; - } - - const int fLocation; - const int fBinding; - const int fIndex; - const int fSet; - const int fBuiltin; - const int fInputAttachmentIndex; - const bool fOriginUpperLeft; - const bool fOverrideCoverage; - const bool fBlendSupportAllEquations; - const Format fFormat; - const bool fPushConstant; -}; - -} // namespace - -#endif diff --git a/src/sksl/ast/SkSLASTModifiers.h b/src/sksl/ast/SkSLASTModifiers.h deleted file mode 100644 index 734169267c..0000000000 --- a/src/sksl/ast/SkSLASTModifiers.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SKSL_ASTMODIFIERS -#define SKSL_ASTMODIFIERS - -#include "SkSLASTLayout.h" -#include "SkSLASTNode.h" - -namespace SkSL { - -/** - * A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration. - */ -struct ASTModifiers : public ASTNode { - enum Flag { - kNo_Flag = 0, - kConst_Flag = 1, - kIn_Flag = 2, - kOut_Flag = 4, - kLowp_Flag = 8, - kMediump_Flag = 16, - kHighp_Flag = 32, - kUniform_Flag = 64, - kFlat_Flag = 128, - kNoPerspective_Flag = 256 - }; - - ASTModifiers(ASTLayout layout, int flags) - : fLayout(layout) - , fFlags(flags) {} - - SkString description() const override { - SkString result = fLayout.description(); - if (fFlags & kUniform_Flag) { - result += "uniform "; - } - if (fFlags & kConst_Flag) { - result += "const "; - } - if (fFlags & kLowp_Flag) { - result += "lowp "; - } - if (fFlags & kMediump_Flag) { - result += "mediump "; - } - if (fFlags & kHighp_Flag) { - result += "highp "; - } - if (fFlags & kFlat_Flag) { - result += "flat "; - } - if (fFlags & kNoPerspective_Flag) { - result += "noperspective "; - } - - if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) { - result += "inout "; - } else if (fFlags & kIn_Flag) { - result += "in "; - } else if (fFlags & kOut_Flag) { - result += "out "; - } - - return result; - } - - const ASTLayout fLayout; - const int fFlags; -}; - -} // namespace - -#endif diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h index 07efdf6024..7950f6dd5d 100644 --- a/src/sksl/ast/SkSLASTModifiersDeclaration.h +++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h @@ -4,12 +4,12 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_ASTMODIFIERDECLARATION #define SKSL_ASTMODIFIERDECLARATION #include "SkSLASTDeclaration.h" -#include "SkSLASTModifiers.h" +#include "../ir/SkSLModifiers.h" namespace SkSL { @@ -19,7 +19,7 @@ namespace SkSL { * layout(blend_support_all_equations) out; */ struct ASTModifiersDeclaration : public ASTDeclaration { - ASTModifiersDeclaration(ASTModifiers modifiers) + ASTModifiersDeclaration(Modifiers modifiers) : INHERITED(Position(), kModifiers_Kind) , fModifiers(modifiers) {} @@ -27,7 +27,7 @@ struct ASTModifiersDeclaration : public ASTDeclaration { return fModifiers.description() + ";"; } - ASTModifiers fModifiers; + Modifiers fModifiers; typedef ASTDeclaration INHERITED; }; diff --git a/src/sksl/ast/SkSLASTParameter.h b/src/sksl/ast/SkSLASTParameter.h index b1fd658434..7b653ad289 100644 --- a/src/sksl/ast/SkSLASTParameter.h +++ b/src/sksl/ast/SkSLASTParameter.h @@ -4,12 +4,12 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_ASTPARAMETER #define SKSL_ASTPARAMETER -#include "SkSLASTModifiers.h" #include "SkSLASTType.h" +#include "../ir/SkSLModifiers.h" namespace SkSL { @@ -17,9 +17,9 @@ namespace SkSL { * A declaration of a parameter, as part of a function declaration. */ struct ASTParameter : public ASTPositionNode { - // 'sizes' is a list of the array sizes appearing on a parameter, in source order. + // 'sizes' is a list of the array sizes appearing on a parameter, in source order. // e.g. int x[3][1] would have sizes [3, 1]. - ASTParameter(Position position, ASTModifiers modifiers, std::unique_ptr type, + ASTParameter(Position position, Modifiers modifiers, std::unique_ptr type, SkString name, std::vector sizes) : INHERITED(position) , fModifiers(modifiers) @@ -35,7 +35,7 @@ struct ASTParameter : public ASTPositionNode { return result; } - const ASTModifiers fModifiers; + const Modifiers fModifiers; const std::unique_ptr fType; const SkString fName; const std::vector fSizes; diff --git a/src/sksl/ast/SkSLASTVarDeclaration.h b/src/sksl/ast/SkSLASTVarDeclaration.h index 9de4cf55b9..7d50a06a50 100644 --- a/src/sksl/ast/SkSLASTVarDeclaration.h +++ b/src/sksl/ast/SkSLASTVarDeclaration.h @@ -4,21 +4,21 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_ASTVARDECLARATIONS #define SKSL_ASTVARDECLARATIONS #include "SkSLASTDeclaration.h" -#include "SkSLASTModifiers.h" #include "SkSLASTStatement.h" #include "SkSLASTType.h" #include "../SkSLUtil.h" +#include "../ir/SkSLModifiers.h" namespace SkSL { /** * A single variable declaration within a var declaration statement. For instance, the statement - * 'int x = 2, y[3];' is an ASTVarDeclarations statement containing two individual ASTVarDeclaration + * 'int x = 2, y[3];' is an ASTVarDeclarations statement containing two individual ASTVarDeclaration * instances. */ struct ASTVarDeclaration { @@ -41,7 +41,7 @@ struct ASTVarDeclaration { if (fValue) { result += " = " + fValue->description(); } - return result; + return result; } SkString fName; @@ -57,8 +57,8 @@ struct ASTVarDeclaration { * A variable declaration statement, which may consist of one or more individual variables. */ struct ASTVarDeclarations : public ASTDeclaration { - ASTVarDeclarations(ASTModifiers modifiers, - std::unique_ptr type, + ASTVarDeclarations(Modifiers modifiers, + std::unique_ptr type, std::vector vars) : INHERITED(type->fPosition, kVar_Kind) , fModifiers(modifiers) @@ -76,7 +76,7 @@ struct ASTVarDeclarations : public ASTDeclaration { return result; } - const ASTModifiers fModifiers; + const Modifiers fModifiers; const std::unique_ptr fType; const std::vector fVars; diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index f433614da9..b2c158eeef 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -4,10 +4,13 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_LAYOUT #define SKSL_LAYOUT +#include "SkString.h" +#include "SkSLUtil.h" + namespace SkSL { /** @@ -16,22 +19,67 @@ namespace SkSL { * layout (location = 0) int x; */ struct Layout { - Layout(const ASTLayout& layout) - : fLocation(layout.fLocation) - , fBinding(layout.fBinding) - , fIndex(layout.fIndex) - , fSet(layout.fSet) - , fBuiltin(layout.fBuiltin) - , fInputAttachmentIndex(layout.fInputAttachmentIndex) - , fOriginUpperLeft(layout.fOriginUpperLeft) - , fOverrideCoverage(layout.fOverrideCoverage) - , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) - , fFormat(layout.fFormat) - , fPushConstant(layout.fPushConstant) {} + // These are used by images in GLSL. We only support a subset of what GL supports. + enum class Format { + kUnspecified = -1, + kRGBA32F, + kR32F, + kRGBA16F, + kR16F, + kRGBA8, + kR8, + kRGBA8I, + kR8I, + }; + + static const char* FormatToStr(Format format) { + switch (format) { + case Format::kUnspecified: return ""; + case Format::kRGBA32F: return "rgba32f"; + case Format::kR32F: return "r32f"; + case Format::kRGBA16F: return "rgba16f"; + case Format::kR16F: return "r16f"; + case Format::kRGBA8: return "rgba8"; + case Format::kR8: return "r8"; + case Format::kRGBA8I: return "rgba8i"; + case Format::kR8I: return "r8i"; + } + SkFAIL("Unexpected format"); + return ""; + } + + static bool ReadFormat(SkString str, Format* format) { + if (str == "rgba32f") { + *format = Format::kRGBA32F; + return true; + } else if (str == "r32f") { + *format = Format::kR32F; + return true; + } else if (str == "rgba16f") { + *format = Format::kRGBA16F; + return true; + } else if (str == "r16f") { + *format = Format::kR16F; + return true; + } else if (str == "rgba8") { + *format = Format::kRGBA8; + return true; + } else if (str == "r8") { + *format = Format::kR8; + return true; + } else if (str == "rgba8i") { + *format = Format::kRGBA8I; + return true; + } else if (str == "r8i") { + *format = Format::kR8I; + return true; + } + return false; + } Layout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex, bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations, - ASTLayout::Format format, bool pushconstant) + Format format, bool pushconstant) : fLocation(location) , fBinding(binding) , fIndex(index) @@ -54,7 +102,7 @@ struct Layout { , fOriginUpperLeft(false) , fOverrideCoverage(false) , fBlendSupportAllEquations(false) - , fFormat(ASTLayout::Format::kUnspecified) + , fFormat(Format::kUnspecified) , fPushConstant(false) {} SkString description() const { @@ -96,8 +144,8 @@ struct Layout { result += separator + "blend_support_all_equations"; separator = ", "; } - if (ASTLayout::Format::kUnspecified != fFormat) { - result += separator + ASTLayout::FormatToStr(fFormat); + if (Format::kUnspecified != fFormat) { + result += separator + FormatToStr(fFormat); separator = ", "; } if (fPushConstant) { @@ -140,7 +188,7 @@ struct Layout { bool fOriginUpperLeft; bool fOverrideCoverage; bool fBlendSupportAllEquations; - ASTLayout::Format fFormat; + Format fFormat; bool fPushConstant; }; diff --git a/src/sksl/ir/SkSLModifiers.h b/src/sksl/ir/SkSLModifiers.h index fb26677c52..dbb9b6ba5a 100644 --- a/src/sksl/ir/SkSLModifiers.h +++ b/src/sksl/ir/SkSLModifiers.h @@ -4,40 +4,35 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #ifndef SKSL_MODIFIERS #define SKSL_MODIFIERS -#include "../ast/SkSLASTModifiers.h" #include "SkSLLayout.h" namespace SkSL { /** - * A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration. + * A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration. */ struct Modifiers { enum Flag { - kNo_Flag = ASTModifiers::kNo_Flag, - kConst_Flag = ASTModifiers::kConst_Flag, - kIn_Flag = ASTModifiers::kIn_Flag, - kOut_Flag = ASTModifiers::kOut_Flag, - kLowp_Flag = ASTModifiers::kLowp_Flag, - kMediump_Flag = ASTModifiers::kMediump_Flag, - kHighp_Flag = ASTModifiers::kHighp_Flag, - kUniform_Flag = ASTModifiers::kUniform_Flag, - kFlat_Flag = ASTModifiers::kFlat_Flag, - kNoPerspective_Flag = ASTModifiers::kNoPerspective_Flag + kNo_Flag = 0, + kConst_Flag = 1, + kIn_Flag = 2, + kOut_Flag = 4, + kLowp_Flag = 8, + kMediump_Flag = 16, + kHighp_Flag = 32, + kUniform_Flag = 64, + kFlat_Flag = 128, + kNoPerspective_Flag = 256 }; Modifiers() : fLayout(Layout()) , fFlags(0) {} - Modifiers(const ASTModifiers& modifiers) - : fLayout(modifiers.fLayout) - , fFlags(modifiers.fFlags) {} - Modifiers(Layout& layout, int flags) : fLayout(layout) , fFlags(flags) {}