xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/SymbolRewriter.cpp (revision d54a7d337331d991e039e4f42f6b4dc64aedce08)
1  //===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===//
2  //
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
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  //     (<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)
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  #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"
81  #include <memory>
82  #include <string>
83  #include <vector>
84  
85  using namespace llvm;
86  using namespace SymbolRewriter;
87  
88  #define DEBUG_TYPE "symbol-rewriter"
89  
90  static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
91                                               cl::desc("Symbol Rewrite Map"),
92                                               cl::value_desc("filename"),
93                                               cl::Hidden);
94  
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();
100  
101      Comdat *C = M.getOrInsertComdat(Target);
102      C->setSelectionKind(CD->getSelectionKind());
103      GO->setComdat(C);
104  
105      Comdats.erase(Comdats.find(Source));
106    }
107  }
108  
109  namespace {
110  
111  template <RewriteDescriptor::Type DT, typename ValueType,
112            ValueType *(Module::*Get)(StringRef) const>
113  class ExplicitRewriteDescriptor : public RewriteDescriptor {
114  public:
115    const std::string Source;
116    const std::string Target;
117  
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)) {}
122  
123    bool performOnModule(Module &M) override;
124  
125    static bool classof(const RewriteDescriptor *RD) {
126      return RD->getType() == DT;
127    }
128  };
129  
130  } // end anonymous namespace
131  
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);
139  
140      if (Value *T = (M.*Get)(Target))
141        S->setValueName(T->getValueName());
142      else
143        S->setName(Target);
144  
145      Changed = true;
146    }
147    return Changed;
148  }
149  
150  namespace {
151  
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 {
157  public:
158    const std::string Pattern;
159    const std::string Transform;
160  
161    PatternRewriteDescriptor(StringRef P, StringRef T)
162        : RewriteDescriptor(DT), Pattern(std::string(P)),
163          Transform(std::string(T)) {}
164  
165    bool performOnModule(Module &M) override;
166  
167    static bool classof(const RewriteDescriptor *RD) {
168      return RD->getType() == DT;
169    }
170  };
171  
172  } // end anonymous namespace
173  
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)()) {
182      std::string Error;
183  
184      std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
185      if (!Error.empty())
186        report_fatal_error(Twine("unable to transforn ") + C.getName() + " in " +
187                           M.getModuleIdentifier() + ": " + Error);
188  
189      if (C.getName() == Name)
190        continue;
191  
192      if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
193        rewriteComdat(M, GO, std::string(C.getName()), Name);
194  
195      if (Value *V = (M.*Get)(Name))
196        C.setValueName(V->getValueName());
197      else
198        C.setName(Name);
199  
200      Changed = true;
201    }
202    return Changed;
203  }
204  
205  namespace {
206  
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>;
213  
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>;
220  
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>;
226  
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>;
233  
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,
241                               &Module::globals>;
242  
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>;
249  
250  } // end anonymous namespace
251  
252  bool RewriteMapParser::parse(const std::string &MapFile,
253                               RewriteDescriptorList *DL) {
254    ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
255        MemoryBuffer::getFile(MapFile);
256  
257    if (!Mapping)
258      report_fatal_error(Twine("unable to read rewrite map '") + MapFile +
259                         "': " + Mapping.getError().message());
260  
261    if (!parse(*Mapping, DL))
262      report_fatal_error(Twine("unable to parse rewrite map '") + MapFile + "'");
263  
264    return true;
265  }
266  
267  bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
268                               RewriteDescriptorList *DL) {
269    SourceMgr SM;
270    yaml::Stream YS(MapFile->getBuffer(), SM);
271  
272    for (auto &Document : YS) {
273      yaml::MappingNode *DescriptorList;
274  
275      // ignore empty documents
276      if (isa<yaml::NullNode>(Document.getRoot()))
277        continue;
278  
279      DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
280      if (!DescriptorList) {
281        YS.printError(Document.getRoot(), "DescriptorList node must be a map");
282        return false;
283      }
284  
285      for (auto &Descriptor : *DescriptorList)
286        if (!parseEntry(YS, Descriptor, DL))
287          return false;
288    }
289  
290    return true;
291  }
292  
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;
299  
300    Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
301    if (!Key) {
302      YS.printError(Entry.getKey(), "rewrite type must be a scalar");
303      return false;
304    }
305  
306    Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
307    if (!Value) {
308      YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
309      return false;
310    }
311  
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);
319  
320    YS.printError(Entry.getKey(), "unknown rewrite type");
321    return false;
322  }
323  
324  bool RewriteMapParser::
325  parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
326                                 yaml::MappingNode *Descriptor,
327                                 RewriteDescriptorList *DL) {
328    bool Naked = false;
329    std::string Source;
330    std::string Target;
331    std::string Transform;
332  
333    for (auto &Field : *Descriptor) {
334      yaml::ScalarNode *Key;
335      yaml::ScalarNode *Value;
336      SmallString<32> KeyStorage;
337      SmallString<32> ValueStorage;
338      StringRef KeyValue;
339  
340      Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
341      if (!Key) {
342        YS.printError(Field.getKey(), "descriptor key must be a scalar");
343        return false;
344      }
345  
346      Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
347      if (!Value) {
348        YS.printError(Field.getValue(), "descriptor value must be a scalar");
349        return false;
350      }
351  
352      KeyValue = Key->getValue(KeyStorage);
353      if (KeyValue.equals("source")) {
354        std::string Error;
355  
356        Source = std::string(Value->getValue(ValueStorage));
357        if (!Regex(Source).isValid(Error)) {
358          YS.printError(Field.getKey(), "invalid regex: " + Error);
359          return false;
360        }
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;
367  
368        Undecorated = std::string(Value->getValue(ValueStorage));
369        Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
370      } else {
371        YS.printError(Field.getKey(), "unknown key for function");
372        return false;
373      }
374    }
375  
376    if (Transform.empty() == Target.empty()) {
377      YS.printError(Descriptor,
378                    "exactly one of transform or target must be specified");
379      return false;
380    }
381  
382    // TODO see if there is a more elegant solution to selecting the rewrite
383    // descriptor type
384    if (!Target.empty())
385      DL->push_back(std::make_unique<ExplicitRewriteFunctionDescriptor>(
386          Source, Target, Naked));
387    else
388      DL->push_back(
389          std::make_unique<PatternRewriteFunctionDescriptor>(Source, Transform));
390  
391    return true;
392  }
393  
394  bool RewriteMapParser::
395  parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
396                                       yaml::MappingNode *Descriptor,
397                                       RewriteDescriptorList *DL) {
398    std::string Source;
399    std::string Target;
400    std::string Transform;
401  
402    for (auto &Field : *Descriptor) {
403      yaml::ScalarNode *Key;
404      yaml::ScalarNode *Value;
405      SmallString<32> KeyStorage;
406      SmallString<32> ValueStorage;
407      StringRef KeyValue;
408  
409      Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
410      if (!Key) {
411        YS.printError(Field.getKey(), "descriptor Key must be a scalar");
412        return false;
413      }
414  
415      Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
416      if (!Value) {
417        YS.printError(Field.getValue(), "descriptor value must be a scalar");
418        return false;
419      }
420  
421      KeyValue = Key->getValue(KeyStorage);
422      if (KeyValue.equals("source")) {
423        std::string Error;
424  
425        Source = std::string(Value->getValue(ValueStorage));
426        if (!Regex(Source).isValid(Error)) {
427          YS.printError(Field.getKey(), "invalid regex: " + Error);
428          return false;
429        }
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));
434      } else {
435        YS.printError(Field.getKey(), "unknown Key for Global Variable");
436        return false;
437      }
438    }
439  
440    if (Transform.empty() == Target.empty()) {
441      YS.printError(Descriptor,
442                    "exactly one of transform or target must be specified");
443      return false;
444    }
445  
446    if (!Target.empty())
447      DL->push_back(std::make_unique<ExplicitRewriteGlobalVariableDescriptor>(
448          Source, Target,
449          /*Naked*/ false));
450    else
451      DL->push_back(std::make_unique<PatternRewriteGlobalVariableDescriptor>(
452          Source, Transform));
453  
454    return true;
455  }
456  
457  bool RewriteMapParser::
458  parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
459                                    yaml::MappingNode *Descriptor,
460                                    RewriteDescriptorList *DL) {
461    std::string Source;
462    std::string Target;
463    std::string Transform;
464  
465    for (auto &Field : *Descriptor) {
466      yaml::ScalarNode *Key;
467      yaml::ScalarNode *Value;
468      SmallString<32> KeyStorage;
469      SmallString<32> ValueStorage;
470      StringRef KeyValue;
471  
472      Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
473      if (!Key) {
474        YS.printError(Field.getKey(), "descriptor key must be a scalar");
475        return false;
476      }
477  
478      Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
479      if (!Value) {
480        YS.printError(Field.getValue(), "descriptor value must be a scalar");
481        return false;
482      }
483  
484      KeyValue = Key->getValue(KeyStorage);
485      if (KeyValue.equals("source")) {
486        std::string Error;
487  
488        Source = std::string(Value->getValue(ValueStorage));
489        if (!Regex(Source).isValid(Error)) {
490          YS.printError(Field.getKey(), "invalid regex: " + Error);
491          return false;
492        }
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));
497      } else {
498        YS.printError(Field.getKey(), "unknown key for Global Alias");
499        return false;
500      }
501    }
502  
503    if (Transform.empty() == Target.empty()) {
504      YS.printError(Descriptor,
505                    "exactly one of transform or target must be specified");
506      return false;
507    }
508  
509    if (!Target.empty())
510      DL->push_back(std::make_unique<ExplicitRewriteNamedAliasDescriptor>(
511          Source, Target,
512          /*Naked*/ false));
513    else
514      DL->push_back(std::make_unique<PatternRewriteNamedAliasDescriptor>(
515          Source, Transform));
516  
517    return true;
518  }
519  
520  namespace {
521  
522  class RewriteSymbolsLegacyPass : public ModulePass {
523  public:
524    static char ID; // Pass identification, replacement for typeid
525  
526    RewriteSymbolsLegacyPass();
527    RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList &DL);
528  
529    bool runOnModule(Module &M) override;
530  
531  private:
532    RewriteSymbolPass Impl;
533  };
534  
535  } // end anonymous namespace
536  
537  char RewriteSymbolsLegacyPass::ID = 0;
538  
539  RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID) {
540    initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
541  }
542  
543  RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
544      SymbolRewriter::RewriteDescriptorList &DL)
545      : ModulePass(ID), Impl(DL) {}
546  
547  bool RewriteSymbolsLegacyPass::runOnModule(Module &M) {
548    return Impl.runImpl(M);
549  }
550  
551  PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) {
552    if (!runImpl(M))
553      return PreservedAnalyses::all();
554  
555    return PreservedAnalyses::none();
556  }
557  
558  bool RewriteSymbolPass::runImpl(Module &M) {
559    bool Changed;
560  
561    Changed = false;
562    for (auto &Descriptor : Descriptors)
563      Changed |= Descriptor->performOnModule(M);
564  
565    return Changed;
566  }
567  
568  void RewriteSymbolPass::loadAndParseMapFiles() {
569    const std::vector<std::string> MapFiles(RewriteMapFiles);
570    SymbolRewriter::RewriteMapParser Parser;
571  
572    for (const auto &MapFile : MapFiles)
573      Parser.parse(MapFile, &Descriptors);
574  }
575  
576  INITIALIZE_PASS(RewriteSymbolsLegacyPass, "rewrite-symbols", "Rewrite Symbols",
577                  false, false)
578  
579  ModulePass *llvm::createRewriteSymbolsPass() {
580    return new RewriteSymbolsLegacyPass();
581  }
582  
583  ModulePass *
584  llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
585    return new RewriteSymbolsLegacyPass(DL);
586  }
587