1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLPrefixExpression.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/sksl/SkSLErrorReporter.h" 11cb93a386Sopenharmony_ci#include "src/sksl/SkSLAnalysis.h" 12cb93a386Sopenharmony_ci#include "src/sksl/SkSLConstantFolder.h" 13cb93a386Sopenharmony_ci#include "src/sksl/SkSLProgramSettings.h" 14cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructor.h" 15cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorArray.h" 16cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorCompound.h" 17cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h" 18cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLConstructorSplat.h" 19cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLLiteral.h" 20cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLVariableReference.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_cinamespace SkSL { 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cistatic ExpressionArray negate_operands(const Context& context, const ExpressionArray& operands); 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cistatic std::unique_ptr<Expression> simplify_negation(const Context& context, 27cb93a386Sopenharmony_ci const Expression& originalExpr) { 28cb93a386Sopenharmony_ci const Expression* value = ConstantFolder::GetConstantValueForVariable(originalExpr); 29cb93a386Sopenharmony_ci switch (value->kind()) { 30cb93a386Sopenharmony_ci case Expression::Kind::kLiteral: { 31cb93a386Sopenharmony_ci // Convert -literal(1) to literal(-1). 32cb93a386Sopenharmony_ci double negated = -value->as<Literal>().value(); 33cb93a386Sopenharmony_ci // Don't simplify the expression if the type can't hold the negated value. 34cb93a386Sopenharmony_ci const Type& type = value->type(); 35cb93a386Sopenharmony_ci if (type.checkForOutOfRangeLiteral(context, negated, value->fLine)) { 36cb93a386Sopenharmony_ci return nullptr; 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci return Literal::Make(originalExpr.fLine, negated, &type); 39cb93a386Sopenharmony_ci } 40cb93a386Sopenharmony_ci case Expression::Kind::kPrefix: { 41cb93a386Sopenharmony_ci // Convert `-(-expression)` into `expression`. 42cb93a386Sopenharmony_ci const PrefixExpression& prefix = value->as<PrefixExpression>(); 43cb93a386Sopenharmony_ci if (prefix.getOperator().kind() == Token::Kind::TK_MINUS) { 44cb93a386Sopenharmony_ci return prefix.operand()->clone(); 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci break; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci case Expression::Kind::kConstructorArray: 49cb93a386Sopenharmony_ci // Convert `-array[N](literal, ...)` into `array[N](-literal, ...)`. 50cb93a386Sopenharmony_ci if (value->isCompileTimeConstant()) { 51cb93a386Sopenharmony_ci const ConstructorArray& ctor = value->as<ConstructorArray>(); 52cb93a386Sopenharmony_ci return ConstructorArray::Make(context, originalExpr.fLine, ctor.type(), 53cb93a386Sopenharmony_ci negate_operands(context, ctor.arguments())); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci break; 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci case Expression::Kind::kConstructorDiagonalMatrix: 58cb93a386Sopenharmony_ci // Convert `-matrix(literal)` into `matrix(-literal)`. 59cb93a386Sopenharmony_ci if (value->isCompileTimeConstant()) { 60cb93a386Sopenharmony_ci const ConstructorDiagonalMatrix& ctor = value->as<ConstructorDiagonalMatrix>(); 61cb93a386Sopenharmony_ci if (std::unique_ptr<Expression> simplified = simplify_negation(context, 62cb93a386Sopenharmony_ci *ctor.argument())) { 63cb93a386Sopenharmony_ci return ConstructorDiagonalMatrix::Make(context, originalExpr.fLine, ctor.type(), 64cb93a386Sopenharmony_ci std::move(simplified)); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci break; 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci case Expression::Kind::kConstructorSplat: 70cb93a386Sopenharmony_ci // Convert `-vector(literal)` into `vector(-literal)`. 71cb93a386Sopenharmony_ci if (value->isCompileTimeConstant()) { 72cb93a386Sopenharmony_ci const ConstructorSplat& ctor = value->as<ConstructorSplat>(); 73cb93a386Sopenharmony_ci if (std::unique_ptr<Expression> simplified = simplify_negation(context, 74cb93a386Sopenharmony_ci *ctor.argument())) { 75cb93a386Sopenharmony_ci return ConstructorSplat::Make(context, originalExpr.fLine, ctor.type(), 76cb93a386Sopenharmony_ci std::move(simplified)); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci break; 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci case Expression::Kind::kConstructorCompound: 82cb93a386Sopenharmony_ci // Convert `-vecN(literal, ...)` into `vecN(-literal, ...)`. 83cb93a386Sopenharmony_ci if (value->isCompileTimeConstant()) { 84cb93a386Sopenharmony_ci const ConstructorCompound& ctor = value->as<ConstructorCompound>(); 85cb93a386Sopenharmony_ci return ConstructorCompound::Make(context, originalExpr.fLine, ctor.type(), 86cb93a386Sopenharmony_ci negate_operands(context, ctor.arguments())); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci break; 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci default: 91cb93a386Sopenharmony_ci break; 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci return nullptr; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_cistatic ExpressionArray negate_operands(const Context& context, const ExpressionArray& array) { 97cb93a386Sopenharmony_ci ExpressionArray replacement; 98cb93a386Sopenharmony_ci replacement.reserve_back(array.size()); 99cb93a386Sopenharmony_ci for (const std::unique_ptr<Expression>& expr : array) { 100cb93a386Sopenharmony_ci // The logic below is very similar to `negate_operand`, but with different ownership rules. 101cb93a386Sopenharmony_ci if (std::unique_ptr<Expression> simplified = simplify_negation(context, *expr)) { 102cb93a386Sopenharmony_ci replacement.push_back(std::move(simplified)); 103cb93a386Sopenharmony_ci } else { 104cb93a386Sopenharmony_ci replacement.push_back(std::make_unique<PrefixExpression>(Token::Kind::TK_MINUS, 105cb93a386Sopenharmony_ci expr->clone())); 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci return replacement; 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_cistatic std::unique_ptr<Expression> negate_operand(const Context& context, 112cb93a386Sopenharmony_ci std::unique_ptr<Expression> value) { 113cb93a386Sopenharmony_ci // Attempt to simplify this negation (e.g. eliminate double negation, literal values) 114cb93a386Sopenharmony_ci if (std::unique_ptr<Expression> simplified = simplify_negation(context, *value)) { 115cb93a386Sopenharmony_ci return simplified; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci // No simplified form; convert expression to Prefix(TK_MINUS, expression). 119cb93a386Sopenharmony_ci return std::make_unique<PrefixExpression>(Token::Kind::TK_MINUS, std::move(value)); 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_cistatic std::unique_ptr<Expression> logical_not_operand(const Context& context, 123cb93a386Sopenharmony_ci std::unique_ptr<Expression> operand) { 124cb93a386Sopenharmony_ci const Expression* value = ConstantFolder::GetConstantValueForVariable(*operand); 125cb93a386Sopenharmony_ci switch (value->kind()) { 126cb93a386Sopenharmony_ci case Expression::Kind::kLiteral: { 127cb93a386Sopenharmony_ci // Convert !boolLiteral(true) to boolLiteral(false). 128cb93a386Sopenharmony_ci SkASSERT(value->type().isBoolean()); 129cb93a386Sopenharmony_ci const Literal& b = value->as<Literal>(); 130cb93a386Sopenharmony_ci return Literal::MakeBool(operand->fLine, !b.boolValue(), &operand->type()); 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci case Expression::Kind::kPrefix: { 133cb93a386Sopenharmony_ci // Convert `!(!expression)` into `expression`. 134cb93a386Sopenharmony_ci PrefixExpression& prefix = operand->as<PrefixExpression>(); 135cb93a386Sopenharmony_ci if (prefix.getOperator().kind() == Token::Kind::TK_LOGICALNOT) { 136cb93a386Sopenharmony_ci return std::move(prefix.operand()); 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci break; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci default: 141cb93a386Sopenharmony_ci break; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci // No simplified form; convert expression to Prefix(TK_LOGICALNOT, expression). 145cb93a386Sopenharmony_ci return std::make_unique<PrefixExpression>(Token::Kind::TK_LOGICALNOT, std::move(operand)); 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_cistd::unique_ptr<Expression> PrefixExpression::Convert(const Context& context, 149cb93a386Sopenharmony_ci Operator op, 150cb93a386Sopenharmony_ci std::unique_ptr<Expression> base) { 151cb93a386Sopenharmony_ci const Type& baseType = base->type(); 152cb93a386Sopenharmony_ci switch (op.kind()) { 153cb93a386Sopenharmony_ci case Token::Kind::TK_PLUS: 154cb93a386Sopenharmony_ci if (baseType.isArray() || !baseType.componentType().isNumber()) { 155cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, 156cb93a386Sopenharmony_ci "'+' cannot operate on '" + baseType.displayName() + "'"); 157cb93a386Sopenharmony_ci return nullptr; 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci break; 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci case Token::Kind::TK_MINUS: 162cb93a386Sopenharmony_ci if (baseType.isArray() || !baseType.componentType().isNumber()) { 163cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, 164cb93a386Sopenharmony_ci "'-' cannot operate on '" + baseType.displayName() + "'"); 165cb93a386Sopenharmony_ci return nullptr; 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci break; 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci case Token::Kind::TK_PLUSPLUS: 170cb93a386Sopenharmony_ci case Token::Kind::TK_MINUSMINUS: 171cb93a386Sopenharmony_ci if (!baseType.isNumber()) { 172cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, 173cb93a386Sopenharmony_ci String("'") + op.operatorName() + "' cannot operate on '" + 174cb93a386Sopenharmony_ci baseType.displayName() + "'"); 175cb93a386Sopenharmony_ci return nullptr; 176cb93a386Sopenharmony_ci } 177cb93a386Sopenharmony_ci if (!Analysis::UpdateVariableRefKind(base.get(), VariableReference::RefKind::kReadWrite, 178cb93a386Sopenharmony_ci context.fErrors)) { 179cb93a386Sopenharmony_ci return nullptr; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci break; 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci case Token::Kind::TK_LOGICALNOT: 184cb93a386Sopenharmony_ci if (!baseType.isBoolean()) { 185cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, 186cb93a386Sopenharmony_ci String("'") + op.operatorName() + "' cannot operate on '" + 187cb93a386Sopenharmony_ci baseType.displayName() + "'"); 188cb93a386Sopenharmony_ci return nullptr; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci break; 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci case Token::Kind::TK_BITWISENOT: 193cb93a386Sopenharmony_ci if (context.fConfig->strictES2Mode()) { 194cb93a386Sopenharmony_ci // GLSL ES 1.00, Section 5.1 195cb93a386Sopenharmony_ci context.fErrors->error( 196cb93a386Sopenharmony_ci base->fLine, 197cb93a386Sopenharmony_ci String("operator '") + op.operatorName() + "' is not allowed"); 198cb93a386Sopenharmony_ci return nullptr; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci if (baseType.isArray() || !baseType.componentType().isInteger()) { 201cb93a386Sopenharmony_ci context.fErrors->error(base->fLine, 202cb93a386Sopenharmony_ci String("'") + op.operatorName() + "' cannot operate on '" + 203cb93a386Sopenharmony_ci baseType.displayName() + "'"); 204cb93a386Sopenharmony_ci return nullptr; 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci if (baseType.isLiteral()) { 207cb93a386Sopenharmony_ci // The expression `~123` is no longer a literal; coerce to the actual type. 208cb93a386Sopenharmony_ci base = baseType.scalarTypeForLiteral().coerceExpression(std::move(base), context); 209cb93a386Sopenharmony_ci if (!base) { 210cb93a386Sopenharmony_ci return nullptr; 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci } 213cb93a386Sopenharmony_ci break; 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci default: 216cb93a386Sopenharmony_ci SK_ABORT("unsupported prefix operator"); 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci return PrefixExpression::Make(context, op, std::move(base)); 220cb93a386Sopenharmony_ci} 221cb93a386Sopenharmony_ci 222cb93a386Sopenharmony_cistd::unique_ptr<Expression> PrefixExpression::Make(const Context& context, Operator op, 223cb93a386Sopenharmony_ci std::unique_ptr<Expression> base) { 224cb93a386Sopenharmony_ci switch (op.kind()) { 225cb93a386Sopenharmony_ci case Token::Kind::TK_PLUS: 226cb93a386Sopenharmony_ci SkASSERT(!base->type().isArray()); 227cb93a386Sopenharmony_ci SkASSERT(base->type().componentType().isNumber()); 228cb93a386Sopenharmony_ci return base; 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci case Token::Kind::TK_MINUS: 231cb93a386Sopenharmony_ci SkASSERT(!base->type().isArray()); 232cb93a386Sopenharmony_ci SkASSERT(base->type().componentType().isNumber()); 233cb93a386Sopenharmony_ci return negate_operand(context, std::move(base)); 234cb93a386Sopenharmony_ci 235cb93a386Sopenharmony_ci case Token::Kind::TK_LOGICALNOT: 236cb93a386Sopenharmony_ci SkASSERT(base->type().isBoolean()); 237cb93a386Sopenharmony_ci return logical_not_operand(context, std::move(base)); 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_ci case Token::Kind::TK_PLUSPLUS: 240cb93a386Sopenharmony_ci case Token::Kind::TK_MINUSMINUS: 241cb93a386Sopenharmony_ci SkASSERT(base->type().isNumber()); 242cb93a386Sopenharmony_ci SkASSERT(Analysis::IsAssignable(*base)); 243cb93a386Sopenharmony_ci break; 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci case Token::Kind::TK_BITWISENOT: 246cb93a386Sopenharmony_ci SkASSERT(!context.fConfig->strictES2Mode()); 247cb93a386Sopenharmony_ci SkASSERT(!base->type().isArray()); 248cb93a386Sopenharmony_ci SkASSERT(base->type().componentType().isInteger()); 249cb93a386Sopenharmony_ci SkASSERT(!base->type().isLiteral()); 250cb93a386Sopenharmony_ci break; 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci default: 253cb93a386Sopenharmony_ci SkDEBUGFAILF("unsupported prefix operator: %s", op.operatorName()); 254cb93a386Sopenharmony_ci } 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci return std::make_unique<PrefixExpression>(op, std::move(base)); 257cb93a386Sopenharmony_ci} 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_ci} // namespace SkSL 260