blob: ea89591afdeb633008b58a28869c9683be76ef2c [file] [log] [blame]
/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/sksl/dsl/DSLExpression.h"
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/dsl/DSLVar.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLFloatLiteral.h"
#include "src/sksl/ir/SkSLIntLiteral.h"
namespace SkSL {
namespace dsl {
static std::unique_ptr<SkSL::Expression> check(std::unique_ptr<SkSL::Expression> expr) {
if (expr == nullptr) {
if (DSLWriter::Compiler().errorCount()) {
DSLWriter::ReportError(DSLWriter::Compiler().errorText(/*showCount=*/false).c_str());
}
}
return expr;
}
DSLExpression::DSLExpression() {}
DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression)
: fExpression(check(std::move(expression))) {}
DSLExpression::DSLExpression(float value)
: fExpression(std::make_unique<SkSL::FloatLiteral>(DSLWriter::Context(),
/*offset=*/-1,
value)) {}
DSLExpression::DSLExpression(int value)
: fExpression(std::make_unique<SkSL::IntLiteral>(DSLWriter::Context(),
/*offset=*/-1,
value)) {}
DSLExpression::DSLExpression(bool value)
: fExpression(std::make_unique<SkSL::BoolLiteral>(DSLWriter::Context(),
/*offset=*/-1,
value)) {}
DSLExpression::DSLExpression(const DSLVar& var)
: fExpression(std::make_unique<SkSL::VariableReference>(
/*offset=*/-1,
var.var(),
SkSL::VariableReference::RefKind::kRead)) {}
DSLExpression::~DSLExpression() {
SkASSERTF(fExpression == nullptr,
"Expression destroyed without being incorporated into output tree");
}
std::unique_ptr<SkSL::Expression> DSLExpression::release() {
return std::move(fExpression);
}
DSLExpression DSLExpression::operator=(DSLExpression&& right) {
SkSL::IRGenerator& ir = DSLWriter::IRGenerator();
return DSLExpression(check(ir.convertBinaryExpression(this->release(), SkSL::Token::Kind::TK_EQ,
right.release())));
}
#define OP(op, token) \
DSLExpression operator op(DSLExpression left, DSLExpression right) { \
SkSL::IRGenerator& ir = DSLWriter::IRGenerator(); \
return DSLExpression(check(ir.convertBinaryExpression(left.release(), SkSL::Token::Kind::token,\
right.release()))); \
}
#define RWOP(op, token) \
OP(op, token) \
DSLExpression operator op(DSLVar& left, DSLExpression right) { \
SkSL::IRGenerator& ir = DSLWriter::IRGenerator(); \
return DSLExpression(check(ir.convertBinaryExpression( \
std::make_unique<SkSL::VariableReference>(/*offset=*/-1, \
left.var(), \
SkSL::VariableReference::RefKind::kReadWrite), \
SkSL::Token::Kind::token, right.release()))); \
}
#define PREFIXOP(op, token) \
DSLExpression operator op(DSLExpression expr) { \
SkSL::IRGenerator& ir = DSLWriter::IRGenerator(); \
return DSLExpression(check(ir.convertPrefixExpression(SkSL::Token::Kind::token, \
expr.release()))); \
}
#define POSTFIXOP(op, token) \
DSLExpression operator op(DSLExpression expr, int) { \
SkSL::IRGenerator& ir = DSLWriter::IRGenerator(); \
return DSLExpression(check(ir.convertPostfixExpression(expr.release(), \
SkSL::Token::Kind::token))); \
}
OP(+, TK_PLUS)
RWOP(+=, TK_PLUSEQ)
OP(-, TK_MINUS)
RWOP(-=, TK_MINUSEQ)
OP(*, TK_STAR)
RWOP(*=, TK_STAREQ)
OP(/, TK_SLASH)
RWOP(/=, TK_SLASHEQ)
OP(%, TK_PERCENT)
RWOP(%=, TK_PERCENTEQ)
OP(<<, TK_SHL)
RWOP(<<=, TK_SHLEQ)
OP(>>, TK_SHR)
RWOP(>>=, TK_SHREQ)
OP(&&, TK_LOGICALAND)
OP(||, TK_LOGICALOR)
OP(&, TK_BITWISEAND)
RWOP(&=, TK_BITWISEANDEQ)
OP(|, TK_BITWISEOR)
RWOP(|=, TK_BITWISEOREQ)
OP(^, TK_BITWISEXOR)
RWOP(^=, TK_BITWISEXOREQ)
OP(==, TK_EQEQ)
OP(!=, TK_NEQ)
OP(>, TK_GT)
OP(<, TK_LT)
OP(>=, TK_GTEQ)
OP(<=, TK_LTEQ)
PREFIXOP(!, TK_LOGICALNOT)
PREFIXOP(~, TK_BITWISENOT)
PREFIXOP(++, TK_PLUSPLUS)
POSTFIXOP(++, TK_PLUSPLUS)
PREFIXOP(--, TK_MINUSMINUS)
POSTFIXOP(--, TK_MINUSMINUS)
DSLExpression operator,(DSLExpression left, DSLExpression right) {
SkSL::IRGenerator& ir = DSLWriter::IRGenerator();
return DSLExpression(check(ir.convertBinaryExpression(left.release(),
SkSL::Token::Kind::TK_COMMA,
right.release())));
}
std::unique_ptr<SkSL::Expression> DSLExpression::coerceAndRelease(const SkSL::Type& type) {
// tripping this assert means we had an error occur somewhere else in DSL construction that
// wasn't caught where it should have been
SkASSERTF(!DSLWriter::Compiler().errorCount(), "Unexpected SkSL DSL error: %s",
DSLWriter::Compiler().errorText().c_str());
return check(DSLWriter::IRGenerator().coerce(this->release(), type));
}
static SkSL::String swizzle_component(SwizzleComponent c) {
switch (c) {
case R:
return "r";
case G:
return "g";
case B:
return "b";
case A:
return "a";
case X:
return "x";
case Y:
return "y";
case Z:
return "z";
case W:
return "w";
case ZERO:
return "0";
case ONE:
return "1";
default:
SkUNREACHABLE;
}
}
DSLExpression Swizzle(DSLExpression base, SwizzleComponent a) {
return DSLExpression(check(DSLWriter::IRGenerator().convertSwizzle(base.release(),
swizzle_component(a))));
}
DSLExpression Swizzle(DSLExpression base, SwizzleComponent a, SwizzleComponent b) {
return DSLExpression(check(DSLWriter::IRGenerator().convertSwizzle(base.release(),
swizzle_component(a) +
swizzle_component(b))));
}
DSLExpression Swizzle(DSLExpression base, SwizzleComponent a, SwizzleComponent b,
SwizzleComponent c) {
return DSLExpression(check(DSLWriter::IRGenerator().convertSwizzle(base.release(),
swizzle_component(a) +
swizzle_component(b) +
swizzle_component(c))));
}
DSLExpression Swizzle(DSLExpression base, SwizzleComponent a, SwizzleComponent b,
SwizzleComponent c, SwizzleComponent d) {
return DSLExpression(check(DSLWriter::IRGenerator().convertSwizzle(base.release(),
swizzle_component(a) +
swizzle_component(b) +
swizzle_component(c) +
swizzle_component(d))));
}
} // namespace dsl
} // namespace SkSL