xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/SymbolRewriter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- SymbolRewriter.cpp - Symbol Rewriter -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // SymbolRewriter is a LLVM pass which can rewrite symbols transparently within
100b57cec5SDimitry Andric // existing code.  It is implemented as a compiler pass and is configured via a
110b57cec5SDimitry Andric // YAML configuration file.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // The YAML configuration file format is as follows:
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric // RewriteMapFile := RewriteDescriptors
160b57cec5SDimitry Andric // RewriteDescriptors := RewriteDescriptor | RewriteDescriptors
170b57cec5SDimitry Andric // RewriteDescriptor := RewriteDescriptorType ':' '{' RewriteDescriptorFields '}'
180b57cec5SDimitry Andric // RewriteDescriptorFields := RewriteDescriptorField | RewriteDescriptorFields
190b57cec5SDimitry Andric // RewriteDescriptorField := FieldIdentifier ':' FieldValue ','
200b57cec5SDimitry Andric // RewriteDescriptorType := Identifier
210b57cec5SDimitry Andric // FieldIdentifier := Identifier
220b57cec5SDimitry Andric // FieldValue := Identifier
230b57cec5SDimitry Andric // Identifier := [0-9a-zA-Z]+
240b57cec5SDimitry Andric //
250b57cec5SDimitry Andric // Currently, the following descriptor types are supported:
260b57cec5SDimitry Andric //
270b57cec5SDimitry Andric // - function:          (function rewriting)
280b57cec5SDimitry Andric //      + Source        (original name of the function)
290b57cec5SDimitry Andric //      + Target        (explicit transformation)
300b57cec5SDimitry Andric //      + Transform     (pattern transformation)
310b57cec5SDimitry Andric //      + Naked         (boolean, whether the function is undecorated)
320b57cec5SDimitry Andric // - global variable:   (external linkage global variable rewriting)
330b57cec5SDimitry Andric //      + Source        (original name of externally visible variable)
340b57cec5SDimitry Andric //      + Target        (explicit transformation)
350b57cec5SDimitry Andric //      + Transform     (pattern transformation)
360b57cec5SDimitry Andric // - global alias:      (global alias rewriting)
370b57cec5SDimitry Andric //      + Source        (original name of the aliased name)
380b57cec5SDimitry Andric //      + Target        (explicit transformation)
390b57cec5SDimitry Andric //      + Transform     (pattern transformation)
400b57cec5SDimitry Andric //
410b57cec5SDimitry Andric // Note that source and exactly one of [Target, Transform] must be provided
420b57cec5SDimitry Andric //
430b57cec5SDimitry Andric // New rewrite descriptors can be created.  Addding a new rewrite descriptor
440b57cec5SDimitry Andric // involves:
450b57cec5SDimitry Andric //
460b57cec5SDimitry Andric //  a) extended the rewrite descriptor kind enumeration
470b57cec5SDimitry Andric //     (<anonymous>::RewriteDescriptor::RewriteDescriptorType)
480b57cec5SDimitry Andric //  b) implementing the new descriptor
490b57cec5SDimitry Andric //     (c.f. <anonymous>::ExplicitRewriteFunctionDescriptor)
500b57cec5SDimitry Andric //  c) extending the rewrite map parser
510b57cec5SDimitry Andric //     (<anonymous>::RewriteMapParser::parseEntry)
520b57cec5SDimitry Andric //
530b57cec5SDimitry Andric //  Specify to rewrite the symbols using the `-rewrite-symbols` option, and
540b57cec5SDimitry Andric //  specify the map file to use for the rewriting via the `-rewrite-map-file`
550b57cec5SDimitry Andric //  option.
560b57cec5SDimitry Andric //
570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SymbolRewriter.h"
600b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
610b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
620b57cec5SDimitry Andric #include "llvm/ADT/ilist.h"
630b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
640b57cec5SDimitry Andric #include "llvm/IR/Comdat.h"
650b57cec5SDimitry Andric #include "llvm/IR/Function.h"
660b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
670b57cec5SDimitry Andric #include "llvm/IR/GlobalObject.h"
680b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
690b57cec5SDimitry Andric #include "llvm/IR/Module.h"
700b57cec5SDimitry Andric #include "llvm/IR/Value.h"
710b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
720b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
730b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
740b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
750b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
760b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
770b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
780b57cec5SDimitry Andric #include "llvm/Support/YAMLParser.h"
790b57cec5SDimitry Andric #include <memory>
800b57cec5SDimitry Andric #include <string>
810b57cec5SDimitry Andric #include <vector>
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric using namespace llvm;
840b57cec5SDimitry Andric using namespace SymbolRewriter;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric #define DEBUG_TYPE "symbol-rewriter"
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric static cl::list<std::string> RewriteMapFiles("rewrite-map-file",
890b57cec5SDimitry Andric                                              cl::desc("Symbol Rewrite Map"),
900b57cec5SDimitry Andric                                              cl::value_desc("filename"),
910b57cec5SDimitry Andric                                              cl::Hidden);
920b57cec5SDimitry Andric 
rewriteComdat(Module & M,GlobalObject * GO,const std::string & Source,const std::string & Target)930b57cec5SDimitry Andric static void rewriteComdat(Module &M, GlobalObject *GO,
940b57cec5SDimitry Andric                           const std::string &Source,
950b57cec5SDimitry Andric                           const std::string &Target) {
960b57cec5SDimitry Andric   if (Comdat *CD = GO->getComdat()) {
970b57cec5SDimitry Andric     auto &Comdats = M.getComdatSymbolTable();
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric     Comdat *C = M.getOrInsertComdat(Target);
1000b57cec5SDimitry Andric     C->setSelectionKind(CD->getSelectionKind());
1010b57cec5SDimitry Andric     GO->setComdat(C);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric     Comdats.erase(Comdats.find(Source));
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric namespace {
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric template <RewriteDescriptor::Type DT, typename ValueType,
1100b57cec5SDimitry Andric           ValueType *(Module::*Get)(StringRef) const>
1110b57cec5SDimitry Andric class ExplicitRewriteDescriptor : public RewriteDescriptor {
1120b57cec5SDimitry Andric public:
1130b57cec5SDimitry Andric   const std::string Source;
1140b57cec5SDimitry Andric   const std::string Target;
1150b57cec5SDimitry Andric 
ExplicitRewriteDescriptor(StringRef S,StringRef T,const bool Naked)1160b57cec5SDimitry Andric   ExplicitRewriteDescriptor(StringRef S, StringRef T, const bool Naked)
1175ffd83dbSDimitry Andric       : RewriteDescriptor(DT),
1185ffd83dbSDimitry Andric         Source(std::string(Naked ? StringRef("\01" + S.str()) : S)),
1195ffd83dbSDimitry Andric         Target(std::string(T)) {}
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   bool performOnModule(Module &M) override;
1220b57cec5SDimitry Andric 
classof(const RewriteDescriptor * RD)1230b57cec5SDimitry Andric   static bool classof(const RewriteDescriptor *RD) {
1240b57cec5SDimitry Andric     return RD->getType() == DT;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric };
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric } // end anonymous namespace
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric template <RewriteDescriptor::Type DT, typename ValueType,
1310b57cec5SDimitry Andric           ValueType *(Module::*Get)(StringRef) const>
performOnModule(Module & M)1320b57cec5SDimitry Andric bool ExplicitRewriteDescriptor<DT, ValueType, Get>::performOnModule(Module &M) {
1330b57cec5SDimitry Andric   bool Changed = false;
1340b57cec5SDimitry Andric   if (ValueType *S = (M.*Get)(Source)) {
1350b57cec5SDimitry Andric     if (GlobalObject *GO = dyn_cast<GlobalObject>(S))
1360b57cec5SDimitry Andric       rewriteComdat(M, GO, Source, Target);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     if (Value *T = (M.*Get)(Target))
1390b57cec5SDimitry Andric       S->setValueName(T->getValueName());
1400b57cec5SDimitry Andric     else
1410b57cec5SDimitry Andric       S->setName(Target);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric     Changed = true;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric   return Changed;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric namespace {
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric template <RewriteDescriptor::Type DT, typename ValueType,
1510b57cec5SDimitry Andric           ValueType *(Module::*Get)(StringRef) const,
1520b57cec5SDimitry Andric           iterator_range<typename iplist<ValueType>::iterator>
1530b57cec5SDimitry Andric           (Module::*Iterator)()>
1540b57cec5SDimitry Andric class PatternRewriteDescriptor : public RewriteDescriptor {
1550b57cec5SDimitry Andric public:
1560b57cec5SDimitry Andric   const std::string Pattern;
1570b57cec5SDimitry Andric   const std::string Transform;
1580b57cec5SDimitry Andric 
PatternRewriteDescriptor(StringRef P,StringRef T)1590b57cec5SDimitry Andric   PatternRewriteDescriptor(StringRef P, StringRef T)
1605ffd83dbSDimitry Andric       : RewriteDescriptor(DT), Pattern(std::string(P)),
1615ffd83dbSDimitry Andric         Transform(std::string(T)) {}
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   bool performOnModule(Module &M) override;
1640b57cec5SDimitry Andric 
classof(const RewriteDescriptor * RD)1650b57cec5SDimitry Andric   static bool classof(const RewriteDescriptor *RD) {
1660b57cec5SDimitry Andric     return RD->getType() == DT;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric };
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric } // end anonymous namespace
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric template <RewriteDescriptor::Type DT, typename ValueType,
1730b57cec5SDimitry Andric           ValueType *(Module::*Get)(StringRef) const,
1740b57cec5SDimitry Andric           iterator_range<typename iplist<ValueType>::iterator>
1750b57cec5SDimitry Andric           (Module::*Iterator)()>
1760b57cec5SDimitry Andric bool PatternRewriteDescriptor<DT, ValueType, Get, Iterator>::
performOnModule(Module & M)1770b57cec5SDimitry Andric performOnModule(Module &M) {
1780b57cec5SDimitry Andric   bool Changed = false;
1790b57cec5SDimitry Andric   for (auto &C : (M.*Iterator)()) {
1800b57cec5SDimitry Andric     std::string Error;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     std::string Name = Regex(Pattern).sub(Transform, C.getName(), &Error);
1830b57cec5SDimitry Andric     if (!Error.empty())
184349cc55cSDimitry Andric       report_fatal_error(Twine("unable to transforn ") + C.getName() + " in " +
1850b57cec5SDimitry Andric                          M.getModuleIdentifier() + ": " + Error);
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     if (C.getName() == Name)
1880b57cec5SDimitry Andric       continue;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     if (GlobalObject *GO = dyn_cast<GlobalObject>(&C))
1915ffd83dbSDimitry Andric       rewriteComdat(M, GO, std::string(C.getName()), Name);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric     if (Value *V = (M.*Get)(Name))
1940b57cec5SDimitry Andric       C.setValueName(V->getValueName());
1950b57cec5SDimitry Andric     else
1960b57cec5SDimitry Andric       C.setName(Name);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     Changed = true;
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric   return Changed;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric namespace {
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric /// Represents a rewrite for an explicitly named (function) symbol.  Both the
2060b57cec5SDimitry Andric /// source function name and target function name of the transformation are
2070b57cec5SDimitry Andric /// explicitly spelt out.
2080b57cec5SDimitry Andric using ExplicitRewriteFunctionDescriptor =
2090b57cec5SDimitry Andric     ExplicitRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
2100b57cec5SDimitry Andric                               &Module::getFunction>;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric /// Represents a rewrite for an explicitly named (global variable) symbol.  Both
2130b57cec5SDimitry Andric /// the source variable name and target variable name are spelt out.  This
2140b57cec5SDimitry Andric /// applies only to module level variables.
2150b57cec5SDimitry Andric using ExplicitRewriteGlobalVariableDescriptor =
2160b57cec5SDimitry Andric     ExplicitRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
2170b57cec5SDimitry Andric                               GlobalVariable, &Module::getGlobalVariable>;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric /// Represents a rewrite for an explicitly named global alias.  Both the source
2200b57cec5SDimitry Andric /// and target name are explicitly spelt out.
2210b57cec5SDimitry Andric using ExplicitRewriteNamedAliasDescriptor =
2220b57cec5SDimitry Andric     ExplicitRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
2230b57cec5SDimitry Andric                               &Module::getNamedAlias>;
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric /// Represents a rewrite for a regular expression based pattern for functions.
2260b57cec5SDimitry Andric /// A pattern for the function name is provided and a transformation for that
2270b57cec5SDimitry Andric /// pattern to determine the target function name create the rewrite rule.
2280b57cec5SDimitry Andric using PatternRewriteFunctionDescriptor =
2290b57cec5SDimitry Andric     PatternRewriteDescriptor<RewriteDescriptor::Type::Function, Function,
2300b57cec5SDimitry Andric                              &Module::getFunction, &Module::functions>;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric /// Represents a rewrite for a global variable based upon a matching pattern.
2330b57cec5SDimitry Andric /// Each global variable matching the provided pattern will be transformed as
2340b57cec5SDimitry Andric /// described in the transformation pattern for the target.  Applies only to
2350b57cec5SDimitry Andric /// module level variables.
2360b57cec5SDimitry Andric using PatternRewriteGlobalVariableDescriptor =
2370b57cec5SDimitry Andric     PatternRewriteDescriptor<RewriteDescriptor::Type::GlobalVariable,
2380b57cec5SDimitry Andric                              GlobalVariable, &Module::getGlobalVariable,
2390b57cec5SDimitry Andric                              &Module::globals>;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric /// PatternRewriteNamedAliasDescriptor - represents a rewrite for global
2420b57cec5SDimitry Andric /// aliases which match a given pattern.  The provided transformation will be
2430b57cec5SDimitry Andric /// applied to each of the matching names.
2440b57cec5SDimitry Andric using PatternRewriteNamedAliasDescriptor =
2450b57cec5SDimitry Andric     PatternRewriteDescriptor<RewriteDescriptor::Type::NamedAlias, GlobalAlias,
2460b57cec5SDimitry Andric                              &Module::getNamedAlias, &Module::aliases>;
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric } // end anonymous namespace
2490b57cec5SDimitry Andric 
parse(const std::string & MapFile,RewriteDescriptorList * DL)2500b57cec5SDimitry Andric bool RewriteMapParser::parse(const std::string &MapFile,
2510b57cec5SDimitry Andric                              RewriteDescriptorList *DL) {
2520b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> Mapping =
2530b57cec5SDimitry Andric       MemoryBuffer::getFile(MapFile);
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   if (!Mapping)
256349cc55cSDimitry Andric     report_fatal_error(Twine("unable to read rewrite map '") + MapFile +
257349cc55cSDimitry Andric                        "': " + Mapping.getError().message());
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (!parse(*Mapping, DL))
260349cc55cSDimitry Andric     report_fatal_error(Twine("unable to parse rewrite map '") + MapFile + "'");
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   return true;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
parse(std::unique_ptr<MemoryBuffer> & MapFile,RewriteDescriptorList * DL)2650b57cec5SDimitry Andric bool RewriteMapParser::parse(std::unique_ptr<MemoryBuffer> &MapFile,
2660b57cec5SDimitry Andric                              RewriteDescriptorList *DL) {
2670b57cec5SDimitry Andric   SourceMgr SM;
2680b57cec5SDimitry Andric   yaml::Stream YS(MapFile->getBuffer(), SM);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   for (auto &Document : YS) {
2710b57cec5SDimitry Andric     yaml::MappingNode *DescriptorList;
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric     // ignore empty documents
2740b57cec5SDimitry Andric     if (isa<yaml::NullNode>(Document.getRoot()))
2750b57cec5SDimitry Andric       continue;
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric     DescriptorList = dyn_cast<yaml::MappingNode>(Document.getRoot());
2780b57cec5SDimitry Andric     if (!DescriptorList) {
2790b57cec5SDimitry Andric       YS.printError(Document.getRoot(), "DescriptorList node must be a map");
2800b57cec5SDimitry Andric       return false;
2810b57cec5SDimitry Andric     }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric     for (auto &Descriptor : *DescriptorList)
2840b57cec5SDimitry Andric       if (!parseEntry(YS, Descriptor, DL))
2850b57cec5SDimitry Andric         return false;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   return true;
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric 
parseEntry(yaml::Stream & YS,yaml::KeyValueNode & Entry,RewriteDescriptorList * DL)2910b57cec5SDimitry Andric bool RewriteMapParser::parseEntry(yaml::Stream &YS, yaml::KeyValueNode &Entry,
2920b57cec5SDimitry Andric                                   RewriteDescriptorList *DL) {
2930b57cec5SDimitry Andric   yaml::ScalarNode *Key;
2940b57cec5SDimitry Andric   yaml::MappingNode *Value;
2950b57cec5SDimitry Andric   SmallString<32> KeyStorage;
2960b57cec5SDimitry Andric   StringRef RewriteType;
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   Key = dyn_cast<yaml::ScalarNode>(Entry.getKey());
2990b57cec5SDimitry Andric   if (!Key) {
3000b57cec5SDimitry Andric     YS.printError(Entry.getKey(), "rewrite type must be a scalar");
3010b57cec5SDimitry Andric     return false;
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   Value = dyn_cast<yaml::MappingNode>(Entry.getValue());
3050b57cec5SDimitry Andric   if (!Value) {
3060b57cec5SDimitry Andric     YS.printError(Entry.getValue(), "rewrite descriptor must be a map");
3070b57cec5SDimitry Andric     return false;
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   RewriteType = Key->getValue(KeyStorage);
311*0fca6ea1SDimitry Andric   if (RewriteType == "function")
3120b57cec5SDimitry Andric     return parseRewriteFunctionDescriptor(YS, Key, Value, DL);
313*0fca6ea1SDimitry Andric   else if (RewriteType == "global variable")
3140b57cec5SDimitry Andric     return parseRewriteGlobalVariableDescriptor(YS, Key, Value, DL);
315*0fca6ea1SDimitry Andric   else if (RewriteType == "global alias")
3160b57cec5SDimitry Andric     return parseRewriteGlobalAliasDescriptor(YS, Key, Value, DL);
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   YS.printError(Entry.getKey(), "unknown rewrite type");
3190b57cec5SDimitry Andric   return false;
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric bool RewriteMapParser::
parseRewriteFunctionDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)3230b57cec5SDimitry Andric parseRewriteFunctionDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
3240b57cec5SDimitry Andric                                yaml::MappingNode *Descriptor,
3250b57cec5SDimitry Andric                                RewriteDescriptorList *DL) {
3260b57cec5SDimitry Andric   bool Naked = false;
3270b57cec5SDimitry Andric   std::string Source;
3280b57cec5SDimitry Andric   std::string Target;
3290b57cec5SDimitry Andric   std::string Transform;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   for (auto &Field : *Descriptor) {
3320b57cec5SDimitry Andric     yaml::ScalarNode *Key;
3330b57cec5SDimitry Andric     yaml::ScalarNode *Value;
3340b57cec5SDimitry Andric     SmallString<32> KeyStorage;
3350b57cec5SDimitry Andric     SmallString<32> ValueStorage;
3360b57cec5SDimitry Andric     StringRef KeyValue;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
3390b57cec5SDimitry Andric     if (!Key) {
3400b57cec5SDimitry Andric       YS.printError(Field.getKey(), "descriptor key must be a scalar");
3410b57cec5SDimitry Andric       return false;
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
3450b57cec5SDimitry Andric     if (!Value) {
3460b57cec5SDimitry Andric       YS.printError(Field.getValue(), "descriptor value must be a scalar");
3470b57cec5SDimitry Andric       return false;
3480b57cec5SDimitry Andric     }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     KeyValue = Key->getValue(KeyStorage);
351*0fca6ea1SDimitry Andric     if (KeyValue == "source") {
3520b57cec5SDimitry Andric       std::string Error;
3530b57cec5SDimitry Andric 
3545ffd83dbSDimitry Andric       Source = std::string(Value->getValue(ValueStorage));
3550b57cec5SDimitry Andric       if (!Regex(Source).isValid(Error)) {
3560b57cec5SDimitry Andric         YS.printError(Field.getKey(), "invalid regex: " + Error);
3570b57cec5SDimitry Andric         return false;
3580b57cec5SDimitry Andric       }
359*0fca6ea1SDimitry Andric     } else if (KeyValue == "target") {
3605ffd83dbSDimitry Andric       Target = std::string(Value->getValue(ValueStorage));
361*0fca6ea1SDimitry Andric     } else if (KeyValue == "transform") {
3625ffd83dbSDimitry Andric       Transform = std::string(Value->getValue(ValueStorage));
363*0fca6ea1SDimitry Andric     } else if (KeyValue == "naked") {
3640b57cec5SDimitry Andric       std::string Undecorated;
3650b57cec5SDimitry Andric 
3665ffd83dbSDimitry Andric       Undecorated = std::string(Value->getValue(ValueStorage));
3670b57cec5SDimitry Andric       Naked = StringRef(Undecorated).lower() == "true" || Undecorated == "1";
3680b57cec5SDimitry Andric     } else {
3690b57cec5SDimitry Andric       YS.printError(Field.getKey(), "unknown key for function");
3700b57cec5SDimitry Andric       return false;
3710b57cec5SDimitry Andric     }
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   if (Transform.empty() == Target.empty()) {
3750b57cec5SDimitry Andric     YS.printError(Descriptor,
3760b57cec5SDimitry Andric                   "exactly one of transform or target must be specified");
3770b57cec5SDimitry Andric     return false;
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   // TODO see if there is a more elegant solution to selecting the rewrite
3810b57cec5SDimitry Andric   // descriptor type
3820b57cec5SDimitry Andric   if (!Target.empty())
3838bcb0991SDimitry Andric     DL->push_back(std::make_unique<ExplicitRewriteFunctionDescriptor>(
3840b57cec5SDimitry Andric         Source, Target, Naked));
3850b57cec5SDimitry Andric   else
3860b57cec5SDimitry Andric     DL->push_back(
3878bcb0991SDimitry Andric         std::make_unique<PatternRewriteFunctionDescriptor>(Source, Transform));
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   return true;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric bool RewriteMapParser::
parseRewriteGlobalVariableDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)3930b57cec5SDimitry Andric parseRewriteGlobalVariableDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
3940b57cec5SDimitry Andric                                      yaml::MappingNode *Descriptor,
3950b57cec5SDimitry Andric                                      RewriteDescriptorList *DL) {
3960b57cec5SDimitry Andric   std::string Source;
3970b57cec5SDimitry Andric   std::string Target;
3980b57cec5SDimitry Andric   std::string Transform;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   for (auto &Field : *Descriptor) {
4010b57cec5SDimitry Andric     yaml::ScalarNode *Key;
4020b57cec5SDimitry Andric     yaml::ScalarNode *Value;
4030b57cec5SDimitry Andric     SmallString<32> KeyStorage;
4040b57cec5SDimitry Andric     SmallString<32> ValueStorage;
4050b57cec5SDimitry Andric     StringRef KeyValue;
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
4080b57cec5SDimitry Andric     if (!Key) {
4090b57cec5SDimitry Andric       YS.printError(Field.getKey(), "descriptor Key must be a scalar");
4100b57cec5SDimitry Andric       return false;
4110b57cec5SDimitry Andric     }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
4140b57cec5SDimitry Andric     if (!Value) {
4150b57cec5SDimitry Andric       YS.printError(Field.getValue(), "descriptor value must be a scalar");
4160b57cec5SDimitry Andric       return false;
4170b57cec5SDimitry Andric     }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric     KeyValue = Key->getValue(KeyStorage);
420*0fca6ea1SDimitry Andric     if (KeyValue == "source") {
4210b57cec5SDimitry Andric       std::string Error;
4220b57cec5SDimitry Andric 
4235ffd83dbSDimitry Andric       Source = std::string(Value->getValue(ValueStorage));
4240b57cec5SDimitry Andric       if (!Regex(Source).isValid(Error)) {
4250b57cec5SDimitry Andric         YS.printError(Field.getKey(), "invalid regex: " + Error);
4260b57cec5SDimitry Andric         return false;
4270b57cec5SDimitry Andric       }
428*0fca6ea1SDimitry Andric     } else if (KeyValue == "target") {
4295ffd83dbSDimitry Andric       Target = std::string(Value->getValue(ValueStorage));
430*0fca6ea1SDimitry Andric     } else if (KeyValue == "transform") {
4315ffd83dbSDimitry Andric       Transform = std::string(Value->getValue(ValueStorage));
4320b57cec5SDimitry Andric     } else {
4330b57cec5SDimitry Andric       YS.printError(Field.getKey(), "unknown Key for Global Variable");
4340b57cec5SDimitry Andric       return false;
4350b57cec5SDimitry Andric     }
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   if (Transform.empty() == Target.empty()) {
4390b57cec5SDimitry Andric     YS.printError(Descriptor,
4400b57cec5SDimitry Andric                   "exactly one of transform or target must be specified");
4410b57cec5SDimitry Andric     return false;
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   if (!Target.empty())
4458bcb0991SDimitry Andric     DL->push_back(std::make_unique<ExplicitRewriteGlobalVariableDescriptor>(
4460b57cec5SDimitry Andric         Source, Target,
4470b57cec5SDimitry Andric         /*Naked*/ false));
4480b57cec5SDimitry Andric   else
4498bcb0991SDimitry Andric     DL->push_back(std::make_unique<PatternRewriteGlobalVariableDescriptor>(
4500b57cec5SDimitry Andric         Source, Transform));
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   return true;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric bool RewriteMapParser::
parseRewriteGlobalAliasDescriptor(yaml::Stream & YS,yaml::ScalarNode * K,yaml::MappingNode * Descriptor,RewriteDescriptorList * DL)4560b57cec5SDimitry Andric parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K,
4570b57cec5SDimitry Andric                                   yaml::MappingNode *Descriptor,
4580b57cec5SDimitry Andric                                   RewriteDescriptorList *DL) {
4590b57cec5SDimitry Andric   std::string Source;
4600b57cec5SDimitry Andric   std::string Target;
4610b57cec5SDimitry Andric   std::string Transform;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   for (auto &Field : *Descriptor) {
4640b57cec5SDimitry Andric     yaml::ScalarNode *Key;
4650b57cec5SDimitry Andric     yaml::ScalarNode *Value;
4660b57cec5SDimitry Andric     SmallString<32> KeyStorage;
4670b57cec5SDimitry Andric     SmallString<32> ValueStorage;
4680b57cec5SDimitry Andric     StringRef KeyValue;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric     Key = dyn_cast<yaml::ScalarNode>(Field.getKey());
4710b57cec5SDimitry Andric     if (!Key) {
4720b57cec5SDimitry Andric       YS.printError(Field.getKey(), "descriptor key must be a scalar");
4730b57cec5SDimitry Andric       return false;
4740b57cec5SDimitry Andric     }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric     Value = dyn_cast<yaml::ScalarNode>(Field.getValue());
4770b57cec5SDimitry Andric     if (!Value) {
4780b57cec5SDimitry Andric       YS.printError(Field.getValue(), "descriptor value must be a scalar");
4790b57cec5SDimitry Andric       return false;
4800b57cec5SDimitry Andric     }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric     KeyValue = Key->getValue(KeyStorage);
483*0fca6ea1SDimitry Andric     if (KeyValue == "source") {
4840b57cec5SDimitry Andric       std::string Error;
4850b57cec5SDimitry Andric 
4865ffd83dbSDimitry Andric       Source = std::string(Value->getValue(ValueStorage));
4870b57cec5SDimitry Andric       if (!Regex(Source).isValid(Error)) {
4880b57cec5SDimitry Andric         YS.printError(Field.getKey(), "invalid regex: " + Error);
4890b57cec5SDimitry Andric         return false;
4900b57cec5SDimitry Andric       }
491*0fca6ea1SDimitry Andric     } else if (KeyValue == "target") {
4925ffd83dbSDimitry Andric       Target = std::string(Value->getValue(ValueStorage));
493*0fca6ea1SDimitry Andric     } else if (KeyValue == "transform") {
4945ffd83dbSDimitry Andric       Transform = std::string(Value->getValue(ValueStorage));
4950b57cec5SDimitry Andric     } else {
4960b57cec5SDimitry Andric       YS.printError(Field.getKey(), "unknown key for Global Alias");
4970b57cec5SDimitry Andric       return false;
4980b57cec5SDimitry Andric     }
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   if (Transform.empty() == Target.empty()) {
5020b57cec5SDimitry Andric     YS.printError(Descriptor,
5030b57cec5SDimitry Andric                   "exactly one of transform or target must be specified");
5040b57cec5SDimitry Andric     return false;
5050b57cec5SDimitry Andric   }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   if (!Target.empty())
5088bcb0991SDimitry Andric     DL->push_back(std::make_unique<ExplicitRewriteNamedAliasDescriptor>(
5090b57cec5SDimitry Andric         Source, Target,
5100b57cec5SDimitry Andric         /*Naked*/ false));
5110b57cec5SDimitry Andric   else
5128bcb0991SDimitry Andric     DL->push_back(std::make_unique<PatternRewriteNamedAliasDescriptor>(
5130b57cec5SDimitry Andric         Source, Transform));
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   return true;
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
run(Module & M,ModuleAnalysisManager & AM)5180b57cec5SDimitry Andric PreservedAnalyses RewriteSymbolPass::run(Module &M, ModuleAnalysisManager &AM) {
5190b57cec5SDimitry Andric   if (!runImpl(M))
5200b57cec5SDimitry Andric     return PreservedAnalyses::all();
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   return PreservedAnalyses::none();
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
runImpl(Module & M)5250b57cec5SDimitry Andric bool RewriteSymbolPass::runImpl(Module &M) {
5260b57cec5SDimitry Andric   bool Changed;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   Changed = false;
5290b57cec5SDimitry Andric   for (auto &Descriptor : Descriptors)
5300b57cec5SDimitry Andric     Changed |= Descriptor->performOnModule(M);
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   return Changed;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
loadAndParseMapFiles()5350b57cec5SDimitry Andric void RewriteSymbolPass::loadAndParseMapFiles() {
5360b57cec5SDimitry Andric   const std::vector<std::string> MapFiles(RewriteMapFiles);
5370b57cec5SDimitry Andric   SymbolRewriter::RewriteMapParser Parser;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   for (const auto &MapFile : MapFiles)
5400b57cec5SDimitry Andric     Parser.parse(MapFile, &Descriptors);
5410b57cec5SDimitry Andric }
542