SkSL description methods are now only present in debug mode

As they are a significant chunk of code, this reduces the size of the
release executable.

Change-Id: Ib764b3ec6244629e50941b0101a540e49d56c320
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/261955
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2020-01-02 14:40:54 -05:00 committed by Skia Commit-Bot
parent ccd45a5efe
commit 2a099dae1e
66 changed files with 328 additions and 100 deletions

View File

@ -115,8 +115,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
SET_TYPES(Variable::Type::kFloat4x4, kHalf4x4_GrSLType);
} else {
RETURN_FAILURE("Invalid input/uniform type: '%s'",
type->description().c_str());
type->displayName().c_str());
}
#undef SET_TYPES

View File

@ -11,6 +11,7 @@
namespace SkSL {
#ifdef SK_DEBUG
String ASTNode::description() const {
switch (fKind) {
case Kind::kNull: return "";
@ -234,5 +235,6 @@ String ASTNode::description() const {
return "<error>";
}
}
#endif
} // namespace

View File

@ -613,7 +613,9 @@ struct ASTNode {
return iterator(fNodes, ID(-1));
}
#ifdef SK_DEBUG
String description() const;
#endif
std::vector<ASTNode>* fNodes;

View File

@ -27,7 +27,7 @@ static TypeCategory type_category(const Type& type) {
SkASSERT(type.fName == "float" || type.fName == "half");
return TypeCategory::kFloat;
}
ABORT("unsupported type: %s\n", type.description().c_str());
ABORT("unsupported type: %s\n", type.displayName().c_str());
}
}
@ -1303,7 +1303,9 @@ void ByteCodeGenerator::writeExpression(const Expression& e, bool discard) {
this->writeTernaryExpression((TernaryExpression&) e);
break;
default:
#ifdef SK_DEBUG
printf("unsupported expression %s\n", e.description().c_str());
#endif
SkASSERT(false);
}
if (discard) {
@ -1455,7 +1457,9 @@ std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Ex
}
case Expression::kTernary_Kind:
default:
printf("unsupported lvalue %s\n", e.description().c_str());
#ifdef SK_DEBUG
ABORT("unsupported lvalue %s\n", e.description().c_str());
#endif
return nullptr;
}
}

View File

@ -51,6 +51,7 @@ void CFG::addExit(BlockId from, BlockId to) {
}
}
#ifdef SK_DEBUG
void CFG::dump() {
for (size_t i = 0; i < fBlocks.size(); i++) {
printf("Block %d\n-------\nBefore: ", (int) i);
@ -82,6 +83,7 @@ void CFG::dump() {
printf("\n\n");
}
}
#endif
bool BasicBlock::tryRemoveExpressionBefore(std::vector<BasicBlock::Node>::iterator* iter,
Expression* e) {
@ -149,7 +151,10 @@ bool BasicBlock::tryRemoveLValueBefore(std::vector<BasicBlock::Node>::iterator*
}
return this->tryRemoveLValueBefore(iter, ((TernaryExpression*) lvalue)->fIfFalse.get());
default:
#ifdef SK_DEBUG
ABORT("invalid lvalue: %s\n", lvalue->description().c_str());
#endif
return false;
}
}
@ -247,7 +252,10 @@ bool BasicBlock::tryRemoveExpression(std::vector<BasicBlock::Node>::iterator* it
*iter = fNodes.erase(*iter);
return true;
default:
#ifdef SK_DEBUG
ABORT("unhandled expression: %s\n", expr->description().c_str());
#endif
return false;
}
}
@ -655,8 +663,10 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
case Statement::kNop_Kind:
break;
default:
printf("statement: %s\n", (*s)->description().c_str());
ABORT("unsupported statement kind");
#ifdef SK_DEBUG
ABORT("unsupported statement: %s\n", (*s)->description().c_str());
#endif
break;
}
}

View File

@ -53,6 +53,7 @@ struct BasicBlock {
*fStatement = std::move(stmt);
}
#ifdef SK_DEBUG
String description() const {
if (fKind == kStatement_Kind) {
return (*fStatement)->description();
@ -61,6 +62,7 @@ struct BasicBlock {
return (*fExpression)->description();
}
}
#endif
Kind fKind;
// if false, this node should not be subject to constant propagation. This happens with

View File

@ -526,7 +526,8 @@ static bool is_dead(const Expression& lvalue) {
return is_dead(*((FieldAccess&) lvalue).fBase);
case Expression::kIndex_Kind: {
const IndexExpression& idx = (IndexExpression&) lvalue;
return is_dead(*idx.fBase) && !idx.fIndex->hasSideEffects();
return is_dead(*idx.fBase) &&
!idx.fIndex->hasProperty(Expression::Property::kSideEffects);
}
case Expression::kTernary_Kind: {
const TernaryExpression& t = (TernaryExpression&) lvalue;
@ -535,7 +536,10 @@ static bool is_dead(const Expression& lvalue) {
case Expression::kExternalValue_Kind:
return false;
default:
#ifdef SK_DEBUG
ABORT("invalid lvalue: %s\n", lvalue.description().c_str());
#endif
return false;
}
}

View File

@ -392,13 +392,15 @@ private:
Defined(const Type& type)
: INHERITED(-1, kDefined_Kind, type) {}
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}
#ifdef SK_DEBUG
String description() const override {
return "<defined>";
}
#endif
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new Defined(fType));

View File

@ -101,9 +101,11 @@ public:
return nullptr;
}
#ifdef SK_DEBUG
String description() const override {
return String("external<") + fName + ">";
}
#endif
private:
typedef Symbol INHERITED;

View File

