Create SkSLOperators, centralize functionality

Change-Id: I3593e7ab0caac2fd572346038cbc8ff63e6fe970
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/366406
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2021-02-04 16:07:11 -05:00 committed by Skia Commit-Bot
parent 9c00b794a7
commit 001850105e
23 changed files with 393 additions and 454 deletions

View File

@ -39,6 +39,8 @@ skia_sksl_sources = [
"$_src/sksl/SkSLMangler.cpp",
"$_src/sksl/SkSLMemoryLayout.h",
"$_src/sksl/SkSLMemoryPool.h",
"$_src/sksl/SkSLOperators.cpp",
"$_src/sksl/SkSLOperators.h",
"$_src/sksl/SkSLOutputStream.cpp",
"$_src/sksl/SkSLOutputStream.h",
"$_src/sksl/SkSLParser.cpp",

View File

@ -6,7 +6,7 @@
*/
#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLString.h"
namespace SkSL {
@ -17,7 +17,7 @@ String ASTNode::description() const {
case Kind::kNull: return "";
case Kind::kBinary:
return "(" + this->begin()->description() + " " +
Compiler::OperatorName(getToken().fKind) + " " +
Operators::OperatorName(getToken().fKind) + " " +
(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() + Compiler::OperatorName(getToken().fKind);
return this->begin()->description() + Operators::OperatorName(getToken().fKind);
case Kind::kPrefix:
return Compiler::OperatorName(getToken().fKind) + this->begin()->description();
return Operators::OperatorName(getToken().fKind) + this->begin()->description();
case Kind::kReturn:
if (this->begin() != this->end()) {
return "return " + this->begin()->description() + ";";

View File

@ -8,6 +8,7 @@
#include "src/sksl/SkSLAnalysis.h"
#include "include/private/SkSLSampleUsage.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLProgram.h"

View File

@ -7,6 +7,7 @@
#include "src/sksl/SkSLCFGGenerator.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLConstructor.h"
#include "src/sksl/ir/SkSLDoStatement.h"
@ -374,7 +375,7 @@ void CFGGenerator::addExpression(CFG& cfg, std::unique_ptr<Expression>* e, bool
}
default:
this->addExpression(cfg, &b.left(),
!Compiler::IsAssignment(b.getOperator()));
!Operators::IsAssignment(b.getOperator()));
this->addExpression(cfg, &b.right(), constantPropagate);
cfg.currentBlock().fNodes.push_back(
BasicBlock::MakeExpression(e, constantPropagate));

View File

@ -75,7 +75,7 @@ void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Token::Kind op = b.getOperator();
if (op == Token::Kind::TK_PERCENT) {
// need to use "%%" instead of "%" b/c the code will be inside of a printf
Precedence precedence = GetBinaryPrecedence(op);
Precedence precedence = Operators::GetBinaryPrecedence(op);
if (precedence >= parentPrecedence) {
this->write("(");
}
@ -239,7 +239,7 @@ void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression
if (is_private(var)) {
this->writeRuntimeValue(var.type(), var.modifiers().fLayout, var.name());
} else {
this->writeExpression(value, kTopLevel_Precedence);
this->writeExpression(value, Precedence::kTopLevel);
}
}
@ -264,7 +264,7 @@ void CPPCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
if (fCPPMode) {
// no support for multiple swizzle components yet
SkASSERT(swizzle.components().size() == 1);
this->writeExpression(*swizzle.base(), kPostfix_Precedence);
this->writeExpression(*swizzle.base(), Precedence::kPostfix);
switch (swizzle.components()[0]) {
case 0: this->write(".left()"); break;
case 1: this->write(".top()"); break;
@ -471,7 +471,7 @@ void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
for (const auto& arg : arguments) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
}
@ -734,7 +734,7 @@ void CPPCodeGenerator::writePrivateVarValues() {
if (is_private(decl.var()) && decl.value()) {
this->writef("%s = ", String(decl.var().name()).c_str());
fCPPMode = true;
this->writeExpression(*decl.value(), kAssignment_Precedence);
this->writeExpression(*decl.value(), Precedence::kAssignment);
fCPPMode = false;
this->write(";\n");
}
@ -900,7 +900,7 @@ String CPPCodeGenerator::convertSKSLExpressionToCPP(const Expression& e,
fFormatArgs.clear();
// Convert the argument expression into a format string and args
this->writeExpression(e, Precedence::kTopLevel_Precedence);
this->writeExpression(e, Precedence::kTopLevel);
std::vector<String> newArgs(fFormatArgs);
String expr = exprBuffer.str();
@ -1289,7 +1289,7 @@ void CPPCodeGenerator::writeGetKey() {
String(var.name()).c_str());
if (decl.value()) {
fCPPMode = true;
this->writeExpression(*decl.value(), kAssignment_Precedence);
this->writeExpression(*decl.value(), Precedence::kAssignment);
fCPPMode = false;
} else {
this->writef("%s", default_value(var).c_str());

View File

@ -25,6 +25,8 @@ public:
bool generateCode() override;
private:
using Precedence = Operators::Precedence;
void writef(const char* s, va_list va) SK_PRINTF_LIKE(2, 0);
void writef(const char* s, ...) SK_PRINTF_LIKE(2, 3);

View File

@ -17,6 +17,7 @@
#include "src/sksl/SkSLHCodeGenerator.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLMetalCodeGenerator.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLPipelineStageCodeGenerator.h"
#include "src/sksl/SkSLRehydrator.h"
#include "src/sksl/SkSLSPIRVCodeGenerator.h"
@ -430,7 +431,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node, DefinitionMap* defin
BinaryExpression* b = &expr->as<BinaryExpression>();
if (b->getOperator() == Token::Kind::TK_EQ) {
this->addDefinition(b->left().get(), &b->right(), definitions);
} else if (Compiler::IsAssignment(b->getOperator())) {
} else if (Operators::IsAssignment(b->getOperator())) {
this->addDefinition(
b->left().get(),
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
@ -586,7 +587,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 (!Compiler::IsAssignment(b.getOperator())) {
if (!Operators::IsAssignment(b.getOperator())) {
return false;
}
return is_dead(*b.left(), usage);
@ -2018,84 +2019,6 @@ bool Compiler::toPipelineStage(Program& program, PipelineStageArgs* outArgs) {
}
#endif
const char* Compiler::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 Compiler::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:
return true;
default:
return false;
}
}
Token::Kind Compiler::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;
}
}
Position Compiler::position(int offset) {
if (fSource && offset >= 0) {
int line = 1;

View File

@ -17,7 +17,6 @@
#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLInliner.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/ir/SkSLProgram.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
@ -194,15 +193,6 @@ public:
return *fContext;
}
static const char* OperatorName(Token::Kind op);
// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
static bool IsAssignment(Token::Kind op);
// Given a compound assignment operator, returns the non-assignment version of the operator
// (e.g. '+=' becomes '+')
static Token::Kind RemoveAssignment(Token::Kind op);
// When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0)
// When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr.
struct ModuleData {

View File

@ -247,15 +247,15 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx
this->fFunctionHeader += String(" ") + this->getTypePrecision(otherExpr.type()) +
this->getTypeName(otherExpr.type()) + " " + tmpVar2 + ";\n";
this->write("((" + tmpVar1 + " = ");
this->writeExpression(absExpr, kTopLevel_Precedence);
this->writeExpression(absExpr, Precedence::kTopLevel);
this->write(") < (" + tmpVar2 + " = ");
this->writeExpression(otherExpr, kAssignment_Precedence);
this->writeExpression(otherExpr, Precedence::kAssignment);
this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
}
void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) {
this->write("(1.0 / sqrt(");
this->writeExpression(x, kTopLevel_Precedence);
this->writeExpression(x, Precedence::kTopLevel);
this->write("))");
}
@ -321,7 +321,7 @@ void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) {
SkASSERT(false);
}
this->write(name + "(");
this->writeExpression(mat, kTopLevel_Precedence);
this->writeExpression(mat, Precedence::kTopLevel);
this->write(")");
}
@ -409,7 +409,7 @@ void GLSLCodeGenerator::writeInverseHack(const Expression& mat) {
SkASSERT(false);
}
this->write(name + "(");
this->writeExpression(mat, kTopLevel_Precedence);
this->writeExpression(mat, Precedence::kTopLevel);
this->write(")");
}
@ -437,7 +437,7 @@ void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) {
fExtraFunctions.writeText("); }");
}
this->write(name + "(");
this->writeExpression(mat, kTopLevel_Precedence);
this->writeExpression(mat, Precedence::kTopLevel);
this->write(")");
}
@ -508,9 +508,9 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
const PrefixExpression& p = (PrefixExpression&) *arguments[1];
if (p.getOperator() == Token::Kind::TK_MINUS) {
this->write("atan(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(", -1.0 * ");
this->writeExpression(*p.operand(), kMultiplicative_Precedence);
this->writeExpression(*p.operand(), Precedence::kMultiplicative);
this->write(")");
return;
}
@ -542,11 +542,11 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (!fProgram.fCaps->builtinFMASupport()) {
SkASSERT(arguments.size() == 3);
this->write("((");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(") * (");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(") + (");
this->writeExpression(*arguments[2], kSequence_Precedence);
this->writeExpression(*arguments[2], Precedence::kSequence);
this->write("))");
return;
}
@ -555,9 +555,9 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (!fProgram.fCaps->canUseFractForNegativeValues()) {
SkASSERT(arguments.size() == 1);
this->write("(0.5 - sign(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(") * (0.5 - fract(abs(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("))))");
return;
}
@ -601,15 +601,15 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
// Change pow(x, y) into exp2(y * log2(x))
this->write("exp2(");
this->writeExpression(*arguments[1], kMultiplicative_Precedence);
this->writeExpression(*arguments[1], Precedence::kMultiplicative);
this->write(" * log2(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("))");
return;
case FunctionClass::kSaturate:
SkASSERT(arguments.size() == 1);
this->write("clamp(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(", 0.0, 1.0)");
return;
case FunctionClass::kTexture: {
@ -701,7 +701,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
for (const auto& arg : arguments) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) {
this->write(", -0.5");
@ -726,7 +726,7 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parent
for (const auto& arg : c.arguments()) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
}
@ -820,9 +820,9 @@ void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
}
void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
this->writeExpression(*expr.base(), kPostfix_Precedence);
this->writeExpression(*expr.base(), Precedence::kPostfix);
this->write("[");
this->writeExpression(*expr.index(), kTopLevel_Precedence);
this->writeExpression(*expr.index(), Precedence::kTopLevel);
this->write("]");
}
@ -832,7 +832,7 @@ bool is_sk_position(const FieldAccess& f) {
void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
if (f.ownerKind() == FieldAccess::OwnerKind::kDefault) {
this->writeExpression(*f.base(), kPostfix_Precedence);
this->writeExpression(*f.base(), Precedence::kPostfix);
this->write(".");
}
const Type& baseType = f.base()->type();
@ -847,7 +847,7 @@ void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
}
void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
this->writeExpression(*swizzle.base(), kPostfix_Precedence);
this->writeExpression(*swizzle.base(), Precedence::kPostfix);
this->write(".");
for (int c : swizzle.components()) {
SkASSERT(c >= 0 && c <= 3);
@ -855,43 +855,6 @@ void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
}
}
GLSLCodeGenerator::Precedence GLSLCodeGenerator::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 GLSLCodeGenerator::kMultiplicative_Precedence;
case Token::Kind::TK_PLUS: // fall through
case Token::Kind::TK_MINUS: return GLSLCodeGenerator::kAdditive_Precedence;
case Token::Kind::TK_SHL: // fall through
case Token::Kind::TK_SHR: return GLSLCodeGenerator::kShift_Precedence;
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 GLSLCodeGenerator::kRelational_Precedence;
case Token::Kind::TK_EQEQ: // fall through
case Token::Kind::TK_NEQ: return GLSLCodeGenerator::kEquality_Precedence;
case Token::Kind::TK_BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence;
case Token::Kind::TK_BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence;
case Token::Kind::TK_BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence;
case Token::Kind::TK_LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence;
case Token::Kind::TK_LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence;
case Token::Kind::TK_LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence;
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 GLSLCodeGenerator::kAssignment_Precedence;
case Token::Kind::TK_COMMA: return GLSLCodeGenerator::kSequence_Precedence;
default: SK_ABORT("unsupported binary operator");
}
}
void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
const Expression& left = *b.left();
@ -903,12 +866,12 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
return;
}
Precedence precedence = GetBinaryPrecedence(op);
Precedence precedence = Operators::GetBinaryPrecedence(op);
if (precedence >= parentPrecedence) {
this->write("(");
}
bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
Compiler::IsAssignment(op) &&
Operators::IsAssignment(op) &&
left.kind() == Expression::Kind::kFieldAccess &&
is_sk_position((FieldAccess&) left) &&
!right.containsRTAdjust() &&
@ -918,7 +881,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
}
this->writeExpression(left, precedence);
this->write(" ");
this->write(Compiler::OperatorName(op));
this->write(Operators::OperatorName(op));
this->write(" ");
this->writeExpression(right, precedence);
if (positionWorkaround) {
@ -931,17 +894,17 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
if (kTernary_Precedence >= parentPrecedence) {
if (Precedence::kTernary >= parentPrecedence) {
this->write("(");
}
// Transform:
// a && b => a ? b : false
// a || b => a ? true : b
this->writeExpression(*b.left(), kTernary_Precedence);
this->writeExpression(*b.left(), Precedence::kTernary);
this->write(" ? ");
if (b.getOperator() == Token::Kind::TK_LOGICALAND) {
this->writeExpression(*b.right(), kTernary_Precedence);
this->writeExpression(*b.right(), Precedence::kTernary);
} else {
BoolLiteral boolTrue(fContext, -1, true);
this->writeBoolLiteral(boolTrue);
@ -951,48 +914,48 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
BoolLiteral boolFalse(fContext, -1, false);
this->writeBoolLiteral(boolFalse);
} else {
this->writeExpression(*b.right(), kTernary_Precedence);
this->writeExpression(*b.right(), Precedence::kTernary);
}
if (kTernary_Precedence >= parentPrecedence) {
if (Precedence::kTernary >= parentPrecedence) {
this->write(")");
}
}
void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
Precedence parentPrecedence) {
if (kTernary_Precedence >= parentPrecedence) {
if (Precedence::kTernary >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*t.test(), kTernary_Precedence);
this->writeExpression(*t.test(), Precedence::kTernary);
this->write(" ? ");
this->writeExpression(*t.ifTrue(), kTernary_Precedence);
this->writeExpression(*t.ifTrue(), Precedence::kTernary);
this->write(" : ");
this->writeExpression(*t.ifFalse(), kTernary_Precedence);
if (kTernary_Precedence >= parentPrecedence) {
this->writeExpression(*t.ifFalse(), Precedence::kTernary);
if (Precedence::kTernary >= parentPrecedence) {
this->write(")");
}
}
void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
Precedence parentPrecedence) {
if (kPrefix_Precedence >= parentPrecedence) {
if (Precedence::kPrefix >= parentPrecedence) {
this->write("(");
}
this->write(Compiler::OperatorName(p.getOperator()));
this->writeExpression(*p.operand(), kPrefix_Precedence);
if (kPrefix_Precedence >= parentPrecedence) {
this->write(Operators::OperatorName(p.getOperator()));
this->writeExpression(*p.operand(), Precedence::kPrefix);
if (Precedence::kPrefix >= parentPrecedence) {
this->write(")");
}
}
void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
Precedence parentPrecedence) {
if (kPostfix_Precedence >= parentPrecedence) {
if (Precedence::kPostfix >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*p.operand(), kPostfix_Precedence);
this->write(Compiler::OperatorName(p.getOperator()));
if (kPostfix_Precedence >= parentPrecedence) {
this->writeExpression(*p.operand(), Precedence::kPostfix);
this->write(Operators::OperatorName(p.getOperator()));
if (Precedence::kPostfix >= parentPrecedence) {
this->write(")");
}
}
@ -1200,7 +1163,7 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
}
void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
this->writeExpression(value, kTopLevel_Precedence);
this->writeExpression(value, Precedence::kTopLevel);
}
const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
@ -1275,7 +1238,7 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
this->writeBlock(s.as<Block>());
break;
case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().expression(), kTopLevel_Precedence);
this->writeExpression(*s.as<ExpressionStatement>().expression(), Precedence::kTopLevel);
this->write(";");
break;
case Statement::Kind::kReturn:
@ -1337,7 +1300,7 @@ void GLSLCodeGenerator::writeBlock(const Block& b) {
void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
this->write("if (");
this->writeExpression(*stmt.test(), kTopLevel_Precedence);
this->writeExpression(*stmt.test(), Precedence::kTopLevel);
this->write(") ");
this->writeStatement(*stmt.ifTrue());
if (stmt.ifFalse()) {
@ -1350,7 +1313,7 @@ void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
// Emit loops of the form 'for(;test;)' as 'while(test)', which is probably how they started
if (!f.initializer() && f.test() && !f.next()) {
this->write("while (");
this->writeExpression(*f.test(), kTopLevel_Precedence);
this->writeExpression(*f.test(), Precedence::kTopLevel);
this->write(") ");
this->writeStatement(*f.statement());
return;
@ -1368,14 +1331,14 @@ void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
std::make_unique<BoolLiteral>(fContext, -1, true),
fContext.fTypes.fBool.get()));
this->writeExpression(*and_true, kTopLevel_Precedence);
this->writeExpression(*and_true, Precedence::kTopLevel);
} else {
this->writeExpression(*f.test(), kTopLevel_Precedence);
this->writeExpression(*f.test(), Precedence::kTopLevel);
}
}
this->write("; ");
if (f.next()) {
this->writeExpression(*f.next(), kTopLevel_Precedence);
this->writeExpression(*f.next(), Precedence::kTopLevel);
}
this->write(") ");
this->writeStatement(*f.statement());
@ -1386,7 +1349,7 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
this->write("do ");
this->writeStatement(*d.statement());
this->write(" while (");
this->writeExpression(*d.test(), kTopLevel_Precedence);
this->writeExpression(*d.test(), Precedence::kTopLevel);
this->write(");");
return;
}
@ -1418,7 +1381,7 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
this->writeLine(") {");
fIndentation++;
this->write("if (!");
this->writeExpression(*d.test(), kPrefix_Precedence);
this->writeExpression(*d.test(), Precedence::kPrefix);
this->writeLine(") {");
fIndentation++;
this->writeLine("break;");
@ -1436,13 +1399,13 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
this->write("switch (");
this->writeExpression(*s.value(), kTopLevel_Precedence);
this->writeExpression(*s.value(), Precedence::kTopLevel);
this->writeLine(") {");
fIndentation++;
for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
if (c->value()) {
this->write("case ");
this->writeExpression(*c->value(), kTopLevel_Precedence);
this->writeExpression(*c->value(), Precedence::kTopLevel);
this->writeLine(":");
} else {
this->writeLine("default:");
@ -1462,7 +1425,7 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->write("return");
if (r.expression()) {
this->write(" ");
this->writeExpression(*r.expression(), kTopLevel_Precedence);
this->writeExpression(*r.expression(), Precedence::kTopLevel);
}
this->write(";");
}

View File

@ -8,11 +8,13 @@
#ifndef SKSL_GLSLCODEGENERATOR
#define SKSL_GLSLCODEGENERATOR
#include <set>
#include <stack>
#include <tuple>
#include <unordered_map>
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
@ -49,27 +51,6 @@ namespace SkSL {
*/
class GLSLCodeGenerator : public CodeGenerator {
public:
enum Precedence {
kParentheses_Precedence = 1,
kPostfix_Precedence = 2,
kPrefix_Precedence = 3,
kMultiplicative_Precedence = 4,
kAdditive_Precedence = 5,
kShift_Precedence = 6,
kRelational_Precedence = 7,
kEquality_Precedence = 8,
kBitwiseAnd_Precedence = 9,
kBitwiseXor_Precedence = 10,
kBitwiseOr_Precedence = 11,
kLogicalAnd_Precedence = 12,
kLogicalXor_Precedence = 13,
kLogicalOr_Precedence = 14,
kTernary_Precedence = 15,
kAssignment_Precedence = 16,
kSequence_Precedence = 17,
kTopLevel_Precedence = kSequence_Precedence
};
GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
@ -80,6 +61,8 @@ public:
bool generateCode() override;
protected:
using Precedence = Operators::Precedence;
void write(const char* s);
void writeLine();
@ -156,8 +139,6 @@ protected:
virtual void writeSwizzle(const Swizzle& swizzle);
static Precedence GetBinaryPrecedence(Token::Kind op);
virtual void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
void writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
Precedence parentPrecedence);

View File

@ -16,6 +16,7 @@
#include "src/sksl/SkSLAnalysis.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLParser.h"
#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
@ -1865,7 +1866,7 @@ static bool determine_binary_type(const Context& context,
return false;
}
bool isAssignment = Compiler::IsAssignment(op);
bool isAssignment = Operators::IsAssignment(op);
if (is_matrix_multiply(left, op, right)) { // left * right
// Determine final component type.
if (!determine_binary_type(context, allowNarrowing, op,
@ -1997,10 +1998,10 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
}
if (this->strictES2Mode() && !op_allowed_in_strict_es2_mode(op)) {
this->errorReporter().error(
offset, String("operator '") + Compiler::OperatorName(op) + "' is not allowed");
offset, String("operator '") + Operators::OperatorName(op) + "' is not allowed");
return nullptr;
}
bool isAssignment = Compiler::IsAssignment(op);
bool isAssignment = Operators::IsAssignment(op);
if (isAssignment && !this->setRefKind(*left, op != Token::Kind::TK_EQ
? VariableReference::RefKind::kReadWrite
: VariableReference::RefKind::kWrite)) {
@ -2009,7 +2010,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: '") + Compiler::OperatorName(op) +
offset, String("type mismatch: '") + Operators::OperatorName(op) +
"' cannot operate on '" + left->type().displayName() + "', '" +
right->type().displayName() + "'");
return nullptr;
@ -2466,7 +2467,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_PLUSPLUS:
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
String("'") + Compiler::OperatorName(op) +
String("'") + Operators::OperatorName(op) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2477,7 +2478,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_MINUSMINUS:
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
String("'") + Compiler::OperatorName(op) +
String("'") + Operators::OperatorName(op) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2488,7 +2489,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
case Token::Kind::TK_LOGICALNOT:
if (!baseType.isBoolean()) {
this->errorReporter().error(base->fOffset,
String("'") + Compiler::OperatorName(op) +
String("'") + Operators::OperatorName(op) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2502,13 +2503,13 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(Token::Kind op,
if (this->strictES2Mode()) {
// GLSL ES 1.00, Section 5.1
this->errorReporter().error(base->fOffset,
String("operator '") + Compiler::OperatorName(op) +
String("operator '") + Operators::OperatorName(op) +
"' is not allowed");
return nullptr;
}
if (!baseType.isInteger()) {
this->errorReporter().error(base->fOffset,
String("'") + Compiler::OperatorName(op) +
String("'") + Operators::OperatorName(op) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}
@ -2912,7 +2913,7 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(std::unique_pt
const Type& baseType = base->type();
if (!baseType.isNumber()) {
this->errorReporter().error(base->fOffset,
"'" + String(Compiler::OperatorName(op)) +
"'" + String(Operators::OperatorName(op)) +
"' cannot operate on '" + baseType.displayName() + "'");
return nullptr;
}

View File

@ -5,7 +5,8 @@
* found in the LICENSE file.
*/
#include "src/sksl/SkSLMetalCodeGenerator.h"
#include "src/sksl/SkSLMangler.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
namespace SkSL {

View File

@ -25,7 +25,7 @@ namespace SkSL {
const char* MetalCodeGenerator::OperatorName(Token::Kind op) {
switch (op) {
case Token::Kind::TK_LOGICALXOR: return "!=";
default: return Compiler::OperatorName(op);
default: return Operators::OperatorName(op);
}
}
@ -271,7 +271,7 @@ String MetalCodeGenerator::getOutParamHelper(const FunctionCall& call,
if (param->modifiers().fFlags & Modifiers::kIn_Flag) {
this->write(" = ");
fIgnoreVariableReferenceModifiers = true;
this->writeExpression(*arguments[index], kAssignment_Precedence);
this->writeExpression(*arguments[index], Precedence::kAssignment);
fIgnoreVariableReferenceModifiers = false;
}
@ -305,7 +305,7 @@ String MetalCodeGenerator::getOutParamHelper(const FunctionCall& call,
}
// outParam.zyx = _var2;
fIgnoreVariableReferenceModifiers = true;
this->writeExpression(*arguments[index], kAssignment_Precedence);
this->writeExpression(*arguments[index], Precedence::kAssignment);
fIgnoreVariableReferenceModifiers = false;
this->write(" = _var");
this->write(to_string(index));
@ -381,9 +381,9 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
separator = ", ";
if (outVars[i]) {
this->writeExpression(*outVars[i], kSequence_Precedence);
this->writeExpression(*outVars[i], Precedence::kSequence);
} else {
this->writeExpression(*arguments[i], kSequence_Precedence);
this->writeExpression(*arguments[i], Precedence::kSequence);
}
}
this->write(")");
@ -513,7 +513,7 @@ void MetalCodeGenerator::writeArgumentList(const ExpressionArray& arguments) {
for (const std::unique_ptr<Expression>& arg : arguments) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
}
@ -522,9 +522,9 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
const ExpressionArray& arguments = c.arguments();
switch (kind) {
case kTexture_IntrinsicKind: {
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(".sample(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(SAMPLER_SUFFIX);
this->write(", ");
const Type& arg1Type = arguments[1]->type();
@ -532,11 +532,11 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
// have to store the vector in a temp variable to avoid double evaluating it
String tmpVar = this->getTempVariable(arg1Type);
this->write("(" + tmpVar + " = ");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(", " + tmpVar + ".xy / " + tmpVar + ".z))");
} else {
SkASSERT(arg1Type == *fContext.fTypes.fFloat2);
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(")");
}
break;
@ -546,9 +546,9 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
String tmpX = this->getTempVariable(arguments[0]->type());
String tmpY = this->getTempVariable(arguments[1]->type());
this->write("(" + tmpX + " = ");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(", " + tmpY + " = ");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(", " + tmpX + " - " + tmpY + " * floor(" + tmpX + " / " + tmpY + "))");
break;
}
@ -556,9 +556,9 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
case kDistance_IntrinsicKind: {
if (arguments[0]->type().columns() == 1) {
this->write("abs(");
this->writeExpression(*arguments[0], kAdditive_Precedence);
this->writeExpression(*arguments[0], Precedence::kAdditive);
this->write(" - ");
this->writeExpression(*arguments[1], kAdditive_Precedence);
this->writeExpression(*arguments[1], Precedence::kAdditive);
this->write(")");
} else {
this->writeSimpleIntrinsic(c);
@ -568,9 +568,9 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
case kDot_IntrinsicKind: {
if (arguments[0]->type().columns() == 1) {
this->write("(");
this->writeExpression(*arguments[0], kMultiplicative_Precedence);
this->writeExpression(*arguments[0], Precedence::kMultiplicative);
this->write(" * ");
this->writeExpression(*arguments[1], kMultiplicative_Precedence);
this->writeExpression(*arguments[1], Precedence::kMultiplicative);
this->write(")");
} else {
this->writeSimpleIntrinsic(c);
@ -581,11 +581,11 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
if (arguments[0]->type().columns() == 1) {
// ((((Nref) * (I) < 0) ? 1 : -1) * (N))
this->write("((((");
this->writeExpression(*arguments[2], kSequence_Precedence);
this->writeExpression(*arguments[2], Precedence::kSequence);
this->write(") * (");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(") < 0) ? 1 : -1) * (");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("))");
} else {
this->writeSimpleIntrinsic(c);
@ -594,32 +594,32 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
}
case kLength_IntrinsicKind: {
this->write(arguments[0]->type().columns() == 1 ? "abs(" : "length(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(")");
break;
}
case kNormalize_IntrinsicKind: {
this->write(arguments[0]->type().columns() == 1 ? "sign(" : "normalize(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(")");
break;
}
case kBitcast_IntrinsicKind: {
this->write(this->getBitcastIntrinsic(c.type()));
this->write("(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(")");
break;
}
case kDegrees_IntrinsicKind: {
this->write("((");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(") * 57.2957795)");
break;
}
case kRadians_IntrinsicKind: {
this->write("((");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(") * 0.0174532925)");
break;
}
@ -660,11 +660,11 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
// (_skTempI = ...
this->write("(" + tmpI + " = ");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
// , _skTempN = ...
this->write(", " + tmpN + " = ");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
// , _skTempI - 2 * _skTempN * _skTempI * _skTempN)
this->write(", " + tmpI + " - 2 * " + tmpN + " * " + tmpI + " * " + tmpN + ")");
@ -678,11 +678,11 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
// Metal does implement refract for vectors; rather than reimplementing refract from
// scratch, we can replace the call with `refract(float2(I,0), float2(N,0), eta).x`.
this->write("(refract(float2(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(", 0), float2(");
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
this->write(", 0), ");
this->writeExpression(*arguments[2], kSequence_Precedence);
this->writeExpression(*arguments[2], Precedence::kSequence);
this->write(").x)");
} else {
this->writeSimpleIntrinsic(c);
@ -696,7 +696,7 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
}
case kBitCount_IntrinsicKind: {
this->write("popcount(");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write(")");
break;
}
@ -712,7 +712,7 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
this->write("(");
this->write(skTemp);
this->write(" = (");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("), select(ctz(");
this->write(skTemp);
this->write("), ");
@ -737,7 +737,7 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
this->write("(");
this->write(skTemp1);
this->write(" = (");
this->writeExpression(*arguments[0], kSequence_Precedence);
this->writeExpression(*arguments[0], Precedence::kSequence);
this->write("), ");
// Signed input types might be negative; we need another helper variable to negate the
@ -784,7 +784,7 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
case kCompareLessThanEqual_IntrinsicKind:
case kCompareNotEqual_IntrinsicKind: {
this->write("(");
this->writeExpression(*c.arguments()[0], kRelational_Precedence);
this->writeExpression(*c.arguments()[0], Precedence::kRelational);
switch (kind) {
case kCompareEqual_IntrinsicKind:
this->write(" == ");
@ -807,7 +807,7 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c, IntrinsicKind
default:
SK_ABORT("unsupported comparison intrinsic kind");
}
this->writeExpression(*c.arguments()[1], kRelational_Precedence);
this->writeExpression(*c.arguments()[1], Precedence::kRelational);
this->write(")");
break;
}
@ -1055,7 +1055,7 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
for (const std::unique_ptr<Expression>& expr : c.arguments()) {
this->write(separator);
separator = ", ";
this->writeExpression(*expr, kSequence_Precedence);
this->writeExpression(*expr, Precedence::kSequence);
}
this->write(")");
return;
@ -1080,7 +1080,7 @@ void MetalCodeGenerator::writeConstructor(const Constructor& c, Precedence paren
}
scalarCount += argType.columns();
}
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
if (scalarCount && scalarCount == constructorType.rows()) {
this->write(")");
scalarCount = 0;
@ -1145,16 +1145,16 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
}
void MetalCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
this->writeExpression(*expr.base(), kPostfix_Precedence);
this->writeExpression(*expr.base(), Precedence::kPostfix);
this->write("[");
this->writeExpression(*expr.index(), kTopLevel_Precedence);
this->writeExpression(*expr.index(), Precedence::kTopLevel);
this->write("]");
}
void MetalCodeGenerator::writeFieldAccess(const FieldAccess& f) {
const Type::Field* field = &f.base()->type().fields()[f.fieldIndex()];
if (FieldAccess::OwnerKind::kDefault == f.ownerKind()) {
this->writeExpression(*f.base(), kPostfix_Precedence);
this->writeExpression(*f.base(), Precedence::kPostfix);
this->write(".");
}
switch (field->fModifiers.fLayout.fBuiltin) {
@ -1176,7 +1176,7 @@ void MetalCodeGenerator::writeFieldAccess(const FieldAccess& f) {
}
void MetalCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
this->writeExpression(*swizzle.base(), kPostfix_Precedence);
this->writeExpression(*swizzle.base(), Precedence::kPostfix);
this->write(".");
for (int c : swizzle.components()) {
SkASSERT(c >= 0 && c <= 3);
@ -1184,43 +1184,6 @@ void MetalCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
}
}
MetalCodeGenerator::Precedence MetalCodeGenerator::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 MetalCodeGenerator::kMultiplicative_Precedence;
case Token::Kind::TK_PLUS: // fall through
case Token::Kind::TK_MINUS: return MetalCodeGenerator::kAdditive_Precedence;
case Token::Kind::TK_SHL: // fall through
case Token::Kind::TK_SHR: return MetalCodeGenerator::kShift_Precedence;
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 MetalCodeGenerator::kRelational_Precedence;
case Token::Kind::TK_EQEQ: // fall through
case Token::Kind::TK_NEQ: return MetalCodeGenerator::kEquality_Precedence;
case Token::Kind::TK_BITWISEAND: return MetalCodeGenerator::kBitwiseAnd_Precedence;
case Token::Kind::TK_BITWISEXOR: return MetalCodeGenerator::kBitwiseXor_Precedence;
case Token::Kind::TK_BITWISEOR: return MetalCodeGenerator::kBitwiseOr_Precedence;
case Token::Kind::TK_LOGICALAND: return MetalCodeGenerator::kLogicalAnd_Precedence;
case Token::Kind::TK_LOGICALXOR: return MetalCodeGenerator::kLogicalXor_Precedence;
case Token::Kind::TK_LOGICALOR: return MetalCodeGenerator::kLogicalOr_Precedence;
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 MetalCodeGenerator::kAssignment_Precedence;
case Token::Kind::TK_COMMA: return MetalCodeGenerator::kSequence_Precedence;
default: SK_ABORT("unsupported binary operator");
}
}
void MetalCodeGenerator::writeMatrixTimesEqualHelper(const Type& left, const Type& right,
const Type& result) {
String key = "TimesEqual" + this->typeName(left) + this->typeName(right);
@ -1243,7 +1206,7 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
const Type& leftType = left.type();
const Type& rightType = right.type();
Token::Kind op = b.getOperator();
Precedence precedence = GetBinaryPrecedence(b.getOperator());
Precedence precedence = Operators::GetBinaryPrecedence(b.getOperator());
bool needParens = precedence >= parentPrecedence;
switch (op) {
case Token::Kind::TK_EQEQ:
@ -1268,7 +1231,7 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
this->writeMatrixTimesEqualHelper(leftType, rightType, b.type());
}
this->writeExpression(left, precedence);
if (op != Token::Kind::TK_EQ && Compiler::IsAssignment(op) &&
if (op != Token::Kind::TK_EQ && Operators::IsAssignment(op) &&
left.kind() == Expression::Kind::kSwizzle && !left.hasSideEffects()) {
// This doesn't compile in Metal:
// float4 x = float4(1);
@ -1277,7 +1240,7 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
// but switching it to x.xy = x.xy * float2x2(...) fixes it. We perform this tranformation
// as long as the LHS has no side effects, and hope for the best otherwise.
this->write(" = ");
this->writeExpression(left, kAssignment_Precedence);
this->writeExpression(left, Precedence::kAssignment);
this->write(" ");
String opName = OperatorName(op);
SkASSERT(opName.endsWith("="));
@ -1294,39 +1257,39 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
void MetalCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
Precedence parentPrecedence) {
if (kTernary_Precedence >= parentPrecedence) {
if (Precedence::kTernary >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*t.test(), kTernary_Precedence);
this->writeExpression(*t.test(), Precedence::kTernary);
this->write(" ? ");
this->writeExpression(*t.ifTrue(), kTernary_Precedence);
this->writeExpression(*t.ifTrue(), Precedence::kTernary);
this->write(" : ");
this->writeExpression(*t.ifFalse(), kTernary_Precedence);
if (kTernary_Precedence >= parentPrecedence) {
this->writeExpression(*t.ifFalse(), Precedence::kTernary);
if (Precedence::kTernary >= parentPrecedence) {
this->write(")");
}
}
void MetalCodeGenerator::writePrefixExpression(const PrefixExpression& p,
Precedence parentPrecedence) {
if (kPrefix_Precedence >= parentPrecedence) {
if (Precedence::kPrefix >= parentPrecedence) {
this->write("(");
}
this->write(OperatorName(p.getOperator()));
this->writeExpression(*p.operand(), kPrefix_Precedence);
if (kPrefix_Precedence >= parentPrecedence) {
this->writeExpression(*p.operand(), Precedence::kPrefix);
if (Precedence::kPrefix >= parentPrecedence) {
this->write(")");
}
}
void MetalCodeGenerator::writePostfixExpression(const PostfixExpression& p,
Precedence parentPrecedence) {
if (kPostfix_Precedence >= parentPrecedence) {
if (Precedence::kPostfix >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*p.operand(), kPostfix_Precedence);
this->writeExpression(*p.operand(), Precedence::kPostfix);
this->write(OperatorName(p.getOperator()));
if (kPostfix_Precedence >= parentPrecedence) {
if (Precedence::kPostfix >= parentPrecedence) {
this->write(")");
}
}
@ -1686,7 +1649,7 @@ void MetalCodeGenerator::writeFields(const std::vector<Type::Field>& fields, int
}
void MetalCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
this->writeExpression(value, kTopLevel_Precedence);
this->writeExpression(value, Precedence::kTopLevel);
}
void MetalCodeGenerator::writeName(const String& name) {
@ -1717,7 +1680,7 @@ void MetalCodeGenerator::writeStatement(const Statement& s) {
this->writeBlock(s.as<Block>());
break;
case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().expression(), kTopLevel_Precedence);
this->writeExpression(*s.as<ExpressionStatement>().expression(), Precedence::kTopLevel);
this->write(";");
break;
case Statement::Kind::kReturn:
@ -1779,7 +1742,7 @@ void MetalCodeGenerator::writeBlock(const Block& b) {
void MetalCodeGenerator::writeIfStatement(const IfStatement& stmt) {
this->write("if (");
this->writeExpression(*stmt.test(), kTopLevel_Precedence);
this->writeExpression(*stmt.test(), Precedence::kTopLevel);
this->write(") ");
this->writeStatement(*stmt.ifTrue());
if (stmt.ifFalse()) {
@ -1792,7 +1755,7 @@ void MetalCodeGenerator::writeForStatement(const ForStatement& f) {
// Emit loops of the form 'for(;test;)' as 'while(test)', which is probably how they started
if (!f.initializer() && f.test() && !f.next()) {
this->write("while (");
this->writeExpression(*f.test(), kTopLevel_Precedence);
this->writeExpression(*f.test(), Precedence::kTopLevel);
this->write(") ");
this->writeStatement(*f.statement());
return;
@ -1805,11 +1768,11 @@ void MetalCodeGenerator::writeForStatement(const ForStatement& f) {
this->write("; ");
}
if (f.test()) {
this->writeExpression(*f.test(), kTopLevel_Precedence);
this->writeExpression(*f.test(), Precedence::kTopLevel);
}
this->write("; ");
if (f.next()) {
this->writeExpression(*f.next(), kTopLevel_Precedence);
this->writeExpression(*f.next(), Precedence::kTopLevel);
}
this->write(") ");
this->writeStatement(*f.statement());
@ -1819,19 +1782,19 @@ void MetalCodeGenerator::writeDoStatement(const DoStatement& d) {
this->write("do ");
this->writeStatement(*d.statement());
this->write(" while (");
this->writeExpression(*d.test(), kTopLevel_Precedence);
this->writeExpression(*d.test(), Precedence::kTopLevel);
this->write(");");
}
void MetalCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
this->write("switch (");
this->writeExpression(*s.value(), kTopLevel_Precedence);
this->writeExpression(*s.value(), Precedence::kTopLevel);
this->writeLine(") {");
fIndentation++;
for (const std::unique_ptr<SwitchCase>& c : s.cases()) {
if (c->value()) {
this->write("case ");
this->writeExpression(*c->value(), kTopLevel_Precedence);
this->writeExpression(*c->value(), Precedence::kTopLevel);
this->writeLine(":");
} else {
this->writeLine("default:");
@ -1866,7 +1829,7 @@ void MetalCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
if (r.expression()) {
if (r.expression()->type() == *fContext.fTypes.fHalf4) {
this->write("_out.sk_FragColor = ");
this->writeExpression(*r.expression(), kTopLevel_Precedence);
this->writeExpression(*r.expression(), Precedence::kTopLevel);
this->writeLine(";");
} else {
fErrors.error(r.fOffset, "Metal does not support returning '" +
@ -1880,7 +1843,7 @@ void MetalCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->write("return");
if (r.expression()) {
this->write(" ");
this->writeExpression(*r.expression(), kTopLevel_Precedence);
this->writeExpression(*r.expression(), Precedence::kTopLevel);
}
this->write(";");
}

View File

@ -8,12 +8,14 @@
#ifndef SKSL_METALCODEGENERATOR
#define SKSL_METALCODEGENERATOR
#include <set>
#include <stack>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
@ -54,27 +56,6 @@ public:
static constexpr const char* SAMPLER_SUFFIX = "Smplr";
static constexpr const char* PACKED_PREFIX = "packed_";
enum Precedence {
kParentheses_Precedence = 1,
kPostfix_Precedence = 2,
kPrefix_Precedence = 3,
kMultiplicative_Precedence = 4,
kAdditive_Precedence = 5,
kShift_Precedence = 6,
kRelational_Precedence = 7,
kEquality_Precedence = 8,
kBitwiseAnd_Precedence = 9,
kBitwiseXor_Precedence = 10,
kBitwiseOr_Precedence = 11,
kLogicalAnd_Precedence = 12,
kLogicalXor_Precedence = 13,
kLogicalOr_Precedence = 14,
kTernary_Precedence = 15,
kAssignment_Precedence = 16,
kSequence_Precedence = 17,
kTopLevel_Precedence = kSequence_Precedence
};
MetalCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
@ -87,6 +68,8 @@ public:
bool generateCode() override;
protected:
using Precedence = Operators::Precedence;
typedef int Requirements;
static constexpr Requirements kNo_Requirements = 0;
static constexpr Requirements kInputs_Requirement = 1 << 0;
@ -243,8 +226,6 @@ protected:
void writeSwizzle(const Swizzle& swizzle);
static Precedence GetBinaryPrecedence(Token::Kind op);
void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence);
void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence);

131
src/sksl/SkSLOperators.cpp Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkTypes.h"
#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;
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:
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;
}
}
} // namespace Operators
} // namespace SkSL

51
src/sksl/SkSLOperators.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SKSL_OPERATORS
#define SKSL_OPERATORS
#include "src/sksl/SkSLLexer.h"
namespace SkSL {
namespace Operators {
enum class Precedence {
kParentheses = 1,
kPostfix = 2,
kPrefix = 3,
kMultiplicative = 4,
kAdditive = 5,
kShift = 6,
kRelational = 7,
kEquality = 8,
kBitwiseAnd = 9,
kBitwiseXor = 10,
kBitwiseOr = 11,
kLogicalAnd = 12,
kLogicalXor = 13,
kLogicalOr = 14,
kTernary = 15,
kAssignment = 16,
kSequence = 17,
kTopLevel = kSequence
};
Precedence GetBinaryPrecedence(Token::Kind op);
const char* OperatorName(Token::Kind op);
// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
bool IsAssignment(Token::Kind op);
// Given a compound assignment operator, returns the non-assignment version of the operator
// (e.g. '+=' becomes '+')
Token::Kind RemoveAssignment(Token::Kind op);
} // namespace Operators
} // namespace SkSL
#endif

View File

@ -76,7 +76,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (arguments.size() > 1) {
StringStream buffer;
AutoOutputStream outputToBuffer(this, &buffer);
this->writeExpression(*arguments[1], kSequence_Precedence);
this->writeExpression(*arguments[1], Precedence::kSequence);
fArgs->fFormatArgs[childCallIndex].fCoords = buffer.str();
}
return;
@ -88,7 +88,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
for (const auto& arg : arguments) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
} else {
@ -109,7 +109,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
for (const std::unique_ptr<Expression>& arg : arguments) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
}
@ -168,7 +168,7 @@ void PipelineStageCodeGenerator::writeIfStatement(const IfStatement& stmt) {
this->write("@");
}
this->write("if (");
this->writeExpression(*stmt.test(), kTopLevel_Precedence);
this->writeExpression(*stmt.test(), Precedence::kTopLevel);
this->write(") ");
this->writeStatement(*stmt.ifTrue());
if (stmt.ifFalse()) {
@ -184,7 +184,7 @@ void PipelineStageCodeGenerator::writeReturnStatement(const ReturnStatement& r)
if (fCastReturnsToHalf) {
this->write("half4(");
}
this->writeExpression(*r.expression(), kTopLevel_Precedence);
this->writeExpression(*r.expression(), Precedence::kTopLevel);
if (fCastReturnsToHalf) {
this->write(")");
}
@ -312,21 +312,21 @@ void PipelineStageCodeGenerator::writeConstructor(const Constructor& c,
for (const auto& arg : c.arguments()) {
this->write(separator);
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
this->writeExpression(*arg, Precedence::kSequence);
}
this->write(")");
}
void PipelineStageCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
this->writeExpression(*expr.base(), kPostfix_Precedence);
this->writeExpression(*expr.base(), Precedence::kPostfix);
this->write("[");
this->writeExpression(*expr.index(), kTopLevel_Precedence);
this->writeExpression(*expr.index(), Precedence::kTopLevel);
this->write("]");
}
void PipelineStageCodeGenerator::writeFieldAccess(const FieldAccess& f) {
if (f.ownerKind() == FieldAccess::OwnerKind::kDefault) {
this->writeExpression(*f.base(), kPostfix_Precedence);
this->writeExpression(*f.base(), Precedence::kPostfix);
this->write(".");
}
const Type& baseType = f.base()->type();
@ -334,7 +334,7 @@ void PipelineStageCodeGenerator::writeFieldAccess(const FieldAccess& f) {
}
void PipelineStageCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
this->writeExpression(*swizzle.base(), kPostfix_Precedence);
this->writeExpression(*swizzle.base(), Precedence::kPostfix);
this->write(".");
for (int c : swizzle.components()) {
SkASSERT(c >= 0 && c <= 3);
@ -342,56 +342,19 @@ void PipelineStageCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
}
}
PipelineStageCodeGenerator::Precedence PipelineStageCodeGenerator::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 PipelineStageCodeGenerator::kMultiplicative_Precedence;
case Token::Kind::TK_PLUS: // fall through
case Token::Kind::TK_MINUS: return PipelineStageCodeGenerator::kAdditive_Precedence;
case Token::Kind::TK_SHL: // fall through
case Token::Kind::TK_SHR: return PipelineStageCodeGenerator::kShift_Precedence;
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 PipelineStageCodeGenerator::kRelational_Precedence;
case Token::Kind::TK_EQEQ: // fall through
case Token::Kind::TK_NEQ: return PipelineStageCodeGenerator::kEquality_Precedence;
case Token::Kind::TK_BITWISEAND: return PipelineStageCodeGenerator::kBitwiseAnd_Precedence;
case Token::Kind::TK_BITWISEXOR: return PipelineStageCodeGenerator::kBitwiseXor_Precedence;
case Token::Kind::TK_BITWISEOR: return PipelineStageCodeGenerator::kBitwiseOr_Precedence;
case Token::Kind::TK_LOGICALAND: return PipelineStageCodeGenerator::kLogicalAnd_Precedence;
case Token::Kind::TK_LOGICALXOR: return PipelineStageCodeGenerator::kLogicalXor_Precedence;
case Token::Kind::TK_LOGICALOR: return PipelineStageCodeGenerator::kLogicalOr_Precedence;
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 PipelineStageCodeGenerator::kAssignment_Precedence;
case Token::Kind::TK_COMMA: return PipelineStageCodeGenerator::kSequence_Precedence;
default: SK_ABORT("unsupported binary operator");
}
}
void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Precedence parentPrecedence) {
const Expression& left = *b.left();
const Expression& right = *b.right();
Token::Kind op = b.getOperator();
Precedence precedence = GetBinaryPrecedence(op);
Precedence precedence = Operators::GetBinaryPrecedence(op);
if (precedence >= parentPrecedence) {
this->write("(");
}
this->writeExpression(left, precedence);
this->write(" ");
this->write(Compiler::OperatorName(op));
this->write(Operators::OperatorName(op));
this->write(" ");
this->writeExpression(right, precedence);
if (precedence >= parentPrecedence) {
@ -401,39 +364,39 @@ void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b
void PipelineStageCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
Precedence parentPrecedence) {
if (kTernary_Precedence >= parentPrecedence) {
if (Precedence::kTernary >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*t.test(), kTernary_Precedence);
this->writeExpression(*t.test(), Precedence::kTernary);
this->write(" ? ");
this->writeExpression(*t.ifTrue(), kTernary_Precedence);
this->writeExpression(*t.ifTrue(), Precedence::kTernary);
this->write(" : ");
this->writeExpression(*t.ifFalse(), kTernary_Precedence);
if (kTernary_Precedence >= parentPrecedence) {
this->writeExpression(*t.ifFalse(), Precedence::kTernary);
if (Precedence::kTernary >= parentPrecedence) {
this->write(")");
}
}
void PipelineStageCodeGenerator::writePrefixExpression(const PrefixExpression& p,
Precedence parentPrecedence) {
if (kPrefix_Precedence >= parentPrecedence) {
if (Precedence::kPrefix >= parentPrecedence) {
this->write("(");
}
this->write(Compiler::OperatorName(p.getOperator()));
this->writeExpression(*p.operand(), kPrefix_Precedence);
if (kPrefix_Precedence >= parentPrecedence) {
this->write(Operators::OperatorName(p.getOperator()));
this->writeExpression(*p.operand(), Precedence::kPrefix);
if (Precedence::kPrefix >= parentPrecedence) {
this->write(")");
}
}
void PipelineStageCodeGenerator::writePostfixExpression(const PostfixExpression& p,
Precedence parentPrecedence) {
if (kPostfix_Precedence >= parentPrecedence) {
if (Precedence::kPostfix >= parentPrecedence) {
this->write("(");
}
this->writeExpression(*p.operand(), kPostfix_Precedence);
this->write(Compiler::OperatorName(p.getOperator()));
if (kPostfix_Precedence >= parentPrecedence) {
this->writeExpression(*p.operand(), Precedence::kPostfix);
this->write(Operators::OperatorName(p.getOperator()));
if (Precedence::kPostfix >= parentPrecedence) {
this->write(")");
}
}
@ -528,7 +491,7 @@ void PipelineStageCodeGenerator::writeVarDeclaration(const VarDeclaration& var)
}
if (var.value()) {
this->write(" = ");
this->writeExpression(*var.value(), kTopLevel_Precedence);
this->writeExpression(*var.value(), Precedence::kTopLevel);
}
this->write(";");
}
@ -545,7 +508,7 @@ void PipelineStageCodeGenerator::writeStatement(const Statement& s) {
this->write("continue;");
break;
case Statement::Kind::kExpression:
this->writeExpression(*s.as<ExpressionStatement>().expression(), kTopLevel_Precedence);
this->writeExpression(*s.as<ExpressionStatement>().expression(), Precedence::kTopLevel);
this->write(";");
break;
case Statement::Kind::kFor:
@ -601,11 +564,11 @@ void PipelineStageCodeGenerator::writeForStatement(const ForStatement& f) {
this->write("; ");
}
if (f.test()) {
this->writeExpression(*f.test(), kTopLevel_Precedence);
this->writeExpression(*f.test(), Precedence::kTopLevel);
}
this->write("; ");
if (f.next()) {
this->writeExpression(*f.next(), kTopLevel_Precedence);
this->writeExpression(*f.next(), Precedence::kTopLevel);
}
this->write(") ");
this->writeStatement(*f.statement());

View File

@ -9,6 +9,7 @@
#define SKSL_PIPELINESTAGECODEGENERATOR
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLConstructor.h"
@ -34,29 +35,10 @@
namespace SkSL {
struct PipelineStageArgs;
class PipelineStageCodeGenerator : public CodeGenerator {
public:
enum Precedence {
kParentheses_Precedence = 1,
kPostfix_Precedence = 2,
kPrefix_Precedence = 3,
kMultiplicative_Precedence = 4,
kAdditive_Precedence = 5,
kShift_Precedence = 6,
kRelational_Precedence = 7,
kEquality_Precedence = 8,
kBitwiseAnd_Precedence = 9,
kBitwiseXor_Precedence = 10,
kBitwiseOr_Precedence = 11,
kLogicalAnd_Precedence = 12,
kLogicalXor_Precedence = 13,
kLogicalOr_Precedence = 14,
kTernary_Precedence = 15,
kAssignment_Precedence = 16,
kSequence_Precedence = 17,
kTopLevel_Precedence = kSequence_Precedence
};
PipelineStageCodeGenerator(const Context* context, const Program* program,
ErrorReporter* errors, OutputStream* out,
PipelineStageArgs* outArgs);
@ -64,6 +46,8 @@ public:
bool generateCode() override;
private:
using Precedence = Operators::Precedence;
void write(const char* s);
void writeLine(const char* s = nullptr);
void write(const String& s);
@ -78,8 +62,6 @@ private:
void writeVarDeclaration(const VarDeclaration& var);
static Precedence GetBinaryPrecedence(Token::Kind op);
void writeExpression(const Expression& expr, Precedence parentPrecedence);
void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c, Precedence parentPrecedence);

View File

@ -10,6 +10,7 @@
#include "src/sksl/GLSL.std.450.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLExpressionStatement.h"
#include "src/sksl/ir/SkSLExtension.h"
@ -2480,7 +2481,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
std::unique_ptr<LValue> lvalue;
SpvId lhs;
if (Compiler::IsAssignment(op)) {
if (Operators::IsAssignment(op)) {
lvalue = this->getLValue(left, out);
lhs = lvalue->load(out);
} else {
@ -2488,7 +2489,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, Compiler::RemoveAssignment(op),
SpvId result = this->writeBinaryExpression(left.type(), lhs, Operators::RemoveAssignment(op),
right.type(), rhs, b.type(), out);
if (lvalue) {
lvalue->store(result, out);

View File

@ -8,6 +8,8 @@
#include "include/private/SkTArray.h"
#include "include/private/SkTPin.h"
#include "src/sksl/SkSLCodeGenerator.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/SkSLVMGenerator.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBlock.h"
@ -527,9 +529,9 @@ 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 = Compiler::IsAssignment(op);
bool isAssignment = Operators::IsAssignment(op);
if (isAssignment) {
op = Compiler::RemoveAssignment(op);
op = Operators::RemoveAssignment(op);
}
Type::NumberKind nk = base_number_kind(lType);

View File

@ -8,10 +8,10 @@
#ifndef SKSL_BINARYEXPRESSION
#define SKSL_BINARYEXPRESSION
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
@ -56,7 +56,7 @@ public:
, fOperator(op)
, fRight(std::move(right)) {
// If we are assigning to a VariableReference, ensure that it is set to Write or ReadWrite
SkASSERT(!Compiler::IsAssignment(op) || check_ref(*this->left()));
SkASSERT(!Operators::IsAssignment(op) || check_ref(*this->left()));
}
std::unique_ptr<Expression>& left() {
@ -90,7 +90,7 @@ public:
}
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && Compiler::IsAssignment(this->getOperator())) {
if (property == Property::kSideEffects && Operators::IsAssignment(this->getOperator())) {
return true;
}
return this->left()->hasProperty(property) || this->right()->hasProperty(property);
@ -106,7 +106,7 @@ public:
String description() const override {
return "(" + this->left()->description() + " " +
Compiler::OperatorName(this->getOperator()) + " " + this->right()->description() +
Operators::OperatorName(this->getOperator()) + " " + this->right()->description() +
")";
}

View File

@ -8,8 +8,8 @@
#ifndef SKSL_POSTFIXEXPRESSION
#define SKSL_POSTFIXEXPRESSION
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLExpression.h"
namespace SkSL {
@ -51,7 +51,7 @@ public:
}
String description() const override {
return this->operand()->description() + Compiler::OperatorName(this->getOperator());
return this->operand()->description() + Operators::OperatorName(this->getOperator());
}
private:

View File

@ -8,9 +8,9 @@
#ifndef SKSL_PREFIXEXPRESSION
#define SKSL_PREFIXEXPRESSION
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/SkSLOperators.h"
#include "src/sksl/ir/SkSLExpression.h"
namespace SkSL {
@ -57,7 +57,7 @@ public:
}
String description() const override {
return Compiler::OperatorName(this->getOperator()) + this->operand()->description();
return Operators::OperatorName(this->getOperator()) + this->operand()->description();
}
private: