moved SkSL FunctionDefinition data into IRNode

Change-Id: Ia828de0793ee66301ba315f4593b4d7d69222b4e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326717
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Ethan Nicholas 2020-10-14 13:33:18 -04:00 committed by Skia Commit-Bot
parent 3172208ad0
commit 0a5d096eeb
18 changed files with 147 additions and 89 deletions

View File

@ -214,7 +214,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
// Functions
else if (elem->is<SkSL::FunctionDefinition>()) {
const auto& func = elem->as<SkSL::FunctionDefinition>();
const SkSL::FunctionDeclaration& decl = func.fDeclaration;
const SkSL::FunctionDeclaration& decl = func.declaration();
if (decl.name() == "main") {
hasMain = true;
}

View File

@ -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<PROG, EXPR, STMT, ELEM>::visitProgramElement(ELEM pe) {
return false;
case ProgramElement::Kind::kFunction:
return this->visitStatement(*pe.template as<FunctionDefinition>().fBody);
return this->visitStatement(*pe.template as<FunctionDefinition>().body());
case ProgramElement::Kind::kInterfaceBlock:
for (auto& e : pe.template as<InterfaceBlock>().fSizes) {

View File

@ -184,14 +184,14 @@ bool ByteCodeGenerator::generateCode() {
std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const FunctionDefinition& f) {
fFunction = &f;
std::unique_ptr<ByteCodeFunction> result(new ByteCodeFunction(&f.fDeclaration));
std::unique_ptr<ByteCodeFunction> 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<ByteCodeFunction> 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;
}

View File

@ -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;

View File

@ -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<Statement>& s : f.fBody->as<Block>().children()) {
for (const std::unique_ptr<Statement>& s : f.body()->as<Block>().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<Statement>& s : f.fBody->as<Block>().children()) {
for (const std::unique_ptr<Statement>& s : f.body()->as<Block>().children()) {
this->writeStatement(*s);
this->writeLine();
}

View File

@ -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<FunctionDefinition>();
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<FunctionDefinition>();
bool dead = fn.fDeclaration.callCount() == 0 &&
fn.fDeclaration.name() != "main";
bool dead = fn.declaration().callCount() == 0 &&
fn.declaration().name() != "main";
madeChanges |= dead;
return dead;
}),

View File

@ -529,11 +529,11 @@ void Dehydrator::write(const ProgramElement& e) {
case ProgramElement::Kind::kFunction: {
const FunctionDefinition& f = e.as<FunctionDefinition>();
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<uint16_t> ordered;
for (const FunctionDeclaration* ref : f.fReferencedIntrinsics) {
for (const FunctionDeclaration* ref : f.referencedIntrinsics()) {
ordered.insert(this->symbolId(ref));
}
for (uint16_t ref : ordered) {

View File

@ -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<Statement>& stmt : f.fBody->as<Block>().children()) {
for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().children()) {
if (!stmt->isEmpty()) {
this->writeStatement(*stmt);
this->writeLine();

View File

@ -727,7 +727,7 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
fContext.fVoid_Type.get(),
/*builtin=*/false));
fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
*invokeDecl,
invokeDecl,
std::move(main)));
std::vector<std::unique_ptr<VarDeclaration>> 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<FunctionDefinition>(f.fOffset, *decl, std::move(body),
auto result = std::make_unique<FunctionDefinition>(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<const FunctionDeclaration*> intrinsics(original.fReferencedIntrinsics.begin(),
original.fReferencedIntrinsics.end());
std::vector<const FunctionDeclaration*> intrinsics(original.referencedIntrinsics().begin(),
original.referencedIntrinsics().end());
std::sort(intrinsics.begin(), intrinsics.end(),
[](const FunctionDeclaration* a, const FunctionDeclaration* b) {
if (a->isBuiltin() != b->isBuiltin()) {

View File

@ -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<Expression> resultExpr;
if (function.fDeclaration.returnType() != *fContext->fVoid_Type) {
if (function.declaration().returnType() != *fContext->fVoid_Type) {
std::unique_ptr<Expression> 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<int> 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<Block>();
const Block& body = function.body()->as<Block>();
auto inlineBlock = std::make_unique<Block>(offset, StatementArray{});
inlineBlock->children().reserve(body.children().size());
for (const std::unique_ptr<Statement>& 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<ExpressionStatement>(std::make_unique<BinaryExpression>(
@ -823,7 +823,7 @@ public:
case ProgramElement::Kind::kFunction: {
FunctionDefinition& funcDef = pe->as<FunctionDefinition>();
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());

View File

@ -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<Statement>& stmt : f.fBody->as<Block>().children()) {
for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().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<FunctionDefinition>()) {
const FunctionDefinition& def = e->as<FunctionDefinition>();
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;
}

View File

@ -83,7 +83,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
int index = 0;
for (const auto& e : fProgram.elements()) {
if (e->is<FunctionDefinition>()) {
if (&e->as<FunctionDefinition>().fDeclaration == &function) {
if (&e->as<FunctionDefinition>().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<Statement>& stmt : f.fBody->as<Block>().children()) {
if (f.declaration().name() == "main") {
for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().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<Statement>& stmt : f.fBody->as<Block>().children()) {
for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().children()) {
this->writeStatement(*stmt);
this->writeLine();
}

View File

@ -300,7 +300,7 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
refs.insert(this->symbolRef<FunctionDeclaration>(
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<ProgramElement>(result);

View File

@ -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<FunctionDefinition>();
fFunctionMap[&f.fDeclaration] = this->nextId();
fFunctionMap[&f.declaration()] = this->nextId();
break;
}
case ProgramElement::Kind::kModifiers: {

View File

@ -12,8 +12,6 @@
#include "src/sksl/ir/SkSLFunctionDeclaration.h"
#include "src/sksl/ir/SkSLProgramElement.h"
#include <unordered_set>
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<Statement> body,
std::unordered_set<const FunctionDeclaration*> 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<Statement>& body() {
return this->fStatementChildren[0];
}
const std::unique_ptr<Statement>& body() const {
return this->fStatementChildren[0];
}
const std::unordered_set<const FunctionDeclaration*>& 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<ProgramElement> clone() const override {
return std::make_unique<FunctionDefinition>(fOffset, fDeclaration,
fBody->clone(), fReferencedIntrinsics);
return std::make_unique<FunctionDefinition>(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<Statement> 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<const FunctionDeclaration*> 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;
};

View File

@ -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)

View File

@ -16,6 +16,7 @@
#include <algorithm>
#include <atomic>
#include <unordered_set>
#include <vector>
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<const FunctionDeclaration*> 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<const FunctionDeclaration*> 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;

View File

@ -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;