@ -235,7 +235,10 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren
this->writeIndexExpression((IndexExpression&) expr);
break;
default:
#ifdef SK_DEBUG
ABORT("unsupported expression: %s", expr.description().c_str());
#endif
break;
}
}
@ -1099,7 +1102,7 @@ void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
Compiler::IsAssignment(b.fOperator) &&
Expression::kFieldAccess_Kind == b.fLeft->fKind &&
is_sk_position((FieldAccess&) *b.fLeft) &&
!strstr(b.fRight->description().c_str(), "sk_RTAdjust") &&
!b.fRight->containsRTAdjust() &&
!fProgram.fSettings.fCaps->canUseFragCoord();
if (positionWorkaround) {
this->write("sk_FragCoord_Workaround = (");
@ -1500,7 +1503,10 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) {
this->write(";");
break;
default:
#ifdef SK_DEBUG
ABORT("unsupported statement: %s", s.description().c_str());
#endif
break;
}
}
@ -1707,8 +1713,10 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
case ProgramElement::kEnum_Kind:
break;
default:
printf("%s\n", e.description().c_str());
ABORT("unsupported program element");
#ifdef SK_DEBUG
printf("unsupported program element %s\n", e.description().c_str());
#endif
SkASSERT(false);
}
}

View File

@ -356,7 +356,7 @@ bool HCodeGenerator::generateCode() {
fFullName.c_str());
for (const auto& p : fProgram) {
if (ProgramElement::kEnum_Kind == p.fKind && !((Enum&) p).fBuiltin) {
this->writef("%s\n", p.description().c_str());
this->writef("%s\n", ((Enum&) p).code().c_str());
}
}
this->writeSection(CLASS_SECTION);

View File

