1 //===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
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.
13 // The YAML configuration file format is as follows:
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]+
25 // Currently, the following descriptor types are supported:
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)
41 // Note that source and exactly one of [Target, Transform] must be provided
43 // New rewrite descriptors can be created. Addding a new rewrite descriptor
46 // a) extended the rewrite descriptor kind enumeration
47 // (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
48 // b) implementing the new descriptor
49 // (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
50 // c) extending the rewrite map parser
51 // (<anonymous>::RewriteMapParser::parseEntry)
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`
57 //===----------------------------------------------------------------------===//
59 #include "llvm/Transforms/Utils/SymbolRewriter.h"
60 #include "llvm/ADT/STLExtras.h"
61 #include "llvm/ADT/SmallString.h"
62 #include "llvm/ADT/StringRef.h"
63 #include "llvm/ADT/ilist.h"
64 #include "llvm/ADT/iterator_range.h"
65 #include "llvm/IR/Comdat.h"
66 #include "llvm/IR/Function.h"
67 #include "llvm/IR/GlobalAlias.h"
68 #include "llvm/IR/GlobalObject.h"
69 #include "llvm/IR/GlobalVariable.h"
70 #include "llvm/IR/Module.h"
71 #include "llvm/IR/Value.h"
72 #include "llvm/InitializePasses.h"
73 #include "llvm/Pass.h"
74 #include "llvm/Support/Casting.h"
75 #include "llvm/Support/CommandLine.h"
76 #include "llvm/Support/ErrorHandling.h"
77 #include "llvm/Support/ErrorOr.h"
78 #include "llvm/Support/MemoryBuffer.h"
79 #include "llvm/Support/Regex.h"
80 #include "llvm/Support/SourceMgr.h"
81 #include "llvm/Support/YAMLParser.h"
87 using namespace SymbolRewriter
;
89 #define DEBUG_TYPE "symbol-rewriter"
91 static cl::list
<std::string
> RewriteMapFiles("rewrite-map-file",
92 cl::desc("Symbol Rewrite Map"),
93 cl::value_desc("filename"),
96 static void rewriteComdat(Module
&M
, GlobalObject
*GO
,
97 const std::string
&Source
,
98 const std::string
&Target
) {
99 if (Comdat
*CD
= GO
->getComdat()) {
100 auto &Comdats
= M
.getComdatSymbolTable();
102 Comdat
*C
= M
.getOrInsertComdat(Target
);
103 C
->setSelectionKind(CD
->getSelectionKind());
106 Comdats
.erase(Comdats
.find(Source
));
112 template <RewriteDescriptor::Type DT
, typename ValueType
,
113 ValueType
*(Module::*Get
)(StringRef
) const>
114 class ExplicitRewriteDescriptor
: public RewriteDescriptor
{
116 const std::string Source
;
117 const std::string Target
;
119 ExplicitRewriteDescriptor(StringRef S
, StringRef T
, const bool Naked
)
120 : RewriteDescriptor(DT
), Source(Naked
? StringRef("\01" + S
.str()) : S
),
123 bool performOnModule(Module
&M
) override
;
125 static bool classof(const RewriteDescriptor
*RD
) {
126 return RD
->getType() == DT
;
130 } // end anonymous namespace
132 template <RewriteDescriptor::Type DT
, typename ValueType
,
133 ValueType
*(Module::*Get
)(StringRef
) const>
134 bool ExplicitRewriteDescriptor
<DT
, ValueType
, Get
>::performOnModule(Module
&M
) {
135 bool Changed
= false;
136 if (ValueType
*S
= (M
.*Get
)(Source
)) {
137 if (GlobalObject
*GO
= dyn_cast
<GlobalObject
>(S
))
138 rewriteComdat(M
, GO
, Source
, Target
);
140 if (Value
*T
= (M
.*Get
)(Target
))
141 S
->setValueName(T
->getValueName());
152 template <RewriteDescriptor::Type DT
, typename ValueType
,
153 ValueType
*(Module::*Get
)(StringRef
) const,
154 iterator_range
<typename iplist
<ValueType
>::iterator
>
155 (Module::*Iterator
)()>
156 class PatternRewriteDescriptor
: public RewriteDescriptor
{
158 const std::string Pattern
;
159 const std::string Transform
;
161 PatternRewriteDescriptor(StringRef P
, StringRef T
)
162 : RewriteDescriptor(DT
), Pattern(P
), Transform(T
) { }
164 bool performOnModule(Module
&M
) override
;
166 static bool classof(const RewriteDescriptor
*RD
) {
167 return RD
->getType() == DT
;
171 } // end anonymous namespace
173 template <RewriteDescriptor::Type DT
, typename ValueType
,
174 ValueType
*(Module::*Get
)(StringRef
) const,
175 iterator_range
<typename iplist
<ValueType
>::iterator
>
176 (Module::*Iterator
)()>
177 bool PatternRewriteDescriptor
<DT
, ValueType
, Get
, Iterator
>::
178 performOnModule(Module
&M
) {
179 bool Changed
= false;
180 for (auto &C
: (M
.*Iterator
)()) {
183 std::string Name
= Regex(Pattern
).sub(Transform
, C
.getName(), &Error
);
185 report_fatal_error("unable to transforn " + C
.getName() + " in " +
186 M
.getModuleIdentifier() + ": " + Error
);
188 if (C
.getName() == Name
)
191 if (GlobalObject
*GO
= dyn_cast
<GlobalObject
>(&C
))
192 rewriteComdat(M
, GO
, C
.getName(), Name
);
194 if (Value
*V
= (M
.*Get
)(Name
))
195 C
.setValueName(V
->getValueName());
206 /// Represents a rewrite for an explicitly named (function) symbol. Both the
207 /// source function name and target function name of the transformation are
208 /// explicitly spelt out.
209 using ExplicitRewriteFunctionDescriptor
=
210 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
211 &Module::getFunction
>;
213 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
214 /// the source variable name and target variable name are spelt out. This
215 /// applies only to module level variables.
216 using ExplicitRewriteGlobalVariableDescriptor
=
217 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
218 GlobalVariable
, &Module::getGlobalVariable
>;
220 /// Represents a rewrite for an explicitly named global alias. Both the source
221 /// and target name are explicitly spelt out.
222 using ExplicitRewriteNamedAliasDescriptor
=
223 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
224 &Module::getNamedAlias
>;
226 /// Represents a rewrite for a regular expression based pattern for functions.
227 /// A pattern for the function name is provided and a transformation for that
228 /// pattern to determine the target function name create the rewrite rule.
229 using PatternRewriteFunctionDescriptor
=
230 PatternRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
231 &Module::getFunction
, &Module::functions
>;
233 /// Represents a rewrite for a global variable based upon a matching pattern.
234 /// Each global variable matching the provided pattern will be transformed as
235 /// described in the transformation pattern for the target. Applies only to
236 /// module level variables.
237 using PatternRewriteGlobalVariableDescriptor
=
238 PatternRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
239 GlobalVariable
, &Module::getGlobalVariable
,
242 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
243 /// aliases which match a given pattern. The provided transformation will be
244 /// applied to each of the matching names.
245 using PatternRewriteNamedAliasDescriptor
=
246 PatternRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
247 &Module::getNamedAlias
, &Module::aliases
>;
249 } // end anonymous namespace
251 bool RewriteMapParser::parse(const std::string
&MapFile
,
252 RewriteDescriptorList
*DL
) {
253 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Mapping
=
254 MemoryBuffer::getFile(MapFile
);
257 report_fatal_error("unable to read rewrite map '" + MapFile
+ "': " +
258 Mapping
.getError().message());
260 if (!parse(*Mapping
, DL
))
261 report_fatal_error("unable to parse rewrite map '" + MapFile
+ "'");
266 bool RewriteMapParser::parse(std::unique_ptr
<MemoryBuffer
> &MapFile
,
267 RewriteDescriptorList
*DL
) {
269 yaml::Stream
YS(MapFile
->getBuffer(), SM
);
271 for (auto &Document
: YS
) {
272 yaml::MappingNode
*DescriptorList
;
274 // ignore empty documents
275 if (isa
<yaml::NullNode
>(Document
.getRoot()))
278 DescriptorList
= dyn_cast
<yaml::MappingNode
>(Document
.getRoot());
279 if (!DescriptorList
) {
280 YS
.printError(Document
.getRoot(), "DescriptorList node must be a map");
284 for (auto &Descriptor
: *DescriptorList
)
285 if (!parseEntry(YS
, Descriptor
, DL
))
292 bool RewriteMapParser::parseEntry(yaml::Stream
&YS
, yaml::KeyValueNode
&Entry
,
293 RewriteDescriptorList
*DL
) {
294 yaml::ScalarNode
*Key
;
295 yaml::MappingNode
*Value
;
296 SmallString
<32> KeyStorage
;
297 StringRef RewriteType
;
299 Key
= dyn_cast
<yaml::ScalarNode
>(Entry
.getKey());
301 YS
.printError(Entry
.getKey(), "rewrite type must be a scalar");
305 Value
= dyn_cast
<yaml::MappingNode
>(Entry
.getValue());
307 YS
.printError(Entry
.getValue(), "rewrite descriptor must be a map");
311 RewriteType
= Key
->getValue(KeyStorage
);
312 if (RewriteType
.equals("function"))
313 return parseRewriteFunctionDescriptor(YS
, Key
, Value
, DL
);
314 else if (RewriteType
.equals("global variable"))
315 return parseRewriteGlobalVariableDescriptor(YS
, Key
, Value
, DL
);
316 else if (RewriteType
.equals("global alias"))
317 return parseRewriteGlobalAliasDescriptor(YS
, Key
, Value
, DL
);
319 YS
.printError(Entry
.getKey(), "unknown rewrite type");
323 bool RewriteMapParser::
324 parseRewriteFunctionDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
325 yaml::MappingNode
*Descriptor
,
326 RewriteDescriptorList
*DL
) {
330 std::string Transform
;
332 for (auto &Field
: *Descriptor
) {
333 yaml::ScalarNode
*Key
;
334 yaml::ScalarNode
*Value
;
335 SmallString
<32> KeyStorage
;
336 SmallString
<32> ValueStorage
;
339 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
341 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
345 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
347 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
351 KeyValue
= Key
->getValue(KeyStorage
);
352 if (KeyValue
.equals("source")) {
355 Source
= Value
->getValue(ValueStorage
);
356 if (!Regex(Source
).isValid(Error
)) {
357 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
360 } else if (KeyValue
.equals("target")) {
361 Target
= Value
->getValue(ValueStorage
);
362 } else if (KeyValue
.equals("transform")) {
363 Transform
= Value
->getValue(ValueStorage
);
364 } else if (KeyValue
.equals("naked")) {
365 std::string Undecorated
;
367 Undecorated
= Value
->getValue(ValueStorage
);
368 Naked
= StringRef(Undecorated
).lower() == "true" || Undecorated
== "1";
370 YS
.printError(Field
.getKey(), "unknown key for function");
375 if (Transform
.empty() == Target
.empty()) {
376 YS
.printError(Descriptor
,
377 "exactly one of transform or target must be specified");
381 // TODO see if there is a more elegant solution to selecting the rewrite
384 DL
->push_back(std::make_unique
<ExplicitRewriteFunctionDescriptor
>(
385 Source
, Target
, Naked
));
388 std::make_unique
<PatternRewriteFunctionDescriptor
>(Source
, Transform
));
393 bool RewriteMapParser::
394 parseRewriteGlobalVariableDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
395 yaml::MappingNode
*Descriptor
,
396 RewriteDescriptorList
*DL
) {
399 std::string Transform
;
401 for (auto &Field
: *Descriptor
) {
402 yaml::ScalarNode
*Key
;
403 yaml::ScalarNode
*Value
;
404 SmallString
<32> KeyStorage
;
405 SmallString
<32> ValueStorage
;
408 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
410 YS
.printError(Field
.getKey(), "descriptor Key must be a scalar");
414 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
416 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
420 KeyValue
= Key
->getValue(KeyStorage
);
421 if (KeyValue
.equals("source")) {
424 Source
= Value
->getValue(ValueStorage
);
425 if (!Regex(Source
).isValid(Error
)) {
426 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
429 } else if (KeyValue
.equals("target")) {
430 Target
= Value
->getValue(ValueStorage
);
431 } else if (KeyValue
.equals("transform")) {
432 Transform
= Value
->getValue(ValueStorage
);
434 YS
.printError(Field
.getKey(), "unknown Key for Global Variable");
439 if (Transform
.empty() == Target
.empty()) {
440 YS
.printError(Descriptor
,
441 "exactly one of transform or target must be specified");
446 DL
->push_back(std::make_unique
<ExplicitRewriteGlobalVariableDescriptor
>(
450 DL
->push_back(std::make_unique
<PatternRewriteGlobalVariableDescriptor
>(
456 bool RewriteMapParser::
457 parseRewriteGlobalAliasDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
458 yaml::MappingNode
*Descriptor
,
459 RewriteDescriptorList
*DL
) {
462 std::string Transform
;
464 for (auto &Field
: *Descriptor
) {
465 yaml::ScalarNode
*Key
;
466 yaml::ScalarNode
*Value
;
467 SmallString
<32> KeyStorage
;
468 SmallString
<32> ValueStorage
;
471 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
473 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
477 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
479 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
483 KeyValue
= Key
->getValue(KeyStorage
);
484 if (KeyValue
.equals("source")) {
487 Source
= Value
->getValue(ValueStorage
);
488 if (!Regex(Source
).isValid(Error
)) {
489 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
492 } else if (KeyValue
.equals("target")) {
493 Target
= Value
->getValue(ValueStorage
);
494 } else if (KeyValue
.equals("transform")) {
495 Transform
= Value
->getValue(ValueStorage
);
497 YS
.printError(Field
.getKey(), "unknown key for Global Alias");
502 if (Transform
.empty() == Target
.empty()) {
503 YS
.printError(Descriptor
,
504 "exactly one of transform or target must be specified");
509 DL
->push_back(std::make_unique
<ExplicitRewriteNamedAliasDescriptor
>(
513 DL
->push_back(std::make_unique
<PatternRewriteNamedAliasDescriptor
>(
521 class RewriteSymbolsLegacyPass
: public ModulePass
{
523 static char ID
; // Pass identification, replacement for typeid
525 RewriteSymbolsLegacyPass();
526 RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList
&DL
);
528 bool runOnModule(Module
&M
) override
;
531 RewriteSymbolPass Impl
;
534 } // end anonymous namespace
536 char RewriteSymbolsLegacyPass::ID
= 0;
538 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID
) {
539 initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
542 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
543 SymbolRewriter::RewriteDescriptorList
&DL
)
544 : ModulePass(ID
), Impl(DL
) {}
546 bool RewriteSymbolsLegacyPass::runOnModule(Module
&M
) {
547 return Impl
.runImpl(M
);
550 PreservedAnalyses
RewriteSymbolPass::run(Module
&M
, ModuleAnalysisManager
&AM
) {
552 return PreservedAnalyses::all();
554 return PreservedAnalyses::none();
557 bool RewriteSymbolPass::runImpl(Module
&M
) {
561 for (auto &Descriptor
: Descriptors
)
562 Changed
|= Descriptor
->performOnModule(M
);
567 void RewriteSymbolPass::loadAndParseMapFiles() {
568 const std::vector
<std::string
> MapFiles(RewriteMapFiles
);
569 SymbolRewriter::RewriteMapParser Parser
;
571 for (const auto &MapFile
: MapFiles
)
572 Parser
.parse(MapFile
, &Descriptors
);
575 INITIALIZE_PASS(RewriteSymbolsLegacyPass
, "rewrite-symbols", "Rewrite Symbols",
578 ModulePass
*llvm::createRewriteSymbolsPass() {
579 return new RewriteSymbolsLegacyPass();
583 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList
&DL
) {
584 return new RewriteSymbolsLegacyPass(DL
);