1 //===- SymbolRewriter.cpp - Symbol Rewriter ---------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 // The YAML configuration file format is as follows:
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]+
26 // Currently, the following descriptor types are supported:
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)
42 // Note that source and exactly one of [Target, Transform] must be provided
44 // New rewrite descriptors can be created. Addding a new rewrite descriptor
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)
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`
58 //===----------------------------------------------------------------------===//
60 #define DEBUG_TYPE "symbol-rewriter"
61 #include "llvm/CodeGen/Passes.h"
62 #include "llvm/Pass.h"
63 #include "llvm/PassManager.h"
64 #include "llvm/Support/CommandLine.h"
65 #include "llvm/Support/Debug.h"
66 #include "llvm/Support/MemoryBuffer.h"
67 #include "llvm/Support/Regex.h"
68 #include "llvm/Support/SourceMgr.h"
69 #include "llvm/Support/YAMLParser.h"
70 #include "llvm/Support/raw_ostream.h"
71 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
72 #include "llvm/Transforms/Utils/SymbolRewriter.h"
76 static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
77 cl::desc("Symbol Rewrite Map"),
78 cl::value_desc("filename"));
81 namespace SymbolRewriter {
82 template <RewriteDescriptor::Type DT, typename ValueType,
83 ValueType *(llvm::Module::*Get)(StringRef) const>
84 class ExplicitRewriteDescriptor : public RewriteDescriptor {
86 const std::string Source;
87 const std::string Target;
89 ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
90 : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S),
93 bool performOnModule(Module &M) override;
95 static bool classof(const RewriteDescriptor *RD) {
96 return RD->getType() == DT;
100 template <RewriteDescriptor::Type DT, typename ValueType,
101 ValueType *(llvm::Module::*Get)(StringRef) const>
102 bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
103 bool Changed = false;
104 if (ValueType *S = (M.*Get)(Source)) {
105 if (Value *T = (M.*Get)(Target))
106 S->setValueName(T->getValueName());
114 template <RewriteDescriptor::Type DT, typename ValueType,
115 ValueType *(llvm::Module::*Get)(StringRef) const,
116 iterator_range<typename iplist<ValueType>::iterator> (llvm::Module::*Iterator)()>
117 class PatternRewriteDescriptor : public RewriteDescriptor {
119 const std::string Pattern;
120 const std::string Transform;
122 PatternRewriteDescriptor(StringRef P, StringRef T)
123 : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
125 bool performOnModule(Module &M) override;
127 static bool classof(const RewriteDescriptor *RD) {
128 return RD->getType() == DT;
132 template <RewriteDescriptor::Type DT, typename ValueType,
133 ValueType *(llvm::Module::*Get)(StringRef) const,
134 iterator_range<typename iplist<ValueType>::iterator> (llvm::Module::*Iterator)()>
135 bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
136 performOnModule(Module &M) {
137 bool Changed = false;
138 for (auto &C : (M.*Iterator)()) {
141 std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
143 report_fatal_error("unable to transforn " + C.getName() + " in " +
144 M.getModuleIdentifier() + ": " + Error);
146 if (Value *V = (M.*Get)(Name))
147 C.setValueName(V->getValueName());
156 /// Represents a rewrite for an explicitly named (function) symbol. Both the
157 /// source function name and target function name of the transformation are
158 /// explicitly spelt out.
159 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function,
160 llvm::Function, &llvm::Module::getFunction>
161 ExplicitRewriteFunctionDescriptor;
163 /// Represents a rewrite for an explicitly named (global variable) symbol. Both
164 /// the source variable name and target variable name are spelt out. This
165 /// applies only to module level variables.
166 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
167 llvm::GlobalVariable,
168 &llvm::Module::getGlobalVariable>
169 ExplicitRewriteGlobalVariableDescriptor;
171 /// Represents a rewrite for an explicitly named global alias. Both the source
172 /// and target name are explicitly spelt out.
173 typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
175 &llvm::Module::getNamedAlias>
176 ExplicitRewriteNamedAliasDescriptor;
178 /// Represents a rewrite for a regular expression based pattern for functions.
179 /// A pattern for the function name is provided and a transformation for that
180 /// pattern to determine the target function name create the rewrite rule.
181 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::Function,
182 llvm::Function, &llvm::Module::getFunction,
183 &llvm::Module::functions>
184 PatternRewriteFunctionDescriptor;
186 /// Represents a rewrite for a global variable based upon a matching pattern.
187 /// Each global variable matching the provided pattern will be transformed as
188 /// described in the transformation pattern for the target. Applies only to
189 /// module level variables.
190 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
191 llvm::GlobalVariable,
192 &llvm::Module::getGlobalVariable,
193 &llvm::Module::globals>
194 PatternRewriteGlobalVariableDescriptor;
196 /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
197 /// aliases which match a given pattern. The provided transformation will be
198 /// applied to each of the matching names.
199 typedef PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
201 &llvm::Module::getNamedAlias,
202 &llvm::Module::aliases>
203 PatternRewriteNamedAliasDescriptor;
205 bool RewriteMapParser::parse(const std::string &MapFile,
206 RewriteDescriptorList *DL) {
207 ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
208 MemoryBuffer::getFile(MapFile);
211 report_fatal_error("unable to read rewrite map '" + MapFile + "': " +
212 Mapping.getError().message());
214 if (!parse(*Mapping, DL))
215 report_fatal_error("unable to parse rewrite map '" + MapFile + "'");
220 bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
221 RewriteDescriptorList *DL) {
223 yaml::Stream YS(MapFile->getBuffer(), SM);
225 for (auto &Document : YS) {
226 yaml::MappingNode *DescriptorList;
228 // ignore empty documents
229 if (isa<yaml::NullNode>(Document.getRoot()))
232 DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
233 if (!DescriptorList) {
234 YS.printError(Document.getRoot(), "DescriptorList node must be a map");
238 for (auto &Descriptor : *DescriptorList)
239 if (!parseEntry(YS, Descriptor, DL))
246 bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
247 RewriteDescriptorList *DL) {
248 yaml::ScalarNode *Key;
249 yaml::MappingNode *Value;
250 SmallString<32> KeyStorage;
251 StringRef RewriteType;
253 Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
255 YS.printError(Entry.getKey(), "rewrite type must be a scalar");
259 Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
261 YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
265 RewriteType = Key->getValue(KeyStorage);
266 if (RewriteType.equals("function"))
267 return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
268 else if (RewriteType.equals("global variable"))
269 return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
270 else if (RewriteType.equals("global alias"))
271 return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
273 YS.printError(Entry.getKey(), "unknown rewrite type");
277 bool RewriteMapParser::
278 parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
279 yaml::MappingNode *Descriptor,
280 RewriteDescriptorList *DL) {
284 std::string Transform;
286 for (auto &Field : *Descriptor) {
287 yaml::ScalarNode *Key;
288 yaml::ScalarNode *Value;
289 SmallString<32> KeyStorage;
290 SmallString<32> ValueStorage;
293 Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
295 YS.printError(Field.getKey(), "descriptor key must be a scalar");
299 Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
301 YS.printError(Field.getValue(), "descriptor value must be a scalar");
305 KeyValue = Key->getValue(KeyStorage);
306 if (KeyValue.equals("source")) {
309 Source = Value->getValue(ValueStorage);
310 if (!Regex(Source).isValid(Error)) {
311 YS.printError(Field.getKey(), "invalid regex: " + Error);
314 } else if (KeyValue.equals("target")) {
315 Target = Value->getValue(ValueStorage);
316 } else if (KeyValue.equals("transform")) {
317 Transform = Value->getValue(ValueStorage);
318 } else if (KeyValue.equals("naked")) {
319 std::string Undecorated;
321 Undecorated = Value->getValue(ValueStorage);
322 Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
324 YS.printError(Field.getKey(), "unknown key for function");
329 if (Transform.empty() == Target.empty()) {
330 YS.printError(Descriptor,
331 "exactly one of transform or target must be specified");
335 // TODO see if there is a more elegant solution to selecting the rewrite
338 DL->push_back(new ExplicitRewriteFunctionDescriptor(Source, Target, Naked));
340 DL->push_back(new PatternRewriteFunctionDescriptor(Source, Transform));
345 bool RewriteMapParser::
346 parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
347 yaml::MappingNode *Descriptor,
348 RewriteDescriptorList *DL) {
351 std::string Transform;
353 for (auto &Field : *Descriptor) {
354 yaml::ScalarNode *Key;
355 yaml::ScalarNode *Value;
356 SmallString<32> KeyStorage;
357 SmallString<32> ValueStorage;
360 Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
362 YS.printError(Field.getKey(), "descriptor Key must be a scalar");
366 Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
368 YS.printError(Field.getValue(), "descriptor value must be a scalar");
372 KeyValue = Key->getValue(KeyStorage);
373 if (KeyValue.equals("source")) {
376 Source = Value->getValue(ValueStorage);
377 if (!Regex(Source).isValid(Error)) {
378 YS.printError(Field.getKey(), "invalid regex: " + Error);
381 } else if (KeyValue.equals("target")) {
382 Target = Value->getValue(ValueStorage);
383 } else if (KeyValue.equals("transform")) {
384 Transform = Value->getValue(ValueStorage);
386 YS.printError(Field.getKey(), "unknown Key for Global Variable");
391 if (Transform.empty() == Target.empty()) {
392 YS.printError(Descriptor,
393 "exactly one of transform or target must be specified");
398 DL->push_back(new ExplicitRewriteGlobalVariableDescriptor(Source, Target,
401 DL->push_back(new PatternRewriteGlobalVariableDescriptor(Source,
407 bool RewriteMapParser::
408 parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
409 yaml::MappingNode *Descriptor,
410 RewriteDescriptorList *DL) {
413 std::string Transform;
415 for (auto &Field : *Descriptor) {
416 yaml::ScalarNode *Key;
417 yaml::ScalarNode *Value;
418 SmallString<32> KeyStorage;
419 SmallString<32> ValueStorage;
422 Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
424 YS.printError(Field.getKey(), "descriptor key must be a scalar");
428 Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
430 YS.printError(Field.getValue(), "descriptor value must be a scalar");
434 KeyValue = Key->getValue(KeyStorage);
435 if (KeyValue.equals("source")) {
438 Source = Value->getValue(ValueStorage);
439 if (!Regex(Source).isValid(Error)) {
440 YS.printError(Field.getKey(), "invalid regex: " + Error);
443 } else if (KeyValue.equals("target")) {
444 Target = Value->getValue(ValueStorage);
445 } else if (KeyValue.equals("transform")) {
446 Transform = Value->getValue(ValueStorage);
448 YS.printError(Field.getKey(), "unknown key for Global Alias");
453 if (Transform.empty() == Target.empty()) {
454 YS.printError(Descriptor,
455 "exactly one of transform or target must be specified");
460 DL->push_back(new ExplicitRewriteNamedAliasDescriptor(Source, Target,
463 DL->push_back(new PatternRewriteNamedAliasDescriptor(Source, Transform));
471 class RewriteSymbols : public ModulePass {
473 static char ID; // Pass identification, replacement for typeid
476 RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL);
478 bool runOnModule(Module &M) override;
481 void loadAndParseMapFiles();
483 SymbolRewriter::RewriteDescriptorList Descriptors;
486 char RewriteSymbols::ID = 0;
488 RewriteSymbols::RewriteSymbols() : ModulePass(ID) {
489 initializeRewriteSymbolsPass(*PassRegistry::getPassRegistry());
490 loadAndParseMapFiles();
493 RewriteSymbols::RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL)
495 std::swap(Descriptors, DL);
498 bool RewriteSymbols::runOnModule(Module &M) {
502 for (auto &Descriptor : Descriptors)
503 Changed |= Descriptor.performOnModule(M);
508 void RewriteSymbols::loadAndParseMapFiles() {
509 const std::vector<std::string> MapFiles(RewriteMapFiles);
510 SymbolRewriter::RewriteMapParser parser;
512 for (const auto &MapFile : MapFiles)
513 parser.parse(MapFile, &Descriptors);
517 INITIALIZE_PASS(RewriteSymbols, "rewrite-symbols", "Rewrite Symbols", false,
520 ModulePass *llvm::createRewriteSymbolsPass() { return new RewriteSymbols(); }
523 llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
524 return new RewriteSymbols(DL);