@ -611,7 +611,7 @@ std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
} else {
if (fCurrentFunction->fReturnType != *fContext.fVoid_Type) {
fErrors.error(r.fOffset, "expected function to return '" +
fCurrentFunction->fReturnType.description() + "'");
fCurrentFunction->fReturnType.displayName() + "'");
}
return std::unique_ptr<Statement>(new ReturnStatement(r.fOffset));
}
@ -836,8 +836,8 @@ void IRGenerator::convertFunction(const ASTNode& f) {
if (*returnType != other->fReturnType) {
FunctionDeclaration newDecl(f.fOffset, fd.fModifiers, fd.fName, parameters,
*returnType);
fErrors.error(f.fOffset, "functions '" + newDecl.description() +
"' and '" + other->description() +
fErrors.error(f.fOffset, "functions '" + newDecl.declaration() +
"' and '" + other->declaration() +
"' differ only in return type");
return;
}
@ -853,7 +853,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
if (other->fDefined && !other->fBuiltin) {
fErrors.error(f.fOffset, "duplicate definition of " +
other->description());
other->declaration());
}
break;
}
@ -1151,7 +1151,10 @@ std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr)
case ASTNode::Kind::kTernary:
return this->convertTernaryExpression(expr);
default:
#ifdef SK_DEBUG
ABORT("unsupported expression: %s\n", expr.description().c_str());
#endif
return nullptr;
}
}
@ -1269,8 +1272,8 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
return nullptr;
}
if (expr->coercionCost(type) == INT_MAX) {
fErrors.error(expr->fOffset, "expected '" + type.description() + "', but found '" +
expr->fType.description() + "'");
fErrors.error(expr->fOffset, "expected '" + type.displayName() + "', but found '" +
expr->fType.displayName() + "'");
return nullptr;
}
if (type.kind() == Type::kScalar_Kind) {
@ -1697,8 +1700,8 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode&
&resultType, !Compiler::IsAssignment(op))) {
fErrors.error(expression.fOffset, String("type mismatch: '") +
Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + left->fType.description() +
"', '" + right->fType.description() + "'");
"' cannot operate on '" + left->fType.displayName() +
"', '" + right->fType.displayName() + "'");
return nullptr;
}
if (Compiler::IsAssignment(op)) {
@ -1743,8 +1746,8 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode&
if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
&falseType, &resultType, true) || trueType != falseType) {
fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
ifTrue->fType.description() + "', '" +
ifFalse->fType.description() + "'");
ifTrue->fType.displayName() + "', '" +
ifFalse->fType.displayName() + "'");
return nullptr;
}
ifTrue = this->coerce(std::move(ifTrue), *trueType);
@ -1801,7 +1804,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
for (size_t i = 0; i < arguments.size(); i++) {
msg += separator;
separator = ", ";
msg += arguments[i]->fType.description();
msg += arguments[i]->fType.displayName();
}
msg += ")";
fErrors.error(offset, msg);
@ -1903,7 +1906,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
for (size_t i = 0; i < arguments.size(); i++) {
msg += separator;
separator = ", ";
msg += arguments[i]->fType.description();
msg += arguments[i]->fType.displayName();
}
msg += ")";
fErrors.error(offset, msg);
@ -1912,7 +1915,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
return this->call(offset, *ref->fFunctions[0], std::move(arguments));
}
default:
fErrors.error(offset, "'" + functionValue->description() + "' is not a function");
fErrors.error(offset, "not a function");
return nullptr;
}
}
@ -1923,7 +1926,7 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
std::vector<std::unique_ptr<Expression>> args) {
SkASSERT(type.isNumber());
if (args.size() != 1) {
fErrors.error(offset, "invalid arguments to '" + type.description() +
fErrors.error(offset, "invalid arguments to '" + type.displayName() +
"' constructor, (expected exactly 1 argument, but found " +
to_string((uint64_t) args.size()) + ")");
return nullptr;
@ -1955,9 +1958,9 @@ std::unique_ptr<Expression> IRGenerator::convertNumberConstructor(
type)));
}
if (!args[0]->fType.isNumber()) {
fErrors.error(offset, "invalid argument to '" + type.description() +
fErrors.error(offset, "invalid argument to '" + type.displayName() +
"' constructor (expected a number or bool, but found '" +
args[0]->fType.description() + "')");
args[0]->fType.displayName() + "')");
return nullptr;
}
return std::unique_ptr<Expression>(new Constructor(offset, type, std::move(args)));
@ -1992,8 +1995,8 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
if (args[i]->fType.kind() == Type::kVector_Kind) {
if (type.componentType().isNumber() !=
args[i]->fType.componentType().isNumber()) {
fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
"parameter to '" + type.description() +
fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
"parameter to '" + type.displayName() +
"' constructor");
return nullptr;
}
@ -2007,13 +2010,13 @@ std::unique_ptr<Expression> IRGenerator::convertCompoundConstructor(
}
}
} else {
fErrors.error(offset, "'" + args[i]->fType.description() + "' is not a valid "
"parameter to '" + type.description() + "' constructor");
fErrors.error(offset, "'" + args[i]->fType.displayName() + "' is not a valid "
"parameter to '" + type.displayName() + "' constructor");
return nullptr;
}
}
if (actual != 1 && actual != expected) {
fErrors.error(offset, "invalid arguments to '" + type.description() +
fErrors.error(offset, "invalid arguments to '" + type.displayName() +
"' constructor (expected " + to_string(expected) +
" scalars, but found " + to_string(actual) + ")");
return nullptr;
@ -2046,7 +2049,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
} else if (kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) {
return this->convertCompoundConstructor(offset, type, std::move(args));
} else {
fErrors.error(offset, "cannot construct '" + type.description() + "'");
fErrors.error(offset, "cannot construct '" + type.displayName() + "'");
return nullptr;
}
}
@ -2062,7 +2065,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
base->fType != *fContext.fFloatLiteral_Type) {
fErrors.error(expression.fOffset,
"'+' cannot operate on '" + base->fType.description() + "'");
"'+' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
return base;
@ -2078,7 +2081,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
}
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
fErrors.error(expression.fOffset,
"'-' cannot operate on '" + base->fType.description() + "'");
"'-' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
@ -2086,7 +2089,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (!base->fType.isNumber()) {
fErrors.error(expression.fOffset,
String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
"' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
@ -2095,7 +2098,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (!base->fType.isNumber()) {
fErrors.error(expression.fOffset,
String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
"' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
@ -2104,7 +2107,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (base->fType != *fContext.fBool_Type) {
fErrors.error(expression.fOffset,
String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
"' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
if (base->fKind == Expression::kBoolLiteral_Kind) {
@ -2116,7 +2119,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
if (base->fType != *fContext.fInt_Type && base->fType != *fContext.fUInt_Type) {
fErrors.error(expression.fOffset,
String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
"' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
break;
@ -2146,7 +2149,7 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
}
if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
base->fType.kind() != Type::kVector_Kind) {
fErrors.error(base->fOffset, "expected array, but found '" + base->fType.description() +
fErrors.error(base->fOffset, "expected array, but found '" + base->fType.displayName() +
"'");
return nullptr;
}
@ -2182,7 +2185,7 @@ std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression
return std::unique_ptr<Expression>(new FieldAccess(std::move(base), (int) i));
}
}
fErrors.error(base->fOffset, "type '" + base->fType.description() + "' does not have a "
fErrors.error(base->fOffset, "type '" + base->fType.displayName() + "' does not have a "
"field named '" + field + "");
return nullptr;
}
@ -2190,7 +2193,7 @@ std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression
std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
StringFragment fields) {
if (base->fType.kind() != Type::kVector_Kind) {
fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.description() + "'");
fErrors.error(base->fOffset, "cannot swizzle type '" + base->fType.displayName() + "'");
return nullptr;
}
std::vector<int> swizzleComponents;
@ -2371,7 +2374,7 @@ std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& f
return this->convertField(std::move(base), field);
default:
fErrors.error(base->fOffset, "cannot swizzle value of type '" +
base->fType.description() + "'");
base->fType.displayName() + "'");
return nullptr;
}
}
@ -2384,7 +2387,7 @@ std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode&
if (!base->fType.isNumber()) {
fErrors.error(expression.fOffset,
"'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
"' cannot operate on '" + base->fType.description() + "'");
"' cannot operate on '" + base->fType.displayName() + "'");
return nullptr;
}
this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
@ -2464,7 +2467,7 @@ void IRGenerator::setRefKind(const Expression& expr, VariableReference::RefKind
break;
}
default:
fErrors.error(expr.fOffset, "cannot assign to '" + expr.description() + "'");
fErrors.error(expr.fOffset, "cannot assign to this expression");
break;
}
}
@ -2531,7 +2534,10 @@ void IRGenerator::convertProgram(Program::Kind kind,
break;
}
default:
#ifdef SK_DEBUG
ABORT("unsupported declaration: %s\n", decl.description().c_str());
#endif
break;
}
}
}

View File

@ -158,7 +158,10 @@ void MetalCodeGenerator::writeExpression(const Expression& expr, Precedence pare
this->writeIndexExpression((IndexExpression&) expr);
break;
default:
#ifdef SK_DEBUG
ABORT("unsupported expression: %s", expr.description().c_str());
#endif
break;
}
}
@ -1177,7 +1180,10 @@ void MetalCodeGenerator::writeStatement(const Statement& s) {
this->write(";");
break;
default:
#ifdef SK_DEBUG
ABORT("unsupported statement: %s", s.description().c_str());
#endif
break;
}
}
@ -1498,8 +1504,10 @@ void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
this->writeLine(";");
break;
default:
printf("%s\n", e.description().c_str());
ABORT("unsupported program element");
#ifdef SK_DEBUG
ABORT("unsupported program element: %s\n", e.description().c_str());
#endif
break;
}
}

View File

