Convert Operators namespace to first-class Operator object.
This lets us write `op.isAssignment()` instead of `Operators::IsAssignment(op)`. Change-Id: If35f2ac500b6ccabc364f9104faaad6e62564667 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/369958 Commit-Queue: John Stiles <johnstiles@google.com> Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
4a3ec173b3
commit
4599050369
@ -17,7 +17,7 @@ String ASTNode::description() const {
|
||||
case Kind::kNull: return "";
|
||||
case Kind::kBinary:
|
||||
return "(" + this->begin()->description() + " " +
|
||||
Operators::OperatorName(getToken().fKind) + " " +
|
||||
getOperator().operatorName() + " " +
|
||||
(this->begin() + 1)->description() + ")";
|
||||
case Kind::kBlock: {
|
||||
String result = "{\n";
|
||||
@ -162,9 +162,9 @@ String ASTNode::description() const {
|
||||
return result;
|
||||
}
|
||||
case Kind::kPostfix:
|
||||
return this->begin()->description() + Operators::OperatorName(getToken().fKind);
|
||||
return this->begin()->description() + getOperator().operatorName();
|
||||
case Kind::kPrefix:
|
||||
return Operators::OperatorName(getToken().fKind) + this->begin()->description();
|
||||
return getOperator().operatorName() + this->begin()->description();
|
||||
case Kind::kReturn:
|
||||
if (this->begin() != this->end()) {
|
||||
return "return " + this->begin()->description() + ";";
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define SKSL_ASTNODE
|
||||
|
||||
#include "src/sksl/SkSLLexer.h"
|
||||
#include "src/sksl/SkSLOperators.h"
|
||||
#include "src/sksl/SkSLString.h"
|
||||
#include "src/sksl/ir/SkSLModifiers.h"
|
||||
|
||||
@ -53,7 +54,7 @@ struct ASTNode {
|
||||
};
|
||||
|
||||
enum class Kind {
|
||||
// data: operator(Token), children: left, right
|
||||
// data: operator, children: left, right
|
||||
kBinary,
|
||||
// children: statements
|
||||
kBlock,
|
||||
@ -97,9 +98,9 @@ struct ASTNode {
|
||||
kNull,
|
||||
// data: ParameterData, children: type, arraySize1, arraySize2, ..., value?
|
||||
kParameter,
|
||||
// data: operator(Token), children: operand
|
||||
// data: operator, children: operand
|
||||
kPostfix,
|
||||
// data: operator(Token), children: operand
|
||||
// data: operator, children: operand
|
||||
kPrefix,
|
||||
// children: value
|
||||
kReturn,
|
||||
@ -250,7 +251,7 @@ struct ASTNode {
|
||||
};
|
||||
|
||||
struct NodeData {
|
||||
char fBytes[std::max({sizeof(Token),
|
||||
char fBytes[std::max({sizeof(Token::Kind),
|
||||
sizeof(StringFragment),
|
||||
sizeof(bool),
|
||||
sizeof(SKSL_INT),
|
||||
@ -263,7 +264,7 @@ struct ASTNode {
|
||||
sizeof(SectionData)})];
|
||||
|
||||
enum class Kind {
|
||||
kToken,
|
||||
kOperator,
|
||||
kStringFragment,
|
||||
kBool,
|
||||
kInt,
|
||||
@ -278,8 +279,9 @@ struct ASTNode {
|
||||
|
||||
NodeData() = default;
|
||||
|
||||
NodeData(Token data)
|
||||
: fKind(Kind::kToken) {
|
||||
NodeData(Operator op)
|
||||
: fKind(Kind::kOperator) {
|
||||
Token::Kind data = op.kind();
|
||||
memcpy(fBytes, &data, sizeof(data));
|
||||
}
|
||||
|
||||
@ -341,12 +343,13 @@ struct ASTNode {
|
||||
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind)
|
||||
: fNodes(nodes)
|
||||
, fOffset(offset)
|
||||
, fKind(kind) {
|
||||
, fKind(kind) {
|
||||
|
||||
switch (kind) {
|
||||
case Kind::kBinary:
|
||||
case Kind::kPostfix:
|
||||
case Kind::kPrefix:
|
||||
fData.fKind = NodeData::Kind::kToken;
|
||||
fData.fKind = NodeData::Kind::kOperator;
|
||||
break;
|
||||
|
||||
case Kind::kBool:
|
||||
@ -398,9 +401,9 @@ struct ASTNode {
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Token t)
|
||||
ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Operator op)
|
||||
: fNodes(nodes)
|
||||
, fData(t)
|
||||
, fData(op)
|
||||
, fOffset(offset)
|
||||
, fKind(kind) {}
|
||||
|
||||
@ -450,11 +453,11 @@ struct ASTNode {
|
||||
return fKind != Kind::kNull;
|
||||
}
|
||||
|
||||
Token getToken() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kToken);
|
||||
Token result;
|
||||
memcpy(&result, fData.fBytes, sizeof(result));
|
||||
return result;
|
||||
Operator getOperator() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kOperator);
|
||||
Token::Kind tokenKind;
|
||||
memcpy(&tokenKind, fData.fBytes, sizeof(tokenKind));
|
||||
return Operator{tokenKind};
|
||||
}
|
||||
|
||||
bool getBool() const {
|
||||
|
@ -538,7 +538,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
|
||||
return "expected loop index on left hand side of condition";
|
||||
}
|
||||
// relational_operator is one of: > >= < <= == or !=
|
||||
switch (cond.getOperator()) {
|
||||
switch (cond.getOperator().kind()) {
|
||||
case Token::Kind::TK_GT:
|
||||
case Token::Kind::TK_GTEQ:
|
||||
case Token::Kind::TK_LT:
|
||||
@ -575,7 +575,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
|
||||
if (!getConstant(next.right(), &loopInfo.fDelta)) {
|
||||
return "loop index must be modified by a constant expression";
|
||||
}
|
||||
switch (next.getOperator()) {
|
||||
switch (next.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSEQ: break;
|
||||
case Token::Kind::TK_MINUSEQ: loopInfo.fDelta = -loopInfo.fDelta; break;
|
||||
default:
|
||||
@ -587,7 +587,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
|
||||
if (!is_loop_index(next.operand())) {
|
||||
return "expected loop index in loop expression";
|
||||
}
|
||||
switch (next.getOperator()) {
|
||||
switch (next.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSPLUS: loopInfo.fDelta = 1; break;
|
||||
case Token::Kind::TK_MINUSMINUS: loopInfo.fDelta = -1; break;
|
||||
default:
|
||||
@ -599,7 +599,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
|
||||
if (!is_loop_index(next.operand())) {
|
||||
return "expected loop index in loop expression";
|
||||
}
|
||||
switch (next.getOperator()) {
|
||||
switch (next.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSPLUS: loopInfo.fDelta = 1; break;
|
||||
case Token::Kind::TK_MINUSMINUS: loopInfo.fDelta = -1; break;
|
||||
default:
|
||||
@ -624,7 +624,7 @@ static const char* invalid_for_ES2(const ForStatement& loop,
|
||||
|
||||
double val = loopInfo.fStart;
|
||||
auto evalCond = [&]() {
|
||||
switch (cond.getOperator()) {
|
||||
switch (cond.getOperator().kind()) {
|
||||
case Token::Kind::TK_GT: return val > loopEnd;
|
||||
case Token::Kind::TK_GTEQ: return val >= loopEnd;
|
||||
case Token::Kind::TK_LT: return val < loopEnd;
|
||||
|
@ -197,7 +197,7 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
|
||||
switch (expr->kind()) {
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression& b = expr->as<BinaryExpression>();
|
||||
if (b.getOperator() == Token::Kind::TK_EQ) {
|
||||
if (b.getOperator().kind() == Token::Kind::TK_EQ) {
|
||||
if (!this->tryRemoveLValueBefore(iter, b.left().get())) {
|
||||
return false;
|
||||
}
|
||||
@ -349,8 +349,8 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
switch ((*e)->kind()) {
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression& b = e->get()->as<BinaryExpression>();
|
||||
Token::Kind op = b.getOperator();
|
||||
switch (op) {
|
||||
Operator op = b.getOperator();
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_LOGICALAND: // fall through
|
||||
case Token::Kind::TK_LOGICALOR: {
|
||||
// this isn't as precise as it could be -- we don't bother to track that if we
|
||||
@ -374,8 +374,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this->addExpression(cfg, &b.left(),
|
||||
!Operators::IsAssignment(b.getOperator()));
|
||||
this->addExpression(cfg, &b.left(), !b.getOperator().isAssignment());
|
||||
this->addExpression(cfg, &b.right(), constantPropagate);
|
||||
cfg.currentBlock().fNodes.push_back(
|
||||
BasicBlock::MakeExpression(e, constantPropagate));
|
||||
@ -421,9 +420,10 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
|
||||
}
|
||||
case Expression::Kind::kPrefix: {
|
||||
PrefixExpression& p = e->get()->as<PrefixExpression>();
|
||||
this->addExpression(cfg, &p.operand(), constantPropagate &&
|
||||
p.getOperator() != Token::Kind::TK_PLUSPLUS &&
|
||||
p.getOperator() != Token::Kind::TK_MINUSMINUS);
|
||||
this->addExpression(cfg, &p.operand(),
|
||||
constantPropagate &&
|
||||
p.getOperator().kind() != Token::Kind::TK_PLUSPLUS &&
|
||||
p.getOperator().kind() != Token::Kind::TK_MINUSMINUS);
|
||||
cfg.currentBlock().fNodes.push_back(BasicBlock::MakeExpression(e, constantPropagate));
|
||||
break;
|
||||
}
|
||||
|
@ -72,10 +72,10 @@ void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
if (op == Token::Kind::TK_PERCENT) {
|
||||
Operator op = b.getOperator();
|
||||
if (op.kind() == Token::Kind::TK_PERCENT) {
|
||||
// need to use "%%" instead of "%" b/c the code will be inside of a printf
|
||||
Precedence precedence = Operators::GetBinaryPrecedence(op);
|
||||
Precedence precedence = op.getBinaryPrecedence();
|
||||
if (precedence >= parentPrecedence) {
|
||||
this->write("(");
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
bool generateCode() override;
|
||||
|
||||
private:
|
||||
using Precedence = Operators::Precedence;
|
||||
using Precedence = Operator::Precedence;
|
||||
|
||||
void writef(const char* s, va_list va) SK_PRINTF_LIKE(2, 0);
|
||||
|
||||
|
@ -431,7 +431,7 @@ static bool is_dead(const Expression& lvalue, ProgramUsage* usage) {
|
||||
* to a dead target and lack of side effects on the left hand side.
|
||||
*/
|
||||
static bool dead_assignment(const BinaryExpression& b, ProgramUsage* usage) {
|
||||
if (!Operators::IsAssignment(b.getOperator())) {
|
||||
if (!b.getOperator().isAssignment()) {
|
||||
return false;
|
||||
}
|
||||
return is_dead(*b.left(), usage);
|
||||
@ -477,7 +477,7 @@ static bool is_matching_expression_tree(const Expression& left, const Expression
|
||||
}
|
||||
|
||||
static bool self_assignment(const BinaryExpression& b) {
|
||||
return b.getOperator() == Token::Kind::TK_EQ &&
|
||||
return b.getOperator().kind() == Token::Kind::TK_EQ &&
|
||||
is_matching_expression_tree(*b.left(), *b.right());
|
||||
}
|
||||
|
||||
@ -576,7 +576,7 @@ static void delete_left(BasicBlock* b,
|
||||
std::unique_ptr<Expression>& rightPointer = bin.right();
|
||||
SkASSERT(!left.hasSideEffects());
|
||||
bool result;
|
||||
if (bin.getOperator() == Token::Kind::TK_EQ) {
|
||||
if (bin.getOperator().kind() == Token::Kind::TK_EQ) {
|
||||
result = b->tryRemoveLValueBefore(iter, &left);
|
||||
} else {
|
||||
result = b->tryRemoveExpressionBefore(iter, &left);
|
||||
@ -764,7 +764,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
|
||||
(!rightType.isScalar() && !rightType.isVector())) {
|
||||
break;
|
||||
}
|
||||
switch (bin->getOperator()) {
|
||||
switch (bin->getOperator().kind()) {
|
||||
case Token::Kind::TK_STAR:
|
||||
if (is_constant(left, 1)) {
|
||||
if (leftType.isVector() && rightType.isScalar()) {
|
||||
|
@ -24,17 +24,17 @@
|
||||
namespace SkSL {
|
||||
|
||||
static std::unique_ptr<Expression> eliminate_no_op_boolean(const Expression& left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Expression& right) {
|
||||
SkASSERT(right.is<BoolLiteral>());
|
||||
bool rightVal = right.as<BoolLiteral>().value();
|
||||
|
||||
// Detect no-op Boolean expressions and optimize them away.
|
||||
if ((op == Token::Kind::TK_LOGICALAND && rightVal) || // (expr && true) -> (expr)
|
||||
(op == Token::Kind::TK_LOGICALOR && !rightVal) || // (expr || false) -> (expr)
|
||||
(op == Token::Kind::TK_LOGICALXOR && !rightVal) || // (expr ^^ false) -> (expr)
|
||||
(op == Token::Kind::TK_EQEQ && rightVal) || // (expr == true) -> (expr)
|
||||
(op == Token::Kind::TK_NEQ && !rightVal)) { // (expr != false) -> (expr)
|
||||
if ((op.kind() == Token::Kind::TK_LOGICALAND && rightVal) || // (expr && true) -> (expr)
|
||||
(op.kind() == Token::Kind::TK_LOGICALOR && !rightVal) || // (expr || false) -> (expr)
|
||||
(op.kind() == Token::Kind::TK_LOGICALXOR && !rightVal) || // (expr ^^ false) -> (expr)
|
||||
(op.kind() == Token::Kind::TK_EQEQ && rightVal) || // (expr == true) -> (expr)
|
||||
(op.kind() == Token::Kind::TK_NEQ && !rightVal)) { // (expr != false) -> (expr)
|
||||
|
||||
return left.clone();
|
||||
}
|
||||
@ -43,14 +43,14 @@ static std::unique_ptr<Expression> eliminate_no_op_boolean(const Expression& lef
|
||||
}
|
||||
|
||||
static std::unique_ptr<Expression> short_circuit_boolean(const Expression& left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Expression& right) {
|
||||
SkASSERT(left.is<BoolLiteral>());
|
||||
bool leftVal = left.as<BoolLiteral>().value();
|
||||
|
||||
// When the literal is on the left, we can sometimes eliminate the other expression entirely.
|
||||
if ((op == Token::Kind::TK_LOGICALAND && !leftVal) || // (false && expr) -> (false)
|
||||
(op == Token::Kind::TK_LOGICALOR && leftVal)) { // (true || expr) -> (true)
|
||||
if ((op.kind() == Token::Kind::TK_LOGICALAND && !leftVal) || // (false && expr) -> (false)
|
||||
(op.kind() == Token::Kind::TK_LOGICALOR && leftVal)) { // (true || expr) -> (true)
|
||||
|
||||
return left.clone();
|
||||
}
|
||||
@ -67,15 +67,15 @@ static std::unique_ptr<Expression> short_circuit_boolean(const Expression& left,
|
||||
template <typename T, typename U = T>
|
||||
static std::unique_ptr<Expression> simplify_vector(const Context& context,
|
||||
const Expression& left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Expression& right) {
|
||||
SkASSERT(left.type().isVector());
|
||||
SkASSERT(left.type() == right.type());
|
||||
const Type& type = left.type();
|
||||
|
||||
// Handle boolean operations: == !=
|
||||
if (op == Token::Kind::TK_EQEQ || op == Token::Kind::TK_NEQ) {
|
||||
bool equality = (op == Token::Kind::TK_EQEQ);
|
||||
if (op.kind() == Token::Kind::TK_EQEQ || op.kind() == Token::Kind::TK_NEQ) {
|
||||
bool equality = (op.kind() == Token::Kind::TK_EQEQ);
|
||||
|
||||
switch (left.compareConstant(right)) {
|
||||
case Expression::ComparisonResult::kNotEqual:
|
||||
@ -102,7 +102,7 @@ static std::unique_ptr<Expression> simplify_vector(const Context& context,
|
||||
return std::make_unique<Constructor>(left.fOffset, &type, std::move(args));
|
||||
};
|
||||
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_PLUS: return vectorComponentwiseFold([](U a, U b) { return a + b; });
|
||||
case Token::Kind::TK_MINUS: return vectorComponentwiseFold([](U a, U b) { return a - b; });
|
||||
case Token::Kind::TK_STAR: return vectorComponentwiseFold([](U a, U b) { return a * b; });
|
||||
@ -167,9 +167,9 @@ static bool contains_constant_zero(const Expression& expr) {
|
||||
(ConstantFolder::GetConstantFloat(expr, &floatValue) && floatValue == 0.0f);
|
||||
}
|
||||
|
||||
bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Token::Kind op,
|
||||
bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Operator op,
|
||||
const Expression& right) {
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_SLASH:
|
||||
case Token::Kind::TK_SLASHEQ:
|
||||
case Token::Kind::TK_PERCENT:
|
||||
@ -187,11 +187,11 @@ bool ConstantFolder::ErrorOnDivideByZero(const Context& context, int offset, Tok
|
||||
std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
|
||||
int offset,
|
||||
const Expression& left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Expression& right) {
|
||||
// If this is the comma operator, the left side is evaluated but not otherwise used in any way.
|
||||
// So if the left side has no side effects, it can just be eliminated entirely.
|
||||
if (op == Token::Kind::TK_COMMA && !left.hasSideEffects()) {
|
||||
if (op.kind() == Token::Kind::TK_COMMA && !left.hasSideEffects()) {
|
||||
return right.clone();
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
|
||||
bool leftVal = left.as<BoolLiteral>().value();
|
||||
bool rightVal = right.as<BoolLiteral>().value();
|
||||
bool result;
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_LOGICALAND: result = leftVal && rightVal; break;
|
||||
case Token::Kind::TK_LOGICALOR: result = leftVal || rightVal; break;
|
||||
case Token::Kind::TK_LOGICALXOR: result = leftVal ^ rightVal; break;
|
||||
@ -249,7 +249,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
|
||||
if (left.is<IntLiteral>() && right.is<IntLiteral>()) {
|
||||
SKSL_INT leftVal = left.as<IntLiteral>().value();
|
||||
SKSL_INT rightVal = right.as<IntLiteral>().value();
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_PLUS: return URESULT(Int, +);
|
||||
case Token::Kind::TK_MINUS: return URESULT(Int, -);
|
||||
case Token::Kind::TK_STAR: return URESULT(Int, *);
|
||||
@ -298,7 +298,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
|
||||
if (left.is<FloatLiteral>() && right.is<FloatLiteral>()) {
|
||||
SKSL_FLOAT leftVal = left.as<FloatLiteral>().value();
|
||||
SKSL_FLOAT rightVal = right.as<FloatLiteral>().value();
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_PLUS: return RESULT(Float, +);
|
||||
case Token::Kind::TK_MINUS: return RESULT(Float, -);
|
||||
case Token::Kind::TK_STAR: return RESULT(Float, *);
|
||||
@ -354,7 +354,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
|
||||
// Perform constant folding on pairs of matrices.
|
||||
if (leftType.isMatrix() && rightType.isMatrix()) {
|
||||
bool equality;
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQEQ:
|
||||
equality = true;
|
||||
break;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "src/sksl/SkSLDefines.h"
|
||||
#include "src/sksl/SkSLLexer.h"
|
||||
#include "src/sksl/SkSLOperators.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -41,14 +41,14 @@ public:
|
||||
* Reports an error and returns true if op is a division / mod operator and right is zero or
|
||||
* contains a zero element.
|
||||
*/
|
||||
static bool ErrorOnDivideByZero(const Context& context, int offset, Token::Kind op,
|
||||
static bool ErrorOnDivideByZero(const Context& context, int offset, Operator op,
|
||||
const Expression& right);
|
||||
|
||||
/** Simplifies the binary expression `left OP right`. Returns null if it can't be simplified. */
|
||||
static std::unique_ptr<Expression> Simplify(const Context& context,
|
||||
int offset,
|
||||
const Expression& left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Expression& right);
|
||||
};
|
||||
|
||||
|
@ -119,9 +119,9 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
|
||||
switch (expr->kind()) {
|
||||
case Expression::Kind::kBinary: {
|
||||
BinaryExpression* b = &expr->as<BinaryExpression>();
|
||||
if (b->getOperator() == Token::Kind::TK_EQ) {
|
||||
if (b->getOperator().kind() == Token::Kind::TK_EQ) {
|
||||
this->addDefinition(context, b->left().get(), &b->right());
|
||||
} else if (Operators::IsAssignment(b->getOperator())) {
|
||||
} else if (b->getOperator().isAssignment()) {
|
||||
this->addDefinition(
|
||||
context, b->left().get(),
|
||||
(std::unique_ptr<Expression>*)&context.fDefined_Expression);
|
||||
@ -142,8 +142,8 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
|
||||
}
|
||||
case Expression::Kind::kPrefix: {
|
||||
const PrefixExpression* p = &expr->as<PrefixExpression>();
|
||||
if (p->getOperator() == Token::Kind::TK_MINUSMINUS ||
|
||||
p->getOperator() == Token::Kind::TK_PLUSPLUS) {
|
||||
if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
|
||||
p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
|
||||
this->addDefinition(
|
||||
context, p->operand().get(),
|
||||
(std::unique_ptr<Expression>*)&context.fDefined_Expression);
|
||||
@ -152,8 +152,8 @@ void DefinitionMap::addDefinitions(const Context& context, const BasicBlock::Nod
|
||||
}
|
||||
case Expression::Kind::kPostfix: {
|
||||
const PostfixExpression* p = &expr->as<PostfixExpression>();
|
||||
if (p->getOperator() == Token::Kind::TK_MINUSMINUS ||
|
||||
p->getOperator() == Token::Kind::TK_PLUSPLUS) {
|
||||
if (p->getOperator().kind() == Token::Kind::TK_MINUSMINUS ||
|
||||
p->getOperator().kind() == Token::Kind::TK_PLUSPLUS) {
|
||||
this->addDefinition(
|
||||
context, p->operand().get(),
|
||||
(std::unique_ptr<Expression>*)&context.fDefined_Expression);
|
||||
|
@ -262,7 +262,7 @@ void Dehydrator::write(const Expression* e) {
|
||||
const BinaryExpression& b = e->as<BinaryExpression>();
|
||||
this->writeCommand(Rehydrator::kBinary_Command);
|
||||
this->write(b.left().get());
|
||||
this->writeU8((int) b.getOperator());
|
||||
this->writeU8((int) b.getOperator().kind());
|
||||
this->write(b.right().get());
|
||||
this->write(b.type());
|
||||
break;
|
||||
@ -332,14 +332,14 @@ void Dehydrator::write(const Expression* e) {
|
||||
case Expression::Kind::kPostfix: {
|
||||
const PostfixExpression& p = e->as<PostfixExpression>();
|
||||
this->writeCommand(Rehydrator::kPostfix_Command);
|
||||
this->writeU8((int) p.getOperator());
|
||||
this->writeU8((int) p.getOperator().kind());
|
||||
this->write(p.operand().get());
|
||||
break;
|
||||
}
|
||||
case Expression::Kind::kPrefix: {
|
||||
const PrefixExpression& p = e->as<PrefixExpression>();
|
||||
this->writeCommand(Rehydrator::kPrefix_Command);
|
||||
this->writeU8((int) p.getOperator());
|
||||
this->writeU8((int) p.getOperator().kind());
|
||||
this->write(p.operand().get());
|
||||
break;
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
arguments.size() == 2 &&
|
||||
arguments[1]->kind() == Expression::Kind::kPrefix) {
|
||||
const PrefixExpression& p = (PrefixExpression&) *arguments[1];
|
||||
if (p.getOperator() == Token::Kind::TK_MINUS) {
|
||||
if (p.getOperator().kind() == Token::Kind::TK_MINUS) {
|
||||
this->write("atan(");
|
||||
this->writeExpression(*arguments[0], Precedence::kSequence);
|
||||
this->write(", -1.0 * ");
|
||||
@ -862,21 +862,21 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
Operator op = b.getOperator();
|
||||
if (fProgram.fCaps->unfoldShortCircuitAsTernary() &&
|
||||
(op == Token::Kind::TK_LOGICALAND || op == Token::Kind::TK_LOGICALOR)) {
|
||||
(op.kind() == Token::Kind::TK_LOGICALAND || op.kind() == Token::Kind::TK_LOGICALOR)) {
|
||||
this->writeShortCircuitWorkaroundExpression(b, parentPrecedence);
|
||||
return;
|
||||
}
|
||||
|
||||
Precedence precedence = Operators::GetBinaryPrecedence(op);
|
||||
Precedence precedence = op.getBinaryPrecedence();
|
||||
if (precedence >= parentPrecedence) {
|
||||
this->write("(");
|
||||
}
|
||||
bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
|
||||
Operators::IsAssignment(op) &&
|
||||
left.kind() == Expression::Kind::kFieldAccess &&
|
||||
is_sk_position((FieldAccess&) left) &&
|
||||
op.isAssignment() &&
|
||||
left.is<FieldAccess>() &&
|
||||
is_sk_position(left.as<FieldAccess>()) &&
|
||||
!right.containsRTAdjust() &&
|
||||
!fProgram.fCaps->canUseFragCoord();
|
||||
if (positionWorkaround) {
|
||||
@ -884,7 +884,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
}
|
||||
this->writeExpression(left, precedence);
|
||||
this->write(" ");
|
||||
this->write(Operators::OperatorName(op));
|
||||
this->write(op.operatorName());
|
||||
this->write(" ");
|
||||
this->writeExpression(right, precedence);
|
||||
if (positionWorkaround) {
|
||||
@ -906,14 +906,14 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
|
||||
// a || b => a ? true : b
|
||||
this->writeExpression(*b.left(), Precedence::kTernary);
|
||||
this->write(" ? ");
|
||||
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
|
||||
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
|
||||
this->writeExpression(*b.right(), Precedence::kTernary);
|
||||
} else {
|
||||
BoolLiteral boolTrue(fContext, -1, true);
|
||||
this->writeBoolLiteral(boolTrue);
|
||||
}
|
||||
this->write(" : ");
|
||||
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
|
||||
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
|
||||
BoolLiteral boolFalse(fContext, -1, false);
|
||||
this->writeBoolLiteral(boolFalse);
|
||||
} else {
|
||||
@ -944,7 +944,7 @@ void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
|
||||
if (Precedence::kPrefix >= parentPrecedence) {
|
||||
this->write("(");
|
||||
}
|
||||
this->write(Operators::OperatorName(p.getOperator()));
|
||||
this->write(p.getOperator().operatorName());
|
||||
this->writeExpression(*p.operand(), Precedence::kPrefix);
|
||||
if (Precedence::kPrefix >= parentPrecedence) {
|
||||
this->write(")");
|
||||
@ -957,7 +957,7 @@ void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
|
||||
this->write("(");
|
||||
}
|
||||
this->writeExpression(*p.operand(), Precedence::kPostfix);
|
||||
this->write(Operators::OperatorName(p.getOperator()));
|
||||
this->write(p.getOperator().operatorName());
|
||||
if (Precedence::kPostfix >= parentPrecedence) {
|
||||
this->write(")");
|
||||
}
|
||||
@ -1332,7 +1332,7 @@ void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
|
||||
if (f.test()) {
|
||||
if (fProgram.fCaps->addAndTrueToLoopCondition()) {
|
||||
std::unique_ptr<Expression> and_true(new BinaryExpression(
|
||||
-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
|
||||
/*offset=*/-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
|
||||
std::make_unique<BoolLiteral>(fContext, -1, true),
|
||||
fContext.fTypes.fBool.get()));
|
||||
this->writeExpression(*and_true, Precedence::kTopLevel);
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
bool generateCode() override;
|
||||
|
||||
protected:
|
||||
using Precedence = Operators::Precedence;
|
||||
using Precedence = Operator::Precedence;
|
||||
|
||||
void write(const char* s);
|
||||
|
||||
|
@ -934,10 +934,12 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
|
||||
// sk_Position.w);
|
||||
SkASSERT(skPerVertex && fRTAdjust);
|
||||
auto Ref = [](const Variable* var) -> std::unique_ptr<Expression> {
|
||||
return std::make_unique<VariableReference>(-1, var, VariableReference::RefKind::kRead);
|
||||
return std::make_unique<VariableReference>(/*offset=*/-1, var,
|
||||
VariableReference::RefKind::kRead);
|
||||
};
|
||||
auto WRef = [](const Variable* var) -> std::unique_ptr<Expression> {
|
||||
return std::make_unique<VariableReference>(-1, var, VariableReference::RefKind::kWrite);
|
||||
return std::make_unique<VariableReference>(/*offset=*/-1, var,
|
||||
VariableReference::RefKind::kWrite);
|
||||
};
|
||||
auto Field = [&](const Variable* var, int idx) -> std::unique_ptr<Expression> {
|
||||
return std::make_unique<FieldAccess>(Ref(var), idx,
|
||||
@ -957,8 +959,8 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
|
||||
};
|
||||
auto Op = [&](std::unique_ptr<Expression> left, Token::Kind op,
|
||||
std::unique_ptr<Expression> right) -> std::unique_ptr<Expression> {
|
||||
return std::make_unique<BinaryExpression>(-1, std::move(left), op, std::move(right),
|
||||
fContext.fTypes.fFloat2.get());
|
||||
return std::make_unique<BinaryExpression>(/*offset=*/-1, std::move(left), op,
|
||||
std::move(right), fContext.fTypes.fFloat2.get());
|
||||
};
|
||||
|
||||
static const ComponentArray kXYIndices{0, 1};
|
||||
@ -1720,8 +1722,8 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
|
||||
return this->convertConstructor(offset, type.scalarTypeForLiteral(), std::move(args));
|
||||
}
|
||||
|
||||
static bool is_matrix_multiply(const Type& left, Token::Kind op, const Type& right) {
|
||||
if (op != Token::Kind::TK_STAR && op != Token::Kind::TK_STAREQ) {
|
||||
static bool is_matrix_multiply(const Type& left, Operator op, const Type& right) {
|
||||
if (op.kind() != Token::Kind::TK_STAR && op.kind() != Token::Kind::TK_STAREQ) {
|
||||
return false;
|
||||
}
|
||||
if (left.isMatrix()) {
|
||||
@ -1730,98 +1732,19 @@ static bool is_matrix_multiply(const Type& left, Token::Kind op, const Type& rig
|
||||
return left.isVector() && right.isMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the set of logical (comparison) operators.
|
||||
*/
|
||||
static bool op_is_logical(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_LT:
|
||||
case Token::Kind::TK_GT:
|
||||
case Token::Kind::TK_LTEQ:
|
||||
case Token::Kind::TK_GTEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the set of operators which are only valid on integral types.
|
||||
*/
|
||||
static bool op_only_valid_for_integral_types(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_SHL:
|
||||
case Token::Kind::TK_SHR:
|
||||
case Token::Kind::TK_BITWISEAND:
|
||||
case Token::Kind::TK_BITWISEOR:
|
||||
case Token::Kind::TK_BITWISEXOR:
|
||||
case Token::Kind::TK_PERCENT:
|
||||
case Token::Kind::TK_SHLEQ:
|
||||
case Token::Kind::TK_SHREQ:
|
||||
case Token::Kind::TK_BITWISEANDEQ:
|
||||
case Token::Kind::TK_BITWISEOREQ:
|
||||
case Token::Kind::TK_BITWISEXOREQ:
|
||||
case Token::Kind::TK_PERCENTEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the set of operators which perform vector/matrix math.
|
||||
*/
|
||||
static bool op_valid_for_matrix_or_vector(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_PLUS:
|
||||
case Token::Kind::TK_MINUS:
|
||||
case Token::Kind::TK_STAR:
|
||||
case Token::Kind::TK_SLASH:
|
||||
case Token::Kind::TK_PERCENT:
|
||||
case Token::Kind::TK_SHL:
|
||||
case Token::Kind::TK_SHR:
|
||||
case Token::Kind::TK_BITWISEAND:
|
||||
case Token::Kind::TK_BITWISEOR:
|
||||
case Token::Kind::TK_BITWISEXOR:
|
||||
case Token::Kind::TK_PLUSEQ:
|
||||
case Token::Kind::TK_MINUSEQ:
|
||||
case Token::Kind::TK_STAREQ:
|
||||
case Token::Kind::TK_SLASHEQ:
|
||||
case Token::Kind::TK_PERCENTEQ:
|
||||
case Token::Kind::TK_SHLEQ:
|
||||
case Token::Kind::TK_SHREQ:
|
||||
case Token::Kind::TK_BITWISEANDEQ:
|
||||
case Token::Kind::TK_BITWISEOREQ:
|
||||
case Token::Kind::TK_BITWISEXOREQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1.
|
||||
* The set of illegal (reserved) operators are the ones that only make sense with integral types.
|
||||
* This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but syntactic
|
||||
* sugar for floats with truncation after each operation).
|
||||
*/
|
||||
static bool op_allowed_in_strict_es2_mode(Token::Kind op) {
|
||||
return !op_only_valid_for_integral_types(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,
|
||||
bool allowNarrowing,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
const Type& left,
|
||||
const Type& right,
|
||||
const Type** outLeftType,
|
||||
const Type** outRightType,
|
||||
const Type** outResultType) {
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQ: // left = right
|
||||
*outLeftType = &left;
|
||||
*outRightType = &left;
|
||||
@ -1876,7 +1799,7 @@ static bool determine_binary_type(const Context& context,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isAssignment = Operators::IsAssignment(op);
|
||||
bool isAssignment = op.isAssignment();
|
||||
if (is_matrix_multiply(left, op, right)) { // left * right
|
||||
// Determine final component type.
|
||||
if (!determine_binary_type(context, allowNarrowing, op,
|
||||
@ -1907,13 +1830,13 @@ static bool determine_binary_type(const Context& context,
|
||||
}
|
||||
|
||||
bool leftIsVectorOrMatrix = left.isVector() || left.isMatrix();
|
||||
bool validMatrixOrVectorOp = op_valid_for_matrix_or_vector(op);
|
||||
bool validMatrixOrVectorOp = op.isValidForMatrixOrVector();
|
||||
|
||||
if (leftIsVectorOrMatrix && validMatrixOrVectorOp && right.isScalar()) {
|
||||
if (determine_binary_type(context, allowNarrowing, op, left.componentType(), right,
|
||||
outLeftType, outRightType, outResultType)) {
|
||||
*outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
|
||||
if (!op_is_logical(op)) {
|
||||
if (!op.isLogical()) {
|
||||
*outResultType = &(*outResultType)->toCompound(context, left.columns(),
|
||||
left.rows());
|
||||
}
|
||||
@ -1928,7 +1851,7 @@ static bool determine_binary_type(const Context& context,
|
||||
if (determine_binary_type(context, allowNarrowing, op, left, right.componentType(),
|
||||
outLeftType, outRightType, outResultType)) {
|
||||
*outRightType = &(*outRightType)->toCompound(context, right.columns(), right.rows());
|
||||
if (!op_is_logical(op)) {
|
||||
if (!op.isLogical()) {
|
||||
*outResultType = &(*outResultType)->toCompound(context, right.columns(),
|
||||
right.rows());
|
||||
}
|
||||
@ -1942,7 +1865,7 @@ static bool determine_binary_type(const Context& context,
|
||||
: left.coercionCost(right);
|
||||
|
||||
if ((left.isScalar() && right.isScalar()) || (leftIsVectorOrMatrix && validMatrixOrVectorOp)) {
|
||||
if (op_only_valid_for_integral_types(op)) {
|
||||
if (op.isOnlyValidForIntegralTypes()) {
|
||||
if (!leftComponentType.isInteger() || !rightComponentType.isInteger()) {
|
||||
return false;
|
||||
}
|
||||
@ -1960,7 +1883,7 @@ static bool determine_binary_type(const Context& context,
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (op_is_logical(op)) {
|
||||
if (op.isLogical()) {
|
||||
*outResultType = context.fTypes.fBool.get();
|
||||
}
|
||||
return true;
|
||||
@ -1975,17 +1898,17 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
|
||||
if (!left) {
|
||||
return nullptr;
|
||||
}
|
||||
Token::Kind op = expression.getToken().fKind;
|
||||
std::unique_ptr<Expression> right = this->convertExpression(*(iter++));
|
||||
if (!right) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->convertBinaryExpression(std::move(left), op, std::move(right));
|
||||
return this->convertBinaryExpression(std::move(left), expression.getOperator(),
|
||||
std::move(right));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
std::unique_ptr<Expression> left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
std::unique_ptr<Expression> right) {
|
||||
if (!left || !right) {
|
||||
return nullptr;
|
||||
@ -2006,13 +1929,13 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
} else {
|
||||
rawRightType = &right->type();
|
||||
}
|
||||
if (this->strictES2Mode() && !op_allowed_in_strict_es2_mode(op)) {
|
||||
this->errorReporter().error(
|
||||
offset, String("operator '") + Operators::OperatorName(op) + "' is not allowed");
|
||||
if (this->strictES2Mode() && !op.isAllowedInStrictES2Mode()) {
|
||||
this->errorReporter().error(offset,
|
||||
String("operator '") + op.operatorName() + "' is not allowed");
|
||||
return nullptr;
|
||||
}
|
||||
bool isAssignment = Operators::IsAssignment(op);
|
||||
if (isAssignment && !this->setRefKind(*left, op != Token::Kind::TK_EQ
|
||||
bool isAssignment = op.isAssignment();
|
||||
if (isAssignment && !this->setRefKind(*left, op.kind() != Token::Kind::TK_EQ
|
||||
? VariableReference::RefKind::kReadWrite
|
||||
: VariableReference::RefKind::kWrite)) {
|
||||
return nullptr;
|
||||
@ -2020,7 +1943,7 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
if (!determine_binary_type(fContext, fSettings->fAllowNarrowingConversions, op,
|
||||
*rawLeftType, *rawRightType, &leftType, &rightType, &resultType)) {
|
||||
this->errorReporter().error(
|
||||
offset, String("type mismatch: '") + Operators::OperatorName(op) +
|
||||
offset, String("type mismatch: '") + op.operatorName() +
|
||||
"' cannot operate on '" + left->type().displayName() + "', '" +
|
||||
right->type().displayName() + "'");
|
||||
return nullptr;
|
||||
@ -2441,13 +2364,13 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
|
||||
if (!base) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->convertPrefixExpression(expression.getToken().fKind, std::move(base));
|
||||
return this->convertPrefixExpression(expression.getOperator(), std::move(base));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
|
||||
std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Operator op,
|
||||
std::unique_ptr<Expression> base) {
|
||||
const Type& baseType = base->type();
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_PLUS:
|
||||
if (!baseType.componentType().isNumber()) {
|
||||
this->errorReporter().error(
|
||||
@ -2477,7 +2400,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
|
||||
case Token::Kind::TK_PLUSPLUS:
|
||||
if (!baseType.isNumber()) {
|
||||
this->errorReporter().error(base->fOffset,
|
||||
String("'") + Operators::OperatorName(op) +
|
||||
String("'") + op.operatorName() +
|
||||
"' cannot operate on '" + baseType.displayName() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -2488,7 +2411,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
|
||||
case Token::Kind::TK_MINUSMINUS:
|
||||
if (!baseType.isNumber()) {
|
||||
this->errorReporter().error(base->fOffset,
|
||||
String("'") + Operators::OperatorName(op) +
|
||||
String("'") + op.operatorName() +
|
||||
"' cannot operate on '" + baseType.displayName() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -2499,7 +2422,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
|
||||
case Token::Kind::TK_LOGICALNOT:
|
||||
if (!baseType.isBoolean()) {
|
||||
this->errorReporter().error(base->fOffset,
|
||||
String("'") + Operators::OperatorName(op) +
|
||||
String("'") + op.operatorName() +
|
||||
"' cannot operate on '" + baseType.displayName() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -2512,14 +2435,14 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
|
||||
case Token::Kind::TK_BITWISENOT:
|
||||
if (this->strictES2Mode()) {
|
||||
// GLSL ES 1.00, Section 5.1
|
||||
this->errorReporter().error(base->fOffset,
|
||||
String("operator '") + Operators::OperatorName(op) +
|
||||
"' is not allowed");
|
||||
this->errorReporter().error(
|
||||
base->fOffset,
|
||||
String("operator '") + op.operatorName() + "' is not allowed");
|
||||
return nullptr;
|
||||
}
|
||||
if (!baseType.isInteger()) {
|
||||
this->errorReporter().error(base->fOffset,
|
||||
String("'") + Operators::OperatorName(op) +
|
||||
String("'") + op.operatorName() +
|
||||
"' cannot operate on '" + baseType.displayName() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -2918,15 +2841,15 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode&
|
||||
if (!base) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->convertPostfixExpression(std::move(base), expression.getToken().fKind);
|
||||
return this->convertPostfixExpression(std::move(base), expression.getOperator());
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(std::unique_ptr<Expression> base,
|
||||
Token::Kind op) {
|
||||
Operator op) {
|
||||
const Type& baseType = base->type();
|
||||
if (!baseType.isNumber()) {
|
||||
this->errorReporter().error(base->fOffset,
|
||||
"'" + String(Operators::OperatorName(op)) +
|
||||
"'" + String(op.operatorName()) +
|
||||
"' cannot operate on '" + baseType.displayName() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "src/sksl/SkSLASTFile.h"
|
||||
#include "src/sksl/SkSLASTNode.h"
|
||||
#include "src/sksl/SkSLErrorReporter.h"
|
||||
#include "src/sksl/SkSLOperators.h"
|
||||
#include "src/sksl/ir/SkSLBlock.h"
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
#include "src/sksl/ir/SkSLExtension.h"
|
||||
@ -185,9 +186,9 @@ private:
|
||||
int convertArraySize(const Type& type, int offset, const ASTNode& s);
|
||||
int convertArraySize(const Type& type, std::unique_ptr<Expression> s);
|
||||
bool containsConstantZero(Expression& expr);
|
||||
bool dividesByZero(Token::Kind op, Expression& right);
|
||||
bool dividesByZero(Operator op, Expression& right);
|
||||
std::unique_ptr<Expression> convertBinaryExpression(std::unique_ptr<Expression> left,
|
||||
Token::Kind op,
|
||||
Operator op,
|
||||
std::unique_ptr<Expression> right);
|
||||
std::unique_ptr<Block> convertBlock(const ASTNode& block);
|
||||
std::unique_ptr<Statement> convertBreak(const ASTNode& b);
|
||||
@ -245,9 +246,9 @@ private:
|
||||
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
|
||||
std::unique_ptr<Expression> index);
|
||||
std::unique_ptr<Expression> convertPostfixExpression(std::unique_ptr<Expression> base,
|
||||
Token::Kind op);
|
||||
Operator op);
|
||||
std::unique_ptr<Expression> convertPostfixExpression(const ASTNode& expression);
|
||||
std::unique_ptr<Expression> convertPrefixExpression(Token::Kind op,
|
||||
std::unique_ptr<Expression> convertPrefixExpression(Operator op,
|
||||
std::unique_ptr<Expression> base);
|
||||
std::unique_ptr<Expression> convertScopeExpression(const ASTNode& expression);
|
||||
std::unique_ptr<StructDefinition> convertStructDefinition(const ASTNode& expression);
|
||||
|
@ -1004,9 +1004,9 @@ public:
|
||||
// It is illegal for side-effects from x() or y() to occur. The simplest way to
|
||||
// enforce that rule is to avoid inlining the right side entirely. However, it is
|
||||
// safe for other types of binary expression to inline both sides.
|
||||
Token::Kind op = binaryExpr.getOperator();
|
||||
bool shortCircuitable = (op == Token::Kind::TK_LOGICALAND ||
|
||||
op == Token::Kind::TK_LOGICALOR);
|
||||
Operator op = binaryExpr.getOperator();
|
||||
bool shortCircuitable = (op.kind() == Token::Kind::TK_LOGICALAND ||
|
||||
op.kind() == Token::Kind::TK_LOGICALOR);
|
||||
if (!shortCircuitable) {
|
||||
this->visitExpression(&binaryExpr.right());
|
||||
}
|
||||
|
@ -22,10 +22,10 @@
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
const char* MetalCodeGenerator::OperatorName(Token::Kind op) {
|
||||
switch (op) {
|
||||
const char* MetalCodeGenerator::OperatorName(Operator op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_LOGICALXOR: return "!=";
|
||||
default: return Operators::OperatorName(op);
|
||||
default: return op.operatorName();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1257,10 +1257,10 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
const Expression& right = *b.right();
|
||||
const Type& leftType = left.type();
|
||||
const Type& rightType = right.type();
|
||||
Token::Kind op = b.getOperator();
|
||||
Precedence precedence = Operators::GetBinaryPrecedence(b.getOperator());
|
||||
Operator op = b.getOperator();
|
||||
Precedence precedence = op.getBinaryPrecedence();
|
||||
bool needParens = precedence >= parentPrecedence;
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQEQ:
|
||||
if (leftType.isVector()) {
|
||||
this->write("all");
|
||||
@ -1280,16 +1280,16 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
this->write("(");
|
||||
}
|
||||
if (leftType.isMatrix() && rightType.isMatrix()) {
|
||||
if (op == Token::Kind::TK_STAREQ) {
|
||||
if (op.kind() == Token::Kind::TK_STAREQ) {
|
||||
this->writeMatrixTimesEqualHelper(leftType, rightType, b.type());
|
||||
} else if (op == Token::Kind::TK_EQEQ) {
|
||||
} else if (op.kind() == Token::Kind::TK_EQEQ) {
|
||||
this->writeMatrixEqualityHelper(leftType, rightType);
|
||||
} else if (op == Token::Kind::TK_NEQ) {
|
||||
} else if (op.kind() == Token::Kind::TK_NEQ) {
|
||||
this->writeMatrixInequalityHelper(leftType, rightType);
|
||||
}
|
||||
}
|
||||
this->writeExpression(left, precedence);
|
||||
if (op != Token::Kind::TK_EQ && Operators::IsAssignment(op) &&
|
||||
if (op.kind() != Token::Kind::TK_EQ && op.isAssignment() &&
|
||||
left.kind() == Expression::Kind::kSwizzle && !left.hasSideEffects()) {
|
||||
// This doesn't compile in Metal:
|
||||
// float4 x = float4(1);
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
bool generateCode() override;
|
||||
|
||||
protected:
|
||||
using Precedence = Operators::Precedence;
|
||||
using Precedence = Operator::Precedence;
|
||||
|
||||
typedef int Requirements;
|
||||
static constexpr Requirements kNo_Requirements = 0;
|
||||
@ -109,7 +109,7 @@ protected:
|
||||
kTexture_IntrinsicKind,
|
||||
};
|
||||
|
||||
static const char* OperatorName(Token::Kind op);
|
||||
static const char* OperatorName(Operator op);
|
||||
|
||||
class GlobalStructVisitor;
|
||||
void visitGlobalStruct(GlobalStructVisitor* visitor);
|
||||
|
@ -9,123 +9,222 @@
|
||||
#include "src/sksl/SkSLOperators.h"
|
||||
|
||||
namespace SkSL {
|
||||
namespace Operators {
|
||||
|
||||
Precedence GetBinaryPrecedence(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_STAR: // fall through
|
||||
case Token::Kind::TK_SLASH: // fall through
|
||||
case Token::Kind::TK_PERCENT: return Precedence::kMultiplicative;
|
||||
case Token::Kind::TK_PLUS: // fall through
|
||||
case Token::Kind::TK_MINUS: return Precedence::kAdditive;
|
||||
case Token::Kind::TK_SHL: // fall through
|
||||
case Token::Kind::TK_SHR: return Precedence::kShift;
|
||||
case Token::Kind::TK_LT: // fall through
|
||||
case Token::Kind::TK_GT: // fall through
|
||||
case Token::Kind::TK_LTEQ: // fall through
|
||||
case Token::Kind::TK_GTEQ: return Precedence::kRelational;
|
||||
case Token::Kind::TK_EQEQ: // fall through
|
||||
case Token::Kind::TK_NEQ: return Precedence::kEquality;
|
||||
case Token::Kind::TK_BITWISEAND: return Precedence::kBitwiseAnd;
|
||||
case Token::Kind::TK_BITWISEXOR: return Precedence::kBitwiseXor;
|
||||
case Token::Kind::TK_BITWISEOR: return Precedence::kBitwiseOr;
|
||||
case Token::Kind::TK_LOGICALAND: return Precedence::kLogicalAnd;
|
||||
case Token::Kind::TK_LOGICALXOR: return Precedence::kLogicalXor;
|
||||
case Token::Kind::TK_LOGICALOR: return Precedence::kLogicalOr;
|
||||
case Token::Kind::TK_EQ: // fall through
|
||||
case Token::Kind::TK_PLUSEQ: // fall through
|
||||
case Token::Kind::TK_MINUSEQ: // fall through
|
||||
case Token::Kind::TK_STAREQ: // fall through
|
||||
case Token::Kind::TK_SLASHEQ: // fall through
|
||||
case Token::Kind::TK_PERCENTEQ: // fall through
|
||||
case Token::Kind::TK_SHLEQ: // fall through
|
||||
case Token::Kind::TK_SHREQ: // fall through
|
||||
case Token::Kind::TK_BITWISEANDEQ: // fall through
|
||||
case Token::Kind::TK_BITWISEXOREQ: // fall through
|
||||
case Token::Kind::TK_BITWISEOREQ: return Precedence::kAssignment;
|
||||
case Token::Kind::TK_COMMA: return Precedence::kSequence;
|
||||
Operator::Precedence Operator::getBinaryPrecedence() const {
|
||||
switch (fKind) {
|
||||
case Kind::TK_STAR: // fall through
|
||||
case Kind::TK_SLASH: // fall through
|
||||
case Kind::TK_PERCENT: return Precedence::kMultiplicative;
|
||||
case Kind::TK_PLUS: // fall through
|
||||
case Kind::TK_MINUS: return Precedence::kAdditive;
|
||||
case Kind::TK_SHL: // fall through
|
||||
case Kind::TK_SHR: return Precedence::kShift;
|
||||
case Kind::TK_LT: // fall through
|
||||
case Kind::TK_GT: // fall through
|
||||
case Kind::TK_LTEQ: // fall through
|
||||
case Kind::TK_GTEQ: return Precedence::kRelational;
|
||||
case Kind::TK_EQEQ: // fall through
|
||||
case Kind::TK_NEQ: return Precedence::kEquality;
|
||||
case Kind::TK_BITWISEAND: return Precedence::kBitwiseAnd;
|
||||
case Kind::TK_BITWISEXOR: return Precedence::kBitwiseXor;
|
||||
case Kind::TK_BITWISEOR: return Precedence::kBitwiseOr;
|
||||
case Kind::TK_LOGICALAND: return Precedence::kLogicalAnd;
|
||||
case Kind::TK_LOGICALXOR: return Precedence::kLogicalXor;
|
||||
case Kind::TK_LOGICALOR: return Precedence::kLogicalOr;
|
||||
case Kind::TK_EQ: // fall through
|
||||
case Kind::TK_PLUSEQ: // fall through
|
||||
case Kind::TK_MINUSEQ: // fall through
|
||||
case Kind::TK_STAREQ: // fall through
|
||||
case Kind::TK_SLASHEQ: // fall through
|
||||
case Kind::TK_PERCENTEQ: // fall through
|
||||
case Kind::TK_SHLEQ: // fall through
|
||||
case Kind::TK_SHREQ: // fall through
|
||||
case Kind::TK_BITWISEANDEQ: // fall through
|
||||
case Kind::TK_BITWISEXOREQ: // fall through
|
||||
case Kind::TK_BITWISEOREQ: return Precedence::kAssignment;
|
||||
case Kind::TK_COMMA: return Precedence::kSequence;
|
||||
default: SK_ABORT("unsupported binary operator");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* OperatorName(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_PLUS: return "+";
|
||||
case Token::Kind::TK_MINUS: return "-";
|
||||
case Token::Kind::TK_STAR: return "*";
|
||||
case Token::Kind::TK_SLASH: return "/";
|
||||
case Token::Kind::TK_PERCENT: return "%";
|
||||
case Token::Kind::TK_SHL: return "<<";
|
||||
case Token::Kind::TK_SHR: return ">>";
|
||||
case Token::Kind::TK_LOGICALNOT: return "!";
|
||||
case Token::Kind::TK_LOGICALAND: return "&&";
|
||||
case Token::Kind::TK_LOGICALOR: return "||";
|
||||
case Token::Kind::TK_LOGICALXOR: return "^^";
|
||||
case Token::Kind::TK_BITWISENOT: return "~";
|
||||
case Token::Kind::TK_BITWISEAND: return "&";
|
||||
case Token::Kind::TK_BITWISEOR: return "|";
|
||||
case Token::Kind::TK_BITWISEXOR: return "^";
|
||||
case Token::Kind::TK_EQ: return "=";
|
||||
case Token::Kind::TK_EQEQ: return "==";
|
||||
case Token::Kind::TK_NEQ: return "!=";
|
||||
case Token::Kind::TK_LT: return "<";
|
||||
case Token::Kind::TK_GT: return ">";
|
||||
case Token::Kind::TK_LTEQ: return "<=";
|
||||
case Token::Kind::TK_GTEQ: return ">=";
|
||||
case Token::Kind::TK_PLUSEQ: return "+=";
|
||||
case Token::Kind::TK_MINUSEQ: return "-=";
|
||||
case Token::Kind::TK_STAREQ: return "*=";
|
||||
case Token::Kind::TK_SLASHEQ: return "/=";
|
||||
case Token::Kind::TK_PERCENTEQ: return "%=";
|
||||
case Token::Kind::TK_SHLEQ: return "<<=";
|
||||
case Token::Kind::TK_SHREQ: return ">>=";
|
||||
case Token::Kind::TK_BITWISEANDEQ: return "&=";
|
||||
case Token::Kind::TK_BITWISEOREQ: return "|=";
|
||||
case Token::Kind::TK_BITWISEXOREQ: return "^=";
|
||||
case Token::Kind::TK_PLUSPLUS: return "++";
|
||||
case Token::Kind::TK_MINUSMINUS: return "--";
|
||||
case Token::Kind::TK_COMMA: return ",";
|
||||
default:
|
||||
SK_ABORT("unsupported operator: %d\n", (int) op);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IsAssignment(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_EQ: // fall through
|
||||
case Token::Kind::TK_PLUSEQ: // fall through
|
||||
case Token::Kind::TK_MINUSEQ: // fall through
|
||||
case Token::Kind::TK_STAREQ: // fall through
|
||||
case Token::Kind::TK_SLASHEQ: // fall through
|
||||
case Token::Kind::TK_PERCENTEQ: // fall through
|
||||
case Token::Kind::TK_SHLEQ: // fall through
|
||||
case Token::Kind::TK_SHREQ: // fall through
|
||||
case Token::Kind::TK_BITWISEOREQ: // fall through
|
||||
case Token::Kind::TK_BITWISEXOREQ: // fall through
|
||||
case Token::Kind::TK_BITWISEANDEQ:
|
||||
bool Operator::isOperator() const {
|
||||
switch (this->kind()) {
|
||||
case Kind::TK_PLUS:
|
||||
case Kind::TK_MINUS:
|
||||
case Kind::TK_STAR:
|
||||
case Kind::TK_SLASH:
|
||||
case Kind::TK_PERCENT:
|
||||
case Kind::TK_SHL:
|
||||
case Kind::TK_SHR:
|
||||
case Kind::TK_LOGICALNOT:
|
||||
case Kind::TK_LOGICALAND:
|
||||
case Kind::TK_LOGICALOR:
|
||||
case Kind::TK_LOGICALXOR:
|
||||
case Kind::TK_BITWISENOT:
|
||||
case Kind::TK_BITWISEAND:
|
||||
case Kind::TK_BITWISEOR:
|
||||
case Kind::TK_BITWISEXOR:
|
||||
case Kind::TK_EQ:
|
||||
case Kind::TK_EQEQ:
|
||||
case Kind::TK_NEQ:
|
||||
case Kind::TK_LT:
|
||||
case Kind::TK_GT:
|
||||
case Kind::TK_LTEQ:
|
||||
case Kind::TK_GTEQ:
|
||||
case Kind::TK_PLUSEQ:
|
||||
case Kind::TK_MINUSEQ:
|
||||
case Kind::TK_STAREQ:
|
||||
case Kind::TK_SLASHEQ:
|
||||
case Kind::TK_PERCENTEQ:
|
||||
case Kind::TK_SHLEQ:
|
||||
case Kind::TK_SHREQ:
|
||||
case Kind::TK_BITWISEANDEQ:
|
||||
case Kind::TK_BITWISEOREQ:
|
||||
case Kind::TK_BITWISEXOREQ:
|
||||
case Kind::TK_PLUSPLUS:
|
||||
case Kind::TK_MINUSMINUS:
|
||||
case Kind::TK_COMMA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Token::Kind RemoveAssignment(Token::Kind op) {
|
||||
switch (op) {
|
||||
case Token::Kind::TK_PLUSEQ: return Token::Kind::TK_PLUS;
|
||||
case Token::Kind::TK_MINUSEQ: return Token::Kind::TK_MINUS;
|
||||
case Token::Kind::TK_STAREQ: return Token::Kind::TK_STAR;
|
||||
case Token::Kind::TK_SLASHEQ: return Token::Kind::TK_SLASH;
|
||||
case Token::Kind::TK_PERCENTEQ: return Token::Kind::TK_PERCENT;
|
||||
case Token::Kind::TK_SHLEQ: return Token::Kind::TK_SHL;
|
||||
case Token::Kind::TK_SHREQ: return Token::Kind::TK_SHR;
|
||||
case Token::Kind::TK_BITWISEOREQ: return Token::Kind::TK_BITWISEOR;
|
||||
case Token::Kind::TK_BITWISEXOREQ: return Token::Kind::TK_BITWISEXOR;
|
||||
case Token::Kind::TK_BITWISEANDEQ: return Token::Kind::TK_BITWISEAND;
|
||||
default: return op;
|
||||
const char* Operator::operatorName() const {
|
||||
switch (fKind) {
|
||||
case Kind::TK_PLUS: return "+";
|
||||
case Kind::TK_MINUS: return "-";
|
||||
case Kind::TK_STAR: return "*";
|
||||
case Kind::TK_SLASH: return "/";
|
||||
case Kind::TK_PERCENT: return "%";
|
||||
case Kind::TK_SHL: return "<<";
|
||||
case Kind::TK_SHR: return ">>";
|
||||
case Kind::TK_LOGICALNOT: return "!";
|
||||
case Kind::TK_LOGICALAND: return "&&";
|
||||
case Kind::TK_LOGICALOR: return "||";
|
||||
case Kind::TK_LOGICALXOR: return "^^";
|
||||
case Kind::TK_BITWISENOT: return "~";
|
||||
case Kind::TK_BITWISEAND: return "&";
|
||||
case Kind::TK_BITWISEOR: return "|";
|
||||
case Kind::TK_BITWISEXOR: return "^";
|
||||
case Kind::TK_EQ: return "=";
|
||||
case Kind::TK_EQEQ: return "==";
|
||||
case Kind::TK_NEQ: return "!=";
|
||||
case Kind::TK_LT: return "<";
|
||||
case Kind::TK_GT: return ">";
|
||||
case Kind::TK_LTEQ: return "<=";
|
||||
case Kind::TK_GTEQ: return ">=";
|
||||
case Kind::TK_PLUSEQ: return "+=";
|
||||
case Kind::TK_MINUSEQ: return "-=";
|
||||
case Kind::TK_STAREQ: return "*=";
|
||||
case Kind::TK_SLASHEQ: return "/=";
|
||||
case Kind::TK_PERCENTEQ: return "%=";
|
||||
case Kind::TK_SHLEQ: return "<<=";
|
||||
case Kind::TK_SHREQ: return ">>=";
|
||||
case Kind::TK_BITWISEANDEQ: return "&=";
|
||||
case Kind::TK_BITWISEOREQ: return "|=";
|
||||
case Kind::TK_BITWISEXOREQ: return "^=";
|
||||
case Kind::TK_PLUSPLUS: return "++";
|
||||
case Kind::TK_MINUSMINUS: return "--";
|
||||
case Kind::TK_COMMA: return ",";
|
||||
default:
|
||||
SK_ABORT("unsupported operator: %d\n", (int) fKind);
|
||||
}
|
||||
}
|
||||
|
||||
bool Operator::isAssignment() const {
|
||||
switch (fKind) {
|
||||
case Kind::TK_EQ: // fall through
|
||||
case Kind::TK_PLUSEQ: // fall through
|
||||
case Kind::TK_MINUSEQ: // fall through
|
||||
case Kind::TK_STAREQ: // fall through
|
||||
case Kind::TK_SLASHEQ: // fall through
|
||||
case Kind::TK_PERCENTEQ: // fall through
|
||||
case Kind::TK_SHLEQ: // fall through
|
||||
case Kind::TK_SHREQ: // fall through
|
||||
case Kind::TK_BITWISEOREQ: // fall through
|
||||
case Kind::TK_BITWISEXOREQ: // fall through
|
||||
case Kind::TK_BITWISEANDEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Operator Operator::removeAssignment() const {
|
||||
switch (fKind) {
|
||||
case Kind::TK_PLUSEQ: return Operator{Kind::TK_PLUS};
|
||||
case Kind::TK_MINUSEQ: return Operator{Kind::TK_MINUS};
|
||||
case Kind::TK_STAREQ: return Operator{Kind::TK_STAR};
|
||||
case Kind::TK_SLASHEQ: return Operator{Kind::TK_SLASH};
|
||||
case Kind::TK_PERCENTEQ: return Operator{Kind::TK_PERCENT};
|
||||
case Kind::TK_SHLEQ: return Operator{Kind::TK_SHL};
|
||||
case Kind::TK_SHREQ: return Operator{Kind::TK_SHR};
|
||||
case Kind::TK_BITWISEOREQ: return Operator{Kind::TK_BITWISEOR};
|
||||
case Kind::TK_BITWISEXOREQ: return Operator{Kind::TK_BITWISEXOR};
|
||||
case Kind::TK_BITWISEANDEQ: return Operator{Kind::TK_BITWISEAND};
|
||||
default: return *this;
|
||||
}
|
||||
}
|
||||
|
||||
bool Operator::isLogical() const {
|
||||
switch (kind()) {
|
||||
case Token::Kind::TK_LT:
|
||||
case Token::Kind::TK_GT:
|
||||
case Token::Kind::TK_LTEQ:
|
||||
case Token::Kind::TK_GTEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Operator::isOnlyValidForIntegralTypes() const {
|
||||
switch (kind()) {
|
||||
case Token::Kind::TK_SHL:
|
||||
case Token::Kind::TK_SHR:
|
||||
case Token::Kind::TK_BITWISEAND:
|
||||
case Token::Kind::TK_BITWISEOR:
|
||||
case Token::Kind::TK_BITWISEXOR:
|
||||
case Token::Kind::TK_PERCENT:
|
||||
case Token::Kind::TK_SHLEQ:
|
||||
case Token::Kind::TK_SHREQ:
|
||||
case Token::Kind::TK_BITWISEANDEQ:
|
||||
case Token::Kind::TK_BITWISEOREQ:
|
||||
case Token::Kind::TK_BITWISEXOREQ:
|
||||
case Token::Kind::TK_PERCENTEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Operator::isValidForMatrixOrVector() const {
|
||||
switch (kind()) {
|
||||
case Token::Kind::TK_PLUS:
|
||||
case Token::Kind::TK_MINUS:
|
||||
case Token::Kind::TK_STAR:
|
||||
case Token::Kind::TK_SLASH:
|
||||
case Token::Kind::TK_PERCENT:
|
||||
case Token::Kind::TK_SHL:
|
||||
case Token::Kind::TK_SHR:
|
||||
case Token::Kind::TK_BITWISEAND:
|
||||
case Token::Kind::TK_BITWISEOR:
|
||||
case Token::Kind::TK_BITWISEXOR:
|
||||
case Token::Kind::TK_PLUSEQ:
|
||||
case Token::Kind::TK_MINUSEQ:
|
||||
case Token::Kind::TK_STAREQ:
|
||||
case Token::Kind::TK_SLASHEQ:
|
||||
case Token::Kind::TK_PERCENTEQ:
|
||||
case Token::Kind::TK_SHLEQ:
|
||||
case Token::Kind::TK_SHREQ:
|
||||
case Token::Kind::TK_BITWISEANDEQ:
|
||||
case Token::Kind::TK_BITWISEOREQ:
|
||||
case Token::Kind::TK_BITWISEXOREQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Operators
|
||||
} // namespace SkSL
|
||||
|
@ -8,10 +8,19 @@
|
||||
#ifndef SKSL_OPERATORS
|
||||
#define SKSL_OPERATORS
|
||||
|
||||
#include "src/sksl/SkSLDefines.h"
|
||||
#include "src/sksl/SkSLLexer.h"
|
||||
|
||||
namespace SkSL {
|
||||
namespace Operators {
|
||||
|
||||
class Operator {
|
||||
public:
|
||||
using Kind = Token::Kind;
|
||||
|
||||
// Allow implicit conversion from Token::Kind, since this is just a utility wrapper on top.
|
||||
Operator(Token::Kind t) : fKind(t) {
|
||||
SkASSERTF(this->isOperator(), "token-kind %d is not an operator", fKind);
|
||||
}
|
||||
|
||||
enum class Precedence {
|
||||
kParentheses = 1,
|
||||
@ -34,18 +43,53 @@ namespace Operators {
|
||||
kTopLevel = kSequence
|
||||
};
|
||||
|
||||
Precedence GetBinaryPrecedence(Token::Kind op);
|
||||
Token::Kind kind() const { return fKind; }
|
||||
|
||||
const char* OperatorName(Token::Kind op);
|
||||
Precedence getBinaryPrecedence() const;
|
||||
|
||||
const char* operatorName() const;
|
||||
|
||||
// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
|
||||
bool IsAssignment(Token::Kind op);
|
||||
bool isAssignment() const;
|
||||
|
||||
// Given a compound assignment operator, returns the non-assignment version of the operator
|
||||
// (e.g. '+=' becomes '+')
|
||||
Token::Kind RemoveAssignment(Token::Kind op);
|
||||
Operator removeAssignment() const;
|
||||
|
||||
/**
|
||||
* Defines the set of logical (comparison) operators:
|
||||
* < <= > >=
|
||||
*/
|
||||
bool isLogical() const;
|
||||
|
||||
/**
|
||||
* Defines the set of operators which are only valid on integral types:
|
||||
* << <<= >> >>= & &= | |= ^ ^= % %=
|
||||
*/
|
||||
bool isOnlyValidForIntegralTypes() const;
|
||||
|
||||
/**
|
||||
* Defines the set of operators which perform vector/matrix math.
|
||||
* + += - -= * *= / /= % %= << <<= >> >>= & &= | |= ^ ^=
|
||||
*/
|
||||
bool isValidForMatrixOrVector() const;
|
||||
|
||||
/*
|
||||
* Defines the set of operators allowed by The OpenGL ES Shading Language 1.00, Section 5.1.
|
||||
* The set of illegal (reserved) operators are the ones that only make sense with integral
|
||||
* types. This is not a coincidence: It's because ES2 doesn't require 'int' to be anything but
|
||||
* syntactic sugar for floats with truncation after each operation.
|
||||
*/
|
||||
bool isAllowedInStrictES2Mode() const {
|
||||
return !this->isOnlyValidForIntegralTypes();
|
||||
}
|
||||
|
||||
private:
|
||||
bool isOperator() const;
|
||||
|
||||
Kind fKind;
|
||||
};
|
||||
|
||||
} // namespace Operators
|
||||
} // namespace SkSL
|
||||
|
||||
#endif
|
||||
|
@ -1610,7 +1610,8 @@ ASTNode::ID Parser::expression() {
|
||||
if (!right) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::ID newResult = this->createNode(t.fOffset, ASTNode::Kind::kBinary,
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1650,7 +1651,7 @@ ASTNode::ID Parser::assignmentExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1710,7 +1711,7 @@ ASTNode::ID Parser::logicalOrExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
std::move(t));
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1735,7 +1736,7 @@ ASTNode::ID Parser::logicalXorExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
std::move(t));
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1760,7 +1761,7 @@ ASTNode::ID Parser::logicalAndExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
std::move(t));
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1784,8 +1785,8 @@ ASTNode::ID Parser::bitwiseOrExpression() {
|
||||
if (!right) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult =
|
||||
this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1809,7 +1810,8 @@ ASTNode::ID Parser::bitwiseXorExpression() {
|
||||
if (!right) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1834,7 +1836,7 @@ ASTNode::ID Parser::bitwiseAndExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset, ASTNode::Kind::kBinary,
|
||||
std::move(t));
|
||||
Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1862,7 +1864,7 @@ ASTNode::ID Parser::equalityExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1896,7 +1898,7 @@ ASTNode::ID Parser::relationalExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1928,7 +1930,7 @@ ASTNode::ID Parser::shiftExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1960,7 +1962,7 @@ ASTNode::ID Parser::additiveExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -1993,7 +1995,7 @@ ASTNode::ID Parser::multiplicativeExpression() {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID newResult = this->createNode(getNode(result).fOffset,
|
||||
ASTNode::Kind::kBinary, std::move(t));
|
||||
ASTNode::Kind::kBinary, Operator(t.fKind));
|
||||
getNode(newResult).addChild(result);
|
||||
getNode(newResult).addChild(right);
|
||||
result = newResult;
|
||||
@ -2023,7 +2025,8 @@ ASTNode::ID Parser::unaryExpression() {
|
||||
if (!expr) {
|
||||
return ASTNode::ID::Invalid();
|
||||
}
|
||||
ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
|
||||
ASTNode::ID result = this->createNode(t.fOffset, ASTNode::Kind::kPrefix,
|
||||
Operator(t.fKind));
|
||||
getNode(result).addChild(expr);
|
||||
return result;
|
||||
}
|
||||
@ -2160,7 +2163,8 @@ ASTNode::ID Parser::suffix(ASTNode::ID base) {
|
||||
}
|
||||
case Token::Kind::TK_PLUSPLUS: // fall through
|
||||
case Token::Kind::TK_MINUSMINUS: {
|
||||
ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix, next);
|
||||
ASTNode::ID result = this->createNode(next.fOffset, ASTNode::Kind::kPostfix,
|
||||
Operator(next.fKind));
|
||||
getNode(result).addChild(base);
|
||||
return result;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
void generateCode();
|
||||
|
||||
private:
|
||||
using Precedence = Operators::Precedence;
|
||||
using Precedence = Operator::Precedence;
|
||||
|
||||
void write(const char* s);
|
||||
void writeLine(const char* s = nullptr);
|
||||
@ -476,15 +476,15 @@ void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b
|
||||
Precedence parentPrecedence) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
Operator op = b.getOperator();
|
||||
|
||||
Precedence precedence = Operators::GetBinaryPrecedence(op);
|
||||
Precedence precedence = op.getBinaryPrecedence();
|
||||
if (precedence >= parentPrecedence) {
|
||||
this->write("(");
|
||||
}
|
||||
this->writeExpression(left, precedence);
|
||||
this->write(" ");
|
||||
this->write(Operators::OperatorName(op));
|
||||
this->write(op.operatorName());
|
||||
this->write(" ");
|
||||
this->writeExpression(right, precedence);
|
||||
if (precedence >= parentPrecedence) {
|
||||
@ -512,7 +512,7 @@ void PipelineStageCodeGenerator::writePrefixExpression(const PrefixExpression& p
|
||||
if (Precedence::kPrefix >= parentPrecedence) {
|
||||
this->write("(");
|
||||
}
|
||||
this->write(Operators::OperatorName(p.getOperator()));
|
||||
this->write(p.getOperator().operatorName());
|
||||
this->writeExpression(*p.operand(), Precedence::kPrefix);
|
||||
if (Precedence::kPrefix >= parentPrecedence) {
|
||||
this->write(")");
|
||||
@ -525,7 +525,7 @@ void PipelineStageCodeGenerator::writePostfixExpression(const PostfixExpression&
|
||||
this->write("(");
|
||||
}
|
||||
this->writeExpression(*p.operand(), Precedence::kPostfix);
|
||||
this->write(Operators::OperatorName(p.getOperator()));
|
||||
this->write(p.getOperator().operatorName());
|
||||
if (Precedence::kPostfix >= parentPrecedence) {
|
||||
this->write(")");
|
||||
}
|
||||
|
@ -2233,11 +2233,11 @@ static std::unique_ptr<Expression> create_literal_1(const Context& context, cons
|
||||
}
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Token::Kind op,
|
||||
SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
|
||||
const Type& rightType, SpvId rhs,
|
||||
const Type& resultType, OutputStream& out) {
|
||||
// The comma operator ignores the type of the left-hand side entirely.
|
||||
if (op == Token::Kind::TK_COMMA) {
|
||||
if (op.kind() == Token::Kind::TK_COMMA) {
|
||||
return rhs;
|
||||
}
|
||||
// overall type we are operating on: float2, int, uint4...
|
||||
@ -2246,14 +2246,14 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
// handling in SPIR-V
|
||||
if (this->getActualType(leftType) != this->getActualType(rightType)) {
|
||||
if (leftType.isVector() && rightType.isNumber()) {
|
||||
if (op == Token::Kind::TK_SLASH) {
|
||||
if (op.kind() == Token::Kind::TK_SLASH) {
|
||||
SpvId one = this->writeExpression(*create_literal_1(fContext, rightType), out);
|
||||
SpvId inverse = this->nextId();
|
||||
this->writeInstruction(SpvOpFDiv, this->getType(rightType), inverse, one, rhs, out);
|
||||
rhs = inverse;
|
||||
op = Token::Kind::TK_STAR;
|
||||
}
|
||||
if (op == Token::Kind::TK_STAR) {
|
||||
if (op.kind() == Token::Kind::TK_STAR) {
|
||||
SpvId result = this->nextId();
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, lhs, rhs, out);
|
||||
@ -2271,7 +2271,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
rhs = vec;
|
||||
operandType = &leftType;
|
||||
} else if (rightType.isVector() && leftType.isNumber()) {
|
||||
if (op == Token::Kind::TK_STAR) {
|
||||
if (op.kind() == Token::Kind::TK_STAR) {
|
||||
SpvId result = this->nextId();
|
||||
this->writeInstruction(SpvOpVectorTimesScalar, this->getType(resultType),
|
||||
result, rhs, lhs, out);
|
||||
@ -2320,7 +2320,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
operandType = &this->getActualType(leftType);
|
||||
SkASSERT(*operandType == this->getActualType(rightType));
|
||||
}
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQEQ: {
|
||||
if (operandType->isMatrix()) {
|
||||
return this->writeMatrixComparison(*operandType, lhs, rhs, SpvOpFOrdEqual,
|
||||
@ -2438,9 +2438,9 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
|
||||
SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, OutputStream& out) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
Operator op = b.getOperator();
|
||||
// handle cases where we don't necessarily evaluate both LHS and RHS
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQ: {
|
||||
SpvId rhs = this->writeExpression(right, out);
|
||||
this->getLValue(left, out)->store(rhs, out);
|
||||
@ -2456,7 +2456,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
|
||||
|
||||
std::unique_ptr<LValue> lvalue;
|
||||
SpvId lhs;
|
||||
if (Operators::IsAssignment(op)) {
|
||||
if (op.isAssignment()) {
|
||||
lvalue = this->getLValue(left, out);
|
||||
lhs = lvalue->load(out);
|
||||
} else {
|
||||
@ -2464,7 +2464,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
|
||||
lhs = this->writeExpression(left, out);
|
||||
}
|
||||
SpvId rhs = this->writeExpression(right, out);
|
||||
SpvId result = this->writeBinaryExpression(left.type(), lhs, Operators::RemoveAssignment(op),
|
||||
SpvId result = this->writeBinaryExpression(left.type(), lhs, op.removeAssignment(),
|
||||
right.type(), rhs, b.type(), out);
|
||||
if (lvalue) {
|
||||
lvalue->store(result, out);
|
||||
@ -2473,7 +2473,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) {
|
||||
SkASSERT(a.getOperator() == Token::Kind::TK_LOGICALAND);
|
||||
SkASSERT(a.getOperator().kind() == Token::Kind::TK_LOGICALAND);
|
||||
BoolLiteral falseLiteral(fContext, -1, false);
|
||||
SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
|
||||
SpvId lhs = this->writeExpression(*a.left(), out);
|
||||
@ -2494,7 +2494,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) {
|
||||
SkASSERT(o.getOperator() == Token::Kind::TK_LOGICALOR);
|
||||
SkASSERT(o.getOperator().kind() == Token::Kind::TK_LOGICALOR);
|
||||
BoolLiteral trueLiteral(fContext, -1, true);
|
||||
SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
|
||||
SpvId lhs = this->writeExpression(*o.left(), out);
|
||||
@ -2553,7 +2553,7 @@ SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, Out
|
||||
|
||||
SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, OutputStream& out) {
|
||||
const Type& type = p.type();
|
||||
if (p.getOperator() == Token::Kind::TK_MINUS) {
|
||||
if (p.getOperator().kind() == Token::Kind::TK_MINUS) {
|
||||
SpvId result = this->nextId();
|
||||
SpvId typeId = this->getType(type);
|
||||
SpvId expr = this->writeExpression(*p.operand(), out);
|
||||
@ -2567,7 +2567,7 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, Outpu
|
||||
this->writePrecisionModifier(type, result);
|
||||
return result;
|
||||
}
|
||||
switch (p.getOperator()) {
|
||||
switch (p.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUS:
|
||||
return this->writeExpression(*p.operand(), out);
|
||||
case Token::Kind::TK_PLUSPLUS: {
|
||||
@ -2611,7 +2611,7 @@ SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, Out
|
||||
std::unique_ptr<LValue> lv = this->getLValue(*p.operand(), out);
|
||||
SpvId result = lv->load(out);
|
||||
SpvId one = this->writeExpression(*create_literal_1(fContext, type), out);
|
||||
switch (p.getOperator()) {
|
||||
switch (p.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSPLUS: {
|
||||
SpvId temp = this->writeBinaryOperation(type, type, result, one, SpvOpFAdd,
|
||||
SpvOpIAdd, SpvOpIAdd, SpvOpUndef, out);
|
||||
|
@ -307,7 +307,7 @@ private:
|
||||
SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt,
|
||||
SpvOp_ ifUInt, OutputStream& out);
|
||||
|
||||
SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Token::Kind op,
|
||||
SpvId writeBinaryExpression(const Type& leftType, SpvId lhs, Operator op,
|
||||
const Type& rightType, SpvId rhs, const Type& resultType,
|
||||
OutputStream& out);
|
||||
|
||||
|
@ -529,8 +529,8 @@ size_t SkVMGenerator::getSlot(const Variable& v) {
|
||||
Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
|
||||
const Expression& left = *b.left();
|
||||
const Expression& right = *b.right();
|
||||
Token::Kind op = b.getOperator();
|
||||
if (op == Token::Kind::TK_EQ) {
|
||||
Operator op = b.getOperator();
|
||||
if (op.kind() == Token::Kind::TK_EQ) {
|
||||
return this->writeStore(left, this->writeExpression(right));
|
||||
}
|
||||
|
||||
@ -538,14 +538,14 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
|
||||
const Type& rType = right.type();
|
||||
bool lVecOrMtx = (lType.isVector() || lType.isMatrix());
|
||||
bool rVecOrMtx = (rType.isVector() || rType.isMatrix());
|
||||
bool isAssignment = Operators::IsAssignment(op);
|
||||
bool isAssignment = op.isAssignment();
|
||||
if (isAssignment) {
|
||||
op = Operators::RemoveAssignment(op);
|
||||
op = op.removeAssignment();
|
||||
}
|
||||
Type::NumberKind nk = base_number_kind(lType);
|
||||
|
||||
// A few ops require special treatment:
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_LOGICALAND: {
|
||||
SkASSERT(!isAssignment);
|
||||
SkASSERT(nk == Type::NumberKind::kBoolean);
|
||||
@ -576,7 +576,7 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
|
||||
rVal = this->writeExpression(right);
|
||||
|
||||
// Special case for M*V, V*M, M*M (but not V*V!)
|
||||
if (op == Token::Kind::TK_STAR
|
||||
if (op.kind() == Token::Kind::TK_STAR
|
||||
&& lVecOrMtx && rVecOrMtx && !(lType.isVector() && rType.isVector())) {
|
||||
int rCols = rType.columns(),
|
||||
rRows = rType.rows(),
|
||||
@ -624,7 +624,7 @@ Value SkVMGenerator::writeBinaryExpression(const BinaryExpression& b) {
|
||||
return skvm::F32{};
|
||||
};
|
||||
|
||||
switch (op) {
|
||||
switch (op.kind()) {
|
||||
case Token::Kind::TK_EQEQ: {
|
||||
SkASSERT(!isAssignment);
|
||||
Value cmp = binary([](skvm::F32 x, skvm::F32 y) { return x == y; },
|
||||
@ -1311,10 +1311,10 @@ Value SkVMGenerator::writeExternalFunctionCall(const ExternalFunctionCall& c) {
|
||||
Value SkVMGenerator::writePrefixExpression(const PrefixExpression& p) {
|
||||
Value val = this->writeExpression(*p.operand());
|
||||
|
||||
switch (p.getOperator()) {
|
||||
switch (p.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSPLUS:
|
||||
case Token::Kind::TK_MINUSMINUS: {
|
||||
bool incr = p.getOperator() == Token::Kind::TK_PLUSPLUS;
|
||||
bool incr = p.getOperator().kind() == Token::Kind::TK_PLUSPLUS;
|
||||
|
||||
switch (base_number_kind(p.type())) {
|
||||
case Type::NumberKind::kFloat:
|
||||
@ -1350,13 +1350,13 @@ Value SkVMGenerator::writePrefixExpression(const PrefixExpression& p) {
|
||||
}
|
||||
|
||||
Value SkVMGenerator::writePostfixExpression(const PostfixExpression& p) {
|
||||
switch (p.getOperator()) {
|
||||
switch (p.getOperator().kind()) {
|
||||
case Token::Kind::TK_PLUSPLUS:
|
||||
case Token::Kind::TK_MINUSMINUS: {
|
||||
Value old = this->writeExpression(*p.operand()),
|
||||
val = old;
|
||||
SkASSERT(val.slots() == 1);
|
||||
bool incr = p.getOperator() == Token::Kind::TK_PLUSPLUS;
|
||||
bool incr = p.getOperator().kind() == Token::Kind::TK_PLUSPLUS;
|
||||
|
||||
switch (base_number_kind(p.type())) {
|
||||
case Type::NumberKind::kFloat:
|
||||
|
@ -104,7 +104,7 @@ DSLExpression DSLWriter::Construct(const SkSL::Type& type, std::vector<DSLExpres
|
||||
std::move(args)));
|
||||
}
|
||||
|
||||
DSLExpression DSLWriter::ConvertBinary(std::unique_ptr<Expression> left, Token::Kind op,
|
||||
DSLExpression DSLWriter::ConvertBinary(std::unique_ptr<Expression> left, Operator op,
|
||||
std::unique_ptr<Expression> right) {
|
||||
return IRGenerator().convertBinaryExpression(std::move(left), op, std::move(right));
|
||||
}
|
||||
@ -118,11 +118,11 @@ DSLExpression DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,
|
||||
return IRGenerator().convertIndex(std::move(base), std::move(index));
|
||||
}
|
||||
|
||||
DSLExpression DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr, Token::Kind op) {
|
||||
DSLExpression DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr, Operator op) {
|
||||
return IRGenerator().convertPostfixExpression(std::move(expr), op);
|
||||
}
|
||||
|
||||
DSLExpression DSLWriter::ConvertPrefix(Token::Kind op, std::unique_ptr<Expression> expr) {
|
||||
DSLExpression DSLWriter::ConvertPrefix(Operator op, std::unique_ptr<Expression> expr) {
|
||||
return IRGenerator().convertPrefixExpression(op, std::move(expr));
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define SKSL_DSLWRITER
|
||||
|
||||
#include "src/sksl/SkSLMangler.h"
|
||||
#include "src/sksl/SkSLOperators.h"
|
||||
#include "src/sksl/dsl/DSLExpression.h"
|
||||
#include "src/sksl/dsl/DSLStatement.h"
|
||||
#include "src/sksl/ir/SkSLExpressionStatement.h"
|
||||
@ -133,7 +134,7 @@ public:
|
||||
|
||||
static DSLExpression Construct(const SkSL::Type& type, std::vector<DSLExpression> rawArgs);
|
||||
|
||||
static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Token::Kind op,
|
||||
static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Operator op,
|
||||
std::unique_ptr<Expression> right);
|
||||
|
||||
static DSLExpression ConvertField(std::unique_ptr<Expression> base, const char* name);
|
||||
@ -141,9 +142,9 @@ public:
|
||||
static DSLExpression ConvertIndex(std::unique_ptr<Expression> base,
|
||||
std::unique_ptr<Expression> index);
|
||||
|
||||
static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Token::Kind op);
|
||||
static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Operator op);
|
||||
|
||||
static DSLExpression ConvertPrefix(Token::Kind op, std::unique_ptr<Expression> expr);
|
||||
static DSLExpression ConvertPrefix(Operator op, std::unique_ptr<Expression> expr);
|
||||
|
||||
static DSLStatement ConvertSwitch(std::unique_ptr<Expression> value,
|
||||
ExpressionArray caseValues,
|
||||
|
@ -49,14 +49,14 @@ class BinaryExpression final : public Expression {
|
||||
public:
|
||||
static constexpr Kind kExpressionKind = Kind::kBinary;
|
||||
|
||||
BinaryExpression(int offset, std::unique_ptr<Expression> left, Token::Kind op,
|
||||
BinaryExpression(int offset, std::unique_ptr<Expression> left, Operator op,
|
||||
std::unique_ptr<Expression> right, const Type* type)
|
||||
: INHERITED(offset, kExpressionKind, type)
|
||||
, fLeft(std::move(left))
|
||||
, fOperator(op)
|
||||
, fRight(std::move(right)) {
|
||||
// If we are assigning to a VariableReference, ensure that it is set to Write or ReadWrite
|
||||
SkASSERT(!Operators::IsAssignment(op) || check_ref(*this->left()));
|
||||
SkASSERT(!op.isAssignment() || check_ref(*this->left()));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression>& left() {
|
||||
@ -75,7 +75,7 @@ public:
|
||||
return fRight;
|
||||
}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
Operator getOperator() const {
|
||||
return fOperator;
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
if (property == Property::kSideEffects && Operators::IsAssignment(this->getOperator())) {
|
||||
if (property == Property::kSideEffects && this->getOperator().isAssignment()) {
|
||||
return true;
|
||||
}
|
||||
return this->left()->hasProperty(property) || this->right()->hasProperty(property);
|
||||
@ -106,13 +106,13 @@ public:
|
||||
|
||||
String description() const override {
|
||||
return "(" + this->left()->description() + " " +
|
||||
Operators::OperatorName(this->getOperator()) + " " + this->right()->description() +
|
||||
this->getOperator().operatorName() + " " + this->right()->description() +
|
||||
")";
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fLeft;
|
||||
Token::Kind fOperator;
|
||||
Operator fOperator;
|
||||
std::unique_ptr<Expression> fRight;
|
||||
|
||||
using INHERITED = Expression;
|
||||
|
@ -21,12 +21,12 @@ class PostfixExpression final : public Expression {
|
||||
public:
|
||||
static constexpr Kind kExpressionKind = Kind::kPostfix;
|
||||
|
||||
PostfixExpression(std::unique_ptr<Expression> operand, Token::Kind op)
|
||||
PostfixExpression(std::unique_ptr<Expression> operand, Operator op)
|
||||
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
|
||||
, fOperand(std::move(operand))
|
||||
, fOperator(op) {}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
Operator getOperator() const {
|
||||
return fOperator;
|
||||
}
|
||||
|
||||
@ -51,12 +51,12 @@ public:
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
return this->operand()->description() + Operators::OperatorName(this->getOperator());
|
||||
return this->operand()->description() + this->getOperator().operatorName();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
Token::Kind fOperator;
|
||||
Operator fOperator;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ static std::unique_ptr<Expression> negate_operand(const Expression& operand) {
|
||||
std::unique_ptr<Expression> PrefixExpression::constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) {
|
||||
if (this->operand()->isCompileTimeConstant()) {
|
||||
if (this->getOperator() == Token::Kind::TK_MINUS) {
|
||||
if (this->getOperator().kind() == Token::Kind::TK_MINUS) {
|
||||
// Constant-propagate negation onto compile-time constants.
|
||||
switch (this->operand()->kind()) {
|
||||
case Expression::Kind::kFloatLiteral:
|
||||
@ -66,7 +66,7 @@ std::unique_ptr<Expression> PrefixExpression::constantPropagate(const IRGenerato
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (this->getOperator() == Token::Kind::TK_LOGICALNOT) {
|
||||
} else if (this->getOperator().kind() == Token::Kind::TK_LOGICALNOT) {
|
||||
if (this->operand()->is<BoolLiteral>()) {
|
||||
// Convert !boolLiteral(true) to boolLiteral(false).
|
||||
const BoolLiteral& b = this->operand()->as<BoolLiteral>();
|
||||
|
@ -22,12 +22,12 @@ class PrefixExpression final : public Expression {
|
||||
public:
|
||||
static constexpr Kind kExpressionKind = Kind::kPrefix;
|
||||
|
||||
PrefixExpression(Token::Kind op, std::unique_ptr<Expression> operand)
|
||||
PrefixExpression(Operator op, std::unique_ptr<Expression> operand)
|
||||
: INHERITED(operand->fOffset, kExpressionKind, &operand->type())
|
||||
, fOperator(op)
|
||||
, fOperand(std::move(operand)) {}
|
||||
|
||||
Token::Kind getOperator() const {
|
||||
Operator getOperator() const {
|
||||
return fOperator;
|
||||
}
|
||||
|
||||
@ -41,8 +41,8 @@ public:
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
if (property == Property::kSideEffects &&
|
||||
(this->getOperator() == Token::Kind::TK_PLUSPLUS ||
|
||||
this->getOperator() == Token::Kind::TK_MINUSMINUS)) {
|
||||
(this->getOperator().kind() == Token::Kind::TK_PLUSPLUS ||
|
||||
this->getOperator().kind() == Token::Kind::TK_MINUSMINUS)) {
|
||||
return true;
|
||||
}
|
||||
return this->operand()->hasProperty(property);
|
||||
@ -57,11 +57,11 @@ public:
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
return Operators::OperatorName(this->getOperator()) + this->operand()->description();
|
||||
return this->getOperator().operatorName() + this->operand()->description();
|
||||
}
|
||||
|
||||
private:
|
||||
Token::Kind fOperator;
|
||||
Operator fOperator;
|
||||
std::unique_ptr<Expression> fOperand;
|
||||
|
||||
using INHERITED = Expression;
|
||||
|
Loading…
Reference in New Issue
Block a user