43class ProgramUsageVisitor :
public ProgramVisitor {
47 bool visitProgramElement(
const ProgramElement& pe)
override {
48 if (pe.is<FunctionDefinition>()) {
49 for (
const Variable* param : pe.as<FunctionDefinition>().declaration().parameters()) {
53 ProgramUsage::VariableCounts&
counts =
fUsage->fVariableCounts[param];
54 counts.fVarExists += fDelta;
56 this->visitType(param->type());
58 }
else if (pe.is<InterfaceBlock>()) {
60 const Variable* var = pe.as<InterfaceBlock>().var();
61 fUsage->fVariableCounts[var];
63 this->visitType(var->type());
64 }
else if (pe.is<StructDefinition>()) {
66 this->visitStructFields(pe.as<StructDefinition>().type());
68 return INHERITED::visitProgramElement(pe);
71 bool visitStatement(
const Statement&
s)
override {
72 if (
s.is<VarDeclaration>()) {
74 const VarDeclaration& vd =
s.as<VarDeclaration>();
75 const Variable* var = vd.var();
76 ProgramUsage::VariableCounts&
counts =
fUsage->fVariableCounts[var];
77 counts.fVarExists += fDelta;
83 this->visitType(var->type());
85 return INHERITED::visitStatement(
s);
88 bool visitExpression(
const Expression&
e)
override {
89 this->visitType(
e.type());
90 if (
e.is<FunctionCall>()) {
91 const FunctionDeclaration*
f = &
e.as<FunctionCall>().
function();
92 fUsage->fCallCounts[
f] += fDelta;
94 }
else if (
e.is<VariableReference>()) {
95 const VariableReference& ref =
e.as<VariableReference>();
96 ProgramUsage::VariableCounts&
counts =
fUsage->fVariableCounts[ref.variable()];
97 switch (ref.refKind()) {
112 return INHERITED::visitExpression(
e);
115 void visitType(
const Type& t) {
117 this->visitType(t.componentType());
121 int& structCount =
fUsage->fStructCounts[&t];
122 structCount += fDelta;
125 this->visitStructFields(t);
129 void visitStructFields(
const Type& t) {
130 for (
const Field&
f : t.fields()) {
131 this->visitType(*
f.fType);
146 auto usage = std::make_unique<ProgramUsage>();
147 ProgramUsageVisitor addRefs(
usage.get(), +1);
148 addRefs.visit(program);
153 auto usage = std::make_unique<ProgramUsage>();
154 ProgramUsageVisitor addRefs(
usage.get(), +1);
156 for (
const Module*
m = &module;
m !=
nullptr;
m =
m->fParent) {
157 for (
const std::unique_ptr<ProgramElement>& element :
m->fElements) {
158 addRefs.visitProgramElement(*element);
191 ProgramUsageVisitor addRefs(
this, +1);
192 addRefs.visitExpression(*expr);
196 ProgramUsageVisitor addRefs(
this, +1);
197 addRefs.visitStatement(*stmt);
201 ProgramUsageVisitor addRefs(
this, +1);
202 addRefs.visitProgramElement(element);
206 ProgramUsageVisitor subRefs(
this, -1);
207 subRefs.visitExpression(*expr);
211 ProgramUsageVisitor subRefs(
this, -1);
212 subRefs.visitStatement(*stmt);
216 ProgramUsageVisitor subRefs(
this, -1);
217 subRefs.visitProgramElement(element);
221 constexpr bool kReportMismatch =
false;
223 for (
const auto& [varA, varCountA] :
a.fVariableCounts) {
225 if (!varCountA.fVarExists && !varCountA.fRead && !varCountA.fWrite) {
230 if (!varCountB || 0 != memcmp(&varCountA, varCountB,
sizeof(varCountA))) {
231 if constexpr (kReportMismatch) {
232 SkDebugf(
"VariableCounts mismatch: '%.*s' (E%d R%d W%d != E%d R%d W%d)\n",
233 (
int)varA->name().size(), varA->name().data(),
234 varCountA.fVarExists,
238 varCountB ? varCountB->
fRead : 0,
239 varCountB ? varCountB->
fWrite : 0);
245 for (
const auto& [callA, callCountA] :
a.fCallCounts) {
251 const int* callCountB =
b.fCallCounts.find(callA);
252 if (!callCountB || callCountA != *callCountB) {
253 if constexpr (kReportMismatch) {
254 SkDebugf(
"CallCounts mismatch: '%.*s' (%d != %d)\n",
255 (
int)callA->name().size(), callA->name().data(),
257 callCountB ? *callCountB : 0);
263 for (
const auto& [structA, structCountA] :
a.fStructCounts) {
269 const int* structCountB =
b.fStructCounts.find(structA);
270 if (!structCountB || structCountA != *structCountB) {
271 if constexpr (kReportMismatch) {
272 SkDebugf(
"StructCounts mismatch: '%.*s' (%d != %d)\n",
273 (
int)structA->name().size(), structA->name().data(),
275 structCountB ? *structCountB : 0);
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define INHERITED(method,...)
void add(const Expression *expr)
VariableCounts get(const Variable &) const
bool operator==(const ProgramUsage &that) const
void remove(const Expression *expr)
bool isDead(const Variable &) const
skia_private::THashMap< const Variable *, VariableCounts > fVariableCounts
skia_private::THashMap< const Symbol *, int > fCallCounts
const Type & type() const
virtual bool visitStatement(typename T::Statement &statement)
virtual bool visitProgramElement(typename T::ProgramElement &programElement)
virtual const Type & componentType() const
const Expression * initialValue() const
ModifierFlags modifierFlags() const
FlutterSemanticsFlag flags
Dart_NativeFunction function
std::unique_ptr< ProgramUsage > GetUsage(const Program &program)
static bool contains_matching_data(const ProgramUsage &a, const ProgramUsage &b)
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
static void usage(char *argv0)
const ProgramUsage * usage() const
std::unique_ptr< ProgramUsage > fUsage