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