From c51f33e784d30098d016fe1c548a770f3607728d Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Tue, 13 Oct 2020 13:49:44 -0400 Subject: [PATCH] moved SkSL VarDeclarations data into IRNode Change-Id: I03bdef43c79bc3c997f9a9a6aa8fbb1a7194943a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326437 Reviewed-by: Brian Osman Commit-Queue: Ethan Nicholas --- src/core/SkRuntimeEffect.cpp | 5 +- src/sksl/SkSLAnalysis.cpp | 8 +- src/sksl/SkSLByteCodeGenerator.cpp | 36 ++++---- src/sksl/SkSLCFGGenerator.cpp | 4 +- src/sksl/SkSLCPPCodeGenerator.cpp | 86 +++++++++--------- src/sksl/SkSLCompiler.cpp | 29 ++++--- src/sksl/SkSLDehydrator.cpp | 14 +-- src/sksl/SkSLGLSLCodeGenerator.cpp | 29 ++++--- src/sksl/SkSLIRGenerator.cpp | 23 ++--- src/sksl/SkSLInliner.cpp | 24 +++--- src/sksl/SkSLMetalCodeGenerator.cpp | 55 ++++++------ src/sksl/SkSLPipelineStageCodeGenerator.cpp | 13 +-- src/sksl/SkSLSPIRVCodeGenerator.cpp | 60 ++++++------- src/sksl/SkSLSectionAndParameterHelper.cpp | 7 +- src/sksl/ir/SkSLIRNode.cpp | 5 ++ src/sksl/ir/SkSLIRNode.h | 30 +++++++ src/sksl/ir/SkSLModifiersDeclaration.h | 4 +- src/sksl/ir/SkSLStatement.h | 3 + src/sksl/ir/SkSLVarDeclarations.h | 96 ++++++++++++++------- 19 files changed, 313 insertions(+), 218 deletions(-) diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp index 33fcb43ce9..68910d62a6 100644 --- a/src/core/SkRuntimeEffect.cpp +++ b/src/core/SkRuntimeEffect.cpp @@ -154,9 +154,10 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) { for (const auto& elem : program->elements()) { // Variables (uniform, varying, etc.) if (elem->is()) { - const auto& varDecl = elem->as().fDecl; + const SkSL::GlobalVarDeclaration& global = elem->as(); + const SkSL::VarDeclaration& varDecl = global.declaration()->as(); - const SkSL::Variable& var = *varDecl->fVar; + const SkSL::Variable& var = varDecl.var(); const SkSL::Type& varType = var.type(); // Varyings (only used in conjunction with drawVertices) diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp index ba59e66fea..a462fb3f50 100644 --- a/src/sksl/SkSLAnalysis.cpp +++ b/src/sksl/SkSLAnalysis.cpp @@ -479,12 +479,12 @@ bool TProgramVisitor::visitStatement(STMT s) { } case Statement::Kind::kVarDeclaration: { auto& v = s.template as(); - for (auto& sizeExpr : v.fSizes) { - if (sizeExpr && this->visitExpression(*sizeExpr)) { + for (int i = 0; i < v.sizeCount(); ++i) { + if (v.size(i) && this->visitExpression(*v.size(i))) { return true; } } - return v.fValue && this->visitExpression(*v.fValue); + return v.value() && this->visitExpression(*v.value()); } case Statement::Kind::kWhile: { auto& w = s.template as(); @@ -517,7 +517,7 @@ bool TProgramVisitor::visitProgramElement(ELEM pe) { return false; case ProgramElement::Kind::kGlobalVar: - if (this->visitStatement(*pe.template as().fDecl)) { + if (this->visitStatement(*pe.template as().declaration())) { return true; } return false; diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp index 4b25fa30c1..a3927e5900 100644 --- a/src/sksl/SkSLByteCodeGenerator.cpp +++ b/src/sksl/SkSLByteCodeGenerator.cpp @@ -161,17 +161,17 @@ bool ByteCodeGenerator::generateCode() { } case ProgramElement::Kind::kGlobalVar: { const GlobalVarDeclaration& decl = e->as(); - const Variable* declVar = decl.fDecl->fVar; - if (declVar->type() == *fContext.fFragmentProcessor_Type) { + const Variable& declVar = decl.declaration()->as().var(); + if (declVar.type() == *fContext.fFragmentProcessor_Type) { fOutput->fChildFPCount++; } - if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) { + if (declVar.modifiers().fLayout.fBuiltin >= 0 || is_in(declVar)) { continue; } - if (is_uniform(*declVar)) { - this->gatherUniforms(declVar->type(), declVar->name()); + if (is_uniform(declVar)) { + this->gatherUniforms(declVar.type(), declVar.name()); } else { - fOutput->fGlobalSlotCount += SlotCount(declVar->type()); + fOutput->fGlobalSlotCount += SlotCount(declVar.type()); } break; } @@ -457,11 +457,11 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decl = e->as(); - const Variable* declVar = decl.fDecl->fVar; - if (declVar->type() != *fContext.fFragmentProcessor_Type) { + const Variable& declVar = decl.declaration()->as().var(); + if (declVar.type() != *fContext.fFragmentProcessor_Type) { continue; } - if (declVar == &var) { + if (&declVar == &var) { SkASSERT(offset <= 255); return { offset, Storage::kChildFP }; } @@ -485,18 +485,18 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decl = e->as(); - const Variable* declVar = decl.fDecl->fVar; - if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) { + const Variable& declVar = decl.declaration()->as().var(); + if (declVar.modifiers().fLayout.fBuiltin >= 0 || is_in(declVar)) { continue; } - if (isUniform != is_uniform(*declVar)) { + if (isUniform != is_uniform(declVar)) { continue; } - if (declVar == &var) { + if (&declVar == &var) { SkASSERT(offset <= 255); return { offset, isUniform ? Storage::kUniform : Storage::kGlobal }; } - offset += SlotCount(declVar->type()); + offset += SlotCount(declVar.type()); } } SkASSERT(false); @@ -1762,10 +1762,10 @@ void ByteCodeGenerator::writeSwitchStatement(const SwitchStatement& r) { void ByteCodeGenerator::writeVarDeclaration(const VarDeclaration& decl) { // we need to grab the location even if we don't use it, to ensure it has been allocated - Location location = this->getLocation(*decl.fVar); - if (decl.fValue) { - this->writeExpression(*decl.fValue); - int count = SlotCount(decl.fValue->type()); + Location location = this->getLocation(decl.var()); + if (decl.value()) { + this->writeExpression(*decl.value()); + int count = SlotCount(decl.value()->type()); this->write(ByteCodeInstruction::kStore, count); this->write8(location.fSlot); } diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp index 3166687b81..79c128a462 100644 --- a/src/sksl/SkSLCFGGenerator.cpp +++ b/src/sksl/SkSLCFGGenerator.cpp @@ -513,8 +513,8 @@ void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr* s) { } case Statement::Kind::kVarDeclaration: { VarDeclaration& vd = (*s)->as(); - if (vd.fValue) { - this->addExpression(cfg, &vd.fValue, /*constantPropagate=*/true); + if (vd.value()) { + this->addExpression(cfg, &vd.value(), /*constantPropagate=*/true); } cfg.currentBlock().fNodes.push_back(BasicBlock::MakeStatement(s)); break; diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 7001518e51..4537608d08 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -415,10 +415,11 @@ int CPPCodeGenerator::getChildFPIndex(const Variable& var) const { int index = 0; for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - if (decl.fVar == &var) { + const VarDeclaration& decl = + p->as().declaration()->as(); + if (&decl.var() == &var) { return index; - } else if (decl.fVar->type().nonnullable() == *fContext.fFragmentProcessor_Type) { + } else if (decl.var().type().nonnullable() == *fContext.fFragmentProcessor_Type) { ++index; } } @@ -660,7 +661,7 @@ void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) { return; case ProgramElement::Kind::kGlobalVar: { const GlobalVarDeclaration& decl = p.as(); - const Variable& var = *decl.fDecl->fVar; + const Variable& var = decl.declaration()->as().var(); if (var.modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) || -1 != var.modifiers().fLayout.fBuiltin) { return; @@ -706,27 +707,27 @@ void CPPCodeGenerator::writeInputVars() { void CPPCodeGenerator::writePrivateVars() { for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - if (is_private(*decl.fVar)) { - if (decl.fVar->type() == *fContext.fFragmentProcessor_Type) { - fErrors.error(decl.fOffset, + const GlobalVarDeclaration& global = p->as(); + const Variable& var = global.declaration()->as().var(); + if (is_private(var)) { + if (var.type() == *fContext.fFragmentProcessor_Type) { + fErrors.error(global.fOffset, "fragmentProcessor variables must be declared 'in'"); return; } this->writef("%s %s = %s;\n", - HCodeGenerator::FieldType(fContext, decl.fVar->type(), - decl.fVar->modifiers().fLayout) - .c_str(), - String(decl.fVar->name()).c_str(), - default_value(*decl.fVar).c_str()); - } else if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) { + HCodeGenerator::FieldType(fContext, var.type(), + var.modifiers().fLayout).c_str(), + String(var.name()).c_str(), + default_value(var).c_str()); + } else if (var.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. - const UniformCTypeMapper* mapper = UniformCTypeMapper::Get(fContext, *decl.fVar); + const UniformCTypeMapper* mapper = UniformCTypeMapper::Get(fContext, var); SkASSERT(mapper && mapper->supportsTracking()); - String name = HCodeGenerator::FieldName(String(decl.fVar->name()).c_str()); + String name = HCodeGenerator::FieldName(String(var.name()).c_str()); // The member statement is different if the mapper reports a default value if (mapper->defaultValue().size() > 0) { this->writef("%s %sPrev = %s;\n", @@ -744,11 +745,12 @@ void CPPCodeGenerator::writePrivateVars() { void CPPCodeGenerator::writePrivateVarValues() { for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - if (is_private(*decl.fVar) && decl.fValue) { - this->writef("%s = ", String(decl.fVar->name()).c_str()); + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + if (is_private(decl.var()) && decl.value()) { + this->writef("%s = ", String(decl.var().name()).c_str()); fCPPMode = true; - this->writeExpression(*decl.fValue, kAssignment_Precedence); + this->writeExpression(*decl.value(), kAssignment_Precedence); fCPPMode = false; this->write(";\n"); } @@ -958,11 +960,12 @@ bool CPPCodeGenerator::writeEmitCode(std::vector& uniforms) { fFullName.c_str(), fFullName.c_str()); for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - String nameString(decl.fVar->name()); + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + String nameString(decl.var().name()); const char* name = nameString.c_str(); - if (SectionAndParameterHelper::IsParameter(*decl.fVar) && - is_accessible(*decl.fVar)) { + if (SectionAndParameterHelper::IsParameter(decl.var()) && + is_accessible(decl.var())) { this->writef(" auto %s = _outer.%s;\n" " (void) %s;\n", name, name, name); @@ -1071,8 +1074,9 @@ void CPPCodeGenerator::writeSetData(std::vector& uniforms) { int samplerIndex = 0; for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - const Variable& variable = *decl.fVar; + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + const Variable& variable = decl.var(); String nameString(variable.name()); const char* name = nameString.c_str(); if (variable.type().typeKind() == Type::TypeKind::kSampler) { @@ -1244,8 +1248,9 @@ void CPPCodeGenerator::writeGetKey() { fFullName.c_str()); for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - const Variable& var = *decl.fVar; + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + const Variable& var = decl.var(); const Type& varType = var.type(); String nameString(var.name()); const char* name = nameString.c_str(); @@ -1260,9 +1265,9 @@ void CPPCodeGenerator::writeGetKey() { HCodeGenerator::FieldType(fContext, varType, var.modifiers().fLayout).c_str(), String(var.name()).c_str()); - if (decl.fValue) { + if (decl.value()) { fCPPMode = true; - this->writeExpression(*decl.fValue, kAssignment_Precedence); + this->writeExpression(*decl.value(), kAssignment_Precedence); fCPPMode = false; } else { this->writef("%s", default_value(var).c_str()); @@ -1318,25 +1323,26 @@ bool CPPCodeGenerator::generateCode() { std::vector uniforms; for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - if ((decl.fVar->modifiers().fFlags & Modifiers::kUniform_Flag) && - decl.fVar->type().typeKind() != Type::TypeKind::kSampler) { - uniforms.push_back(decl.fVar); + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + if ((decl.var().modifiers().fFlags & Modifiers::kUniform_Flag) && + decl.var().type().typeKind() != Type::TypeKind::kSampler) { + uniforms.push_back(&decl.var()); } - if (is_uniform_in(*decl.fVar)) { + if (is_uniform_in(decl.var())) { // Validate the "uniform in" declarations to make sure they are fully supported, // instead of generating surprising C++ const UniformCTypeMapper* mapper = - UniformCTypeMapper::Get(fContext, *decl.fVar); + UniformCTypeMapper::Get(fContext, decl.var()); if (mapper == nullptr) { - fErrors.error(decl.fOffset, String(decl.fVar->name()) + fErrors.error(decl.fOffset, String(decl.var().name()) + "'s type is not supported for use as a 'uniform in'"); return false; } - if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) { + if (decl.var().modifiers().fLayout.fFlags & Layout::kTracked_Flag) { if (!mapper->supportsTracking()) { - fErrors.error(decl.fOffset, String(decl.fVar->name()) + fErrors.error(decl.fOffset, String(decl.var().name()) + "'s type does not support state tracking"); return false; } @@ -1344,7 +1350,7 @@ bool CPPCodeGenerator::generateCode() { } else { // If it's not a uniform_in, it's an error to be tracked - if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) { + if (decl.var().modifiers().fLayout.fFlags & Layout::kTracked_Flag) { fErrors.error(decl.fOffset, "Non-'in uniforms' cannot be tracked"); return false; } diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 1bde5dc06f..ee2993784f 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -371,9 +371,10 @@ ParsedModule Compiler::parseModule(Program::Kind kind, ModuleData data, const Pa break; } case ProgramElement::Kind::kGlobalVar: { - const Variable* var = element->as().fDecl->fVar; - SkASSERT(var->isBuiltin()); - intrinsics->insertOrDie(var->name(), std::move(element)); + const GlobalVarDeclaration& global = element->as(); + const Variable& var = global.declaration()->as().var(); + SkASSERT(var.isBuiltin()); + intrinsics->insertOrDie(var.name(), std::move(element)); break; } case ProgramElement::Kind::kInterfaceBlock: { @@ -515,8 +516,8 @@ void Compiler::addDefinitions(const BasicBlock::Node& node, DefinitionMap* defin Statement* stmt = node.statement()->get(); if (stmt->is()) { VarDeclaration& vd = stmt->as(); - if (vd.fValue) { - definitions->set(vd.fVar, &vd.fValue); + if (vd.value()) { + definitions->set(&vd.var(), &vd.value()); } } } @@ -570,7 +571,7 @@ static DefinitionMap compute_start_state(const CFG& cfg) { if (node.isStatement()) { const Statement* s = node.statement()->get(); if (s->is()) { - result[s->as().fVar] = nullptr; + result[&s->as().var()] = nullptr; } } } @@ -1284,12 +1285,12 @@ void Compiler::simplifyStatement(DefinitionMap& definitions, switch (stmt->kind()) { case Statement::Kind::kVarDeclaration: { const auto& varDecl = stmt->as(); - if (varDecl.fVar->dead() && - (!varDecl.fValue || - !varDecl.fValue->hasSideEffects())) { - if (varDecl.fValue) { + if (varDecl.var().dead() && + (!varDecl.value() || + !varDecl.value()->hasSideEffects())) { + if (varDecl.value()) { SkASSERT((*iter)->statement()->get() == stmt); - if (!b.tryRemoveExpressionBefore(iter, varDecl.fValue.get())) { + if (!b.tryRemoveExpressionBefore(iter, varDecl.value().get())) { *outNeedsRescan = true; } } @@ -1616,8 +1617,10 @@ bool Compiler::optimize(Program& program) { if (!element->is()) { return false; } - const auto& varDecl = element->as(); - bool dead = varDecl.fDecl->fVar->dead(); + const auto& global = element->as(); + const auto& varDecl = + global.declaration()->as(); + bool dead = varDecl.var().dead(); madeChanges |= dead; return dead; }), diff --git a/src/sksl/SkSLDehydrator.cpp b/src/sksl/SkSLDehydrator.cpp index 1492412966..6bbcfd4e50 100644 --- a/src/sksl/SkSLDehydrator.cpp +++ b/src/sksl/SkSLDehydrator.cpp @@ -485,13 +485,13 @@ void Dehydrator::write(const Statement* s) { case Statement::Kind::kVarDeclaration: { const VarDeclaration& v = s->as(); this->writeCommand(Rehydrator::kVarDeclaration_Command); - this->writeU16(this->symbolId(v.fVar)); - this->write(v.fBaseType); - this->writeU8(v.fSizes.size()); - for (const std::unique_ptr& sizeExpr : v.fSizes) { - this->write(sizeExpr.get()); + this->writeU16(this->symbolId(&v.var())); + this->write(v.baseType()); + this->writeU8(v.sizeCount()); + for (int i = 0; i < v.sizeCount(); ++i) { + this->write(v.size(i).get()); } - this->write(v.fValue.get()); + this->write(v.value().get()); break; } case Statement::Kind::kWhile: { @@ -562,7 +562,7 @@ void Dehydrator::write(const ProgramElement& e) { case ProgramElement::Kind::kGlobalVar: { const GlobalVarDeclaration& v = e.as(); this->writeCommand(Rehydrator::kVarDeclarations_Command); - this->write(v.fDecl.get()); + this->write(v.declaration().get()); break; } } diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 94fd0b8972..1d53ad4aa9 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -1246,23 +1246,23 @@ void GLSLCodeGenerator::writeTypePrecision(const Type& type) { } void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) { - this->writeModifiers(var.fVar->modifiers(), global); - this->writeTypePrecision(var.fBaseType); - this->writeType(var.fBaseType); + this->writeModifiers(var.var().modifiers(), global); + this->writeTypePrecision(var.baseType()); + this->writeType(var.baseType()); this->write(" "); - this->write(var.fVar->name()); - for (const auto& size : var.fSizes) { + this->write(var.var().name()); + for (int i = 0; i < var.sizeCount(); ++i) { this->write("["); - if (size) { - this->writeExpression(*size, kTopLevel_Precedence); + if (var.size(i)) { + this->writeExpression(*var.size(i), kTopLevel_Precedence); } this->write("]"); } - if (var.fValue) { + if (var.value()) { this->write(" = "); - this->writeVarInitializer(*var.fVar, *var.fValue); + this->writeVarInitializer(var.var(), *var.value()); } - if (!fFoundExternalSamplerDecl && var.fVar->type() == *fContext.fSamplerExternalOES_Type) { + if (!fFoundExternalSamplerDecl && var.var().type() == *fContext.fSamplerExternalOES_Type) { if (fProgram.fSettings.fCaps->externalTextureExtensionString()) { this->writeExtension(fProgram.fSettings.fCaps->externalTextureExtensionString()); } @@ -1271,7 +1271,7 @@ void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool glob } fFoundExternalSamplerDecl = true; } - if (!fFoundRectSamplerDecl && var.fVar->type() == *fContext.fSampler2DRect_Type) { + if (!fFoundRectSamplerDecl && var.var().type() == *fContext.fSampler2DRect_Type) { fFoundRectSamplerDecl = true; } this->write(";"); @@ -1487,15 +1487,16 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { this->writeExtension(e.as().name()); break; case ProgramElement::Kind::kGlobalVar: { - const VarDeclaration& decl = *e.as().fDecl; - int builtin = decl.fVar->modifiers().fLayout.fBuiltin; + const VarDeclaration& decl = + e.as().declaration()->as(); + int builtin = decl.var().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->writeCount()) { + decl.var().writeCount()) { if (fProgram.fSettings.fFragColorIsInOut) { this->write("inout "); } else { diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index d4d093745c..a1b784f244 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -1099,19 +1099,19 @@ std::unique_ptr IRGenerator::convertInterfaceBlock(const ASTNode "only the last entry in an interface block may be a runtime-sized " "array"); } - if (vd.fVar == fRTAdjust) { + if (&vd.var() == fRTAdjust) { foundRTAdjust = true; - SkASSERT(vd.fVar->type() == *fContext.fFloat4_Type); + SkASSERT(vd.var().type() == *fContext.fFloat4_Type); fRTAdjustFieldIndex = fields.size(); } - fields.push_back(Type::Field(vd.fVar->modifiers(), vd.fVar->name(), - &vd.fVar->type())); - if (vd.fValue) { + fields.push_back(Type::Field(vd.var().modifiers(), vd.var().name(), + &vd.var().type())); + if (vd.value()) { fErrors.error(decl->fOffset, "initializers are not permitted on interface block fields"); } - if (vd.fVar->type().typeKind() == Type::TypeKind::kArray && - vd.fVar->type().columns() == Type::kUnsizedArray) { + if (vd.var().type().typeKind() == Type::TypeKind::kArray && + vd.var().type().columns() == Type::kUnsizedArray) { haveRuntimeArray = true; } } @@ -2829,8 +2829,10 @@ void IRGenerator::cloneBuiltinVariables() { const Expression* initialValue = nullptr; if (clonedDecl->is()) { - sharedVar = clonedDecl->as().fDecl->fVar; - initialValue = clonedDecl->as().fDecl->fValue.get(); + GlobalVarDeclaration& global = clonedDecl->as(); + VarDeclaration& decl = global.declaration()->as(); + sharedVar = &decl.var(); + initialValue = decl.value().get(); } else { SkASSERT(clonedDecl->is()); sharedVar = clonedDecl->as().fVariable; @@ -2847,7 +2849,8 @@ void IRGenerator::cloneBuiltinVariables() { // Go back and update the declaring element to point at the cloned Variable. if (clonedDecl->is()) { - clonedDecl->as().fDecl->fVar = clonedVar; + GlobalVarDeclaration& global = clonedDecl->as(); + global.declaration()->as().setVar(clonedVar); } else { clonedDecl->as().fVariable = clonedVar; } diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp index 2f757d2b82..c80374d86c 100644 --- a/src/sksl/SkSLInliner.cpp +++ b/src/sksl/SkSLInliner.cpp @@ -543,29 +543,29 @@ std::unique_ptr Inliner::inlineStatement(int offset, case Statement::Kind::kVarDeclaration: { const VarDeclaration& decl = statement.as(); ExpressionArray sizes; - sizes.reserve(decl.fSizes.size()); - for (const auto& size : decl.fSizes) { - sizes.push_back(expr(size)); + sizes.reserve(decl.sizeCount()); + for (int i = 0; i < decl.sizeCount(); ++i) { + sizes.push_back(expr(decl.size(i))); } - std::unique_ptr initialValue = expr(decl.fValue); - const Variable* old = decl.fVar; + std::unique_ptr initialValue = expr(decl.value()); + const Variable& old = decl.var(); // We assign unique names to inlined variables--scopes hide most of the problems in this // regard, but see `InlinerAvoidsVariableNameOverlap` for a counterexample where unique // names are important. auto name = std::make_unique( - this->uniqueNameForInlineVar(String(old->name()), symbolTableForStatement)); + this->uniqueNameForInlineVar(String(old.name()), symbolTableForStatement)); const String* namePtr = symbolTableForStatement->takeOwnershipOfString(std::move(name)); - const Type* baseTypePtr = copy_if_needed(&decl.fBaseType, *symbolTableForStatement); - const Type* typePtr = copy_if_needed(&old->type(), *symbolTableForStatement); + const Type* baseTypePtr = copy_if_needed(&decl.baseType(), *symbolTableForStatement); + const Type* typePtr = copy_if_needed(&old.type(), *symbolTableForStatement); const Variable* clone = symbolTableForStatement->takeOwnershipOfSymbol( std::make_unique(offset, - old->modifiersHandle(), + old.modifiersHandle(), namePtr->c_str(), typePtr, isBuiltinCode, - old->storage(), + old.storage(), initialValue.get())); - (*varMap)[old] = std::make_unique(offset, clone); + (*varMap)[&old] = std::make_unique(offset, clone); return std::make_unique(clone, baseTypePtr, std::move(sizes), std::move(initialValue)); } @@ -941,7 +941,7 @@ public: case Statement::Kind::kVarDeclaration: { VarDeclaration& varDeclStmt = (*stmt)->as(); // Don't need to scan the declaration's sizes; those are always IntLiterals. - this->visitExpression(&varDeclStmt.fValue); + this->visitExpression(&varDeclStmt.value()); break; } case Statement::Kind::kWhile: { diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp index e1df944cc7..710bf60d6a 100644 --- a/src/sksl/SkSLMetalCodeGenerator.cpp +++ b/src/sksl/SkSLMetalCodeGenerator.cpp @@ -956,28 +956,28 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decls = e->as(); - const VarDeclaration& var = *decls.fDecl; - if (var.fVar->type().typeKind() == Type::TypeKind::kSampler) { - if (var.fVar->modifiers().fLayout.fBinding < 0) { + const VarDeclaration& var = decls.declaration()->as(); + if (var.var().type().typeKind() == Type::TypeKind::kSampler) { + if (var.var().modifiers().fLayout.fBinding < 0) { fErrors.error(decls.fOffset, "Metal samplers must have 'layout(binding=...)'"); return; } - if (var.fVar->type().dimensions() != SpvDim2D) { + if (var.var().type().dimensions() != SpvDim2D) { // TODO: Support other texture types (skbug.com/10797) fErrors.error(decls.fOffset, "Unsupported texture dimensions"); return; } this->write(", texture2d "); - this->writeName(var.fVar->name()); + this->writeName(var.var().name()); this->write("[[texture("); - this->write(to_string(var.fVar->modifiers().fLayout.fBinding)); + this->write(to_string(var.var().modifiers().fLayout.fBinding)); this->write(")]]"); this->write(", sampler "); - this->writeName(var.fVar->name()); + this->writeName(var.var().name()); this->write(SAMPLER_SUFFIX); this->write("[[sampler("); - this->write(to_string(var.fVar->modifiers().fLayout.fBinding)); + this->write(to_string(var.var().modifiers().fLayout.fBinding)); this->write(")]]"); } } else if (e->is()) { @@ -1218,23 +1218,23 @@ void MetalCodeGenerator::writeName(const String& name) { } void MetalCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) { - if (global && !(var.fVar->modifiers().fFlags & Modifiers::kConst_Flag)) { + if (global && !(var.var().modifiers().fFlags & Modifiers::kConst_Flag)) { return; } - this->writeModifiers(var.fVar->modifiers(), global); - this->writeType(var.fBaseType); + this->writeModifiers(var.var().modifiers(), global); + this->writeType(var.baseType()); this->write(" "); - this->writeName(var.fVar->name()); - for (const auto& size : var.fSizes) { + this->writeName(var.var().name()); + for (int i = 0; i < var.sizeCount(); ++i) { this->write("["); - if (size) { - this->writeExpression(*size, kTopLevel_Precedence); + if (var.size(i)) { + this->writeExpression(*var.size(i), kTopLevel_Precedence); } this->write("]"); } - if (var.fValue) { + if (var.value()) { this->write(" = "); - this->writeVarInitializer(*var.fVar, *var.fValue); + this->writeVarInitializer(var.var(), *var.value()); } this->write(";"); } @@ -1395,7 +1395,7 @@ void MetalCodeGenerator::writeUniformStruct() { for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decls = e->as(); - const Variable& var = *decls.fDecl->fVar; + const Variable& var = decls.declaration()->as().var(); if (var.modifiers().fFlags & Modifiers::kUniform_Flag && var.type().typeKind() != Type::TypeKind::kSampler) { if (-1 == fUniformBuffer) { @@ -1428,7 +1428,7 @@ void MetalCodeGenerator::writeInputStruct() { for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decls = e->as(); - const Variable& var = *decls.fDecl->fVar; + const Variable& var = decls.declaration()->as().var(); if (var.modifiers().fFlags & Modifiers::kIn_Flag && -1 == var.modifiers().fLayout.fBuiltin) { this->write(" "); @@ -1461,7 +1461,7 @@ void MetalCodeGenerator::writeOutputStruct() { for (const auto& e : fProgram.elements()) { if (e->is()) { const GlobalVarDeclaration& decls = e->as(); - const Variable& var = *decls.fDecl->fVar; + const Variable& var = decls.declaration()->as().var(); if (var.modifiers().fFlags & Modifiers::kOut_Flag && -1 == var.modifiers().fLayout.fBuiltin) { this->write(" "); @@ -1514,9 +1514,9 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) { if (!element->is()) { continue; } - const GlobalVarDeclaration& decls = element->as(); - const VarDeclaration& decl = *decls.fDecl; - const Variable& var = *decl.fVar; + const GlobalVarDeclaration& global = element->as(); + const VarDeclaration& decl = global.declaration()->as(); + const Variable& var = decl.var(); if ((!var.modifiers().fFlags && -1 == var.modifiers().fLayout.fBuiltin) || var.type().typeKind() == Type::TypeKind::kSampler) { if (var.type().typeKind() == Type::TypeKind::kSampler) { @@ -1525,7 +1525,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) { visitor->VisitSampler(var.type(), String(var.name()) + SAMPLER_SUFFIX); } else { // Visit a regular variable. - visitor->VisitVariable(var, decl.fValue.get()); + visitor->VisitVariable(var, decl.value().get()); } } } @@ -1640,8 +1640,9 @@ void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) { case ProgramElement::Kind::kExtension: break; case ProgramElement::Kind::kGlobalVar: { - const VarDeclaration& decl = *e.as().fDecl; - int builtin = decl.fVar->modifiers().fLayout.fBuiltin; + const GlobalVarDeclaration& global = e.as(); + const VarDeclaration& decl = global.declaration()->as(); + int builtin = decl.var().modifiers().fLayout.fBuiltin; if (-1 == builtin) { // normal var this->writeVarDeclaration(decl, true); @@ -1756,7 +1757,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Statemen } case Statement::Kind::kVarDeclaration: { const VarDeclaration& var = s->as(); - return this->requirements(var.fValue.get()); + return this->requirements(var.value().get()); } case Statement::Kind::kExpression: return this->requirements(s->as().expression().get()); diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp index 2cb2b4f72d..be2c69a2ef 100644 --- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp +++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp @@ -46,10 +46,11 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) { bool found = false; for (const auto& p : fProgram.elements()) { if (p->is()) { - const VarDeclaration& decl = *p->as().fDecl; - if (decl.fVar == arguments[0]->as().variable()) { + const GlobalVarDeclaration& global = p->as(); + const VarDeclaration& decl = global.declaration()->as(); + if (&decl.var() == arguments[0]->as().variable()) { found = true; - } else if (decl.fVar->type() == *fContext.fFragmentProcessor_Type) { + } else if (decl.var().type() == *fContext.fFragmentProcessor_Type) { ++index; } } @@ -125,7 +126,8 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& break; } if (e->is()) { - const Variable& var = *e->as().fDecl->fVar; + const GlobalVarDeclaration& global = e->as(); + const Variable& var = global.declaration()->as().var(); if (&var == ref.variable()) { found = true; break; @@ -213,7 +215,8 @@ void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) { return; } if (p.is()) { - const Variable& var = *p.as().fDecl->fVar; + const GlobalVarDeclaration& global = p.as(); + const Variable& var = global.declaration()->as().var(); if (var.modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag) || var.modifiers().fLayout.fBuiltin == -1) { diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 08a1665f45..f3f0580193 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -2780,32 +2780,32 @@ bool is_dead(const Variable& var) { #define BUILTIN_IGNORE 9999 void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration& varDecl, OutputStream& out) { - const Variable* var = varDecl.fVar; + const Variable& var = varDecl.var(); // These haven't been implemented in our SPIR-V generator yet and we only currently use them // in the OpenGL backend. - SkASSERT(!(var->modifiers().fFlags & (Modifiers::kReadOnly_Flag | + 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) { + if (var.modifiers().fLayout.fBuiltin == BUILTIN_IGNORE) { return; } - if (var->modifiers().fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN && + if (var.modifiers().fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN && kind != Program::kFragment_Kind) { SkASSERT(!fProgram.fSettings.fFragColorIsInOut); return; } - if (is_dead(*var)) { + if (is_dead(var)) { return; } - const Type& type = var->type(); + const Type& type = var.type(); SpvStorageClass_ storageClass; - if (var->modifiers().fFlags & Modifiers::kIn_Flag) { + if (var.modifiers().fFlags & Modifiers::kIn_Flag) { storageClass = SpvStorageClassInput; - } else if (var->modifiers().fFlags & Modifiers::kOut_Flag) { + } else if (var.modifiers().fFlags & Modifiers::kOut_Flag) { storageClass = SpvStorageClassOutput; - } else if (var->modifiers().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) { @@ -2817,9 +2817,9 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration storageClass = SpvStorageClassPrivate; } SpvId id = this->nextId(); - fVariableMap[var] = id; + fVariableMap[&var] = id; SpvId typeId; - if (var->modifiers().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); @@ -2827,41 +2827,41 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration typeId = this->getPointerType(type, storageClass); } this->writeInstruction(SpvOpVariable, typeId, id, storageClass, fConstantBuffer); - this->writeInstruction(SpvOpName, id, var->name(), fNameBuffer); + this->writeInstruction(SpvOpName, id, var.name(), fNameBuffer); this->writePrecisionModifier(type, id); - if (varDecl.fValue) { + if (varDecl.value()) { SkASSERT(!fCurrentBlock); fCurrentBlock = -1; - SpvId value = this->writeExpression(*varDecl.fValue, fGlobalInitializersBuffer); + SpvId value = this->writeExpression(*varDecl.value(), fGlobalInitializersBuffer); this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer); fCurrentBlock = 0; } - this->writeLayout(var->modifiers().fLayout, id); - if (var->modifiers().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->modifiers().fFlags & Modifiers::kNoPerspective_Flag) { + if (var.modifiers().fFlags & Modifiers::kNoPerspective_Flag) { this->writeInstruction(SpvOpDecorate, id, SpvDecorationNoPerspective, fDecorationBuffer); } } void SPIRVCodeGenerator::writeVarDeclaration(const VarDeclaration& varDecl, OutputStream& out) { - const Variable* var = varDecl.fVar; + const Variable& var = varDecl.var(); // These haven't been implemented in our SPIR-V generator yet and we only currently use them // in the OpenGL backend. - SkASSERT(!(var->modifiers().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); + fVariableMap[&var] = id; + SpvId type = this->getPointerType(var.type(), SpvStorageClassFunction); this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer); - this->writeInstruction(SpvOpName, id, var->name(), fNameBuffer); - if (varDecl.fValue) { - SpvId value = this->writeExpression(*varDecl.fValue, out); + this->writeInstruction(SpvOpName, id, var.name(), fNameBuffer); + if (varDecl.value()) { + SpvId value = this->writeExpression(*varDecl.value(), out); this->writeInstruction(SpvOpStore, id, value, out); } } @@ -3214,7 +3214,9 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& } for (const auto& e : program.elements()) { if (e->is()) { - this->writeGlobalVar(program.fKind, *e->as().fDecl, body); + this->writeGlobalVar(program.fKind, + e->as().declaration()->as(), + body); } } for (const auto& e : program.elements()) { diff --git a/src/sksl/SkSLSectionAndParameterHelper.cpp b/src/sksl/SkSLSectionAndParameterHelper.cpp index 3ecf4f5c4d..d70058712a 100644 --- a/src/sksl/SkSLSectionAndParameterHelper.cpp +++ b/src/sksl/SkSLSectionAndParameterHelper.cpp @@ -30,9 +30,10 @@ SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, Err for (const auto& p : fProgram.elements()) { switch (p->kind()) { case ProgramElement::Kind::kGlobalVar: { - const VarDeclaration& decl = *p->as().fDecl; - if (IsParameter(*decl.fVar)) { - fParameters.push_back(decl.fVar); + const VarDeclaration& decl = + p->as().declaration()->as(); + if (IsParameter(decl.var())) { + fParameters.push_back(&decl.var()); } break; } diff --git a/src/sksl/ir/SkSLIRNode.cpp b/src/sksl/ir/SkSLIRNode.cpp index 44a500cd10..8cfcda364b 100644 --- a/src/sksl/ir/SkSLIRNode.cpp +++ b/src/sksl/ir/SkSLIRNode.cpp @@ -137,6 +137,11 @@ IRNode::IRNode(int offset, int kind, const UnresolvedFunctionData& data) , fKind(kind) , fData(data) {} +IRNode::IRNode(int offset, int kind, const VarDeclarationData& data) +: fOffset(offset) +, fKind(kind) +, fData(data) {} + IRNode::IRNode(int offset, int kind, const VariableData& data) : fOffset(offset) , fKind(kind) diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h index 10ee8f0b1d..de68ceb06d 100644 --- a/src/sksl/ir/SkSLIRNode.h +++ b/src/sksl/ir/SkSLIRNode.h @@ -202,6 +202,11 @@ protected: std::vector fFunctions; }; + struct VarDeclarationData { + const Type* fBaseType; + const Variable* fVar; + }; + struct VariableData { StringFragment fName; const Type* fType; @@ -249,6 +254,7 @@ protected: kTypeReference, kTypeToken, kUnresolvedFunction, + kVarDeclaration, kVariable, kVariableReference, } fKind = Kind::kType; @@ -280,6 +286,7 @@ protected: TypeReferenceData fTypeReference; TypeTokenData fTypeToken; UnresolvedFunctionData fUnresolvedFunction; + VarDeclarationData fVarDeclaration; VariableData fVariable; VariableReferenceData fVariableReference; @@ -413,6 +420,11 @@ protected: *(new(&fContents) UnresolvedFunctionData) = data; } + NodeData(const VarDeclarationData& data) + : fKind(Kind::kVarDeclaration) { + *(new(&fContents) VarDeclarationData) = data; + } + NodeData(const VariableData& data) : fKind(Kind::kVariable) { *(new(&fContents) VariableData) = data; @@ -508,6 +520,9 @@ protected: case Kind::kUnresolvedFunction: *(new(&fContents) UnresolvedFunctionData) = other.fContents.fUnresolvedFunction; break; + case Kind::kVarDeclaration: + *(new(&fContents) VarDeclarationData) = other.fContents.fVarDeclaration; + break; case Kind::kVariable: *(new(&fContents) VariableData) = other.fContents.fVariable; break; @@ -599,6 +614,9 @@ protected: case Kind::kUnresolvedFunction: fContents.fUnresolvedFunction.~UnresolvedFunctionData(); break; + case Kind::kVarDeclaration: + fContents.fVarDeclaration.~VarDeclarationData(); + break; case Kind::kVariable: fContents.fVariable.~VariableData(); break; @@ -659,6 +677,8 @@ protected: IRNode(int offset, int kind, const UnresolvedFunctionData& data); + IRNode(int offset, int kind, const VarDeclarationData& data); + IRNode(int offset, int kind, const VariableData& data); IRNode(int offset, int kind, const VariableReferenceData& data); @@ -847,6 +867,16 @@ protected: return fData.fContents.fUnresolvedFunction; } + VarDeclarationData& varDeclarationData() { + SkASSERT(fData.fKind == NodeData::Kind::kVarDeclaration); + return fData.fContents.fVarDeclaration; + } + + const VarDeclarationData& varDeclarationData() const { + SkASSERT(fData.fKind == NodeData::Kind::kVarDeclaration); + return fData.fContents.fVarDeclaration; + } + VariableData& variableData() { SkASSERT(fData.fKind == NodeData::Kind::kVariable); return fData.fContents.fVariable; diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h index 13c87e97bc..3d76226003 100644 --- a/src/sksl/ir/SkSLModifiersDeclaration.h +++ b/src/sksl/ir/SkSLModifiersDeclaration.h @@ -18,7 +18,8 @@ namespace SkSL { * * layout(blend_support_all_equations) out; */ -struct ModifiersDeclaration : public ProgramElement { +class ModifiersDeclaration : public ProgramElement { +public: static constexpr Kind kProgramElementKind = Kind::kModifiers; ModifiersDeclaration(ModifiersPool::Handle modifiers) @@ -40,6 +41,7 @@ struct ModifiersDeclaration : public ProgramElement { return this->modifiers().description() + ";"; } +private: using INHERITED = ProgramElement; }; diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h index a37ec0cd41..8ceabc26c3 100644 --- a/src/sksl/ir/SkSLStatement.h +++ b/src/sksl/ir/SkSLStatement.h @@ -58,6 +58,9 @@ public: Statement(int offset, const InlineMarkerData& data) : INHERITED(offset, (int) Kind::kInlineMarker, data) {} + Statement(int offset, const VarDeclarationData& data) + : INHERITED(offset, (int) Kind::kVarDeclaration, data) {} + Kind kind() const { return (Kind) fKind; } diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h index 7514e461c2..67f53f9a80 100644 --- a/src/sksl/ir/SkSLVarDeclarations.h +++ b/src/sksl/ir/SkSLVarDeclarations.h @@ -20,55 +20,82 @@ namespace SkSL { * separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two * VarDeclaration instances (wrapped in an unscoped Block). */ -struct VarDeclaration : public Statement { +class VarDeclaration : public Statement { +public: static constexpr Kind kStatementKind = Kind::kVarDeclaration; VarDeclaration(const Variable* var, const Type* baseType, ExpressionArray sizes, std::unique_ptr value) - : INHERITED(var->fOffset, kStatementKind) - , fVar(var) - , fBaseType(*baseType) - , fSizes(std::move(sizes)) - , fValue(std::move(value)) {} + : INHERITED(var->fOffset, VarDeclarationData{baseType, var}) { + fExpressionChildren.reserve(sizes.size() + 1); + fExpressionChildren.move_back_n(sizes.size(), sizes.data()); + fExpressionChildren.push_back(std::move(value)); + } + + const Type& baseType() const { + return *this->varDeclarationData().fBaseType; + } + + const Variable& var() const { + return *this->varDeclarationData().fVar; + } + + void setVar(const Variable* var) { + this->varDeclarationData().fVar = var; + } + + int sizeCount() const { + return fExpressionChildren.size() - 1; + } + + const std::unique_ptr& size(int index) const { + SkASSERT(index >= 0 && index < this->sizeCount()); + return fExpressionChildren[index]; + } + + std::unique_ptr& value() { + return fExpressionChildren.back(); + } + + const std::unique_ptr& value() const { + return fExpressionChildren.back(); + } std::unique_ptr clone() const override { ExpressionArray sizesClone; - sizesClone.reserve(fSizes.size()); - for (const auto& s : fSizes) { - if (s) { - sizesClone.push_back(s->clone()); + sizesClone.reserve(this->sizeCount()); + for (int i = 0; i < this->sizeCount(); ++i) { + if (this->size(i)) { + sizesClone.push_back(this->size(i)->clone()); } else { sizesClone.push_back(nullptr); } } - return std::make_unique(fVar, &fBaseType, std::move(sizesClone), - fValue ? fValue->clone() : nullptr); + return std::make_unique(&this->var(), + &this->baseType(), + std::move(sizesClone), + this->value() ? this->value()->clone() : nullptr); } String description() const override { - String result = fVar->modifiers().description() + fBaseType.description() + " " + - fVar->name(); - for (const auto& size : fSizes) { - if (size) { - result += "[" + size->description() + "]"; + String result = this->var().modifiers().description() + this->baseType().description() + + " " + this->var().name(); + for (int i = 0; i < this->sizeCount(); ++i) { + if (this->size(i)) { + result += "[" + this->size(i)->description() + "]"; } else { result += "[]"; } } - if (fValue) { - result += " = " + fValue->description(); + if (this->value()) { + result += " = " + this->value()->description(); } result += ";"; return result; } - const Variable* fVar; - const Type& fBaseType; - ExpressionArray fSizes; - std::unique_ptr fValue; - using INHERITED = Statement; }; @@ -76,26 +103,33 @@ struct VarDeclaration : public Statement { * A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces * two GlobalVarDeclaration elements, each containing the declaration of one variable. */ -struct GlobalVarDeclaration : public ProgramElement { +class GlobalVarDeclaration : public ProgramElement { +public: static constexpr Kind kProgramElementKind = Kind::kGlobalVar; - // decl must be a unique_ptr, but to simplify construction, we take a Statement GlobalVarDeclaration(int offset, std::unique_ptr decl) : INHERITED(offset, kProgramElementKind) { SkASSERT(decl->is()); - fDecl.reset(static_cast(decl.release())); + fStatementChildren.push_back(std::move(decl)); + } + + std::unique_ptr& declaration() { + return fStatementChildren[0]; + } + + const std::unique_ptr& declaration() const { + return fStatementChildren[0]; } std::unique_ptr clone() const override { - return std::make_unique(fOffset, fDecl->clone()); + return std::make_unique(fOffset, this->declaration()->clone()); } String description() const override { - return fDecl->description(); + return this->declaration()->description(); } - std::unique_ptr fDecl; - +private: using INHERITED = ProgramElement; };