From 0a5d096eeba2ea49d64d2ef341e4b6a8ce92af8f Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Wed, 14 Oct 2020 13:33:18 -0400 Subject: [PATCH] moved SkSL FunctionDefinition data into IRNode Change-Id: Ia828de0793ee66301ba315f4593b4d7d69222b4e Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326717 Reviewed-by: John Stiles Commit-Queue: Ethan Nicholas --- src/core/SkRuntimeEffect.cpp | 2 +- src/sksl/SkSLAnalysis.cpp | 4 +- src/sksl/SkSLByteCodeGenerator.cpp | 10 ++-- src/sksl/SkSLCFGGenerator.cpp | 2 +- src/sksl/SkSLCPPCodeGenerator.cpp | 6 +-- src/sksl/SkSLCompiler.cpp | 12 ++--- src/sksl/SkSLDehydrator.cpp | 8 +-- src/sksl/SkSLGLSLCodeGenerator.cpp | 10 ++-- src/sksl/SkSLIRGenerator.cpp | 10 ++-- src/sksl/SkSLInliner.cpp | 18 +++---- src/sksl/SkSLMetalCodeGenerator.cpp | 20 ++++---- src/sksl/SkSLPipelineStageCodeGenerator.cpp | 10 ++-- src/sksl/SkSLRehydrator.cpp | 2 +- src/sksl/SkSLSPIRVCodeGenerator.cpp | 10 ++-- src/sksl/ir/SkSLFunctionDefinition.h | 54 +++++++++++++-------- src/sksl/ir/SkSLIRNode.cpp | 5 ++ src/sksl/ir/SkSLIRNode.h | 38 +++++++++++++++ src/sksl/ir/SkSLProgramElement.h | 15 +++--- 18 files changed, 147 insertions(+), 89 deletions(-) diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp index 68910d62a6..951c386844 100644 --- a/src/core/SkRuntimeEffect.cpp +++ b/src/core/SkRuntimeEffect.cpp @@ -214,7 +214,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) { // Functions else if (elem->is()) { const auto& func = elem->as(); - const SkSL::FunctionDeclaration& decl = func.fDeclaration; + const SkSL::FunctionDeclaration& decl = func.declaration(); if (decl.name() == "main") { hasMain = true; } diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp index a462fb3f50..6e6e83d54c 100644 --- a/src/sksl/SkSLAnalysis.cpp +++ b/src/sksl/SkSLAnalysis.cpp @@ -324,7 +324,7 @@ bool Analysis::ReferencesFragCoords(const Program& program) { } bool Analysis::NodeCountExceeds(const FunctionDefinition& function, int limit) { - return NodeCountVisitor{limit}.visit(*function.fBody) > limit; + return NodeCountVisitor{limit}.visit(*function.body()) > limit; } bool Analysis::StatementWritesToVariable(const Statement& stmt, const Variable& var) { @@ -506,7 +506,7 @@ bool TProgramVisitor::visitProgramElement(ELEM pe) { return false; case ProgramElement::Kind::kFunction: - return this->visitStatement(*pe.template as().fBody); + return this->visitStatement(*pe.template as().body()); case ProgramElement::Kind::kInterfaceBlock: for (auto& e : pe.template as().fSizes) { diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp index a3927e5900..492807467f 100644 --- a/src/sksl/SkSLByteCodeGenerator.cpp +++ b/src/sksl/SkSLByteCodeGenerator.cpp @@ -184,14 +184,14 @@ bool ByteCodeGenerator::generateCode() { std::unique_ptr ByteCodeGenerator::writeFunction(const FunctionDefinition& f) { fFunction = &f; - std::unique_ptr result(new ByteCodeFunction(&f.fDeclaration)); + std::unique_ptr result(new ByteCodeFunction(&f.declaration())); fParameterCount = result->fParameterCount; fLoopCount = fMaxLoopCount = 0; fConditionCount = fMaxConditionCount = 0; fStackCount = fMaxStackCount = 0; fCode = &result->fCode; - this->writeStatement(*f.fBody); + this->writeStatement(*f.body()); if (0 == fErrors.errorCount()) { SkASSERT(fLoopCount == 0); SkASSERT(fConditionCount == 0); @@ -204,7 +204,7 @@ std::unique_ptr ByteCodeGenerator::writeFunction(const Functio result->fLoopCount = fMaxLoopCount; result->fStackCount = fMaxStackCount; - const Type& returnType = f.fDeclaration.returnType(); + const Type& returnType = f.declaration().returnType(); if (returnType != *fContext.fVoid_Type) { result->fReturnCount = SlotCount(returnType); } @@ -441,7 +441,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) } case Variable::Storage::kParameter: { int offset = 0; - for (const auto& p : fFunction->fDeclaration.parameters()) { + for (const auto& p : fFunction->declaration().parameters()) { if (p == &var) { SkASSERT(offset <= 255); return { offset, Storage::kLocal }; @@ -1238,7 +1238,7 @@ void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) { // before they're defined. This is an easy-to-understand rule that prevents recursion. int idx = -1; for (size_t i = 0; i < fFunctions.size(); ++i) { - if (f.function().matches(fFunctions[i]->fDeclaration)) { + if (f.function().matches(fFunctions[i]->declaration())) { idx = i; break; } diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp index 79c128a462..0c2cd6bd91 100644 --- a/src/sksl/SkSLCFGGenerator.cpp +++ b/src/sksl/SkSLCFGGenerator.cpp @@ -654,7 +654,7 @@ CFG CFGGenerator::getCFG(FunctionDefinition& f) { CFG result; result.fStart = result.newBlock(); result.fCurrent = result.fStart; - this->addStatement(result, &f.fBody); + this->addStatement(result, &f.body()); result.newBlock(); result.fExit = result.fCurrent; return result; diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 4537608d08..8d26ede529 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -595,7 +595,7 @@ static const char* glsltype_string(const Context& context, const Type& type) { } void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) { - const FunctionDeclaration& decl = f.fDeclaration; + const FunctionDeclaration& decl = f.declaration(); if (decl.isBuiltin()) { return; } @@ -605,7 +605,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) { fOut = &buffer; if (decl.name() == "main") { fInMain = true; - for (const std::unique_ptr& s : f.fBody->as().children()) { + for (const std::unique_ptr& s : f.body()->as().children()) { this->writeStatement(*s); this->writeLine(); } @@ -625,7 +625,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) { } args += "};"; this->addExtraEmitCodeLine(args.c_str()); - for (const std::unique_ptr& s : f.fBody->as().children()) { + for (const std::unique_ptr& s : f.body()->as().children()) { this->writeStatement(*s); this->writeLine(); } diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index ee2993784f..528ce07d33 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -360,8 +360,8 @@ ParsedModule Compiler::parseModule(Program::Kind kind, ModuleData data, const Pa switch (element->kind()) { case ProgramElement::Kind::kFunction: { const FunctionDefinition& f = element->as(); - SkASSERT(f.fDeclaration.isBuiltin()); - intrinsics->insertOrDie(f.fDeclaration.description(), std::move(element)); + SkASSERT(f.declaration().isBuiltin()); + intrinsics->insertOrDie(f.declaration().description(), std::move(element)); break; } case ProgramElement::Kind::kEnum: { @@ -1525,9 +1525,9 @@ bool Compiler::scanCFG(FunctionDefinition& f) { } // check for missing return - if (f.fDeclaration.returnType() != *fContext->fVoid_Type) { + if (f.declaration().returnType() != *fContext->fVoid_Type) { if (cfg.fBlocks[cfg.fExit].fIsReachable) { - this->error(f.fOffset, String("function '" + String(f.fDeclaration.name()) + + this->error(f.fOffset, String("function '" + String(f.declaration().name()) + "' can exit without returning a value")); } } @@ -1601,8 +1601,8 @@ bool Compiler::optimize(Program& program) { return false; } const auto& fn = element->as(); - bool dead = fn.fDeclaration.callCount() == 0 && - fn.fDeclaration.name() != "main"; + bool dead = fn.declaration().callCount() == 0 && + fn.declaration().name() != "main"; madeChanges |= dead; return dead; }), diff --git a/src/sksl/SkSLDehydrator.cpp b/src/sksl/SkSLDehydrator.cpp index 6bbcfd4e50..ea36e947fb 100644 --- a/src/sksl/SkSLDehydrator.cpp +++ b/src/sksl/SkSLDehydrator.cpp @@ -529,11 +529,11 @@ void Dehydrator::write(const ProgramElement& e) { case ProgramElement::Kind::kFunction: { const FunctionDefinition& f = e.as(); this->writeCommand(Rehydrator::kFunctionDefinition_Command); - this->writeU16(this->symbolId(&f.fDeclaration)); - this->write(f.fBody.get()); - this->writeU8(f.fReferencedIntrinsics.size()); + this->writeU16(this->symbolId(&f.declaration())); + this->write(f.body().get()); + this->writeU8(f.referencedIntrinsics().size()); std::set ordered; - for (const FunctionDeclaration* ref : f.fReferencedIntrinsics) { + for (const FunctionDeclaration* ref : f.referencedIntrinsics()) { ordered.insert(this->symbolId(ref)); } for (uint16_t ref : ordered) { diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 1d53ad4aa9..1994bf3b17 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -1044,11 +1044,11 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { // accidentally end up here. SkASSERT(fProgramKind != Program::kPipelineStage_Kind); - this->writeTypePrecision(f.fDeclaration.returnType()); - this->writeType(f.fDeclaration.returnType()); - this->write(" " + f.fDeclaration.name() + "("); + this->writeTypePrecision(f.declaration().returnType()); + this->writeType(f.declaration().returnType()); + this->write(" " + f.declaration().name() + "("); const char* separator = ""; - for (const auto& param : f.fDeclaration.parameters()) { + for (const auto& param : f.declaration().parameters()) { this->write(separator); separator = ", "; this->writeModifiers(param->modifiers(), false); @@ -1076,7 +1076,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { OutputStream* oldOut = fOut; StringStream buffer; fOut = &buffer; - for (const std::unique_ptr& stmt : f.fBody->as().children()) { + for (const std::unique_ptr& stmt : f.body()->as().children()) { if (!stmt->isEmpty()) { this->writeStatement(*stmt); this->writeLine(); diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index a1b784f244..239f32b89b 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -727,7 +727,7 @@ std::unique_ptr IRGenerator::applyInvocationIDWorkaround(std::unique_ptr< fContext.fVoid_Type.get(), /*builtin=*/false)); fProgramElements->push_back(std::make_unique(/*offset=*/-1, - *invokeDecl, + invokeDecl, std::move(main))); std::vector> variables; @@ -1061,10 +1061,10 @@ void IRGenerator::convertFunction(const ASTNode& f) { if (Program::kVertex_Kind == fKind && funcData.fName == "main" && fRTAdjust) { body->children().push_back(this->getNormalizeSkPositionCode()); } - auto result = std::make_unique(f.fOffset, *decl, std::move(body), + auto result = std::make_unique(f.fOffset, decl, std::move(body), std::move(fReferencedIntrinsics)); decl->setDefinition(result.get()); - result->fSource = &f; + result->setSource(&f); fProgramElements->push_back(std::move(result)); } } @@ -2001,8 +2001,8 @@ void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) { // Sort the referenced intrinsics into a consistent order; otherwise our output will become // non-deterministic. - std::vector intrinsics(original.fReferencedIntrinsics.begin(), - original.fReferencedIntrinsics.end()); + std::vector intrinsics(original.referencedIntrinsics().begin(), + original.referencedIntrinsics().end()); std::sort(intrinsics.begin(), intrinsics.end(), [](const FunctionDeclaration* a, const FunctionDeclaration* b) { if (a->isBuiltin() != b->isBuiltin()) { diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp index c80374d86c..bbb6ee03c2 100644 --- a/src/sksl/SkSLInliner.cpp +++ b/src/sksl/SkSLInliner.cpp @@ -660,10 +660,10 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call, // Create a variable to hold the result in the extra statements (excepting void). std::unique_ptr resultExpr; - if (function.fDeclaration.returnType() != *fContext->fVoid_Type) { + if (function.declaration().returnType() != *fContext->fVoid_Type) { std::unique_ptr noInitialValue; - resultExpr = makeInlineVar(String(function.fDeclaration.name()), - &function.fDeclaration.returnType(), + resultExpr = makeInlineVar(String(function.declaration().name()), + &function.declaration().returnType(), Modifiers{}, &noInitialValue); } @@ -672,13 +672,13 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call, VariableRewriteMap varMap; std::vector argsToCopyBack; for (int i = 0; i < (int) arguments.size(); ++i) { - const Variable* param = function.fDeclaration.parameters()[i]; + const Variable* param = function.declaration().parameters()[i]; 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])) { // ... and it's an `out` param, or it isn't written to within the inline function... - if (isOutParam || !Analysis::StatementWritesToVariable(*function.fBody, *param)) { + if (isOutParam || !Analysis::StatementWritesToVariable(*function.body(), *param)) { // ... we don't need to copy it at all! We can just use the existing expression. varMap[param] = arguments[i]->clone(); continue; @@ -693,7 +693,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call, param->modifiers(), &arguments[i]); } - const Block& body = function.fBody->as(); + const Block& body = function.body()->as(); auto inlineBlock = std::make_unique(offset, StatementArray{}); inlineBlock->children().reserve(body.children().size()); for (const std::unique_ptr& stmt : body.children()) { @@ -718,7 +718,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call, // Copy back the values of `out` parameters into their real destinations. for (int i : argsToCopyBack) { - const Variable* p = function.fDeclaration.parameters()[i]; + const Variable* p = function.declaration().parameters()[i]; SkASSERT(varMap.find(p) != varMap.end()); inlinedBody.children().push_back( std::make_unique(std::make_unique( @@ -823,7 +823,7 @@ public: case ProgramElement::Kind::kFunction: { FunctionDefinition& funcDef = pe->as(); fEnclosingFunction = &funcDef; - this->visitStatement(&funcDef.fBody); + this->visitStatement(&funcDef.body()); break; } default: @@ -1164,7 +1164,7 @@ bool Inliner::analyze(Program& program) { // Convert the function call to its inlined equivalent. InlinedCall inlinedCall = this->inlineCall(&funcCall, candidate.fSymbols, - &candidate.fEnclosingFunction->fDeclaration); + &candidate.fEnclosingFunction->declaration()); if (inlinedCall.fInlinedBody) { // Ensure that the inlined body has a scope if it needs one. this->ensureScopedBlocks(inlinedCall.fInlinedBody.get(), candidate.fParentStmt->get()); diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp index 710bf60d6a..985c9fe604 100644 --- a/src/sksl/SkSLMetalCodeGenerator.cpp +++ b/src/sksl/SkSLMetalCodeGenerator.cpp @@ -936,7 +936,7 @@ void MetalCodeGenerator::writeSetting(const Setting& s) { void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { fRTHeightName = fProgram.fInputs.fRTHeight ? "_globals->_anonInterface0->u_skRTHeight" : ""; const char* separator = ""; - if ("main" == f.fDeclaration.name()) { + if ("main" == f.declaration().name()) { switch (fProgram.fKind) { case Program::kFragment_Kind: this->write("fragment Outputs fragmentMain"); @@ -1006,11 +1006,11 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { } separator = ", "; } else { - this->writeType(f.fDeclaration.returnType()); + this->writeType(f.declaration().returnType()); this->write(" "); - this->writeName(f.fDeclaration.name()); + this->writeName(f.declaration().name()); this->write("("); - Requirements requirements = this->requirements(f.fDeclaration); + Requirements requirements = this->requirements(f.declaration()); if (requirements & kInputs_Requirement) { this->write("Inputs _in"); separator = ", "; @@ -1036,7 +1036,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { separator = ", "; } } - for (const auto& param : f.fDeclaration.parameters()) { + for (const auto& param : f.declaration().parameters()) { this->write(separator); separator = ", "; this->writeModifiers(param->modifiers(), false); @@ -1064,7 +1064,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { SkASSERT(!fProgram.fSettings.fFragColorIsInOut); - if (f.fDeclaration.name() == "main") { + if (f.declaration().name() == "main") { this->writeGlobalInit(); this->writeLine(" Outputs _outputStruct;"); this->writeLine(" thread Outputs* _out = &_outputStruct;"); @@ -1075,13 +1075,13 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) { StringStream buffer; fOut = &buffer; fIndentation++; - for (const std::unique_ptr& stmt : f.fBody->as().children()) { + for (const std::unique_ptr& stmt : f.body()->as().children()) { if (!stmt->isEmpty()) { this->writeStatement(*stmt); this->writeLine(); } } - if (f.fDeclaration.name() == "main") { + if (f.declaration().name() == "main") { switch (fProgram.fKind) { case Program::kFragment_Kind: this->writeLine("return *_out;"); @@ -1813,8 +1813,8 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Function for (const auto& e : fProgram.elements()) { if (e->is()) { const FunctionDefinition& def = e->as(); - if (&def.fDeclaration == &f) { - Requirements reqs = this->requirements(def.fBody.get()); + if (&def.declaration() == &f) { + Requirements reqs = this->requirements(def.body().get()); fRequirements[&f] = reqs; return reqs; } diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp index be2c69a2ef..3c5d6e04c2 100644 --- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp +++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp @@ -83,7 +83,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) { int index = 0; for (const auto& e : fProgram.elements()) { if (e->is()) { - if (&e->as().fDeclaration == &function) { + if (&e->as().declaration() == &function) { break; } ++index; @@ -175,8 +175,8 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) { OutputStream* oldOut = fOut; StringStream buffer; fOut = &buffer; - if (f.fDeclaration.name() == "main") { - for (const std::unique_ptr& stmt : f.fBody->as().children()) { + if (f.declaration().name() == "main") { + for (const std::unique_ptr& stmt : f.body()->as().children()) { this->writeStatement(*stmt); this->writeLine(); } @@ -184,7 +184,7 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) { this->write(fFunctionHeader); this->write(buffer.str()); } else { - const FunctionDeclaration& decl = f.fDeclaration; + const FunctionDeclaration& decl = f.declaration(); Compiler::GLSLFunction result; if (!type_to_grsltype(fContext, decl.returnType(), &result.fReturnType)) { fErrors.error(f.fOffset, "unsupported return type"); @@ -199,7 +199,7 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) { } result.fParameters.emplace_back(v->name(), paramSLType); } - for (const std::unique_ptr& stmt : f.fBody->as().children()) { + for (const std::unique_ptr& stmt : f.body()->as().children()) { this->writeStatement(*stmt); this->writeLine(); } diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp index 9ae585035f..fd5453fac6 100644 --- a/src/sksl/SkSLRehydrator.cpp +++ b/src/sksl/SkSLRehydrator.cpp @@ -300,7 +300,7 @@ std::unique_ptr Rehydrator::element() { refs.insert(this->symbolRef( Symbol::Kind::kFunctionDeclaration)); } - FunctionDefinition* result = new FunctionDefinition(-1, *decl, std::move(body), + FunctionDefinition* result = new FunctionDefinition(-1, decl, std::move(body), std::move(refs)); decl->setDefinition(result); return std::unique_ptr(result); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index f3f0580193..27b2833492 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -2598,17 +2598,17 @@ SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, Outpu SpvId SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, OutputStream& out) { fVariableBuffer.reset(); - SpvId result = this->writeFunctionStart(f.fDeclaration, out); + SpvId result = this->writeFunctionStart(f.declaration(), out); this->writeLabel(this->nextId(), out); StringStream bodyBuffer; - this->writeBlock((Block&) *f.fBody, bodyBuffer); + this->writeBlock((Block&) *f.body(), bodyBuffer); write_stringstream(fVariableBuffer, out); - if (f.fDeclaration.name() == "main") { + if (f.declaration().name() == "main") { write_stringstream(fGlobalInitializersBuffer, out); } write_stringstream(bodyBuffer, out); if (fCurrentBlock) { - if (f.fDeclaration.returnType() == *fContext.fVoid_Type) { + if (f.declaration().returnType() == *fContext.fVoid_Type) { this->writeInstruction(SpvOpReturn, out); } else { this->writeInstruction(SpvOpUnreachable, out); @@ -3167,7 +3167,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& switch (e->kind()) { case ProgramElement::Kind::kFunction: { const FunctionDefinition& f = e->as(); - fFunctionMap[&f.fDeclaration] = this->nextId(); + fFunctionMap[&f.declaration()] = this->nextId(); break; } case ProgramElement::Kind::kModifiers: { diff --git a/src/sksl/ir/SkSLFunctionDefinition.h b/src/sksl/ir/SkSLFunctionDefinition.h index c122173042..304aee1d4e 100644 --- a/src/sksl/ir/SkSLFunctionDefinition.h +++ b/src/sksl/ir/SkSLFunctionDefinition.h @@ -12,8 +12,6 @@ #include "src/sksl/ir/SkSLFunctionDeclaration.h" #include "src/sksl/ir/SkSLProgramElement.h" -#include - namespace SkSL { struct ASTNode; @@ -25,34 +23,48 @@ struct FunctionDefinition : public ProgramElement { static constexpr Kind kProgramElementKind = Kind::kFunction; FunctionDefinition(int offset, - const FunctionDeclaration& declaration, + const FunctionDeclaration* declaration, std::unique_ptr body, std::unordered_set referencedIntrinsics = {}) - : INHERITED(offset, kProgramElementKind) - , fDeclaration(declaration) - , fBody(std::move(body)) - , fReferencedIntrinsics(std::move(referencedIntrinsics)) {} + : INHERITED(offset, FunctionDefinitionData{declaration, std::move(referencedIntrinsics), + nullptr}) { + fStatementChildren.push_back(std::move(body)); + } + + const FunctionDeclaration& declaration() const { + return *this->functionDefinitionData().fDeclaration; + } + + std::unique_ptr& body() { + return this->fStatementChildren[0]; + } + + const std::unique_ptr& body() const { + return this->fStatementChildren[0]; + } + + const std::unordered_set& referencedIntrinsics() const { + return this->functionDefinitionData().fReferencedIntrinsics; + } + + const ASTNode* source() const { + return this->functionDefinitionData().fSource; + } + + void setSource(const ASTNode* source) { + this->functionDefinitionData().fSource = source; + } std::unique_ptr clone() const override { - return std::make_unique(fOffset, fDeclaration, - fBody->clone(), fReferencedIntrinsics); + return std::make_unique(fOffset, &this->declaration(), + this->body()->clone(), + this->referencedIntrinsics()); } String description() const override { - return fDeclaration.description() + " " + fBody->description(); + return this->declaration().description() + " " + this->body()->description(); } - const FunctionDeclaration& fDeclaration; - std::unique_ptr fBody; - // We track intrinsic functions we reference so that we can ensure that all of them end up - // copied into the final output. - std::unordered_set fReferencedIntrinsics; - // This pointer may be null, and even when non-null is not guaranteed to remain valid for the - // entire lifespan of this object. The parse tree's lifespan is normally controlled by - // IRGenerator, so the IRGenerator being destroyed or being used to compile another file will - // invalidate this pointer. - const ASTNode* fSource = nullptr; - using INHERITED = ProgramElement; }; diff --git a/src/sksl/ir/SkSLIRNode.cpp b/src/sksl/ir/SkSLIRNode.cpp index 8cfcda364b..7dbd665f15 100644 --- a/src/sksl/ir/SkSLIRNode.cpp +++ b/src/sksl/ir/SkSLIRNode.cpp @@ -62,6 +62,11 @@ IRNode::IRNode(int offset, int kind, const FunctionDeclarationData& data) , fKind(kind) , fData(data) {} +IRNode::IRNode(int offset, int kind, const FunctionDefinitionData& data) +: fOffset(offset) +, fKind(kind) +, fData(data) {} + IRNode::IRNode(int offset, int kind, const FunctionReferenceData& data) : fOffset(offset) , fKind(kind) diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h index de68ceb06d..af9ad33b32 100644 --- a/src/sksl/ir/SkSLIRNode.h +++ b/src/sksl/ir/SkSLIRNode.h @@ -16,6 +16,7 @@ #include #include +#include #include namespace SkSL { @@ -138,6 +139,18 @@ protected: } }; + struct FunctionDefinitionData { + const FunctionDeclaration* fDeclaration; + // We track intrinsic functions we reference so that we can ensure that all of them end up + // copied into the final output. + std::unordered_set fReferencedIntrinsics; + // This pointer may be null, and even when non-null is not guaranteed to remain valid for + // the entire lifespan of this object. The parse tree's lifespan is normally controlled by + // IRGenerator, so the IRGenerator being destroyed or being used to compile another file + // will invalidate this pointer. + const ASTNode* fSource; + }; + struct FunctionReferenceData { const Type* fType; std::vector fFunctions; @@ -239,6 +252,7 @@ protected: kForStatement, kFunctionCall, kFunctionDeclaration, + kFunctionDefinition, kFunctionReference, kIfStatement, kInlineMarker, @@ -271,6 +285,7 @@ protected: ForStatementData fForStatement; FunctionCallData fFunctionCall; FunctionDeclarationData fFunctionDeclaration; + FunctionDefinitionData fFunctionDefinition; FunctionReferenceData fFunctionReference; IfStatementData fIfStatement; InlineMarkerData fInlineMarker; @@ -345,6 +360,11 @@ protected: *(new(&fContents) FunctionDeclarationData) = data; } + NodeData(const FunctionDefinitionData& data) + : fKind(Kind::kFunctionDefinition) { + *(new(&fContents) FunctionDefinitionData) = data; + } + NodeData(const FunctionReferenceData& data) : fKind(Kind::kFunctionReference) { *(new(&fContents) FunctionReferenceData) = data; @@ -474,6 +494,9 @@ protected: *(new(&fContents) FunctionDeclarationData) = other.fContents.fFunctionDeclaration; break; + case Kind::kFunctionDefinition: + *(new(&fContents) FunctionDefinitionData) = other.fContents.fFunctionDefinition; + break; case Kind::kFunctionReference: *(new(&fContents) FunctionReferenceData) = other.fContents.fFunctionReference; break; @@ -570,6 +593,9 @@ protected: case Kind::kFunctionDeclaration: fContents.fFunctionDeclaration.~FunctionDeclarationData(); break; + case Kind::kFunctionDefinition: + fContents.fFunctionDefinition.~FunctionDefinitionData(); + break; case Kind::kFunctionReference: fContents.fFunctionReference.~FunctionReferenceData(); break; @@ -647,6 +673,8 @@ protected: IRNode(int offset, int kind, const FunctionDeclarationData& data); + IRNode(int offset, int kind, const FunctionDefinitionData& data); + IRNode(int offset, int kind, const FunctionReferenceData& data); IRNode(int offset, int kind, const IfStatementData& data); @@ -782,6 +810,16 @@ protected: return fData.fContents.fFunctionDeclaration; } + FunctionDefinitionData& functionDefinitionData() { + SkASSERT(fData.fKind == NodeData::Kind::kFunctionDefinition); + return fData.fContents.fFunctionDefinition; + } + + const FunctionDefinitionData& functionDefinitionData() const { + SkASSERT(fData.fKind == NodeData::Kind::kFunctionDefinition); + return fData.fContents.fFunctionDefinition; + } + const FunctionReferenceData& functionReferenceData() const { SkASSERT(fData.fKind == NodeData::Kind::kFunctionReference); return fData.fContents.fFunctionReference; diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h index 2ea4fd311a..7a2873b741 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -37,19 +37,22 @@ public: SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast); } - ProgramElement(int offset, const EnumData& enumData) - : INHERITED(offset, (int) Kind::kEnum, enumData) {} + ProgramElement(int offset, const EnumData& data) + : INHERITED(offset, (int) Kind::kEnum, data) {} - ProgramElement(int offset, const ModifiersDeclarationData& enumData) - : INHERITED(offset, (int) Kind::kModifiers, enumData) {} + ProgramElement(int offset, const FunctionDefinitionData& data) + : INHERITED(offset, (int) Kind::kFunction, data) {} + + ProgramElement(int offset, const ModifiersDeclarationData& data) + : INHERITED(offset, (int) Kind::kModifiers, data) {} ProgramElement(int offset, Kind kind, const String& data) : INHERITED(offset, (int) kind, data) { SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast); } - ProgramElement(int offset, const SectionData& sectionData) - : INHERITED(offset, (int) Kind::kSection, sectionData) {} + ProgramElement(int offset, const SectionData& data) + : INHERITED(offset, (int) Kind::kSection, data) {} Kind kind() const { return (Kind) fKind;