1286d5897SEugene Zelenko //===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===//
25898e090SSaleem Abdulrasool //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65898e090SSaleem Abdulrasool //
75898e090SSaleem Abdulrasool //===----------------------------------------------------------------------===//
85898e090SSaleem Abdulrasool //
95898e090SSaleem Abdulrasool // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
105898e090SSaleem Abdulrasool // existing code.  It is implemented as a compiler pass and is configured via a
115898e090SSaleem Abdulrasool // YAML configuration file.
125898e090SSaleem Abdulrasool //
135898e090SSaleem Abdulrasool // The YAML configuration file format is as follows:
145898e090SSaleem Abdulrasool //
155898e090SSaleem Abdulrasool // RewriteMapFile := RewriteDescriptors
165898e090SSaleem Abdulrasool // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
175898e090SSaleem Abdulrasool // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
185898e090SSaleem Abdulrasool // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
195898e090SSaleem Abdulrasool // RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
205898e090SSaleem Abdulrasool // RewriteDescriptorType := Identifier
215898e090SSaleem Abdulrasool // FieldIdentifier := Identifier
225898e090SSaleem Abdulrasool // FieldValue := Identifier
235898e090SSaleem Abdulrasool // Identifier := [0-9a-zA-Z]+
245898e090SSaleem Abdulrasool //
255898e090SSaleem Abdulrasool // Currently, the following descriptor types are supported:
265898e090SSaleem Abdulrasool //
275898e090SSaleem Abdulrasool // - function:          (function rewriting)
285898e090SSaleem Abdulrasool //      + Source        (original name of the function)
295898e090SSaleem Abdulrasool //      + Target        (explicit transformation)
305898e090SSaleem Abdulrasool //      + Transform     (pattern transformation)
315898e090SSaleem Abdulrasool //      + Naked         (boolean, whether the function is undecorated)
325898e090SSaleem Abdulrasool // - global variable:   (external linkage global variable rewriting)
335898e090SSaleem Abdulrasool //      + Source        (original name of externally visible variable)
345898e090SSaleem Abdulrasool //      + Target        (explicit transformation)
355898e090SSaleem Abdulrasool //      + Transform     (pattern transformation)
365898e090SSaleem Abdulrasool // - global alias:      (global alias rewriting)
375898e090SSaleem Abdulrasool //      + Source        (original name of the aliased name)
385898e090SSaleem Abdulrasool //      + Target        (explicit transformation)
395898e090SSaleem Abdulrasool //      + Transform     (pattern transformation)
405898e090SSaleem Abdulrasool //
415898e090SSaleem Abdulrasool // Note that source and exactly one of [Target, Transform] must be provided
425898e090SSaleem Abdulrasool //
435898e090SSaleem Abdulrasool // New rewrite descriptors can be created.  Addding a new rewrite descriptor
445898e090SSaleem Abdulrasool // involves:
455898e090SSaleem Abdulrasool //
465898e090SSaleem Abdulrasool //  a) extended the rewrite descriptor kind enumeration
475898e090SSaleem Abdulrasool //     (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
485898e090SSaleem Abdulrasool //  b) implementing the new descriptor
495898e090SSaleem Abdulrasool //     (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
505898e090SSaleem Abdulrasool //  c) extending the rewrite map parser
515898e090SSaleem Abdulrasool //     (<anonymous>::RewriteMapParser::parseEntry)
525898e090SSaleem Abdulrasool //
535898e090SSaleem Abdulrasool //  Specify to rewrite the symbols using the `-rewrite-symbols` option, and
545898e090SSaleem Abdulrasool //  specify the map file to use for the rewriting via the `-rewrite-map-file`
555898e090SSaleem Abdulrasool //  option.
565898e090SSaleem Abdulrasool //
575898e090SSaleem Abdulrasool //===----------------------------------------------------------------------===//
585898e090SSaleem Abdulrasool 
5939feb629SMichael Kuperstein #include "llvm/Transforms/Utils/SymbolRewriter.h"
6016132e6fSBenjamin Kramer #include "llvm/ADT/SmallString.h"
61286d5897SEugene Zelenko #include "llvm/ADT/StringRef.h"
62286d5897SEugene Zelenko #include "llvm/ADT/ilist.h"
63286d5897SEugene Zelenko #include "llvm/ADT/iterator_range.h"
64286d5897SEugene Zelenko #include "llvm/IR/Comdat.h"
65286d5897SEugene Zelenko #include "llvm/IR/Function.h"
66286d5897SEugene Zelenko #include "llvm/IR/GlobalAlias.h"
67286d5897SEugene Zelenko #include "llvm/IR/GlobalObject.h"
68286d5897SEugene Zelenko #include "llvm/IR/GlobalVariable.h"
69286d5897SEugene Zelenko #include "llvm/IR/Module.h"
70286d5897SEugene Zelenko #include "llvm/IR/Value.h"
7105da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
726bda14b3SChandler Carruth #include "llvm/Pass.h"
73286d5897SEugene Zelenko #include "llvm/Support/Casting.h"
745898e090SSaleem Abdulrasool #include "llvm/Support/CommandLine.h"
75286d5897SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
76286d5897SEugene Zelenko #include "llvm/Support/ErrorOr.h"
775898e090SSaleem Abdulrasool #include "llvm/Support/MemoryBuffer.h"
785898e090SSaleem Abdulrasool #include "llvm/Support/Regex.h"
795898e090SSaleem Abdulrasool #include "llvm/Support/SourceMgr.h"
805898e090SSaleem Abdulrasool #include "llvm/Support/YAMLParser.h"
81286d5897SEugene Zelenko #include <memory>
82286d5897SEugene Zelenko #include <string>
83286d5897SEugene Zelenko #include <vector>
845898e090SSaleem Abdulrasool 
855898e090SSaleem Abdulrasool using namespace llvm;
86fd3bc744SBenjamin Kramer using namespace SymbolRewriter;
875898e090SSaleem Abdulrasool 
88286d5897SEugene Zelenko #define DEBUG_TYPE "symbol-rewriter"
89286d5897SEugene Zelenko 
905898e090SSaleem Abdulrasool static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
915898e090SSaleem Abdulrasool                                              cl::desc("Symbol Rewrite Map"),
928065f0b9SZachary Turner                                              cl::value_desc("filename"),
938065f0b9SZachary Turner                                              cl::Hidden);
945898e090SSaleem Abdulrasool 
rewriteComdat(Module & M,GlobalObject * GO,const std::string & Source,const std::string & Target)95fd3bc744SBenjamin Kramer static void rewriteComdat(Module &M, GlobalObject *GO,
96fd3bc744SBenjamin Kramer                           const std::string &Source,
97c44d71b8SSaleem Abdulrasool                           const std::string &Target) {
98c44d71b8SSaleem Abdulrasool   if (Comdat *CD = GO->getComdat()) {
99c44d71b8SSaleem Abdulrasool     auto &Comdats = M.getComdatSymbolTable();
100c44d71b8SSaleem Abdulrasool 
101c44d71b8SSaleem Abdulrasool     Comdat *C = M.getOrInsertComdat(Target);
102c44d71b8SSaleem Abdulrasool     C->setSelectionKind(CD->getSelectionKind());
103c44d71b8SSaleem Abdulrasool     GO->setComdat(C);
104c44d71b8SSaleem Abdulrasool 
105c44d71b8SSaleem Abdulrasool     Comdats.erase(Comdats.find(Source));
106c44d71b8SSaleem Abdulrasool   }
107c44d71b8SSaleem Abdulrasool }
108c44d71b8SSaleem Abdulrasool 
109fd3bc744SBenjamin Kramer namespace {
110286d5897SEugene Zelenko 
1115898e090SSaleem Abdulrasool template <RewriteDescriptor::Type DT, typename ValueType,
112286d5897SEugene Zelenko           ValueType *(Module::*Get)(StringRef) const>
1135898e090SSaleem Abdulrasool class ExplicitRewriteDescriptor : public RewriteDescriptor {
1145898e090SSaleem Abdulrasool public:
1155898e090SSaleem Abdulrasool   const std::string Source;
1165898e090SSaleem Abdulrasool   const std::string Target;
1175898e090SSaleem Abdulrasool 
ExplicitRewriteDescriptor(StringRef S,StringRef T,const bool Naked)1185898e090SSaleem Abdulrasool   ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
119adcd0268SBenjamin Kramer       : RewriteDescriptor(DT),
120adcd0268SBenjamin Kramer         Source(std::string(Naked ? StringRef("\01" + S.str()) : S)),
121adcd0268SBenjamin Kramer         Target(std::string(T)) {}
1225898e090SSaleem Abdulrasool 
1235898e090SSaleem Abdulrasool   bool performOnModule(Module &M) override;
1245898e090SSaleem Abdulrasool 
classof(const RewriteDescriptor * RD)1255898e090SSaleem Abdulrasool   static bool classof(const RewriteDescriptor *RD) {
1265898e090SSaleem Abdulrasool     return RD->getType() == DT;
1275898e090SSaleem Abdulrasool   }
1285898e090SSaleem Abdulrasool };
1295898e090SSaleem Abdulrasool 
130286d5897SEugene Zelenko } // end anonymous namespace
131286d5897SEugene Zelenko 
1325898e090SSaleem Abdulrasool template <RewriteDescriptor::Type DT, typename ValueType,
133286d5897SEugene Zelenko           ValueType *(Module::*Get)(StringRef) const>
performOnModule(Module & M)1345898e090SSaleem Abdulrasool bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
1355898e090SSaleem Abdulrasool   bool Changed = false;
1365898e090SSaleem Abdulrasool   if (ValueType *S = (M.*Get)(Source)) {
137c44d71b8SSaleem Abdulrasool     if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
138c44d71b8SSaleem Abdulrasool       rewriteComdat(M, GO, Source, Target);
139c44d71b8SSaleem Abdulrasool 
1405898e090SSaleem Abdulrasool     if (Value *T = (M.*Get)(Target))
1415898e090SSaleem Abdulrasool       S->setValueName(T->getValueName());
1425898e090SSaleem Abdulrasool     else
1435898e090SSaleem Abdulrasool       S->setName(Target);
144c44d71b8SSaleem Abdulrasool 
1455898e090SSaleem Abdulrasool     Changed = true;
1465898e090SSaleem Abdulrasool   }
1475898e090SSaleem Abdulrasool   return Changed;
1485898e090SSaleem Abdulrasool }
1495898e090SSaleem Abdulrasool 
150286d5897SEugene Zelenko namespace {
151286d5897SEugene Zelenko 
1525898e090SSaleem Abdulrasool template <RewriteDescriptor::Type DT, typename ValueType,
153286d5897SEugene Zelenko           ValueType *(Module::*Get)(StringRef) const,
154d37ce308SSaleem Abdulrasool           iterator_range<typename iplist<ValueType>::iterator>
155286d5897SEugene Zelenko           (Module::*Iterator)()>
1565898e090SSaleem Abdulrasool class PatternRewriteDescriptor : public RewriteDescriptor {
1575898e090SSaleem Abdulrasool public:
1585898e090SSaleem Abdulrasool   const std::string Pattern;
1595898e090SSaleem Abdulrasool   const std::string Transform;
1605898e090SSaleem Abdulrasool 
PatternRewriteDescriptor(StringRef P,StringRef T)1615898e090SSaleem Abdulrasool   PatternRewriteDescriptor(StringRef P, StringRef T)
162adcd0268SBenjamin Kramer       : RewriteDescriptor(DT), Pattern(std::string(P)),
163adcd0268SBenjamin Kramer         Transform(std::string(T)) {}
1645898e090SSaleem Abdulrasool 
1655898e090SSaleem Abdulrasool   bool performOnModule(Module &M) override;
1665898e090SSaleem Abdulrasool 
classof(const RewriteDescriptor * RD)1675898e090SSaleem Abdulrasool   static bool classof(const RewriteDescriptor *RD) {
1685898e090SSaleem Abdulrasool     return RD->getType() == DT;
1695898e090SSaleem Abdulrasool   }
1705898e090SSaleem Abdulrasool };
1715898e090SSaleem Abdulrasool 
172286d5897SEugene Zelenko } // end anonymous namespace
173286d5897SEugene Zelenko 
1745898e090SSaleem Abdulrasool template <RewriteDescriptor::Type DT, typename ValueType,
175286d5897SEugene Zelenko           ValueType *(Module::*Get)(StringRef) const,
176d37ce308SSaleem Abdulrasool           iterator_range<typename iplist<ValueType>::iterator>
177286d5897SEugene Zelenko           (Module::*Iterator)()>
1785898e090SSaleem Abdulrasool bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
performOnModule(Module & M)1795898e090SSaleem Abdulrasool performOnModule(Module &M) {
1805898e090SSaleem Abdulrasool   bool Changed = false;
1815898e090SSaleem Abdulrasool   for (auto &C : (M.*Iterator)()) {
1825898e090SSaleem Abdulrasool     std::string Error;
1835898e090SSaleem Abdulrasool 
1845898e090SSaleem Abdulrasool     std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
1855898e090SSaleem Abdulrasool     if (!Error.empty())
186*21661607SSimon Pilgrim       report_fatal_error(Twine("unable to transforn ") + C.getName() + " in " +
1875898e090SSaleem Abdulrasool                          M.getModuleIdentifier() + ": " + Error);
1885898e090SSaleem Abdulrasool 
1899769b18cSSaleem Abdulrasool     if (C.getName() == Name)
1909769b18cSSaleem Abdulrasool       continue;
1919769b18cSSaleem Abdulrasool 
192c44d71b8SSaleem Abdulrasool     if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
193adcd0268SBenjamin Kramer       rewriteComdat(M, GO, std::string(C.getName()), Name);
194c44d71b8SSaleem Abdulrasool 
1955898e090SSaleem Abdulrasool     if (Value *V = (M.*Get)(Name))
1965898e090SSaleem Abdulrasool       C.setValueName(V->getValueName());
1975898e090SSaleem Abdulrasool     else
1985898e090SSaleem Abdulrasool       C.setName(Name);
1995898e090SSaleem Abdulrasool 
2005898e090SSaleem Abdulrasool     Changed = true;
2015898e090SSaleem Abdulrasool   }
2025898e090SSaleem Abdulrasool   return Changed;
2035898e090SSaleem Abdulrasool }
2045898e090SSaleem Abdulrasool 
205286d5897SEugene Zelenko namespace {
206286d5897SEugene Zelenko 
2075898e090SSaleem Abdulrasool /// Represents a rewrite for an explicitly named (function) symbol.  Both the
2085898e090SSaleem Abdulrasool /// source function name and target function name of the transformation are
2095898e090SSaleem Abdulrasool /// explicitly spelt out.
210286d5897SEugene Zelenko using ExplicitRewriteFunctionDescriptor =
211286d5897SEugene Zelenko     ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
212286d5897SEugene Zelenko                               &Module::getFunction>;
2135898e090SSaleem Abdulrasool 
2145898e090SSaleem Abdulrasool /// Represents a rewrite for an explicitly named (global variable) symbol.  Both
2155898e090SSaleem Abdulrasool /// the source variable name and target variable name are spelt out.  This
2165898e090SSaleem Abdulrasool /// applies only to module level variables.
217286d5897SEugene Zelenko using ExplicitRewriteGlobalVariableDescriptor =
218286d5897SEugene Zelenko     ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
219286d5897SEugene Zelenko                               GlobalVariable, &Module::getGlobalVariable>;
2205898e090SSaleem Abdulrasool 
2215898e090SSaleem Abdulrasool /// Represents a rewrite for an explicitly named global alias.  Both the source
2225898e090SSaleem Abdulrasool /// and target name are explicitly spelt out.
223286d5897SEugene Zelenko using ExplicitRewriteNamedAliasDescriptor =
224286d5897SEugene Zelenko     ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
225286d5897SEugene Zelenko                               &Module::getNamedAlias>;
2265898e090SSaleem Abdulrasool 
2275898e090SSaleem Abdulrasool /// Represents a rewrite for a regular expression based pattern for functions.
2285898e090SSaleem Abdulrasool /// A pattern for the function name is provided and a transformation for that
2295898e090SSaleem Abdulrasool /// pattern to determine the target function name create the rewrite rule.
230286d5897SEugene Zelenko using PatternRewriteFunctionDescriptor =
231286d5897SEugene Zelenko     PatternRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
232286d5897SEugene Zelenko                              &Module::getFunction, &Module::functions>;
2335898e090SSaleem Abdulrasool 
2345898e090SSaleem Abdulrasool /// Represents a rewrite for a global variable based upon a matching pattern.
2355898e090SSaleem Abdulrasool /// Each global variable matching the provided pattern will be transformed as
2365898e090SSaleem Abdulrasool /// described in the transformation pattern for the target.  Applies only to
2375898e090SSaleem Abdulrasool /// module level variables.
238286d5897SEugene Zelenko using PatternRewriteGlobalVariableDescriptor =
239286d5897SEugene Zelenko     PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
240286d5897SEugene Zelenko                              GlobalVariable, &Module::getGlobalVariable,
241286d5897SEugene Zelenko                              &Module::globals>;
2425898e090SSaleem Abdulrasool 
2435898e090SSaleem Abdulrasool /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
2445898e090SSaleem Abdulrasool /// aliases which match a given pattern.  The provided transformation will be
2455898e090SSaleem Abdulrasool /// applied to each of the matching names.
246286d5897SEugene Zelenko using PatternRewriteNamedAliasDescriptor =
247286d5897SEugene Zelenko     PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
248286d5897SEugene Zelenko                              &Module::getNamedAlias, &Module::aliases>;
249286d5897SEugene Zelenko 
250286d5897SEugene Zelenko } // end anonymous namespace
2515898e090SSaleem Abdulrasool 
parse(const std::string & MapFile,RewriteDescriptorList * DL)2525898e090SSaleem Abdulrasool bool RewriteMapParser::parse(const std::string &MapFile,
2535898e090SSaleem Abdulrasool                              RewriteDescriptorList *DL) {
2545898e090SSaleem Abdulrasool   ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
2555898e090SSaleem Abdulrasool       MemoryBuffer::getFile(MapFile);
2565898e090SSaleem Abdulrasool 
2575898e090SSaleem Abdulrasool   if (!Mapping)
258*21661607SSimon Pilgrim     report_fatal_error(Twine("unable to read rewrite map '") + MapFile +
259*21661607SSimon Pilgrim                        "': " + Mapping.getError().message());
2605898e090SSaleem Abdulrasool 
2615898e090SSaleem Abdulrasool   if (!parse(*Mapping, DL))
262*21661607SSimon Pilgrim     report_fatal_error(Twine("unable to parse rewrite map '") + MapFile + "'");
2635898e090SSaleem Abdulrasool 
2645898e090SSaleem Abdulrasool   return true;
2655898e090SSaleem Abdulrasool }
2665898e090SSaleem Abdulrasool 
parse(std::unique_ptr<MemoryBuffer> & MapFile,RewriteDescriptorList * DL)2675898e090SSaleem Abdulrasool bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
2685898e090SSaleem Abdulrasool                              RewriteDescriptorList *DL) {
2695898e090SSaleem Abdulrasool   SourceMgr SM;
2705898e090SSaleem Abdulrasool   yaml::Stream YS(MapFile->getBuffer(), SM);
2715898e090SSaleem Abdulrasool 
2725898e090SSaleem Abdulrasool   for (auto &Document : YS) {
2735898e090SSaleem Abdulrasool     yaml::MappingNode *DescriptorList;
2745898e090SSaleem Abdulrasool 
2755898e090SSaleem Abdulrasool     // ignore empty documents
2765898e090SSaleem Abdulrasool     if (isa<yaml::NullNode>(Document.getRoot()))
2775898e090SSaleem Abdulrasool       continue;
2785898e090SSaleem Abdulrasool 
2795898e090SSaleem Abdulrasool     DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
2805898e090SSaleem Abdulrasool     if (!DescriptorList) {
2815898e090SSaleem Abdulrasool       YS.printError(Document.getRoot(), "DescriptorList node must be a map");
2825898e090SSaleem Abdulrasool       return false;
2835898e090SSaleem Abdulrasool     }
2845898e090SSaleem Abdulrasool 
2855898e090SSaleem Abdulrasool     for (auto &Descriptor : *DescriptorList)
2865898e090SSaleem Abdulrasool       if (!parseEntry(YS, Descriptor, DL))
2875898e090SSaleem Abdulrasool         return false;
2885898e090SSaleem Abdulrasool   }
2895898e090SSaleem Abdulrasool 
2905898e090SSaleem Abdulrasool   return true;
2915898e090SSaleem Abdulrasool }
2925898e090SSaleem Abdulrasool 
parseEntry(yaml::Stream & YS,yaml::KeyValueNode & Entry,RewriteDescriptorList * DL)2935898e090SSaleem Abdulrasool bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
2945898e090SSaleem Abdulrasool                                   RewriteDescriptorList *DL) {
2955898e090SSaleem Abdulrasool   yaml::ScalarNode *Key;
2965898e090SSaleem Abdulrasool   yaml::MappingNode *Value;
2975898e090SSaleem Abdulrasool   SmallString<32> KeyStorage;
2985898e090SSaleem Abdulrasool   StringRef RewriteType;
2995898e090SSaleem Abdulrasool 
3005898e090SSaleem Abdulrasool   Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
3015898e090SSaleem Abdulrasool   if (!Key) {
3025898e090SSaleem Abdulrasool     YS.printError(Entry.getKey(), "rewrite type must be a scalar");
3035898e090SSaleem Abdulrasool     return false;
3045898e090SSaleem Abdulrasool   }
3055898e090SSaleem Abdulrasool 
3065898e090SSaleem Abdulrasool   Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
3075898e090SSaleem Abdulrasool   if (!Value) {
3085898e090SSaleem Abdulrasool     YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
3095898e090SSaleem Abdulrasool     return false;
3105898e090SSaleem Abdulrasool   }
3115898e090SSaleem Abdulrasool 
3125898e090SSaleem Abdulrasool   RewriteType = Key->getValue(KeyStorage);
313d2c5d7f6SSaleem Abdulrasool   if (RewriteType.equals("function"))
3145898e090SSaleem Abdulrasool     return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
315d2c5d7f6SSaleem Abdulrasool   else if (RewriteType.equals("global variable"))
3165898e090SSaleem Abdulrasool     return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
317d2c5d7f6SSaleem Abdulrasool   else if (RewriteType.equals("global alias"))
3185898e090SSaleem Abdulrasool     return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
3195898e090SSaleem Abdulrasool 
3205898e090SSaleem Abdulrasool   YS.printError(Entry.getKey(), "unknown rewrite type");
3215898e090SSaleem Abdulrasool   return false;
3225898e090SSaleem Abdulrasool }
3235898e090SSaleem Abdulrasool 
3245898e090SSaleem Abdulrasool bool RewriteMapParser::
parseRewriteFunctionDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)3255898e090SSaleem Abdulrasool parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
3265898e090SSaleem Abdulrasool                                yaml::MappingNode *Descriptor,
3275898e090SSaleem Abdulrasool                                RewriteDescriptorList *DL) {
3285898e090SSaleem Abdulrasool   bool Naked = false;
3295898e090SSaleem Abdulrasool   std::string Source;
3305898e090SSaleem Abdulrasool   std::string Target;
3315898e090SSaleem Abdulrasool   std::string Transform;
3325898e090SSaleem Abdulrasool 
3335898e090SSaleem Abdulrasool   for (auto &Field : *Descriptor) {
3345898e090SSaleem Abdulrasool     yaml::ScalarNode *Key;
3355898e090SSaleem Abdulrasool     yaml::ScalarNode *Value;
3365898e090SSaleem Abdulrasool     SmallString<32> KeyStorage;
3375898e090SSaleem Abdulrasool     SmallString<32> ValueStorage;
3385898e090SSaleem Abdulrasool     StringRef KeyValue;
3395898e090SSaleem Abdulrasool 
3405898e090SSaleem Abdulrasool     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
3415898e090SSaleem Abdulrasool     if (!Key) {
3425898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "descriptor key must be a scalar");
3435898e090SSaleem Abdulrasool       return false;
3445898e090SSaleem Abdulrasool     }
3455898e090SSaleem Abdulrasool 
3465898e090SSaleem Abdulrasool     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
3475898e090SSaleem Abdulrasool     if (!Value) {
3485898e090SSaleem Abdulrasool       YS.printError(Field.getValue(), "descriptor value must be a scalar");
3495898e090SSaleem Abdulrasool       return false;
3505898e090SSaleem Abdulrasool     }
3515898e090SSaleem Abdulrasool 
3525898e090SSaleem Abdulrasool     KeyValue = Key->getValue(KeyStorage);
353d2c5d7f6SSaleem Abdulrasool     if (KeyValue.equals("source")) {
3545898e090SSaleem Abdulrasool       std::string Error;
3555898e090SSaleem Abdulrasool 
356adcd0268SBenjamin Kramer       Source = std::string(Value->getValue(ValueStorage));
3575898e090SSaleem Abdulrasool       if (!Regex(Source).isValid(Error)) {
3585898e090SSaleem Abdulrasool         YS.printError(Field.getKey(), "invalid regex: " + Error);
3595898e090SSaleem Abdulrasool         return false;
3605898e090SSaleem Abdulrasool       }
361d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("target")) {
362adcd0268SBenjamin Kramer       Target = std::string(Value->getValue(ValueStorage));
363d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("transform")) {
364adcd0268SBenjamin Kramer       Transform = std::string(Value->getValue(ValueStorage));
365d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("naked")) {
3665898e090SSaleem Abdulrasool       std::string Undecorated;
3675898e090SSaleem Abdulrasool 
368adcd0268SBenjamin Kramer       Undecorated = std::string(Value->getValue(ValueStorage));
3695898e090SSaleem Abdulrasool       Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
3705898e090SSaleem Abdulrasool     } else {
3715898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "unknown key for function");
3725898e090SSaleem Abdulrasool       return false;
3735898e090SSaleem Abdulrasool     }
3745898e090SSaleem Abdulrasool   }
3755898e090SSaleem Abdulrasool 
3765898e090SSaleem Abdulrasool   if (Transform.empty() == Target.empty()) {
3775898e090SSaleem Abdulrasool     YS.printError(Descriptor,
3785898e090SSaleem Abdulrasool                   "exactly one of transform or target must be specified");
3795898e090SSaleem Abdulrasool     return false;
3805898e090SSaleem Abdulrasool   }
3815898e090SSaleem Abdulrasool 
3825898e090SSaleem Abdulrasool   // TODO see if there is a more elegant solution to selecting the rewrite
3835898e090SSaleem Abdulrasool   // descriptor type
3845898e090SSaleem Abdulrasool   if (!Target.empty())
3850eaee545SJonas Devlieghere     DL->push_back(std::make_unique<ExplicitRewriteFunctionDescriptor>(
3869a89b15aSMichael Kuperstein         Source, Target, Naked));
3875898e090SSaleem Abdulrasool   else
3888f8e1d1bSMichael Kuperstein     DL->push_back(
3890eaee545SJonas Devlieghere         std::make_unique<PatternRewriteFunctionDescriptor>(Source, Transform));
3905898e090SSaleem Abdulrasool 
3915898e090SSaleem Abdulrasool   return true;
3925898e090SSaleem Abdulrasool }
3935898e090SSaleem Abdulrasool 
3945898e090SSaleem Abdulrasool bool RewriteMapParser::
parseRewriteGlobalVariableDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)3955898e090SSaleem Abdulrasool parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
3965898e090SSaleem Abdulrasool                                      yaml::MappingNode *Descriptor,
3975898e090SSaleem Abdulrasool                                      RewriteDescriptorList *DL) {
3985898e090SSaleem Abdulrasool   std::string Source;
3995898e090SSaleem Abdulrasool   std::string Target;
4005898e090SSaleem Abdulrasool   std::string Transform;
4015898e090SSaleem Abdulrasool 
4025898e090SSaleem Abdulrasool   for (auto &Field : *Descriptor) {
4035898e090SSaleem Abdulrasool     yaml::ScalarNode *Key;
4045898e090SSaleem Abdulrasool     yaml::ScalarNode *Value;
4055898e090SSaleem Abdulrasool     SmallString<32> KeyStorage;
4065898e090SSaleem Abdulrasool     SmallString<32> ValueStorage;
4075898e090SSaleem Abdulrasool     StringRef KeyValue;
4085898e090SSaleem Abdulrasool 
4095898e090SSaleem Abdulrasool     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
4105898e090SSaleem Abdulrasool     if (!Key) {
4115898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "descriptor Key must be a scalar");
4125898e090SSaleem Abdulrasool       return false;
4135898e090SSaleem Abdulrasool     }
4145898e090SSaleem Abdulrasool 
4155898e090SSaleem Abdulrasool     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
4165898e090SSaleem Abdulrasool     if (!Value) {
4175898e090SSaleem Abdulrasool       YS.printError(Field.getValue(), "descriptor value must be a scalar");
4185898e090SSaleem Abdulrasool       return false;
4195898e090SSaleem Abdulrasool     }
4205898e090SSaleem Abdulrasool 
4215898e090SSaleem Abdulrasool     KeyValue = Key->getValue(KeyStorage);
422d2c5d7f6SSaleem Abdulrasool     if (KeyValue.equals("source")) {
4235898e090SSaleem Abdulrasool       std::string Error;
4245898e090SSaleem Abdulrasool 
425adcd0268SBenjamin Kramer       Source = std::string(Value->getValue(ValueStorage));
4265898e090SSaleem Abdulrasool       if (!Regex(Source).isValid(Error)) {
4275898e090SSaleem Abdulrasool         YS.printError(Field.getKey(), "invalid regex: " + Error);
4285898e090SSaleem Abdulrasool         return false;
4295898e090SSaleem Abdulrasool       }
430d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("target")) {
431adcd0268SBenjamin Kramer       Target = std::string(Value->getValue(ValueStorage));
432d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("transform")) {
433adcd0268SBenjamin Kramer       Transform = std::string(Value->getValue(ValueStorage));
4345898e090SSaleem Abdulrasool     } else {
4355898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "unknown Key for Global Variable");
4365898e090SSaleem Abdulrasool       return false;
4375898e090SSaleem Abdulrasool     }
4385898e090SSaleem Abdulrasool   }
4395898e090SSaleem Abdulrasool 
4405898e090SSaleem Abdulrasool   if (Transform.empty() == Target.empty()) {
4415898e090SSaleem Abdulrasool     YS.printError(Descriptor,
4425898e090SSaleem Abdulrasool                   "exactly one of transform or target must be specified");
4435898e090SSaleem Abdulrasool     return false;
4445898e090SSaleem Abdulrasool   }
4455898e090SSaleem Abdulrasool 
4465898e090SSaleem Abdulrasool   if (!Target.empty())
4470eaee545SJonas Devlieghere     DL->push_back(std::make_unique<ExplicitRewriteGlobalVariableDescriptor>(
4489a89b15aSMichael Kuperstein         Source, Target,
4495898e090SSaleem Abdulrasool         /*Naked*/ false));
4505898e090SSaleem Abdulrasool   else
4510eaee545SJonas Devlieghere     DL->push_back(std::make_unique<PatternRewriteGlobalVariableDescriptor>(
4529a89b15aSMichael Kuperstein         Source, Transform));
4535898e090SSaleem Abdulrasool 
4545898e090SSaleem Abdulrasool   return true;
4555898e090SSaleem Abdulrasool }
4565898e090SSaleem Abdulrasool 
4575898e090SSaleem Abdulrasool bool RewriteMapParser::
parseRewriteGlobalAliasDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)4585898e090SSaleem Abdulrasool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
4595898e090SSaleem Abdulrasool                                   yaml::MappingNode *Descriptor,
4605898e090SSaleem Abdulrasool                                   RewriteDescriptorList *DL) {
4615898e090SSaleem Abdulrasool   std::string Source;
4625898e090SSaleem Abdulrasool   std::string Target;
4635898e090SSaleem Abdulrasool   std::string Transform;
4645898e090SSaleem Abdulrasool 
4655898e090SSaleem Abdulrasool   for (auto &Field : *Descriptor) {
4665898e090SSaleem Abdulrasool     yaml::ScalarNode *Key;
4675898e090SSaleem Abdulrasool     yaml::ScalarNode *Value;
4685898e090SSaleem Abdulrasool     SmallString<32> KeyStorage;
4695898e090SSaleem Abdulrasool     SmallString<32> ValueStorage;
4705898e090SSaleem Abdulrasool     StringRef KeyValue;
4715898e090SSaleem Abdulrasool 
4725898e090SSaleem Abdulrasool     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
4735898e090SSaleem Abdulrasool     if (!Key) {
4745898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "descriptor key must be a scalar");
4755898e090SSaleem Abdulrasool       return false;
4765898e090SSaleem Abdulrasool     }
4775898e090SSaleem Abdulrasool 
4785898e090SSaleem Abdulrasool     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
4795898e090SSaleem Abdulrasool     if (!Value) {
4805898e090SSaleem Abdulrasool       YS.printError(Field.getValue(), "descriptor value must be a scalar");
4815898e090SSaleem Abdulrasool       return false;
4825898e090SSaleem Abdulrasool     }
4835898e090SSaleem Abdulrasool 
4845898e090SSaleem Abdulrasool     KeyValue = Key->getValue(KeyStorage);
485d2c5d7f6SSaleem Abdulrasool     if (KeyValue.equals("source")) {
4865898e090SSaleem Abdulrasool       std::string Error;
4875898e090SSaleem Abdulrasool 
488adcd0268SBenjamin Kramer       Source = std::string(Value->getValue(ValueStorage));
4895898e090SSaleem Abdulrasool       if (!Regex(Source).isValid(Error)) {
4905898e090SSaleem Abdulrasool         YS.printError(Field.getKey(), "invalid regex: " + Error);
4915898e090SSaleem Abdulrasool         return false;
4925898e090SSaleem Abdulrasool       }
493d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("target")) {
494adcd0268SBenjamin Kramer       Target = std::string(Value->getValue(ValueStorage));
495d2c5d7f6SSaleem Abdulrasool     } else if (KeyValue.equals("transform")) {
496adcd0268SBenjamin Kramer       Transform = std::string(Value->getValue(ValueStorage));
4975898e090SSaleem Abdulrasool     } else {
4985898e090SSaleem Abdulrasool       YS.printError(Field.getKey(), "unknown key for Global Alias");
4995898e090SSaleem Abdulrasool       return false;
5005898e090SSaleem Abdulrasool     }
5015898e090SSaleem Abdulrasool   }
5025898e090SSaleem Abdulrasool 
5035898e090SSaleem Abdulrasool   if (Transform.empty() == Target.empty()) {
5045898e090SSaleem Abdulrasool     YS.printError(Descriptor,
5055898e090SSaleem Abdulrasool                   "exactly one of transform or target must be specified");
5065898e090SSaleem Abdulrasool     return false;
5075898e090SSaleem Abdulrasool   }
5085898e090SSaleem Abdulrasool 
5095898e090SSaleem Abdulrasool   if (!Target.empty())
5100eaee545SJonas Devlieghere     DL->push_back(std::make_unique<ExplicitRewriteNamedAliasDescriptor>(
5119a89b15aSMichael Kuperstein         Source, Target,
5125898e090SSaleem Abdulrasool         /*Naked*/ false));
5135898e090SSaleem Abdulrasool   else
5140eaee545SJonas Devlieghere     DL->push_back(std::make_unique<PatternRewriteNamedAliasDescriptor>(
5159a89b15aSMichael Kuperstein         Source, Transform));
5165898e090SSaleem Abdulrasool 
5175898e090SSaleem Abdulrasool   return true;
5185898e090SSaleem Abdulrasool }
5195898e090SSaleem Abdulrasool 
5205898e090SSaleem Abdulrasool namespace {
521286d5897SEugene Zelenko 
52239feb629SMichael Kuperstein class RewriteSymbolsLegacyPass : public ModulePass {
5235898e090SSaleem Abdulrasool public:
5245898e090SSaleem Abdulrasool   static char ID; // Pass identification, replacement for typeid
5255898e090SSaleem Abdulrasool 
52639feb629SMichael Kuperstein   RewriteSymbolsLegacyPass();
52739feb629SMichael Kuperstein   RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList &DL);
5285898e090SSaleem Abdulrasool 
529711cd9c5SDavid Blaikie   bool runOnModule(Module &M) override;
5305898e090SSaleem Abdulrasool 
5315898e090SSaleem Abdulrasool private:
53239feb629SMichael Kuperstein   RewriteSymbolPass Impl;
5335898e090SSaleem Abdulrasool };
5345898e090SSaleem Abdulrasool 
535286d5897SEugene Zelenko } // end anonymous namespace
536286d5897SEugene Zelenko 
53739feb629SMichael Kuperstein char RewriteSymbolsLegacyPass::ID = 0;
5385898e090SSaleem Abdulrasool 
RewriteSymbolsLegacyPass()539286d5897SEugene Zelenko RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass() : ModulePass(ID) {
54039feb629SMichael Kuperstein   initializeRewriteSymbolsLegacyPassPass(*PassRegistry::getPassRegistry());
5415898e090SSaleem Abdulrasool }
5425898e090SSaleem Abdulrasool 
RewriteSymbolsLegacyPass(SymbolRewriter::RewriteDescriptorList & DL)54339feb629SMichael Kuperstein RewriteSymbolsLegacyPass::RewriteSymbolsLegacyPass(
54439feb629SMichael Kuperstein     SymbolRewriter::RewriteDescriptorList &DL)
54539feb629SMichael Kuperstein     : ModulePass(ID), Impl(DL) {}
54639feb629SMichael Kuperstein 
runOnModule(Module & M)54739feb629SMichael Kuperstein bool RewriteSymbolsLegacyPass::runOnModule(Module &M) {
54839feb629SMichael Kuperstein   return Impl.runImpl(M);
54939feb629SMichael Kuperstein }
5505898e090SSaleem Abdulrasool 
run(Module & M,ModuleAnalysisManager & AM)55139feb629SMichael Kuperstein PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) {
55239feb629SMichael Kuperstein   if (!runImpl(M))
55339feb629SMichael Kuperstein     return PreservedAnalyses::all();
55439feb629SMichael Kuperstein 
55539feb629SMichael Kuperstein   return PreservedAnalyses::none();
55639feb629SMichael Kuperstein }
55739feb629SMichael Kuperstein 
runImpl(Module & M)55839feb629SMichael Kuperstein bool RewriteSymbolPass::runImpl(Module &M) {
5595898e090SSaleem Abdulrasool   bool Changed;
5605898e090SSaleem Abdulrasool 
5615898e090SSaleem Abdulrasool   Changed = false;
5625898e090SSaleem Abdulrasool   for (auto &Descriptor : Descriptors)
5638f8e1d1bSMichael Kuperstein     Changed |= Descriptor->performOnModule(M);
5645898e090SSaleem Abdulrasool 
5655898e090SSaleem Abdulrasool   return Changed;
5665898e090SSaleem Abdulrasool }
5675898e090SSaleem Abdulrasool 
loadAndParseMapFiles()56839feb629SMichael Kuperstein void RewriteSymbolPass::loadAndParseMapFiles() {
5695898e090SSaleem Abdulrasool   const std::vector<std::string> MapFiles(RewriteMapFiles);
57039feb629SMichael Kuperstein   SymbolRewriter::RewriteMapParser Parser;
5715898e090SSaleem Abdulrasool 
5725898e090SSaleem Abdulrasool   for (const auto &MapFile : MapFiles)
57339feb629SMichael Kuperstein     Parser.parse(MapFile, &Descriptors);
5745898e090SSaleem Abdulrasool }
5755898e090SSaleem Abdulrasool 
57639feb629SMichael Kuperstein INITIALIZE_PASS(RewriteSymbolsLegacyPass, "rewrite-symbols", "Rewrite Symbols",
57739feb629SMichael Kuperstein                 false, false)
5785898e090SSaleem Abdulrasool 
createRewriteSymbolsPass()57939feb629SMichael Kuperstein ModulePass *llvm::createRewriteSymbolsPass() {
58039feb629SMichael Kuperstein   return new RewriteSymbolsLegacyPass();
58139feb629SMichael Kuperstein }
5825898e090SSaleem Abdulrasool 
5835898e090SSaleem Abdulrasool ModulePass *
createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList & DL)5845898e090SSaleem Abdulrasool llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
58539feb629SMichael Kuperstein   return new RewriteSymbolsLegacyPass(DL);
5865898e090SSaleem Abdulrasool }
587