@ -560,7 +560,9 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
if (type == *fContext.fVoid_Type) {
this->writeInstruction(SpvOpTypeVoid, result, fConstantBuffer);
} else {
#ifdef SK_DEBUG
ABORT("invalid type: %s", type.description().c_str());
#endif
}
}
fTypeMap[key] = result;
@ -578,12 +580,12 @@ SpvId SPIRVCodeGenerator::getImageType(const Type& type) {
}
SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) {
String key = function.fReturnType.description() + "(";
String key = function.fReturnType.displayName() + "(";
String separator;
for (size_t i = 0; i < function.fParameters.size(); i++) {
key += separator;
separator = ", ";
key += function.fParameters[i]->fType.description();
key += function.fParameters[i]->fType.displayName();
}
key += ")";
auto entry = fTypeMap.find(key);
@ -641,7 +643,7 @@ SpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ stor
SpvId SPIRVCodeGenerator::getPointerType(const Type& rawType, const MemoryLayout& layout,
SpvStorageClass_ storageClass) {
Type type = this->getActualType(rawType);
String key = type.description() + "*" + to_string(layout.fStd) + to_string(storageClass);
String key = type.displayName() + "*" + to_string(layout.fStd) + to_string(storageClass);
auto entry = fTypeMap.find(key);
if (entry == fTypeMap.end()) {
SpvId result = this->nextId();
@ -682,7 +684,10 @@ SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream&
case Expression::kIndex_Kind:
return this->writeIndexExpression((IndexExpression&) expr, out);
default:
#ifdef SK_DEBUG
ABORT("unsupported expression: %s", expr.description().c_str());
#endif
break;
}
return -1;
}
@ -1507,7 +1512,10 @@ SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, OutputStream& o
case Type::kArray_Kind:
return this->writeArrayConstructor(c, out);
default:
#ifdef SK_DEBUG
ABORT("unsupported constructor: %s", c.description().c_str());
#endif
return -1;
}
}
@ -1972,7 +1980,9 @@ SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
this->writeInstruction(ifBool, this->getType(resultType), result, lhs, rhs, out);
return result; // skip RelaxedPrecision check
} else {
#ifdef SK_DEBUG
ABORT("invalid operandType: %s", operandType.description().c_str());
#endif
}
if (getActualType(resultType) == operandType && !resultType.highPrecision()) {
this->writeInstruction(SpvOpDecorate, result, SpvDecorationRelaxedPrecision,
@ -2388,7 +2398,9 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, Outpu
} else if (is_signed(fContext, p.fType)) {
this->writeInstruction(SpvOpSNegate, typeId, result, expr, out);
} else {
#ifdef SK_DEBUG
ABORT("unsupported prefix expression %s", p.description().c_str());
#endif
}
this->writePrecisionModifier(p.fType, result);
return result;
@ -2428,7 +2440,10 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, Outpu
return result;
}
default:
#ifdef SK_DEBUG
ABORT("unsupported prefix expression: %s", p.description().c_str());
#endif
return -1;
}
}
@ -2450,7 +2465,10 @@ SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, Out
return result;
}
default:
#ifdef SK_DEBUG
ABORT("unsupported postfix expression %s", p.description().c_str());
#endif
return -1;
}
}
@ -2868,7 +2886,10 @@ void SPIRVCodeGenerator::writeStatement(const Statement& s, OutputStream& out) {
this->writeInstruction(SpvOpKill, out);
break;
default:
#ifdef SK_DEBUG
ABORT("unsupported statement: %s", s.description().c_str());
#endif
break;
}
}

View File

@ -34,9 +34,11 @@ struct BinaryExpression : public Expression {
*fRight);
}
bool hasSideEffects() const override {
return Compiler::IsAssignment(fOperator) || fLeft->hasSideEffects() ||
fRight->hasSideEffects();
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && Compiler::IsAssignment(fOperator)) {
return true;
}
return fLeft->hasProperty(property) || fRight->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
@ -44,10 +46,12 @@ struct BinaryExpression : public Expression {
fRight->clone(), fType));
}
#ifdef SK_DEBUG
String description() const override {
return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
fRight->description() + ")";
}
#endif
std::unique_ptr<Expression> fLeft;
const Token::Kind fOperator;

View File

