Flutter Engine
The Flutter Engine
Classes | Public Member Functions | List of all members
SkSL::Inliner Class Reference

#include <SkSLInliner.h>

Public Member Functions

 Inliner (const Context *context)
 
bool analyze (const std::vector< std::unique_ptr< ProgramElement > > &elements, SymbolTable *symbols, ProgramUsage *usage)
 

Detailed Description

Converts a FunctionCall in the IR to a set of statements to be injected ahead of the function call, and a replacement expression. Can also detect cases where inlining isn't cleanly possible (e.g. return statements nested inside of a loop construct). The inliner isn't able to guarantee identical-to-GLSL execution order if the inlined function has visible side effects.

Definition at line 44 of file SkSLInliner.h.

Constructor & Destructor Documentation

◆ Inliner()

SkSL::Inliner::Inliner ( const Context context)
inline

Definition at line 46 of file SkSLInliner.h.

46: fContext(context) {}

Member Function Documentation

◆ analyze()

bool SkSL::Inliner::analyze ( const std::vector< std::unique_ptr< ProgramElement > > &  elements,
SymbolTable symbols,
ProgramUsage usage 
)

Inlines any eligible functions that are found. Returns true if any changes are made.

Definition at line 1080 of file SkSLInliner.cpp.

1082 {
1083 // A threshold of zero indicates that the inliner is completely disabled, so we can just return.
1084 if (this->settings().fInlineThreshold <= 0) {
1085 return false;
1086 }
1087
1088 // Enforce a limit on inlining to avoid pathological cases. (inliner/ExponentialGrowth.sksl)
1089 if (fInlinedStatementCounter >= kInlinedStatementLimit) {
1090 return false;
1091 }
1092
1093 InlineCandidateList candidateList;
1094 this->buildCandidateList(elements, symbols, usage, &candidateList);
1095
1096 // Inline the candidates where we've determined that it's safe to do so.
1097 using StatementRemappingTable = THashMap<std::unique_ptr<Statement>*,
1098 std::unique_ptr<Statement>*>;
1099 StatementRemappingTable statementRemappingTable;
1100
1101 bool madeChanges = false;
1102 for (const InlineCandidate& candidate : candidateList.fCandidates) {
1103 const FunctionCall& funcCall = (*candidate.fCandidateExpr)->as<FunctionCall>();
1104
1105 // Convert the function call to its inlined equivalent.
1106 InlinedCall inlinedCall = this->inlineCall(funcCall, candidate.fSymbols, *usage,
1107 &candidate.fEnclosingFunction->declaration());
1108
1109 // Stop if an error was detected during the inlining process.
1110 if (!inlinedCall.fInlinedBody && !inlinedCall.fReplacementExpr) {
1111 break;
1112 }
1113
1114 // Ensure that the inlined body has a scope if it needs one.
1115 this->ensureScopedBlocks(inlinedCall.fInlinedBody.get(), candidate.fParentStmt->get());
1116
1117 // Add references within the inlined body
1118 usage->add(inlinedCall.fInlinedBody.get());
1119
1120 // Look up the enclosing statement; remap it if necessary.
1121 std::unique_ptr<Statement>* enclosingStmt = candidate.fEnclosingStmt;
1122 for (;;) {
1123 std::unique_ptr<Statement>** remappedStmt = statementRemappingTable.find(enclosingStmt);
1124 if (!remappedStmt) {
1125 break;
1126 }
1127 enclosingStmt = *remappedStmt;
1128 }
1129
1130 // Move the enclosing statement to the end of the unscoped Block containing the inlined
1131 // function, then replace the enclosing statement with that Block.
1132 // Before:
1133 // fInlinedBody = Block{ stmt1, stmt2, stmt3 }
1134 // fEnclosingStmt = stmt4
1135 // After:
1136 // fInlinedBody = null
1137 // fEnclosingStmt = Block{ stmt1, stmt2, stmt3, stmt4 }
1138 inlinedCall.fInlinedBody->children().push_back(std::move(*enclosingStmt));
1139 *enclosingStmt = std::move(inlinedCall.fInlinedBody);
1140
1141 // Replace the candidate function call with our replacement expression.
1142 usage->remove(candidate.fCandidateExpr->get());
1143 usage->add(inlinedCall.fReplacementExpr.get());
1144 *candidate.fCandidateExpr = std::move(inlinedCall.fReplacementExpr);
1145 madeChanges = true;
1146
1147 // If anything else pointed at our enclosing statement, it's now pointing at a Block
1148 // containing many other statements as well. Maintain a fix-up table to account for this.
1149 statementRemappingTable.set(enclosingStmt,&(*enclosingStmt)->as<Block>().children().back());
1150
1151 // Stop inlining if we've reached our hard cap on new statements.
1152 if (fInlinedStatementCounter >= kInlinedStatementLimit) {
1153 break;
1154 }
1155
1156 // Note that nothing was destroyed except for the FunctionCall. All other nodes should
1157 // remain valid.
1158 }
1159
1160 return madeChanges;
1161}
V * find(const K &key) const
Definition: SkTHash.h:494
static void usage(char *argv0)

The documentation for this class was generated from the following files: