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:
parent
3172208ad0
commit
0a5d096eeb
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}),
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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: {
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user