Add Make factory functions to literal types.

This is mostly for consistency with other IRNode types; there isn't any
optimization opportunity or error checking for literals.

Change-Id: I0e6a55cddbd814585ecafeddab4e591fe5113911
Bug: skia:11342
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/383996
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-03-11 22:35:19 -05:00 committed by Skia Commit-Bot
parent 91113acfd1
commit 9ce80f71de
14 changed files with 117 additions and 101 deletions

View File

@ -84,7 +84,7 @@ static std::unique_ptr<Expression> simplify_vector(const Context& context,
[[fallthrough]]; [[fallthrough]];
case Expression::ComparisonResult::kEqual: case Expression::ComparisonResult::kEqual:
return std::make_unique<BoolLiteral>(context, left.fOffset, equality); return BoolLiteral::Make(context, left.fOffset, equality);
case Expression::ComparisonResult::kUnknown: case Expression::ComparisonResult::kUnknown:
return nullptr; return nullptr;
@ -98,7 +98,7 @@ static std::unique_ptr<Expression> simplify_vector(const Context& context,
args.reserve_back(type.columns()); args.reserve_back(type.columns());
for (int i = 0; i < type.columns(); i++) { for (int i = 0; i < type.columns(); i++) {
U value = foldFn(left.getVecComponent<T>(i), right.getVecComponent<T>(i)); U value = foldFn(left.getVecComponent<T>(i), right.getVecComponent<T>(i));
args.push_back(std::make_unique<Literal<T>>(left.fOffset, value, &componentType)); args.push_back(Literal<T>::Make(left.fOffset, value, &componentType));
} }
auto foldedCtor = Constructor::Convert(context, left.fOffset, type, std::move(args)); auto foldedCtor = Constructor::Convert(context, left.fOffset, type, std::move(args));
SkASSERT(foldedCtor); SkASSERT(foldedCtor);
@ -349,7 +349,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
case Token::Kind::TK_NEQ: result = leftVal != rightVal; break; case Token::Kind::TK_NEQ: result = leftVal != rightVal; break;
default: return nullptr; default: return nullptr;
} }
return std::make_unique<BoolLiteral>(context, offset, result); return BoolLiteral::Make(context, offset, result);
} }
// If the left side is a Boolean literal, apply short-circuit optimizations. // If the left side is a Boolean literal, apply short-circuit optimizations.
@ -372,13 +372,13 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
if (op.kind() == Token::Kind::TK_EQEQ && Analysis::IsSameExpressionTree(*left, *right)) { if (op.kind() == Token::Kind::TK_EQEQ && Analysis::IsSameExpressionTree(*left, *right)) {
// With == comparison, if both sides are the same trivial expression, this is self- // With == comparison, if both sides are the same trivial expression, this is self-
// comparison and is always true. (We are not concerned with NaN.) // comparison and is always true. (We are not concerned with NaN.)
return std::make_unique<BoolLiteral>(context, leftExpr.fOffset, /*value=*/true); return BoolLiteral::Make(context, leftExpr.fOffset, /*value=*/true);
} }
if (op.kind() == Token::Kind::TK_NEQ && Analysis::IsSameExpressionTree(*left, *right)) { if (op.kind() == Token::Kind::TK_NEQ && Analysis::IsSameExpressionTree(*left, *right)) {
// With != comparison, if both sides are the same trivial expression, this is self- // With != comparison, if both sides are the same trivial expression, this is self-
// comparison and is always false. (We are not concerned with NaN.) // comparison and is always false. (We are not concerned with NaN.)
return std::make_unique<BoolLiteral>(context, leftExpr.fOffset, /*value=*/false); return BoolLiteral::Make(context, leftExpr.fOffset, /*value=*/false);
} }
if (ErrorOnDivideByZero(context, offset, op, *right)) { if (ErrorOnDivideByZero(context, offset, op, *right)) {
@ -404,13 +404,11 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
// Note that we expressly do not worry about precision and overflow here -- we use the maximum // Note that we expressly do not worry about precision and overflow here -- we use the maximum
// precision to calculate the results and hope the result makes sense. // precision to calculate the results and hope the result makes sense.
// TODO: detect and handle integer overflow properly. // TODO(skia:10932): detect and handle integer overflow properly.
using SKSL_UINT = uint64_t; using SKSL_UINT = uint64_t;
#define RESULT(t, op) std::make_unique<t ## Literal>(context, offset, \ #define RESULT(t, op) t ## Literal::Make(context, offset, leftVal op rightVal)
leftVal op rightVal) #define URESULT(t, op) t ## Literal::Make(context, offset, (SKSL_UINT) leftVal op \
#define URESULT(t, op) std::make_unique<t ## Literal>(context, offset, \ (SKSL_UINT) rightVal)
(SKSL_UINT) leftVal op \
(SKSL_UINT) rightVal)
if (left->is<IntLiteral>() && right->is<IntLiteral>()) { if (left->is<IntLiteral>() && right->is<IntLiteral>()) {
SKSL_INT leftVal = left->as<IntLiteral>().value(); SKSL_INT leftVal = left->as<IntLiteral>().value();
SKSL_INT rightVal = right->as<IntLiteral>().value(); SKSL_INT rightVal = right->as<IntLiteral>().value();
@ -535,7 +533,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
[[fallthrough]]; [[fallthrough]];
case Expression::ComparisonResult::kEqual: case Expression::ComparisonResult::kEqual:
return std::make_unique<BoolLiteral>(context, offset, equality); return BoolLiteral::Make(context, offset, equality);
case Expression::ComparisonResult::kUnknown: case Expression::ComparisonResult::kUnknown:
return nullptr; return nullptr;

View File

@ -909,12 +909,12 @@ void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpres
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) { if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
this->writeExpression(*b.right(), Precedence::kTernary); this->writeExpression(*b.right(), Precedence::kTernary);
} else { } else {
BoolLiteral boolTrue(fContext, -1, true); BoolLiteral boolTrue(/*offset=*/-1, /*value=*/true, fContext.fTypes.fBool.get());
this->writeBoolLiteral(boolTrue); this->writeBoolLiteral(boolTrue);
} }
this->write(" : "); this->write(" : ");
if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) { if (b.getOperator().kind() == Token::Kind::TK_LOGICALAND) {
BoolLiteral boolFalse(fContext, -1, false); BoolLiteral boolFalse(/*offset=*/-1, /*value=*/false, fContext.fTypes.fBool.get());
this->writeBoolLiteral(boolFalse); this->writeBoolLiteral(boolFalse);
} else { } else {
this->writeExpression(*b.right(), Precedence::kTernary); this->writeExpression(*b.right(), Precedence::kTernary);
@ -1289,7 +1289,7 @@ void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
if (this->caps().addAndTrueToLoopCondition()) { if (this->caps().addAndTrueToLoopCondition()) {
std::unique_ptr<Expression> and_true(new BinaryExpression( std::unique_ptr<Expression> and_true(new BinaryExpression(
/*offset=*/-1, f.test()->clone(), Token::Kind::TK_LOGICALAND, /*offset=*/-1, f.test()->clone(), Token::Kind::TK_LOGICALAND,
std::make_unique<BoolLiteral>(fContext, -1, true), BoolLiteral::Make(fContext, /*offset=*/-1, /*value=*/true),
fContext.fTypes.fBool.get())); fContext.fTypes.fBool.get()));
this->writeExpression(*and_true, Precedence::kTopLevel); this->writeExpression(*and_true, Precedence::kTopLevel);
} else { } else {

View File

@ -775,7 +775,7 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
fContext, fContext,
std::make_unique<VariableReference>(/*offset=*/-1, loopIdx), std::make_unique<VariableReference>(/*offset=*/-1, loopIdx),
Token::Kind::TK_LT, Token::Kind::TK_LT,
std::make_unique<IntLiteral>(fContext, /*offset=*/-1, fInvocations)); IntLiteral::Make(fContext, /*offset=*/-1, fInvocations));
auto next = PostfixExpression::Make( auto next = PostfixExpression::Make(
fContext, fContext,
std::make_unique<VariableReference>(/*offset=*/-1, loopIdx,VariableRefKind::kReadWrite), std::make_unique<VariableReference>(/*offset=*/-1, loopIdx,VariableRefKind::kReadWrite),
@ -796,7 +796,7 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
fContext, fContext,
std::make_unique<VariableReference>(/*offset=*/-1, loopIdx, VariableRefKind::kWrite), std::make_unique<VariableReference>(/*offset=*/-1, loopIdx, VariableRefKind::kWrite),
Token::Kind::TK_EQ, Token::Kind::TK_EQ,
std::make_unique<IntLiteral>(fContext, /*offset=*/-1, /*value=*/0)); IntLiteral::Make(fContext, /*offset=*/-1, /*value=*/0));
auto initializer = ExpressionStatement::Make(fContext, std::move(assignment)); auto initializer = ExpressionStatement::Make(fContext, std::move(assignment));
auto loop = ForStatement::Make( auto loop = ForStatement::Make(
fContext, /*offset=*/-1, std::move(initializer), std::move(test), std::move(next), fContext, /*offset=*/-1, std::move(initializer), std::move(test), std::move(next),
@ -858,7 +858,7 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
Op(Swizzle(Pos(), kXYIndices), Token::Kind::TK_STAR, Swizzle(Adjust(), kXZIndices)), Op(Swizzle(Pos(), kXYIndices), Token::Kind::TK_STAR, Swizzle(Adjust(), kXZIndices)),
Token::Kind::TK_PLUS, Token::Kind::TK_PLUS,
Op(Swizzle(Pos(), kWWIndices), Token::Kind::TK_STAR, Swizzle(Adjust(), kYWIndices)))); Op(Swizzle(Pos(), kWWIndices), Token::Kind::TK_STAR, Swizzle(Adjust(), kYWIndices))));
children.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1, /*value=*/0.0)); children.push_back(FloatLiteral::Make(fContext, /*offset=*/-1, /*value=*/0.0));
children.push_back(Swizzle(Pos(), kWIndex)); children.push_back(Swizzle(Pos(), kWIndex));
std::unique_ptr<Expression> result = std::unique_ptr<Expression> result =
Op(Pos(), Token::Kind::TK_EQ, Op(Pos(), Token::Kind::TK_EQ,
@ -1421,7 +1421,7 @@ void IRGenerator::convertEnum(const ASTNode& e) {
return; return;
} }
} }
value = std::make_unique<IntLiteral>(fContext, e.fOffset, currentValue); value = IntLiteral::Make(fContext, e.fOffset, currentValue);
++currentValue; ++currentValue;
auto var = std::make_unique<Variable>(e.fOffset, fModifiers->addToPool(modifiers), auto var = std::make_unique<Variable>(e.fOffset, fModifiers->addToPool(modifiers),
child.getString(), type, fIsBuiltinCode, child.getString(), type, fIsBuiltinCode,
@ -1491,22 +1491,19 @@ std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr)
case ASTNode::Kind::kBinary: case ASTNode::Kind::kBinary:
return this->convertBinaryExpression(expr); return this->convertBinaryExpression(expr);
case ASTNode::Kind::kBool: case ASTNode::Kind::kBool:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset, return BoolLiteral::Make(fContext, expr.fOffset, expr.getBool());
expr.getBool()));
case ASTNode::Kind::kCall: case ASTNode::Kind::kCall:
return this->convertCallExpression(expr); return this->convertCallExpression(expr);
case ASTNode::Kind::kField: case ASTNode::Kind::kField:
return this->convertFieldExpression(expr); return this->convertFieldExpression(expr);
case ASTNode::Kind::kFloat: case ASTNode::Kind::kFloat:
return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset, return FloatLiteral::Make(fContext, expr.fOffset, expr.getFloat());
expr.getFloat()));
case ASTNode::Kind::kIdentifier: case ASTNode::Kind::kIdentifier:
return this->convertIdentifier(expr); return this->convertIdentifier(expr);
case ASTNode::Kind::kIndex: case ASTNode::Kind::kIndex:
return this->convertIndexExpression(expr); return this->convertIndexExpression(expr);
case ASTNode::Kind::kInt: case ASTNode::Kind::kInt:
return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset, return IntLiteral::Make(fContext, expr.fOffset, expr.getInt());
expr.getInt()));
case ASTNode::Kind::kPostfix: case ASTNode::Kind::kPostfix:
return this->convertPostfixExpression(expr); return this->convertPostfixExpression(expr);
case ASTNode::Kind::kPrefix: case ASTNode::Kind::kPrefix:
@ -1971,8 +1968,7 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
if (result) { if (result) {
const Variable& v = *result->as<VariableReference>().variable(); const Variable& v = *result->as<VariableReference>().variable();
SkASSERT(v.initialValue()); SkASSERT(v.initialValue());
result = std::make_unique<IntLiteral>(offset, v.initialValue()->as<IntLiteral>().value(), result = IntLiteral::Make(offset, v.initialValue()->as<IntLiteral>().value(), &type);
&type);
} else { } else {
this->errorReporter().error( this->errorReporter().error(
offset, "type '" + type.name() + "' does not contain enumerator '" + field + "'"); offset, "type '" + type.name() + "' does not contain enumerator '" + field + "'");

View File

@ -691,9 +691,9 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
// int _1_loop = 0; // int _1_loop = 0;
symbolTable = std::make_shared<SymbolTable>(std::move(symbolTable), caller->isBuiltin()); symbolTable = std::make_shared<SymbolTable>(std::move(symbolTable), caller->isBuiltin());
const Type* intType = fContext->fTypes.fInt.get(); const Type* intType = fContext->fTypes.fInt.get();
std::unique_ptr<Expression> initialValue = std::make_unique<IntLiteral>(/*offset=*/-1, std::unique_ptr<Expression> initialValue = IntLiteral::Make(/*offset=*/-1,
/*value=*/0, /*value=*/0,
intType); intType);
InlineVariable loopVar = this->makeInlineVariable("loop", intType, symbolTable.get(), InlineVariable loopVar = this->makeInlineVariable("loop", intType, symbolTable.get(),
Modifiers{}, caller->isBuiltin(), Modifiers{}, caller->isBuiltin(),
&initialValue); &initialValue);
@ -703,7 +703,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
*fContext, *fContext,
std::make_unique<VariableReference>(/*offset=*/-1, loopVar.fVarSymbol), std::make_unique<VariableReference>(/*offset=*/-1, loopVar.fVarSymbol),
Token::Kind::TK_LT, Token::Kind::TK_LT,
std::make_unique<IntLiteral>(/*offset=*/-1, /*value=*/1, intType)); IntLiteral::Make(/*offset=*/-1, /*value=*/1, intType));
// _1_loop++ // _1_loop++
std::unique_ptr<Expression> increment = PostfixExpression::Make( std::unique_ptr<Expression> increment = PostfixExpression::Make(
@ -754,9 +754,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
} else if (function.declaration().returnType() == *fContext->fTypes.fVoid) { } else if (function.declaration().returnType() == *fContext->fTypes.fVoid) {
// It's a void function, so it doesn't actually result in anything, but we have to return // It's a void function, so it doesn't actually result in anything, but we have to return
// something non-null as a standin. // something non-null as a standin.
inlinedCall.fReplacementExpr = std::make_unique<BoolLiteral>(*fContext, inlinedCall.fReplacementExpr = BoolLiteral::Make(*fContext, offset, /*value=*/false);
offset,
/*value=*/false);
} else { } else {
// It's a non-void function, but it never created a result expression--that is, it never // It's a non-void function, but it never created a result expression--that is, it never
// returned anything on any path! This should have been detected in the function finalizer. // returned anything on any path! This should have been detected in the function finalizer.

View File

@ -288,7 +288,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
int value = this->readS32(); int value = this->readS32();
// enum variables aren't really 'declared', but we have to create a declaration to // enum variables aren't really 'declared', but we have to create a declaration to
// store the value // store the value
auto valueLiteral = std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value); auto valueLiteral = IntLiteral::Make(fContext, /*offset=*/-1, value);
auto declaration = std::make_unique<VarDeclaration>(&v, &v.type(), /*arraySize=*/0, auto declaration = std::make_unique<VarDeclaration>(&v, &v.type(), /*arraySize=*/0,
std::move(valueLiteral)); std::move(valueLiteral));
v.setDeclaration(declaration.get()); v.setDeclaration(declaration.get());
@ -446,7 +446,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
} }
case Rehydrator::kBoolLiteral_Command: { case Rehydrator::kBoolLiteral_Command: {
bool value = this->readU8(); bool value = this->readU8();
return std::make_unique<BoolLiteral>(fContext, -1, value); return BoolLiteral::Make(fContext, /*offset=*/-1, value);
} }
case Rehydrator::kConstructor_Command: { case Rehydrator::kConstructor_Command: {
const Type* type = this->type(); const Type* type = this->type();
@ -470,7 +470,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
const Type* type = this->type(); const Type* type = this->type();
FloatIntUnion u; FloatIntUnion u;
u.fInt = this->readS32(); u.fInt = this->readS32();
return std::make_unique<FloatLiteral>(-1, u.fFloat, type); return FloatLiteral::Make(/*offset=*/-1, u.fFloat, type);
} }
case Rehydrator::kFunctionCall_Command: { case Rehydrator::kFunctionCall_Command: {
const Type* type = this->type(); const Type* type = this->type();
@ -492,7 +492,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
case Rehydrator::kIntLiteral_Command: { case Rehydrator::kIntLiteral_Command: {
const Type* type = this->type(); const Type* type = this->type();
int value = this->readS32(); int value = this->readS32();
return std::make_unique<IntLiteral>(-1, value, type); return IntLiteral::Make(/*offset=*/-1, value, type);
} }
case Rehydrator::kPostfix_Command: { case Rehydrator::kPostfix_Command: {
Token::Kind op = (Token::Kind) this->readU8(); Token::Kind op = (Token::Kind) this->readU8();

View File

@ -549,7 +549,8 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
} }
if (type.columns() > 0) { if (type.columns() > 0) {
SpvId typeId = this->getType(type.componentType(), layout); SpvId typeId = this->getType(type.componentType(), layout);
IntLiteral countLiteral(fContext, /*offset=*/-1, type.columns()); IntLiteral countLiteral(/*offset=*/-1, type.columns(),
fContext.fTypes.fInt.get());
SpvId countId = this->writeIntLiteral(countLiteral); SpvId countId = this->writeIntLiteral(countLiteral);
this->writeInstruction(SpvOpTypeArray, result, typeId, countId, this->writeInstruction(SpvOpTypeArray, result, typeId, countId,
fConstantBuffer); fConstantBuffer);
@ -903,8 +904,8 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
SpvId img = this->writeExpression(*arguments[0], out); SpvId img = this->writeExpression(*arguments[0], out);
ExpressionArray args; ExpressionArray args;
args.reserve_back(2); args.reserve_back(2);
args.push_back(std::make_unique<IntLiteral>(fContext, /*offset=*/-1, /*value=*/0)); args.push_back(IntLiteral::Make(fContext, /*offset=*/-1, /*value=*/0));
args.push_back(std::make_unique<IntLiteral>(fContext, /*offset=*/-1, /*value=*/0)); args.push_back(IntLiteral::Make(fContext, /*offset=*/-1, /*value=*/0));
Constructor ctor(/*offset=*/-1, *fContext.fTypes.fInt2, std::move(args)); Constructor ctor(/*offset=*/-1, *fContext.fTypes.fInt2, std::move(args));
SpvId coords = this->writeConstantVector(ctor); SpvId coords = this->writeConstantVector(ctor);
if (arguments.size() == 1) { if (arguments.size() == 1) {
@ -970,7 +971,8 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
} else { } else {
SkASSERT(arguments.size() == 2); SkASSERT(arguments.size() == 2);
if (fProgram.fConfig->fSettings.fSharpenTextures) { if (fProgram.fConfig->fSettings.fSharpenTextures) {
FloatLiteral lodBias(fContext, -1, -0.5); FloatLiteral lodBias(/*offset=*/-1, /*value=*/-0.5,
fContext.fTypes.fFloat.get());
this->writeInstruction(op, type, result, sampler, uv, this->writeInstruction(op, type, result, sampler, uv,
SpvImageOperandsBiasMask, SpvImageOperandsBiasMask,
this->writeFloatLiteral(lodBias), this->writeFloatLiteral(lodBias),
@ -1053,10 +1055,8 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
ExpressionArray finalArgs; ExpressionArray finalArgs;
finalArgs.reserve_back(3); finalArgs.reserve_back(3);
finalArgs.push_back(arguments[0]->clone()); finalArgs.push_back(arguments[0]->clone());
finalArgs.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1, finalArgs.push_back(FloatLiteral::Make(fContext, /*offset=*/-1, /*value=*/0));
/*value=*/0)); finalArgs.push_back(FloatLiteral::Make(fContext, /*offset=*/-1, /*value=*/1));
finalArgs.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1,
/*value=*/1));
std::vector<SpvId> spvArgs = this->vectorize(finalArgs, out); std::vector<SpvId> spvArgs = this->vectorize(finalArgs, out);
this->writeGLSLExtendedInstruction(callType, result, GLSLstd450FClamp, GLSLstd450SClamp, this->writeGLSLExtendedInstruction(callType, result, GLSLstd450FClamp, GLSLstd450SClamp,
GLSLstd450UClamp, spvArgs, out); GLSLstd450UClamp, spvArgs, out);
@ -1225,9 +1225,9 @@ SpvId SPIRVCodeGenerator::castScalarToFloat(SpvId inputId, const Type& inputType
SpvId result = this->nextId(); SpvId result = this->nextId();
if (inputType.isBoolean()) { if (inputType.isBoolean()) {
// Use OpSelect to convert the boolean argument to a literal 1.0 or 0.0. // Use OpSelect to convert the boolean argument to a literal 1.0 or 0.0.
FloatLiteral one(fContext, /*offset=*/-1, /*value=*/1); FloatLiteral one(/*offset=*/-1, /*value=*/1, fContext.fTypes.fFloat.get());
SpvId oneID = this->writeFloatLiteral(one); SpvId oneID = this->writeFloatLiteral(one);
FloatLiteral zero(fContext, /*offset=*/-1, /*value=*/0); FloatLiteral zero(/*offset=*/-1, /*value=*/0, fContext.fTypes.fFloat.get());
SpvId zeroID = this->writeFloatLiteral(zero); SpvId zeroID = this->writeFloatLiteral(zero);
this->writeInstruction(SpvOpSelect, this->getType(outputType), result, this->writeInstruction(SpvOpSelect, this->getType(outputType), result,
inputId, oneID, zeroID, out); inputId, oneID, zeroID, out);
@ -1360,7 +1360,7 @@ SpvId SPIRVCodeGenerator::castScalarToBoolean(SpvId inputId, const Type& inputTy
void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type, void SPIRVCodeGenerator::writeUniformScaleMatrix(SpvId id, SpvId diagonal, const Type& type,
OutputStream& out) { OutputStream& out) {
FloatLiteral zero(fContext, -1, 0); FloatLiteral zero(/*offset=*/-1, /*value=*/0, fContext.fTypes.fFloat.get());
SpvId zeroId = this->writeFloatLiteral(zero); SpvId zeroId = this->writeFloatLiteral(zero);
std::vector<SpvId> columnIds; std::vector<SpvId> columnIds;
for (int column = 0; column < type.columns(); column++) { for (int column = 0; column < type.columns(); column++) {
@ -1399,10 +1399,10 @@ void SPIRVCodeGenerator::writeMatrixCopy(SpvId id, SpvId src, const Type& srcTyp
1)); 1));
SpvId zeroId; SpvId zeroId;
if (dstType.componentType() == *fContext.fTypes.fFloat) { if (dstType.componentType() == *fContext.fTypes.fFloat) {
FloatLiteral zero(fContext, -1, 0.0); FloatLiteral zero(/*offset=*/-1, /*value=*/0.0, fContext.fTypes.fFloat.get());
zeroId = this->writeFloatLiteral(zero); zeroId = this->writeFloatLiteral(zero);
} else if (dstType.componentType() == *fContext.fTypes.fInt) { } else if (dstType.componentType() == *fContext.fTypes.fInt) {
IntLiteral zero(fContext, -1, 0); IntLiteral zero(/*offset=*/-1, /*value=*/0, fContext.fTypes.fInt.get());
zeroId = this->writeIntLiteral(zero); zeroId = this->writeIntLiteral(zero);
} else { } else {
SK_ABORT("unsupported matrix component type"); SK_ABORT("unsupported matrix component type");
@ -1745,7 +1745,7 @@ std::vector<SpvId> SPIRVCodeGenerator::getAccessChain(const Expression& expr, Ou
case Expression::Kind::kFieldAccess: { case Expression::Kind::kFieldAccess: {
const FieldAccess& fieldExpr = expr.as<FieldAccess>(); const FieldAccess& fieldExpr = expr.as<FieldAccess>();
chain = this->getAccessChain(*fieldExpr.base(), out); chain = this->getAccessChain(*fieldExpr.base(), out);
IntLiteral index(fContext, /*offset=*/-1, fieldExpr.fieldIndex()); IntLiteral index(/*offset=*/-1, fieldExpr.fieldIndex(), fContext.fTypes.fInt.get());
chain.push_back(this->writeIntLiteral(index)); chain.push_back(this->writeIntLiteral(index));
break; break;
} }
@ -1894,7 +1894,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
const Variable& var = *expr.as<VariableReference>().variable(); const Variable& var = *expr.as<VariableReference>().variable();
int uniformIdx = this->findUniformFieldIndex(var); int uniformIdx = this->findUniformFieldIndex(var);
if (uniformIdx >= 0) { if (uniformIdx >= 0) {
IntLiteral uniformIdxLiteral{fContext, /*offset=*/-1, uniformIdx}; IntLiteral uniformIdxLiteral{/*offset=*/-1, uniformIdx, fContext.fTypes.fInt.get()};
SpvId memberId = this->nextId(); SpvId memberId = this->nextId();
SpvId typeId = this->getPointerType(type, SpvStorageClassUniform); SpvId typeId = this->getPointerType(type, SpvStorageClassUniform);
SpvId uniformIdxId = this->writeIntLiteral(uniformIdxLiteral); SpvId uniformIdxId = this->writeIntLiteral(uniformIdxLiteral);
@ -1939,7 +1939,8 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
if (swizzle.components().size() == 1) { if (swizzle.components().size() == 1) {
SpvId member = this->nextId(); SpvId member = this->nextId();
SpvId typeId = this->getPointerType(type, get_storage_class(*swizzle.base())); SpvId typeId = this->getPointerType(type, get_storage_class(*swizzle.base()));
IntLiteral index(fContext, /*offset=*/-1, swizzle.components()[0]); IntLiteral index(/*offset=*/-1, swizzle.components()[0],
fContext.fTypes.fInt.get());
SpvId indexId = this->writeIntLiteral(index); SpvId indexId = this->writeIntLiteral(index);
this->writeInstruction(SpvOpAccessChain, typeId, member, base, indexId, out); this->writeInstruction(SpvOpAccessChain, typeId, member, base, indexId, out);
return std::make_unique<PointerLValue>(*this, member, this->getType(type), return std::make_unique<PointerLValue>(*this, member, this->getType(type),
@ -2038,7 +2039,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
} }
SkASSERT(fRTHeightFieldIndex != (SpvId)-1); SkASSERT(fRTHeightFieldIndex != (SpvId)-1);
IntLiteral fieldIndex(fContext, -1, fRTHeightFieldIndex); IntLiteral fieldIndex(/*offset=*/-1, fRTHeightFieldIndex, fContext.fTypes.fInt.get());
SpvId fieldIndexId = this->writeIntLiteral(fieldIndex); SpvId fieldIndexId = this->writeIntLiteral(fieldIndex);
SpvId heightPtr = this->nextId(); SpvId heightPtr = this->nextId();
this->writeOpCode(SpvOpAccessChain, 5, out); this->writeOpCode(SpvOpAccessChain, 5, out);
@ -2057,7 +2058,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
} }
// The z component will always be zero so we just get an id to the 0 literal // The z component will always be zero so we just get an id to the 0 literal
FloatLiteral zero(fContext, -1, 0.0); FloatLiteral zero(/*offset=*/-1, /*value=*/0.0, fContext.fTypes.fFloat.get());
SpvId zeroId = writeFloatLiteral(zero); SpvId zeroId = writeFloatLiteral(zero);
// Calculate the w component // Calculate the w component
@ -2233,10 +2234,10 @@ SpvId SPIRVCodeGenerator::writeComponentwiseMatrixBinary(const Type& operandType
static std::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) { static std::unique_ptr<Expression> create_literal_1(const Context& context, const Type& type) {
if (type.isInteger()) { if (type.isInteger()) {
return std::unique_ptr<Expression>(new IntLiteral(-1, 1, &type)); return IntLiteral::Make(/*offset=*/-1, /*value=*/1, &type);
} }
else if (type.isFloat()) { else if (type.isFloat()) {
return std::unique_ptr<Expression>(new FloatLiteral(-1, 1.0, &type)); return FloatLiteral::Make(/*offset=*/-1, /*value=*/1.0, &type);
} else { } else {
SK_ABORT("math is unsupported on type '%s'", String(type.name()).c_str()); SK_ABORT("math is unsupported on type '%s'", String(type.name()).c_str());
} }
@ -2483,7 +2484,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, Outpu
SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) { SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStream& out) {
SkASSERT(a.getOperator().kind() == Token::Kind::TK_LOGICALAND); SkASSERT(a.getOperator().kind() == Token::Kind::TK_LOGICALAND);
BoolLiteral falseLiteral(fContext, -1, false); BoolLiteral falseLiteral(/*offset=*/-1, /*value=*/false, fContext.fTypes.fBool.get());
SpvId falseConstant = this->writeBoolLiteral(falseLiteral); SpvId falseConstant = this->writeBoolLiteral(falseLiteral);
SpvId lhs = this->writeExpression(*a.left(), out); SpvId lhs = this->writeExpression(*a.left(), out);
SpvId rhsLabel = this->nextId(); SpvId rhsLabel = this->nextId();
@ -2504,7 +2505,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, OutputStrea
SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) { SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, OutputStream& out) {
SkASSERT(o.getOperator().kind() == Token::Kind::TK_LOGICALOR); SkASSERT(o.getOperator().kind() == Token::Kind::TK_LOGICALOR);
BoolLiteral trueLiteral(fContext, -1, true); BoolLiteral trueLiteral(/*offset=*/-1, /*value=*/true, fContext.fTypes.fBool.get());
SpvId trueConstant = this->writeBoolLiteral(trueLiteral); SpvId trueConstant = this->writeBoolLiteral(trueLiteral);
SpvId lhs = this->writeExpression(*o.left(), out); SpvId lhs = this->writeExpression(*o.left(), out);
SpvId rhsLabel = this->nextId(); SpvId rhsLabel = this->nextId();

View File

@ -41,9 +41,9 @@ DSLExpression::DSLExpression(std::unique_ptr<SkSL::Expression> expression)
} }
DSLExpression::DSLExpression(float value) DSLExpression::DSLExpression(float value)
: fExpression(std::make_unique<SkSL::FloatLiteral>(DSLWriter::Context(), : fExpression(SkSL::FloatLiteral::Make(DSLWriter::Context(),
/*offset=*/-1, /*offset=*/-1,
value)) { value)) {
if (!isfinite(value)) { if (!isfinite(value)) {
if (isinf(value)) { if (isinf(value)) {
DSLWriter::ReportError("error: floating point value is infinite\n"); DSLWriter::ReportError("error: floating point value is infinite\n");
@ -54,14 +54,14 @@ DSLExpression::DSLExpression(float value)
} }
DSLExpression::DSLExpression(int value) DSLExpression::DSLExpression(int value)
: fExpression(std::make_unique<SkSL::IntLiteral>(DSLWriter::Context(), : fExpression(SkSL::IntLiteral::Make(DSLWriter::Context(),
/*offset=*/-1, /*offset=*/-1,
value)) {} value)) {}
DSLExpression::DSLExpression(bool value) DSLExpression::DSLExpression(bool value)
: fExpression(std::make_unique<SkSL::BoolLiteral>(DSLWriter::Context(), : fExpression(SkSL::BoolLiteral::Make(DSLWriter::Context(),
/*offset=*/-1, /*offset=*/-1,
value)) {} value)) {}
DSLExpression::DSLExpression(const DSLVar& var) DSLExpression::DSLExpression(const DSLVar& var)
: fExpression(std::make_unique<SkSL::VariableReference>( : fExpression(std::make_unique<SkSL::VariableReference>(

View File

@ -25,13 +25,22 @@ class Literal<bool> final : public Expression {
public: public:
static constexpr Kind kExpressionKind = Kind::kBoolLiteral; static constexpr Kind kExpressionKind = Kind::kBoolLiteral;
Literal(const Context& context, int offset, bool value)
: Literal(offset, value, context.fTypes.fBool.get()) {}
Literal(int offset, bool value, const Type* type) Literal(int offset, bool value, const Type* type)
: INHERITED(offset, kExpressionKind, type) : INHERITED(offset, kExpressionKind, type)
, fValue(value) {} , fValue(value) {}
// Makes a literal of boolean type.
static std::unique_ptr<BoolLiteral> Make(const Context& context, int offset, float value) {
return std::make_unique<BoolLiteral>(offset, value, context.fTypes.fBool.get());
}
// Makes a literal of boolean type. (Functionally identical to the above, but useful if you
// don't have access to the Context.)
static std::unique_ptr<BoolLiteral> Make(int offset, float value, const Type* type) {
SkASSERT(type->isBoolean());
return std::make_unique<BoolLiteral>(offset, value, type);
}
bool value() const { bool value() const {
return fValue; return fValue;
} }

View File

@ -212,39 +212,37 @@ std::unique_ptr<Expression> Constructor::SimplifyConversion(const Type& construc
SKSL_INT value = expr.as<IntLiteral>().value(); SKSL_INT value = expr.as<IntLiteral>().value();
if (constructorType.isFloat()) { if (constructorType.isFloat()) {
// promote float(1) to 1.0 // promote float(1) to 1.0
return std::make_unique<FloatLiteral>(expr.fOffset, (SKSL_FLOAT)value, return FloatLiteral::Make(expr.fOffset, (SKSL_FLOAT)value, &constructorType);
&constructorType);
} else if (constructorType.isInteger()) { } else if (constructorType.isInteger()) {
// promote uint(1) to 1u // promote uint(1) to 1u
return std::make_unique<IntLiteral>(expr.fOffset, value, &constructorType); return IntLiteral::Make(expr.fOffset, value, &constructorType);
} else if (constructorType.isBoolean()) { } else if (constructorType.isBoolean()) {
// promote bool(1) to true/false // promote bool(1) to true/false
return std::make_unique<BoolLiteral>(expr.fOffset, value != 0, &constructorType); return BoolLiteral::Make(expr.fOffset, value != 0, &constructorType);
} }
} else if (expr.is<FloatLiteral>()) { } else if (expr.is<FloatLiteral>()) {
float value = expr.as<FloatLiteral>().value(); float value = expr.as<FloatLiteral>().value();
if (constructorType.isFloat()) { if (constructorType.isFloat()) {
// promote float(1.23) to 1.23 // promote float(1.23) to 1.23
return std::make_unique<FloatLiteral>(expr.fOffset, value, &constructorType); return FloatLiteral::Make(expr.fOffset, value, &constructorType);
} else if (constructorType.isInteger()) { } else if (constructorType.isInteger()) {
// promote uint(1.23) to 1u // promote uint(1.23) to 1u
return std::make_unique<IntLiteral>(expr.fOffset, (SKSL_INT)value, &constructorType); return IntLiteral::Make(expr.fOffset, (SKSL_INT)value, &constructorType);
} else if (constructorType.isBoolean()) { } else if (constructorType.isBoolean()) {
// promote bool(1.23) to true/false // promote bool(1.23) to true/false
return std::make_unique<BoolLiteral>(expr.fOffset, value != 0.0f, &constructorType); return BoolLiteral::Make(expr.fOffset, value != 0.0f, &constructorType);
} }
} else if (expr.is<BoolLiteral>()) { } else if (expr.is<BoolLiteral>()) {
bool value = expr.as<BoolLiteral>().value(); bool value = expr.as<BoolLiteral>().value();
if (constructorType.isFloat()) { if (constructorType.isFloat()) {
// promote float(true) to 1.0 // promote float(true) to 1.0
return std::make_unique<FloatLiteral>(expr.fOffset, value ? 1.0f : 0.0f, return FloatLiteral::Make(expr.fOffset, value ? 1.0f : 0.0f, &constructorType);
&constructorType);
} else if (constructorType.isInteger()) { } else if (constructorType.isInteger()) {
// promote uint(true) to 1u // promote uint(true) to 1u
return std::make_unique<IntLiteral>(expr.fOffset, value ? 1 : 0, &constructorType); return IntLiteral::Make(expr.fOffset, value ? 1 : 0, &constructorType);
} else if (constructorType.isBoolean()) { } else if (constructorType.isBoolean()) {
// promote bool(true) to true/false // promote bool(true) to true/false
return std::make_unique<BoolLiteral>(expr.fOffset, value, &constructorType); return BoolLiteral::Make(expr.fOffset, value, &constructorType);
} }
} }
return nullptr; return nullptr;

View File

@ -25,13 +25,21 @@ class Literal<SKSL_FLOAT> final : public Expression {
public: public:
static constexpr Kind kExpressionKind = Kind::kFloatLiteral; static constexpr Kind kExpressionKind = Kind::kFloatLiteral;
Literal(const Context& context, int offset, float value)
: Literal(offset, value, context.fTypes.fFloatLiteral.get()) {}
Literal(int offset, float value, const Type* type) Literal(int offset, float value, const Type* type)
: INHERITED(offset, kExpressionKind, type) : INHERITED(offset, kExpressionKind, type)
, fValue(value) {} , fValue(value) {}
// Makes a literal of $intLiteral type.
static std::unique_ptr<FloatLiteral> Make(const Context& context, int offset, float value) {
return std::make_unique<FloatLiteral>(offset, value, context.fTypes.fFloatLiteral.get());
}
// Makes a literal of the specified floating-point type.
static std::unique_ptr<FloatLiteral> Make(int offset, float value, const Type* type) {
SkASSERT(type->isFloat());
return std::make_unique<FloatLiteral>(offset, value, type);
}
float value() const { float value() const {
return fValue; return fValue;
} }

View File

@ -27,13 +27,21 @@ public:
// We will need to revisit this if we want full support for unsigned 64-bit integers, // We will need to revisit this if we want full support for unsigned 64-bit integers,
// but for now an SKSL_INT (int64_t) will hold every value we care about. // but for now an SKSL_INT (int64_t) will hold every value we care about.
Literal(const Context& context, int offset, SKSL_INT value) Literal(int offset, SKSL_INT value, const Type* type)
: Literal(offset, value, context.fTypes.fIntLiteral.get()) {}
Literal(int offset, int64_t value, const Type* type)
: INHERITED(offset, kExpressionKind, type) : INHERITED(offset, kExpressionKind, type)
, fValue(value) {} , fValue(value) {}
// Makes a literal of $intLiteral type.
static std::unique_ptr<IntLiteral> Make(const Context& context, int offset, SKSL_INT value) {
return std::make_unique<IntLiteral>(offset, value, context.fTypes.fIntLiteral.get());
}
// Makes a literal of the specified integer type.
static std::unique_ptr<IntLiteral> Make(int offset, SKSL_INT value, const Type* type) {
SkASSERT(type->isInteger() || type->isEnum());
return std::make_unique<IntLiteral>(offset, value, type);
}
SKSL_INT value() const { SKSL_INT value() const {
return fValue; return fValue;
} }

View File

@ -21,15 +21,15 @@ static std::unique_ptr<Expression> negate_operand(const Context& context,
switch (value->kind()) { switch (value->kind()) {
case Expression::Kind::kFloatLiteral: case Expression::Kind::kFloatLiteral:
// Convert -floatLiteral(1) to floatLiteral(-1). // Convert -floatLiteral(1) to floatLiteral(-1).
return std::make_unique<FloatLiteral>(operand->fOffset, return FloatLiteral::Make(operand->fOffset,
-value->as<FloatLiteral>().value(), -value->as<FloatLiteral>().value(),
&value->type()); &value->type());
case Expression::Kind::kIntLiteral: case Expression::Kind::kIntLiteral:
// Convert -intLiteral(1) to intLiteral(-1). // Convert -intLiteral(1) to intLiteral(-1).
return std::make_unique<IntLiteral>(operand->fOffset, return IntLiteral::Make(operand->fOffset,
-value->as<IntLiteral>().value(), -value->as<IntLiteral>().value(),
&value->type()); &value->type());
case Expression::Kind::kPrefix: case Expression::Kind::kPrefix:
if (context.fConfig->fSettings.fOptimize) { if (context.fConfig->fSettings.fOptimize) {
@ -81,7 +81,7 @@ static std::unique_ptr<Expression> logical_not_operand(const Context& context,
case Expression::Kind::kBoolLiteral: { case Expression::Kind::kBoolLiteral: {
// Convert !boolLiteral(true) to boolLiteral(false). // Convert !boolLiteral(true) to boolLiteral(false).
const BoolLiteral& b = value->as<BoolLiteral>(); const BoolLiteral& b = value->as<BoolLiteral>();
return std::make_unique<BoolLiteral>(operand->fOffset, !b.value(), &operand->type()); return BoolLiteral::Make(operand->fOffset, !b.value(), &operand->type());
} }
case Expression::Kind::kPrefix: case Expression::Kind::kPrefix:
if (context.fConfig->fSettings.fOptimize) { if (context.fConfig->fSettings.fOptimize) {

View File

@ -31,7 +31,7 @@ public:
return context.fTypes.fBool.get(); return context.fTypes.fBool.get();
} }
std::unique_ptr<Expression> value(const Context& context) const override { std::unique_ptr<Expression> value(const Context& context) const override {
return std::make_unique<BoolLiteral>(context, /*offset=*/-1, (context.fCaps.*fGetCap)()); return BoolLiteral::Make(context, /*offset=*/-1, (context.fCaps.*fGetCap)());
} }
private: private:
@ -48,7 +48,7 @@ public:
return context.fTypes.fInt.get(); return context.fTypes.fInt.get();
} }
std::unique_ptr<Expression> value(const Context& context) const override { std::unique_ptr<Expression> value(const Context& context) const override {
return std::make_unique<IntLiteral>(context, /*offset=*/-1, (context.fCaps.*fGetCap)()); return IntLiteral::Make(context, /*offset=*/-1, (context.fCaps.*fGetCap)());
} }
private: private:

View File

@ -95,7 +95,7 @@ std::unique_ptr<Expression> Swizzle::Convert(const Context& context,
if (constantZeroIdx == -1) { if (constantZeroIdx == -1) {
// Synthesize a 'type(0)' argument at the end of the constructor. // Synthesize a 'type(0)' argument at the end of the constructor.
ExpressionArray zeroArgs; ExpressionArray zeroArgs;
zeroArgs.push_back(std::make_unique<IntLiteral>(context, offset,/*fValue=*/0)); zeroArgs.push_back(IntLiteral::Make(context, offset, /*value=*/0));
constructorArgs.push_back(Constructor::Convert(context, offset, *numberType, constructorArgs.push_back(Constructor::Convert(context, offset, *numberType,
std::move(zeroArgs))); std::move(zeroArgs)));
constantZeroIdx = constantFieldIdx++; constantZeroIdx = constantFieldIdx++;
@ -106,7 +106,7 @@ std::unique_ptr<Expression> Swizzle::Convert(const Context& context,
if (constantOneIdx == -1) { if (constantOneIdx == -1) {
// Synthesize a 'type(1)' argument at the end of the constructor. // Synthesize a 'type(1)' argument at the end of the constructor.
ExpressionArray oneArgs; ExpressionArray oneArgs;
oneArgs.push_back(std::make_unique<IntLiteral>(context, offset, /*fValue=*/1)); oneArgs.push_back(IntLiteral::Make(context, offset, /*value=*/1));
constructorArgs.push_back(Constructor::Convert(context, offset, *numberType, constructorArgs.push_back(Constructor::Convert(context, offset, *numberType,
std::move(oneArgs))); std::move(oneArgs)));
constantOneIdx = constantFieldIdx++; constantOneIdx = constantFieldIdx++;