moved SkSL Variable data into IRNode
Change-Id: I53af66c1b65971c204ac7c515e0d0e39481b015d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323097
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index 5277aa2..5e57629 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -160,7 +160,7 @@
const SkSL::Type& varType = var.type();
// Varyings (only used in conjunction with drawVertices)
- if (var.fModifiers.fFlags & SkSL::Modifiers::kVarying_Flag) {
+ if (var.modifiers().fFlags & SkSL::Modifiers::kVarying_Flag) {
varyings.push_back({var.name(),
varType.typeKind() == SkSL::Type::TypeKind::kVector
? varType.columns()
@@ -172,7 +172,7 @@
sampleUsages.push_back(SkSL::Analysis::GetSampleUsage(*program, var));
}
// 'uniform' variables
- else if (var.fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
+ else if (var.modifiers().fFlags & SkSL::Modifiers::kUniform_Flag) {
Uniform uni;
uni.fName = var.name();
uni.fFlags = 0;
@@ -189,7 +189,7 @@
RETURN_FAILURE("Invalid uniform type: '%s'", type->displayName().c_str());
}
- const SkSL::StringFragment& marker(var.fModifiers.fLayout.fMarker);
+ const SkSL::StringFragment& marker(var.modifiers().fLayout.fMarker);
if (marker.fLength) {
uni.fFlags |= Uniform::kMarker_Flag;
allowColorFilter = false;
@@ -199,7 +199,7 @@
}
}
- if (var.fModifiers.fLayout.fFlags & SkSL::Layout::Flag::kSRGBUnpremul_Flag) {
+ if (var.modifiers().fLayout.fFlags & SkSL::Layout::Flag::kSRGBUnpremul_Flag) {
uni.fFlags |= Uniform::kSRGBUnpremul_Flag;
}
diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp
index 9804945..857bdc3 100644
--- a/src/sksl/SkSLAnalysis.cpp
+++ b/src/sksl/SkSLAnalysis.cpp
@@ -139,7 +139,7 @@
bool visitExpression(const Expression& e) override {
if (e.is<VariableReference>()) {
const VariableReference& var = e.as<VariableReference>();
- return var.fVariable->fModifiers.fLayout.fBuiltin == fBuiltin;
+ return var.fVariable->modifiers().fLayout.fBuiltin == fBuiltin;
}
return INHERITED::visitExpression(e);
}
@@ -240,8 +240,8 @@
case Expression::Kind::kVariableReference: {
VariableReference& varRef = expr.as<VariableReference>();
const Variable* var = varRef.fVariable;
- if (var->fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag |
- Modifiers::kVarying_Flag)) {
+ if (var->modifiers().fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag |
+ Modifiers::kVarying_Flag)) {
fErrors->error(expr.fOffset,
"cannot modify immutable variable '" + var->name() + "'");
} else if (fAssignableVar) {
diff --git a/src/sksl/SkSLAnalysis.h b/src/sksl/SkSLAnalysis.h
index c606dc0..c6ce66f 100644
--- a/src/sksl/SkSLAnalysis.h
+++ b/src/sksl/SkSLAnalysis.h
@@ -21,7 +21,7 @@
struct Program;
struct ProgramElement;
struct Statement;
-struct Variable;
+class Variable;
struct VariableReference;
/**
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index f71328d..dc5a406 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -117,11 +117,11 @@
}
static inline bool is_uniform(const SkSL::Variable& var) {
- return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
+ return var.modifiers().fFlags & Modifiers::kUniform_Flag;
}
static inline bool is_in(const SkSL::Variable& var) {
- return var.fModifiers.fFlags & Modifiers::kIn_Flag;
+ return var.modifiers().fFlags & Modifiers::kIn_Flag;
}
void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
@@ -165,7 +165,7 @@
if (declVar->type() == *fContext.fFragmentProcessor_Type) {
fOutput->fChildFPCount++;
}
- if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
+ if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) {
continue;
}
if (is_uniform(*declVar)) {
@@ -218,8 +218,8 @@
static int expression_as_builtin(const Expression& e) {
if (e.is<VariableReference>()) {
const Variable& var(*e.as<VariableReference>().fVariable);
- if (var.fStorage == Variable::kGlobal_Storage) {
- return var.fModifiers.fLayout.fBuiltin;
+ if (var.storage() == Variable::kGlobal_Storage) {
+ return var.modifiers().fLayout.fBuiltin;
}
}
return -1;
@@ -423,7 +423,7 @@
ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
// given that we seldom have more than a couple of variables, linear search is probably the most
// efficient way to handle lookups
- switch (var.fStorage) {
+ switch (var.storage()) {
case Variable::kLocal_Storage: {
for (int i = fLocals.size() - 1; i >= 0; --i) {
if (fLocals[i] == &var) {
@@ -486,7 +486,7 @@
if (e.is<GlobalVarDeclaration>()) {
const GlobalVarDeclaration& decl = e.as<GlobalVarDeclaration>();
const Variable* declVar = decl.fDecl->fVar;
- if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
+ if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) {
continue;
}
if (isUniform != is_uniform(*declVar)) {
@@ -1265,7 +1265,7 @@
for (int i = 0; i < argCount; ++i) {
const auto& param = f.function().fParameters[i];
const auto& arg = f.arguments()[i];
- if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
lvalues.emplace_back(this->getLValue(*arg));
lvalues.back()->load();
} else {
@@ -1298,7 +1298,7 @@
for (int i = argCount - 1; i >= 0; --i) {
const auto& param = f.function().fParameters[i];
const auto& arg = f.arguments()[i];
- if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
pop();
lvalues.back()->store(true);
lvalues.pop_back();
@@ -1834,7 +1834,7 @@
fParameterCount = 0;
for (const auto& p : declaration->fParameters) {
int slots = ByteCodeGenerator::SlotCount(p->type());
- fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
+ fParameters.push_back({ slots, (bool)(p->modifiers().fFlags & Modifiers::kOut_Flag) });
fParameterCount += slots;
}
}
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 77a3933..dd71973 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -20,8 +20,8 @@
namespace SkSL {
static bool needs_uniform_var(const Variable& var) {
- return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
- var.type().typeKind() != Type::TypeKind::kSampler;
+ return (var.modifiers().fFlags & Modifiers::kUniform_Flag) &&
+ var.type().typeKind() != Type::TypeKind::kSampler;
}
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
@@ -128,22 +128,24 @@
}
static String default_value(const Variable& var) {
- if (var.fModifiers.fLayout.fCType == SkSL::Layout::CType::kSkPMColor4f) {
+ if (var.modifiers().fLayout.fCType == SkSL::Layout::CType::kSkPMColor4f) {
return "{SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}";
}
return default_value(var.type());
}
static bool is_private(const Variable& var) {
- return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
- !(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
- var.fStorage == Variable::kGlobal_Storage &&
- var.fModifiers.fLayout.fBuiltin == -1;
+ const Modifiers& modifiers = var.modifiers();
+ return !(modifiers.fFlags & Modifiers::kUniform_Flag) &&
+ !(modifiers.fFlags & Modifiers::kIn_Flag) &&
+ var.storage() == Variable::kGlobal_Storage &&
+ modifiers.fLayout.fBuiltin == -1;
}
static bool is_uniform_in(const Variable& var) {
- return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
- (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
+ const Modifiers& modifiers = var.modifiers();
+ return (modifiers.fFlags & Modifiers::kUniform_Flag) &&
+ (modifiers.fFlags & Modifiers::kIn_Flag) &&
var.type().typeKind() != Type::TypeKind::kSampler;
}
@@ -260,7 +262,7 @@
void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
if (is_private(var)) {
- this->writeRuntimeValue(var.type(), var.fModifiers.fLayout, var.name());
+ this->writeRuntimeValue(var.type(), var.modifiers().fLayout, var.name());
} else {
this->writeExpression(value, kTopLevel_Precedence);
}
@@ -312,7 +314,7 @@
this->write(ref.fVariable->name());
return;
}
- switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
+ switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
case SK_OUTCOLOR_BUILTIN:
this->write("%s");
fFormatArgs.push_back(String("args.fOutputColor"));
@@ -336,13 +338,13 @@
this->getSamplerHandle(*ref.fVariable) + ")");
return;
}
- if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) {
+ if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) {
this->write("%s");
String name = ref.fVariable->name();
String var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
HCodeGenerator::FieldName(name.c_str()).c_str());
String code;
- if (ref.fVariable->fModifiers.fLayout.fWhen.fLength) {
+ if (ref.fVariable->modifiers().fLayout.fWhen.fLength) {
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
HCodeGenerator::FieldName(name.c_str()).c_str(),
var.c_str(),
@@ -353,7 +355,7 @@
fFormatArgs.push_back(code);
} else if (SectionAndParameterHelper::IsParameter(*ref.fVariable)) {
String name(ref.fVariable->name());
- this->writeRuntimeValue(ref.fVariable->type(), ref.fVariable->fModifiers.fLayout,
+ this->writeRuntimeValue(ref.fVariable->type(), ref.fVariable->modifiers().fLayout,
String::printf("_outer.%s", name.c_str()).c_str());
} else {
this->write(ref.fVariable->name());
@@ -657,8 +659,8 @@
case ProgramElement::Kind::kGlobalVar: {
const GlobalVarDeclaration& decl = p.as<GlobalVarDeclaration>();
const Variable& var = *decl.fDecl->fVar;
- if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
- -1 != var.fModifiers.fLayout.fBuiltin) {
+ if (var.modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
+ -1 != var.modifiers().fLayout.fBuiltin) {
return;
}
break;
@@ -673,8 +675,8 @@
if (!needs_uniform_var(var)) {
return;
}
- if (var.fModifiers.fLayout.fWhen.fLength) {
- this->writef(" if (%s) {\n ", String(var.fModifiers.fLayout.fWhen).c_str());
+ if (var.modifiers().fLayout.fWhen.fLength) {
+ this->writef(" if (%s) {\n ", String(var.modifiers().fLayout.fWhen).c_str());
}
String name(var.name());
if (var.type().typeKind() != Type::TypeKind::kArray) {
@@ -691,7 +693,7 @@
name.c_str(),
var.type().columns());
}
- if (var.fModifiers.fLayout.fWhen.fLength) {
+ if (var.modifiers().fLayout.fWhen.fLength) {
this->write(" }\n");
}
}
@@ -711,11 +713,11 @@
}
this->writef("%s %s = %s;\n",
HCodeGenerator::FieldType(fContext, decl.fVar->type(),
- decl.fVar->fModifiers.fLayout)
+ decl.fVar->modifiers().fLayout)
.c_str(),
String(decl.fVar->name()).c_str(),
default_value(*decl.fVar).c_str());
- } else if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
+ } else if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
// An auto-tracked uniform in variable, so add a field to hold onto the prior
// state. Note that tracked variables must be uniform in's and that is validated
// before writePrivateVars() is called.
@@ -1010,8 +1012,8 @@
const char* name = nameString.c_str();
// Switches for setData behavior in the generated code
- bool conditionalUniform = u->fModifiers.fLayout.fWhen != "";
- bool isTracked = u->fModifiers.fLayout.fFlags & Layout::kTracked_Flag;
+ bool conditionalUniform = u->modifiers().fLayout.fWhen != "";
+ bool isTracked = u->modifiers().fLayout.fFlags & Layout::kTracked_Flag;
bool needsValueDeclaration = isTracked || !mapper->canInlineUniformValue();
String uniformName = HCodeGenerator::FieldName(name) + "Var";
@@ -1029,7 +1031,7 @@
valueVar.appendf("%sValue", name);
// Use AccessType since that will match the return type of _outer's public API.
String valueType = HCodeGenerator::AccessType(fContext, u->type(),
- u->fModifiers.fLayout);
+ u->modifiers().fLayout);
this->writef("%s%s %s = _outer.%s;\n",
indent.c_str(), valueType.c_str(), valueVar.c_str(), name);
} else {
@@ -1189,7 +1191,7 @@
// Add this field onto the format string and argument list.
String fieldName = HCodeGenerator::FieldName(String(param->name()).c_str());
String runtimeValue = this->formatRuntimeValue(param->type(),
- param->fModifiers.fLayout,
+ param->modifiers().fLayout,
param->name(),
&argumentList);
formatString.appendf("%s%s=%s",
@@ -1245,16 +1247,16 @@
const Type& varType = var.type();
String nameString(var.name());
const char* name = nameString.c_str();
- if (var.fModifiers.fLayout.fKey != Layout::kNo_Key &&
- (var.fModifiers.fFlags & Modifiers::kUniform_Flag)) {
+ if (var.modifiers().fLayout.fKey != Layout::kNo_Key &&
+ (var.modifiers().fFlags & Modifiers::kUniform_Flag)) {
fErrors.error(var.fOffset, "layout(key) may not be specified on uniforms");
}
- switch (var.fModifiers.fLayout.fKey) {
+ switch (var.modifiers().fLayout.fKey) {
case Layout::kKey_Key:
if (is_private(var)) {
this->writef("%s %s =",
HCodeGenerator::FieldType(fContext, varType,
- var.fModifiers.fLayout).c_str(),
+ var.modifiers().fLayout).c_str(),
String(var.name()).c_str());
if (decl.fValue) {
fCPPMode = true;
@@ -1265,8 +1267,8 @@
}
this->write(";\n");
}
- if (var.fModifiers.fLayout.fWhen.fLength) {
- this->writef("if (%s) {", String(var.fModifiers.fLayout.fWhen).c_str());
+ if (var.modifiers().fLayout.fWhen.fLength) {
+ this->writef("if (%s) {", String(var.modifiers().fLayout.fWhen).c_str());
}
if (varType == *fContext.fHalf4_Type) {
this->writef(" uint16_t red = SkFloatToHalf(%s.fR);\n",
@@ -1291,7 +1293,7 @@
ABORT("NOT YET IMPLEMENTED: automatic key handling for %s\n",
varType.displayName().c_str());
}
- if (var.fModifiers.fLayout.fWhen.fLength) {
+ if (var.modifiers().fLayout.fWhen.fLength) {
this->write("}");
}
break;
@@ -1315,7 +1317,7 @@
for (const auto& p : fProgram) {
if (p.is<GlobalVarDeclaration>()) {
const VarDeclaration& decl = *p.as<GlobalVarDeclaration>().fDecl;
- if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
+ if ((decl.fVar->modifiers().fFlags & Modifiers::kUniform_Flag) &&
decl.fVar->type().typeKind() != Type::TypeKind::kSampler) {
uniforms.push_back(decl.fVar);
}
@@ -1330,7 +1332,7 @@
+ "'s type is not supported for use as a 'uniform in'");
return false;
}
- if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
+ if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
if (!mapper->supportsTracking()) {
fErrors.error(decl.fOffset, String(decl.fVar->name())
+ "'s type does not support state tracking");
@@ -1340,7 +1342,7 @@
} else {
// If it's not a uniform_in, it's an error to be tracked
- if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
+ if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
fErrors.error(decl.fOffset, "Non-'in uniforms' cannot be tracked");
return false;
}
@@ -1369,7 +1371,7 @@
this->writeSetData(uniforms);
this->writePrivateVars();
for (const auto& u : uniforms) {
- if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
+ if (needs_uniform_var(*u) && !(u->modifiers().fFlags & Modifiers::kIn_Flag)) {
this->writef(" UniformHandle %sVar;\n",
HCodeGenerator::FieldName(String(u->name()).c_str()).c_str());
}
diff --git a/src/sksl/SkSLCPPUniformCTypes.h b/src/sksl/SkSLCPPUniformCTypes.h
index f3455e9..1db23ac 100644
--- a/src/sksl/SkSLCPPUniformCTypes.h
+++ b/src/sksl/SkSLCPPUniformCTypes.h
@@ -50,7 +50,7 @@
const Layout& layout);
static const UniformCTypeMapper* Get(const Context& context, const Variable& variable) {
- return Get(context, variable.type(), variable.fModifiers.fLayout);
+ return Get(context, variable.type(), variable.modifiers().fLayout);
}
// The C++ type name that this mapper applies to
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 55f5c25..de6a241 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -250,8 +250,9 @@
// treat it as builtin (ie, no need to clone it into the Program).
StringFragment skCapsName("sk_Caps");
fRootSymbolTable->add(skCapsName,
- std::make_unique<Variable>(/*offset=*/-1, Modifiers(), skCapsName,
- fContext->fSkCaps_Type.get(),
+ std::make_unique<Variable>(/*offset=*/-1,
+ fIRGenerator->fModifiers->handle(Modifiers()),
+ skCapsName, fContext->fSkCaps_Type.get(),
/*builtin=*/false, Variable::kGlobal_Storage));
fIRGenerator->fIntrinsics = nullptr;
@@ -266,22 +267,28 @@
&fragElements, &fFragmentSymbolTable);
#else
{
- Rehydrator rehydrator(fContext.get(), fRootSymbolTable, this, SKSL_INCLUDE_sksl_gpu,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fRootSymbolTable, this, SKSL_INCLUDE_sksl_gpu,
SKSL_INCLUDE_sksl_gpu_LENGTH);
fGpuSymbolTable = rehydrator.symbolTable();
gpuElements = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
{
- Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_vert,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fGpuSymbolTable, this, SKSL_INCLUDE_sksl_vert,
SKSL_INCLUDE_sksl_vert_LENGTH);
fVertexSymbolTable = rehydrator.symbolTable();
fVertexInclude = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
{
- Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_frag,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fGpuSymbolTable, this, SKSL_INCLUDE_sksl_frag,
SKSL_INCLUDE_sksl_frag_LENGTH);
fFragmentSymbolTable = rehydrator.symbolTable();
fragElements = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
#endif
// Call counts are used to track dead-stripping and inlinability within the program being
@@ -308,10 +315,12 @@
}
#if !SKSL_STANDALONE
{
- Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_geom,
- SKSL_INCLUDE_sksl_geom_LENGTH);
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fGpuSymbolTable, this, SKSL_INCLUDE_sksl_geom,
+ SKSL_INCLUDE_sksl_geom_LENGTH);
fGeometrySymbolTable = rehydrator.symbolTable();
fGeometryInclude = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
#else
this->processIncludeFile(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE, fGpuSymbolTable,
@@ -327,7 +336,8 @@
std::vector<std::unique_ptr<ProgramElement>> fpElements;
#if !SKSL_STANDALONE
{
- Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_fp,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fGpuSymbolTable, this, SKSL_INCLUDE_sksl_fp,
SKSL_INCLUDE_sksl_fp_LENGTH);
fFPSymbolTable = rehydrator.symbolTable();
fpElements = rehydrator.elements();
@@ -347,11 +357,12 @@
std::vector<std::unique_ptr<ProgramElement>> pipelineIntrinics;
#if !SKSL_STANDALONE
{
- Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this,
- SKSL_INCLUDE_sksl_pipeline,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fGpuSymbolTable, this, SKSL_INCLUDE_sksl_pipeline,
SKSL_INCLUDE_sksl_pipeline_LENGTH);
fPipelineSymbolTable = rehydrator.symbolTable();
pipelineIntrinics = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
#else
this->processIncludeFile(Program::kPipelineStage_Kind, SKSL_PIPELINE_INCLUDE,
@@ -368,11 +379,12 @@
std::vector<std::unique_ptr<ProgramElement>> interpElements;
#if !SKSL_STANDALONE
{
- Rehydrator rehydrator(fContext.get(), fRootSymbolTable, this,
- SKSL_INCLUDE_sksl_interp,
+ Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
+ fRootSymbolTable, this, SKSL_INCLUDE_sksl_interp,
SKSL_INCLUDE_sksl_interp_LENGTH);
fInterpreterSymbolTable = rehydrator.symbolTable();
interpElements = rehydrator.elements();
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
}
#else
this->processIncludeFile(Program::kGeneric_Kind, SKSL_INTERP_INCLUDE,
@@ -414,6 +426,7 @@
#ifdef SK_DEBUG
fSource = nullptr;
#endif
+ fModifiers.push_back(fIRGenerator->releaseModifiers());
fIRGenerator->finish();
}
@@ -423,7 +436,7 @@
switch (lvalue->kind()) {
case Expression::Kind::kVariableReference: {
const Variable& var = *lvalue->as<VariableReference>().fVariable;
- if (var.fStorage == Variable::kLocal_Storage) {
+ if (var.storage() == Variable::kLocal_Storage) {
(*definitions)[&var] = expr;
}
break;
@@ -492,7 +505,7 @@
case Expression::Kind::kFunctionCall: {
const FunctionCall& c = expr->as<FunctionCall>();
for (size_t i = 0; i < c.function().fParameters.size(); ++i) {
- if (c.function().fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (c.function().fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
this->addDefinition(
c.arguments()[i].get(),
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
@@ -905,7 +918,7 @@
const Variable* var = ref.fVariable;
if (ref.refKind() != VariableReference::kWrite_RefKind &&
ref.refKind() != VariableReference::kPointer_RefKind &&
- var->fStorage == Variable::kLocal_Storage && !definitions[var] &&
+ var->storage() == Variable::kLocal_Storage && !definitions[var] &&
(*undefinedVariables).find(var) == (*undefinedVariables).end()) {
(*undefinedVariables).insert(var);
this->error(expr->fOffset,
@@ -1572,7 +1585,7 @@
fErrorText = "";
fErrorCount = 0;
- fInliner.reset(context(), settings);
+ fInliner.reset(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &settings);
std::vector<std::unique_ptr<ProgramElement>>* inherited;
std::vector<std::unique_ptr<ProgramElement>> elements;
switch (kind) {
@@ -1627,6 +1640,7 @@
fContext,
inherited,
std::move(elements),
+ fIRGenerator->releaseModifiers(),
fIRGenerator->fSymbolTable,
fIRGenerator->fInputs);
fIRGenerator->finish();
@@ -1696,6 +1710,7 @@
break;
}
}
+ program.finish();
return fErrorCount == 0;
}
@@ -1705,7 +1720,8 @@
#ifdef SK_ENABLE_SPIRV_VALIDATION
StringStream buffer;
fSource = program.fSource.get();
- SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer);
+ SPIRVCodeGenerator cg(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &program, this,
+ &buffer);
bool result = cg.generateCode();
fSource = nullptr;
if (result) {
@@ -1723,7 +1739,8 @@
}
#else
fSource = program.fSource.get();
- SPIRVCodeGenerator cg(fContext.get(), &program, this, &out);
+ SPIRVCodeGenerator cg(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &program, this,
+ &out);
bool result = cg.generateCode();
fSource = nullptr;
#endif
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 6de2480..1a18b77 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -252,6 +252,9 @@
std::shared_ptr<SymbolTable> fFPSymbolTable;
std::unique_ptr<IRIntrinsicMap> fFPIntrinsics;
+ // holds ModifiersPools belonging to the core includes for lifetime purposes
+ std::vector<std::unique_ptr<ModifiersPool>> fModifiers;
+
Inliner fInliner;
std::unique_ptr<IRGenerator> fIRGenerator;
int fFlags;
diff --git a/src/sksl/SkSLDehydrator.cpp b/src/sksl/SkSLDehydrator.cpp
index c2619ec..b67bf65 100644
--- a/src/sksl/SkSLDehydrator.cpp
+++ b/src/sksl/SkSLDehydrator.cpp
@@ -216,10 +216,10 @@
const Variable& v = s.as<Variable>();
this->writeU8(Rehydrator::kVariable_Command);
this->writeId(&v);
- this->write(v.fModifiers);
+ this->write(v.modifiers());
this->write(v.name());
this->write(v.type());
- this->writeU8(v.fStorage);
+ this->writeU8(v.storage());
break;
}
case Symbol::Kind::kField: {
@@ -519,8 +519,8 @@
for (const std::unique_ptr<const Symbol>& s : en.symbols()->fOwnedSymbols) {
SkASSERT(s->kind() == Symbol::Kind::kVariable);
Variable& v = (Variable&) *s;
- SkASSERT(v.fInitialValue);
- const IntLiteral& i = v.fInitialValue->as<IntLiteral>();
+ SkASSERT(v.initialValue());
+ const IntLiteral& i = v.initialValue()->as<IntLiteral>();
this->writeS32(i.value());
}
break;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 66452fd..9541eb9 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -785,7 +785,7 @@
}
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
- switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
+ switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
case SK_FRAGCOLOR_BUILTIN:
if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
this->write("sk_FragColor");
@@ -1050,7 +1050,7 @@
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
separator = ", ";
- this->writeModifiers(param->fModifiers, false);
+ this->writeModifiers(param->modifiers(), false);
std::vector<int> sizes;
const Type* type = ¶m->type();
while (type->typeKind() == Type::TypeKind::kArray) {
@@ -1177,7 +1177,7 @@
if (intf.fTypeName == "sk_PerVertex") {
return;
}
- this->writeModifiers(intf.fVariable.fModifiers, true);
+ this->writeModifiers(intf.fVariable.modifiers(), true);
this->writeLine(intf.fTypeName + " {");
fIndentation++;
const Type* structType = &intf.fVariable.type();
@@ -1245,7 +1245,7 @@
}
void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
- this->writeModifiers(var.fVar->fModifiers, global);
+ this->writeModifiers(var.fVar->modifiers(), global);
this->writeTypePrecision(var.fBaseType);
this->writeType(var.fBaseType);
this->write(" ");
@@ -1487,14 +1487,14 @@
break;
case ProgramElement::Kind::kGlobalVar: {
const VarDeclaration& decl = *e.as<GlobalVarDeclaration>().fDecl;
- int builtin = decl.fVar->fModifiers.fLayout.fBuiltin;
+ int builtin = decl.fVar->modifiers().fLayout.fBuiltin;
if (builtin == -1) {
// normal var
this->writeVarDeclaration(decl, true);
this->writeLine();
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput() &&
- decl.fVar->fWriteCount) {
+ decl.fVar->writeCount()) {
if (fProgram.fSettings.fFragColorIsInOut) {
this->write("inout ");
} else {
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 291b8dc..fb4ffe6 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -190,7 +190,7 @@
separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
this->writef("%s%s %s", separator, ParameterType(fContext, param->type(),
- param->fModifiers.fLayout).c_str(),
+ param->modifiers().fLayout).c_str(),
String(param->name()).c_str());
separator = ", ";
}
@@ -234,7 +234,7 @@
const char* separator = "";
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
this->writef("%s%s %s", separator, ParameterType(fContext, param->type(),
- param->fModifiers.fLayout).c_str(),
+ param->modifiers().fLayout).c_str(),
String(param->name()).c_str());
separator = ", ";
}
@@ -287,7 +287,7 @@
std::string perspExpression;
if (usage.hasUniformMatrix()) {
for (const Variable* p : fSectionAndParameterHelper.getParameters()) {
- if ((p->fModifiers.fFlags & Modifiers::kIn_Flag) &&
+ if ((p->modifiers().fFlags & Modifiers::kIn_Flag) &&
usage.fExpression == String(p->name())) {
perspExpression = usage.fExpression + ".hasPerspective()";
break;
@@ -315,7 +315,7 @@
// Don't need to write any fields, FPs are held as children
} else {
this->writef(" %s %s;\n", FieldType(fContext, param->type(),
- param->fModifiers.fLayout).c_str(),
+ param->modifiers().fLayout).c_str(),
name.c_str());
}
}
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index e883af8..fc6bd2d 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -127,7 +127,8 @@
, fSymbolTable(symbolTable)
, fLoopLevel(0)
, fSwitchLevel(0)
- , fErrors(errorReporter) {
+ , fErrors(errorReporter)
+ , fModifiers(new ModifiersPool()) {
SkASSERT(fInliner);
}
@@ -211,6 +212,14 @@
void IRGenerator::finish() {
this->popSymbolTable();
fSettings = nullptr;
+ // releaseModifiers should have been called before now
+ SkASSERT(fModifiers->empty());
+}
+
+std::unique_ptr<ModifiersPool> IRGenerator::releaseModifiers() {
+ std::unique_ptr<ModifiersPool> result = std::move(fModifiers);
+ fModifiers = std::make_unique<ModifiersPool>();
+ return result;
}
std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
@@ -444,8 +453,8 @@
sizes.push_back(nullptr);
}
}
- auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, type,
- fIsBuiltinCode, storage);
+ auto var = std::make_unique<Variable>(varDecl.fOffset, fModifiers->handle(modifiers),
+ varData.fName, type, fIsBuiltinCode, storage);
if (var->name() == Compiler::RTADJUST_NAME) {
SkASSERT(!fRTAdjust);
SkASSERT(var->type() == *fContext.fFloat4_Type);
@@ -461,17 +470,16 @@
if (!value) {
return {};
}
- var->fWriteCount = 1;
- var->fInitialValue = value.get();
+ var->setInitialValue(value.get());
}
- const Symbol* symbol = (*fSymbolTable)[var->name()];
+ Symbol* symbol = (*fSymbolTable)[var->name()];
if (symbol && storage == Variable::kGlobal_Storage && var->name() == "sk_FragColor") {
// Already defined, ignore.
} else if (symbol && storage == Variable::kGlobal_Storage &&
symbol->kind() == Symbol::Kind::kVariable &&
- symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) {
+ symbol->as<Variable>().modifiers().fLayout.fBuiltin >= 0) {
// Already defined, just update the modifiers.
- symbol->as<Variable>().fModifiers = var->fModifiers;
+ symbol->as<Variable>().setModifiersHandle(var->modifiersHandle());
} else {
varDecls.emplace_back(std::make_unique<VarDeclaration>(
var.get(), baseType, std::move(sizes), std::move(value)));
@@ -500,9 +508,11 @@
fInvocations = modifiers.fLayout.fInvocations;
if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
modifiers.fLayout.fInvocations = -1;
- const Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
- invocationId.fModifiers.fFlags = 0;
- invocationId.fModifiers.fLayout.fBuiltin = -1;
+ Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
+ Modifiers modifiers = invocationId.modifiers();
+ modifiers.fFlags = 0;
+ modifiers.fLayout.fBuiltin = -1;
+ invocationId.setModifiersHandle(fModifiers->handle(modifiers));
if (modifiers.fLayout.description() == "") {
return nullptr;
}
@@ -768,7 +778,7 @@
"_invoke", std::make_unique<FunctionDeclaration>(/*offset=*/-1,
invokeModifiers,
"_invoke",
- std::vector<const Variable*>(),
+ std::vector<Variable*>(),
*fContext.fVoid_Type,
/*builtin=*/false));
fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
@@ -930,7 +940,7 @@
const ASTNode::FunctionData& funcData = f.getFunctionData();
this->checkModifiers(f.fOffset, funcData.fModifiers, Modifiers::kHasSideEffects_Flag |
Modifiers::kInline_Flag);
- std::vector<const Variable*> parameters;
+ std::vector<Variable*> parameters;
for (size_t i = 0; i < funcData.fParameterCount; ++i) {
const ASTNode& param = *(iter++);
SkASSERT(param.fKind == ASTNode::Kind::kParameter);
@@ -956,15 +966,16 @@
return;
}
StringFragment name = pd.fName;
- const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
- std::make_unique<Variable>(param.fOffset, pd.fModifiers, name, type,
- fIsBuiltinCode, Variable::kParameter_Storage));
+ Variable* var = fSymbolTable->takeOwnershipOfSymbol(
+ std::make_unique<Variable>(param.fOffset, fModifiers->handle(pd.fModifiers),
+ name, type, fIsBuiltinCode,
+ Variable::kParameter_Storage));
parameters.push_back(var);
}
auto paramIsCoords = [&](int idx) {
return parameters[idx]->type() == *fContext.fFloat2_Type &&
- parameters[idx]->fModifiers.fFlags == 0;
+ parameters[idx]->modifiers().fFlags == 0;
};
if (funcData.fName == "main") {
@@ -1036,7 +1047,7 @@
}
decl = other;
for (size_t i = 0; i < parameters.size(); i++) {
- if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
+ if (parameters[i]->modifiers() != other->fParameters[i]->modifiers()) {
fErrors.error(f.fOffset, "modifiers on parameter " +
to_string((uint64_t) i + 1) +
" differ between declaration and definition");
@@ -1077,7 +1088,9 @@
fKind == Program::kFragmentProcessor_Kind)) {
if (parameters.size() == 1) {
SkASSERT(paramIsCoords(0));
- parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
+ Modifiers m = parameters[0]->modifiers();
+ m.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
+ parameters[0]->setModifiersHandle(fModifiers->handle(m));
}
}
for (size_t i = 0; i < parameters.size(); i++) {
@@ -1140,7 +1153,7 @@
SkASSERT(vd.fVar->type() == *fContext.fFloat4_Type);
fRTAdjustFieldIndex = fields.size();
}
- fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->name(),
+ fields.push_back(Type::Field(vd.fVar->modifiers(), vd.fVar->name(),
&vd.fVar->type()));
if (vd.fValue) {
fErrors.error(decl->fOffset,
@@ -1186,9 +1199,9 @@
sizes.push_back(nullptr);
}
}
- const Variable* var = old->takeOwnershipOfSymbol(
+ Variable* var = old->takeOwnershipOfSymbol(
std::make_unique<Variable>(intf.fOffset,
- id.fModifiers,
+ fModifiers->handle(id.fModifiers),
id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
type,
fIsBuiltinCode,
@@ -1218,9 +1231,8 @@
return true;
case Expression::Kind::kVariableReference: {
const Variable& var = *value.as<VariableReference>().fVariable;
- return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
- var.fInitialValue &&
- this->getConstantInt(*var.fInitialValue, out);
+ return (var.modifiers().fFlags & Modifiers::kConst_Flag) &&
+ var.initialValue() && this->getConstantInt(*var.initialValue(), out);
}
default:
return false;
@@ -1262,8 +1274,9 @@
++currentValue;
fSymbolTable->add(
child.getString(),
- std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), type,
- fIsBuiltinCode, Variable::kGlobal_Storage, value.get()));
+ std::make_unique<Variable>(e.fOffset, fModifiers->handle(modifiers),
+ child.getString(), type, fIsBuiltinCode,
+ Variable::kGlobal_Storage, value.get()));
fSymbolTable->takeOwnershipOfIRNode(std::move(value));
}
// Now we orphanize the Enum's symbol table, so that future lookups in it are strict
@@ -1376,7 +1389,8 @@
}
case Symbol::Kind::kVariable: {
const Variable* var = &result->as<Variable>();
- switch (var->fModifiers.fLayout.fBuiltin) {
+ const Modifiers& modifiers = var->modifiers();
+ switch (modifiers.fLayout.fBuiltin) {
case SK_WIDTH_BUILTIN:
fInputs.fRTWidth = true;
break;
@@ -1394,10 +1408,10 @@
#endif
}
if (fKind == Program::kFragmentProcessor_Kind &&
- (var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
- !(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
- !var->fModifiers.fLayout.fKey &&
- var->fModifiers.fLayout.fBuiltin == -1 &&
+ (modifiers.fFlags & Modifiers::kIn_Flag) &&
+ !(modifiers.fFlags & Modifiers::kUniform_Flag) &&
+ !modifiers.fLayout.fKey &&
+ modifiers.fLayout.fBuiltin == -1 &&
var->type().nonnullable() != *fContext.fFragmentProcessor_Type &&
var->type().typeKind() != Type::TypeKind::kSampler) {
bool valid = false;
@@ -1454,7 +1468,6 @@
section.fText);
}
-
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
const Type& type) {
if (!expr) {
@@ -2109,7 +2122,7 @@
if (!arguments[i]) {
return nullptr;
}
- const Modifiers& paramModifiers = function.fParameters[i]->fModifiers;
+ const Modifiers& paramModifiers = function.fParameters[i]->modifiers();
if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
if (!this->setRefKind(*arguments[i], paramModifiers.fFlags & Modifiers::kIn_Flag
? VariableReference::kReadWrite_RefKind
@@ -2697,9 +2710,9 @@
ASTNode(&fFile->fNodes, offset, ASTNode::Kind::kIdentifier, field));
if (result) {
const Variable& v = *result->as<VariableReference>().fVariable;
- SkASSERT(v.fInitialValue);
+ SkASSERT(v.initialValue());
result = std::make_unique<IntLiteral>(
- offset, v.fInitialValue->as<IntLiteral>().value(), &type);
+ offset, v.initialValue()->as<IntLiteral>().value(), &type);
} else {
fErrors.error(offset,
"type '" + type.name() + "' does not have a member named '" + field +
@@ -2860,8 +2873,8 @@
// so we're pointing at a Program-owned expression.
const Variable* clonedVar =
fGenerator->fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
- sharedVar->fOffset, sharedVar->fModifiers, sharedVar->name(),
- &sharedVar->type(), /*builtin=*/false, sharedVar->fStorage,
+ sharedVar->fOffset, sharedVar->modifiersHandle(), sharedVar->name(),
+ &sharedVar->type(), /*builtin=*/false, sharedVar->storage(),
varDecl.fValue.get()));
// Go back and update the VarDeclaration to point at the cloned Variable.
@@ -2877,7 +2890,7 @@
bool visitExpression(Expression& e) override {
// Look for references to builtin variables.
- if (e.is<VariableReference>() && e.as<VariableReference>().fVariable->fBuiltin) {
+ if (e.is<VariableReference>() && e.as<VariableReference>().fVariable->isBuiltin()) {
const Variable* sharedVar = e.as<VariableReference>().fVariable;
this->cloneVariable(sharedVar->name());
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 9ba9e77..5e60f70 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -123,6 +123,11 @@
*/
void finish();
+ /**
+ * Relinquishes ownership of the Modifiers that have been collected so far and returns them.
+ */
+ std::unique_ptr<ModifiersPool> releaseModifiers();
+
void pushSymbolTable();
void popSymbolTable();
@@ -224,6 +229,7 @@
bool fCanInline = true;
// true if we are currently processing one of the built-in SkSL include files
bool fIsBuiltinCode;
+ std::unique_ptr<ModifiersPool> fModifiers;
friend class AutoSymbolTable;
friend class AutoLoopLevel;
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index 5b3fb4e..1755bdf 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -301,9 +301,11 @@
}
}
-void Inliner::reset(const Context& context, const Program::Settings& settings) {
- fContext = &context;
- fSettings = &settings;
+void Inliner::reset(const Context* context, ModifiersPool* modifiers,
+ const Program::Settings* settings) {
+ fContext = context;
+ fModifiers = modifiers;
+ fSettings = settings;
fInlineVarCounter = 0;
}
@@ -550,11 +552,11 @@
const Type* typePtr = copy_if_needed(&old->type(), *symbolTableForStatement);
const Variable* clone = symbolTableForStatement->takeOwnershipOfSymbol(
std::make_unique<Variable>(offset,
- old->fModifiers,
+ old->modifiersHandle(),
namePtr->c_str(),
typePtr,
isBuiltinCode,
- old->fStorage,
+ old->storage(),
initialValue.get()));
(*varMap)[old] = std::make_unique<VariableReference>(offset, clone);
return std::make_unique<VarDeclaration>(clone, baseTypePtr, std::move(sizes),
@@ -628,9 +630,10 @@
StringFragment nameFrag{namePtr->c_str(), namePtr->length()};
// Add our new variable to the symbol table.
- auto newVar = std::make_unique<Variable>(/*offset=*/-1, Modifiers(), nameFrag, type,
- caller->fBuiltin, Variable::kLocal_Storage,
- initialValue->get());
+ auto newVar = std::make_unique<Variable>(/*offset=*/-1,
+ fModifiers->handle(Modifiers()),
+ nameFrag, type, caller->fBuiltin,
+ Variable::kLocal_Storage, initialValue->get());
const Variable* variableSymbol = symbolTableForCall->add(nameFrag, std::move(newVar));
// Prepare the variable declaration (taking extra care with `out` params to not clobber any
@@ -667,7 +670,7 @@
std::vector<int> argsToCopyBack;
for (int i = 0; i < (int) arguments.size(); ++i) {
const Variable* param = function.fDeclaration.fParameters[i];
- bool isOutParam = param->fModifiers.fFlags & Modifiers::kOut_Flag;
+ bool isOutParam = param->modifiers().fFlags & Modifiers::kOut_Flag;
// If this argument can be inlined trivially (e.g. a swizzle, or a constant array index)...
if (is_trivial_argument(*arguments[i])) {
@@ -684,7 +687,7 @@
}
varMap[param] = makeInlineVar(String(param->name()), &arguments[i]->type(),
- param->fModifiers, &arguments[i]);
+ param->modifiers(), &arguments[i]);
}
const Block& body = function.fBody->as<Block>();
@@ -730,7 +733,8 @@
} else {
// It's a void function, so it doesn't actually result in anything, but we have to return
// something non-null as a standin.
- inlinedCall.fReplacementExpr = std::make_unique<BoolLiteral>(*fContext, offset,
+ inlinedCall.fReplacementExpr = std::make_unique<BoolLiteral>(*fContext,
+ offset,
/*value=*/false);
}
diff --git a/src/sksl/SkSLInliner.h b/src/sksl/SkSLInliner.h
index 7a723b7..8f9d382 100644
--- a/src/sksl/SkSLInliner.h
+++ b/src/sksl/SkSLInliner.h
@@ -23,9 +23,10 @@
struct FunctionDefinition;
struct InlineCandidate;
struct InlineCandidateList;
+class ModifiersPool;
struct Statement;
class SymbolTable;
-struct Variable;
+class Variable;
/**
* Converts a FunctionCall in the IR to a set of statements to be injected ahead of the function
@@ -37,7 +38,7 @@
public:
Inliner() {}
- void reset(const Context&, const Program::Settings&);
+ void reset(const Context*, ModifiersPool* modifiers, const Program::Settings*);
/**
* Processes the passed-in FunctionCall expression. The FunctionCall expression should be
@@ -87,6 +88,7 @@
bool isLargeFunction(const InlineCandidate& candidate, LargeFunctionCache* cache);
const Context* fContext = nullptr;
+ ModifiersPool* fModifiers = nullptr;
const Program::Settings* fSettings = nullptr;
int fInlineVarCounter = 0;
};
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index 2ef5451..8dfb0f9 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -265,7 +265,7 @@
const Expression& arg = *arguments[i];
this->write(separator);
separator = ", ";
- if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
this->write("&");
}
this->writeExpression(arg, kSequence_Precedence);
@@ -680,7 +680,7 @@
}
void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
- switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
+ switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
case SK_FRAGCOLOR_BUILTIN:
this->write("_out->sk_FragColor");
break;
@@ -699,12 +699,12 @@
this->write(fProgram.fSettings.fFlipY ? "_frontFacing" : "(!_frontFacing)");
break;
default:
- if (Variable::kGlobal_Storage == ref.fVariable->fStorage) {
- if (ref.fVariable->fModifiers.fFlags & Modifiers::kIn_Flag) {
+ if (Variable::kGlobal_Storage == ref.fVariable->storage()) {
+ if (ref.fVariable->modifiers().fFlags & Modifiers::kIn_Flag) {
this->write("_in.");
- } else if (ref.fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ } else if (ref.fVariable->modifiers().fFlags & Modifiers::kOut_Flag) {
this->write("_out->");
- } else if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag &&
+ } else if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag &&
ref.fVariable->type().typeKind() != Type::TypeKind::kSampler) {
this->write("_uniforms.");
} else {
@@ -836,8 +836,8 @@
this->write("(");
}
if (Compiler::IsAssignment(op) && left.is<VariableReference>() &&
- left.as<VariableReference>().fVariable->fStorage == Variable::kParameter_Storage &&
- left.as<VariableReference>().fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ left.as<VariableReference>().fVariable->storage() == Variable::kParameter_Storage &&
+ left.as<VariableReference>().fVariable->modifiers().fFlags & Modifiers::kOut_Flag) {
// writing to an out parameter. Since we have to turn those into pointers, we have to
// dereference it here.
this->write("*");
@@ -955,7 +955,7 @@
const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
const VarDeclaration& var = *decls.fDecl;
if (var.fVar->type().typeKind() == Type::TypeKind::kSampler) {
- if (var.fVar->fModifiers.fLayout.fBinding < 0) {
+ if (var.fVar->modifiers().fLayout.fBinding < 0) {
fErrors.error(decls.fOffset,
"Metal samplers must have 'layout(binding=...)'");
return;
@@ -968,13 +968,13 @@
this->write(", texture2d<float> ");
this->writeName(var.fVar->name());
this->write("[[texture(");
- this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
+ this->write(to_string(var.fVar->modifiers().fLayout.fBinding));
this->write(")]]");
this->write(", sampler ");
this->writeName(var.fVar->name());
this->write(SAMPLER_SUFFIX);
this->write("[[sampler(");
- this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
+ this->write(to_string(var.fVar->modifiers().fLayout.fBinding));
this->write(")]]");
}
} else if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
@@ -987,7 +987,7 @@
this->write("& " );
this->write(fInterfaceBlockNameMap[&intf]);
this->write(" [[buffer(");
- this->write(to_string(intf.fVariable.fModifiers.fLayout.fBinding));
+ this->write(to_string(intf.fVariable.modifiers().fLayout.fBinding));
this->write(")]]");
}
}
@@ -1036,7 +1036,7 @@
for (const auto& param : f.fDeclaration.fParameters) {
this->write(separator);
separator = ", ";
- this->writeModifiers(param->fModifiers, false);
+ this->writeModifiers(param->modifiers(), false);
std::vector<int> sizes;
const Type* type = ¶m->type();
while (type->typeKind() == Type::TypeKind::kArray) {
@@ -1044,7 +1044,7 @@
type = &type->componentType();
}
this->writeType(*type);
- if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
this->write("*");
}
this->write(" ");
@@ -1113,7 +1113,7 @@
if ("sk_PerVertex" == intf.fTypeName) {
return;
}
- this->writeModifiers(intf.fVariable.fModifiers, true);
+ this->writeModifiers(intf.fVariable.modifiers(), true);
this->write("struct ");
this->writeLine(intf.fTypeName + " {");
const Type* structType = &intf.fVariable.type();
@@ -1215,10 +1215,10 @@
}
void MetalCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
- if (global && !(var.fVar->fModifiers.fFlags & Modifiers::kConst_Flag)) {
+ if (global && !(var.fVar->modifiers().fFlags & Modifiers::kConst_Flag)) {
return;
}
- this->writeModifiers(var.fVar->fModifiers, global);
+ this->writeModifiers(var.fVar->modifiers(), global);
this->writeType(var.fBaseType);
this->write(" ");
this->writeName(var.fVar->name());
@@ -1393,15 +1393,15 @@
if (e.is<GlobalVarDeclaration>()) {
const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
const Variable& var = *decls.fDecl->fVar;
- if (var.fModifiers.fFlags & Modifiers::kUniform_Flag &&
+ if (var.modifiers().fFlags & Modifiers::kUniform_Flag &&
var.type().typeKind() != Type::TypeKind::kSampler) {
if (-1 == fUniformBuffer) {
this->write("struct Uniforms {\n");
- fUniformBuffer = var.fModifiers.fLayout.fSet;
+ fUniformBuffer = var.modifiers().fLayout.fSet;
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal uniforms must have 'layout(set=...)'");
}
- } else if (var.fModifiers.fLayout.fSet != fUniformBuffer) {
+ } else if (var.modifiers().fLayout.fSet != fUniformBuffer) {
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
"the same 'layout(set=...)'");
@@ -1426,19 +1426,19 @@
if (e.is<GlobalVarDeclaration>()) {
const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
const Variable& var = *decls.fDecl->fVar;
- if (var.fModifiers.fFlags & Modifiers::kIn_Flag &&
- -1 == var.fModifiers.fLayout.fBuiltin) {
+ if (var.modifiers().fFlags & Modifiers::kIn_Flag &&
+ -1 == var.modifiers().fLayout.fBuiltin) {
this->write(" ");
this->writeType(var.type());
this->write(" ");
this->writeName(var.name());
- if (-1 != var.fModifiers.fLayout.fLocation) {
+ if (-1 != var.modifiers().fLayout.fLocation) {
if (fProgram.fKind == Program::kVertex_Kind) {
this->write(" [[attribute(" +
- to_string(var.fModifiers.fLayout.fLocation) + ")]]");
+ to_string(var.modifiers().fLayout.fLocation) + ")]]");
} else if (fProgram.fKind == Program::kFragment_Kind) {
this->write(" [[user(locn" +
- to_string(var.fModifiers.fLayout.fLocation) + ")]]");
+ to_string(var.modifiers().fLayout.fLocation) + ")]]");
}
}
this->write(";\n");
@@ -1459,19 +1459,19 @@
if (e.is<GlobalVarDeclaration>()) {
const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
const Variable& var = *decls.fDecl->fVar;
- if (var.fModifiers.fFlags & Modifiers::kOut_Flag &&
- -1 == var.fModifiers.fLayout.fBuiltin) {
+ if (var.modifiers().fFlags & Modifiers::kOut_Flag &&
+ -1 == var.modifiers().fLayout.fBuiltin) {
this->write(" ");
this->writeType(var.type());
this->write(" ");
this->writeName(var.name());
if (fProgram.fKind == Program::kVertex_Kind) {
this->write(" [[user(locn" +
- to_string(var.fModifiers.fLayout.fLocation) + ")]]");
+ to_string(var.modifiers().fLayout.fLocation) + ")]]");
} else if (fProgram.fKind == Program::kFragment_Kind) {
this->write(" [[color(" +
- to_string(var.fModifiers.fLayout.fLocation) +")");
- int colorIndex = var.fModifiers.fLayout.fIndex;
+ to_string(var.modifiers().fLayout.fLocation) +")");
+ int colorIndex = var.modifiers().fLayout.fIndex;
if (colorIndex) {
this->write(", index(" + to_string(colorIndex) + ")");
}
@@ -1514,7 +1514,7 @@
const GlobalVarDeclaration& decls = element.as<GlobalVarDeclaration>();
const VarDeclaration& decl = *decls.fDecl;
const Variable& var = *decl.fVar;
- if ((!var.fModifiers.fFlags && -1 == var.fModifiers.fLayout.fBuiltin) ||
+ if ((!var.modifiers().fFlags && -1 == var.modifiers().fLayout.fBuiltin) ||
var.type().typeKind() == Type::TypeKind::kSampler) {
if (var.type().typeKind() == Type::TypeKind::kSampler) {
// Samplers are represented as a "texture/sampler" duo in the global struct.
@@ -1638,7 +1638,7 @@
break;
case ProgramElement::Kind::kGlobalVar: {
const VarDeclaration& decl = *e.as<GlobalVarDeclaration>().fDecl;
- int builtin = decl.fVar->fModifiers.fLayout.fBuiltin;
+ int builtin = decl.fVar->modifiers().fLayout.fBuiltin;
if (-1 == builtin) {
// normal var
this->writeVarDeclaration(decl, true);
@@ -1716,15 +1716,16 @@
}
case Expression::Kind::kVariableReference: {
const VariableReference& v = e->as<VariableReference>();
+ const Modifiers& modifiers = v.fVariable->modifiers();
Requirements result = kNo_Requirements;
- if (v.fVariable->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
+ if (modifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
result = kGlobals_Requirement | kFragCoord_Requirement;
- } else if (Variable::kGlobal_Storage == v.fVariable->fStorage) {
- if (v.fVariable->fModifiers.fFlags & Modifiers::kIn_Flag) {
+ } else if (Variable::kGlobal_Storage == v.fVariable->storage()) {
+ if (modifiers.fFlags & Modifiers::kIn_Flag) {
result = kInputs_Requirement;
- } else if (v.fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
result = kOutputs_Requirement;
- } else if (v.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag &&
+ } else if (modifiers.fFlags & Modifiers::kUniform_Flag &&
v.fVariable->type().typeKind() != Type::TypeKind::kSampler) {
result = kUniforms_Requirement;
} else {
diff --git a/src/sksl/SkSLModifiersPool.h b/src/sksl/SkSLModifiersPool.h
new file mode 100644
index 0000000..31e9bc4
--- /dev/null
+++ b/src/sksl/SkSLModifiersPool.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_MODIFIERSPOOL
+#define SKSL_MODIFIERSPOOL
+
+#include <unordered_map>
+
+namespace SkSL {
+
+struct Modifiers;
+
+/**
+ * Stores a pool of Modifiers objects. Modifiers is fairly heavy, so to reduce IRNode's size we only
+ * store a handle to the Modifiers inside of the node and keep the object itself in a ModifiersPool.
+ */
+class ModifiersPool {
+public:
+ class Handle {
+ public:
+ Handle() = default;
+
+ Handle(const ModifiersPool* pool, int index)
+ : fPool(pool)
+ , fIndex(index) {}
+
+ const Modifiers* operator->() const {
+ return &fPool->fModifiers[fIndex];
+ }
+
+ const Modifiers& operator*() const {
+ return fPool->fModifiers[fIndex];
+ }
+
+ private:
+ const ModifiersPool* fPool;
+ int fIndex;
+ };
+
+ bool empty() {
+ return fModifiers.empty();
+ }
+
+ Handle handle(const Modifiers& modifiers) {
+ SkASSERT(fModifiers.size() == fModifiersMap.size());
+ int index;
+ auto found = fModifiersMap.find(modifiers);
+ if (found != fModifiersMap.end()) {
+ index = found->second;
+ } else {
+ index = fModifiers.size();
+ fModifiers.push_back(modifiers);
+ fModifiersMap.insert({modifiers, index});
+ }
+ return Handle(this, index);
+ }
+
+ void finish() {
+ fModifiersMap.clear();
+ }
+
+private:
+ std::vector<Modifiers> fModifiers;
+ std::unordered_map<Modifiers, int> fModifiersMap;
+};
+
+} // namespace SkSL
+
+#endif
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index 35e2aae..8b03c5b 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -107,7 +107,7 @@
}
void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
- switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
+ switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
case SK_OUTCOLOR_BUILTIN:
this->write(Compiler::kFormatArgPlaceholderStr);
fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
@@ -130,7 +130,7 @@
found = true;
break;
}
- if (var.fModifiers.fFlags & flag) {
+ if (var.modifiers().fFlags & flag) {
++index;
}
}
@@ -139,12 +139,12 @@
return index;
};
- if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) {
+ if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) {
this->write(Compiler::kFormatArgPlaceholderStr);
fArgs->fFormatArgs.push_back(
Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
varIndexByFlag(Modifiers::kUniform_Flag)));
- } else if (ref.fVariable->fModifiers.fFlags & Modifiers::kVarying_Flag) {
+ } else if (ref.fVariable->modifiers().fFlags & Modifiers::kVarying_Flag) {
this->write("_vtx_attr_");
this->write(to_string(varIndexByFlag(Modifiers::kVarying_Flag)));
} else {
@@ -214,9 +214,9 @@
}
if (p.is<GlobalVarDeclaration>()) {
const Variable& var = *p.as<GlobalVarDeclaration>().fDecl->fVar;
- if (var.fModifiers.fFlags &
+ if (var.modifiers().fFlags &
(Modifiers::kIn_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag) ||
- -1 != var.fModifiers.fLayout.fBuiltin) {
+ var.modifiers().fLayout.fBuiltin == -1) {
return;
}
}
diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp
index c778bf4..3e9d7bf 100644
--- a/src/sksl/SkSLRehydrator.cpp
+++ b/src/sksl/SkSLRehydrator.cpp
@@ -126,7 +126,7 @@
}
}
-const Symbol* Rehydrator::symbol() {
+Symbol* Rehydrator::symbol() {
int kind = this->readU8();
switch (kind) {
case kArrayType_Command: {
@@ -139,7 +139,7 @@
} else {
name += "[" + to_string(count) + "]";
}
- const Type* result = fSymbolTable->takeOwnershipOfSymbol(
+ Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(name, Type::TypeKind::kArray, *componentType, count));
this->addSymbol(id, result);
return result;
@@ -147,7 +147,7 @@
case kEnumType_Command: {
uint16_t id = this->readU16();
StringFragment name = this->readString();
- const Type* result = fSymbolTable->takeOwnershipOfSymbol(
+ Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(name, Type::TypeKind::kEnum));
this->addSymbol(id, result);
return result;
@@ -157,13 +157,13 @@
Modifiers modifiers = this->modifiers();
StringFragment name = this->readString();
int parameterCount = this->readU8();
- std::vector<const Variable*> parameters;
+ std::vector<Variable*> parameters;
parameters.reserve(parameterCount);
for (int i = 0; i < parameterCount; ++i) {
parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
}
const Type* returnType = this->type();
- const FunctionDeclaration* result =
+ FunctionDeclaration* result =
fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
/*offset=*/-1, modifiers, name, std::move(parameters), *returnType,
/*builtin=*/true));
@@ -173,14 +173,14 @@
case kField_Command: {
const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
uint8_t index = this->readU8();
- const Field* result = fSymbolTable->takeOwnershipOfSymbol(
+ Field* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Field>(/*offset=*/-1, owner, index));
return result;
}
case kNullableType_Command: {
uint16_t id = this->readU16();
const Type* base = this->type();
- const Type* result = fSymbolTable->takeOwnershipOfSymbol(
+ Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(base->name() + "?", Type::TypeKind::kNullable, *base));
this->addSymbol(id, result);
return result;
@@ -197,7 +197,7 @@
const Type* type = this->type();
fields.emplace_back(m, fieldName, type);
}
- const Type* result = fSymbolTable->takeOwnershipOfSymbol(
+ Type* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<Type>(/*offset=*/-1, name, std::move(fields)));
this->addSymbol(id, result);
return result;
@@ -210,8 +210,8 @@
case kSymbolAlias_Command: {
uint16_t id = this->readU16();
StringFragment name = this->readString();
- const Symbol* origSymbol = this->symbol();
- const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
+ Symbol* origSymbol = this->symbol();
+ SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
this->addSymbol(id, symbolAlias);
return symbolAlias;
@@ -219,7 +219,7 @@
case kSystemType_Command: {
uint16_t id = this->readU16();
StringFragment name = this->readString();
- const Symbol* result = (*fSymbolTable)[name];
+ Symbol* result = (*fSymbolTable)[name];
SkASSERT(result && result->kind() == Symbol::Kind::kType);
this->addSymbol(id, result);
return result;
@@ -234,18 +234,18 @@
SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
functions.push_back((const FunctionDeclaration*) f);
}
- const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
+ UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
std::make_unique<UnresolvedFunction>(std::move(functions)));
this->addSymbol(id, result);
return result;
}
case kVariable_Command: {
uint16_t id = this->readU16();
- Modifiers m = this->modifiers();
+ ModifiersPool::Handle m = fModifiers.handle(this->modifiers());
StringFragment name = this->readString();
const Type* type = this->type();
Variable::Storage storage = (Variable::Storage) this->readU8();
- const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
+ Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
/*offset=*/-1, m, name, type, /*builtin=*/true, storage));
this->addSymbol(id, result);
return result;
@@ -285,9 +285,8 @@
SkASSERT(s->kind() == Symbol::Kind::kVariable);
Variable& v = (Variable&) *s;
int value = this->readS32();
- v.fInitialValue = symbols->takeOwnershipOfIRNode(
- std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value));
- v.fWriteCount = 1;
+ v.setInitialValue(symbols->takeOwnershipOfIRNode(
+ std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value)));
}
return std::unique_ptr<ProgramElement>(new Enum(-1, typeName, std::move(symbols)));
}
@@ -429,9 +428,7 @@
}
std::unique_ptr<Expression> value = this->expression();
if (value) {
- var->fInitialValue = value.get();
- SkASSERT(var->fWriteCount == 0);
- ++var->fWriteCount;
+ var->setInitialValue(value.get());
}
return std::unique_ptr<Statement>(
new VarDeclaration(var, baseType, std::move(sizes), std::move(value)));
@@ -567,7 +564,7 @@
std::shared_ptr<SymbolTable> result = inherit ? std::make_shared<SymbolTable>(fSymbolTable)
: std::make_shared<SymbolTable>(fErrors);
fSymbolTable = result;
- std::vector<const Symbol*> ownedSymbols;
+ std::vector<Symbol*> ownedSymbols;
ownedSymbols.reserve(ownedCount);
for (int i = 0; i < ownedCount; ++i) {
ownedSymbols.push_back(this->symbol());
diff --git a/src/sksl/SkSLRehydrator.h b/src/sksl/SkSLRehydrator.h
index 18bdda4..f254f05 100644
--- a/src/sksl/SkSLRehydrator.h
+++ b/src/sksl/SkSLRehydrator.h
@@ -20,6 +20,7 @@
class Context;
class ErrorReporter;
struct Expression;
+class IRGenerator;
struct ProgramElement;
struct Statement;
class SymbolTable;
@@ -144,9 +145,11 @@
};
// src must remain in memory as long as the objects created from it do
- Rehydrator(Context* context, std::shared_ptr<SymbolTable> symbolTable,
- ErrorReporter* errorReporter, const uint8_t* src, size_t length)
+ Rehydrator(const Context* context, ModifiersPool* modifiers,
+ std::shared_ptr<SymbolTable> symbolTable, ErrorReporter* errorReporter,
+ const uint8_t* src, size_t length)
: fContext(*context)
+ , fModifiers(*modifiers)
, fErrors(errorReporter)
, fSymbolTable(std::move(symbolTable))
, fStart(src)
@@ -200,7 +203,7 @@
return StringFragment(chars, length);
}
- void addSymbol(int id, const Symbol* symbol) {
+ void addSymbol(int id, Symbol* symbol) {
while ((size_t) id >= fSymbols.size()) {
fSymbols.push_back(nullptr);
}
@@ -218,7 +221,7 @@
Modifiers modifiers();
- const Symbol* symbol();
+ Symbol* symbol();
std::unique_ptr<ProgramElement> element();
@@ -228,10 +231,11 @@
const Type* type();
- Context& fContext;
+ const Context& fContext;
+ ModifiersPool& fModifiers;
ErrorReporter* fErrors;
std::shared_ptr<SymbolTable> fSymbolTable;
- std::vector<const Symbol*> fSymbols;
+ std::vector<Symbol*> fSymbols;
const uint8_t* fStart;
const uint8_t* fIP;
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index 05cbea6..5e7dbab 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -179,7 +179,7 @@
}
static bool is_out(const Variable& var) {
- return (var.fModifiers.fFlags & Modifiers::kOut_Flag) != 0;
+ return (var.modifiers().fFlags & Modifiers::kOut_Flag) != 0;
}
void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, OutputStream& out) {
@@ -717,7 +717,7 @@
SpvId result = this->nextId();
std::vector<SpvId> argumentIds;
for (size_t i = 0; i < arguments.size(); i++) {
- if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
} else {
argumentIds.push_back(this->writeExpression(*arguments[i], out));
@@ -737,7 +737,7 @@
SpvId result = this->nextId();
std::vector<SpvId> argumentIds;
for (size_t i = 0; i < arguments.size(); i++) {
- if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
} else {
argumentIds.push_back(this->writeExpression(*arguments[i], out));
@@ -1564,10 +1564,10 @@
switch (expr.kind()) {
case Expression::Kind::kVariableReference: {
const Variable& var = *expr.as<VariableReference>().fVariable;
- if (var.fStorage != Variable::kGlobal_Storage) {
+ if (var.storage() != Variable::kGlobal_Storage) {
return SpvStorageClassFunction;
}
- SpvStorageClass_ result = get_storage_class(var.fModifiers);
+ SpvStorageClass_ result = get_storage_class(var.modifiers());
if (result == SpvStorageClassFunction) {
result = SpvStorageClassPrivate;
}
@@ -1727,7 +1727,7 @@
case Expression::Kind::kVariableReference: {
SpvId typeId;
const Variable& var = *expr.as<VariableReference>().fVariable;
- if (var.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
+ if (var.modifiers().fLayout.fBuiltin == SK_IN_BUILTIN) {
typeId = this->getType(Type("sk_in", Type::TypeKind::kArray,
var.type().componentType(), fSkInCount));
} else {
@@ -1838,7 +1838,7 @@
SpvId var = entry->second;
this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable->type()), result, var, out);
this->writePrecisionModifier(ref.fVariable->type(), result);
- if (ref.fVariable->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
+ if (ref.fVariable->modifiers().fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
(fProgram.fSettings.fFlipY || fProgram.fSettings.fInverseW)) {
// The x component never changes, so just grab it
SpvId xId = this->nextId();
@@ -1875,9 +1875,10 @@
Layout layout(0, -1, -1, binding, -1, set, -1, -1, Layout::Format::kUnspecified,
Layout::kUnspecified_Primitive, -1, -1, "", "", Layout::kNo_Key,
Layout::CType::kDefault);
+ Modifiers modifiers(layout, Modifiers::kUniform_Flag);
const Variable* intfVar = fSynthetics.takeOwnershipOfSymbol(
std::make_unique<Variable>(/*offset=*/-1,
- Modifiers(layout, Modifiers::kUniform_Flag),
+ fModifiers.handle(modifiers),
name,
&intfStruct,
/*builtin=*/false,
@@ -1946,7 +1947,7 @@
return adjusted;
}
- if (ref.fVariable->fModifiers.fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN &&
+ if (ref.fVariable->modifiers().fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN &&
!fProgram.fSettings.fFlipY) {
// FrontFacing in Vulkan is defined in terms of a top-down render target. In skia, we use
// the default convention of "counter-clockwise face is front".
@@ -2692,8 +2693,8 @@
}
SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight) {
- bool isBuffer = (0 != (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag));
- bool pushConstant = (0 != (intf.fVariable.fModifiers.fLayout.fFlags &
+ bool isBuffer = (0 != (intf.fVariable.modifiers().fFlags & Modifiers::kBuffer_Flag));
+ bool pushConstant = (0 != (intf.fVariable.modifiers().fLayout.fFlags &
Layout::kPushConstant_Flag));
MemoryLayout memoryLayout = (pushConstant || isBuffer) ?
MemoryLayout(MemoryLayout::k430_Standard) :
@@ -2710,7 +2711,8 @@
type = new Type(type->fOffset, type->name(), fields);
}
SpvId typeId;
- if (intf.fVariable.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
+ Modifiers intfModifiers = intf.fVariable.modifiers();
+ if (intfModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
for (const auto& e : fProgram) {
if (e.kind() == ProgramElement::Kind::kModifiers) {
const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers;
@@ -2724,17 +2726,17 @@
} else {
typeId = this->getType(*type, memoryLayout);
}
- if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) {
+ if (intfModifiers.fFlags & Modifiers::kBuffer_Flag) {
this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBufferBlock, fDecorationBuffer);
- } else if (intf.fVariable.fModifiers.fLayout.fBuiltin == -1) {
+ } else if (intfModifiers.fLayout.fBuiltin == -1) {
this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer);
}
- SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers);
+ SpvStorageClass_ storageClass = get_storage_class(intfModifiers);
SpvId ptrType = this->nextId();
this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer);
this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer);
- Layout layout = intf.fVariable.fModifiers.fLayout;
- if (intf.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && layout.fSet == -1) {
+ Layout layout = intfModifiers.fLayout;
+ if (intfModifiers.fFlags & Modifiers::kUniform_Flag && layout.fSet == -1) {
layout.fSet = 0;
}
this->writeLayout(layout, result);
@@ -2756,19 +2758,19 @@
}
bool is_dead(const Variable& var) {
- if (var.fReadCount || var.fWriteCount) {
+ if (var.readCount() || var.writeCount()) {
return false;
}
// not entirely sure what the rules are for when it's safe to elide interface variables, but it
// causes various problems to elide some of them even when dead. But it also causes problems
// *not* to elide sk_SampleMask when it's not being used.
- if (!(var.fModifiers.fFlags & (Modifiers::kIn_Flag |
- Modifiers::kOut_Flag |
- Modifiers::kUniform_Flag |
- Modifiers::kBuffer_Flag))) {
+ if (!(var.modifiers().fFlags & (Modifiers::kIn_Flag |
+ Modifiers::kOut_Flag |
+ Modifiers::kUniform_Flag |
+ Modifiers::kBuffer_Flag))) {
return true;
}
- return var.fModifiers.fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
+ return var.modifiers().fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
}
#define BUILTIN_IGNORE 9999
@@ -2777,15 +2779,15 @@
const Variable* var = varDecl.fVar;
// These haven't been implemented in our SPIR-V generator yet and we only currently use them
// in the OpenGL backend.
- SkASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag |
- Modifiers::kWriteOnly_Flag |
- Modifiers::kCoherent_Flag |
- Modifiers::kVolatile_Flag |
- Modifiers::kRestrict_Flag)));
- if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) {
+ SkASSERT(!(var->modifiers().fFlags & (Modifiers::kReadOnly_Flag |
+ Modifiers::kWriteOnly_Flag |
+ Modifiers::kCoherent_Flag |
+ Modifiers::kVolatile_Flag |
+ Modifiers::kRestrict_Flag)));
+ if (var->modifiers().fLayout.fBuiltin == BUILTIN_IGNORE) {
return;
}
- if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
+ if (var->modifiers().fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
kind != Program::kFragment_Kind) {
SkASSERT(!fProgram.fSettings.fFragColorIsInOut);
return;
@@ -2795,11 +2797,11 @@
}
const Type& type = var->type();
SpvStorageClass_ storageClass;
- if (var->fModifiers.fFlags & Modifiers::kIn_Flag) {
+ if (var->modifiers().fFlags & Modifiers::kIn_Flag) {
storageClass = SpvStorageClassInput;
- } else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) {
+ } else if (var->modifiers().fFlags & Modifiers::kOut_Flag) {
storageClass = SpvStorageClassOutput;
- } else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) {
+ } else if (var->modifiers().fFlags & Modifiers::kUniform_Flag) {
if (type.typeKind() == Type::TypeKind::kSampler ||
type.typeKind() == Type::TypeKind::kSeparateSampler ||
type.typeKind() == Type::TypeKind::kTexture) {
@@ -2813,7 +2815,7 @@
SpvId id = this->nextId();
fVariableMap[var] = id;
SpvId typeId;
- if (var->fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
+ if (var->modifiers().fLayout.fBuiltin == SK_IN_BUILTIN) {
typeId = this->getPointerType(
Type("sk_in", Type::TypeKind::kArray, type.componentType(), fSkInCount),
storageClass);
@@ -2830,11 +2832,11 @@
this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer);
fCurrentBlock = 0;
}
- this->writeLayout(var->fModifiers.fLayout, id);
- if (var->fModifiers.fFlags & Modifiers::kFlat_Flag) {
+ this->writeLayout(var->modifiers().fLayout, id);
+ if (var->modifiers().fFlags & Modifiers::kFlat_Flag) {
this->writeInstruction(SpvOpDecorate, id, SpvDecorationFlat, fDecorationBuffer);
}
- if (var->fModifiers.fFlags & Modifiers::kNoPerspective_Flag) {
+ if (var->modifiers().fFlags & Modifiers::kNoPerspective_Flag) {
this->writeInstruction(SpvOpDecorate, id, SpvDecorationNoPerspective,
fDecorationBuffer);
}
@@ -2844,11 +2846,11 @@
const Variable* var = varDecl.fVar;
// These haven't been implemented in our SPIR-V generator yet and we only currently use them
// in the OpenGL backend.
- SkASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag |
- Modifiers::kWriteOnly_Flag |
- Modifiers::kCoherent_Flag |
- Modifiers::kVolatile_Flag |
- Modifiers::kRestrict_Flag)));
+ SkASSERT(!(var->modifiers().fFlags & (Modifiers::kReadOnly_Flag |
+ Modifiers::kWriteOnly_Flag |
+ Modifiers::kCoherent_Flag |
+ Modifiers::kVolatile_Flag |
+ Modifiers::kRestrict_Flag)));
SpvId id = this->nextId();
fVariableMap[var] = id;
SpvId type = this->getPointerType(var->type(), SpvStorageClassFunction);
@@ -3192,14 +3194,15 @@
for (const auto& e : program) {
if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
InterfaceBlock& intf = (InterfaceBlock&) e;
- if (SK_IN_BUILTIN == intf.fVariable.fModifiers.fLayout.fBuiltin) {
+ const Modifiers& modifiers = intf.fVariable.modifiers();
+ if (SK_IN_BUILTIN == modifiers.fLayout.fBuiltin) {
SkASSERT(skInSize != -1);
intf.fSizes.emplace_back(new IntLiteral(fContext, -1, skInSize));
}
SpvId id = this->writeInterfaceBlock(intf);
- if (((intf.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) ||
- (intf.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) &&
- intf.fVariable.fModifiers.fLayout.fBuiltin == -1 &&
+ if (((modifiers.fFlags & Modifiers::kIn_Flag) ||
+ (modifiers.fFlags & Modifiers::kOut_Flag)) &&
+ modifiers.fLayout.fBuiltin == -1 &&
!is_dead(intf.fVariable)) {
interfaceVars.insert(id);
}
@@ -3227,9 +3230,9 @@
}
for (auto entry : fVariableMap) {
const Variable* var = entry.first;
- if (var->fStorage == Variable::kGlobal_Storage &&
- ((var->fModifiers.fFlags & Modifiers::kIn_Flag) ||
- (var->fModifiers.fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
+ if (var->storage() == Variable::kGlobal_Storage &&
+ ((var->modifiers().fFlags & Modifiers::kIn_Flag) ||
+ (var->modifiers().fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
interfaceVars.insert(entry.second);
}
}
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index 2bc8b32..21f9f4e 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -104,10 +104,11 @@
virtual void store(SpvId value, OutputStream& out) = 0;
};
- SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
- OutputStream* out)
+ SPIRVCodeGenerator(const Context* context, ModifiersPool* modifiers,
+ const Program* program, ErrorReporter* errors, OutputStream* out)
: INHERITED(program, errors, out)
, fContext(*context)
+ , fModifiers(*modifiers)
, fDefaultLayout(MemoryLayout::k140_Standard)
, fCapabilities(0)
, fIdCount(1)
@@ -366,6 +367,7 @@
void writeGeometryShaderExecutionMode(SpvId entryPoint, OutputStream& out);
const Context& fContext;
+ ModifiersPool& fModifiers;
const MemoryLayout fDefaultLayout;
uint64_t fCapabilities;
diff --git a/src/sksl/SkSLSectionAndParameterHelper.h b/src/sksl/SkSLSectionAndParameterHelper.h
index e35f27d..6dc7cf4 100644
--- a/src/sksl/SkSLSectionAndParameterHelper.h
+++ b/src/sksl/SkSLSectionAndParameterHelper.h
@@ -63,8 +63,8 @@
}
static bool IsParameter(const Variable& var) {
- return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
- -1 == var.fModifiers.fLayout.fBuiltin;
+ return (var.modifiers().fFlags & Modifiers::kIn_Flag) &&
+ -1 == var.modifiers().fLayout.fBuiltin;
}
static bool IsSupportedSection(const char* name) {
diff --git a/src/sksl/ir/SkSLEnum.h b/src/sksl/ir/SkSLEnum.h
index 6859f48..c5bbadd 100644
--- a/src/sksl/ir/SkSLEnum.h
+++ b/src/sksl/ir/SkSLEnum.h
@@ -55,7 +55,7 @@
std::sort(sortedSymbols.begin(), sortedSymbols.end(),
[](const Symbol* a, const Symbol* b) { return a->name() < b->name(); });
for (const auto& s : sortedSymbols) {
- const Expression& initialValue = *s->as<Variable>().fInitialValue;
+ const Expression& initialValue = *s->as<Variable>().initialValue();
result += separator + " " + s->name() + " = " +
to_string(initialValue.as<IntLiteral>().value());
separator = ",\n";
diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h
index 7646268..746f4ce 100644
--- a/src/sksl/ir/SkSLExpression.h
+++ b/src/sksl/ir/SkSLExpression.h
@@ -18,7 +18,7 @@
struct Expression;
class IRGenerator;
-struct Variable;
+class Variable;
using DefinitionMap = TinyUnorderedMap<const Variable*, std::unique_ptr<Expression>*>;
diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h
index f4bfbd0..ffbd3d1 100644
--- a/src/sksl/ir/SkSLFunctionDeclaration.h
+++ b/src/sksl/ir/SkSLFunctionDeclaration.h
@@ -28,7 +28,7 @@
static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration;
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
- std::vector<const Variable*> parameters, const Type& returnType,
+ std::vector<Variable*> parameters, const Type& returnType,
bool builtin)
: INHERITED(offset, kSymbolKind, std::move(name))
, fDefinition(nullptr)
@@ -118,7 +118,7 @@
mutable FunctionDefinition* fDefinition;
bool fBuiltin;
Modifiers fModifiers;
- const std::vector<const Variable*> fParameters;
+ const std::vector<Variable*> fParameters;
const Type& fReturnType;
mutable std::atomic<int> fCallCount = 0;
diff --git a/src/sksl/ir/SkSLIRNode.cpp b/src/sksl/ir/SkSLIRNode.cpp
index 3361ebb..7fbcd4e 100644
--- a/src/sksl/ir/SkSLIRNode.cpp
+++ b/src/sksl/ir/SkSLIRNode.cpp
@@ -83,15 +83,10 @@
, fKind(kind)
, fData(data) {}
-IRNode::IRNode(const IRNode& other)
- : fOffset(other.fOffset)
- , fKind(other.fKind)
- , fData(other.fData) {
- // For now, we can't use a default copy constructor because of the std::unique_ptr children.
- // Since we never copy nodes containing children, it's easiest just to assert we don't have any
- // than bother with cloning them.
- SkASSERT(other.fExpressionChildren.empty());
-}
+IRNode::IRNode(int offset, int kind, const VariableData& data)
+: fOffset(offset)
+, fKind(kind)
+, fData(data) {}
IRNode::~IRNode() {}
diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h
index 012d3dc..18c9b2f 100644
--- a/src/sksl/ir/SkSLIRNode.h
+++ b/src/sksl/ir/SkSLIRNode.h
@@ -10,6 +10,7 @@
#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/SkSLLexer.h"
+#include "src/sksl/SkSLModifiersPool.h"
#include "src/sksl/SkSLString.h"
#include <algorithm>
@@ -24,7 +25,7 @@
class Symbol;
class SymbolTable;
class Type;
-struct Variable;
+class Variable;
/**
* Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
@@ -72,6 +73,8 @@
return *this->typeData();
case NodeData::Kind::kTypeToken:
return *this->typeTokenData().fType;
+ case NodeData::Kind::kVariable:
+ return *this->variableData().fType;
default:
SkUNREACHABLE;
}
@@ -135,7 +138,7 @@
struct SymbolAliasData {
StringFragment fName;
- const Symbol* fOrigSymbol;
+ Symbol* fOrigSymbol;
};
struct TypeTokenData {
@@ -143,6 +146,21 @@
Token::Kind fToken;
};
+ struct VariableData {
+ StringFragment fName;
+ const Type* fType;
+ const Expression* fInitialValue = nullptr;
+ ModifiersPool::Handle fModifiersHandle;
+ // Tracks how many sites read from the variable. If this is zero for a non-out variable (or
+ // becomes zero during optimization), the variable is dead and may be eliminated.
+ mutable int16_t fReadCount;
+ // Tracks how many sites write to the variable. If this is zero, the variable is dead and
+ // may be eliminated.
+ mutable int16_t fWriteCount;
+ /*Variable::Storage*/int8_t fStorage;
+ bool fBuiltin;
+ };
+
struct NodeData {
enum class Kind {
kBlock,
@@ -159,6 +177,7 @@
kSymbolAlias,
kType,
kTypeToken,
+ kVariable,
} fKind = Kind::kType;
// it doesn't really matter what kind we default to, as long as it's a POD type
@@ -177,6 +196,7 @@
SymbolAliasData fSymbolAlias;
const Type* fType;
TypeTokenData fTypeToken;
+ VariableData fVariable;
Contents() {}
@@ -253,6 +273,11 @@
*(new(&fContents) TypeTokenData) = data;
}
+ NodeData(const VariableData& data)
+ : fKind(Kind::kVariable) {
+ *(new(&fContents) VariableData) = data;
+ }
+
NodeData(const NodeData& other) {
*this = other;
}
@@ -303,6 +328,9 @@
case Kind::kTypeToken:
*(new(&fContents) TypeTokenData) = other.fContents.fTypeToken;
break;
+ case Kind::kVariable:
+ *(new(&fContents) VariableData) = other.fContents.fVariable;
+ break;
}
return *this;
}
@@ -355,6 +383,9 @@
case Kind::kTypeToken:
fContents.fTypeToken.~TypeTokenData();
break;
+ case Kind::kVariable:
+ fContents.fVariable.~VariableData();
+ break;
}
}
};
@@ -388,7 +419,7 @@
IRNode(int offset, int kind, const TypeTokenData& data);
- IRNode(const IRNode& other);
+ IRNode(int offset, int kind, const VariableData& data);
Expression& expressionChild(int index) const {
SkASSERT(index >= 0 && index < (int) fExpressionChildren.size());
@@ -509,6 +540,16 @@
return fData.fContents.fTypeToken;
}
+ VariableData& variableData() {
+ SkASSERT(fData.fKind == NodeData::Kind::kVariable);
+ return fData.fContents.fVariable;
+ }
+
+ const VariableData& variableData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kVariable);
+ return fData.fContents.fVariable;
+ }
+
int fKind;
NodeData fData;
diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h
index 2bc2f79..cee0a22 100644
--- a/src/sksl/ir/SkSLInterfaceBlock.h
+++ b/src/sksl/ir/SkSLInterfaceBlock.h
@@ -49,7 +49,7 @@
}
String description() const override {
- String result = fVariable.fModifiers.description() + fTypeName + " {\n";
+ String result = fVariable.modifiers().description() + fTypeName + " {\n";
const Type* structType = &fVariable.type();
while (structType->typeKind() == Type::TypeKind::kArray) {
structType = &structType->componentType();
diff --git a/src/sksl/ir/SkSLModifiers.h b/src/sksl/ir/SkSLModifiers.h
index f830b0f..7030377 100644
--- a/src/sksl/ir/SkSLModifiers.h
+++ b/src/sksl/ir/SkSLModifiers.h
@@ -10,6 +10,8 @@
#include "src/sksl/ir/SkSLLayout.h"
+#include <vector>
+
namespace SkSL {
/**
@@ -116,6 +118,17 @@
int fFlags;
};
-} // namespace SkSL
+} // namespace SkSL
+
+namespace std {
+
+template <>
+struct hash<SkSL::Modifiers> {
+ size_t operator()(const SkSL::Modifiers& key) const {
+ return key.fFlags ^ (key.fLayout.fFlags << 8) ^ ((unsigned) key.fLayout.fBuiltin << 16);
+ }
+};
+
+} // namespace std
#endif
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index bf22189..0a5d667 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -250,6 +250,7 @@
std::shared_ptr<Context> context,
std::vector<std::unique_ptr<ProgramElement>>* inheritedElements,
std::vector<std::unique_ptr<ProgramElement>> elements,
+ std::unique_ptr<ModifiersPool> modifiers,
std::shared_ptr<SymbolTable> symbols,
Inputs inputs)
: fKind(kind)
@@ -259,7 +260,8 @@
, fSymbols(symbols)
, fInputs(inputs)
, fInheritedElements(inheritedElements)
- , fElements(std::move(elements)) {}
+ , fElements(std::move(elements))
+ , fModifiers(std::move(modifiers)) {}
iterator begin() {
if (fInheritedElements) {
@@ -293,6 +295,10 @@
return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
}
+ void finish() {
+ fModifiers->finish();
+ }
+
Kind fKind;
std::unique_ptr<String> fSource;
Settings fSettings;
@@ -305,6 +311,7 @@
private:
std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements;
std::vector<std::unique_ptr<ProgramElement>> fElements;
+ std::unique_ptr<ModifiersPool> fModifiers;
friend class Compiler;
};
diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h
index 3d18c1a..76e7c58 100644
--- a/src/sksl/ir/SkSLSymbol.h
+++ b/src/sksl/ir/SkSLSymbol.h
@@ -42,7 +42,9 @@
Symbol(int offset, const SymbolAliasData& data)
: INHERITED(offset, (int) Kind::kSymbolAlias, data) {}
- Symbol(const Symbol&) = default;
+ Symbol(int offset, const VariableData& data)
+ : INHERITED(offset, (int) Kind::kVariable, data) {}
+
Symbol& operator=(const Symbol&) = default;
~Symbol() override {}
diff --git a/src/sksl/ir/SkSLSymbolAlias.h b/src/sksl/ir/SkSLSymbolAlias.h
index 109824f..a84f25f 100644
--- a/src/sksl/ir/SkSLSymbolAlias.h
+++ b/src/sksl/ir/SkSLSymbolAlias.h
@@ -19,14 +19,14 @@
public:
static constexpr Kind kSymbolKind = Kind::kSymbolAlias;
- SymbolAlias(int offset, StringFragment name, const Symbol* origSymbol)
+ SymbolAlias(int offset, StringFragment name, Symbol* origSymbol)
: INHERITED(offset, SymbolAliasData{name, origSymbol}) {}
StringFragment name() const override {
return this->symbolAliasData().fName;
}
- const Symbol* origSymbol() const {
+ Symbol* origSymbol() const {
return this->symbolAliasData().fOrigSymbol;
}
diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp
index 26a7cb6..5e9b30e 100644
--- a/src/sksl/ir/SkSLSymbolTable.cpp
+++ b/src/sksl/ir/SkSLSymbolTable.cpp
@@ -23,8 +23,8 @@
}
}
-const Symbol* SymbolTable::operator[](StringFragment name) {
- const auto& entry = fSymbols.find(name);
+Symbol* SymbolTable::operator[](StringFragment name) {
+ auto entry = fSymbols.find(name);
if (entry == fSymbols.end()) {
if (fParent) {
return (*fParent)[name];
@@ -59,7 +59,7 @@
}
}
}
- const Symbol* symbol = entry->second;
+ Symbol* symbol = entry->second;
while (symbol && symbol->is<SymbolAlias>()) {
symbol = symbol->as<SymbolAlias>().origSymbol();
}
@@ -72,14 +72,14 @@
return result;
}
-void SymbolTable::addAlias(StringFragment name, const Symbol* symbol) {
+void SymbolTable::addAlias(StringFragment name, Symbol* symbol) {
this->add(name, std::make_unique<SymbolAlias>(symbol->fOffset, name, symbol));
}
-void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
+void SymbolTable::addWithoutOwnership(StringFragment name, Symbol* symbol) {
SkASSERT(symbol->name() == name);
- const Symbol*& refInSymbolTable = fSymbols[name];
+ Symbol*& refInSymbolTable = fSymbols[name];
if (refInSymbolTable == nullptr) {
refInSymbolTable = symbol;
return;
@@ -106,11 +106,11 @@
}
}
-std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
+std::unordered_map<StringFragment, Symbol*>::iterator SymbolTable::begin() {
return fSymbols.begin();
}
-std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
+std::unordered_map<StringFragment, Symbol*>::iterator SymbolTable::end() {
return fSymbols.end();
}
diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h
index b10341c..1c36de0 100644
--- a/src/sksl/ir/SkSLSymbolTable.h
+++ b/src/sksl/ir/SkSLSymbolTable.h
@@ -31,38 +31,38 @@
: fParent(parent)
, fErrorReporter(parent->fErrorReporter) {}
- const Symbol* operator[](StringFragment name);
+ Symbol* operator[](StringFragment name);
- void addAlias(StringFragment name, const Symbol* symbol);
- void addWithoutOwnership(StringFragment name, const Symbol* symbol);
+ void addAlias(StringFragment name, Symbol* symbol);
+ void addWithoutOwnership(StringFragment name, Symbol* symbol);
template <typename T>
const T* add(StringFragment name, std::unique_ptr<T> symbol) {
- const T* ptr = symbol.get();
+ T* ptr = symbol.get();
this->addWithoutOwnership(name, ptr);
this->takeOwnershipOfSymbol(std::move(symbol));
return ptr;
}
template <typename T>
- const T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
- const T* ptr = symbol.get();
+ T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
+ T* ptr = symbol.get();
fOwnedSymbols.push_back(std::move(symbol));
return ptr;
}
template <typename T>
- const T* takeOwnershipOfIRNode(std::unique_ptr<T> node) {
- const T* ptr = node.get();
+ T* takeOwnershipOfIRNode(std::unique_ptr<T> node) {
+ T* ptr = node.get();
fOwnedNodes.push_back(std::move(node));
return ptr;
}
const String* takeOwnershipOfString(std::unique_ptr<String> n);
- std::unordered_map<StringFragment, const Symbol*>::iterator begin();
+ std::unordered_map<StringFragment, Symbol*>::iterator begin();
- std::unordered_map<StringFragment, const Symbol*>::iterator end();
+ std::unordered_map<StringFragment, Symbol*>::iterator end();
std::shared_ptr<SymbolTable> fParent;
@@ -75,7 +75,7 @@
std::vector<std::unique_ptr<String>> fOwnedStrings;
- std::unordered_map<StringFragment, const Symbol*> fSymbols;
+ std::unordered_map<StringFragment, Symbol*> fSymbols;
ErrorReporter& fErrorReporter;
diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h
index 21883f5..5ddb4b6 100644
--- a/src/sksl/ir/SkSLVarDeclarations.h
+++ b/src/sksl/ir/SkSLVarDeclarations.h
@@ -47,8 +47,8 @@
}
String description() const override {
- String result =
- fVar->fModifiers.description() + fBaseType.description() + " " + fVar->name();
+ String result = fVar->modifiers().description() + fBaseType.description() + " " +
+ fVar->name();
for (const auto& size : fSizes) {
if (size) {
result += "[" + size->description() + "]";
diff --git a/src/sksl/ir/SkSLVariable.h b/src/sksl/ir/SkSLVariable.h
index e1a21c8..e5a39dd 100644
--- a/src/sksl/ir/SkSLVariable.h
+++ b/src/sksl/ir/SkSLVariable.h
@@ -12,6 +12,7 @@
#include "src/sksl/ir/SkSLModifiers.h"
#include "src/sksl/ir/SkSLSymbol.h"
#include "src/sksl/ir/SkSLType.h"
+#include "src/sksl/ir/SkSLVariableReference.h"
namespace SkSL {
@@ -22,7 +23,8 @@
* variable itself (the storage location), which is shared between all VariableReferences which
* read or write that storage location.
*/
-struct Variable : public Symbol {
+class Variable : public Symbol {
+public:
static constexpr Kind kSymbolKind = Kind::kVariable;
enum Storage {
@@ -32,53 +34,102 @@
kParameter_Storage
};
- Variable(int offset, Modifiers modifiers, StringFragment name, const Type* type,
+ Variable(int offset, ModifiersPool::Handle modifiers, StringFragment name, const Type* type,
bool builtin, Storage storage, Expression* initialValue = nullptr)
- : INHERITED(offset, kSymbolKind, name, type)
- , fModifiers(modifiers)
- , fStorage(storage)
- , fInitialValue(initialValue)
- , fBuiltin(builtin)
- , fReadCount(0)
- , fWriteCount(initialValue ? 1 : 0) {}
+ : INHERITED(offset, VariableData{name, type, initialValue, modifiers, /*readCount=*/0,
+ /*writeCount=*/(int16_t) (initialValue ? 1 : 0),
+ (int8_t) storage, builtin}) {}
~Variable() override {
// can't destroy a variable while there are remaining references to it
- if (fInitialValue) {
- --fWriteCount;
+ if (this->initialValue()) {
+ --this->variableData().fWriteCount;
}
- SkASSERT(!fReadCount && !fWriteCount);
+ SkASSERT(!this->variableData().fReadCount && !this->variableData().fWriteCount);
+ }
+
+ const Modifiers& modifiers() const {
+ return *this->variableData().fModifiersHandle;
+ }
+
+ const ModifiersPool::Handle& modifiersHandle() const {
+ return this->variableData().fModifiersHandle;
+ }
+
+ void setModifiersHandle(const ModifiersPool::Handle& handle) {
+ this->variableData().fModifiersHandle = handle;
+ }
+
+ bool isBuiltin() const {
+ return this->variableData().fBuiltin;
+ }
+
+ Storage storage() const {
+ return (Storage) this->variableData().fStorage;
+ }
+
+ const Expression* initialValue() const {
+ return this->variableData().fInitialValue;
+ }
+
+ void setInitialValue(const Expression* initialValue) {
+ SkASSERT(!this->initialValue());
+ SkASSERT(this->variableData().fWriteCount == 0);
+ this->variableData().fInitialValue = initialValue;
+ ++this->variableData().fWriteCount;
+ }
+
+ int readCount() const {
+ return this->variableData().fReadCount;
+ }
+
+ int writeCount() const {
+ return this->variableData().fWriteCount;
+ }
+
+ StringFragment name() const override {
+ return this->variableData().fName;
}
String description() const override {
- return fModifiers.description() + this->type().name() + " " + this->name();
+ return this->modifiers().description() + this->type().name() + " " + this->name();
}
bool dead() const {
- if ((fStorage != kLocal_Storage && fReadCount) ||
- (fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
+ const VariableData& data = this->variableData();
+ const Modifiers& modifiers = this->modifiers();
+ if ((data.fStorage != kLocal_Storage && this->variableData().fReadCount) ||
+ (modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
Modifiers::kUniform_Flag | Modifiers::kVarying_Flag))) {
return false;
}
- return !fWriteCount ||
- (!fReadCount && !(fModifiers.fFlags & (Modifiers::kPLS_Flag |
- Modifiers::kPLSOut_Flag)));
+ return !data.fWriteCount ||
+ (!data.fReadCount && !(modifiers.fFlags & (Modifiers::kPLS_Flag |
+ Modifiers::kPLSOut_Flag)));
}
- mutable Modifiers fModifiers;
- const Storage fStorage;
+private:
+ void referenceCreated(VariableReference::RefKind refKind) const {
+ if (refKind != VariableReference::kRead_RefKind) {
+ ++this->variableData().fWriteCount;
+ }
+ if (refKind != VariableReference::kWrite_RefKind) {
+ ++this->variableData().fReadCount;
+ }
+ }
- const Expression* fInitialValue = nullptr;
- bool fBuiltin;
-
- // Tracks how many sites read from the variable. If this is zero for a non-out variable (or
- // becomes zero during optimization), the variable is dead and may be eliminated.
- mutable int fReadCount;
- // Tracks how many sites write to the variable. If this is zero, the variable is dead and may be
- // eliminated.
- mutable int fWriteCount;
+ void referenceDestroyed(VariableReference::RefKind refKind) const {
+ if (refKind != VariableReference::kRead_RefKind) {
+ --this->variableData().fWriteCount;
+ }
+ if (refKind != VariableReference::kWrite_RefKind) {
+ --this->variableData().fReadCount;
+ }
+ }
using INHERITED = Symbol;
+
+ friend struct VariableReference;
};
} // namespace SkSL
diff --git a/src/sksl/ir/SkSLVariableReference.cpp b/src/sksl/ir/SkSLVariableReference.cpp
index 1387287..376036a 100644
--- a/src/sksl/ir/SkSLVariableReference.cpp
+++ b/src/sksl/ir/SkSLVariableReference.cpp
@@ -19,41 +19,41 @@
, fVariable(variable)
, fRefKind(refKind) {
SkASSERT(fVariable);
- this->incrementRefs();
+ fVariable->referenceCreated(fRefKind);
}
VariableReference::~VariableReference() {
- this->decrementRefs();
+ fVariable->referenceDestroyed(fRefKind);
}
-void VariableReference::incrementRefs() const {
- if (fRefKind != kRead_RefKind) {
- fVariable->fWriteCount++;
- }
- if (fRefKind != kWrite_RefKind) {
- fVariable->fReadCount++;
+bool VariableReference::hasProperty(Property property) const {
+ switch (property) {
+ case Property::kSideEffects: return false;
+ case Property::kContainsRTAdjust: return fVariable->name() == "sk_RTAdjust";
+ default:
+ SkASSERT(false);
+ return false;
}
}
-void VariableReference::decrementRefs() const {
- if (fRefKind != kRead_RefKind) {
- fVariable->fWriteCount--;
- }
- if (fRefKind != kWrite_RefKind) {
- fVariable->fReadCount--;
- }
+bool VariableReference::isConstantOrUniform() const {
+ return (fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) != 0;
+}
+
+String VariableReference::description() const {
+ return fVariable->name();
}
void VariableReference::setRefKind(RefKind refKind) {
- this->decrementRefs();
+ fVariable->referenceDestroyed(fRefKind);
fRefKind = refKind;
- this->incrementRefs();
+ fVariable->referenceCreated(fRefKind);
}
void VariableReference::setVariable(const Variable* variable) {
- this->decrementRefs();
+ fVariable->referenceDestroyed(fRefKind);
fVariable = variable;
- this->incrementRefs();
+ fVariable->referenceCreated(fRefKind);
}
std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
@@ -61,10 +61,11 @@
if (fRefKind != kRead_RefKind) {
return nullptr;
}
- if ((fVariable->fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable->fInitialValue &&
- fVariable->fInitialValue->isCompileTimeConstant() &&
+ const Expression* initialValue = fVariable->initialValue();
+ if ((fVariable->modifiers().fFlags & Modifiers::kConst_Flag) && initialValue &&
+ initialValue->isCompileTimeConstant() &&
this->type().typeKind() != Type::TypeKind::kArray) {
- return fVariable->fInitialValue->clone();
+ return initialValue->clone();
}
auto exprIter = definitions.find(fVariable);
if (exprIter != definitions.end() && exprIter->second &&
diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h
index 6f38b9c..7b98ed5 100644
--- a/src/sksl/ir/SkSLVariableReference.h
+++ b/src/sksl/ir/SkSLVariableReference.h
@@ -9,11 +9,11 @@
#define SKSL_VARIABLEREFERENCE
#include "src/sksl/ir/SkSLExpression.h"
-#include "src/sksl/ir/SkSLVariable.h"
namespace SkSL {
class IRGenerator;
+class Variable;
/**
* A reference to a variable, through which it can be read or written. In the statement:
@@ -48,27 +48,15 @@
void setRefKind(RefKind refKind);
void setVariable(const Variable* variable);
- bool hasProperty(Property property) const override {
- switch (property) {
- case Property::kSideEffects: return false;
- case Property::kContainsRTAdjust: return fVariable->name() == "sk_RTAdjust";
- default:
- SkASSERT(false);
- return false;
- }
- }
+ bool hasProperty(Property property) const override;
- bool isConstantOrUniform() const override {
- return (fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) != 0;
- }
+ bool isConstantOrUniform() const override;
std::unique_ptr<Expression> clone() const override {
return std::unique_ptr<Expression>(new VariableReference(fOffset, fVariable, fRefKind));
}
- String description() const override {
- return fVariable->name();
- }
+ String description() const override;
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
const DefinitionMap& definitions) override;
@@ -77,9 +65,6 @@
RefKind fRefKind;
private:
- void incrementRefs() const;
- void decrementRefs() const;
-
using INHERITED = Expression;
};