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 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 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 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> 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 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 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>:: 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 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 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 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:: 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:: 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:: 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 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 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 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