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/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
), Source(Naked
? StringRef("\01" + S
.str()) : S
),
122 bool performOnModule(Module
&M
) override
;
124 static bool classof(const RewriteDescriptor
*RD
) {
125 return RD
->getType() == DT
;
129 } // end anonymous namespace
131 template <RewriteDescriptor::Type DT
, typename ValueType
,
132 ValueType
*(Module::*Get
)(StringRef
) const>
133 bool ExplicitRewriteDescriptor
<DT
, ValueType
, Get
>::performOnModule(Module
&M
) {
134 bool Changed
= false;
135 if (ValueType
*S
= (M
.*Get
)(Source
)) {
136 if (GlobalObject
*GO
= dyn_cast
<GlobalObject
>(S
))
137 rewriteComdat(M
, GO
, Source
, Target
);
139 if (Value
*T
= (M
.*Get
)(Target
))
140 S
->setValueName(T
->getValueName());
151 template <RewriteDescriptor::Type DT
, typename ValueType
,
152 ValueType
*(Module::*Get
)(StringRef
) const,
153 iterator_range
<typename iplist
<ValueType
>::iterator
>
154 (Module::*Iterator
)()>
155 class PatternRewriteDescriptor
: public RewriteDescriptor
{
157 const std::string Pattern
;
158 const std::string Transform
;
160 PatternRewriteDescriptor(StringRef P
, StringRef T
)
161 : RewriteDescriptor(DT
), Pattern(P
), Transform(T
) { }
163 bool performOnModule(Module
&M
) override
;
165 static bool classof(const RewriteDescriptor
*RD
) {
166 return RD
->getType() == DT
;
170 } // end anonymous namespace
172 template <RewriteDescriptor::Type DT
, typename ValueType
,
173 ValueType
*(Module::*Get
)(StringRef
) const,
174 iterator_range
<typename iplist
<ValueType
>::iterator
>
175 (Module::*Iterator
)()>
176 bool PatternRewriteDescriptor
<DT
, ValueType
, Get
, Iterator
>::
177 performOnModule(Module
&M
) {
178 bool Changed
= false;
179 for (auto &C
: (M
.*Iterator
)()) {
182 std::string Name
= Regex(Pattern
).sub(Transform
, C
.getName(), &Error
);
184 report_fatal_error("unable to transforn " + C
.getName() + " in " +
185 M
.getModuleIdentifier() + ": " + Error
);
187 if (C
.getName() == Name
)
190 if (GlobalObject
*GO
= dyn_cast
<GlobalObject
>(&C
))
191 rewriteComdat(M
, GO
, C
.getName(), Name
);
193 if (Value
*V
= (M
.*Get
)(Name
))
194 C
.setValueName(V
->getValueName());
205 /// Represents a rewrite for an explicitly named (function) symbol. Both the
206 /// source function name and target function name of the transformation are
207 /// explicitly spelt out.
208 using ExplicitRewriteFunctionDescriptor
=
209 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
210 &Module::getFunction
>;
212 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
213 /// the source variable name and target variable name are spelt out. This
214 /// applies only to module level variables.
215 using ExplicitRewriteGlobalVariableDescriptor
=
216 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
217 GlobalVariable
, &Module::getGlobalVariable
>;
219 /// Represents a rewrite for an explicitly named global alias. Both the source
220 /// and target name are explicitly spelt out.
221 using ExplicitRewriteNamedAliasDescriptor
=
222 ExplicitRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
223 &Module::getNamedAlias
>;
225 /// Represents a rewrite for a regular expression based pattern for functions.
226 /// A pattern for the function name is provided and a transformation for that
227 /// pattern to determine the target function name create the rewrite rule.
228 using PatternRewriteFunctionDescriptor
=
229 PatternRewriteDescriptor
<RewriteDescriptor::Type::Function
, Function
,
230 &Module::getFunction
, &Module::functions
>;
232 /// Represents a rewrite for a global variable based upon a matching pattern.
233 /// Each global variable matching the provided pattern will be transformed as
234 /// described in the transformation pattern for the target. Applies only to
235 /// module level variables.
236 using PatternRewriteGlobalVariableDescriptor
=
237 PatternRewriteDescriptor
<RewriteDescriptor::Type::GlobalVariable
,
238 GlobalVariable
, &Module::getGlobalVariable
,
241 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
242 /// aliases which match a given pattern. The provided transformation will be
243 /// applied to each of the matching names.
244 using PatternRewriteNamedAliasDescriptor
=
245 PatternRewriteDescriptor
<RewriteDescriptor::Type::NamedAlias
, GlobalAlias
,
246 &Module::getNamedAlias
, &Module::aliases
>;
248 } // end anonymous namespace
250 bool RewriteMapParser::parse(const std::string
&MapFile
,
251 RewriteDescriptorList
*DL
) {
252 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> Mapping
=
253 MemoryBuffer::getFile(MapFile
);
256 report_fatal_error("unable to read rewrite map '" + MapFile
+ "': " +
257 Mapping
.getError().message());
259 if (!parse(*Mapping
, DL
))
260 report_fatal_error("unable to parse rewrite map '" + MapFile
+ "'");
265 bool RewriteMapParser::parse(std::unique_ptr
<MemoryBuffer
> &MapFile
,
266 RewriteDescriptorList
*DL
) {
268 yaml::Stream
YS(MapFile
->getBuffer(), SM
);
270 for (auto &Document
: YS
) {
271 yaml::MappingNode
*DescriptorList
;
273 // ignore empty documents
274 if (isa
<yaml::NullNode
>(Document
.getRoot()))
277 DescriptorList
= dyn_cast
<yaml::MappingNode
>(Document
.getRoot());
278 if (!DescriptorList
) {
279 YS
.printError(Document
.getRoot(), "DescriptorList node must be a map");
283 for (auto &Descriptor
: *DescriptorList
)
284 if (!parseEntry(YS
, Descriptor
, DL
))
291 bool RewriteMapParser::parseEntry(yaml::Stream
&YS
, yaml::KeyValueNode
&Entry
,
292 RewriteDescriptorList
*DL
) {
293 yaml::ScalarNode
*Key
;
294 yaml::MappingNode
*Value
;
295 SmallString
<32> KeyStorage
;
296 StringRef RewriteType
;
298 Key
= dyn_cast
<yaml::ScalarNode
>(Entry
.getKey());
300 YS
.printError(Entry
.getKey(), "rewrite type must be a scalar");
304 Value
= dyn_cast
<yaml::MappingNode
>(Entry
.getValue());
306 YS
.printError(Entry
.getValue(), "rewrite descriptor must be a map");
310 RewriteType
= Key
->getValue(KeyStorage
);
311 if (RewriteType
.equals("function"))
312 return parseRewriteFunctionDescriptor(YS
, Key
, Value
, DL
);
313 else if (RewriteType
.equals("global variable"))
314 return parseRewriteGlobalVariableDescriptor(YS
, Key
, Value
, DL
);
315 else if (RewriteType
.equals("global alias"))
316 return parseRewriteGlobalAliasDescriptor(YS
, Key
, Value
, DL
);
318 YS
.printError(Entry
.getKey(), "unknown rewrite type");
322 bool RewriteMapParser::
323 parseRewriteFunctionDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
324 yaml::MappingNode
*Descriptor
,
325 RewriteDescriptorList
*DL
) {
329 std::string Transform
;
331 for (auto &Field
: *Descriptor
) {
332 yaml::ScalarNode
*Key
;
333 yaml::ScalarNode
*Value
;
334 SmallString
<32> KeyStorage
;
335 SmallString
<32> ValueStorage
;
338 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
340 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
344 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
346 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
350 KeyValue
= Key
->getValue(KeyStorage
);
351 if (KeyValue
.equals("source")) {
354 Source
= Value
->getValue(ValueStorage
);
355 if (!Regex(Source
).isValid(Error
)) {
356 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
359 } else if (KeyValue
.equals("target")) {
360 Target
= Value
->getValue(ValueStorage
);
361 } else if (KeyValue
.equals("transform")) {
362 Transform
= Value
->getValue(ValueStorage
);
363 } else if (KeyValue
.equals("naked")) {
364 std::string Undecorated
;
366 Undecorated
= Value
->getValue(ValueStorage
);
367 Naked
= StringRef(Undecorated
).lower() == "true" || Undecorated
== "1";
369 YS
.printError(Field
.getKey(), "unknown key for function");
374 if (Transform
.empty() == Target
.empty()) {
375 YS
.printError(Descriptor
,
376 "exactly one of transform or target must be specified");
380 // TODO see if there is a more elegant solution to selecting the rewrite
383 DL
->push_back(llvm::make_unique
<ExplicitRewriteFunctionDescriptor
>(
384 Source
, Target
, Naked
));
387 llvm::make_unique
<PatternRewriteFunctionDescriptor
>(Source
, Transform
));
392 bool RewriteMapParser::
393 parseRewriteGlobalVariableDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
394 yaml::MappingNode
*Descriptor
,
395 RewriteDescriptorList
*DL
) {
398 std::string Transform
;
400 for (auto &Field
: *Descriptor
) {
401 yaml::ScalarNode
*Key
;
402 yaml::ScalarNode
*Value
;
403 SmallString
<32> KeyStorage
;
404 SmallString
<32> ValueStorage
;
407 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
409 YS
.printError(Field
.getKey(), "descriptor Key must be a scalar");
413 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
415 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
419 KeyValue
= Key
->getValue(KeyStorage
);
420 if (KeyValue
.equals("source")) {
423 Source
= Value
->getValue(ValueStorage
);
424 if (!Regex(Source
).isValid(Error
)) {
425 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
428 } else if (KeyValue
.equals("target")) {
429 Target
= Value
->getValue(ValueStorage
);
430 } else if (KeyValue
.equals("transform")) {
431 Transform
= Value
->getValue(ValueStorage
);
433 YS
.printError(Field
.getKey(), "unknown Key for Global Variable");
438 if (Transform
.empty() == Target
.empty()) {
439 YS
.printError(Descriptor
,
440 "exactly one of transform or target must be specified");
445 DL
->push_back(llvm::make_unique
<ExplicitRewriteGlobalVariableDescriptor
>(
449 DL
->push_back(llvm::make_unique
<PatternRewriteGlobalVariableDescriptor
>(
455 bool RewriteMapParser::
456 parseRewriteGlobalAliasDescriptor(yaml::Stream
&YS
, yaml::ScalarNode
*K
,
457 yaml::MappingNode
*Descriptor
,
458 RewriteDescriptorList
*DL
) {
461 std::string Transform
;
463 for (auto &Field
: *Descriptor
) {
464 yaml::ScalarNode
*Key
;
465 yaml::ScalarNode
*Value
;
466 SmallString
<32> KeyStorage
;
467 SmallString
<32> ValueStorage
;
470 Key
= dyn_cast
<yaml::ScalarNode
>(Field
.getKey());
472 YS
.printError(Field
.getKey(), "descriptor key must be a scalar");
476 Value
= dyn_cast
<yaml::ScalarNode
>(Field
.getValue());
478 YS
.printError(Field
.getValue(), "descriptor value must be a scalar");
482 KeyValue
= Key
->getValue(KeyStorage
);
483 if (KeyValue
.equals("source")) {
486 Source
= Value
->getValue(ValueStorage
);
487 if (!Regex(Source
).isValid(Error
)) {
488 YS
.printError(Field
.getKey(), "invalid regex: " + Error
);
491 } else if (KeyValue
.equals("target")) {
492 Target
= Value
->getValue(ValueStorage
);
493 } else if (KeyValue
.equals("transform")) {
494 Transform
= Value
->getValue(ValueStorage
);
496 YS
.printError(Field
.getKey(), "unknown key for Global Alias");
501 if (Transform
.empty() == Target
.empty()) {
502 YS
.printError(Descriptor
,
503 "exactly one of transform or target must be specified");
508 DL
->push_back(llvm::make_unique
<ExplicitRewriteNamedAliasDescriptor
>(
512 DL
->push_back(llvm::make_unique
<PatternRewriteNamedAliasDescriptor
>(
520 class RewriteSymbolsLegacyPass
: public ModulePass
{
522 static char ID
; // Pass identification, replacement for typeid
524 RewriteSymbolsLegacyPass();
525 RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList
&DL
);
527 bool runOnModule(Module
&M
) override
;
530 RewriteSymbolPass Impl
;
533 } // end anonymous namespace
535 char RewriteSymbolsLegacyPass::ID
= 0;
537 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID
) {
538 initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
541 RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
542 SymbolRewriter::RewriteDescriptorList
&DL
)
543 : ModulePass(ID
), Impl(DL
) {}
545 bool RewriteSymbolsLegacyPass::runOnModule(Module
&M
) {
546 return Impl
.runImpl(M
);
549 PreservedAnalyses
RewriteSymbolPass::run(Module
&M
, ModuleAnalysisManager
&AM
) {
551 return PreservedAnalyses::all();
553 return PreservedAnalyses::none();
556 bool RewriteSymbolPass::runImpl(Module
&M
) {
560 for (auto &Descriptor
: Descriptors
)
561 Changed
|= Descriptor
->performOnModule(M
);
566 void RewriteSymbolPass::loadAndParseMapFiles() {
567 const std::vector
<std::string
> MapFiles(RewriteMapFiles
);
568 SymbolRewriter::RewriteMapParser Parser
;
570 for (const auto &MapFile
: MapFiles
)
571 Parser
.parse(MapFile
, &Descriptors
);
574 INITIALIZE_PASS(RewriteSymbolsLegacyPass
, "rewrite-symbols", "Rewrite Symbols",
577 ModulePass
*llvm::createRewriteSymbolsPass() {
578 return new RewriteSymbolsLegacyPass();
582 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList
&DL
) {
583 return new RewriteSymbolsLegacyPass(DL
);