xref: /aosp_15_r20/external/llvm/lib/Transforms/Utils/SymbolRewriter.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- SymbolRewriter.cpp - Symbol Rewriter ---------------------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
11*9880d681SAndroid Build Coastguard Worker // existing code.  It is implemented as a compiler pass and is configured via a
12*9880d681SAndroid Build Coastguard Worker // YAML configuration file.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker // The YAML configuration file format is as follows:
15*9880d681SAndroid Build Coastguard Worker //
16*9880d681SAndroid Build Coastguard Worker // RewriteMapFile := RewriteDescriptors
17*9880d681SAndroid Build Coastguard Worker // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
18*9880d681SAndroid Build Coastguard Worker // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
19*9880d681SAndroid Build Coastguard Worker // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
20*9880d681SAndroid Build Coastguard Worker // RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
21*9880d681SAndroid Build Coastguard Worker // RewriteDescriptorType := Identifier
22*9880d681SAndroid Build Coastguard Worker // FieldIdentifier := Identifier
23*9880d681SAndroid Build Coastguard Worker // FieldValue := Identifier
24*9880d681SAndroid Build Coastguard Worker // Identifier := [0-9a-zA-Z]+
25*9880d681SAndroid Build Coastguard Worker //
26*9880d681SAndroid Build Coastguard Worker // Currently, the following descriptor types are supported:
27*9880d681SAndroid Build Coastguard Worker //
28*9880d681SAndroid Build Coastguard Worker // - function:          (function rewriting)
29*9880d681SAndroid Build Coastguard Worker //      + Source        (original name of the function)
30*9880d681SAndroid Build Coastguard Worker //      + Target        (explicit transformation)
31*9880d681SAndroid Build Coastguard Worker //      + Transform     (pattern transformation)
32*9880d681SAndroid Build Coastguard Worker //      + Naked         (boolean, whether the function is undecorated)
33*9880d681SAndroid Build Coastguard Worker // - global variable:   (external linkage global variable rewriting)
34*9880d681SAndroid Build Coastguard Worker //      + Source        (original name of externally visible variable)
35*9880d681SAndroid Build Coastguard Worker //      + Target        (explicit transformation)
36*9880d681SAndroid Build Coastguard Worker //      + Transform     (pattern transformation)
37*9880d681SAndroid Build Coastguard Worker // - global alias:      (global alias rewriting)
38*9880d681SAndroid Build Coastguard Worker //      + Source        (original name of the aliased name)
39*9880d681SAndroid Build Coastguard Worker //      + Target        (explicit transformation)
40*9880d681SAndroid Build Coastguard Worker //      + Transform     (pattern transformation)
41*9880d681SAndroid Build Coastguard Worker //
42*9880d681SAndroid Build Coastguard Worker // Note that source and exactly one of [Target, Transform] must be provided
43*9880d681SAndroid Build Coastguard Worker //
44*9880d681SAndroid Build Coastguard Worker // New rewrite descriptors can be created.  Addding a new rewrite descriptor
45*9880d681SAndroid Build Coastguard Worker // involves:
46*9880d681SAndroid Build Coastguard Worker //
47*9880d681SAndroid Build Coastguard Worker //  a) extended the rewrite descriptor kind enumeration
48*9880d681SAndroid Build Coastguard Worker //     (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
49*9880d681SAndroid Build Coastguard Worker //  b) implementing the new descriptor
50*9880d681SAndroid Build Coastguard Worker //     (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
51*9880d681SAndroid Build Coastguard Worker //  c) extending the rewrite map parser
52*9880d681SAndroid Build Coastguard Worker //     (<anonymous>::RewriteMapParser::parseEntry)
53*9880d681SAndroid Build Coastguard Worker //
54*9880d681SAndroid Build Coastguard Worker //  Specify to rewrite the symbols using the `-rewrite-symbols` option, and
55*9880d681SAndroid Build Coastguard Worker //  specify the map file to use for the rewriting via the `-rewrite-map-file`
56*9880d681SAndroid Build Coastguard Worker //  option.
57*9880d681SAndroid Build Coastguard Worker //
58*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "symbol-rewriter"
61*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
62*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
63*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LegacyPassManager.h"
64*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
65*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
66*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
67*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Regex.h"
68*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
69*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/YAMLParser.h"
70*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
71*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/SymbolRewriter.h"
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker using namespace llvm;
74*9880d681SAndroid Build Coastguard Worker using namespace SymbolRewriter;
75*9880d681SAndroid Build Coastguard Worker 
76*9880d681SAndroid Build Coastguard Worker static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
77*9880d681SAndroid Build Coastguard Worker                                              cl::desc("Symbol Rewrite Map"),
78*9880d681SAndroid Build Coastguard Worker                                              cl::value_desc("filename"));
79*9880d681SAndroid Build Coastguard Worker 
rewriteComdat(Module & M,GlobalObject * GO,const std::string & Source,const std::string & Target)80*9880d681SAndroid Build Coastguard Worker static void rewriteComdat(Module &M, GlobalObject *GO,
81*9880d681SAndroid Build Coastguard Worker                           const std::string &Source,
82*9880d681SAndroid Build Coastguard Worker                           const std::string &Target) {
83*9880d681SAndroid Build Coastguard Worker   if (Comdat *CD = GO->getComdat()) {
84*9880d681SAndroid Build Coastguard Worker     auto &Comdats = M.getComdatSymbolTable();
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker     Comdat *C = M.getOrInsertComdat(Target);
87*9880d681SAndroid Build Coastguard Worker     C->setSelectionKind(CD->getSelectionKind());
88*9880d681SAndroid Build Coastguard Worker     GO->setComdat(C);
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker     Comdats.erase(Comdats.find(Source));
91*9880d681SAndroid Build Coastguard Worker   }
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker namespace {
95*9880d681SAndroid Build Coastguard Worker template <RewriteDescriptor::Type DT, typename ValueType,
96*9880d681SAndroid Build Coastguard Worker           ValueType *(llvm::Module::*Get)(StringRef) const>
97*9880d681SAndroid Build Coastguard Worker class ExplicitRewriteDescriptor : public RewriteDescriptor {
98*9880d681SAndroid Build Coastguard Worker public:
99*9880d681SAndroid Build Coastguard Worker   const std::string Source;
100*9880d681SAndroid Build Coastguard Worker   const std::string Target;
101*9880d681SAndroid Build Coastguard Worker 
ExplicitRewriteDescriptor(StringRef S,StringRef T,const bool Naked)102*9880d681SAndroid Build Coastguard Worker   ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
103*9880d681SAndroid Build Coastguard Worker       : RewriteDescriptor(DT), Source(Naked ? StringRef("\01" + S.str()) : S),
104*9880d681SAndroid Build Coastguard Worker         Target(T) {}
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   bool performOnModule(Module &M) override;
107*9880d681SAndroid Build Coastguard Worker 
classof(const RewriteDescriptor * RD)108*9880d681SAndroid Build Coastguard Worker   static bool classof(const RewriteDescriptor *RD) {
109*9880d681SAndroid Build Coastguard Worker     return RD->getType() == DT;
110*9880d681SAndroid Build Coastguard Worker   }
111*9880d681SAndroid Build Coastguard Worker };
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker template <RewriteDescriptor::Type DT, typename ValueType,
114*9880d681SAndroid Build Coastguard Worker           ValueType *(llvm::Module::*Get)(StringRef) const>
performOnModule(Module & M)115*9880d681SAndroid Build Coastguard Worker bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
116*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
117*9880d681SAndroid Build Coastguard Worker   if (ValueType *S = (M.*Get)(Source)) {
118*9880d681SAndroid Build Coastguard Worker     if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
119*9880d681SAndroid Build Coastguard Worker       rewriteComdat(M, GO, Source, Target);
120*9880d681SAndroid Build Coastguard Worker 
121*9880d681SAndroid Build Coastguard Worker     if (Value *T = (M.*Get)(Target))
122*9880d681SAndroid Build Coastguard Worker       S->setValueName(T->getValueName());
123*9880d681SAndroid Build Coastguard Worker     else
124*9880d681SAndroid Build Coastguard Worker       S->setName(Target);
125*9880d681SAndroid Build Coastguard Worker 
126*9880d681SAndroid Build Coastguard Worker     Changed = true;
127*9880d681SAndroid Build Coastguard Worker   }
128*9880d681SAndroid Build Coastguard Worker   return Changed;
129*9880d681SAndroid Build Coastguard Worker }
130*9880d681SAndroid Build Coastguard Worker 
131*9880d681SAndroid Build Coastguard Worker template <RewriteDescriptor::Type DT, typename ValueType,
132*9880d681SAndroid Build Coastguard Worker           ValueType *(llvm::Module::*Get)(StringRef) const,
133*9880d681SAndroid Build Coastguard Worker           iterator_range<typename iplist<ValueType>::iterator>
134*9880d681SAndroid Build Coastguard Worker           (llvm::Module::*Iterator)()>
135*9880d681SAndroid Build Coastguard Worker class PatternRewriteDescriptor : public RewriteDescriptor {
136*9880d681SAndroid Build Coastguard Worker public:
137*9880d681SAndroid Build Coastguard Worker   const std::string Pattern;
138*9880d681SAndroid Build Coastguard Worker   const std::string Transform;
139*9880d681SAndroid Build Coastguard Worker 
PatternRewriteDescriptor(StringRef P,StringRef T)140*9880d681SAndroid Build Coastguard Worker   PatternRewriteDescriptor(StringRef P, StringRef T)
141*9880d681SAndroid Build Coastguard Worker     : RewriteDescriptor(DT), Pattern(P), Transform(T) { }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker   bool performOnModule(Module &M) override;
144*9880d681SAndroid Build Coastguard Worker 
classof(const RewriteDescriptor * RD)145*9880d681SAndroid Build Coastguard Worker   static bool classof(const RewriteDescriptor *RD) {
146*9880d681SAndroid Build Coastguard Worker     return RD->getType() == DT;
147*9880d681SAndroid Build Coastguard Worker   }
148*9880d681SAndroid Build Coastguard Worker };
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker template <RewriteDescriptor::Type DT, typename ValueType,
151*9880d681SAndroid Build Coastguard Worker           ValueType *(llvm::Module::*Get)(StringRef) const,
152*9880d681SAndroid Build Coastguard Worker           iterator_range<typename iplist<ValueType>::iterator>
153*9880d681SAndroid Build Coastguard Worker           (llvm::Module::*Iterator)()>
154*9880d681SAndroid Build Coastguard Worker bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
performOnModule(Module & M)155*9880d681SAndroid Build Coastguard Worker performOnModule(Module &M) {
156*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
157*9880d681SAndroid Build Coastguard Worker   for (auto &C : (M.*Iterator)()) {
158*9880d681SAndroid Build Coastguard Worker     std::string Error;
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker     std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
161*9880d681SAndroid Build Coastguard Worker     if (!Error.empty())
162*9880d681SAndroid Build Coastguard Worker       report_fatal_error("unable to transforn " + C.getName() + " in " +
163*9880d681SAndroid Build Coastguard Worker                          M.getModuleIdentifier() + ": " + Error);
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker     if (C.getName() == Name)
166*9880d681SAndroid Build Coastguard Worker       continue;
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker     if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
169*9880d681SAndroid Build Coastguard Worker       rewriteComdat(M, GO, C.getName(), Name);
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker     if (Value *V = (M.*Get)(Name))
172*9880d681SAndroid Build Coastguard Worker       C.setValueName(V->getValueName());
173*9880d681SAndroid Build Coastguard Worker     else
174*9880d681SAndroid Build Coastguard Worker       C.setName(Name);
175*9880d681SAndroid Build Coastguard Worker 
176*9880d681SAndroid Build Coastguard Worker     Changed = true;
177*9880d681SAndroid Build Coastguard Worker   }
178*9880d681SAndroid Build Coastguard Worker   return Changed;
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker /// Represents a rewrite for an explicitly named (function) symbol.  Both the
182*9880d681SAndroid Build Coastguard Worker /// source function name and target function name of the transformation are
183*9880d681SAndroid Build Coastguard Worker /// explicitly spelt out.
184*9880d681SAndroid Build Coastguard Worker typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function,
185*9880d681SAndroid Build Coastguard Worker                                   llvm::Function, &llvm::Module::getFunction>
186*9880d681SAndroid Build Coastguard Worker     ExplicitRewriteFunctionDescriptor;
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker /// Represents a rewrite for an explicitly named (global variable) symbol.  Both
189*9880d681SAndroid Build Coastguard Worker /// the source variable name and target variable name are spelt out.  This
190*9880d681SAndroid Build Coastguard Worker /// applies only to module level variables.
191*9880d681SAndroid Build Coastguard Worker typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
192*9880d681SAndroid Build Coastguard Worker                                   llvm::GlobalVariable,
193*9880d681SAndroid Build Coastguard Worker                                   &llvm::Module::getGlobalVariable>
194*9880d681SAndroid Build Coastguard Worker     ExplicitRewriteGlobalVariableDescriptor;
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker /// Represents a rewrite for an explicitly named global alias.  Both the source
197*9880d681SAndroid Build Coastguard Worker /// and target name are explicitly spelt out.
198*9880d681SAndroid Build Coastguard Worker typedef ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
199*9880d681SAndroid Build Coastguard Worker                                   llvm::GlobalAlias,
200*9880d681SAndroid Build Coastguard Worker                                   &llvm::Module::getNamedAlias>
201*9880d681SAndroid Build Coastguard Worker     ExplicitRewriteNamedAliasDescriptor;
202*9880d681SAndroid Build Coastguard Worker 
203*9880d681SAndroid Build Coastguard Worker /// Represents a rewrite for a regular expression based pattern for functions.
204*9880d681SAndroid Build Coastguard Worker /// A pattern for the function name is provided and a transformation for that
205*9880d681SAndroid Build Coastguard Worker /// pattern to determine the target function name create the rewrite rule.
206*9880d681SAndroid Build Coastguard Worker typedef PatternRewriteDescriptor<RewriteDescriptor::Type::Function,
207*9880d681SAndroid Build Coastguard Worker                                  llvm::Function, &llvm::Module::getFunction,
208*9880d681SAndroid Build Coastguard Worker                                  &llvm::Module::functions>
209*9880d681SAndroid Build Coastguard Worker     PatternRewriteFunctionDescriptor;
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker /// Represents a rewrite for a global variable based upon a matching pattern.
212*9880d681SAndroid Build Coastguard Worker /// Each global variable matching the provided pattern will be transformed as
213*9880d681SAndroid Build Coastguard Worker /// described in the transformation pattern for the target.  Applies only to
214*9880d681SAndroid Build Coastguard Worker /// module level variables.
215*9880d681SAndroid Build Coastguard Worker typedef PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
216*9880d681SAndroid Build Coastguard Worker                                  llvm::GlobalVariable,
217*9880d681SAndroid Build Coastguard Worker                                  &llvm::Module::getGlobalVariable,
218*9880d681SAndroid Build Coastguard Worker                                  &llvm::Module::globals>
219*9880d681SAndroid Build Coastguard Worker     PatternRewriteGlobalVariableDescriptor;
220*9880d681SAndroid Build Coastguard Worker 
221*9880d681SAndroid Build Coastguard Worker /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
222*9880d681SAndroid Build Coastguard Worker /// aliases which match a given pattern.  The provided transformation will be
223*9880d681SAndroid Build Coastguard Worker /// applied to each of the matching names.
224*9880d681SAndroid Build Coastguard Worker typedef PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias,
225*9880d681SAndroid Build Coastguard Worker                                  llvm::GlobalAlias,
226*9880d681SAndroid Build Coastguard Worker                                  &llvm::Module::getNamedAlias,
227*9880d681SAndroid Build Coastguard Worker                                  &llvm::Module::aliases>
228*9880d681SAndroid Build Coastguard Worker     PatternRewriteNamedAliasDescriptor;
229*9880d681SAndroid Build Coastguard Worker } // namespace
230*9880d681SAndroid Build Coastguard Worker 
parse(const std::string & MapFile,RewriteDescriptorList * DL)231*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::parse(const std::string &MapFile,
232*9880d681SAndroid Build Coastguard Worker                              RewriteDescriptorList *DL) {
233*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
234*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getFile(MapFile);
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   if (!Mapping)
237*9880d681SAndroid Build Coastguard Worker     report_fatal_error("unable to read rewrite map '" + MapFile + "': " +
238*9880d681SAndroid Build Coastguard Worker                        Mapping.getError().message());
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker   if (!parse(*Mapping, DL))
241*9880d681SAndroid Build Coastguard Worker     report_fatal_error("unable to parse rewrite map '" + MapFile + "'");
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker   return true;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker 
parse(std::unique_ptr<MemoryBuffer> & MapFile,RewriteDescriptorList * DL)246*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
247*9880d681SAndroid Build Coastguard Worker                              RewriteDescriptorList *DL) {
248*9880d681SAndroid Build Coastguard Worker   SourceMgr SM;
249*9880d681SAndroid Build Coastguard Worker   yaml::Stream YS(MapFile->getBuffer(), SM);
250*9880d681SAndroid Build Coastguard Worker 
251*9880d681SAndroid Build Coastguard Worker   for (auto &Document : YS) {
252*9880d681SAndroid Build Coastguard Worker     yaml::MappingNode *DescriptorList;
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker     // ignore empty documents
255*9880d681SAndroid Build Coastguard Worker     if (isa<yaml::NullNode>(Document.getRoot()))
256*9880d681SAndroid Build Coastguard Worker       continue;
257*9880d681SAndroid Build Coastguard Worker 
258*9880d681SAndroid Build Coastguard Worker     DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
259*9880d681SAndroid Build Coastguard Worker     if (!DescriptorList) {
260*9880d681SAndroid Build Coastguard Worker       YS.printError(Document.getRoot(), "DescriptorList node must be a map");
261*9880d681SAndroid Build Coastguard Worker       return false;
262*9880d681SAndroid Build Coastguard Worker     }
263*9880d681SAndroid Build Coastguard Worker 
264*9880d681SAndroid Build Coastguard Worker     for (auto &Descriptor : *DescriptorList)
265*9880d681SAndroid Build Coastguard Worker       if (!parseEntry(YS, Descriptor, DL))
266*9880d681SAndroid Build Coastguard Worker         return false;
267*9880d681SAndroid Build Coastguard Worker   }
268*9880d681SAndroid Build Coastguard Worker 
269*9880d681SAndroid Build Coastguard Worker   return true;
270*9880d681SAndroid Build Coastguard Worker }
271*9880d681SAndroid Build Coastguard Worker 
parseEntry(yaml::Stream & YS,yaml::KeyValueNode & Entry,RewriteDescriptorList * DL)272*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
273*9880d681SAndroid Build Coastguard Worker                                   RewriteDescriptorList *DL) {
274*9880d681SAndroid Build Coastguard Worker   yaml::ScalarNode *Key;
275*9880d681SAndroid Build Coastguard Worker   yaml::MappingNode *Value;
276*9880d681SAndroid Build Coastguard Worker   SmallString<32> KeyStorage;
277*9880d681SAndroid Build Coastguard Worker   StringRef RewriteType;
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker   Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
280*9880d681SAndroid Build Coastguard Worker   if (!Key) {
281*9880d681SAndroid Build Coastguard Worker     YS.printError(Entry.getKey(), "rewrite type must be a scalar");
282*9880d681SAndroid Build Coastguard Worker     return false;
283*9880d681SAndroid Build Coastguard Worker   }
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
286*9880d681SAndroid Build Coastguard Worker   if (!Value) {
287*9880d681SAndroid Build Coastguard Worker     YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
288*9880d681SAndroid Build Coastguard Worker     return false;
289*9880d681SAndroid Build Coastguard Worker   }
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker   RewriteType = Key->getValue(KeyStorage);
292*9880d681SAndroid Build Coastguard Worker   if (RewriteType.equals("function"))
293*9880d681SAndroid Build Coastguard Worker     return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
294*9880d681SAndroid Build Coastguard Worker   else if (RewriteType.equals("global variable"))
295*9880d681SAndroid Build Coastguard Worker     return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
296*9880d681SAndroid Build Coastguard Worker   else if (RewriteType.equals("global alias"))
297*9880d681SAndroid Build Coastguard Worker     return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
298*9880d681SAndroid Build Coastguard Worker 
299*9880d681SAndroid Build Coastguard Worker   YS.printError(Entry.getKey(), "unknown rewrite type");
300*9880d681SAndroid Build Coastguard Worker   return false;
301*9880d681SAndroid Build Coastguard Worker }
302*9880d681SAndroid Build Coastguard Worker 
303*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::
parseRewriteFunctionDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)304*9880d681SAndroid Build Coastguard Worker parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
305*9880d681SAndroid Build Coastguard Worker                                yaml::MappingNode *Descriptor,
306*9880d681SAndroid Build Coastguard Worker                                RewriteDescriptorList *DL) {
307*9880d681SAndroid Build Coastguard Worker   bool Naked = false;
308*9880d681SAndroid Build Coastguard Worker   std::string Source;
309*9880d681SAndroid Build Coastguard Worker   std::string Target;
310*9880d681SAndroid Build Coastguard Worker   std::string Transform;
311*9880d681SAndroid Build Coastguard Worker 
312*9880d681SAndroid Build Coastguard Worker   for (auto &Field : *Descriptor) {
313*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Key;
314*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Value;
315*9880d681SAndroid Build Coastguard Worker     SmallString<32> KeyStorage;
316*9880d681SAndroid Build Coastguard Worker     SmallString<32> ValueStorage;
317*9880d681SAndroid Build Coastguard Worker     StringRef KeyValue;
318*9880d681SAndroid Build Coastguard Worker 
319*9880d681SAndroid Build Coastguard Worker     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
320*9880d681SAndroid Build Coastguard Worker     if (!Key) {
321*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "descriptor key must be a scalar");
322*9880d681SAndroid Build Coastguard Worker       return false;
323*9880d681SAndroid Build Coastguard Worker     }
324*9880d681SAndroid Build Coastguard Worker 
325*9880d681SAndroid Build Coastguard Worker     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
326*9880d681SAndroid Build Coastguard Worker     if (!Value) {
327*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getValue(), "descriptor value must be a scalar");
328*9880d681SAndroid Build Coastguard Worker       return false;
329*9880d681SAndroid Build Coastguard Worker     }
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker     KeyValue = Key->getValue(KeyStorage);
332*9880d681SAndroid Build Coastguard Worker     if (KeyValue.equals("source")) {
333*9880d681SAndroid Build Coastguard Worker       std::string Error;
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker       Source = Value->getValue(ValueStorage);
336*9880d681SAndroid Build Coastguard Worker       if (!Regex(Source).isValid(Error)) {
337*9880d681SAndroid Build Coastguard Worker         YS.printError(Field.getKey(), "invalid regex: " + Error);
338*9880d681SAndroid Build Coastguard Worker         return false;
339*9880d681SAndroid Build Coastguard Worker       }
340*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("target")) {
341*9880d681SAndroid Build Coastguard Worker       Target = Value->getValue(ValueStorage);
342*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("transform")) {
343*9880d681SAndroid Build Coastguard Worker       Transform = Value->getValue(ValueStorage);
344*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("naked")) {
345*9880d681SAndroid Build Coastguard Worker       std::string Undecorated;
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker       Undecorated = Value->getValue(ValueStorage);
348*9880d681SAndroid Build Coastguard Worker       Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
349*9880d681SAndroid Build Coastguard Worker     } else {
350*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "unknown key for function");
351*9880d681SAndroid Build Coastguard Worker       return false;
352*9880d681SAndroid Build Coastguard Worker     }
353*9880d681SAndroid Build Coastguard Worker   }
354*9880d681SAndroid Build Coastguard Worker 
355*9880d681SAndroid Build Coastguard Worker   if (Transform.empty() == Target.empty()) {
356*9880d681SAndroid Build Coastguard Worker     YS.printError(Descriptor,
357*9880d681SAndroid Build Coastguard Worker                   "exactly one of transform or target must be specified");
358*9880d681SAndroid Build Coastguard Worker     return false;
359*9880d681SAndroid Build Coastguard Worker   }
360*9880d681SAndroid Build Coastguard Worker 
361*9880d681SAndroid Build Coastguard Worker   // TODO see if there is a more elegant solution to selecting the rewrite
362*9880d681SAndroid Build Coastguard Worker   // descriptor type
363*9880d681SAndroid Build Coastguard Worker   if (!Target.empty())
364*9880d681SAndroid Build Coastguard Worker     DL->push_back(new ExplicitRewriteFunctionDescriptor(Source, Target, Naked));
365*9880d681SAndroid Build Coastguard Worker   else
366*9880d681SAndroid Build Coastguard Worker     DL->push_back(new PatternRewriteFunctionDescriptor(Source, Transform));
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker   return true;
369*9880d681SAndroid Build Coastguard Worker }
370*9880d681SAndroid Build Coastguard Worker 
371*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::
parseRewriteGlobalVariableDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)372*9880d681SAndroid Build Coastguard Worker parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
373*9880d681SAndroid Build Coastguard Worker                                      yaml::MappingNode *Descriptor,
374*9880d681SAndroid Build Coastguard Worker                                      RewriteDescriptorList *DL) {
375*9880d681SAndroid Build Coastguard Worker   std::string Source;
376*9880d681SAndroid Build Coastguard Worker   std::string Target;
377*9880d681SAndroid Build Coastguard Worker   std::string Transform;
378*9880d681SAndroid Build Coastguard Worker 
379*9880d681SAndroid Build Coastguard Worker   for (auto &Field : *Descriptor) {
380*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Key;
381*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Value;
382*9880d681SAndroid Build Coastguard Worker     SmallString<32> KeyStorage;
383*9880d681SAndroid Build Coastguard Worker     SmallString<32> ValueStorage;
384*9880d681SAndroid Build Coastguard Worker     StringRef KeyValue;
385*9880d681SAndroid Build Coastguard Worker 
386*9880d681SAndroid Build Coastguard Worker     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
387*9880d681SAndroid Build Coastguard Worker     if (!Key) {
388*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "descriptor Key must be a scalar");
389*9880d681SAndroid Build Coastguard Worker       return false;
390*9880d681SAndroid Build Coastguard Worker     }
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
393*9880d681SAndroid Build Coastguard Worker     if (!Value) {
394*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getValue(), "descriptor value must be a scalar");
395*9880d681SAndroid Build Coastguard Worker       return false;
396*9880d681SAndroid Build Coastguard Worker     }
397*9880d681SAndroid Build Coastguard Worker 
398*9880d681SAndroid Build Coastguard Worker     KeyValue = Key->getValue(KeyStorage);
399*9880d681SAndroid Build Coastguard Worker     if (KeyValue.equals("source")) {
400*9880d681SAndroid Build Coastguard Worker       std::string Error;
401*9880d681SAndroid Build Coastguard Worker 
402*9880d681SAndroid Build Coastguard Worker       Source = Value->getValue(ValueStorage);
403*9880d681SAndroid Build Coastguard Worker       if (!Regex(Source).isValid(Error)) {
404*9880d681SAndroid Build Coastguard Worker         YS.printError(Field.getKey(), "invalid regex: " + Error);
405*9880d681SAndroid Build Coastguard Worker         return false;
406*9880d681SAndroid Build Coastguard Worker       }
407*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("target")) {
408*9880d681SAndroid Build Coastguard Worker       Target = Value->getValue(ValueStorage);
409*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("transform")) {
410*9880d681SAndroid Build Coastguard Worker       Transform = Value->getValue(ValueStorage);
411*9880d681SAndroid Build Coastguard Worker     } else {
412*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "unknown Key for Global Variable");
413*9880d681SAndroid Build Coastguard Worker       return false;
414*9880d681SAndroid Build Coastguard Worker     }
415*9880d681SAndroid Build Coastguard Worker   }
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker   if (Transform.empty() == Target.empty()) {
418*9880d681SAndroid Build Coastguard Worker     YS.printError(Descriptor,
419*9880d681SAndroid Build Coastguard Worker                   "exactly one of transform or target must be specified");
420*9880d681SAndroid Build Coastguard Worker     return false;
421*9880d681SAndroid Build Coastguard Worker   }
422*9880d681SAndroid Build Coastguard Worker 
423*9880d681SAndroid Build Coastguard Worker   if (!Target.empty())
424*9880d681SAndroid Build Coastguard Worker     DL->push_back(new ExplicitRewriteGlobalVariableDescriptor(Source, Target,
425*9880d681SAndroid Build Coastguard Worker                                                               /*Naked*/false));
426*9880d681SAndroid Build Coastguard Worker   else
427*9880d681SAndroid Build Coastguard Worker     DL->push_back(new PatternRewriteGlobalVariableDescriptor(Source,
428*9880d681SAndroid Build Coastguard Worker                                                              Transform));
429*9880d681SAndroid Build Coastguard Worker 
430*9880d681SAndroid Build Coastguard Worker   return true;
431*9880d681SAndroid Build Coastguard Worker }
432*9880d681SAndroid Build Coastguard Worker 
433*9880d681SAndroid Build Coastguard Worker bool RewriteMapParser::
parseRewriteGlobalAliasDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)434*9880d681SAndroid Build Coastguard Worker parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
435*9880d681SAndroid Build Coastguard Worker                                   yaml::MappingNode *Descriptor,
436*9880d681SAndroid Build Coastguard Worker                                   RewriteDescriptorList *DL) {
437*9880d681SAndroid Build Coastguard Worker   std::string Source;
438*9880d681SAndroid Build Coastguard Worker   std::string Target;
439*9880d681SAndroid Build Coastguard Worker   std::string Transform;
440*9880d681SAndroid Build Coastguard Worker 
441*9880d681SAndroid Build Coastguard Worker   for (auto &Field : *Descriptor) {
442*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Key;
443*9880d681SAndroid Build Coastguard Worker     yaml::ScalarNode *Value;
444*9880d681SAndroid Build Coastguard Worker     SmallString<32> KeyStorage;
445*9880d681SAndroid Build Coastguard Worker     SmallString<32> ValueStorage;
446*9880d681SAndroid Build Coastguard Worker     StringRef KeyValue;
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
449*9880d681SAndroid Build Coastguard Worker     if (!Key) {
450*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "descriptor key must be a scalar");
451*9880d681SAndroid Build Coastguard Worker       return false;
452*9880d681SAndroid Build Coastguard Worker     }
453*9880d681SAndroid Build Coastguard Worker 
454*9880d681SAndroid Build Coastguard Worker     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
455*9880d681SAndroid Build Coastguard Worker     if (!Value) {
456*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getValue(), "descriptor value must be a scalar");
457*9880d681SAndroid Build Coastguard Worker       return false;
458*9880d681SAndroid Build Coastguard Worker     }
459*9880d681SAndroid Build Coastguard Worker 
460*9880d681SAndroid Build Coastguard Worker     KeyValue = Key->getValue(KeyStorage);
461*9880d681SAndroid Build Coastguard Worker     if (KeyValue.equals("source")) {
462*9880d681SAndroid Build Coastguard Worker       std::string Error;
463*9880d681SAndroid Build Coastguard Worker 
464*9880d681SAndroid Build Coastguard Worker       Source = Value->getValue(ValueStorage);
465*9880d681SAndroid Build Coastguard Worker       if (!Regex(Source).isValid(Error)) {
466*9880d681SAndroid Build Coastguard Worker         YS.printError(Field.getKey(), "invalid regex: " + Error);
467*9880d681SAndroid Build Coastguard Worker         return false;
468*9880d681SAndroid Build Coastguard Worker       }
469*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("target")) {
470*9880d681SAndroid Build Coastguard Worker       Target = Value->getValue(ValueStorage);
471*9880d681SAndroid Build Coastguard Worker     } else if (KeyValue.equals("transform")) {
472*9880d681SAndroid Build Coastguard Worker       Transform = Value->getValue(ValueStorage);
473*9880d681SAndroid Build Coastguard Worker     } else {
474*9880d681SAndroid Build Coastguard Worker       YS.printError(Field.getKey(), "unknown key for Global Alias");
475*9880d681SAndroid Build Coastguard Worker       return false;
476*9880d681SAndroid Build Coastguard Worker     }
477*9880d681SAndroid Build Coastguard Worker   }
478*9880d681SAndroid Build Coastguard Worker 
479*9880d681SAndroid Build Coastguard Worker   if (Transform.empty() == Target.empty()) {
480*9880d681SAndroid Build Coastguard Worker     YS.printError(Descriptor,
481*9880d681SAndroid Build Coastguard Worker                   "exactly one of transform or target must be specified");
482*9880d681SAndroid Build Coastguard Worker     return false;
483*9880d681SAndroid Build Coastguard Worker   }
484*9880d681SAndroid Build Coastguard Worker 
485*9880d681SAndroid Build Coastguard Worker   if (!Target.empty())
486*9880d681SAndroid Build Coastguard Worker     DL->push_back(new ExplicitRewriteNamedAliasDescriptor(Source, Target,
487*9880d681SAndroid Build Coastguard Worker                                                           /*Naked*/false));
488*9880d681SAndroid Build Coastguard Worker   else
489*9880d681SAndroid Build Coastguard Worker     DL->push_back(new PatternRewriteNamedAliasDescriptor(Source, Transform));
490*9880d681SAndroid Build Coastguard Worker 
491*9880d681SAndroid Build Coastguard Worker   return true;
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker 
494*9880d681SAndroid Build Coastguard Worker namespace {
495*9880d681SAndroid Build Coastguard Worker class RewriteSymbols : public ModulePass {
496*9880d681SAndroid Build Coastguard Worker public:
497*9880d681SAndroid Build Coastguard Worker   static char ID; // Pass identification, replacement for typeid
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker   RewriteSymbols();
500*9880d681SAndroid Build Coastguard Worker   RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL);
501*9880d681SAndroid Build Coastguard Worker 
502*9880d681SAndroid Build Coastguard Worker   bool runOnModule(Module &M) override;
503*9880d681SAndroid Build Coastguard Worker 
504*9880d681SAndroid Build Coastguard Worker private:
505*9880d681SAndroid Build Coastguard Worker   void loadAndParseMapFiles();
506*9880d681SAndroid Build Coastguard Worker 
507*9880d681SAndroid Build Coastguard Worker   SymbolRewriter::RewriteDescriptorList Descriptors;
508*9880d681SAndroid Build Coastguard Worker };
509*9880d681SAndroid Build Coastguard Worker 
510*9880d681SAndroid Build Coastguard Worker char RewriteSymbols::ID = 0;
511*9880d681SAndroid Build Coastguard Worker 
RewriteSymbols()512*9880d681SAndroid Build Coastguard Worker RewriteSymbols::RewriteSymbols() : ModulePass(ID) {
513*9880d681SAndroid Build Coastguard Worker   initializeRewriteSymbolsPass(*PassRegistry::getPassRegistry());
514*9880d681SAndroid Build Coastguard Worker   loadAndParseMapFiles();
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker 
RewriteSymbols(SymbolRewriter::RewriteDescriptorList & DL)517*9880d681SAndroid Build Coastguard Worker RewriteSymbols::RewriteSymbols(SymbolRewriter::RewriteDescriptorList &DL)
518*9880d681SAndroid Build Coastguard Worker     : ModulePass(ID) {
519*9880d681SAndroid Build Coastguard Worker   Descriptors.splice(Descriptors.begin(), DL);
520*9880d681SAndroid Build Coastguard Worker }
521*9880d681SAndroid Build Coastguard Worker 
runOnModule(Module & M)522*9880d681SAndroid Build Coastguard Worker bool RewriteSymbols::runOnModule(Module &M) {
523*9880d681SAndroid Build Coastguard Worker   bool Changed;
524*9880d681SAndroid Build Coastguard Worker 
525*9880d681SAndroid Build Coastguard Worker   Changed = false;
526*9880d681SAndroid Build Coastguard Worker   for (auto &Descriptor : Descriptors)
527*9880d681SAndroid Build Coastguard Worker     Changed |= Descriptor.performOnModule(M);
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker   return Changed;
530*9880d681SAndroid Build Coastguard Worker }
531*9880d681SAndroid Build Coastguard Worker 
loadAndParseMapFiles()532*9880d681SAndroid Build Coastguard Worker void RewriteSymbols::loadAndParseMapFiles() {
533*9880d681SAndroid Build Coastguard Worker   const std::vector<std::string> MapFiles(RewriteMapFiles);
534*9880d681SAndroid Build Coastguard Worker   SymbolRewriter::RewriteMapParser parser;
535*9880d681SAndroid Build Coastguard Worker 
536*9880d681SAndroid Build Coastguard Worker   for (const auto &MapFile : MapFiles)
537*9880d681SAndroid Build Coastguard Worker     parser.parse(MapFile, &Descriptors);
538*9880d681SAndroid Build Coastguard Worker }
539*9880d681SAndroid Build Coastguard Worker }
540*9880d681SAndroid Build Coastguard Worker 
541*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(RewriteSymbols, "rewrite-symbols", "Rewrite Symbols", false,
542*9880d681SAndroid Build Coastguard Worker                 false)
543*9880d681SAndroid Build Coastguard Worker 
createRewriteSymbolsPass()544*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createRewriteSymbolsPass() { return new RewriteSymbols(); }
545*9880d681SAndroid Build Coastguard Worker 
546*9880d681SAndroid Build Coastguard Worker ModulePass *
createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList & DL)547*9880d681SAndroid Build Coastguard Worker llvm::createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &DL) {
548*9880d681SAndroid Build Coastguard Worker   return new RewriteSymbols(DL);
549*9880d681SAndroid Build Coastguard Worker }
550