10#ifndef SK_ENABLE_OPTIMIZE_SIZE
80static constexpr int kInlinedStatementLimit = 2500;
82static bool is_scopeless_block(Statement* stmt) {
83 return stmt->is<
Block>() && !stmt->as<
Block>().isScope();
86static std::unique_ptr<Statement>* find_parent_statement(
87 const std::vector<std::unique_ptr<Statement>*>& stmtStack) {
92 auto iter = stmtStack.rbegin();
96 for (; iter != stmtStack.rend(); ++iter) {
97 std::unique_ptr<Statement>* stmt = *iter;
98 if (!is_scopeless_block(stmt->get())) {
107std::unique_ptr<Expression> clone_with_ref_kind(
const Expression& expr,
110 std::unique_ptr<Expression> clone = expr.clone(
pos);
117const Variable* Inliner::RemapVariable(
const Variable* variable,
118 const VariableRewriteMap* varMap) {
119 std::unique_ptr<Expression>* remap = varMap->find(variable);
121 SkDEBUGFAILF(
"rewrite map does not contain variable '%.*s'",
122 (
int)variable->name().size(), variable->name().data());
125 Expression* expr = remap->get();
127 if (!expr->is<VariableReference>()) {
128 SkDEBUGFAILF(
"rewrite map contains non-variable replacement for '%.*s'",
129 (
int)variable->name().size(), variable->name().data());
132 return expr->as<VariableReference>().variable();
135void Inliner::ensureScopedBlocks(Statement* inlinedBody, Statement* parentStmt) {
137 if (!inlinedBody || !inlinedBody->is<
Block>()) {
142 if (!parentStmt || !(parentStmt->is<IfStatement>() || parentStmt->is<ForStatement>() ||
143 parentStmt->is<DoStatement>() || is_scopeless_block(parentStmt))) {
154 for (
Block* nestedBlock = █; ) {
155 if (nestedBlock->isScope()) {
159 if (nestedBlock->children().size() == 1 && nestedBlock->children()[0]->is<
Block>()) {
161 nestedBlock = &nestedBlock->children()[0]->as<
Block>();
166 block.setBlockKind(Block::Kind::kBracedScope);
171std::unique_ptr<Expression> Inliner::inlineExpression(Position
pos,
172 VariableRewriteMap* varMap,
173 SymbolTable* symbolTableForExpression,
174 const Expression& expression) {
175 auto expr = [&](
const std::unique_ptr<Expression>&
e) -> std::unique_ptr<Expression> {
177 return this->inlineExpression(
pos, varMap, symbolTableForExpression, *
e);
181 auto argList = [&](
const ExpressionArray& originalArgs) -> ExpressionArray {
182 ExpressionArray
args;
183 args.reserve_exact(originalArgs.size());
184 for (
const std::unique_ptr<Expression>& arg : originalArgs) {
185 args.push_back(expr(arg));
190 switch (expression.kind()) {
191 case Expression::Kind::kBinary: {
192 const BinaryExpression& binaryExpr = expression.as<BinaryExpression>();
195 expr(binaryExpr.left()),
196 binaryExpr.getOperator(),
197 expr(binaryExpr.right()));
200 return expression.clone(
pos);
202 return expression.clone(
pos);
203 case Expression::Kind::kChildCall: {
204 const ChildCall& childCall = expression.as<ChildCall>();
207 childCall.type().clone(*fContext, symbolTableForExpression),
209 argList(childCall.arguments()));
211 case Expression::Kind::kConstructorArray: {
212 const ConstructorArray& ctor = expression.as<ConstructorArray>();
215 *ctor.type().clone(*fContext, symbolTableForExpression),
216 argList(ctor.arguments()));
218 case Expression::Kind::kConstructorArrayCast: {
219 const ConstructorArrayCast& ctor = expression.as<ConstructorArrayCast>();
223 *ctor.type().clone(*fContext, symbolTableForExpression),
224 expr(ctor.argument()));
226 case Expression::Kind::kConstructorCompound: {
227 const ConstructorCompound& ctor = expression.as<ConstructorCompound>();
231 *ctor.type().clone(*fContext, symbolTableForExpression),
232 argList(ctor.arguments()));
234 case Expression::Kind::kConstructorCompoundCast: {
235 const ConstructorCompoundCast& ctor = expression.as<ConstructorCompoundCast>();
239 *ctor.type().clone(*fContext, symbolTableForExpression),
240 expr(ctor.argument()));
242 case Expression::Kind::kConstructorDiagonalMatrix: {
243 const ConstructorDiagonalMatrix& ctor = expression.as<ConstructorDiagonalMatrix>();
247 *ctor.type().clone(*fContext, symbolTableForExpression),
248 expr(ctor.argument()));
250 case Expression::Kind::kConstructorMatrixResize: {
251 const ConstructorMatrixResize& ctor = expression.as<ConstructorMatrixResize>();
255 *ctor.type().clone(*fContext, symbolTableForExpression),
256 expr(ctor.argument()));
258 case Expression::Kind::kConstructorScalarCast: {
259 const ConstructorScalarCast& ctor = expression.as<ConstructorScalarCast>();
263 *ctor.type().clone(*fContext, symbolTableForExpression),
264 expr(ctor.argument()));
266 case Expression::Kind::kConstructorSplat: {
267 const ConstructorSplat& ctor = expression.as<ConstructorSplat>();
270 *ctor.type().clone(*fContext, symbolTableForExpression),
271 expr(ctor.argument()));
273 case Expression::Kind::kConstructorStruct: {
274 const ConstructorStruct& ctor = expression.as<ConstructorStruct>();
277 *ctor.type().clone(*fContext, symbolTableForExpression),
278 argList(ctor.arguments()));
280 case Expression::Kind::kFieldAccess: {
281 const FieldAccess&
f = expression.as<FieldAccess>();
284 case Expression::Kind::kFunctionCall: {
285 const FunctionCall& funcCall = expression.as<FunctionCall>();
288 funcCall.type().clone(*fContext, symbolTableForExpression),
290 argList(funcCall.arguments()));
292 case Expression::Kind::kFunctionReference:
293 return expression.clone(
pos);
295 const IndexExpression& idx = expression.as<IndexExpression>();
298 case Expression::Kind::kMethodReference:
299 return expression.clone(
pos);
300 case Expression::Kind::kPrefix: {
301 const PrefixExpression&
p = expression.as<PrefixExpression>();
304 case Expression::Kind::kPostfix: {
305 const PostfixExpression&
p = expression.as<PostfixExpression>();
308 case Expression::Kind::kSetting: {
309 const Setting&
s = expression.as<Setting>();
312 case Expression::Kind::kSwizzle: {
313 const Swizzle&
s = expression.as<Swizzle>();
316 case Expression::Kind::kTernary: {
317 const TernaryExpression& t = expression.as<TernaryExpression>();
319 expr(t.ifTrue()), expr(t.ifFalse()));
321 case Expression::Kind::kTypeReference:
322 return expression.clone(
pos);
323 case Expression::Kind::kVariableReference: {
324 const VariableReference& v = expression.as<VariableReference>();
325 std::unique_ptr<Expression>* remap = varMap->find(v.variable());
327 return clone_with_ref_kind(**remap, v.refKind(),
pos);
329 return expression.clone(
pos);
332 SkDEBUGFAILF(
"unsupported expression: %s", expression.description().c_str());
337std::unique_ptr<Statement> Inliner::inlineStatement(Position
pos,
338 VariableRewriteMap* varMap,
339 SymbolTable* symbolTableForStatement,
340 std::unique_ptr<Expression>* resultExpr,
342 const Statement& statement,
343 const ProgramUsage&
usage,
344 bool isBuiltinCode) {
345 auto stmt = [&](
const std::unique_ptr<Statement>&
s) -> std::unique_ptr<Statement> {
347 return this->inlineStatement(
pos, varMap, symbolTableForStatement, resultExpr,
348 returnComplexity, *
s,
usage, isBuiltinCode);
352 auto expr = [&](
const std::unique_ptr<Expression>&
e) -> std::unique_ptr<Expression> {
354 return this->inlineExpression(
pos, varMap, symbolTableForStatement, *
e);
358 auto variableModifiers = [&](
const Variable& variable,
359 const Expression* initialValue) -> ModifierFlags {
362 auto makeWithChildSymbolTable = [&](
auto callback) -> std::unique_ptr<Statement> {
363 SymbolTable* origSymbolTable = symbolTableForStatement;
364 auto childSymbols = std::make_unique<SymbolTable>(origSymbolTable, isBuiltinCode);
365 symbolTableForStatement = childSymbols.get();
367 std::unique_ptr<Statement> stmt =
callback(std::move(childSymbols));
369 symbolTableForStatement = origSymbolTable;
373 ++fInlinedStatementCounter;
375 switch (statement.kind()) {
376 case Statement::Kind::kBlock:
377 return makeWithChildSymbolTable([&](std::unique_ptr<SymbolTable> symbolTable) {
381 for (
const std::unique_ptr<Statement>& child : block.children()) {
382 statements.push_back(stmt(child));
385 std::move(statements),
387 std::move(symbolTable));
390 case Statement::Kind::kBreak:
399 case Statement::Kind::kDo: {
400 const DoStatement&
d = statement.as<DoStatement>();
403 case Statement::Kind::kExpression: {
404 const ExpressionStatement&
e = statement.as<ExpressionStatement>();
407 case Statement::Kind::kFor:
408 return makeWithChildSymbolTable([&](std::unique_ptr<SymbolTable> symbolTable) {
409 const ForStatement&
f = statement.as<ForStatement>();
412 std::unique_ptr<Statement> initializerStmt = stmt(
f.initializer());
413 std::unique_ptr<Expression> testExpr = expr(
f.test());
414 std::unique_ptr<Expression> nextExpr = expr(
f.next());
415 std::unique_ptr<Statement> bodyStmt = stmt(
f.statement());
417 std::unique_ptr<LoopUnrollInfo> unrollInfo;
418 if (
f.unrollInfo()) {
422 unrollInfo = std::make_unique<LoopUnrollInfo>(*
f.unrollInfo());
423 unrollInfo->fIndex = RemapVariable(unrollInfo->fIndex, varMap);
427 std::move(initializerStmt),
431 std::move(unrollInfo),
432 std::move(symbolTable));
435 case Statement::Kind::kIf: {
436 const IfStatement&
i = statement.as<IfStatement>();
438 stmt(
i.ifTrue()), stmt(
i.ifFalse()));
443 case Statement::Kind::kReturn: {
444 const ReturnStatement& r = statement.as<ReturnStatement>();
445 if (!r.expression()) {
456 *resultExpr = expr(r.expression());
471 expr(r.expression())));
473 case Statement::Kind::kSwitch: {
474 const SwitchStatement& ss = statement.as<SwitchStatement>();
477 case Statement::Kind::kSwitchCase: {
478 const SwitchCase& sc = statement.as<SwitchCase>();
480 : SwitchCase::
Make(
pos, sc.
value(), stmt(sc.statement()));
482 case Statement::Kind::kVarDeclaration: {
483 const VarDeclaration& decl = statement.as<VarDeclaration>();
484 std::unique_ptr<Expression> initialValue = expr(decl.value());
485 const Variable* variable = decl.var();
490 const std::string*
name = symbolTableForStatement->takeOwnershipOfString(
491 fMangler.
uniqueName(variable->name(), symbolTableForStatement));
494 variable->modifiersPosition(),
496 variableModifiers(*variable, initialValue.get()),
497 variable->type().clone(*fContext, symbolTableForStatement),
501 variable->storage());
503 std::unique_ptr<Statement>
result =
506 decl.baseType().clone(*fContext, symbolTableForStatement),
508 std::move(initialValue));
509 symbolTableForStatement->add(*fContext, std::move(clonedVar));
536Inliner::InlinedCall Inliner::inlineCall(
const FunctionCall&
call,
537 SymbolTable* symbolTable,
538 const ProgramUsage&
usage,
539 const FunctionDeclaration* caller) {
540 using ScratchVariable = Variable::ScratchVariable;
552 const ExpressionArray& arguments =
call.arguments();
553 const Position
pos =
call.fPosition;
554 const FunctionDefinition&
function = *
call.function().definition();
559 int expectedStmtCount = 1 +
561 body.children().size();
563 inlineStatements.reserve_exact(expectedStmtCount);
565 std::unique_ptr<Expression> resultExpr;
567 !
function.declaration().returnType().isVoid()) {
574 &
function.declaration().returnType(),
577 inlineStatements.push_back(std::move(var.fVarDecl));
583 VariableRewriteMap varMap;
584 for (
int i = 0;
i < arguments.size(); ++
i) {
585 const Expression* arg = arguments[
i].get();
586 const Variable* param =
function.declaration().parameters()[
i];
588 varMap.set(param, arg->clone());
597 inlineStatements.push_back(std::move(var.fVarDecl));
601 for (
const std::unique_ptr<Statement>& stmt : body.children()) {
602 inlineStatements.push_back(this->inlineStatement(
pos, &varMap, symbolTable,
603 &resultExpr, returnComplexity, *stmt,
604 usage, caller->isBuiltin()));
607 SkASSERT(inlineStatements.size() <= expectedStmtCount);
611 InlinedCall inlinedCall;
613 Block::Kind::kUnbracedBlock);
616 inlinedCall.fReplacementExpr = std::move(resultExpr);
617 }
else if (
function.declaration().returnType().isVoid()) {
624 SkDEBUGFAIL(
"inliner found non-void function that fails to return a value on any path");
626 std::string(
function.declaration().name()) +
627 "' that fails to return a value on any path");
634bool Inliner::isSafeToInline(
const FunctionDefinition* functionDef,
const ProgramUsage&
usage) {
636 if (this->settings().fInlineThreshold <= 0) {
641 if (fInlinedStatementCounter >= kInlinedStatementLimit) {
645 if (functionDef ==
nullptr) {
650 if (functionDef->declaration().modifierFlags().isNoInline()) {
655 for (
const Variable* param : functionDef->declaration().parameters()) {
660 param->type().isArray() ||
661 param->type().isStruct()) {
662 ProgramUsage::VariableCounts
counts =
usage.get(*param);
701 void visit(
const std::vector<std::unique_ptr<ProgramElement>>& elements,
707 for (
const std::unique_ptr<ProgramElement>& pe : elements) {
716 switch (pe->
kind()) {
722 bool foundShadowingParameterName =
false;
725 foundShadowingParameterName =
true;
730 if (!foundShadowingParameterName) {
743 bool isViableAsEnclosingStatement =
true) {
758 if (isViableAsEnclosingStatement) {
762 switch ((*stmt)->kind()) {
763 case Statement::Kind::kBreak:
769 case Statement::Kind::kBlock: {
771 for (std::unique_ptr<Statement>& blockStmt : block.
children()) {
776 case Statement::Kind::kDo: {
791 case Statement::Kind::kExpression: {
796 case Statement::Kind::kFor: {
819 case Statement::Kind::kIf: {
826 case Statement::Kind::kReturn: {
831 case Statement::Kind::kSwitch: {
834 for (
const std::unique_ptr<Statement>& switchCase : switchStmt.
cases()) {
840 case Statement::Kind::kVarDeclaration: {
859 switch ((*expr)->kind()) {
860 case Expression::Kind::kFieldAccess:
861 case Expression::Kind::kFunctionReference:
863 case Expression::Kind::kMethodReference:
864 case Expression::Kind::kSetting:
865 case Expression::Kind::kTypeReference:
866 case Expression::Kind::kVariableReference:
870 case Expression::Kind::kBinary: {
883 bool shortCircuitable = (op.
kind() == Operator::Kind::LOGICALAND ||
884 op.
kind() == Operator::Kind::LOGICALOR);
885 if (!shortCircuitable) {
890 case Expression::Kind::kChildCall: {
892 for (std::unique_ptr<Expression>& arg : childCallExpr.
arguments()) {
897 case Expression::Kind::kConstructorArray:
898 case Expression::Kind::kConstructorArrayCast:
899 case Expression::Kind::kConstructorCompound:
900 case Expression::Kind::kConstructorCompoundCast:
901 case Expression::Kind::kConstructorDiagonalMatrix:
902 case Expression::Kind::kConstructorMatrixResize:
903 case Expression::Kind::kConstructorScalarCast:
904 case Expression::Kind::kConstructorSplat:
905 case Expression::Kind::kConstructorStruct: {
907 for (std::unique_ptr<Expression>& arg : constructorExpr.
argumentSpan()) {
912 case Expression::Kind::kFunctionCall: {
914 for (std::unique_ptr<Expression>& arg : funcCallExpr.
arguments()) {
926 case Expression::Kind::kPostfix: {
931 case Expression::Kind::kPrefix: {
936 case Expression::Kind::kSwizzle: {
941 case Expression::Kind::kTernary: {
968bool Inliner::functionCanBeInlined(
const FunctionDeclaration& funcDecl,
969 const ProgramUsage&
usage,
970 InlinabilityCache*
cache) {
971 if (
const bool* cachedInlinability =
cache->find(&funcDecl)) {
972 return *cachedInlinability;
974 bool inlinability = this->isSafeToInline(funcDecl.definition(),
usage);
975 cache->set(&funcDecl, inlinability);
979bool Inliner::candidateCanBeInlined(
const InlineCandidate& candidate,
980 const ProgramUsage&
usage,
981 InlinabilityCache*
cache) {
984 if (!this->functionCanBeInlined(funcDecl,
usage,
cache)) {
991 const FunctionCall&
call = candidate.fCandidateExpr->get()->as<FunctionCall>();
992 const ExpressionArray& arguments =
call.arguments();
993 for (
int i = 0;
i < arguments.size(); ++
i) {
994 const Expression* arg = arguments[
i].get();
995 if (arg->type().isOpaque()) {
996 const Variable* param = funcDecl.parameters()[
i];
1006int Inliner::getFunctionSize(
const FunctionDeclaration& funcDecl, FunctionSizeCache*
cache) {
1007 if (
const int* cachedSize =
cache->find(&funcDecl)) {
1011 this->settings().fInlineThreshold);
1016void Inliner::buildCandidateList(
const std::vector<std::unique_ptr<ProgramElement>>& elements,
1018 ProgramUsage*
usage,
1019 InlineCandidateList* candidateList) {
1024 InlineCandidateAnalyzer analyzer;
1025 analyzer.visit(elements,
symbols, candidateList);
1028 std::vector<InlineCandidate>& candidates = candidateList->fCandidates;
1029 if (candidates.empty()) {
1034 InlinabilityCache
cache;
1035 candidates.erase(std::remove_if(candidates.begin(),
1037 [&](
const InlineCandidate& candidate) {
1038 return !this->candidateCanBeInlined(
1039 candidate, *usage, &cache);
1045 if (this->settings().fInlineThreshold == INT_MAX || candidates.empty()) {
1052 FunctionSizeCache functionSizeCache;
1053 FunctionSizeCache candidateTotalCost;
1054 for (InlineCandidate& candidate : candidates) {
1056 candidateTotalCost[&fnDecl] += this->getFunctionSize(fnDecl, &functionSizeCache);
1059 candidates.erase(std::remove_if(candidates.begin(), candidates.end(),
1060 [&](
const InlineCandidate& candidate) {
1061 const FunctionDeclaration& fnDecl = candidate_func(candidate);
1062 if (fnDecl.modifierFlags().isInline()) {
1066 if (
usage->get(fnDecl) == 1) {
1070 if (candidateTotalCost[&fnDecl] <= this->settings().fInlineThreshold) {
1084 if (this->
settings().fInlineThreshold <= 0) {
1089 if (fInlinedStatementCounter >= kInlinedStatementLimit) {
1094 this->buildCandidateList(elements,
symbols,
usage, &candidateList);
1098 std::unique_ptr<Statement>*>;
1099 StatementRemappingTable statementRemappingTable;
1101 bool madeChanges =
false;
1106 InlinedCall inlinedCall = this->inlineCall(funcCall, candidate.
fSymbols, *
usage,
1110 if (!inlinedCall.fInlinedBody && !inlinedCall.fReplacementExpr) {
1115 this->ensureScopedBlocks(inlinedCall.fInlinedBody.get(), candidate.
fParentStmt->get());
1118 usage->add(inlinedCall.fInlinedBody.get());
1121 std::unique_ptr<Statement>* enclosingStmt = candidate.
fEnclosingStmt;
1123 std::unique_ptr<Statement>** remappedStmt = statementRemappingTable.
find(enclosingStmt);
1124 if (!remappedStmt) {
1127 enclosingStmt = *remappedStmt;
1138 inlinedCall.fInlinedBody->children().push_back(std::move(*enclosingStmt));
1139 *enclosingStmt = std::move(inlinedCall.fInlinedBody);
1143 usage->add(inlinedCall.fReplacementExpr.get());
1144 *candidate.
fCandidateExpr = std::move(inlinedCall.fReplacementExpr);
1149 statementRemappingTable.set(enclosingStmt,&(*enclosingStmt)->as<
Block>().
children().
back());
1152 if (fInlinedStatementCounter >= kInlinedStatementLimit) {
#define SkDEBUGFAIL(message)
#define SkDEBUGFAILF(fmt,...)
virtual SkSpan< std::unique_ptr< Expression > > argumentSpan()=0
std::unique_ptr< Expression > & left()
std::unique_ptr< Expression > & right()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > left, Operator op, std::unique_ptr< Expression > right)
Operator getOperator() const
const StatementArray & children() const
static std::unique_ptr< Statement > Make(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
static std::unique_ptr< Block > MakeBlock(Position pos, StatementArray statements, Kind kind=Kind::kBracedScope, std::unique_ptr< SymbolTable > symbols=nullptr)
static std::unique_ptr< Statement > Make(Position pos)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type *returnType, const Variable &child, ExpressionArray arguments)
ExpressionArray & arguments()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, ExpressionArray args)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, ExpressionArray args)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, std::unique_ptr< Expression > arg)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type &type, ExpressionArray args)
static std::unique_ptr< Statement > Make(Position pos)
static std::unique_ptr< Statement > Make(const Context &context, Position pos)
static std::unique_ptr< Statement > Make(const Context &context, Position pos, std::unique_ptr< Statement > stmt, std::unique_ptr< Expression > test)
std::unique_ptr< Statement > & statement()
static std::unique_ptr< Expression > Make(Position pos, const Context &context)
void error(Position position, std::string_view msg)
static std::unique_ptr< Statement > Make(const Context &context, std::unique_ptr< Expression > expr)
const std::unique_ptr< Expression > & expression() const
AnyConstructor & asAnyConstructor()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > base, int fieldIndex, OwnerKind ownerKind=OwnerKind::kDefault)
std::unique_ptr< Statement > & statement()
static std::unique_ptr< Statement > Make(const Context &context, Position pos, ForLoopPositions forLoopPositions, std::unique_ptr< Statement > initializer, std::unique_ptr< Expression > test, std::unique_ptr< Expression > next, std::unique_ptr< Statement > statement, std::unique_ptr< LoopUnrollInfo > unrollInfo, std::unique_ptr< SymbolTable > symbolTable)
std::unique_ptr< Statement > & initializer()
ExpressionArray & arguments()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, const Type *returnType, const FunctionDeclaration &function, ExpressionArray arguments)
SkSpan< Variable *const > parameters() const
std::unique_ptr< Statement > & body()
const FunctionDeclaration & declaration() const
static std::unique_ptr< Statement > Make(const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Statement > ifTrue, std::unique_ptr< Statement > ifFalse)
std::unique_ptr< Expression > & test()
std::unique_ptr< Statement > & ifTrue()
std::unique_ptr< Statement > & ifFalse()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > base, std::unique_ptr< Expression > index)
std::unique_ptr< Expression > & base()
std::unique_ptr< Expression > & index()
InlineCandidateList * fCandidateList
void addInlineCandidate(std::unique_ptr< Expression > *candidate)
std::vector< SymbolTable * > fSymbolTableStack
void visit(const std::vector< std::unique_ptr< ProgramElement > > &elements, SymbolTable *symbols, InlineCandidateList *candidateList)
FunctionDefinition * fEnclosingFunction
void visitStatement(std::unique_ptr< Statement > *stmt, bool isViableAsEnclosingStatement=true)
void visitProgramElement(ProgramElement *pe)
std::vector< std::unique_ptr< Statement > * > fEnclosingStmtStack
void visitExpression(std::unique_ptr< Expression > *expr)
std::string uniqueName(std::string_view baseName, SymbolTable *symbolTable)
static std::unique_ptr< Statement > Make()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > base, Operator op)
std::unique_ptr< Expression > & operand()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, Operator op, std::unique_ptr< Expression > base)
std::unique_ptr< Expression > & operand()
std::unique_ptr< Expression > & expression()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, CapsPtr capsPtr)
static std::unique_ptr< SwitchCase > MakeDefault(Position pos, std::unique_ptr< Statement > statement)
std::unique_ptr< Statement > & statement()
std::unique_ptr< Expression > & value()
static std::unique_ptr< Statement > Make(const Context &context, Position pos, std::unique_ptr< Expression > value, std::unique_ptr< Statement > caseBlock)
std::unique_ptr< Expression > & base()
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > expr, ComponentArray inComponents)
static std::unique_ptr< Expression > Make(const Context &context, Position pos, std::unique_ptr< Expression > test, std::unique_ptr< Expression > ifTrue, std::unique_ptr< Expression > ifFalse)
std::unique_ptr< Expression > & test()
std::unique_ptr< Expression > & value()
static std::unique_ptr< VarDeclaration > Make(const Context &context, Variable *var, const Type *baseType, int arraySize, std::unique_ptr< Expression > value)
static std::unique_ptr< Expression > Make(Position pos, const Variable *variable, RefKind refKind=RefKind::kRead)
static std::unique_ptr< Variable > Make(Position pos, Position modifiersPosition, const Layout &layout, ModifierFlags flags, const Type *type, std::string_view name, std::string mangledName, bool builtin, Storage storage)
static ScratchVariable MakeScratchVariable(const Context &context, Mangler &mangler, std::string_view baseName, const Type *type, SymbolTable *symbolTable, std::unique_ptr< Expression > initialValue)
void reserve_exact(int n)
V * find(const K &key) const
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Dart_NativeFunction function
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
ReturnComplexity GetReturnComplexity(const FunctionDefinition &funcDef)
int NodeCountUpToLimit(const FunctionDefinition &function, int limit)
bool IsTrivialExpression(const Expression &expr)
bool HasSideEffects(const Expression &expr)
bool UpdateVariableRefKind(Expression *expr, VariableRefKind kind, ErrorReporter *errors=nullptr)
static bool argument_needs_scratch_variable(const Expression *arg, const Variable *param, const ProgramUsage &usage)
static const FunctionDeclaration & candidate_func(const InlineCandidate &candidate)
skia_private::STArray< 2, std::unique_ptr< Statement > > StatementArray
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core counts
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static void usage(char *argv0)
std::vector< InlineCandidate > fCandidates
FunctionDefinition * fEnclosingFunction
std::unique_ptr< Expression > * fCandidateExpr
std::unique_ptr< Statement > * fEnclosingStmt
std::unique_ptr< Statement > * fParentStmt