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:
parent
9c00b794a7
commit
001850105e
@ -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",
|
||||
|
@ -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() + ";";
|
||||
|
@ -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"
|
||||
|
@ -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));
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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(";");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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(";");
|
||||
}
|
||||
|
@ -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
131
src/sksl/SkSLOperators.cpp
Normal 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
51
src/sksl/SkSLOperators.h
Normal 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
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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() +
|
||||
")";
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user