Home | History | Annotate | Download | only in Utils
      1 //===-- SymbolRewriter.h - Symbol Rewriting Pass ----------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file provides the prototypes and definitions related to the Symbol
     11 // Rewriter pass.
     12 //
     13 // The Symbol Rewriter pass takes a set of rewrite descriptors which define
     14 // transformations for symbol names.  These can be either single name to name
     15 // trnsformation or more broad regular expression based transformations.
     16 //
     17 // All the functions are re-written at the IR level.  The Symbol Rewriter itself
     18 // is exposed as a module level pass.  All symbols at the module level are
     19 // iterated.  For any matching symbol, the requested transformation is applied,
     20 // updating references to it as well (a la RAUW).  The resulting binary will
     21 // only contain the rewritten symbols.
     22 //
     23 // By performing this operation in the compiler, we are able to catch symbols
     24 // that would otherwise not be possible to catch (e.g. inlined symbols).
     25 //
     26 // This makes it possible to cleanly transform symbols without resorting to
     27 // overly-complex macro tricks and the pre-processor.  An example of where this
     28 // is useful is the sanitizers where we would like to intercept a well-defined
     29 // set of functions across the module.
     30 //
     31 //===----------------------------------------------------------------------===//
     32 
     33 #ifndef LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
     34 #define LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H
     35 
     36 #include "llvm/ADT/ilist.h"
     37 #include "llvm/ADT/ilist_node.h"
     38 #include "llvm/IR/Module.h"
     39 
     40 namespace llvm {
     41 class MemoryBuffer;
     42 
     43 namespace yaml {
     44 class KeyValueNode;
     45 class MappingNode;
     46 class ScalarNode;
     47 class Stream;
     48 }
     49 
     50 namespace SymbolRewriter {
     51 /// The basic entity representing a rewrite operation.  It serves as the base
     52 /// class for any rewrite descriptor.  It has a certain set of specializations
     53 /// which describe a particular rewrite.
     54 ///
     55 /// The RewriteMapParser can be used to parse a mapping file that provides the
     56 /// mapping for rewriting the symbols.  The descriptors individually describe
     57 /// whether to rewrite a function, global variable, or global alias.  Each of
     58 /// these can be selected either by explicitly providing a name for the ones to
     59 /// be rewritten or providing a (posix compatible) regular expression that will
     60 /// select the symbols to rewrite.  This descriptor list is passed to the
     61 /// SymbolRewriter pass.
     62 class RewriteDescriptor : public ilist_node<RewriteDescriptor> {
     63   RewriteDescriptor(const RewriteDescriptor &) = delete;
     64 
     65   const RewriteDescriptor &
     66   operator=(const RewriteDescriptor &) = delete;
     67 
     68 public:
     69   enum class Type {
     70     Invalid,        /// invalid
     71     Function,       /// function - descriptor rewrites a function
     72     GlobalVariable, /// global variable - descriptor rewrites a global variable
     73     NamedAlias,     /// named alias - descriptor rewrites a global alias
     74   };
     75 
     76   virtual ~RewriteDescriptor() {}
     77 
     78   Type getType() const { return Kind; }
     79 
     80   virtual bool performOnModule(Module &M) = 0;
     81 
     82 protected:
     83   explicit RewriteDescriptor(Type T) : Kind(T) {}
     84 
     85 private:
     86   const Type Kind;
     87 };
     88 
     89 typedef iplist<RewriteDescriptor> RewriteDescriptorList;
     90 
     91 class RewriteMapParser {
     92 public:
     93   bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors);
     94 
     95 private:
     96   bool parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL);
     97   bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry,
     98                   RewriteDescriptorList *DL);
     99   bool parseRewriteFunctionDescriptor(yaml::Stream &Stream,
    100                                       yaml::ScalarNode *Key,
    101                                       yaml::MappingNode *Value,
    102                                       RewriteDescriptorList *DL);
    103   bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream,
    104                                             yaml::ScalarNode *Key,
    105                                             yaml::MappingNode *Value,
    106                                             RewriteDescriptorList *DL);
    107   bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
    108                                          yaml::MappingNode *V,
    109                                          RewriteDescriptorList *DL);
    110 };
    111 }
    112 
    113 template <>
    114 struct ilist_traits<SymbolRewriter::RewriteDescriptor>
    115     : public ilist_default_traits<SymbolRewriter::RewriteDescriptor> {
    116   mutable ilist_half_node<SymbolRewriter::RewriteDescriptor> Sentinel;
    117 
    118 public:
    119   // createSentinel is used to get a reference to a node marking the end of
    120   // the list.  Because the sentinel is relative to this instance, use a
    121   // non-static method.
    122   SymbolRewriter::RewriteDescriptor *createSentinel() const {
    123     // since i[p] lists always publicly derive from the corresponding
    124     // traits, placing a data member in this class will augment the
    125     // i[p]list.  Since the NodeTy is expected to publicly derive from
    126     // ilist_node<NodeTy>, there is a legal viable downcast from it to
    127     // NodeTy.  We use this trick to superpose i[p]list with a "ghostly"
    128     // NodeTy, which becomes the sentinel.  Dereferencing the sentinel is
    129     // forbidden (save the ilist_node<NodeTy>) so no one will ever notice
    130     // the superposition.
    131     return static_cast<SymbolRewriter::RewriteDescriptor *>(&Sentinel);
    132   }
    133   void destroySentinel(SymbolRewriter::RewriteDescriptor *) {}
    134 
    135   SymbolRewriter::RewriteDescriptor *provideInitialHead() const {
    136     return createSentinel();
    137   }
    138 
    139   SymbolRewriter::RewriteDescriptor *
    140   ensureHead(SymbolRewriter::RewriteDescriptor *&) const {
    141     return createSentinel();
    142   }
    143 
    144   static void noteHead(SymbolRewriter::RewriteDescriptor *,
    145                        SymbolRewriter::RewriteDescriptor *) {}
    146 };
    147 
    148 ModulePass *createRewriteSymbolsPass();
    149 ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &);
    150 }
    151 
    152 #endif
    153