Add a reference to the ErrorReporter to the SkSL Context.

This will allow errors to be reported outside of the IRGenerator more
easily (without passing around an ErrorReporter object).

Change-Id: I4bcb59fcd526599fa593fcb3b1de0a5ae64ab901
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/352737
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
John Stiles 2021-01-11 16:13:08 -05:00 committed by Skia Commit-Bot
parent c92df39de0
commit b30151eb73
10 changed files with 269 additions and 214 deletions

View File

@ -85,7 +85,7 @@ public:
}; };
Compiler::Compiler(const ShaderCapsClass* caps, Flags flags) Compiler::Compiler(const ShaderCapsClass* caps, Flags flags)
: fContext(std::make_shared<Context>()) : fContext(std::make_shared<Context>(/*errors=*/*this))
, fCaps(caps) , fCaps(caps)
, fInliner(fContext.get()) , fInliner(fContext.get())
, fFlags(flags) , fFlags(flags)
@ -93,7 +93,7 @@ Compiler::Compiler(const ShaderCapsClass* caps, Flags flags)
SkASSERT(fCaps); SkASSERT(fCaps);
fRootSymbolTable = std::make_shared<SymbolTable>(this, /*builtin=*/true); fRootSymbolTable = std::make_shared<SymbolTable>(this, /*builtin=*/true);
fPrivateSymbolTable = std::make_shared<SymbolTable>(fRootSymbolTable, /*builtin=*/true); fPrivateSymbolTable = std::make_shared<SymbolTable>(fRootSymbolTable, /*builtin=*/true);
fIRGenerator = std::make_unique<IRGenerator>(fContext.get(), fCaps, *this); fIRGenerator = std::make_unique<IRGenerator>(fContext.get(), fCaps);
#define TYPE(t) fContext->fTypes.f ## t .get() #define TYPE(t) fContext->fTypes.f ## t .get()

View File

