Code cleanup: Add isMain() accessor to FunctionDeclaration.

This returns true if the function name is `main`. We have special
treatment for functions named `main` in various places throughout the
compiler, so this accessor comes in handy fairly often.

Change-Id: I9da17648800f0385875e1e7d66aacb5f3dea3817
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/388443
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-03-24 09:19:45 -04:00 committed by Skia Commit-Bot
parent 3f5bee1a7a
commit e8da4d2757
8 changed files with 31 additions and 25 deletions

View File

@ -230,7 +230,7 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl, const Options& opti
else if (elem->is<SkSL::FunctionDefinition>()) {
const auto& func = elem->as<SkSL::FunctionDefinition>();
const SkSL::FunctionDeclaration& decl = func.declaration();
if (decl.name() == "main") {
if (decl.isMain()) {
main = &func;
}
}

View File

@ -515,7 +515,7 @@ static const char* glsltype_string(const Context& context, const Type& type) {
}
void CPPCodeGenerator::prepareHelperFunction(const FunctionDeclaration& decl) {
if (decl.isBuiltin() || decl.name() == "main") {
if (decl.isBuiltin() || decl.isMain()) {
return;
}
@ -557,7 +557,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
OutputStream* oldOut = fOut;
StringStream buffer;
fOut = &buffer;
if (decl.name() == "main") {
if (decl.isMain()) {
fInMain = true;
for (const std::unique_ptr<Statement>& s : f.body()->as<Block>().children()) {
this->writeStatement(*s);

View File

@ -541,7 +541,7 @@ bool Compiler::removeDeadFunctions(Program& program, ProgramUsage* usage) {
return false;
}
const FunctionDefinition& fn = element->as<FunctionDefinition>();
if (fn.declaration().name() == "main" || usage->get(fn.declaration()) > 0) {
if (fn.declaration().isMain() || usage->get(fn.declaration()) > 0) {
return false;
}
usage->remove(*element);

View File

@ -907,7 +907,7 @@ void IRGenerator::finalizeFunction(const FunctionDeclaration& funcDecl, Statemen
// will probably never actually be necessary.
SkASSERT(fIRGenerator->programKind() != ProgramKind::kVertex ||
!fIRGenerator->fRTAdjust ||
fFunction->name() != "main");
!fFunction->isMain());
// Verify that the return statement matches the function's return type.
ReturnStatement& returnStmt = stmt.as<ReturnStatement>();
@ -1010,6 +1010,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
return;
}
const ASTNode::FunctionData& funcData = f.getFunctionData();
bool isMain = (funcData.fName == "main");
// Check function modifiers.
this->checkModifiers(
@ -1053,8 +1054,8 @@ void IRGenerator::convertFunction(const ASTNode& f) {
}
Modifiers m = pd.fModifiers;
if (funcData.fName == "main" && (this->programKind() == ProgramKind::kRuntimeEffect ||
this->programKind() == ProgramKind::kFragmentProcessor)) {
if (isMain && (this->programKind() == ProgramKind::kRuntimeEffect ||
this->programKind() == ProgramKind::kFragmentProcessor)) {
if (i == 0) {
// We verify that the type is correct later, for now, if there is a parameter to
// a .fp or runtime-effect main(), it's supposed to be the coords:
@ -1075,7 +1076,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
};
// Check the function signature of `main`.
if (funcData.fName == "main") {
if (isMain) {
switch (this->programKind()) {
case ProgramKind::kRuntimeEffect: {
// (half4|float4) main() -or- (half4|float4) main(float2)
@ -1212,7 +1213,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
for (const Variable* param : decl->parameters()) {
fSymbolTable->addWithoutOwnership(param);
}
bool needInvocationIDWorkaround = fInvocations != -1 && funcData.fName == "main" &&
bool needInvocationIDWorkaround = fInvocations != -1 && isMain &&
!this->caps().gsInvocationsSupport();
std::unique_ptr<Block> body = this->convertBlock(*iter);
if (!body) {
@ -1221,7 +1222,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
if (needInvocationIDWorkaround) {
body = this->applyInvocationIDWorkaround(std::move(body));
}
if (ProgramKind::kVertex == this->programKind() && funcData.fName == "main" && fRTAdjust) {
if (ProgramKind::kVertex == this->programKind() && isMain && fRTAdjust) {
body->children().push_back(this->getNormalizeSkPositionCode());
}
this->finalizeFunction(*decl, body.get());
@ -2023,7 +2024,7 @@ void IRGenerator::findAndDeclareBuiltinVariables() {
const FunctionDefinition& funcDef = pe.as<FunctionDefinition>();
// We synthesize writes to sk_FragColor if main() returns a color, even if it's
// otherwise unreferenced. Check main's return type to see if it's half4.
if (funcDef.declaration().name() == "main" &&
if (funcDef.declaration().isMain() &&
funcDef.declaration().returnType() == *fGenerator->fContext.fTypes.fHalf4) {
fPreserveFragColor = true;
}

View File

@ -1457,7 +1457,7 @@ int MetalCodeGenerator::getUniformSet(const Modifiers& m) {
bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) {
fRTHeightName = fProgram.fInputs.fRTHeight ? "_globals._anonInterface0->u_skRTHeight" : "";
const char* separator = "";
if ("main" == f.name()) {
if (f.isMain()) {
switch (fProgram.fConfig->fKind) {
case ProgramKind::kFragment:
this->write("fragment Outputs fragmentMain");
@ -1587,7 +1587,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeLine(" {");
if (f.declaration().name() == "main") {
if (f.declaration().isMain()) {
this->writeGlobalInit();
this->writeLine(" Outputs _out;");
this->writeLine(" (void)_out;");
@ -1604,7 +1604,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->finishLine();
}
}
if (f.declaration().name() == "main") {
if (f.declaration().isMain()) {
// If the main function doesn't end with a return, we need to synthesize one here.
if (!is_block_ending_with_return(f.body().get())) {
this->writeReturnStatementFromMain();
@ -1891,7 +1891,7 @@ void MetalCodeGenerator::writeReturnStatementFromMain() {
}
void MetalCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
if (fCurrentFunction && fCurrentFunction->name() == "main") {
if (fCurrentFunction && fCurrentFunction->isMain()) {
if (r.expression()) {
if (r.expression()->type() == *fContext.fTypes.fHalf4) {
this->write("_out.sk_FragColor = ");

View File

@ -282,9 +282,7 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
// if the return type is float4 - injecting it unconditionally reduces the risk of an
// obscure bug.
const FunctionDeclaration& decl = f.declaration();
bool isMain = decl.name() == "main";
if (isMain) {
if (decl.isMain()) {
fCastReturnsToHalf = true;
}
@ -293,11 +291,12 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
this->writeLine();
}
if (isMain) {
if (decl.isMain()) {
fCastReturnsToHalf = false;
}
String fnName = isMain ? "main" : fCallbacks->getMangledName(String(decl.name()).c_str());
String fnName = decl.isMain() ? decl.name()
: fCallbacks->getMangledName(String(decl.name()).c_str());
// This is similar to decl.description(), but substitutes a mangled name, and handles modifiers
// on the function (e.g. `inline`) and its parameters (e.g. `inout`).
@ -320,7 +319,7 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
declString.append(")");
fFunctionNames.insert({&decl, std::move(fnName)});
fCallbacks->defineFunction(declString.c_str(), body.fBuffer.str().c_str(), isMain);
fCallbacks->defineFunction(declString.c_str(), body.fBuffer.str().c_str(), decl.isMain());
}
void PipelineStageCodeGenerator::writeGlobalVarDeclaration(const GlobalVarDeclaration& g) {

View File

@ -2713,7 +2713,7 @@ SpvId SPIRVCodeGenerator::writeFunction(const FunctionDefinition& f, OutputStrea
StringStream bodyBuffer;
this->writeBlock(f.body()->as<Block>(), bodyBuffer);
write_stringstream(fVariableBuffer, out);
if (f.declaration().name() == "main") {
if (f.declaration().isMain()) {
write_stringstream(fGlobalInitializersBuffer, out);
}
write_stringstream(bodyBuffer, out);
@ -3314,7 +3314,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
const FunctionDefinition& funcDef = e->as<FunctionDefinition>();
const FunctionDeclaration& funcDecl = funcDef.declaration();
fFunctionMap[&funcDecl] = this->nextId(nullptr);
if (funcDecl.name() == "main") {
if (funcDecl.isMain()) {
main = &funcDecl;
}
}

View File

@ -35,7 +35,8 @@ public:
, fModifiers(modifiers)
, fParameters(std::move(parameters))
, fReturnType(returnType)
, fBuiltin(builtin) {}
, fBuiltin(builtin)
, fIsMain(name == "main") {}
const Modifiers& modifiers() const {
return *fModifiers;
@ -61,8 +62,12 @@ public:
return fBuiltin;
}
bool isMain() const {
return fIsMain;
}
String mangledName() const {
if ((this->isBuiltin() && !this->definition()) || this->name() == "main") {
if ((this->isBuiltin() && !this->definition()) || this->isMain()) {
// Builtins without a definition (like `sin` or `sqrt`) must use their real names.
return this->name();
}
@ -175,6 +180,7 @@ private:
std::vector<const Variable*> fParameters;
const Type* fReturnType;
bool fBuiltin;
bool fIsMain;
using INHERITED = Symbol;
};