| /* |
| * 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/sksl/DSLCore.h" |
| #include "include/sksl/DSLVar.h" |
| #include "src/sksl/SkSLCompiler.h" |
| #include "src/sksl/SkSLIRGenerator.h" |
| #include "src/sksl/dsl/priv/DSLWriter.h" |
| #include "src/sksl/ir/SkSLBinaryExpression.h" |
| #include "src/sksl/ir/SkSLLiteral.h" |
| #include "src/sksl/ir/SkSLPoison.h" |
| |
| #include "math.h" |
| |
| #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
| #include "src/gpu/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(float value, PositionInfo pos) |
| : fExpression(SkSL::Literal::MakeFloat(DSLWriter::Context(), |
| pos.offset(), |
| value)) { |
| if (!isfinite(value)) { |
| if (isinf(value)) { |
| DSLWriter::ReportError("floating point value is infinite"); |
| } else if (isnan(value)) { |
| DSLWriter::ReportError("floating point value is NaN"); |
| } |
| } |
| } |
| |
| DSLExpression::DSLExpression(int value, PositionInfo pos) |
| : fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(), |
| pos.offset(), |
| value)) {} |
| |
| DSLExpression::DSLExpression(int64_t value, PositionInfo pos) |
| : fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(), |
| pos.offset(), |
| value)) {} |
| |
| DSLExpression::DSLExpression(unsigned int value, PositionInfo pos) |
| : fExpression(SkSL::Literal::MakeInt(DSLWriter::Context(), |
| pos.offset(), |
| value)) {} |
| |
| DSLExpression::DSLExpression(bool value, PositionInfo pos) |
| : fExpression(SkSL::Literal::MakeBool(DSLWriter::Context(), |
| pos.offset(), |
| value)) {} |
| |
| DSLExpression::DSLExpression(DSLVarBase& var, PositionInfo pos) { |
| fExpression = std::make_unique<SkSL::VariableReference>(pos.offset(), DSLWriter::Var(var), |
| SkSL::VariableReference::RefKind::kRead); |
| } |
| |
| DSLExpression::DSLExpression(DSLVarBase&& var, PositionInfo pos) |
| : DSLExpression(var) {} |
| |
| DSLExpression::DSLExpression(DSLPossibleExpression expr, PositionInfo pos) { |
| DSLWriter::ReportErrors(pos); |
| if (expr.valid()) { |
| fExpression = std::move(expr.fExpression); |
| } else { |
| fExpression = SkSL::Poison::Make(pos.offset(), DSLWriter::Context()); |
| } |
| } |
| |
| DSLExpression DSLExpression::Poison(PositionInfo pos) { |
| return DSLExpression(SkSL::Poison::Make(pos.offset(), DSLWriter::Context())); |
| } |
| |
| DSLExpression::~DSLExpression() { |
| #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
| if (fExpression && DSLWriter::InFragmentProcessor()) { |
| DSLWriter::CurrentEmitArgs()->fFragBuilder->codeAppend( |
| DSLStatement(this->release()).release()); |
| return; |
| } |
| #endif |
| SkASSERTF(!fExpression || !DSLWriter::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() { |
| if (!this->hasValue()) { |
| return kVoid_Type; |
| } |
| return &fExpression->type(); |
| } |
| |
| DSLExpression DSLExpression::x(PositionInfo pos) { |
| return Swizzle(std::move(*this), X, pos); |
| } |
| |
| DSLExpression DSLExpression::y(PositionInfo pos) { |
| return Swizzle(std::move(*this), Y, pos); |
| } |
| |
| DSLExpression DSLExpression::z(PositionInfo pos) { |
| return Swizzle(std::move(*this), Z, pos); |
| } |
| |
| DSLExpression DSLExpression::w(PositionInfo pos) { |
| return Swizzle(std::move(*this), W, pos); |
| } |
| |
| DSLExpression DSLExpression::r(PositionInfo pos) { |
| return Swizzle(std::move(*this), R, pos); |
| } |
| |
| DSLExpression DSLExpression::g(PositionInfo pos) { |
| return Swizzle(std::move(*this), G, pos); |
| } |
| |
| DSLExpression DSLExpression::b(PositionInfo pos) { |
| return Swizzle(std::move(*this), B, pos); |
| } |
| |
| DSLExpression DSLExpression::a(PositionInfo pos) { |
| return Swizzle(std::move(*this), A, pos); |
| } |
| |
| DSLExpression DSLExpression::field(skstd::string_view name, PositionInfo pos) { |
| return DSLExpression(DSLWriter::ConvertField(this->release(), name), pos); |
| } |
| |
| DSLPossibleExpression DSLExpression::operator=(DSLExpression right) { |
| return DSLWriter::ConvertBinary(this->release(), SkSL::Token::Kind::TK_EQ, right.release()); |
| } |
| |
| DSLPossibleExpression DSLExpression::operator[](DSLExpression right) { |
| return DSLWriter::ConvertIndex(this->release(), right.release()); |
| } |
| |
| DSLPossibleExpression DSLExpression::operator()(SkTArray<DSLWrapper<DSLExpression>> args, |
| PositionInfo pos) { |
| ExpressionArray converted; |
| converted.reserve_back(args.count()); |
| for (DSLWrapper<DSLExpression>& arg : args) { |
| converted.push_back(arg->release()); |
| } |
| return DSLWriter::Call(this->release(), std::move(converted), pos); |
| } |
| |
| DSLPossibleExpression DSLExpression::operator()(ExpressionArray args, PositionInfo pos) { |
| return DSLWriter::Call(this->release(), std::move(args), pos); |
| } |
| |
| #define OP(op, token) \ |
| DSLPossibleExpression operator op(DSLExpression left, DSLExpression right) { \ |
| return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::token, right.release()); \ |
| } |
| |
| #define PREFIXOP(op, token) \ |
| DSLPossibleExpression operator op(DSLExpression expr) { \ |
| return DSLWriter::ConvertPrefix(SkSL::Token::Kind::token, expr.release()); \ |
| } |
| |
| #define POSTFIXOP(op, token) \ |
| DSLPossibleExpression operator op(DSLExpression expr, int) { \ |
| return DSLWriter::ConvertPostfix(expr.release(), SkSL::Token::Kind::token); \ |
| } |
| |
| OP(+, TK_PLUS) |
| OP(+=, TK_PLUSEQ) |
| OP(-, TK_MINUS) |
| OP(-=, TK_MINUSEQ) |
| OP(*, TK_STAR) |
| OP(*=, TK_STAREQ) |
| OP(/, TK_SLASH) |
| OP(/=, TK_SLASHEQ) |
| OP(%, TK_PERCENT) |
| OP(%=, TK_PERCENTEQ) |
| OP(<<, TK_SHL) |
| OP(<<=, TK_SHLEQ) |
| OP(>>, TK_SHR) |
| OP(>>=, TK_SHREQ) |
| OP(&&, TK_LOGICALAND) |
| OP(||, TK_LOGICALOR) |
| OP(&, TK_BITWISEAND) |
| OP(&=, TK_BITWISEANDEQ) |
| OP(|, TK_BITWISEOR) |
| OP(|=, TK_BITWISEOREQ) |
| OP(^, TK_BITWISEXOR) |
| OP(^=, TK_BITWISEXOREQ) |
| DSLPossibleExpression LogicalXor(DSLExpression left, DSLExpression right) { |
| return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::TK_LOGICALXOR, |
| right.release()); |
| } |
| OP(==, TK_EQEQ) |
| OP(!=, TK_NEQ) |
| OP(>, TK_GT) |
| OP(<, TK_LT) |
| OP(>=, TK_GTEQ) |
| OP(<=, TK_LTEQ) |
| |
| PREFIXOP(+, TK_PLUS) |
| PREFIXOP(-, TK_MINUS) |
| PREFIXOP(!, TK_LOGICALNOT) |
| PREFIXOP(~, TK_BITWISENOT) |
| PREFIXOP(++, TK_PLUSPLUS) |
| POSTFIXOP(++, TK_PLUSPLUS) |
| PREFIXOP(--, TK_MINUSMINUS) |
| POSTFIXOP(--, TK_MINUSMINUS) |
| |
| DSLPossibleExpression operator,(DSLExpression left, DSLExpression right) { |
| return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::TK_COMMA, |
| right.release()); |
| } |
| |
| DSLPossibleExpression operator,(DSLPossibleExpression left, DSLExpression right) { |
| return DSLWriter::ConvertBinary(DSLExpression(std::move(left)).release(), |
| SkSL::Token::Kind::TK_COMMA, right.release()); |
| } |
| |
| DSLPossibleExpression operator,(DSLExpression left, DSLPossibleExpression right) { |
| return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::TK_COMMA, |
| DSLExpression(std::move(right)).release()); |
| } |
| |
| DSLPossibleExpression operator,(DSLPossibleExpression left, DSLPossibleExpression right) { |
| return DSLWriter::ConvertBinary(DSLExpression(std::move(left)).release(), |
| SkSL::Token::Kind::TK_COMMA, |
| DSLExpression(std::move(right)).release()); |
| } |
| |
| std::unique_ptr<SkSL::Expression> DSLExpression::coerceAndRelease(const SkSL::Type& type) { |
| return DSLWriter::Coerce(this->release(), type).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(PositionInfo pos) { |
| SkASSERT(!this->valid()); |
| DSLWriter::ReportErrors(pos); |
| } |
| |
| DSLType DSLPossibleExpression::type() { |
| if (!this->valid()) { |
| return kVoid_Type; |
| } |
| return &fExpression->type(); |
| } |
| |
| DSLExpression DSLPossibleExpression::x(PositionInfo pos) { |
| return DSLExpression(this->release()).x(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::y(PositionInfo pos) { |
| return DSLExpression(this->release()).y(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::z(PositionInfo pos) { |
| return DSLExpression(this->release()).z(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::w(PositionInfo pos) { |
| return DSLExpression(this->release()).w(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::r(PositionInfo pos) { |
| return DSLExpression(this->release()).r(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::g(PositionInfo pos) { |
| return DSLExpression(this->release()).g(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::b(PositionInfo pos) { |
| return DSLExpression(this->release()).b(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::a(PositionInfo pos) { |
| return DSLExpression(this->release()).a(pos); |
| } |
| |
| DSLExpression DSLPossibleExpression::field(skstd::string_view name, PositionInfo 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, |
| PositionInfo pos) { |
| return DSLExpression(this->release())(std::move(args), pos); |
| } |
| |
| DSLPossibleExpression DSLPossibleExpression::operator()(ExpressionArray args, PositionInfo 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(PositionInfo pos) { |
| return DSLExpression(std::move(*this), pos).release(); |
| } |
| |
| } // namespace dsl |
| |
| } // namespace SkSL |