blob: 42a5a4f5543bfa117c175a51fe484c12b3d88866 [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 "include/sksl/DSLExpression.h"
#include "include/core/SkTypes.h"
#include "include/private/SkSLDefines.h"
#include "include/sksl/DSLCore.h"
#include "include/sksl/DSLStatement.h"
#include "include/sksl/DSLType.h"
#include "include/sksl/DSLVar.h"
#include "include/sksl/DSLWrapper.h"
#include "include/sksl/SkSLOperator.h"
#include "src/sksl/SkSLThreadContext.h"
#include "src/sksl/dsl/priv/DSLWriter.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLFieldAccess.h"
#include "src/sksl/ir/SkSLFunctionCall.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLLiteral.h"
#include "src/sksl/ir/SkSLPoison.h"
#include "src/sksl/ir/SkSLPostfixExpression.h"
#include "src/sksl/ir/SkSLPrefixExpression.h"
#include "src/sksl/ir/SkSLVariableReference.h"
#include <math.h>
#include <utility>
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/glsl/GrGLSLFragmentShaderBuilder.h"
#endif
namespace SkSL {
namespace dsl {
DSLExpression::DSLExpression() {}
DSLExpression::DSLExpression(DSLExpression&& other)
: fExpression(std::move(other.fExpression)) {}
DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression)
: fExpression(std::move(expression)) {
SkASSERT(this->hasValue());
}
DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression, Position pos)
: fExpression(expression ? std::move(expression)
: SkSL::Poison::Make(pos, ThreadContext::Context())) {
ThreadContext::ReportErrors(pos);
SkASSERTF(this->position() == pos, "expected expression position (%d-%d), but received (%d-%d)",
pos.startOffset(), pos.endOffset(), this->position().startOffset(),
this->position().endOffset());
}
DSLExpression::DSLExpression(float value, Position pos)
: fExpression(SkSL::Literal::MakeFloat(ThreadContext::Context(),
pos,
value)) {
if (!isfinite(value)) {
if (isinf(value)) {
ThreadContext::ReportError("floating point value is infinite");
} else if (isnan(value)) {
ThreadContext::ReportError("floating point value is NaN");
}
}
}
DSLExpression::DSLExpression(int value, Position pos)
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos,
value)) {}
DSLExpression::DSLExpression(int64_t value, Position pos)
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos,
value)) {}
DSLExpression::DSLExpression(unsigned int value, Position pos)
: fExpression(SkSL::Literal::MakeInt(ThreadContext::Context(),
pos,
value)) {}
DSLExpression::DSLExpression(bool value, Position pos)
: fExpression(SkSL::Literal::MakeBool(ThreadContext::Context(),
pos,
value)) {}
DSLExpression::DSLExpression(DSLVarBase& var, Position pos) {
fExpression = std::make_unique<SkSL::VariableReference>(pos, DSLWriter::Var(var),
SkSL::VariableReference::RefKind::kRead);
}
DSLExpression::DSLExpression(DSLVarBase&& var, Position pos)
: DSLExpression(var) {}
DSLExpression::DSLExpression(DSLPossibleExpression expr, Position pos) {
ThreadContext::ReportErrors(pos);
if (expr.valid()) {
fExpression = std::move(expr.fExpression);
if (!this->position().valid()) {
fExpression->fPosition = pos;
}
} else {
fExpression = SkSL::Poison::Make(pos, ThreadContext::Context());
}
}
DSLExpression DSLExpression::Poison(Position pos) {
return DSLExpression(SkSL::Poison::Make(pos, ThreadContext::Context()));
}
DSLExpression::~DSLExpression() {
#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
if (fExpression && ThreadContext::InFragmentProcessor()) {
ThreadContext::CurrentEmitArgs()->fFragBuilder->codeAppend(
DSLStatement(this->release()).release());
return;
}
#endif
SkASSERTF(!fExpression || !ThreadContext::Settings().fAssertDSLObjectsReleased,
"Expression destroyed without being incorporated into program (see "
"ProgramSettings::fAssertDSLObjectsReleased)");
}
bool DSLExpression::isValid() const {
return this->hasValue() && !fExpression->is<SkSL::Poison>();
}
void DSLExpression::swap(DSLExpression& other) {
std::swap(fExpression, other.fExpression);
}
std::unique_ptr<SkSL::Expression> DSLExpression::release() {
SkASSERT(this->hasValue());
return std::move(fExpression);
}
std::unique_ptr<SkSL::Expression> DSLExpression::releaseIfPossible() {
return std::move(fExpression);
}
DSLType DSLExpression::type() const {
if (!this->hasValue()) {
return kVoid_Type;
}
return &fExpression->type();
}
std::string DSLExpression::description() const {
SkASSERT(this->hasValue());
return fExpression->description();
}
Position DSLExpression::position() const {
SkASSERT(this->hasValue());
return fExpression->fPosition;
}
void DSLExpression::setPosition(Position pos) {
SkASSERT(this->hasValue());
fExpression->fPosition = pos;
}
DSLExpression DSLExpression::x(Position pos) {
return Swizzle(std::move(*this), X, pos);
}
DSLExpression DSLExpression::y(Position pos) {
return Swizzle(std::move(*this), Y, pos);
}
DSLExpression DSLExpression::z(Position pos) {
return Swizzle(std::move(*this), Z, pos);
}
DSLExpression DSLExpression::w(Position pos) {
return Swizzle(std::move(*this), W, pos);
}
DSLExpression DSLExpression::r(Position pos) {
return Swizzle(std::move(*this), R, pos);
}
DSLExpression DSLExpression::g(Position pos) {
return Swizzle(std::move(*this), G, pos);
}
DSLExpression DSLExpression::b(Position pos) {
return Swizzle(std::move(*this), B, pos);
}
DSLExpression DSLExpression::a(Position pos) {
return Swizzle(std::move(*this), A, pos);
}
DSLExpression DSLExpression::field(std::string_view name, Position pos) {
return DSLExpression(FieldAccess::Convert(ThreadContext::Context(), pos,
*ThreadContext::SymbolTable(), this->release(), name), pos);
}
DSLPossibleExpression DSLExpression::operator=(DSLExpression right) {
Position pos = this->position().rangeThrough(right.position());
return BinaryExpression::Convert(ThreadContext::Context(), pos, this->release(),
SkSL::Operator::Kind::EQ, right.release());
}
DSLPossibleExpression DSLExpression::operator[](DSLExpression right) {
Position pos = this->position().rangeThrough(right.position());
return IndexExpression::Convert(ThreadContext::Context(), *ThreadContext::SymbolTable(), pos,
this->release(), right.release());
}
DSLExpression DSLExpression::index(DSLExpression index, Position pos) {
std::unique_ptr<SkSL::Expression> result = IndexExpression::Convert(ThreadContext::Context(),
*ThreadContext::SymbolTable(), pos, this->release(), index.release());
return DSLExpression(std::move(result), pos);
}
DSLPossibleExpression DSLExpression::operator()(SkTArray<DSLWrapper<DSLExpression>> args,
Position pos) {
ExpressionArray converted;
converted.reserve_back(args.count());
for (DSLWrapper<DSLExpression>& arg : args) {
converted.push_back(arg->release());
}
return (*this)(std::move(converted), pos);
}
DSLPossibleExpression DSLExpression::operator()(ExpressionArray args, Position pos) {
return SkSL::FunctionCall::Convert(ThreadContext::Context(), pos, this->release(),
std::move(args));
}
DSLExpression DSLExpression::prefix(Operator::Kind op, Position pos) {
std::unique_ptr<SkSL::Expression> result = PrefixExpression::Convert(ThreadContext::Context(),
pos, op, this->release());
return DSLExpression(std::move(result), pos);
}
DSLExpression DSLExpression::postfix(Operator::Kind op, Position pos) {
std::unique_ptr<SkSL::Expression> result = PostfixExpression::Convert(ThreadContext::Context(),
pos, this->release(), op);
return DSLExpression(std::move(result), pos);
}
DSLExpression DSLExpression::binary(Operator::Kind op, DSLExpression right, Position pos) {
std::unique_ptr<SkSL::Expression> result = BinaryExpression::Convert(ThreadContext::Context(),
pos, this->release(), op, right.release());
return DSLExpression(std::move(result), pos);
}
#define OP(op, token) \
DSLPossibleExpression operator op(DSLExpression left, DSLExpression right) { \
return BinaryExpression::Convert(ThreadContext::Context(), Position(), left.release(), \
Operator::Kind::token, right.release()); \
}
#define PREFIXOP(op, token) \
DSLPossibleExpression operator op(DSLExpression expr) { \
return PrefixExpression::Convert(ThreadContext::Context(), Position(), Operator::Kind::token, \
expr.release()); \
}
#define POSTFIXOP(op, token) \
DSLPossibleExpression operator op(DSLExpression expr, int) { \
return PostfixExpression::Convert(ThreadContext::Context(), Position(), expr.release(), \
Operator::Kind::token); \
}
OP(+, PLUS)
OP(+=, PLUSEQ)
OP(-, MINUS)
OP(-=, MINUSEQ)
OP(*, STAR)
OP(*=, STAREQ)
OP(/, SLASH)
OP(/=, SLASHEQ)
OP(%, PERCENT)
OP(%=, PERCENTEQ)
OP(<<, SHL)
OP(<<=, SHLEQ)
OP(>>, SHR)
OP(>>=, SHREQ)
OP(&&, LOGICALAND)
OP(||, LOGICALOR)
OP(&, BITWISEAND)
OP(&=, BITWISEANDEQ)
OP(|, BITWISEOR)
OP(|=, BITWISEOREQ)
OP(^, BITWISEXOR)
OP(^=, BITWISEXOREQ)
DSLPossibleExpression LogicalXor(DSLExpression left, DSLExpression right) {
return BinaryExpression::Convert(ThreadContext::Context(), Position(), left.release(),
SkSL::Operator::Kind::LOGICALXOR, right.release());
}
OP(==, EQEQ)
OP(!=, NEQ)
OP(>, GT)
OP(<, LT)
OP(>=, GTEQ)
OP(<=, LTEQ)
PREFIXOP(+, PLUS)
PREFIXOP(-, MINUS)
PREFIXOP(!, LOGICALNOT)
PREFIXOP(~, BITWISENOT)
PREFIXOP(++, PLUSPLUS)
POSTFIXOP(++, PLUSPLUS)
PREFIXOP(--, MINUSMINUS)
POSTFIXOP(--, MINUSMINUS)
DSLPossibleExpression operator,(DSLExpression left, DSLExpression right) {
return BinaryExpression::Convert(ThreadContext::Context(), Position(), left.release(),
SkSL::Operator::Kind::COMMA, right.release());
}
DSLPossibleExpression operator,(DSLPossibleExpression left, DSLExpression right) {
return BinaryExpression::Convert(ThreadContext::Context(), Position(),
DSLExpression(std::move(left)).release(), SkSL::Operator::Kind::COMMA, right.release());
}
DSLPossibleExpression operator,(DSLExpression left, DSLPossibleExpression right) {
return BinaryExpression::Convert(ThreadContext::Context(), Position(), left.release(),
SkSL::Operator::Kind::COMMA, DSLExpression(std::move(right)).release());
}
DSLPossibleExpression operator,(DSLPossibleExpression left, DSLPossibleExpression right) {
return BinaryExpression::Convert(ThreadContext::Context(), Position(),
DSLExpression(std::move(left)).release(), SkSL::Operator::Kind::COMMA,
DSLExpression(std::move(right)).release());
}
DSLPossibleExpression::DSLPossibleExpression(std::unique_ptr<SkSL::Expression> expr)
: fExpression(std::move(expr)) {}
DSLPossibleExpression::DSLPossibleExpression(DSLPossibleExpression&& other)
: fExpression(std::move(other.fExpression)) {}
DSLPossibleExpression::~DSLPossibleExpression() {
if (fExpression) {
// this handles incorporating the expression into the output tree
DSLExpression(std::move(fExpression));
}
}
void DSLPossibleExpression::reportErrors(Position pos) {
SkASSERT(!this->valid());
ThreadContext::ReportErrors(pos);
}
DSLType DSLPossibleExpression::type() const {
if (!this->valid()) {
return kVoid_Type;
}
return &fExpression->type();
}
std::string DSLPossibleExpression::description() const {
SkASSERT(this->valid());
return fExpression->description();
}
Position DSLPossibleExpression::position() const {
SkASSERT(this->valid());
return fExpression->fPosition;
}
DSLExpression DSLPossibleExpression::x(Position pos) {
return DSLExpression(this->release()).x(pos);
}
DSLExpression DSLPossibleExpression::y(Position pos) {
return DSLExpression(this->release()).y(pos);
}
DSLExpression DSLPossibleExpression::z(Position pos) {
return DSLExpression(this->release()).z(pos);
}
DSLExpression DSLPossibleExpression::w(Position pos) {
return DSLExpression(this->release()).w(pos);
}
DSLExpression DSLPossibleExpression::r(Position pos) {
return DSLExpression(this->release()).r(pos);
}
DSLExpression DSLPossibleExpression::g(Position pos) {
return DSLExpression(this->release()).g(pos);
}
DSLExpression DSLPossibleExpression::b(Position pos) {
return DSLExpression(this->release()).b(pos);
}
DSLExpression DSLPossibleExpression::a(Position pos) {
return DSLExpression(this->release()).a(pos);
}
DSLExpression DSLPossibleExpression::field(std::string_view name, Position pos) {
return DSLExpression(this->release()).field(name, pos);
}
DSLPossibleExpression DSLPossibleExpression::operator=(DSLExpression expr) {
return DSLExpression(this->release()) = std::move(expr);
}
DSLPossibleExpression DSLPossibleExpression::operator=(int expr) {
return this->operator=(DSLExpression(expr));
}
DSLPossibleExpression DSLPossibleExpression::operator=(float expr) {
return this->operator=(DSLExpression(expr));
}
DSLPossibleExpression DSLPossibleExpression::operator=(double expr) {
return this->operator=(DSLExpression(expr));
}
DSLPossibleExpression DSLPossibleExpression::operator[](DSLExpression index) {
return DSLExpression(this->release())[std::move(index)];
}
DSLPossibleExpression DSLPossibleExpression::operator()(SkTArray<DSLWrapper<DSLExpression>> args,
Position pos) {
return DSLExpression(this->release())(std::move(args), pos);
}
DSLPossibleExpression DSLPossibleExpression::operator()(ExpressionArray args, Position pos) {
return DSLExpression(this->release())(std::move(args), pos);
}
DSLPossibleExpression DSLPossibleExpression::operator++() {
return ++DSLExpression(this->release());
}
DSLPossibleExpression DSLPossibleExpression::operator++(int) {
return DSLExpression(this->release())++;
}
DSLPossibleExpression DSLPossibleExpression::operator--() {
return --DSLExpression(this->release());
}
DSLPossibleExpression DSLPossibleExpression::operator--(int) {
return DSLExpression(this->release())--;
}
std::unique_ptr<SkSL::Expression> DSLPossibleExpression::release(Position pos) {
return DSLExpression(std::move(*this), pos).release();
}
} // namespace dsl
} // namespace SkSL