/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/Utils/SymbolRewriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SymbolRewriter.cpp - Symbol Rewriter ---------------------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within |
11 | | // existing code. It is implemented as a compiler pass and is configured via a |
12 | | // YAML configuration file. |
13 | | // |
14 | | // The YAML configuration file format is as follows: |
15 | | // |
16 | | // RewriteMapFile := RewriteDescriptors |
17 | | // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors |
18 | | // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}' |
19 | | // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields |
20 | | // RewriteDescriptorField := FieldIdentifier ':' FieldValue ',' |
21 | | // RewriteDescriptorType := Identifier |
22 | | // FieldIdentifier := Identifier |
23 | | // FieldValue := Identifier |
24 | | // Identifier := [0-9a-zA-Z]+ |
25 | | // |
26 | | // Currently, the following descriptor types are supported: |
27 | | // |
28 | | // - function: (function rewriting) |
29 | | // + Source (original name of the function) |
30 | | // + Target (explicit transformation) |
31 | | // + Transform (pattern transformation) |
32 | | // + Naked (boolean, whether the function is undecorated) |
33 | | // - global variable: (external linkage global variable rewriting) |
34 | | // + Source (original name of externally visible variable) |
35 | | // + Target (explicit transformation) |
36 | | // + Transform (pattern transformation) |
37 | | // - global alias: (global alias rewriting) |
38 | | // + Source (original name of the aliased name) |
39 | | // + Target (explicit transformation) |
40 | | // + Transform (pattern transformation) |
41 | | // |
42 | | // Note that source and exactly one of [Target, Transform] must be provided |
43 | | // |
44 | | // New rewrite descriptors can be created. Addding a new rewrite descriptor |
45 | | // involves: |
46 | | // |
47 | | // a) extended the rewrite descriptor kind enumeration |
48 | | // (<anonymous>::RewriteDescriptor::RewriteDescriptorType) |
49 | | // b) implementing the new descriptor |
50 | | // (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor) |
51 | | // c) extending the rewrite map parser |
52 | | // (<anonymous>::RewriteMapParser::parseEntry) |
53 | | // |
54 | | // Specify to rewrite the symbols using the `-rewrite-symbols` option, and |
55 | | // specify the map file to use for the rewriting via the `-rewrite-map-file` |
56 | | // option. |
57 | | // |
58 | | //===----------------------------------------------------------------------===// |
59 | | |
60 | | #define DEBUG_TYPE "symbol-rewriter" |
61 | | #include "llvm/Transforms/Utils/SymbolRewriter.h" |
62 | | #include "llvm/ADT/SmallString.h" |
63 | | #include "llvm/IR/LegacyPassManager.h" |
64 | | #include "llvm/Pass.h" |
65 | | #include "llvm/Support/CommandLine.h" |
66 | | #include "llvm/Support/Debug.h" |
67 | | #include "llvm/Support/MemoryBuffer.h" |
68 | | #include "llvm/Support/Regex.h" |
69 | | #include "llvm/Support/SourceMgr.h" |
70 | | #include "llvm/Support/YAMLParser.h" |
71 | | #include "llvm/Support/raw_ostream.h" |
72 | | |
73 | | using namespace llvm; |
74 | | using namespace SymbolRewriter; |
75 | | |
76 | | static cl::list<std::string> RewriteMapFiles("rewrite-map-file", |
77 | | cl::desc("Symbol Rewrite Map"), |
78 | | cl::value_desc("filename")); |
79 | | |
80 | | static void rewriteComdat(Module &M, GlobalObject *GO, |
81 | | const std::string &Source, |
82 | 24 | const std::string &Target) { |
83 | 24 | if (Comdat *CD24 = GO->getComdat()) { |
84 | 8 | auto &Comdats = M.getComdatSymbolTable(); |
85 | 8 | |
86 | 8 | Comdat *C = M.getOrInsertComdat(Target); |
87 | 8 | C->setSelectionKind(CD->getSelectionKind()); |
88 | 8 | GO->setComdat(C); |
89 | 8 | |
90 | 8 | Comdats.erase(Comdats.find(Source)); |
91 | 8 | } |
92 | 24 | } |
93 | | |
94 | | namespace { |
95 | | template <RewriteDescriptor::Type DT, typename ValueType, |
96 | | ValueType *(llvm::Module::*Get)(StringRef) const> |
97 | | class ExplicitRewriteDescriptor : public RewriteDescriptor { |
98 | | public: |
99 | | const std::string Source; |
100 | | const std::string Target; |
101 | | |
102 | | ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked) |
103 | | : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S), |
104 | 18 | Target(T) {} SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool) Line | Count | Source | 104 | 12 | Target(T) {} |
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool) Line | Count | Source | 104 | 4 | Target(T) {} |
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const)>::ExplicitRewriteDescriptor(llvm::StringRef, llvm::StringRef, bool) Line | Count | Source | 104 | 2 | Target(T) {} |
|
105 | | |
106 | | bool performOnModule(Module &M) override; |
107 | | |
108 | | static bool classof(const RewriteDescriptor *RD) { |
109 | | return RD->getType() == DT; |
110 | | } |
111 | | }; |
112 | | |
113 | | template <RewriteDescriptor::Type DT, typename ValueType, |
114 | | ValueType *(llvm::Module::*Get)(StringRef) const> |
115 | 18 | bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { |
116 | 18 | bool Changed = false; |
117 | 18 | if (ValueType *S18 = (M.*Get)(Source)) { |
118 | 14 | if (GlobalObject *GO = dyn_cast<GlobalObject>(S)) |
119 | 12 | rewriteComdat(M, GO, Source, Target); |
120 | 14 | |
121 | 14 | if (Value *T = (M.*Get)(Target)) |
122 | 0 | S->setValueName(T->getValueName()); |
123 | 14 | else |
124 | 14 | S->setName(Target); |
125 | 14 | |
126 | 14 | Changed = true; |
127 | 14 | } |
128 | 18 | return Changed; |
129 | 18 | } SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const)>::performOnModule(llvm::Module&) Line | Count | Source | 115 | 12 | bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { | 116 | 12 | bool Changed = false; | 117 | 12 | if (ValueType *S12 = (M.*Get)(Source)) { | 118 | 8 | if (GlobalObject *GO = dyn_cast<GlobalObject>(S)) | 119 | 8 | rewriteComdat(M, GO, Source, Target); | 120 | 8 | | 121 | 8 | if (Value *T = (M.*Get)(Target)) | 122 | 0 | S->setValueName(T->getValueName()); | 123 | 8 | else | 124 | 8 | S->setName(Target); | 125 | 8 | | 126 | 8 | Changed = true; | 127 | 8 | } | 128 | 12 | return Changed; | 129 | 12 | } |
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const)>::performOnModule(llvm::Module&) Line | Count | Source | 115 | 4 | bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { | 116 | 4 | bool Changed = false; | 117 | 4 | if (ValueType *S4 = (M.*Get)(Source)) { | 118 | 4 | if (GlobalObject *GO = dyn_cast<GlobalObject>(S)) | 119 | 4 | rewriteComdat(M, GO, Source, Target); | 120 | 4 | | 121 | 4 | if (Value *T = (M.*Get)(Target)) | 122 | 0 | S->setValueName(T->getValueName()); | 123 | 4 | else | 124 | 4 | S->setName(Target); | 125 | 4 | | 126 | 4 | Changed = true; | 127 | 4 | } | 128 | 4 | return Changed; | 129 | 4 | } |
SymbolRewriter.cpp:(anonymous namespace)::ExplicitRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const)>::performOnModule(llvm::Module&) Line | Count | Source | 115 | 2 | bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) { | 116 | 2 | bool Changed = false; | 117 | 2 | if (ValueType *S2 = (M.*Get)(Source)) { | 118 | 2 | if (GlobalObject *GO = dyn_cast<GlobalObject>(S)) | 119 | 0 | rewriteComdat(M, GO, Source, Target); | 120 | 2 | | 121 | 2 | if (Value *T = (M.*Get)(Target)) | 122 | 0 | S->setValueName(T->getValueName()); | 123 | 2 | else | 124 | 2 | S->setName(Target); | 125 | 2 | | 126 | 2 | Changed = true; | 127 | 2 | } | 128 | 2 | return Changed; | 129 | 2 | } |
|
130 | | |
131 | | template <RewriteDescriptor::Type DT, typename ValueType, |
132 | | ValueType *(llvm::Module::*Get)(StringRef) const, |
133 | | iterator_range<typename iplist<ValueType>::iterator> |
134 | | (llvm::Module::*Iterator)()> |
135 | | class PatternRewriteDescriptor : public RewriteDescriptor { |
136 | | public: |
137 | | const std::string Pattern; |
138 | | const std::string Transform; |
139 | | |
140 | | PatternRewriteDescriptor(StringRef P, StringRef T) |
141 | 8 | : RewriteDescriptor(DT), Pattern(P), Transform(T) { } SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const), &(llvm::Module::functions())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef) Line | Count | Source | 141 | 4 | : RewriteDescriptor(DT), Pattern(P), Transform(T) { } |
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const), &(llvm::Module::globals())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef) Line | Count | Source | 141 | 4 | : RewriteDescriptor(DT), Pattern(P), Transform(T) { } |
Unexecuted instantiation: SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const), &(llvm::Module::aliases())>::PatternRewriteDescriptor(llvm::StringRef, llvm::StringRef) |
142 | | |
143 | | bool performOnModule(Module &M) override; |
144 | | |
145 | | static bool classof(const RewriteDescriptor *RD) { |
146 | | return RD->getType() == DT; |
147 | | } |
148 | | }; |
149 | | |
150 | | template <RewriteDescriptor::Type DT, typename ValueType, |
151 | | ValueType *(llvm::Module::*Get)(StringRef) const, |
152 | | iterator_range<typename iplist<ValueType>::iterator> |
153 | | (llvm::Module::*Iterator)()> |
154 | | bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>:: |
155 | 8 | performOnModule(Module &M) { |
156 | 8 | bool Changed = false; |
157 | 64 | for (auto &C : (M.*Iterator)()) { |
158 | 64 | std::string Error; |
159 | 64 | |
160 | 64 | std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error); |
161 | 64 | if (!Error.empty()) |
162 | 0 | report_fatal_error("unable to transforn " + C.getName() + " in " + |
163 | 0 | M.getModuleIdentifier() + ": " + Error); |
164 | 64 | |
165 | 64 | if (64 C.getName() == Name64 ) |
166 | 52 | continue; |
167 | 12 | |
168 | 12 | if (GlobalObject *12 GO12 = dyn_cast<GlobalObject>(&C)) |
169 | 12 | rewriteComdat(M, GO, C.getName(), Name); |
170 | 12 | |
171 | 12 | if (Value *V = (M.*Get)(Name)) |
172 | 0 | C.setValueName(V->getValueName()); |
173 | 12 | else |
174 | 12 | C.setName(Name); |
175 | 64 | |
176 | 64 | Changed = true; |
177 | 64 | } |
178 | 8 | return Changed; |
179 | 8 | } SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)1, llvm::Function, &(llvm::Module::getFunction(llvm::StringRef) const), &(llvm::Module::functions())>::performOnModule(llvm::Module&) Line | Count | Source | 155 | 4 | performOnModule(Module &M) { | 156 | 4 | bool Changed = false; | 157 | 44 | for (auto &C : (M.*Iterator)()) { | 158 | 44 | std::string Error; | 159 | 44 | | 160 | 44 | std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error); | 161 | 44 | if (!Error.empty()) | 162 | 0 | report_fatal_error("unable to transforn " + C.getName() + " in " + | 163 | 0 | M.getModuleIdentifier() + ": " + Error); | 164 | 44 | | 165 | 44 | if (44 C.getName() == Name44 ) | 166 | 38 | continue; | 167 | 6 | | 168 | 6 | if (GlobalObject *6 GO6 = dyn_cast<GlobalObject>(&C)) | 169 | 6 | rewriteComdat(M, GO, C.getName(), Name); | 170 | 6 | | 171 | 6 | if (Value *V = (M.*Get)(Name)) | 172 | 0 | C.setValueName(V->getValueName()); | 173 | 6 | else | 174 | 6 | C.setName(Name); | 175 | 44 | | 176 | 44 | Changed = true; | 177 | 44 | } | 178 | 4 | return Changed; | 179 | 4 | } |
SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)2, llvm::GlobalVariable, &(llvm::Module::getGlobalVariable(llvm::StringRef) const), &(llvm::Module::globals())>::performOnModule(llvm::Module&) Line | Count | Source | 155 | 4 | performOnModule(Module &M) { | 156 | 4 | bool Changed = false; | 157 | 20 | for (auto &C : (M.*Iterator)()) { | 158 | 20 | std::string Error; | 159 | 20 | | 160 | 20 | std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error); | 161 | 20 | if (!Error.empty()) | 162 | 0 | report_fatal_error("unable to transforn " + C.getName() + " in " + | 163 | 0 | M.getModuleIdentifier() + ": " + Error); | 164 | 20 | | 165 | 20 | if (20 C.getName() == Name20 ) | 166 | 14 | continue; | 167 | 6 | | 168 | 6 | if (GlobalObject *6 GO6 = dyn_cast<GlobalObject>(&C)) | 169 | 6 | rewriteComdat(M, GO, C.getName(), Name); | 170 | 6 | | 171 | 6 | if (Value *V = (M.*Get)(Name)) | 172 | 0 | C.setValueName(V->getValueName()); | 173 | 6 | else | 174 | 6 | C.setName(Name); | 175 | 20 | | 176 | 20 | Changed = true; | 177 | 20 | } | 178 | 4 | return Changed; | 179 | 4 | } |
Unexecuted instantiation: SymbolRewriter.cpp:(anonymous namespace)::PatternRewriteDescriptor<(llvm::SymbolRewriter::RewriteDescriptor::Type)3, llvm::GlobalAlias, &(llvm::Module::getNamedAlias(llvm::StringRef) const), &(llvm::Module::aliases())>::performOnModule(llvm::Module&) |
180 | | |
181 | | /// Represents a rewrite for an explicitly named (function) symbol. Both the |
182 | | /// source function name and target function name of the transformation are |
183 | | /// explicitly spelt out. |
184 | | typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function, |
185 | | llvm::Function, &llvm::Module::getFunction> |
186 | | ExplicitRewriteFunctionDescriptor; |
187 | | |
188 | | /// Represents a rewrite for an explicitly named (global variable) symbol. Both |
189 | | /// the source variable name and target variable name are spelt out. This |
190 | | /// applies only to module level variables. |
191 | | typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable, |
192 | | llvm::GlobalVariable, |
193 | | &llvm::Module::getGlobalVariable> |
194 | | ExplicitRewriteGlobalVariableDescriptor; |
195 | | |
196 | | /// Represents a rewrite for an explicitly named global alias. Both the source |
197 | | /// and target name are explicitly spelt out. |
198 | | typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, |
199 | | llvm::GlobalAlias, |
200 | | &llvm::Module::getNamedAlias> |
201 | | ExplicitRewriteNamedAliasDescriptor; |
202 | | |
203 | | /// Represents a rewrite for a regular expression based pattern for functions. |
204 | | /// A pattern for the function name is provided and a transformation for that |
205 | | /// pattern to determine the target function name create the rewrite rule. |
206 | | typedef PatternRewriteDescriptor<RewriteDescriptor::Type::Function, |
207 | | llvm::Function, &llvm::Module::getFunction, |
208 | | &llvm::Module::functions> |
209 | | PatternRewriteFunctionDescriptor; |
210 | | |
211 | | /// Represents a rewrite for a global variable based upon a matching pattern. |
212 | | /// Each global variable matching the provided pattern will be transformed as |
213 | | /// described in the transformation pattern for the target. Applies only to |
214 | | /// module level variables. |
215 | | typedef PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable, |
216 | | llvm::GlobalVariable, |
217 | | &llvm::Module::getGlobalVariable, |
218 | | &llvm::Module::globals> |
219 | | PatternRewriteGlobalVariableDescriptor; |
220 | | |
221 | | /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global |
222 | | /// aliases which match a given pattern. The provided transformation will be |
223 | | /// applied to each of the matching names. |
224 | | typedef PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, |
225 | | llvm::GlobalAlias, |
226 | | &llvm::Module::getNamedAlias, |
227 | | &llvm::Module::aliases> |
228 | | PatternRewriteNamedAliasDescriptor; |
229 | | } // namespace |
230 | | |
231 | | bool RewriteMapParser::parse(const std::string &MapFile, |
232 | 2 | RewriteDescriptorList *DL) { |
233 | 2 | ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping = |
234 | 2 | MemoryBuffer::getFile(MapFile); |
235 | 2 | |
236 | 2 | if (!Mapping) |
237 | 0 | report_fatal_error("unable to read rewrite map '" + MapFile + "': " + |
238 | 0 | Mapping.getError().message()); |
239 | 2 | |
240 | 2 | if (2 !parse(*Mapping, DL)2 ) |
241 | 0 | report_fatal_error("unable to parse rewrite map '" + MapFile + "'"); |
242 | 2 | |
243 | 2 | return true; |
244 | 2 | } |
245 | | |
246 | | bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile, |
247 | 2 | RewriteDescriptorList *DL) { |
248 | 2 | SourceMgr SM; |
249 | 2 | yaml::Stream YS(MapFile->getBuffer(), SM); |
250 | 2 | |
251 | 2 | for (auto &Document : YS) { |
252 | 2 | yaml::MappingNode *DescriptorList; |
253 | 2 | |
254 | 2 | // ignore empty documents |
255 | 2 | if (isa<yaml::NullNode>(Document.getRoot())) |
256 | 0 | continue; |
257 | 2 | |
258 | 2 | DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot()); |
259 | 2 | if (!DescriptorList2 ) { |
260 | 0 | YS.printError(Document.getRoot(), "DescriptorList node must be a map"); |
261 | 0 | return false; |
262 | 0 | } |
263 | 2 | |
264 | 2 | for (auto &Descriptor : *DescriptorList) |
265 | 26 | if (26 !parseEntry(YS, Descriptor, DL)26 ) |
266 | 0 | return false; |
267 | 2 | } |
268 | 2 | |
269 | 2 | return true; |
270 | 2 | } |
271 | | |
272 | | bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry, |
273 | 26 | RewriteDescriptorList *DL) { |
274 | 26 | yaml::ScalarNode *Key; |
275 | 26 | yaml::MappingNode *Value; |
276 | 26 | SmallString<32> KeyStorage; |
277 | 26 | StringRef RewriteType; |
278 | 26 | |
279 | 26 | Key = dyn_cast<yaml::ScalarNode>(Entry.getKey()); |
280 | 26 | if (!Key26 ) { |
281 | 0 | YS.printError(Entry.getKey(), "rewrite type must be a scalar"); |
282 | 0 | return false; |
283 | 0 | } |
284 | 26 | |
285 | 26 | Value = dyn_cast<yaml::MappingNode>(Entry.getValue()); |
286 | 26 | if (!Value26 ) { |
287 | 0 | YS.printError(Entry.getValue(), "rewrite descriptor must be a map"); |
288 | 0 | return false; |
289 | 0 | } |
290 | 26 | |
291 | 26 | RewriteType = Key->getValue(KeyStorage); |
292 | 26 | if (RewriteType.equals("function")) |
293 | 16 | return parseRewriteFunctionDescriptor(YS, Key, Value, DL); |
294 | 10 | else if (10 RewriteType.equals("global variable")10 ) |
295 | 8 | return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL); |
296 | 2 | else if (2 RewriteType.equals("global alias")2 ) |
297 | 2 | return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL); |
298 | 0 |
|
299 | 0 | YS.printError(Entry.getKey(), "unknown rewrite type"); |
300 | 0 | return false; |
301 | 0 | } |
302 | | |
303 | | bool RewriteMapParser:: |
304 | | parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, |
305 | | yaml::MappingNode *Descriptor, |
306 | 16 | RewriteDescriptorList *DL) { |
307 | 16 | bool Naked = false; |
308 | 16 | std::string Source; |
309 | 16 | std::string Target; |
310 | 16 | std::string Transform; |
311 | 16 | |
312 | 34 | for (auto &Field : *Descriptor) { |
313 | 34 | yaml::ScalarNode *Key; |
314 | 34 | yaml::ScalarNode *Value; |
315 | 34 | SmallString<32> KeyStorage; |
316 | 34 | SmallString<32> ValueStorage; |
317 | 34 | StringRef KeyValue; |
318 | 34 | |
319 | 34 | Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); |
320 | 34 | if (!Key34 ) { |
321 | 0 | YS.printError(Field.getKey(), "descriptor key must be a scalar"); |
322 | 0 | return false; |
323 | 0 | } |
324 | 34 | |
325 | 34 | Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); |
326 | 34 | if (!Value34 ) { |
327 | 0 | YS.printError(Field.getValue(), "descriptor value must be a scalar"); |
328 | 0 | return false; |
329 | 0 | } |
330 | 34 | |
331 | 34 | KeyValue = Key->getValue(KeyStorage); |
332 | 34 | if (KeyValue.equals("source")34 ) { |
333 | 16 | std::string Error; |
334 | 16 | |
335 | 16 | Source = Value->getValue(ValueStorage); |
336 | 16 | if (!Regex(Source).isValid(Error)16 ) { |
337 | 0 | YS.printError(Field.getKey(), "invalid regex: " + Error); |
338 | 0 | return false; |
339 | 0 | } |
340 | 18 | } else if (18 KeyValue.equals("target")18 ) { |
341 | 12 | Target = Value->getValue(ValueStorage); |
342 | 18 | } else if (6 KeyValue.equals("transform")6 ) { |
343 | 4 | Transform = Value->getValue(ValueStorage); |
344 | 6 | } else if (2 KeyValue.equals("naked")2 ) { |
345 | 2 | std::string Undecorated; |
346 | 2 | |
347 | 2 | Undecorated = Value->getValue(ValueStorage); |
348 | 0 | Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1"; |
349 | 0 | } else { |
350 | 0 | YS.printError(Field.getKey(), "unknown key for function"); |
351 | 0 | return false; |
352 | 0 | } |
353 | 16 | } |
354 | 16 | |
355 | 16 | if (16 Transform.empty() == Target.empty()16 ) { |
356 | 0 | YS.printError(Descriptor, |
357 | 0 | "exactly one of transform or target must be specified"); |
358 | 0 | return false; |
359 | 0 | } |
360 | 16 | |
361 | 16 | // TODO see if there is a more elegant solution to selecting the rewrite |
362 | 16 | // descriptor type |
363 | 16 | if (16 !Target.empty()16 ) |
364 | 12 | DL->push_back(llvm::make_unique<ExplicitRewriteFunctionDescriptor>( |
365 | 12 | Source, Target, Naked)); |
366 | 16 | else |
367 | 4 | DL->push_back( |
368 | 4 | llvm::make_unique<PatternRewriteFunctionDescriptor>(Source, Transform)); |
369 | 16 | |
370 | 16 | return true; |
371 | 16 | } |
372 | | |
373 | | bool RewriteMapParser:: |
374 | | parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, |
375 | | yaml::MappingNode *Descriptor, |
376 | 8 | RewriteDescriptorList *DL) { |
377 | 8 | std::string Source; |
378 | 8 | std::string Target; |
379 | 8 | std::string Transform; |
380 | 8 | |
381 | 16 | for (auto &Field : *Descriptor) { |
382 | 16 | yaml::ScalarNode *Key; |
383 | 16 | yaml::ScalarNode *Value; |
384 | 16 | SmallString<32> KeyStorage; |
385 | 16 | SmallString<32> ValueStorage; |
386 | 16 | StringRef KeyValue; |
387 | 16 | |
388 | 16 | Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); |
389 | 16 | if (!Key16 ) { |
390 | 0 | YS.printError(Field.getKey(), "descriptor Key must be a scalar"); |
391 | 0 | return false; |
392 | 0 | } |
393 | 16 | |
394 | 16 | Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); |
395 | 16 | if (!Value16 ) { |
396 | 0 | YS.printError(Field.getValue(), "descriptor value must be a scalar"); |
397 | 0 | return false; |
398 | 0 | } |
399 | 16 | |
400 | 16 | KeyValue = Key->getValue(KeyStorage); |
401 | 16 | if (KeyValue.equals("source")16 ) { |
402 | 8 | std::string Error; |
403 | 8 | |
404 | 8 | Source = Value->getValue(ValueStorage); |
405 | 8 | if (!Regex(Source).isValid(Error)8 ) { |
406 | 0 | YS.printError(Field.getKey(), "invalid regex: " + Error); |
407 | 0 | return false; |
408 | 0 | } |
409 | 8 | } else if (8 KeyValue.equals("target")8 ) { |
410 | 4 | Target = Value->getValue(ValueStorage); |
411 | 8 | } else if (4 KeyValue.equals("transform")4 ) { |
412 | 4 | Transform = Value->getValue(ValueStorage); |
413 | 4 | } else { |
414 | 0 | YS.printError(Field.getKey(), "unknown Key for Global Variable"); |
415 | 0 | return false; |
416 | 0 | } |
417 | 8 | } |
418 | 8 | |
419 | 8 | if (8 Transform.empty() == Target.empty()8 ) { |
420 | 0 | YS.printError(Descriptor, |
421 | 0 | "exactly one of transform or target must be specified"); |
422 | 0 | return false; |
423 | 0 | } |
424 | 8 | |
425 | 8 | if (8 !Target.empty()8 ) |
426 | 4 | DL->push_back(llvm::make_unique<ExplicitRewriteGlobalVariableDescriptor>( |
427 | 4 | Source, Target, |
428 | 4 | /*Naked*/ false)); |
429 | 8 | else |
430 | 4 | DL->push_back(llvm::make_unique<PatternRewriteGlobalVariableDescriptor>( |
431 | 4 | Source, Transform)); |
432 | 8 | |
433 | 8 | return true; |
434 | 8 | } |
435 | | |
436 | | bool RewriteMapParser:: |
437 | | parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, |
438 | | yaml::MappingNode *Descriptor, |
439 | 2 | RewriteDescriptorList *DL) { |
440 | 2 | std::string Source; |
441 | 2 | std::string Target; |
442 | 2 | std::string Transform; |
443 | 2 | |
444 | 4 | for (auto &Field : *Descriptor) { |
445 | 4 | yaml::ScalarNode *Key; |
446 | 4 | yaml::ScalarNode *Value; |
447 | 4 | SmallString<32> KeyStorage; |
448 | 4 | SmallString<32> ValueStorage; |
449 | 4 | StringRef KeyValue; |
450 | 4 | |
451 | 4 | Key = dyn_cast<yaml::ScalarNode>(Field.getKey()); |
452 | 4 | if (!Key4 ) { |
453 | 0 | YS.printError(Field.getKey(), "descriptor key must be a scalar"); |
454 | 0 | return false; |
455 | 0 | } |
456 | 4 | |
457 | 4 | Value = dyn_cast<yaml::ScalarNode>(Field.getValue()); |
458 | 4 | if (!Value4 ) { |
459 | 0 | YS.printError(Field.getValue(), "descriptor value must be a scalar"); |
460 | 0 | return false; |
461 | 0 | } |
462 | 4 | |
463 | 4 | KeyValue = Key->getValue(KeyStorage); |
464 | 4 | if (KeyValue.equals("source")4 ) { |
465 | 2 | std::string Error; |
466 | 2 | |
467 | 2 | Source = Value->getValue(ValueStorage); |
468 | 2 | if (!Regex(Source).isValid(Error)2 ) { |
469 | 0 | YS.printError(Field.getKey(), "invalid regex: " + Error); |
470 | 0 | return false; |
471 | 0 | } |
472 | 2 | } else if (2 KeyValue.equals("target")2 ) { |
473 | 2 | Target = Value->getValue(ValueStorage); |
474 | 2 | } else if (0 KeyValue.equals("transform")0 ) { |
475 | 0 | Transform = Value->getValue(ValueStorage); |
476 | 0 | } else { |
477 | 0 | YS.printError(Field.getKey(), "unknown key for Global Alias"); |
478 | 0 | return false; |
479 | 0 | } |
480 | 2 | } |
481 | 2 | |
482 | 2 | if (2 Transform.empty() == Target.empty()2 ) { |
483 | 0 | YS.printError(Descriptor, |
484 | 0 | "exactly one of transform or target must be specified"); |
485 | 0 | return false; |
486 | 0 | } |
487 | 2 | |
488 | 2 | if (2 !Target.empty()2 ) |
489 | 2 | DL->push_back(llvm::make_unique<ExplicitRewriteNamedAliasDescriptor>( |
490 | 2 | Source, Target, |
491 | 2 | /*Naked*/ false)); |
492 | 2 | else |
493 | 0 | DL->push_back(llvm::make_unique<PatternRewriteNamedAliasDescriptor>( |
494 | 0 | Source, Transform)); |
495 | 2 | |
496 | 2 | return true; |
497 | 2 | } |
498 | | |
499 | | namespace { |
500 | | class RewriteSymbolsLegacyPass : public ModulePass { |
501 | | public: |
502 | | static char ID; // Pass identification, replacement for typeid |
503 | | |
504 | | RewriteSymbolsLegacyPass(); |
505 | | RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList &DL); |
506 | | |
507 | | bool runOnModule(Module &M) override; |
508 | | |
509 | | private: |
510 | | RewriteSymbolPass Impl; |
511 | | }; |
512 | | |
513 | | char RewriteSymbolsLegacyPass::ID = 0; |
514 | | |
515 | 33.5k | RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID), Impl() { |
516 | 33.5k | initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry()); |
517 | 33.5k | } |
518 | | |
519 | | RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass( |
520 | | SymbolRewriter::RewriteDescriptorList &DL) |
521 | 0 | : ModulePass(ID), Impl(DL) {} |
522 | | |
523 | 33.4k | bool RewriteSymbolsLegacyPass::runOnModule(Module &M) { |
524 | 33.4k | return Impl.runImpl(M); |
525 | 33.4k | } |
526 | | } |
527 | | |
528 | | namespace llvm { |
529 | 1 | PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) { |
530 | 1 | if (!runImpl(M)) |
531 | 0 | return PreservedAnalyses::all(); |
532 | 1 | |
533 | 1 | return PreservedAnalyses::none(); |
534 | 1 | } |
535 | | |
536 | 33.4k | bool RewriteSymbolPass::runImpl(Module &M) { |
537 | 33.4k | bool Changed; |
538 | 33.4k | |
539 | 33.4k | Changed = false; |
540 | 33.4k | for (auto &Descriptor : Descriptors) |
541 | 26 | Changed |= Descriptor->performOnModule(M); |
542 | 33.4k | |
543 | 33.4k | return Changed; |
544 | 33.4k | } |
545 | | |
546 | 33.5k | void RewriteSymbolPass::loadAndParseMapFiles() { |
547 | 33.5k | const std::vector<std::string> MapFiles(RewriteMapFiles); |
548 | 33.5k | SymbolRewriter::RewriteMapParser Parser; |
549 | 33.5k | |
550 | 33.5k | for (const auto &MapFile : MapFiles) |
551 | 2 | Parser.parse(MapFile, &Descriptors); |
552 | 33.5k | } |
553 | | } |
554 | | |
555 | | INITIALIZE_PASS(RewriteSymbolsLegacyPass, "rewrite-symbols", "Rewrite Symbols", |
556 | | false, false) |
557 | | |
558 | 33.5k | ModulePass *llvm::createRewriteSymbolsPass() { |
559 | 33.5k | return new RewriteSymbolsLegacyPass(); |
560 | 33.5k | } |
561 | | |
562 | | ModulePass * |
563 | 0 | llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) { |
564 | 0 | return new RewriteSymbolsLegacyPass(DL); |
565 | 0 | } |