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/SmallString.h"
61 #include "llvm/ADT/StringRef.h"
62 #include "llvm/ADT/ilist.h"
63 #include "llvm/ADT/iterator_range.h"
64 #include "llvm/IR/Comdat.h"
65 #include "llvm/IR/Function.h"
66 #include "llvm/IR/GlobalAlias.h"
67 #include "llvm/IR/GlobalObject.h"
68 #include "llvm/IR/GlobalVariable.h"
69 #include "llvm/IR/Module.h"
70 #include "llvm/IR/Value.h"
71 #include "llvm/InitializePasses.h"
72 #include "llvm/Pass.h"
73 #include "llvm/Support/Casting.h"
74 #include "llvm/Support/CommandLine.h"
75 #include "llvm/Support/ErrorHandling.h"
76 #include "llvm/Support/ErrorOr.h"
77 #include "llvm/Support/MemoryBuffer.h"
78 #include "llvm/Support/Regex.h"
79 #include "llvm/Support/SourceMgr.h"
80 #include "llvm/Support/YAMLParser.h"
86 using namespace SymbolRewriter
;
88 #define DEBUG_TYPE "symbol-rewriter"
90 static cl::list
<std::string
> RewriteMapFiles("rewrite-map-file",
91 cl::desc("Symbol Rewrite Map"),
92 cl::value_desc("filename"),
95 static void rewriteComdat(Module
&M
, GlobalObject
*GO
,
96 const std::string
&Source
,
97 const std::string
&Target
) {
98 if (Comdat
*CD
= GO
->getComdat()) {
99 auto &Comdats
= M
.getComdatSymbolTable();
101 Comdat
*C
= M
.getOrInsertComdat(Target
);
102 C
->setSelectionKind(CD
->getSelectionKind());
105 Comdats
.erase(Comdats
.find(Source
));
111 template <RewriteDescriptor::Type DT
, typename ValueType
,
112 ValueType
*(Module::*Get
)(StringRef
) const>
113 class ExplicitRewriteDescriptor
: public RewriteDescriptor
{
115 const std::string Source
;
116 const std::string Target
;
118 ExplicitRewriteDescriptor(StringRef S
, StringRef T
, const bool Naked
)
119 : RewriteDescriptor(DT
),
120 Source(std::string(Naked
? StringRef("\01" + S
.str()) : S
)),
121 Target(std::string(T
)) {}
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(std::string(P
)),
163 Transform(std::string(T
)) {}
165 bool performOnModule(Module
&M
) override
;
167 static bool classof(const RewriteDescriptor
*RD
) {
168 return RD
->getType() == DT
;
172 } // end anonymous namespace
174 template <RewriteDescriptor::Type DT
, typename ValueType
,
175 ValueType
*(Module::*Get
)(StringRef
) const,
176 iterator_range
<typename iplist
<ValueType
>::iterator
>
177 (Module::*Iterator
)()>
178 bool PatternRewriteDescriptor
<DT
, ValueType
, Get
, Iterator
>::
179 performOnModule(Module
&M
) {
180 bool Changed
= false;
181 for (auto &C
: (M
.*Iterator
)()) {
184 std::string Name
= Regex(Pattern
).sub(Transform
, C
.getName(), &Error
);
186 report_fatal_error(Twine("unable to transforn ") + C
.getName() + " in " +
187 M
.getModuleIdentifier() + ": " + Error
);
189 if (C
.getName() == Name
)
192 if (GlobalObject
*GO
= dyn_cast
<GlobalObject
>(&C
))
193 rewriteComdat(M
, GO
, std::string(C
.getName()), Name
);
195 if (Value
*V
= (M
.*Get
)(Name
))
196 C
.setValueName(V
->getValueName());
207 /// Represents a rewrite for an explicitly named (function) symbol. Both the
208 /// source function name and target function name of the transformation are
209 /// explicitly spelt out.
210 using ExplicitRewriteFunctionDescriptor
=
211 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
212 &Module::getFunction
>;
214 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
215 /// the source variable name and target variable name are spelt out. This
216 /// applies only to module level variables.
217 using ExplicitRewriteGlobalVariableDescriptor
=
218 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
219 GlobalVariable
, &Module::getGlobalVariable
>;
221 /// Represents a rewrite for an explicitly named global alias. Both the source
222 /// and target name are explicitly spelt out.
223 using ExplicitRewriteNamedAliasDescriptor
=
224 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
225 &Module::getNamedAlias
>;
227 /// Represents a rewrite for a regular expression based pattern for functions.
228 /// A pattern for the function name is provided and a transformation for that
229 /// pattern to determine the target function name create the rewrite rule.
230 using PatternRewriteFunctionDescriptor
=
231 PatternRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
232 &Module::getFunction
, &Module::functions
>;
234 /// Represents a rewrite for a global variable based upon a matching pattern.
235 /// Each global variable matching the provided pattern will be transformed as
236 /// described in the transformation pattern for the target. Applies only to
237 /// module level variables.
238 using PatternRewriteGlobalVariableDescriptor
=
239 PatternRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
240 GlobalVariable
, &Module::getGlobalVariable
,
243 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
244 /// aliases which match a given pattern. The provided transformation will be
245 /// applied to each of the matching names.
246 using PatternRewriteNamedAliasDescriptor
=
247 PatternRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
248 &Module::getNamedAlias
, &Module::aliases
>;
250 } // end anonymous namespace
252 bool RewriteMapParser::parse(const std::string
&MapFile
,
253 RewriteDescriptorList
*DL
) {
254 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Mapping
=
255 MemoryBuffer::getFile(MapFile
);
258 report_fatal_error(Twine("unable to read rewrite map '") + MapFile
+
259 "': " + Mapping
.getError().message());
261 if (!parse(*Mapping
, DL
))
262 report_fatal_error(Twine("unable to parse rewrite map '") + MapFile
+ "'");
267 bool RewriteMapParser::parse(std::unique_ptr
<MemoryBuffer
> &MapFile
,
268 RewriteDescriptorList
*DL
) {
270 yaml::Stream
YS(MapFile
->getBuffer(), SM
);
272 for (auto &Document
: YS
) {
273 yaml::MappingNode
*DescriptorList
;
275 // ignore empty documents
276 if (isa
<yaml::NullNode
>(Document
.getRoot()))
279 DescriptorList
= dyn_cast
<yaml::MappingNode
>(Document
.getRoot());
280 if (!DescriptorList
) {
281 YS
.printError(Document
.getRoot(), "DescriptorList node must be a map");
285 for (auto &Descriptor
: *DescriptorList
)
286 if (!parseEntry(YS
, Descriptor
, DL
))
293 bool RewriteMapParser::parseEntry(yaml::Stream
&YS
, yaml::KeyValueNode
&Entry
,
294 RewriteDescriptorList
*DL
) {
295 yaml::ScalarNode
*Key
;
296 yaml::MappingNode
*Value
;
297 SmallString
<32> KeyStorage
;
298 StringRef RewriteType
;
300 Key
= dyn_cast
<yaml::ScalarNode
>(Entry
.getKey());
302 YS
.printError(Entry
.getKey(), "rewrite type must be a scalar");
306 Value
= dyn_cast
<yaml::MappingNode
>(Entry
.getValue());
308 YS
.printError(Entry
.getValue(), "rewrite descriptor must be a map");
312 RewriteType
= Key
->getValue(KeyStorage
);
313 if (RewriteType
.equals("function"))
314 return parseRewriteFunctionDescriptor(YS
, Key
, Value
, DL
);
315 else if (RewriteType
.equals("global variable"))
316 return parseRewriteGlobalVariableDescriptor(YS
, Key
, Value
, DL
);
317 else if (RewriteType
.equals("global alias"))
318 return parseRewriteGlobalAliasDescriptor(YS
, Key
, Value
, DL
);
320 YS
.printError(Entry
.getKey(), "unknown rewrite type");
324 bool RewriteMapParser::
325 parseRewriteFunctionDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
326 yaml::MappingNode
*Descriptor
,
327 RewriteDescriptorList
*DL
) {
331 std::string Transform
;
333 for (auto &Field
: *Descriptor
) {
334 yaml::ScalarNode
*Key
;
335 yaml::ScalarNode
*Value
;
336 SmallString
<32> KeyStorage
;
337 SmallString
<32> ValueStorage
;
340 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
342 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
346 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
348 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
352 KeyValue
= Key
->getValue(KeyStorage
);
353 if (KeyValue
.equals("source")) {
356 Source
= std::string(Value
->getValue(ValueStorage
));
357 if (!Regex(Source
).isValid(Error
)) {
358 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
361 } else if (KeyValue
.equals("target")) {
362 Target
= std::string(Value
->getValue(ValueStorage
));
363 } else if (KeyValue
.equals("transform")) {
364 Transform
= std::string(Value
->getValue(ValueStorage
));
365 } else if (KeyValue
.equals("naked")) {
366 std::string Undecorated
;
368 Undecorated
= std::string(Value
->getValue(ValueStorage
));
369 Naked
= StringRef(Undecorated
).lower() == "true" || Undecorated
== "1";
371 YS
.printError(Field
.getKey(), "unknown key for function");
376 if (Transform
.empty() == Target
.empty()) {
377 YS
.printError(Descriptor
,
378 "exactly one of transform or target must be specified");
382 // TODO see if there is a more elegant solution to selecting the rewrite
385 DL
->push_back(std::make_unique
<ExplicitRewriteFunctionDescriptor
>(
386 Source
, Target
, Naked
));
389 std::make_unique
<PatternRewriteFunctionDescriptor
>(Source
, Transform
));
394 bool RewriteMapParser::
395 parseRewriteGlobalVariableDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
396 yaml::MappingNode
*Descriptor
,
397 RewriteDescriptorList
*DL
) {
400 std::string Transform
;
402 for (auto &Field
: *Descriptor
) {
403 yaml::ScalarNode
*Key
;
404 yaml::ScalarNode
*Value
;
405 SmallString
<32> KeyStorage
;
406 SmallString
<32> ValueStorage
;
409 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
411 YS
.printError(Field
.getKey(), "descriptor Key must be a scalar");
415 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
417 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
421 KeyValue
= Key
->getValue(KeyStorage
);
422 if (KeyValue
.equals("source")) {
425 Source
= std::string(Value
->getValue(ValueStorage
));
426 if (!Regex(Source
).isValid(Error
)) {
427 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
430 } else if (KeyValue
.equals("target")) {
431 Target
= std::string(Value
->getValue(ValueStorage
));
432 } else if (KeyValue
.equals("transform")) {
433 Transform
= std::string(Value
->getValue(ValueStorage
));
435 YS
.printError(Field
.getKey(), "unknown Key for Global Variable");
440 if (Transform
.empty() == Target
.empty()) {
441 YS
.printError(Descriptor
,
442 "exactly one of transform or target must be specified");
447 DL
->push_back(std::make_unique
<ExplicitRewriteGlobalVariableDescriptor
>(
451 DL
->push_back(std::make_unique
<PatternRewriteGlobalVariableDescriptor
>(
457 bool RewriteMapParser::
458 parseRewriteGlobalAliasDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
459 yaml::MappingNode
*Descriptor
,
460 RewriteDescriptorList
*DL
) {
463 std::string Transform
;
465 for (auto &Field
: *Descriptor
) {
466 yaml::ScalarNode
*Key
;
467 yaml::ScalarNode
*Value
;
468 SmallString
<32> KeyStorage
;
469 SmallString
<32> ValueStorage
;
472 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
474 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
478 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
480 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
484 KeyValue
= Key
->getValue(KeyStorage
);
485 if (KeyValue
.equals("source")) {
488 Source
= std::string(Value
->getValue(ValueStorage
));
489 if (!Regex(Source
).isValid(Error
)) {
490 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
493 } else if (KeyValue
.equals("target")) {
494 Target
= std::string(Value
->getValue(ValueStorage
));
495 } else if (KeyValue
.equals("transform")) {
496 Transform
= std::string(Value
->getValue(ValueStorage
));
498 YS
.printError(Field
.getKey(), "unknown key for Global Alias");
503 if (Transform
.empty() == Target
.empty()) {
504 YS
.printError(Descriptor
,
505 "exactly one of transform or target must be specified");
510 DL
->push_back(std::make_unique
<ExplicitRewriteNamedAliasDescriptor
>(
514 DL
->push_back(std::make_unique
<PatternRewriteNamedAliasDescriptor
>(
522 class RewriteSymbolsLegacyPass
: public ModulePass
{
524 static char ID
; // Pass identification, replacement for typeid
526 RewriteSymbolsLegacyPass();
527 RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList
&DL
);
529 bool runOnModule(Module
&M
) override
;
532 RewriteSymbolPass Impl
;
535 } // end anonymous namespace
537 char RewriteSymbolsLegacyPass::ID
= 0;
539 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID
) {
540 initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
543 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
544 SymbolRewriter::RewriteDescriptorList
&DL
)
545 : ModulePass(ID
), Impl(DL
) {}
547 bool RewriteSymbolsLegacyPass::runOnModule(Module
&M
) {
548 return Impl
.runImpl(M
);
551 PreservedAnalyses
RewriteSymbolPass::run(Module
&M
, ModuleAnalysisManager
&AM
) {
553 return PreservedAnalyses::all();
555 return PreservedAnalyses::none();
558 bool RewriteSymbolPass::runImpl(Module
&M
) {
562 for (auto &Descriptor
: Descriptors
)
563 Changed
|= Descriptor
->performOnModule(M
);
568 void RewriteSymbolPass::loadAndParseMapFiles() {
569 const std::vector
<std::string
> MapFiles(RewriteMapFiles
);
570 SymbolRewriter::RewriteMapParser Parser
;
572 for (const auto &MapFile
: MapFiles
)
573 Parser
.parse(MapFile
, &Descriptors
);
576 INITIALIZE_PASS(RewriteSymbolsLegacyPass
, "rewrite-symbols", "Rewrite Symbols",
579 ModulePass
*llvm::createRewriteSymbolsPass() {
580 return new RewriteSymbolsLegacyPass();
584 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList
&DL
) {
585 return new RewriteSymbolsLegacyPass(DL
);