unified ASTLayout/Layout and ASTModifiers/Modifiers

BUG=skia:

Change-Id: Ib4c2c94401e586e93e926776e13c0f7c12212f7e
Reviewed-on: https://skia-review.googlesource.com/5268
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2016-11-28 11:23:23 -05:00 committed by Skia Commit-Bot
parent 2b3dab62bc
commit 11d5397431
12 changed files with 313 additions and 518 deletions

View File

@ -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> symbolTable,
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
ErrorReporter& errorReporter)
: fContext(*context)
, fCurrentFunction(nullptr)
@ -162,10 +162,6 @@ std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
}
Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) {
return Modifiers(modifiers);
}
std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
Variable::Storage storage) {
std::vector<VarDeclaration> variables;
@ -174,7 +170,6 @@ std::unique_ptr<VarDeclarations> 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<std::unique_ptr<Expression>> sizes;
@ -205,8 +200,8 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
sizes.push_back(nullptr);
}
}
auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, varDecl.fName,
*type, storage));
auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers,
varDecl.fName, *type, storage));
std::unique_ptr<Expression> value;
if (varDecl.fValue) {
value = this->convertExpression(*varDecl.fValue);
@ -215,7 +210,7 @@ std::unique_ptr<VarDeclarations> 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<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
fSymbolTable->add(varDecl.fName, std::move(var));
}
}
return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
baseType,
std::move(variables)));
}
std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
const ASTModifiersDeclaration& m) {
Modifiers modifiers = this->convertModifiers(m.fModifiers);
return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(m.fModifiers));
}
std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
*fContext.fBool_Type);
if (!test) {
return nullptr;
@ -266,11 +260,11 @@ std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
} else {
// False & no else clause. Not an error, so don't return null!
std::vector<std::unique_ptr<Statement>> empty;
return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
fSymbolTable));
}
}
return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
std::move(ifTrue), std::move(ifFalse)));
}
@ -303,14 +297,14 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
if (!statement) {
return nullptr;
}
return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
std::move(test), std::move(next),
std::move(statement), fSymbolTable));
}
std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
AutoLoopLevel level(this);
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
*fContext.fBool_Type);
if (!test) {
return nullptr;
@ -334,7 +328,7 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
if (!statement) {
return nullptr;
}
return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
std::move(test)));
}
@ -414,9 +408,8 @@ std::unique_ptr<FunctionDefinition> 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<FunctionDefinition> 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<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
if (!body) {
return nullptr;
}
return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
std::move(body)));
}
return nullptr;
@ -507,20 +500,19 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
std::shared_ptr<SymbolTable> old = fSymbolTable;
AutoSymbolTable table(this);
Modifiers mods = this->convertModifiers(intf.fModifiers);
std::vector<Type::Field> fields;
for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
std::unique_ptr<VarDeclarations> 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<InterfaceBlock> 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<Field>(new Field(intf.fPosition, *var,
old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
(int) i)));
}
}
@ -620,7 +613,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
}
case Symbol::kType_Kind: {
const Type* t = (const Type*) result;
return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
*t));
}
default:
@ -629,7 +622,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
}
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
const Type& type) {
if (!expr) {
return nullptr;
@ -642,7 +635,7 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> 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<Expression> 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<Expression> 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<Expression> 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<Expression> IRGenerator::convertBinaryExpression(
if (!left || !right) {
return nullptr;
}
std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
*right.get());
if (!result) {
result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
@ -931,9 +924,9 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
return result;
}
std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
const ASTTernaryExpression& expression) {
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
*fContext.fBool_Type);
if (!test) {
return nullptr;
@ -951,8 +944,8 @@ std::unique_ptr<Expression> 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<Expression> IRGenerator::convertTernaryExpression(
return ifFalse;
}
}
return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
std::move(test),
std::move(ifTrue),
std::move(ifTrue),
std::move(ifFalse)));
}
std::unique_ptr<Expression> IRGenerator::call(Position position,
const FunctionDeclaration& function,
std::unique_ptr<Expression> IRGenerator::call(Position position,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> 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<Expression> 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<std::unique_ptr<Expression>>& arguments,
int* outCost) {
if (function.fParameters.size() != arguments.size()) {
@ -1043,12 +1036,12 @@ bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
return true;
}
std::unique_ptr<Expression> IRGenerator::call(Position position,
std::unique_ptr<Expression> functionValue,
std::unique_ptr<Expression> IRGenerator::call(Position position,
std::unique_ptr<Expression> functionValue,
std::vector<std::unique_ptr<Expression>> 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<Expression> IRGenerator::call(Position position,
}
std::unique_ptr<Expression> IRGenerator::convertConstructor(
Position position,
const Type& type,
Position position,
const 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 &&
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<Expression>(new FloatLiteral(fContext, position, (double) value));
@ -1105,7 +1098,7 @@ std::unique_ptr<Expression> 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<Expression> IRGenerator::convertConstructor(
return std::unique_ptr<Expression>(
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<Expression>(new IntLiteral(fContext,
position,
return std::unique_ptr<Expression>(new IntLiteral(fContext,
position,
((IntLiteral&) *args[0]).fValue,
&type));
}
@ -1170,9 +1163,9 @@ std::unique_ptr<Expression> 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<Expression> 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<Expression> IRGenerator::convertPrefixExpression(
}
if (base->fKind == Expression::kFloatLiteral_Kind) {
double value = -((FloatLiteral&) *base).fValue;
return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
value));
}
return std::unique_ptr<Expression>(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<Expression> 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<Expression> 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<Expression>(new PrefixExpression(expression.fOperator,
return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
std::move(base)));
}
@ -1259,7 +1252,7 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
const ASTExpression& index) {
if (base->fType.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<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
return nullptr;
}
}
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
std::move(converted)));
}
@ -1301,7 +1294,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
switch (fields[i]) {
case 'x': // fall through
case 'r': // fall through
case 's':
case 's':
swizzleComponents.push_back(0);
break;
case 'y': // fall through
@ -1314,7 +1307,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
// fall through
case 'z': // fall through
case 'b': // fall through
case 'p':
case 'p':
if (base->fType.columns() >= 3) {
swizzleComponents.push_back(2);
break;
@ -1354,7 +1347,7 @@ std::unique_ptr<Expression> IRGenerator::getCap(Position position, SkString name
return std::unique_ptr<Expression>(new BoolLiteral(fContext, position,
(bool) found->second.fValue));
case CapValue::kInt_Kind:
return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
found->second.fValue));
}
ASSERT(false);
@ -1374,10 +1367,10 @@ std::unique_ptr<Expression> 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<Expression>(new TypeReference(fContext, base->fPosition,
return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
*newType));
} else {
fErrors.error(expression.fPosition, "'[]' must follow a type name");
@ -1388,7 +1381,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
std::vector<std::unique_ptr<Expression>> arguments;
for (size_t i = 0; i < rawArguments->size(); i++) {
std::unique_ptr<Expression> converted =
std::unique_ptr<Expression> converted =
this->convertExpression(*(*rawArguments)[i]);
if (!converted) {
return nullptr;
@ -1404,34 +1397,34 @@ std::unique_ptr<Expression> 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<Expression>(new PostfixExpression(std::move(base),
return std::unique_ptr<Expression>(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<Expression>(new PostfixExpression(std::move(base),
return std::unique_ptr<Expression>(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);

View File

@ -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<SymbolTable> root,
IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
ErrorReporter& errorReporter);
std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTVarDeclarations& decl,
std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTVarDeclarations& decl,
Variable::Storage storage);
std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f);
std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
@ -104,25 +103,25 @@ private:
void popSymbolTable();
const Type* convertType(const ASTType& type);
std::unique_ptr<Expression> call(Position position,
const FunctionDeclaration& function,
std::unique_ptr<Expression> call(Position position,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments);
bool determineCallCost(const FunctionDeclaration& function,
bool determineCallCost(const FunctionDeclaration& function,
const std::vector<std::unique_ptr<Expression>>& arguments,
int* outCost);
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
std::vector<std::unique_ptr<Expression>> arguments);
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
std::unique_ptr<Block> convertBlock(const ASTBlock& block);
std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
std::unique_ptr<Expression> convertConstructor(Position position,
const Type& type,
std::unique_ptr<Expression> convertConstructor(Position position,
const Type& type,
std::vector<std::unique_ptr<Expression>> params);
std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
std::unique_ptr<Expression> 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<Expression> constantFold(const Expression& left,
Token::Kind op,
@ -135,12 +134,12 @@ private:
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
const ASTExpression& index);
std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTInterfaceBlock& s);
Modifiers convertModifiers(const ASTModifiers& m);
Modifiers convertModifiers(const Modifiers& m);
std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
std::unique_ptr<Expression> getCap(Position position, SkString name);
std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
const SkString& field);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
const SkString& fields);

View File

@ -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<ASTDeclaration> 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<ASTDeclaration> Parser::precision() {
return std::unique_ptr<ASTDeclaration>(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<ASTDeclaration> Parser::directive() {
Token start;
@ -269,7 +270,7 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
if (!this->expect(Token::IDENTIFIER, "an identifier")) {
return nullptr;
}
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
std::move(name.fText)));
} else {
this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
@ -277,10 +278,10 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
}
}
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
(COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
std::unique_ptr<ASTDeclaration> 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<ASTDeclaration> Parser::declaration() {
return nullptr;
}
}
return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
std::move(name.fText),
std::move(parameters),
return std::unique_ptr<ASTDeclaration>(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<ASTDeclaration> Parser::declaration() {
/* modifiers type IDENTIFIER varDeclarationEnd */
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
ASTModifiers modifiers = this->modifiers();
Modifiers modifiers = this->modifiers();
std::unique_ptr<ASTType> type(this->type());
if (!type) {
return nullptr;
@ -393,25 +394,25 @@ std::unique_ptr<ASTType> Parser::structDeclaration() {
return nullptr;
}
fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fText, fields)));
return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
ASTType::kStruct_Kind));
}
/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers modifiers) {
std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
std::unique_ptr<ASTType> type = this->structDeclaration();
if (!type) {
return nullptr;
}
if (peek().fKind == Token::IDENTIFIER) {
Token name = this->nextToken();
std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
std::move(type),
std::unique_ptr<ASTVarDeclarations> 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<ASTVarDeclarations> 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<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
std::unique_ptr<ASTType> type,
SkString name) {
std::vector<ASTVarDeclaration> vars;
@ -497,7 +498,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
std::unique_ptr<ASTParameter> Parser::parameter() {
ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag);
Modifiers modifiers = this->modifiersWithDefaults(Modifiers::kIn_Flag);
std::unique_ptr<ASTType> type = this->type();
if (!type) {
return nullptr;
@ -518,8 +519,8 @@ std::unique_ptr<ASTParameter> Parser::parameter() {
return nullptr;
}
}
return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
std::move(type), name.fText,
return std::unique_ptr<ASTParameter>(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<ASTStatement> Parser::statement() {
case Token::LBRACE:
return this->block();
case Token::SEMICOLON:
this->nextToken();
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
this->nextToken();
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
std::vector<std::unique_ptr<ASTStatement>>()));
case Token::CONST: // fall through
case Token::HIGHP: // fall through
@ -706,7 +707,7 @@ std::unique_ptr<ASTStatement> Parser::statement() {
// fall through
default:
return this->expressionStatement();
}
}
}
/* IDENTIFIER(type) */
@ -719,25 +720,25 @@ std::unique_ptr<ASTType> Parser::type() {
this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
return nullptr;
}
return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
ASTType::kIdentifier_Kind));
}
/* IDENTIFIER LBRACE varDeclaration* RBRACE */
std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
std::unique_ptr<ASTDeclaration> 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<std::unique_ptr<ASTVarDeclarations>> decls;
std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
while (this->peek().fKind != Token::RBRACE) {
std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
if (!decl) {
@ -751,7 +752,7 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
valueName = this->nextToken().fText;
}
this->expect(Token::SEMICOLON, "';'");
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
name.fText, std::move(valueName),
std::move(decls)));
}
@ -784,8 +785,8 @@ std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
return nullptr;
}
}
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
std::move(ifTrue),
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
std::move(ifTrue),
std::move(ifFalse)));
}
@ -815,7 +816,7 @@ std::unique_ptr<ASTDoStatement> Parser::doStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
std::move(statement),
std::move(test)));
}
@ -840,12 +841,12 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
if (!statement) {
return nullptr;
}
return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
std::move(test),
return std::unique_ptr<ASTWhileStatement>(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<ASTForStatement> Parser::forStatement() {
Token start;
@ -858,7 +859,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() {
std::unique_ptr<ASTStatement> 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<ASTForStatement> Parser::forStatement() {
if (!statement) {
return nullptr;
}
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
std::move(initializer),
std::move(test), std::move(next),
std::move(statement)));
@ -930,7 +931,7 @@ std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
if (!this->expect(Token::SEMICOLON, "';'")) {
return nullptr;
}
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
std::move(expression)));
}
@ -983,11 +984,11 @@ std::unique_ptr<ASTBlock> Parser::block() {
std::vector<std::unique_ptr<ASTStatement>> statements;
for (;;) {
switch (this->peek().fKind) {
case Token::RBRACE:
case Token::RBRACE:
this->nextToken();
return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
return std::unique_ptr<ASTBlock>(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<ASTExpression> Parser::assignmentExpression() {
if (!right) {
return nullptr;
}
result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
t,
result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
t,
std::move(right)));
}
default:
@ -1076,8 +1077,8 @@ std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
}
if (this->expect(Token::COLON, "':'")) {
std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
std::move(trueExpr),
return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
std::move(trueExpr),
std::move(falseExpr)));
}
return nullptr;
@ -1357,7 +1358,7 @@ std::unique_ptr<ASTExpression> Parser::postfixExpression() {
}
}
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
PLUSPLUS | MINUSMINUS */
std::unique_ptr<ASTSuffix> Parser::suffix() {
Token next = this->nextToken();
@ -1398,17 +1399,17 @@ std::unique_ptr<ASTSuffix> Parser::suffix() {
}
}
this->expect(Token::RPAREN, "')' to complete function parameters");
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
std::move(parameters)));
}
case Token::PLUSPLUS:
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
ASTSuffix::kPostIncrement_Kind));
case Token::MINUSMINUS:
return std::unique_ptr<ASTSuffix>(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;

View File

@ -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<ASTType> structDeclaration();
std::unique_ptr<ASTVarDeclarations> structVarDeclaration(ASTModifiers modifiers);
std::unique_ptr<ASTVarDeclarations> structVarDeclaration(Modifiers modifiers);
std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(ASTModifiers modifiers,
std::unique_ptr<ASTType> type,
std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers,
std::unique_ptr<ASTType> type,
SkString name);
std::unique_ptr<ASTParameter> parameter();
int layoutInt();
ASTLayout layout();
Layout layout();
ASTModifiers modifiers();
Modifiers modifiers();
ASTModifiers modifiersWithDefaults(int defaultFlags);
Modifiers modifiersWithDefaults(int defaultFlags);
std::unique_ptr<ASTStatement> statement();
std::unique_ptr<ASTType> type();
std::unique_ptr<ASTDeclaration> interfaceBlock(ASTModifiers mods);
std::unique_ptr<ASTDeclaration> interfaceBlock(Modifiers mods);
std::unique_ptr<ASTIfStatement> ifStatement();
@ -157,7 +157,7 @@ private:
std::unique_ptr<ASTExpression> expression();
std::unique_ptr<ASTExpression> assignmentExpression();
std::unique_ptr<ASTExpression> ternaryExpression();
std::unique_ptr<ASTExpression> logicalOrExpression();

View File

@ -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<std::unique_ptr<ASTVarDeclarations>> 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<std::unique_ptr<ASTVarDeclarations>> fDeclarations;

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -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<ASTType> type,
ASTParameter(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type,
SkString name, std::vector<int> 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<ASTType> fType;
const SkString fName;
const std::vector<int> fSizes;

View File

@ -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<ASTType> type,
ASTVarDeclarations(Modifiers modifiers,
std::unique_ptr<ASTType> type,
std::vector<ASTVarDeclaration> 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<ASTType> fType;
const std::vector<ASTVarDeclaration> fVars;

View File

@ -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;
};

View File

@ -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) {}