Removed ErrorHandler pointers from CodeGenerators

These pointers were largely redundant because the CodeGenerators also
had access to a Context, and in a future CL Context becomes the source
of truth regarding the current ErrorHandler, so they are potentially
dangerous.

Change-Id: Ie4175fcb3e1f586baaa42d16c05058aea78532f0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/439164
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2021-08-13 11:20:09 -04:00 committed by SkCQ
parent abae48eb5b
commit 3abc6c68ad
8 changed files with 78 additions and 80 deletions

View File

@ -892,7 +892,7 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) {
dsl::DSLWriter::IRGenerator().fSymbolTable = program.fSymbols;
#ifdef SK_ENABLE_SPIRV_VALIDATION
StringStream buffer;
SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer);
SPIRVCodeGenerator cg(fContext.get(), &program, &buffer);
bool result = cg.generateCode();
if (result && program.fConfig->fSettings.fValidateSPIRV) {
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
@ -925,7 +925,7 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) {
out.write(data.c_str(), data.size());
}
#else
SPIRVCodeGenerator cg(fContext.get(), &program, this, &out);
SPIRVCodeGenerator cg(fContext.get(), &program, &out);
bool result = cg.generateCode();
#endif
dsl::End();
@ -944,7 +944,7 @@ bool Compiler::toSPIRV(Program& program, String* out) {
bool Compiler::toGLSL(Program& program, OutputStream& out) {
TRACE_EVENT0("skia.shaders", "SkSL::Compiler::toGLSL");
AutoSource as(this, program.fSource->c_str());
GLSLCodeGenerator cg(fContext.get(), &program, this, &out);
GLSLCodeGenerator cg(fContext.get(), &program, &out);
bool result = cg.generateCode();
return result;
}
@ -970,7 +970,7 @@ bool Compiler::toHLSL(Program& program, String* out) {
bool Compiler::toMetal(Program& program, OutputStream& out) {
TRACE_EVENT0("skia.shaders", "SkSL::Compiler::toMetal");
AutoSource as(this, program.fSource->c_str());
MetalCodeGenerator cg(fContext.get(), &program, this, &out);
MetalCodeGenerator cg(fContext.get(), &program, &out);
bool result = cg.generateCode();
return result;
}

View File

@ -19,9 +19,9 @@ namespace SkSL {
*/
class CodeGenerator {
public:
CodeGenerator(const Program* program, ErrorReporter* errors, OutputStream* out)
: fProgram(*program)
, fErrors(*errors)
CodeGenerator(const Context* context, const Program* program, OutputStream* out)
: fContext(*context)
, fProgram(*program)
, fOut(out) {}
virtual ~CodeGenerator() {}
@ -33,8 +33,8 @@ public:
void setOutputStream(OutputStream* output) { fOut = output; }
protected:
const Context& fContext;
const Program& fProgram;
ErrorReporter& fErrors;
OutputStream* fOut;
};

View File

@ -1546,7 +1546,7 @@ bool GLSLCodeGenerator::generateCode() {
}
write_stringstream(fExtraFunctions, *rawOut);
write_stringstream(body, *rawOut);
return 0 == fErrors.errorCount();
return fContext.errors().errorCount() == 0;
}
} // namespace SkSL

View File

@ -53,11 +53,9 @@ namespace SkSL {
*/
class GLSLCodeGenerator : public CodeGenerator {
public:
GLSLCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
, fLineEnding("\n")
, fContext(*context) {}
GLSLCodeGenerator(const Context* context, const Program* program, OutputStream* out)
: INHERITED(context, program, out)
, fLineEnding("\n") {}
bool generateCode() override;
@ -179,7 +177,6 @@ protected:
const ShaderCapsClass& caps() const { return fContext.fCaps; }
const char* fLineEnding;
const Context& fContext;
StringStream fExtensions;
StringStream fGlobals;
StringStream fExtraFunctions;

View File

@ -1038,7 +1038,7 @@ void MetalCodeGenerator::writeConstructorCompound(const ConstructorCompound& c,
} else if (c.type().isMatrix()) {
this->writeConstructorCompoundMatrix(c, parentPrecedence);
} else {
fErrors.error(c.fOffset, "unsupported compound constructor");
fContext.errors().error(c.fOffset, "unsupported compound constructor");
}
}
@ -1686,7 +1686,7 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f)
this->write("vertex Outputs vertexMain");
break;
default:
fErrors.error(-1, "unsupported kind of program");
fContext.errors().error(-1, "unsupported kind of program");
return false;
}
this->write("(Inputs _in [[stage_in]]");
@ -1700,13 +1700,13 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f)
const VarDeclaration& var = decls.declaration()->as<VarDeclaration>();
if (var.var().type().typeKind() == Type::TypeKind::kSampler) {
if (var.var().modifiers().fLayout.fBinding < 0) {
fErrors.error(decls.fOffset,
"Metal samplers must have 'layout(binding=...)'");
fContext.errors().error(decls.fOffset,
"Metal samplers must have 'layout(binding=...)'");
return false;
}
if (var.var().type().dimensions() != SpvDim2D) {
// Not yet implemented--Skia currently only uses 2D textures.
fErrors.error(decls.fOffset, "Unsupported texture dimensions");
fContext.errors().error(decls.fOffset, "Unsupported texture dimensions");
return false;
}
this->write(", texture2d<float> ");
@ -1894,14 +1894,15 @@ void MetalCodeGenerator::writeFields(const std::vector<Type::Field>& fields, int
int fieldOffset = field.fModifiers.fLayout.fOffset;
const Type* fieldType = field.fType;
if (!MemoryLayout::LayoutIsSupported(*fieldType)) {
fErrors.error(parentOffset, "type '" + fieldType->name() + "' is not permitted here");
fContext.errors().error(parentOffset, "type '" + fieldType->name() +
"' is not permitted here");
return;
}
if (fieldOffset != -1) {
if (currentOffset > fieldOffset) {
fErrors.error(parentOffset,
"offset of field '" + field.fName + "' must be at least " +
to_string((int) currentOffset));
fContext.errors().error(parentOffset,
"offset of field '" + field.fName + "' must be at least " +
to_string((int) currentOffset));
return;
} else if (currentOffset < fieldOffset) {
this->write("char pad");
@ -1913,15 +1914,15 @@ void MetalCodeGenerator::writeFields(const std::vector<Type::Field>& fields, int
}
int alignment = memoryLayout.alignment(*fieldType);
if (fieldOffset % alignment) {
fErrors.error(parentOffset,
"offset of field '" + field.fName + "' must be a multiple of " +
to_string((int) alignment));
fContext.errors().error(parentOffset,
"offset of field '" + field.fName + "' must be a multiple of " +
to_string((int) alignment));
return;
}
}
size_t fieldSize = memoryLayout.size(*fieldType);
if (fieldSize > static_cast<size_t>(std::numeric_limits<int>::max() - currentOffset)) {
fErrors.error(parentOffset, "field offset overflow");
fContext.errors().error(parentOffset, "field offset overflow");
return;
}
currentOffset += fieldSize;
@ -2116,8 +2117,9 @@ void MetalCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
this->writeExpression(*r.expression(), Precedence::kTopLevel);
this->writeLine(";");
} else {
fErrors.error(r.fOffset, "Metal does not support returning '" +
r.expression()->type().description() + "' from main()");
fContext.errors().error(r.fOffset,
"Metal does not support returning '" +
r.expression()->type().description() + "' from main()");
}
}
this->writeReturnStatementFromMain();
@ -2151,8 +2153,9 @@ void MetalCodeGenerator::writeUniformStruct() {
this->write("struct Uniforms {\n");
fUniformBuffer = uniformSet;
} else if (uniformSet != fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
"the same 'layout(set=...)'");
fContext.errors().error(decls.fOffset,
"Metal backend requires all uniforms to have the same "
"'layout(set=...)'");
}
this->write(" ");
this->writeType(var.type());
@ -2215,8 +2218,8 @@ void MetalCodeGenerator::writeOutputStruct() {
int location = var.modifiers().fLayout.fLocation;
if (location < 0) {
fErrors.error(var.fOffset,
"Metal out variables must have 'layout(location=...)'");
fContext.errors().error(var.fOffset,
"Metal out variables must have 'layout(location=...)'");
} else if (fProgram.fConfig->fKind == ProgramKind::kVertex) {
this->write(" [[user(locn" + to_string(location) + ")]]");
} else if (fProgram.fConfig->fKind == ProgramKind::kFragment) {
@ -2600,7 +2603,7 @@ bool MetalCodeGenerator::generateCode() {
write_stringstream(fExtraFunctionPrototypes, *fOut);
write_stringstream(fExtraFunctions, *fOut);
write_stringstream(body, *fOut);
return 0 == fErrors.errorCount();
return fContext.errors().errorCount() == 0;
}
} // namespace SkSL

View File

@ -58,12 +58,10 @@ public:
static constexpr const char* SAMPLER_SUFFIX = "Smplr";
static constexpr const char* PACKED_PREFIX = "packed_";
MetalCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
MetalCodeGenerator(const Context* context, const Program* program, OutputStream* out)
: INHERITED(context, program, out)
, fReservedWords({"atan2", "rsqrt", "rint", "dfdx", "dfdy", "vertex", "fragment"})
, fLineEnding("\n")
, fContext(*context) {}
, fLineEnding("\n") {}
bool generateCode() override;
@ -276,7 +274,6 @@ protected:
int fAnonInterfaceCount = 0;
int fPaddingCount = 0;
const char* fLineEnding;
const Context& fContext;
String fFunctionHeader;
StringStream fExtraFunctions;
StringStream fExtraFunctionPrototypes;

View File

@ -439,7 +439,8 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
for (int32_t i = 0; i < (int32_t) type.fields().size(); i++) {
const Type::Field& field = type.fields()[i];
if (!MemoryLayout::LayoutIsSupported(*field.fType)) {
fErrors.error(type.fOffset, "type '" + field.fType->name() + "' is not permitted here");
fContext.errors().error(type.fOffset, "type '" + field.fType->name() +
"' is not permitted here");
return;
}
size_t size = memoryLayout.size(*field.fType);
@ -447,14 +448,14 @@ void SPIRVCodeGenerator::writeStruct(const Type& type, const MemoryLayout& memor
const Layout& fieldLayout = field.fModifiers.fLayout;
if (fieldLayout.fOffset >= 0) {
if (fieldLayout.fOffset < (int) offset) {
fErrors.error(type.fOffset,
"offset of field '" + field.fName + "' must be at "
"least " + to_string((int) offset));
fContext.errors().error(type.fOffset,
"offset of field '" + field.fName + "' must be at "
"least " + to_string((int) offset));
}
if (fieldLayout.fOffset % alignment) {
fErrors.error(type.fOffset,
"offset of field '" + field.fName + "' must be a multiple"
" of " + to_string((int) alignment));
fContext.errors().error(type.fOffset,
"offset of field '" + field.fName + "' must be a multiple"
" of " + to_string((int) alignment));
}
offset = fieldLayout.fOffset;
} else {
@ -581,8 +582,8 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
break;
case Type::TypeKind::kArray: {
if (!MemoryLayout::LayoutIsSupported(*type)) {
fErrors.error(type->fOffset,
"type '" + type->name() + "' is not permitted here");
fContext.errors().error(type->fOffset,
"type '" + type->name() + "' is not permitted here");
return this->nextId(nullptr);
}
if (type->columns() > 0) {
@ -597,8 +598,8 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou
fDecorationBuffer);
} else {
// We shouldn't have any runtime-sized arrays right now
fErrors.error(type->fOffset,
"runtime-sized arrays are not supported in SPIR-V");
fContext.errors().error(type->fOffset,
"runtime-sized arrays are not supported in SPIR-V");
this->writeInstruction(SpvOpTypeRuntimeArray, result,
this->getType(type->componentType(), layout),
fConstantBuffer);
@ -787,7 +788,8 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
const FunctionDeclaration& function = c.function();
auto intrinsic = fIntrinsicMap.find(function.intrinsicKind());
if (intrinsic == fIntrinsicMap.end()) {
fErrors.error(c.fOffset, "unsupported intrinsic '" + function.description() + "'");
fContext.errors().error(c.fOffset, "unsupported intrinsic '" + function.description() +
"'");
return -1;
}
int32_t intrinsicId;
@ -861,7 +863,8 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
case kSpecial_IntrinsicOpcodeKind:
return this->writeSpecialIntrinsic(c, (SpecialIntrinsic) intrinsicId, out);
default:
fErrors.error(c.fOffset, "unsupported intrinsic '" + function.description() + "'");
fContext.errors().error(c.fOffset, "unsupported intrinsic '" + function.description() +
"'");
return -1;
}
}
@ -1176,7 +1179,8 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream&
const ExpressionArray& arguments = c.arguments();
const auto& entry = fFunctionMap.find(&function);
if (entry == fFunctionMap.end()) {
fErrors.error(c.fOffset, "function '" + function.description() + "' is not defined");
fContext.errors().error(c.fOffset, "function '" + function.description() +
"' is not defined");
return -1;
}
// Temp variables are used to write back out-parameters after the function call is complete.
@ -1282,8 +1286,8 @@ SpvId SPIRVCodeGenerator::castScalarToType(SpvId inputExprId,
return this->castScalarToBoolean(inputExprId, inputType, outputType, out);
}
fErrors.error(-1, "unsupported cast: " + inputType.description() +
" to " + outputType.description());
fContext.errors().error(-1, "unsupported cast: " + inputType.description() +
" to " + outputType.description());
return inputExprId;
}
@ -2029,7 +2033,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
}
SpvId base = lvalue->getPointer();
if (base == (SpvId) -1) {
fErrors.error(swizzle.fOffset, "unable to retrieve lvalue from swizzle");
fContext.errors().error(swizzle.fOffset, "unable to retrieve lvalue from swizzle");
}
if (swizzle.components().size() == 1) {
SpvId member = this->nextId(nullptr);
@ -2203,8 +2207,8 @@ SpvId SPIRVCodeGenerator::writeBinaryOperation(const Type& resultType,
} else if (is_bool(fContext, operandType)) {
this->writeInstruction(ifBool, this->getType(resultType), result, lhs, rhs, out);
} else {
fErrors.error(operandType.fOffset,
"unsupported operand for binary expression: " + operandType.description());
fContext.errors().error(operandType.fOffset,
"unsupported operand for binary expression: " + operandType.description());
}
return result;
}
@ -2420,7 +2424,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
resultType, out);
}
} else {
fErrors.error(leftType.fOffset, "unsupported mixed-type expression");
fContext.errors().error(leftType.fOffset, "unsupported mixed-type expression");
return -1;
}
} else {
@ -2551,7 +2555,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(const Type& leftType, SpvId lhs,
return this->writeBinaryOperation(resultType, *operandType, lhs, rhs, SpvOpUndef,
SpvOpBitwiseXor, SpvOpBitwiseXor, SpvOpUndef, out);
default:
fErrors.error(0, "unsupported token");
fContext.errors().error(0, "unsupported token");
return -1;
}
}
@ -3042,7 +3046,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
const Variable& intfVar = intf.variable();
const Type& type = intfVar.type();
if (!MemoryLayout::LayoutIsSupported(type)) {
fErrors.error(type.fOffset, "type '" + type.name() + "' is not permitted here");
fContext.errors().error(type.fOffset, "type '" + type.name() + "' is not permitted here");
return this->nextId(nullptr);
}
SpvStorageClass_ storageClass = get_storage_class(intf.variable(), SpvStorageClassFunction);
@ -3490,16 +3494,16 @@ SPIRVCodeGenerator::EntrypointAdapter SPIRVCodeGenerator::writeEntrypointAdapter
VariableReference::RefKind::kWrite);
// Synthesize a call to the `main()` function.
if (main.returnType() != skFragColorRef->type()) {
fErrors.error(main.fOffset, "SPIR-V does not support returning '" +
main.returnType().description() + "' from main()");
fContext.errors().error(main.fOffset, "SPIR-V does not support returning '" +
main.returnType().description() + "' from main()");
return {};
}
ExpressionArray args;
if (main.parameters().size() == 1) {
if (main.parameters()[0]->type() != *fContext.fTypes.fFloat2) {
fErrors.error(main.fOffset,
"SPIR-V does not support parameter of type '" +
main.parameters()[0]->type().description() + "' to main()");
fContext.errors().error(main.fOffset,
"SPIR-V does not support parameter of type '" +
main.parameters()[0]->type().description() + "' to main()");
return {};
}
auto zero = std::make_unique<FloatLiteral>(
@ -3590,7 +3594,7 @@ void SPIRVCodeGenerator::addRTFlipUniform(int offset) {
fWroteRTFlip = true;
std::vector<Type::Field> fields;
if (fProgram.fConfig->fSettings.fRTFlipOffset < 0) {
fErrors.error(offset, "RTFlipOffset is negative");
fContext.errors().error(offset, "RTFlipOffset is negative");
}
fields.emplace_back(Modifiers(Layout(/*flags=*/0,
/*location=*/-1,
@ -3611,11 +3615,11 @@ void SPIRVCodeGenerator::addRTFlipUniform(int offset) {
fSynthetics.takeOwnershipOfSymbol(Type::MakeStructType(/*offset=*/-1, name, fields));
int binding = fProgram.fConfig->fSettings.fRTFlipBinding;
if (binding == -1) {
fErrors.error(offset, "layout(binding=...) is required in SPIR-V");
fContext.errors().error(offset, "layout(binding=...) is required in SPIR-V");
}
int set = fProgram.fConfig->fSettings.fRTFlipSet;
if (set == -1) {
fErrors.error(offset, "layout(set=...) is required in SPIR-V");
fContext.errors().error(offset, "layout(set=...) is required in SPIR-V");
}
bool usePushConstants = fProgram.fConfig->fSettings.fUsePushConstants;
int flags = usePushConstants ? Layout::Flag::kPushConstant_Flag : 0;
@ -3653,7 +3657,7 @@ void SPIRVCodeGenerator::addRTFlipUniform(int offset) {
name,
/*instanceName=*/"",
/*arraySize=*/0,
std::make_shared<SymbolTable>(&fErrors, /*builtin=*/false));
std::make_shared<SymbolTable>(&fContext.errors(), /*builtin=*/false));
this->writeInterfaceBlock(intf, false);
}
@ -3675,7 +3679,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
// Make sure we have a main() function.
if (!main) {
fErrors.error(/*offset=*/0, "program does not contain a main() function");
fContext.errors().error(/*offset=*/0, "program does not contain a main() function");
return;
}
// Emit interface blocks.
@ -3776,7 +3780,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
bool SPIRVCodeGenerator::generateCode() {
SkASSERT(!fErrors.errorCount());
SkASSERT(!fContext.errors().errorCount());
this->writeWord(SpvMagicNumber, *fOut);
this->writeWord(SpvVersion, *fOut);
this->writeWord(SKSL_MAGIC, *fOut);
@ -3785,7 +3789,7 @@ bool SPIRVCodeGenerator::generateCode() {
this->writeWord(fIdCount, *fOut);
this->writeWord(0, *fOut); // reserved, always zero
write_stringstream(buffer, *fOut);
return 0 == fErrors.errorCount();
return fContext.errors().errorCount() == 0;
}
} // namespace SkSL

View File

@ -128,10 +128,8 @@ public:
SPIRVCodeGenerator(const Context* context,
const Program* program,
ErrorReporter* errors,
OutputStream* out)
: INHERITED(program, errors, out)
, fContext(*context)
: INHERITED(context, program, out)
, fDefaultLayout(MemoryLayout::k140_Standard)
, fCapabilities(0)
, fIdCount(1)
@ -139,7 +137,7 @@ public:
, fBoolFalse(0)
, fSetupFragPosition(false)
, fCurrentBlock(0)
, fSynthetics(errors, /*builtin=*/true) {
, fSynthetics(&fContext.errors(), /*builtin=*/true) {
this->setupIntrinsics();
}
@ -467,7 +465,6 @@ private:
void addRTFlipUniform(int offset);
const Context& fContext;
const MemoryLayout fDefaultLayout;
uint64_t fCapabilities;