llvm.org GIT mirror llvm / 35c1630
Transform: add SymbolRewriter pass This introduces the symbol rewriter. This is an IR->IR transformation that is implemented as a CodeGenPrepare pass. This allows for the transparent adjustment of the symbols during compilation. It provides a clean, simple, elegant solution for symbol inter-positioning. This technique is often used, such as in the various sanitizers and performance analysis. The control of this is via a custom YAML syntax map file that indicates source to destination mapping, so as to avoid having the compiler to know the exact details of the source to destination transformations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221548 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 4 years ago
10 changed file(s) with 822 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
370370 /// does not exist, return null. If AllowInternal is set to true, this
371371 /// function will return types that have InternalLinkage. By default, these
372372 /// types are not returned.
373 const GlobalVariable *getGlobalVariable(StringRef Name,
374 bool AllowInternal = false) const {
373 GlobalVariable *getGlobalVariable(StringRef Name) const {
374 return getGlobalVariable(Name, false);
375 }
376
377 GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const {
375378 return const_cast(this)->getGlobalVariable(Name, AllowInternal);
376379 }
377380
563566 size_t size() const { return FunctionList.size(); }
564567 bool empty() const { return FunctionList.empty(); }
565568
569 iterator_range functions() {
570 return iterator_range(begin(), end());
571 }
572 iterator_range functions() const {
573 return iterator_range(begin(), end());
574 }
575
566576 /// @}
567577 /// @name Alias Iteration
568578 /// @{
283283 void initializeStackMapLivenessPass(PassRegistry&);
284284 void initializeMachineCombinerPass(PassRegistry &);
285285 void initializeLoadCombinePass(PassRegistry&);
286 void initializeRewriteSymbolsPass(PassRegistry&);
286287 }
287288
288289 #endif
3333 #include "llvm/Transforms/ObjCARC.h"
3434 #include "llvm/Transforms/Scalar.h"
3535 #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
36 #include "llvm/Transforms/Utils/SymbolRewriter.h"
3637 #include "llvm/Transforms/Vectorize.h"
3738 #include
3839
162163 (void) llvm::createPartiallyInlineLibCallsPass();
163164 (void) llvm::createScalarizerPass();
164165 (void) llvm::createSeparateConstOffsetFromGEPPass();
166 (void) llvm::createRewriteSymbolsPass();
165167
166168 (void)new llvm::IntervalPartition();
167169 (void)new llvm::FindUsedTypes();
0 //===-- SymbolRewriter.h - Symbol Rewriting Pass ----------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides the prototypes and definitions related to the Symbol
10 // Rewriter pass.
11 //
12 // The Symbol Rewriter pass takes a set of rewrite descriptors which define
13 // transformations for symbol names. These can be either single name to name
14 // trnsformation or more broad regular expression based transformations.
15 //
16 // All the functions are re-written at the IR level. The Symbol Rewriter itself
17 // is exposed as a module level pass. All symbols at the module level are
18 // iterated. For any matching symbol, the requested transformation is applied,
19 // updating references to it as well (a la RAUW). The resulting binary will
20 // only contain the rewritten symbols.
21 //
22 // By performing this operation in the compiler, we are able to catch symbols
23 // that would otherwise not be possible to catch (e.g. inlined symbols).
24 //
25 // This makes it possible to cleanly transform symbols without resorting to
26 // overly-complex macro tricks and the pre-processor. An example of where this
27 // is useful is the sanitizers where we would like to intercept a well-defined
28 // set of functions across the module.
29 //
30 //===----------------------------------------------------------------------===//
31
32 #ifndef LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
33 #define LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
34
35 #include "llvm/ADT/ilist.h"
36 #include "llvm/ADT/ilist_node.h"
37 #include "llvm/IR/Module.h"
38
39 namespace llvm {
40 class MemoryBuffer;
41
42 namespace yaml {
43 class KeyValueNode;
44 class MappingNode;
45 class ScalarNode;
46 class Stream;
47 }
48
49 namespace SymbolRewriter {
50 /// The basic entity representing a rewrite operation. It serves as the base
51 /// class for any rewrite descriptor. It has a certain set of specializations
52 /// which describe a particular rewrite.
53 ///
54 /// The RewriteMapParser can be used to parse a mapping file that provides the
55 /// mapping for rewriting the symbols. The descriptors individually describe
56 /// whether to rewrite a function, global variable, or global alias. Each of
57 /// these can be selected either by explicitly providing a name for the ones to
58 /// be rewritten or providing a (posix compatible) regular expression that will
59 /// select the symbols to rewrite. This descriptor list is passed to the
60 /// SymbolRewriter pass.
61 class RewriteDescriptor : public ilist_node {
62 RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
63
64 const RewriteDescriptor &
65 operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION;
66
67 public:
68 enum class Type {
69 Invalid, /// invalid
70 Function, /// function - descriptor rewrites a function
71 GlobalVariable, /// global variable - descriptor rewrites a global variable
72 NamedAlias, /// named alias - descriptor rewrites a global alias
73 };
74
75 virtual ~RewriteDescriptor() {}
76
77 Type getType() const { return Kind; }
78
79 virtual bool performOnModule(Module &M) = 0;
80
81 protected:
82 explicit RewriteDescriptor(Type T) : Kind(T) {}
83
84 private:
85 const Type Kind;
86 };
87
88 typedef iplist RewriteDescriptorList;
89
90 class RewriteMapParser {
91 public:
92 RewriteMapParser() {}
93 ~RewriteMapParser() {}
94
95 bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors);
96
97 private:
98 bool parse(std::unique_ptr &MapFile, RewriteDescriptorList *DL);
99 bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry,
100 RewriteDescriptorList *DL);
101 bool parseRewriteFunctionDescriptor(yaml::Stream &Stream,
102 yaml::ScalarNode *Key,
103 yaml::MappingNode *Value,
104 RewriteDescriptorList *DL);
105 bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream,
106 yaml::ScalarNode *Key,
107 yaml::MappingNode *Value,
108 RewriteDescriptorList *DL);
109 bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
110 yaml::MappingNode *V,
111 RewriteDescriptorList *DL);
112 };
113 }
114
115 template <>
116 struct ilist_traits
117 : public ilist_default_traits {
118 mutable ilist_half_node Sentinel;
119
120 public:
121 // createSentinel is used to get a reference to a node marking the end of
122 // the list. Because the sentinel is relative to this instance, use a
123 // non-static method.
124 SymbolRewriter::RewriteDescriptor *createSentinel() const {
125 // since i[p] lists always publicly derive from the corresponding
126 // traits, placing a data member in this class will augment the
127 // i[p]list. Since the NodeTy is expected to publicly derive from
128 // ilist_node, there is a legal viable downcast from it to
129 // NodeTy. We use this trick to superpose i[p]list with a "ghostly"
130 // NodeTy, which becomes the sentinel. Dereferencing the sentinel is
131 // forbidden (save the ilist_node) so no one will ever notice
132 // the superposition.
133 return static_cast(&Sentinel);
134 }
135 void destroySentinel(SymbolRewriter::RewriteDescriptor *) {}
136
137 SymbolRewriter::RewriteDescriptor *provideInitialHead() const {
138 return createSentinel();
139 }
140
141 SymbolRewriter::RewriteDescriptor *
142 ensureHead(SymbolRewriter::RewriteDescriptor *&) const {
143 return createSentinel();
144 }
145
146 static void noteHead(SymbolRewriter::RewriteDescriptor *,
147 SymbolRewriter::RewriteDescriptor *) {}
148 };
149
150 ModulePass *createRewriteSymbolsPass();
151 ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &);
152 }
153
154 #endif
2626 #include "llvm/Target/TargetLowering.h"
2727 #include "llvm/Target/TargetSubtargetInfo.h"
2828 #include "llvm/Transforms/Scalar.h"
29 #include "llvm/Transforms/Utils/SymbolRewriter.h"
2930
3031 using namespace llvm;
3132
444445 void TargetPassConfig::addCodeGenPrepare() {
445446 if (getOptLevel() != CodeGenOpt::None && !DisableCGP)
446447 addPass(createCodeGenPreparePass(TM));
448 addPass(llvm::createRewriteSymbolsPass());
447449 }
448450
449451 /// Add common passes that perform LLVM IR to IR transforms in preparation for
3535 UnifyFunctionExitNodes.cpp
3636 Utils.cpp
3737 ValueMapper.cpp
38 SymbolRewriter.cpp
3839 )
3940
4041 add_dependencies(LLVMTransformUtils intrinsics_gen)
0 //===- SymbolRewriter.cpp - Symbol Rewriter ---------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
10 // existing code. It is implemented as a compiler pass and is configured via a
11 // YAML configuration file.
12 //
13 // The YAML configuration file format is as follows:
14 //
15 // RewriteMapFile := RewriteDescriptors
16 // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
17 // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
18 // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
19 // RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
20 // RewriteDescriptorType := Identifier
21 // FieldIdentifier := Identifier
22 // FieldValue := Identifier
23 // Identifier := [0-9a-zA-Z]+
24 //
25 // Currently, the following descriptor types are supported:
26 //
27 // - function: (function rewriting)
28 // + Source (original name of the function)
29 // + Target (explicit transformation)
30 // + Transform (pattern transformation)
31 // + Naked (boolean, whether the function is undecorated)
32 // - global variable: (external linkage global variable rewriting)
33 // + Source (original name of externally visible variable)
34 // + Target (explicit transformation)
35 // + Transform (pattern transformation)
36 // - global alias: (global alias rewriting)
37 // + Source (original name of the aliased name)
38 // + Target (explicit transformation)
39 // + Transform (pattern transformation)
40 //
41 // Note that source and exactly one of [Target, Transform] must be provided
42 //
43 // New rewrite descriptors can be created. Addding a new rewrite descriptor
44 // involves:
45 //
46 // a) extended the rewrite descriptor kind enumeration
47 // (::RewriteDescriptor::RewriteDescriptorType)
48 // b) implementing the new descriptor
49 // (c.f. ::ExplicitRewriteFunctionDescriptor)
50 // c) extending the rewrite map parser
51 // (::RewriteMapParser::parseEntry)
52 //
53 // Specify to rewrite the symbols using the `-rewrite-symbols` option, and
54 // specify the map file to use for the rewriting via the `-rewrite-map-file`
55 // option.
56 //
57 //===----------------------------------------------------------------------===//
58
59 #define DEBUG_TYPE "symbol-rewriter"
60 #include "llvm/CodeGen/Passes.h"
61 #include "llvm/Pass.h"
62 #include "llvm/PassManager.h"
63 #include "llvm/Support/CommandLine.h"
64 #include "llvm/Support/Debug.h"
65 #include "llvm/Support/MemoryBuffer.h"
66 #include "llvm/Support/Regex.h"
67 #include "llvm/Support/SourceMgr.h"
68 #include "llvm/Support/YAMLParser.h"
69 #include "llvm/Support/raw_ostream.h"
70 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
71 #include "llvm/Transforms/Utils/SymbolRewriter.h"
72
73 using namespace llvm;
74
75 static cl::list RewriteMapFiles("rewrite-map-file",
76 cl::desc("Symbol Rewrite Map"),
77 cl::value_desc("filename"));
78
79 namespace llvm {
80 namespace SymbolRewriter {
81 template
82 ValueType *(llvm::Module::*Get)(StringRef) const>
83 class ExplicitRewriteDescriptor : public RewriteDescriptor {
84 public:
85 const std::string Source;
86 const std::string Target;
87
88 ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
89 : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S),
90 Target(T) {}
91
92 bool performOnModule(Module &M) override;
93
94 static bool classof(const RewriteDescriptor *RD) {
95 return RD->getType() == DT;
96 }
97 };
98
99 template
100 ValueType *(llvm::Module::*Get)(StringRef) const>
101 bool ExplicitRewriteDescriptor::performOnModule(Module &M) {
102 bool Changed = false;
103 if (ValueType *S = (M.*Get)(Source)) {
104 if (Value *T = (M.*Get)(Target))
105 S->setValueName(T->getValueName());
106 else
107 S->setName(Target);
108 Changed = true;
109 }
110 return Changed;
111 }
112
113 template
114 ValueType *(llvm::Module::*Get)(StringRef) const,
115 iterator_range::iterator> (llvm::Module::*Iterator)()>
116 class PatternRewriteDescriptor : public RewriteDescriptor {
117 public:
118 const std::string Pattern;
119 const std::string Transform;
120
121 PatternRewriteDescriptor(StringRef P, StringRef T)
122 : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
123
124 bool performOnModule(Module &M) override;
125
126 static bool classof(const RewriteDescriptor *RD) {
127 return RD->getType() == DT;
128 }
129 };
130
131 template
132 ValueType *(llvm::Module::*Get)(StringRef) const,
133 iterator_range::iterator> (llvm::Module::*Iterator)()>
134 bool PatternRewriteDescriptor::
135 performOnModule(Module &M) {
136 bool Changed = false;
137 for (auto &C : (M.*Iterator)()) {
138 std::string Error;
139
140 std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
141 if (!Error.empty())
142 report_fatal_error("unable to transforn " + C.getName() + " in " +
143 M.getModuleIdentifier() + ": " + Error);
144
145 if (Value *V = (M.*Get)(Name))
146 C.setValueName(V->getValueName());
147 else
148 C.setName(Name);
149
150 Changed = true;
151 }
152 return Changed;
153 }
154
155 /// Represents a rewrite for an explicitly named (function) symbol. Both the
156 /// source function name and target function name of the transformation are
157 /// explicitly spelt out.
158 using ExplicitRewriteFunctionDescriptor =
159 ExplicitRewriteDescriptor
160 &llvm::Module::getFunction>;
161
162 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
163 /// the source variable name and target variable name are spelt out. This
164 /// applies only to module level variables.
165 using ExplicitRewriteGlobalVariableDescriptor =
166 ExplicitRewriteDescriptor
167 llvm::GlobalVariable,
168 &llvm::Module::getGlobalVariable>;
169
170 /// Represents a rewrite for an explicitly named global alias. Both the source
171 /// and target name are explicitly spelt out.
172 using ExplicitRewriteNamedAliasDescriptor =
173 ExplicitRewriteDescriptor
174 llvm::GlobalAlias, &llvm::Module::getNamedAlias>;
175
176 /// Represents a rewrite for a regular expression based pattern for functions.
177 /// A pattern for the function name is provided and a transformation for that
178 /// pattern to determine the target function name create the rewrite rule.
179 using PatternRewriteFunctionDescriptor =
180 PatternRewriteDescriptor
181 &llvm::Module::getFunction,
182 &llvm::Module::functions>;
183
184
185 /// Represents a rewrite for a global variable based upon a matching pattern.
186 /// Each global variable matching the provided pattern will be transformed as
187 /// described in the transformation pattern for the target. Applies only to
188 /// module level variables.
189 using PatternRewriteGlobalVariableDescriptor =
190 PatternRewriteDescriptor
191 llvm::GlobalVariable,
192 &llvm::Module::getGlobalVariable,
193 &llvm::Module::globals>;
194
195 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
196 /// aliases which match a given pattern. The provided transformation will be
197 /// applied to each of the matching names.
198 using PatternRewriteNamedAliasDescriptor =
199 PatternRewriteDescriptor
200 llvm::GlobalAlias,
201 &llvm::Module::getNamedAlias,
202 &llvm::Module::aliases>;
203
204
205 bool RewriteMapParser::parse(const std::string &MapFile,
206 RewriteDescriptorList *DL) {
207 ErrorOr> Mapping =
208 MemoryBuffer::getFile(MapFile);
209
210 if (!Mapping)
211 report_fatal_error("unable to read rewrite map '" + MapFile + "': " +
212 Mapping.getError().message());
213
214 if (!parse(*Mapping, DL))
215 report_fatal_error("unable to parse rewrite map '" + MapFile + "'");
216
217 return true;
218 }
219
220 bool RewriteMapParser::parse(std::unique_ptr &MapFile,
221 RewriteDescriptorList *DL) {
222 SourceMgr SM;
223 yaml::Stream YS(MapFile->getBuffer(), SM);
224
225 for (auto &Document : YS) {
226 yaml::MappingNode *DescriptorList;
227
228 // ignore empty documents
229 if (isa(Document.getRoot()))
230 continue;
231
232 DescriptorList = dyn_cast(Document.getRoot());
233 if (!DescriptorList) {
234 YS.printError(Document.getRoot(), "DescriptorList node must be a map");
235 return false;
236 }
237
238 for (auto &Descriptor : *DescriptorList)
239 if (!parseEntry(YS, Descriptor, DL))
240 return false;
241 }
242
243 return true;
244 }
245
246 bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
247 RewriteDescriptorList *DL) {
248 const std::string kRewriteTypeFunction = "function";
249 const std::string kRewriteTypeGlobalVariable = "global variable";
250 const std::string kRewriteTypeGlobalAlias = "global alias";
251
252 yaml::ScalarNode *Key;
253 yaml::MappingNode *Value;
254 SmallString<32> KeyStorage;
255 StringRef RewriteType;
256
257 Key = dyn_cast(Entry.getKey());
258 if (!Key) {
259 YS.printError(Entry.getKey(), "rewrite type must be a scalar");
260 return false;
261 }
262
263 Value = dyn_cast(Entry.getValue());
264 if (!Value) {
265 YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
266 return false;
267 }
268
269 RewriteType = Key->getValue(KeyStorage);
270 if (RewriteType == kRewriteTypeFunction)
271 return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
272 else if (RewriteType == kRewriteTypeGlobalVariable)
273 return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
274 else if (RewriteType == kRewriteTypeGlobalAlias)
275 return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
276
277 YS.printError(Entry.getKey(), "unknown rewrite type");
278 return false;
279 }
280
281 bool RewriteMapParser::
282 parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
283 yaml::MappingNode *Descriptor,
284 RewriteDescriptorList *DL) {
285 const std::string kDescriptorFieldSource = "source";
286 const std::string kDescriptorFieldTarget = "target";
287 const std::string kDescriptorFieldTransform = "transform";
288 const std::string kDescriptorFieldNaked = "naked";
289
290 bool Naked = false;
291 std::string Source;
292 std::string Target;
293 std::string Transform;
294
295 for (auto &Field : *Descriptor) {
296 yaml::ScalarNode *Key;
297 yaml::ScalarNode *Value;
298 SmallString<32> KeyStorage;
299 SmallString<32> ValueStorage;
300 StringRef KeyValue;
301
302 Key = dyn_cast(Field.getKey());
303 if (!Key) {
304 YS.printError(Field.getKey(), "descriptor key must be a scalar");
305 return false;
306 }
307
308 Value = dyn_cast(Field.getValue());
309 if (!Value) {
310 YS.printError(Field.getValue(), "descriptor value must be a scalar");
311 return false;
312 }
313
314 KeyValue = Key->getValue(KeyStorage);
315 if (KeyValue == kDescriptorFieldSource) {
316 std::string Error;
317
318 Source = Value->getValue(ValueStorage);
319 if (!Regex(Source).isValid(Error)) {
320 YS.printError(Field.getKey(), "invalid regex: " + Error);
321 return false;
322 }
323 } else if (KeyValue == kDescriptorFieldTarget) {
324 Target = Value->getValue(ValueStorage);
325 } else if (KeyValue == kDescriptorFieldTransform) {
326 Transform = Value->getValue(ValueStorage);
327 } else if (KeyValue == kDescriptorFieldNaked) {
328 std::string Undecorated;
329
330 Undecorated = Value->getValue(ValueStorage);
331 Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
332 } else {
333 YS.printError(Field.getKey(), "unknown key for function");
334 return false;
335 }
336 }
337
338 if (Transform.empty() == Target.empty()) {
339 YS.printError(Descriptor,
340 "exactly one of transform or target must be specified");
341 return false;
342 }
343
344 // TODO see if there is a more elegant solution to selecting the rewrite
345 // descriptor type
346 if (!Target.empty())
347 DL->push_back(new ExplicitRewriteFunctionDescriptor(Source, Target, Naked));
348 else
349 DL->push_back(new PatternRewriteFunctionDescriptor(Source, Transform));
350
351 return true;
352 }
353
354 bool RewriteMapParser::
355 parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
356 yaml::MappingNode *Descriptor,
357 RewriteDescriptorList *DL) {
358 const std::string kDescriptorFieldSource = "source";
359 const std::string kDescriptorFieldTarget = "target";
360 const std::string kDescriptorFieldTransform = "transform";
361
362 std::string Source;
363 std::string Target;
364 std::string Transform;
365
366 for (auto &Field : *Descriptor) {
367 yaml::ScalarNode *Key;
368 yaml::ScalarNode *Value;
369 SmallString<32> KeyStorage;
370 SmallString<32> ValueStorage;
371 StringRef KeyValue;
372
373 Key = dyn_cast(Field.getKey());
374 if (!Key) {
375 YS.printError(Field.getKey(), "descriptor Key must be a scalar");
376 return false;
377 }
378
379 Value = dyn_cast(Field.getValue());
380 if (!Value) {
381 YS.printError(Field.getValue(), "descriptor value must be a scalar");
382 return false;
383 }
384
385 KeyValue = Key->getValue(KeyStorage);
386 if (KeyValue == kDescriptorFieldSource) {
387 std::string Error;
388
389 Source = Value->getValue(ValueStorage);
390 if (!Regex(Source).isValid(Error)) {
391 YS.printError(Field.getKey(), "invalid regex: " + Error);
392 return false;
393 }
394 } else if (KeyValue == kDescriptorFieldTarget) {
395 Target = Value->getValue(ValueStorage);
396 } else if (KeyValue == kDescriptorFieldTransform) {
397 Transform = Value->getValue(ValueStorage);
398 } else {
399 YS.printError(Field.getKey(), "unknown Key for Global Variable");
400 return false;
401 }
402 }
403
404 if (Transform.empty() == Target.empty()) {
405 YS.printError(Descriptor,
406 "exactly one of transform or target must be specified");
407 return false;
408 }
409
410 if (!Target.empty())
411 DL->push_back(new ExplicitRewriteGlobalVariableDescriptor(Source, Target,
412 /*Naked*/false));
413 else
414 DL->push_back(new PatternRewriteGlobalVariableDescriptor(Source,
415 Transform));
416
417 return true;
418 }
419
420 bool RewriteMapParser::
421 parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
422 yaml::MappingNode *Descriptor,
423 RewriteDescriptorList *DL) {
424 const std::string kDescriptorFieldSource = "source";
425 const std::string kDescriptorFieldTarget = "target";
426 const std::string kDescriptorFieldTransform = "transform";
427
428 std::string Source;
429 std::string Target;
430 std::string Transform;
431
432 for (auto &Field : *Descriptor) {
433 yaml::ScalarNode *Key;
434 yaml::ScalarNode *Value;
435 SmallString<32> KeyStorage;
436 SmallString<32> ValueStorage;
437 StringRef KeyValue;
438
439 Key = dyn_cast(Field.getKey());
440 if (!Key) {
441 YS.printError(Field.getKey(), "descriptor key must be a scalar");
442 return false;
443 }
444
445 Value = dyn_cast(Field.getValue());
446 if (!Value) {
447 YS.printError(Field.getValue(), "descriptor value must be a scalar");
448 return false;
449 }
450
451 KeyValue = Key->getValue(KeyStorage);
452 if (KeyValue == kDescriptorFieldSource) {
453 std::string Error;
454
455 Source = Value->getValue(ValueStorage);
456 if (!Regex(Source).isValid(Error)) {
457 YS.printError(Field.getKey(), "invalid regex: " + Error);
458 return false;
459 }
460 } else if (KeyValue == kDescriptorFieldTarget) {
461 Target = Value->getValue(ValueStorage);
462 } else if (KeyValue == kDescriptorFieldTransform) {
463 Transform = Value->getValue(ValueStorage);
464 } else {
465 YS.printError(Field.getKey(), "unknown key for Global Alias");
466 return false;
467 }
468 }
469
470 if (Transform.empty() == Target.empty()) {
471 YS.printError(Descriptor,
472 "exactly one of transform or target must be specified");
473 return false;
474 }
475
476 if (!Target.empty())
477 DL->push_back(new ExplicitRewriteNamedAliasDescriptor(Source, Target,
478 /*Naked*/false));
479 else
480 DL->push_back(new PatternRewriteNamedAliasDescriptor(Source, Transform));
481
482 return true;
483 }
484 }
485 }
486
487 namespace {
488 class RewriteSymbols : public ModulePass {
489 public:
490 static char ID; // Pass identification, replacement for typeid
491
492 RewriteSymbols();
493 RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL);
494
495 virtual bool runOnModule(Module &M) override;
496
497 private:
498 void loadAndParseMapFiles();
499
500 SymbolRewriter::RewriteDescriptorList Descriptors;
501 };
502
503 char RewriteSymbols::ID = 0;
504
505 RewriteSymbols::RewriteSymbols() : ModulePass(ID) {
506 initializeRewriteSymbolsPass(*PassRegistry::getPassRegistry());
507 loadAndParseMapFiles();
508 }
509
510 RewriteSymbols::RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL)
511 : ModulePass(ID) {
512 std::swap(Descriptors, DL);
513 }
514
515 bool RewriteSymbols::runOnModule(Module &M) {
516 bool Changed;
517
518 Changed = false;
519 for (auto &Descriptor : Descriptors)
520 Changed |= Descriptor.performOnModule(M);
521
522 return Changed;
523 }
524
525 void RewriteSymbols::loadAndParseMapFiles() {
526 const std::vector MapFiles(RewriteMapFiles);
527 SymbolRewriter::RewriteMapParser parser;
528
529 for (const auto &MapFile : MapFiles)
530 parser.parse(MapFile, &Descriptors);
531 }
532 }
533
534 INITIALIZE_PASS(RewriteSymbols, "rewrite-symbols", "Rewrite Symbols", false,
535 false);
536
537 ModulePass *llvm::createRewriteSymbolsPass() { return new RewriteSymbols(); }
538
539 ModulePass *
540 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
541 return new RewriteSymbols(DL);
542 }
0 ; RUN: opt -mtriple i686-win32 -rewrite-symbols -rewrite-map-file %p/rewrite.map \
1 ; RUN: %s -o - | llvm-dis | FileCheck %s
2
3 declare void @source_function()
4 @source_variable = external global i32
5 declare void @source_function_pattern_function()
6 declare void @source_function_pattern_multiple_function_matches()
7 @source_variable_pattern_variable = external global i32
8 @source_variable_pattern_multiple_variable_matches = external global i32
9 declare void @"\01naked_source_function"()
10 declare void @"\01__imp_missing_global_leader_prefix"()
11
12 declare i32 @first_callee()
13 declare i32 @second_callee()
14 define i32 @caller() {
15 %rhs = call i32 @first_callee()
16 %lhs = call i32 @second_callee()
17 %res = add i32 %rhs, %lhs
18 ret i32 %res
19 }
20
21 %struct.S = type { i8 }
22 @_ZN1SC1Ev = alias void (%struct.S*)* @_ZN1SC2Ev
23 define void @_ZN1SC2Ev(%struct.S* %this) unnamed_addr align 2 {
24 entry:
25 %this.addr = alloca %struct.S*, align 4
26 store %struct.S* %this, %struct.S** %this.addr, align 4
27 ret void
28 }
29
30 ; CHECK: @target_variable = external global i32
31 ; CHECK-NOT: @source_variable = external global i32
32 ; CHECK: @target_pattern_variable = external global i32
33 ; CHECK-NOT: @source_pattern_variable = external global i32
34 ; CHECK: @target_pattern_multiple_variable_matches = external global i32
35 ; CHECK-NOT: @source_pattern_multiple_variable_matches = external global i32
36 ; CHECK: declare void @target_function()
37 ; CHECK-NOT: declare void @source_function()
38 ; CHECK: declare void @target_pattern_function()
39 ; CHECK-NOT: declare void @source_function_pattern_function()
40 ; CHECK: declare void @target_pattern_multiple_function_matches()
41 ; CHECK-NOT: declare void @source_function_pattern_multiple_function_matches()
42 ; CHECK: declare void @naked_target_function()
43 ; CHECK-NOT: declare void @"\01naked_source_function"()
44 ; CHECK-NOT: declare void @"\01__imp__imported_function"()
45 ; CHECK: declare void @"\01__imp_missing_global_leader_prefix"()
46 ; CHECK-NOT: declare void @"\01__imp_DO_NOT_REWRITE"()
47
48 ; CHECK: declare i32 @renamed_callee()
49 ; CHECK-NOT: declare i32 @first_callee()
50 ; CHECK: declare i32 @second_callee()
51 ; CHECK: define i32 @caller() {
52 ; CHECK: %rhs = call i32 @renamed_callee()
53 ; CHECK-NOT: %rhs = call i32 @first_callee()
54 ; CHECK: %lhs = call i32 @second_callee()
55 ; CHECK: %res = add i32 %rhs, %lhs
56 ; CHECK: ret i32 %res
57 ; CHECK: }
58
0 function: {
1 source: source_function,
2 target: target_function,
3 }
4
5 global variable: {
6 source: source_variable,
7 target: target_variable,
8 }
9
10 function: {
11 source: source_function_(.*),
12 transform: target_\1,
13 }
14
15 global variable: {
16 source: source_variable_(.*),
17 transform: target_\1,
18 }
19
20 function: {
21 source: naked_source_function,
22 target: naked_target_function,
23 naked: true,
24 }
25
26 function: {
27 source: imported_function,
28 target: exported_function,
29 }
30
31 function: {
32 source: missing_global_leader_prefix,
33 target: DO_NOT_REWRITE,
34 }
35
36 function: {
37 source: first_callee,
38 target: renamed_callee,
39 }
40
41 global alias: {
42 source: _ZN1SC1Ev,
43 target: _ZN1SD1Ev,
44 }
45
321321 // supported.
322322 initializeCodeGenPreparePass(Registry);
323323 initializeAtomicExpandPass(Registry);
324 initializeRewriteSymbolsPass(Registry);
324325
325326 #ifdef LINK_POLLY_INTO_TOOLS
326327 polly::initializePollyPasses(Registry);