@ -40,6 +40,7 @@ struct Block : public Statement {
return std::unique_ptr<Statement>(new Block(fOffset, std::move(cloned), fSymbols));
}
#ifdef SK_DEBUG
String description() const override {
String result("{");
for (size_t i = 0; i < fStatements.size(); i++) {
@ -49,6 +50,7 @@ struct Block : public Statement {
result += "\n}\n";
return result;
}
#endif
// it's important to keep fStatements defined after (and thus destroyed before) fSymbols,
// because destroying statements can modify reference counts in symbols

View File

@ -21,11 +21,13 @@ struct BoolLiteral : public Expression {
: INHERITED(offset, kBoolLiteral_Kind, *context.fBool_Type)
, fValue(value) {}
#ifdef SK_DEBUG
String description() const override {
return String(fValue ? "true" : "false");
}
#endif
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}

View File

@ -24,9 +24,11 @@ struct BreakStatement : public Statement {
return std::unique_ptr<Statement>(new BreakStatement(fOffset));
}
#ifdef SK_DEBUG
String description() const override {
return String("break;");
}
#endif
typedef Statement INHERITED;
};

View File

@ -50,9 +50,9 @@ struct Constructor : public Expression {
return nullptr;
}
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
for (const auto& arg : fArguments) {
if (arg->hasSideEffects()) {
if (arg->hasProperty(property)) {
return true;
}
}
@ -67,6 +67,7 @@ struct Constructor : public Expression {
return std::unique_ptr<Expression>(new Constructor(fOffset, fType, std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
String result = fType.description() + "(";
String separator;
@ -78,6 +79,7 @@ struct Constructor : public Expression {
result += ")";
return result;
}
#endif
bool isConstant() const override {
for (size_t i = 0; i < fArguments.size(); i++) {
@ -156,7 +158,10 @@ struct Constructor : public Expression {
current += arg->fType.columns();
}
}
#ifdef SK_DEBUG
ABORT("failed to find vector component %d in %s\n", index, description().c_str());
#endif
return -1;
}
SKSL_FLOAT getFVecComponent(int n) const override {

View File

@ -24,9 +24,11 @@ struct ContinueStatement : public Statement {
return std::unique_ptr<Statement>(new ContinueStatement(fOffset));
}
#ifdef SK_DEBUG
String description() const override {
return String("continue;");
}
#endif
typedef Statement INHERITED;
};

View File

@ -24,9 +24,11 @@ struct DiscardStatement : public Statement {
return std::unique_ptr<Statement>(new DiscardStatement(fOffset));
}
#ifdef SK_DEBUG
String description() const override {
return String("discard;");
}
#endif
typedef Statement INHERITED;
};

View File

@ -28,9 +28,11 @@ struct DoStatement : public Statement {
fTest->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return "do " + fStatement->description() + " while (" + fTest->description() + ");";
}
#endif
std::unique_ptr<Statement> fStatement;
std::unique_ptr<Expression> fTest;

View File

@ -30,7 +30,7 @@ struct Enum : public ProgramElement {
return std::unique_ptr<ProgramElement>(new Enum(fOffset, fTypeName, fSymbols));
}
String description() const override {
String code() const {
String result = "enum class " + fTypeName + " {\n";
String separator;
std::vector<const Symbol*> sortedSymbols;
@ -40,14 +40,22 @@ struct Enum : public ProgramElement {
std::sort(sortedSymbols.begin(), sortedSymbols.end(),
[](const Symbol* a, const Symbol* b) { return a->fName < b->fName; });
for (const auto& s : sortedSymbols) {
const Expression& initialValue = *((Variable*) s)->fInitialValue;
SkASSERT(initialValue.fKind == Expression::kIntLiteral_Kind);
result += separator + " " + s->fName + " = " +
((Variable*) s)->fInitialValue->description();
to_string(((IntLiteral&) initialValue).fValue);
separator = ",\n";
}
result += "\n};";
return result;
}
#ifdef SK_DEBUG
String description() const override {
return this->code();
}
#endif
bool fBuiltin = false;
const StringFragment fTypeName;
const std::shared_ptr<SymbolTable> fSymbols;

View File

@ -47,6 +47,11 @@ struct Expression : public IRNode {
kDefined_Kind
};
enum class Property {
kSideEffects,
kContainsRTAdjust
};
Expression(int offset, Kind kind, const Type& type)
: INHERITED(offset)
, fKind(kind)
@ -85,12 +90,15 @@ struct Expression : public IRNode {
ABORT("not a constant float");
}
/**
* Returns true if evaluating the expression potentially has side effects. Expressions may never
* return false if they actually have side effects, but it is legal (though suboptimal) to
* return true if there are not actually any side effects.
*/
virtual bool hasSideEffects() const = 0;
virtual bool hasProperty(Property property) const = 0;
bool hasSideEffects() const {
return this->hasProperty(Property::kSideEffects);
}
bool containsRTAdjust() const {
return this->hasProperty(Property::kContainsRTAdjust);
}
/**
* Given a map of known constant variable values, substitute them in for references to those

View File

@ -25,9 +25,11 @@ struct ExpressionStatement : public Statement {
return std::unique_ptr<Statement>(new ExpressionStatement(fExpression->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return fExpression->description() + ";";
}
#endif
std::unique_ptr<Expression> fExpression;

View File

@ -24,9 +24,11 @@ struct Extension : public ProgramElement {
return std::unique_ptr<ProgramElement>(new Extension(fOffset, fName));
}
#ifdef SK_DEBUG
String description() const override {
return "#extension " + fName + " : enable";
}
#endif
const String fName;

View File

@ -24,8 +24,16 @@ struct ExternalFunctionCall : public Expression {
, fFunction(function)
, fArguments(std::move(arguments)) {}
bool hasSideEffects() const override {
return true;
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects) {
return true;
}
for (const auto& arg : fArguments) {
if (arg->hasProperty(property)) {
return true;
}
}
return false;
}
std::unique_ptr<Expression> clone() const override {
@ -39,6 +47,7 @@ struct ExternalFunctionCall : public Expression {
std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
String result = String(fFunction->fName) + "(";
String separator;
@ -50,6 +59,7 @@ struct ExternalFunctionCall : public Expression {
result += ")";
return result;
}
#endif
ExternalValue* fFunction;
std::vector<std::unique_ptr<Expression>> fArguments;

View File

@ -21,13 +21,15 @@ struct ExternalValueReference : public Expression {
: INHERITED(offset, kExternalValue_Kind, ev->type())
, fValue(ev) {}
bool hasSideEffects() const override {
return true;
bool hasProperty(Property property) const override {
return property == Property::kSideEffects;
}
#ifdef SK_DEBUG
String description() const override {
return String(fValue->fName);
}
#endif
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new ExternalValueReference(fOffset, fValue));

View File

@ -27,9 +27,11 @@ struct Field : public Symbol {
, fOwner(owner)
, fFieldIndex(fieldIndex) {}
#ifdef SK_DEBUG
virtual String description() const override {
return fOwner.description() + "." + fOwner.fType.fields()[fFieldIndex].fName;
}
#endif
const Variable& fOwner;
const int fFieldIndex;

View File

@ -31,8 +31,8 @@ struct FieldAccess : public Expression {
, fFieldIndex(fieldIndex)
, fOwnerKind(ownerKind) {}
bool hasSideEffects() const override {
return fBase->hasSideEffects();
bool hasProperty(Property property) const override {
return fBase->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
@ -40,9 +40,11 @@ struct FieldAccess : public Expression {
fOwnerKind));
}
#ifdef SK_DEBUG
String description() const override {
return fBase->description() + "." + fBase->fType.fields()[fFieldIndex].fName;
}
#endif
std::unique_ptr<Expression> fBase;
const int fFieldIndex;

View File

@ -25,11 +25,13 @@ struct FloatLiteral : public Expression {
: INHERITED(offset, kFloatLiteral_Kind, *type)
, fValue(value) {}
#ifdef SK_DEBUG
String description() const override {
return to_string(fValue);
}
#endif
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}

View File

@ -34,6 +34,7 @@ struct ForStatement : public Statement {
fStatement->clone(), fSymbols));
}
#ifdef SK_DEBUG
String description() const override {
String result("for (");
if (fInitializer) {
@ -50,6 +51,7 @@ struct ForStatement : public Statement {
result += ") " + fStatement->description();
return result;
}
#endif
// it's important to keep fSymbols defined first (and thus destroyed last) because destroying
// the other fields can update symbol reference counts

View File

@ -23,13 +23,17 @@ struct FunctionCall : public Expression {
, fFunction(std::move(function))
, fArguments(std::move(arguments)) {}
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && (fFunction.fModifiers.fFlags &
Modifiers::kHasSideEffects_Flag)) {
return true;
}
for (const auto& arg : fArguments) {
if (arg->hasSideEffects()) {
if (arg->hasProperty(property)) {
return true;
}
}
return fFunction.fModifiers.fFlags & Modifiers::kHasSideEffects_Flag;
return false;
}
std::unique_ptr<Expression> clone() const override {
@ -41,6 +45,7 @@ struct FunctionCall : public Expression {
std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
String result = String(fFunction.fName) + "(";
String separator;
@ -52,6 +57,7 @@ struct FunctionCall : public Expression {
result += ")";
return result;
}
#endif
const FunctionDeclaration& fFunction;
std::vector<std::unique_ptr<Expression>> fArguments;

View File

@ -30,18 +30,24 @@ struct FunctionDeclaration : public Symbol {
, fParameters(std::move(parameters))
, fReturnType(returnType) {}
String description() const override {
String result = fReturnType.description() + " " + fName + "(";
String declaration() const {
String result = fReturnType.displayName() + " " + fName + "(";
String separator;
for (auto p : fParameters) {
result += separator;
separator = ", ";
result += p->description();
result += p->fName;
}
result += ")";
return result;
}
#ifdef SK_DEBUG
String description() const override {
return this->declaration();
}
#endif
bool matches(const FunctionDeclaration& f) const {
if (fName != f.fName) {
return false;

View File

@ -31,9 +31,11 @@ struct FunctionDefinition : public ProgramElement {
fBody->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return fDeclaration.description() + " " + fBody->description();
}
#endif
const FunctionDeclaration& fDeclaration;
std::unique_ptr<Statement> fBody;

View File

@ -24,7 +24,7 @@ struct FunctionReference : public Expression {
: INHERITED(offset, kFunctionReference_Kind, *context.fInvalid_Type)
, fFunctions(function) {}
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}
@ -32,9 +32,11 @@ struct FunctionReference : public Expression {
return std::unique_ptr<Expression>(new FunctionReference(fOffset, fFunctions, &fType));
}
#ifdef SK_DEBUG
String description() const override {
return String("<function>");
}
#endif
const std::vector<const FunctionDeclaration*> fFunctions;

View File

@ -23,7 +23,9 @@ struct IRNode {
virtual ~IRNode() {}
#ifdef SK_DEBUG
virtual String description() const = 0;
#endif
// character offset of this element within the program being compiled, for error reporting
// purposes

View File

@ -30,6 +30,7 @@ struct IfStatement : public Statement {
fIfTrue->clone(), fIfFalse ? fIfFalse->clone() : nullptr));
}
#ifdef SK_DEBUG
String description() const override {
String result;
if (fIsStatic) {
@ -41,6 +42,7 @@ struct IfStatement : public Statement {
}
return result;
}
#endif
bool fIsStatic;
std::unique_ptr<Expression> fTest;

View File

@ -58,8 +58,8 @@ struct IndexExpression : public Expression {
SkASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type);
}
bool hasSideEffects() const override {
return fBase->hasSideEffects() || fIndex->hasSideEffects();
bool hasProperty(Property property) const override {
return fBase->hasProperty(property) || fIndex->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
@ -67,9 +67,11 @@ struct IndexExpression : public Expression {
&fType));
}
#ifdef SK_DEBUG
String description() const override {
return fBase->description() + "[" + fIndex->description() + "]";
}
#endif
std::unique_ptr<Expression> fBase;
std::unique_ptr<Expression> fIndex;

View File

@ -27,11 +27,13 @@ struct IntLiteral : public Expression {
: INHERITED(offset, kIntLiteral_Kind, *type)
, fValue(value) {}
#ifdef SK_DEBUG
String description() const override {
return to_string(fValue);
}
#endif
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}

View File

@ -46,6 +46,7 @@ struct InterfaceBlock : public ProgramElement {
fTypeOwner));
}
#ifdef SK_DEBUG
String description() const override {
String result = fVariable.fModifiers.description() + fTypeName + " {\n";
const Type* structType = &fVariable.fType;
@ -68,6 +69,7 @@ struct InterfaceBlock : public ProgramElement {
}
return result + ";";
}
#endif
const Variable& fVariable;
const String fTypeName;

View File

@ -27,9 +27,11 @@ struct ModifiersDeclaration : public ProgramElement {
return std::unique_ptr<ProgramElement>(new ModifiersDeclaration(fModifiers));
}
#ifdef SK_DEBUG
String description() const override {
return fModifiers.description() + ";";
}
#endif
Modifiers fModifiers;

View File

@ -24,9 +24,11 @@ struct Nop : public Statement {
return true;
}
#ifdef SK_DEBUG
String description() const override {
return String(";");
}
#endif
std::unique_ptr<Statement> clone() const override {
return std::unique_ptr<Statement>(new Nop());

View File

@ -23,11 +23,13 @@ struct NullLiteral : public Expression {
NullLiteral(int offset, const Type& type)
: INHERITED(offset, kNullLiteral_Kind, type) {}
#ifdef SK_DEBUG
String description() const override {
return "null";
}
#endif
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}

View File

@ -23,17 +23,22 @@ struct PostfixExpression : public Expression {
, fOperand(std::move(operand))
, fOperator(op) {}
bool hasSideEffects() const override {
return true;
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects) {
return true;
}
return fOperand->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new PostfixExpression(fOperand->clone(), fOperator));
}
#ifdef SK_DEBUG
String description() const override {
return fOperand->description() + Compiler::OperatorName(fOperator);
}
#endif
std::unique_ptr<Expression> fOperand;
const Token::Kind fOperator;

View File

@ -29,9 +29,12 @@ struct PrefixExpression : public Expression {
return fOperator == Token::MINUS && fOperand->isConstant();
}
bool hasSideEffects() const override {
return fOperator == Token::PLUSPLUS || fOperator == Token::MINUSMINUS ||
fOperand->hasSideEffects();
bool hasProperty(Property property) const override {
if (property == Property::kSideEffects && (fOperator == Token::PLUSPLUS ||
fOperator == Token::MINUSMINUS)) {
return true;
}
return fOperand->hasProperty(property);
}
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
@ -65,9 +68,11 @@ struct PrefixExpression : public Expression {
return std::unique_ptr<Expression>(new PrefixExpression(fOperator, fOperand->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return Compiler::OperatorName(fOperator) + fOperand->description();
}
#endif
std::unique_ptr<Expression> fOperand;
const Token::Kind fOperator;

View File

@ -31,6 +31,7 @@ struct ReturnStatement : public Statement {
return std::unique_ptr<Statement>(new ReturnStatement(fOffset));
}
#ifdef SK_DEBUG
String description() const override {
if (fExpression) {
return "return " + fExpression->description() + ";";
@ -38,6 +39,7 @@ struct ReturnStatement : public Statement {
return String("return;");
}
}
#endif
std::unique_ptr<Expression> fExpression;

View File

@ -26,6 +26,7 @@ struct Section : public ProgramElement {
return std::unique_ptr<ProgramElement>(new Section(fOffset, fName, fArgument, fText));
}
#ifdef SK_DEBUG
String description() const override {
String result = "@" + fName;
if (fArgument.size()) {
@ -34,6 +35,7 @@ struct Section : public ProgramElement {
result += " { " + fText + " }";
return result;
}
#endif
const String fName;
const String fArgument;

View File

@ -32,11 +32,13 @@ struct Setting : public Expression {
return std::unique_ptr<Expression>(new Setting(fOffset, fName, fValue->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return fName;
}
#endif
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}

View File

@ -33,6 +33,7 @@ struct SwitchCase : public Statement {
std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
String result;
if (fValue) {
@ -45,6 +46,7 @@ struct SwitchCase : public Statement {
}
return result;
}
#endif
// null value implies "default" case
std::unique_ptr<Expression> fValue;

View File

@ -37,6 +37,7 @@ struct SwitchStatement : public Statement {
std::move(cloned), fSymbols));
}
#ifdef SK_DEBUG
String description() const override {
String result;
if (fIsStatic) {
@ -49,6 +50,7 @@ struct SwitchStatement : public Statement {
result += "}";
return result;
}
#endif
bool fIsStatic;
std::unique_ptr<Expression> fValue;

View File

@ -93,7 +93,10 @@ static const Type& get_type(const Context& context, Expression& value, size_t co
case 4: return *context.fBool4_Type;
}
}
#ifdef SK_DEBUG
ABORT("cannot swizzle %s\n", value.description().c_str());
#endif
return value.fType;
}
/**
@ -129,14 +132,15 @@ struct Swizzle : public Expression {
return nullptr;
}
bool hasSideEffects() const override {
return fBase->hasSideEffects();
bool hasProperty(Property property) const override {
return fBase->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new Swizzle(fType, fBase->clone(), fComponents));
}
#ifdef SK_DEBUG
String description() const override {
String result = fBase->description() + ".";
for (int x : fComponents) {
@ -144,6 +148,7 @@ struct Swizzle : public Expression {
}
return result;
}
#endif
std::unique_ptr<Expression> fBase;
std::vector<int> fComponents;

View File

@ -26,8 +26,9 @@ struct TernaryExpression : public Expression {
SkASSERT(fIfTrue->fType == fIfFalse->fType);
}
bool hasSideEffects() const override {
return fTest->hasSideEffects() || fIfTrue->hasSideEffects() || fIfFalse->hasSideEffects();
bool hasProperty(Property property) const override {
return fTest->hasProperty(property) || fIfTrue->hasProperty(property) ||
fIfFalse->hasProperty(property);
}
std::unique_ptr<Expression> clone() const override {
@ -36,10 +37,12 @@ struct TernaryExpression : public Expression {
fIfFalse->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " +
fIfFalse->description() + ")";
}
#endif
std::unique_ptr<Expression> fTest;
std::unique_ptr<Expression> fIfTrue;

View File

@ -226,7 +226,10 @@ const Type& Type::toCompound(const Context& context, int columns, int rows) cons
default: ABORT("unsupported row count (%d)", rows);
}
}
#ifdef SK_DEBUG
ABORT("unsupported scalar_to_compound type %s", this->description().c_str());
#endif
return *context.fVoid_Type;
}
} // namespace

View File

@ -33,7 +33,7 @@ public:
, fType(std::move(type)) {}
const String description() const {
return fType->description() + " " + fName + ";";
return fType->displayName() + " " + fName + ";";
}
Modifiers fModifiers;
@ -232,7 +232,7 @@ public:
return fNameString;
}
String description() const override {
const String displayName() const {
if (fNameString == "$floatLiteral") {
return "float";
}
@ -242,6 +242,12 @@ public:
return fNameString;
}
#ifdef SK_DEBUG
String description() const override {
return this->displayName();
}
#endif
bool operator==(const Type& other) const {
return fName == other.fName;
}

View File

@ -22,13 +22,15 @@ struct TypeReference : public Expression {
: INHERITED(offset, kTypeReference_Kind, *context.fInvalid_Type)
, fValue(value) {}
bool hasSideEffects() const override {
bool hasProperty(Property property) const override {
return false;
}
#ifdef SK_DEBUG
String description() const override {
return String(fValue.fName);
}
#endif
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new TypeReference(fOffset, fValue, &fType));

View File

@ -26,9 +26,11 @@ struct UnresolvedFunction : public Symbol {
#endif
}
#ifdef SK_DEBUG
String description() const override {
return fName;
}
#endif
const std::vector<const FunctionDeclaration*> fFunctions;

View File

@ -42,6 +42,7 @@ struct VarDeclaration : public Statement {
fValue ? fValue->clone() : nullptr));
}
#ifdef SK_DEBUG
String description() const override {
String result = fVar->fName;
for (const auto& size : fSizes) {
@ -56,6 +57,7 @@ struct VarDeclaration : public Statement {
}
return result;
}
#endif
const Variable* fVar;
std::vector<std::unique_ptr<Expression>> fSizes;
@ -87,6 +89,7 @@ struct VarDeclarations : public ProgramElement {
std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
if (!fVars.size()) {
return String();
@ -101,6 +104,7 @@ struct VarDeclarations : public ProgramElement {
}
return result;
}
#endif
const Type& fBaseType;
// this *should* be a vector of unique_ptr<VarDeclaration>, but it significantly simplifies the

View File

@ -35,9 +35,11 @@ struct VarDeclarationsStatement : public Statement {
return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(cloned)));
}
#ifdef SK_DEBUG
String description() const override {
return fDeclaration->description() + ";";
}
#endif
std::unique_ptr<VarDeclarations> fDeclaration;

View File

@ -48,9 +48,11 @@ struct Variable : public Symbol {
SkASSERT(!fReadCount && !fWriteCount);
}
#ifdef SK_DEBUG
virtual String description() const override {
return fModifiers.description() + fType.fName + " " + fName;
}
#endif
bool dead() const {
if ((fStorage != kLocal_Storage && fReadCount) ||

View File

@ -41,8 +41,14 @@ struct VariableReference : public Expression {
void setRefKind(RefKind refKind);
bool hasSideEffects() const override {
return false;
bool hasProperty(Property property) const override {
switch (property) {
case Property::kSideEffects: return false;
case Property::kContainsRTAdjust: return fVariable.fName == "sk_RTAdjust";
default:
SkASSERT(false);
return false;
}
}
bool isConstant() const override {
@ -53,9 +59,11 @@ struct VariableReference : public Expression {
return std::unique_ptr<Expression>(new VariableReference(fOffset, fVariable, fRefKind));
}
#ifdef SK_DEBUG
String description() const override {
return fVariable.fName;
}
#endif
static std::unique_ptr<Expression> copy_constant(const IRGenerator& irGenerator,
const Expression* expr);

View File

@ -28,9 +28,11 @@ struct WhileStatement : public Statement {
fStatement->clone()));
}
#ifdef SK_DEBUG
String description() const override {
return "while (" + fTest->description() + ") " + fStatement->description();
}
#endif
std::unique_ptr<Expression> fTest;
std::unique_ptr<Statement> fStatement;

View File

@ -28,6 +28,7 @@ struct DFAState {
return !(*this == other);
}
#ifdef SK_DEBUG
std::string description() const {
std::string result = "<";
const char* separator = "";
@ -39,6 +40,7 @@ struct DFAState {
result += ">";
return result;
}
#endif
};
DFAState()

View File

@ -79,6 +79,7 @@ struct NFAState {
}
}
#ifdef SK_DEBUG
std::string description() const {
switch (fKind) {
case kAccept_Kind:
@ -134,6 +135,7 @@ struct NFAState {
ABORT("unreachable");
}
}
#endif
Kind fKind;

View File

@ -82,6 +82,7 @@ std::vector<int> RegexNode::createStates(NFA* nfa, const std::vector<int>& accep
return result;
}
#ifdef SK_DEBUG
std::string RegexNode::description() const {
switch (fKind) {
case kChar_Kind:
@ -115,3 +116,4 @@ std::string RegexNode::description() const {
return "<" + std::to_string(fKind) + ">";
}
}
#endif

View File

@ -270,7 +270,7 @@ DEF_TEST(SkSLBinaryTypeMismatch, r) {
DEF_TEST(SkSLCallNonFunction, r) {
test_failure(r,
"void main() { float x = 3; x(); }",
"error: 1: 'x' is not a function\n1 error\n");
"error: 1: not a function\n1 error\n");
}
DEF_TEST(SkSLInvalidUnary, r) {
@ -302,7 +302,7 @@ DEF_TEST(SkSLInvalidUnary, r) {
DEF_TEST(SkSLInvalidAssignment, r) {
test_failure(r,
"void main() { 1 = 2; }",
"error: 1: cannot assign to '1'\n1 error\n");
"error: 1: cannot assign to this expression\n1 error\n");
test_failure(r,
"uniform int x; void main() { x = 0; }",
"error: 1: cannot modify immutable variable 'x'\n1 error\n");