@ -49,7 +49,6 @@ static std::unique_ptr<Expression> short_circuit_boolean(const Expression& left,
template <typename T> template <typename T>
static std::unique_ptr<Expression> simplify_vector(const Context& context, static std::unique_ptr<Expression> simplify_vector(const Context& context,
ErrorReporter& errors,
const Expression& left, const Expression& left,
Token::Kind op, Token::Kind op,
const Expression& right) { const Expression& right) {
@ -101,7 +100,7 @@ static std::unique_ptr<Expression> simplify_vector(const Context& context,
case Token::Kind::TK_STAR: return vectorComponentwiseFold([](T a, T b) { return a * b; }); case Token::Kind::TK_STAR: return vectorComponentwiseFold([](T a, T b) { return a * b; });
case Token::Kind::TK_SLASH: { case Token::Kind::TK_SLASH: {
if (isVectorDivisionByZero()) { if (isVectorDivisionByZero()) {
errors.error(right.fOffset, "division by zero"); context.fErrors.error(right.fOffset, "division by zero");
return nullptr; return nullptr;
} }
return vectorComponentwiseFold([](T a, T b) { return a / b; }); return vectorComponentwiseFold([](T a, T b) { return a / b; });
@ -122,7 +121,6 @@ static Constructor splat_scalar(const Expression& scalar, const Type& type) {
} }
std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context, std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
ErrorReporter& errors,
const Expression& left, const Expression& left,
Token::Kind op, Token::Kind op,
const Expression& right) { const Expression& right) {
@ -175,21 +173,21 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
case Token::Kind::TK_STAR: return URESULT(Int, *); case Token::Kind::TK_STAR: return URESULT(Int, *);
case Token::Kind::TK_SLASH: case Token::Kind::TK_SLASH:
if (leftVal == std::numeric_limits<SKSL_INT>::min() && rightVal == -1) { if (leftVal == std::numeric_limits<SKSL_INT>::min() && rightVal == -1) {
errors.error(right.fOffset, "arithmetic overflow"); context.fErrors.error(right.fOffset, "arithmetic overflow");
return nullptr; return nullptr;
} }
if (!rightVal) { if (!rightVal) {
errors.error(right.fOffset, "division by zero"); context.fErrors.error(right.fOffset, "division by zero");
return nullptr; return nullptr;
} }
return RESULT(Int, /); return RESULT(Int, /);
case Token::Kind::TK_PERCENT: case Token::Kind::TK_PERCENT:
if (leftVal == std::numeric_limits<SKSL_INT>::min() && rightVal == -1) { if (leftVal == std::numeric_limits<SKSL_INT>::min() && rightVal == -1) {
errors.error(right.fOffset, "arithmetic overflow"); context.fErrors.error(right.fOffset, "arithmetic overflow");
return nullptr; return nullptr;
} }
if (!rightVal) { if (!rightVal) {
errors.error(right.fOffset, "division by zero"); context.fErrors.error(right.fOffset, "division by zero");
return nullptr; return nullptr;
} }
return RESULT(Int, %); return RESULT(Int, %);
@ -206,13 +204,13 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
if (rightVal >= 0 && rightVal <= 31) { if (rightVal >= 0 && rightVal <= 31) {
return RESULT(Int, <<); return RESULT(Int, <<);
} }
errors.error(right.fOffset, "shift value out of range"); context.fErrors.error(right.fOffset, "shift value out of range");
return nullptr; return nullptr;
case Token::Kind::TK_SHR: case Token::Kind::TK_SHR:
if (rightVal >= 0 && rightVal <= 31) { if (rightVal >= 0 && rightVal <= 31) {
return RESULT(Int, >>); return RESULT(Int, >>);
} }
errors.error(right.fOffset, "shift value out of range"); context.fErrors.error(right.fOffset, "shift value out of range");
return nullptr; return nullptr;
default: default:
@ -232,7 +230,7 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
if (rightVal) { if (rightVal) {
return RESULT(Float, /); return RESULT(Float, /);
} }
errors.error(right.fOffset, "division by zero"); context.fErrors.error(right.fOffset, "division by zero");
return nullptr; return nullptr;
case Token::Kind::TK_EQEQ: return RESULT(Bool, ==); case Token::Kind::TK_EQEQ: return RESULT(Bool, ==);
case Token::Kind::TK_NEQ: return RESULT(Bool, !=); case Token::Kind::TK_NEQ: return RESULT(Bool, !=);
@ -249,10 +247,10 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
const Type& rightType = right.type(); const Type& rightType = right.type();
if (leftType.isVector() && leftType == rightType) { if (leftType.isVector() && leftType == rightType) {
if (leftType.componentType().isFloat()) { if (leftType.componentType().isFloat()) {
return simplify_vector<SKSL_FLOAT>(context, errors, left, op, right); return simplify_vector<SKSL_FLOAT>(context, left, op, right);
} }
if (leftType.componentType().isInteger()) { if (leftType.componentType().isInteger()) {
return simplify_vector<SKSL_INT>(context, errors, left, op, right); return simplify_vector<SKSL_INT>(context, left, op, right);
} }
return nullptr; return nullptr;
} }
@ -260,12 +258,10 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
// Perform constant folding on vectors against scalars, e.g.: half4(2) + 2 // Perform constant folding on vectors against scalars, e.g.: half4(2) + 2
if (leftType.isVector() && leftType.componentType() == rightType) { if (leftType.isVector() && leftType.componentType() == rightType) {
if (rightType.isFloat()) { if (rightType.isFloat()) {
return simplify_vector<SKSL_FLOAT>(context, errors, return simplify_vector<SKSL_FLOAT>(context, left, op, splat_scalar(right, left.type()));
left, op, splat_scalar(right, left.type()));
} }
if (rightType.isInteger()) { if (rightType.isInteger()) {
return simplify_vector<SKSL_INT>(context, errors, return simplify_vector<SKSL_INT>(context, left, op, splat_scalar(right, left.type()));
left, op, splat_scalar(right, left.type()));
} }
return nullptr; return nullptr;
} }
@ -273,12 +269,11 @@ std::unique_ptr<Expression> ConstantFolder::Simplify(const Context& context,
// Perform constant folding on scalars against vectors, e.g.: 2 + half4(2) // Perform constant folding on scalars against vectors, e.g.: 2 + half4(2)
if (rightType.isVector() && rightType.componentType() == leftType) { if (rightType.isVector() && rightType.componentType() == leftType) {
if (leftType.isFloat()) { if (leftType.isFloat()) {
return simplify_vector<SKSL_FLOAT>(context, errors, return simplify_vector<SKSL_FLOAT>(context, splat_scalar(left, right.type()), op,
splat_scalar(left, right.type()), op, right); right);
} }
if (leftType.isInteger()) { if (leftType.isInteger()) {
return simplify_vector<SKSL_INT>(context, errors, return simplify_vector<SKSL_INT>(context, splat_scalar(left, right.type()), op, right);
splat_scalar(left, right.type()), op, right);
} }
return nullptr; return nullptr;
} }

View File

@ -26,7 +26,6 @@ class ConstantFolder {
public: public:
/** Simplifies the binary expression `left OP right`. Returns null if it can't be simplified. */ /** Simplifies the binary expression `left OP right`. Returns null if it can't be simplified. */
static std::unique_ptr<Expression> Simplify(const Context& context, static std::unique_ptr<Expression> Simplify(const Context& context,
ErrorReporter& errors,
const Expression& left, const Expression& left,
Token::Kind op, Token::Kind op,
const Expression& right); const Expression& right);

View File

@ -236,8 +236,9 @@ public:
using INHERITED = Expression; using INHERITED = Expression;
}; };
Context::Context() Context::Context(ErrorReporter& errors)
: fDefined_Expression(std::make_unique<DefinedExpression>(fTypes.fInvalid.get())) {} : fErrors(errors)
, fDefined_Expression(std::make_unique<DefinedExpression>(fTypes.fInvalid.get())) {}
} // namespace SkSL } // namespace SkSL

View File

@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/ir/SkSLExpression.h" #include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLType.h" #include "src/sksl/ir/SkSLType.h"
@ -147,11 +148,14 @@ struct BuiltinTypes {
*/ */
class Context { class Context {
public: public:
Context(); Context(ErrorReporter& errors);
// The Context holds all of the built-in types. // The Context holds all of the built-in types.
BuiltinTypes fTypes; BuiltinTypes fTypes;
// The Context holds a reference to our error reporter.
ErrorReporter& fErrors;
// A sentinel expression used to mark that a variable has a value during dataflow analysis (when // A sentinel expression used to mark that a variable has a value during dataflow analysis (when
// it could have several different values, or the analyzer is otherwise unable to assign it a // it could have several different values, or the analyzer is otherwise unable to assign it a
// specific expression) // specific expression)

View File

@ -28,6 +28,15 @@ public:
virtual int errorCount() = 0; virtual int errorCount() = 0;
}; };
/**
* Error reporter for tests that need an SkSL context; aborts immediately if an error is reported.
*/
class TestingOnly_AbortErrorReporter : public ErrorReporter {
public:
void error(int offset, String msg) override { ABORT("%s", msg.c_str()); }
int errorCount() override { return 0; }
};
} // namespace SkSL } // namespace SkSL
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -102,8 +102,7 @@ private:
class IRGenerator { class IRGenerator {
public: public:
IRGenerator(const Context* context, IRGenerator(const Context* context,
const ShaderCapsClass* caps, const ShaderCapsClass* caps);
ErrorReporter& errorReporter);
struct IRBundle { struct IRBundle {
std::vector<std::unique_ptr<ProgramElement>> fElements; std::vector<std::unique_ptr<ProgramElement>> fElements;
@ -132,7 +131,7 @@ public:
const Program::Settings* settings() const { return fSettings; } const Program::Settings* settings() const { return fSettings; }
ErrorReporter& errorReporter() const { return fErrors; } ErrorReporter& errorReporter() const { return fContext.fErrors; }
std::shared_ptr<SymbolTable>& symbolTable() { std::shared_ptr<SymbolTable>& symbolTable() {
return fSymbolTable; return fSymbolTable;
@ -268,7 +267,6 @@ private:
std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics; std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
int fLoopLevel = 0; int fLoopLevel = 0;
int fSwitchLevel = 0; int fSwitchLevel = 0;
ErrorReporter& fErrors;
int fInvocations; int fInvocations;
std::vector<std::unique_ptr<ProgramElement>>* fProgramElements = nullptr; std::vector<std::unique_ptr<ProgramElement>>* fProgramElements = nullptr;
std::vector<const ProgramElement*>* fSharedElements = nullptr; std::vector<const ProgramElement*>* fSharedElements = nullptr;

View File

@ -85,8 +85,8 @@ public:
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator, std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override { const DefinitionMap& definitions) override {
return ConstantFolder::Simplify(irGenerator.fContext, irGenerator.errorReporter(), return ConstantFolder::Simplify(irGenerator.fContext, *this->left(), this->getOperator(),
*this->left(), this->getOperator(), *this->right()); *this->right());
} }
bool hasProperty(Property property) const override { bool hasProperty(Property property) const override {

View File

@ -6,12 +6,14 @@
*/ */
#include "src/sksl/SkSLContext.h" #include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLMemoryLayout.h" #include "src/sksl/SkSLMemoryLayout.h"
#include "tests/Test.h" #include "tests/Test.h"
DEF_TEST(SkSLMemoryLayout140Test, r) { DEF_TEST(SkSLMemoryLayout140Test, r) {
SkSL::Context context; SkSL::TestingOnly_AbortErrorReporter errors;
SkSL::Context context(errors);
SkSL::MemoryLayout layout(SkSL::MemoryLayout::k140_Standard); SkSL::MemoryLayout layout(SkSL::MemoryLayout::k140_Standard);
// basic types // basic types
@ -96,7 +98,8 @@ DEF_TEST(SkSLMemoryLayout140Test, r) {
} }
DEF_TEST(SkSLMemoryLayout430Test, r) { DEF_TEST(SkSLMemoryLayout430Test, r) {
SkSL::Context context; SkSL::TestingOnly_AbortErrorReporter errors;
SkSL::Context context(errors);
SkSL::MemoryLayout layout(SkSL::MemoryLayout::k430_Standard); SkSL::MemoryLayout layout(SkSL::MemoryLayout::k430_Standard);
// basic types // basic types