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