Flutter Engine
The Flutter Engine
SkSLFindAndDeclareBuiltinFunctions.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9#include "src/core/SkTHash.h"
19
20#include <algorithm>
21#include <cstddef>
22#include <memory>
23#include <string>
24#include <string_view>
25#include <vector>
26
27namespace SkSL {
28
29class ProgramElement;
30
32 ProgramUsage* usage = program.fUsage.get();
33 Context& context = *program.fContext;
34
35 std::vector<const FunctionDefinition*> addedBuiltins;
36 for (;;) {
37 // Find all the built-ins referenced by the program but not yet included in the code.
38 size_t numBuiltinsAtStart = addedBuiltins.size();
39 for (const auto& [symbol, count] : usage->fCallCounts) {
40 const FunctionDeclaration& fn = symbol->as<FunctionDeclaration>();
41 if (!fn.isBuiltin() || count == 0) {
42 // Not a built-in; skip it.
43 continue;
44 }
45 if (fn.intrinsicKind() == k_dFdy_IntrinsicKind) {
46 // Programs that invoke the `dFdy` intrinsic will need the RTFlip input.
47 if (!context.fConfig->fSettings.fForceNoRTFlip) {
49 }
50 }
51 if (const FunctionDefinition* builtinDef = fn.definition()) {
52 // Make sure we only add a built-in function once. We rarely add more than a handful
53 // of builtin functions, so linear search here is good enough.
54 if (std::find(addedBuiltins.begin(), addedBuiltins.end(), builtinDef) ==
55 addedBuiltins.end()) {
56 addedBuiltins.push_back(builtinDef);
57 }
58 }
59 }
60
61 if (addedBuiltins.size() == numBuiltinsAtStart) {
62 // If we didn't reference any more built-in functions than before, we're done.
63 break;
64 }
65
66 // Sort the referenced builtin functions into a consistent order; otherwise our output will
67 // become non-deterministic. The exact order isn't particularly important; we sort backwards
68 // because we add elements to the shared-elements in reverse order at the end.
69 std::sort(addedBuiltins.begin() + numBuiltinsAtStart,
70 addedBuiltins.end(),
71 [](const FunctionDefinition* aDefinition, const FunctionDefinition* bDefinition) {
72 const FunctionDeclaration& a = aDefinition->declaration();
73 const FunctionDeclaration& b = bDefinition->declaration();
74 if (a.name() != b.name()) {
75 return a.name() > b.name();
76 }
77 return a.description() > b.description();
78 });
79
80 // Update the ProgramUsage to track all these newly discovered functions.
81 int usageCallCounts = usage->fCallCounts.count();
82
83 for (size_t index = numBuiltinsAtStart; index < addedBuiltins.size(); ++index) {
84 usage->add(*addedBuiltins[index]);
85 }
86
87 if (usage->fCallCounts.count() == usageCallCounts) {
88 // If we aren't making any more unique function calls than before, we're done.
89 break;
90 }
91 }
92
93 // Insert the new functions into the program's shared elements, right at the front.
94 // They are added in reverse so that the deepest dependencies are added to the top.
95 program.fSharedElements.insert(program.fSharedElements.begin(),
96 addedBuiltins.rbegin(), addedBuiltins.rend());
97}
98
99} // namespace SkSL
int count
Definition: FontMgrTest.cpp:50
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
int find(T *array, int N, T item)
ProgramConfig * fConfig
Definition: SkSLContext.h:33
const FunctionDefinition * definition() const
IntrinsicKind intrinsicKind() const
const T & as() const
Definition: SkSLIRNode.h:133
static bool b
struct MyStruct a[10]
void FindAndDeclareBuiltinFunctions(Program &program)
static void usage(char *argv0)
ProgramSettings fSettings
std::shared_ptr< Context > fContext
Definition: SkSLProgram.h:154
std::unique_ptr< ProgramUsage > fUsage
Definition: SkSLProgram.h:155
ProgramInterface fInterface
Definition: SkSLProgram.h:165