1b5e2faaaSDavid van Moolenbroek #include <sectionify/SectionifyPass.h>
2b5e2faaaSDavid van Moolenbroek 
3b5e2faaaSDavid van Moolenbroek using namespace llvm;
4b5e2faaaSDavid van Moolenbroek 
5b5e2faaaSDavid van Moolenbroek static cl::list<std::string>
6b5e2faaaSDavid van Moolenbroek sectionMapOpt("sectionify-section-map",
7b5e2faaaSDavid van Moolenbroek     cl::desc("Specify all the comma-separated symbol_regex/section pairs which need to be sectionified. \"NULL\" section doesn't sectionify."),
8b5e2faaaSDavid van Moolenbroek     cl::ZeroOrMore, cl::CommaSeparated, cl::NotHidden, cl::ValueRequired);
9b5e2faaaSDavid van Moolenbroek 
10b5e2faaaSDavid van Moolenbroek static cl::list<std::string>
11b5e2faaaSDavid van Moolenbroek functionSectionMapOpt("sectionify-function-section-map",
12b5e2faaaSDavid van Moolenbroek     cl::desc("Specify all the comma-separated function_regex/section pairs which need to be sectionified"),
13b5e2faaaSDavid van Moolenbroek     cl::ZeroOrMore, cl::CommaSeparated, cl::NotHidden, cl::ValueRequired);
14b5e2faaaSDavid van Moolenbroek 
15b5e2faaaSDavid van Moolenbroek static cl::list<std::string>
16b5e2faaaSDavid van Moolenbroek dataSectionMapOpt("sectionify-data-section-map",
17b5e2faaaSDavid van Moolenbroek     cl::desc("Specify all the comma-separated data_regex/section pairs which need to be sectionified"),
18b5e2faaaSDavid van Moolenbroek     cl::ZeroOrMore, cl::CommaSeparated, cl::NotHidden, cl::ValueRequired);
19b5e2faaaSDavid van Moolenbroek 
20b5e2faaaSDavid van Moolenbroek static cl::opt<std::string>
21b5e2faaaSDavid van Moolenbroek prefixOpt("sectionify-prefix",
22b5e2faaaSDavid van Moolenbroek     cl::desc("Specify the prefix-string for prefixing names of global variables and functions"),
23b5e2faaaSDavid van Moolenbroek     cl::Optional, cl::NotHidden, cl::ValueRequired);
24b5e2faaaSDavid van Moolenbroek 
25b5e2faaaSDavid van Moolenbroek static cl::opt<bool>
26b5e2faaaSDavid van Moolenbroek sectionifyExternalFunctions("sectionify-function-external",
27b5e2faaaSDavid van Moolenbroek     llvm::cl::desc("Also sectionify external functions"),
28b5e2faaaSDavid van Moolenbroek     cl::init(false));
29b5e2faaaSDavid van Moolenbroek 
30b5e2faaaSDavid van Moolenbroek static cl::opt<bool>
31b5e2faaaSDavid van Moolenbroek sectionifyExternalData("sectionify-data-external",
32b5e2faaaSDavid van Moolenbroek     llvm::cl::desc("Also sectionify external data"),
33b5e2faaaSDavid van Moolenbroek     cl::init(false));
34b5e2faaaSDavid van Moolenbroek 
35b5e2faaaSDavid van Moolenbroek static cl::opt<bool>
36b5e2faaaSDavid van Moolenbroek sectionifySkipReadOnlyData("sectionify-data-skip-read-only",
37b5e2faaaSDavid van Moolenbroek     llvm::cl::desc("Don't sectionify read-only data"),
38b5e2faaaSDavid van Moolenbroek     cl::init(false));
39b5e2faaaSDavid van Moolenbroek 
40b5e2faaaSDavid van Moolenbroek static cl::opt<bool>
41b5e2faaaSDavid van Moolenbroek sectionifyTLSData("sectionify-data-tls",
42b5e2faaaSDavid van Moolenbroek     llvm::cl::desc("Also sectionify tls data"),
43b5e2faaaSDavid van Moolenbroek     cl::init(false));
44b5e2faaaSDavid van Moolenbroek 
45b5e2faaaSDavid van Moolenbroek static cl::opt<bool>
46b5e2faaaSDavid van Moolenbroek sectionifyNoOverride("sectionify-no-override",
47b5e2faaaSDavid van Moolenbroek     llvm::cl::desc("Do not override existing sections"),
48b5e2faaaSDavid van Moolenbroek     cl::init(false));
49b5e2faaaSDavid van Moolenbroek 
50b5e2faaaSDavid van Moolenbroek STATISTIC(numSectionifiedGVs, "Number of sectionified global variables");
51b5e2faaaSDavid van Moolenbroek STATISTIC(numSectionifiedFuncs, "Number of sectionified functions");
52b5e2faaaSDavid van Moolenbroek 
53b5e2faaaSDavid van Moolenbroek namespace llvm {
54b5e2faaaSDavid van Moolenbroek 
55b5e2faaaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
56b5e2faaaSDavid van Moolenbroek // Constructors, destructor, and operators
57b5e2faaaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
58b5e2faaaSDavid van Moolenbroek 
SectionifyPass()59b5e2faaaSDavid van Moolenbroek SectionifyPass::SectionifyPass() : ModulePass(ID) {}
60b5e2faaaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
61b5e2faaaSDavid van Moolenbroek // Public methods
62b5e2faaaSDavid van Moolenbroek //===----------------------------------------------------------------------===//
63b5e2faaaSDavid van Moolenbroek 
runOnModule(Module & M)64b5e2faaaSDavid van Moolenbroek bool SectionifyPass::runOnModule(Module &M) {
65b5e2faaaSDavid van Moolenbroek     bool sectionified = false;
66b5e2faaaSDavid van Moolenbroek     Module::GlobalListType &globalList = M.getGlobalList();
67b5e2faaaSDavid van Moolenbroek     Module::FunctionListType &functionList = M.getFunctionList();
68b5e2faaaSDavid van Moolenbroek 
69b5e2faaaSDavid van Moolenbroek     functionSectionMapOpt.insert(functionSectionMapOpt.end(), sectionMapOpt.begin(), sectionMapOpt.end());
70b5e2faaaSDavid van Moolenbroek     dataSectionMapOpt.insert(dataSectionMapOpt.end(), sectionMapOpt.begin(), sectionMapOpt.end());
71b5e2faaaSDavid van Moolenbroek     parseAndInitRegexMap(functionSectionMapOpt, functionRegexList, functionRegexMap, "function");
72b5e2faaaSDavid van Moolenbroek     parseAndInitRegexMap(dataSectionMapOpt, dataRegexList, dataRegexMap, "data");
73b5e2faaaSDavid van Moolenbroek 
74b5e2faaaSDavid van Moolenbroek     moduleName = "";
75b5e2faaaSDavid van Moolenbroek     if ("" != prefixOpt && "%MODULE_NAME%" == prefixOpt)
76b5e2faaaSDavid van Moolenbroek     {
77b5e2faaaSDavid van Moolenbroek 	PassUtil::getModuleName(M, NULL, NULL, &moduleName);
78b5e2faaaSDavid van Moolenbroek     }
79b5e2faaaSDavid van Moolenbroek 
80b5e2faaaSDavid van Moolenbroek     for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
81b5e2faaaSDavid van Moolenbroek         GlobalVariable *GV = it;
82b5e2faaaSDavid van Moolenbroek         if (GV->isDeclaration() && !sectionifyExternalData) {
83b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping external GlobalVariable " << GV->getName() << "\n");
84b5e2faaaSDavid van Moolenbroek             continue;
85b5e2faaaSDavid van Moolenbroek         }
86b5e2faaaSDavid van Moolenbroek         if (GV->isConstant() && sectionifySkipReadOnlyData) {
87b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping read-only GlobalVariable " << GV->getName() << "\n");
88b5e2faaaSDavid van Moolenbroek             continue;
89b5e2faaaSDavid van Moolenbroek         }
90b5e2faaaSDavid van Moolenbroek         if (GV->isThreadLocal() && !sectionifyTLSData) {
91b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping TLS GlobalVariable " << GV->getName() << "\n");
92b5e2faaaSDavid van Moolenbroek             continue;
93b5e2faaaSDavid van Moolenbroek         }
94b5e2faaaSDavid van Moolenbroek         if (GV->hasSection() && sectionifyNoOverride) {
95b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping sectionified GlobalVariable " << GV->getName() << "\n");
96b5e2faaaSDavid van Moolenbroek             continue;
97b5e2faaaSDavid van Moolenbroek         }
98b5e2faaaSDavid van Moolenbroek         if (GV->getName().startswith("llvm.")) {
99b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping LLVM instrinsic GlobalVariable " << GV->getName() << "\n");
100b5e2faaaSDavid van Moolenbroek             continue;
101b5e2faaaSDavid van Moolenbroek         }
102b5e2faaaSDavid van Moolenbroek         if (sectionify(GV, dataRegexList, dataRegexMap)) {
103b5e2faaaSDavid van Moolenbroek             numSectionifiedGVs++;
104b5e2faaaSDavid van Moolenbroek             sectionified = true;
105b5e2faaaSDavid van Moolenbroek         }
106b5e2faaaSDavid van Moolenbroek     }
107b5e2faaaSDavid van Moolenbroek     for (Module::iterator it = functionList.begin(); it != functionList.end(); ++it) {
108b5e2faaaSDavid van Moolenbroek         Function *F = it;
109b5e2faaaSDavid van Moolenbroek         if (F->isDeclaration() && !sectionifyExternalFunctions) {
110b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping external Function " << F->getName() << "\n");
111b5e2faaaSDavid van Moolenbroek             continue;
112b5e2faaaSDavid van Moolenbroek         }
113b5e2faaaSDavid van Moolenbroek         if (F->hasSection() && sectionifyNoOverride) {
114b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping sectionified Function " << F->getName() << "\n");
115b5e2faaaSDavid van Moolenbroek             continue;
116b5e2faaaSDavid van Moolenbroek         }
117b5e2faaaSDavid van Moolenbroek         if (F->getName().startswith("llvm.")) {
118b5e2faaaSDavid van Moolenbroek             DEBUG(errs() << "Skipping LLVM instrinsic Function " << F->getName() << "\n");
119b5e2faaaSDavid van Moolenbroek             continue;
120b5e2faaaSDavid van Moolenbroek         }
121b5e2faaaSDavid van Moolenbroek         if (sectionify(F, functionRegexList, functionRegexMap)) {
122b5e2faaaSDavid van Moolenbroek             numSectionifiedFuncs++;
123b5e2faaaSDavid van Moolenbroek             sectionified = true;
124b5e2faaaSDavid van Moolenbroek         }
125b5e2faaaSDavid van Moolenbroek     }
126b5e2faaaSDavid van Moolenbroek 
127b5e2faaaSDavid van Moolenbroek     return sectionified;
128b5e2faaaSDavid van Moolenbroek }
129b5e2faaaSDavid van Moolenbroek 
sectionifyFromRegex(GlobalObject * value,Regex * regex,std::string & section)130*bdb56518SDavid van Moolenbroek bool SectionifyPass::sectionifyFromRegex(GlobalObject *value, Regex *regex, std::string &section)
131b5e2faaaSDavid van Moolenbroek {
132b5e2faaaSDavid van Moolenbroek     bool returnValue = false;
133b5e2faaaSDavid van Moolenbroek 
134b5e2faaaSDavid van Moolenbroek     if("NULL" != section && regex->match(value->getName(), NULL)) {
135b5e2faaaSDavid van Moolenbroek 	std::string trgSection = section;
136b5e2faaaSDavid van Moolenbroek 	std::string valueStrPrefix = "";
137b5e2faaaSDavid van Moolenbroek 	GlobalVariable *GV = dyn_cast<GlobalVariable>(value);
138b5e2faaaSDavid van Moolenbroek 	if (GV && GV->isConstant()) {
139b5e2faaaSDavid van Moolenbroek             trgSection += "_ro";
140b5e2faaaSDavid van Moolenbroek             valueStrPrefix = "read-only ";
141b5e2faaaSDavid van Moolenbroek 	}
142b5e2faaaSDavid van Moolenbroek 	DEBUG(errs() << "Sectionified " << valueStrPrefix << (isa<Function>(value) ? "Function " : "GlobalVariable ") << value->getName() << " with section " << trgSection << "\n");
143b5e2faaaSDavid van Moolenbroek         value->setSection(trgSection);
144b5e2faaaSDavid van Moolenbroek         if (value->hasCommonLinkage()) {
145*bdb56518SDavid van Moolenbroek             value->setLinkage(GlobalObject::WeakAnyLinkage);
146b5e2faaaSDavid van Moolenbroek         }
147b5e2faaaSDavid van Moolenbroek         returnValue = true;
148b5e2faaaSDavid van Moolenbroek     }
149b5e2faaaSDavid van Moolenbroek     if ("" != prefixOpt)
150b5e2faaaSDavid van Moolenbroek     {
151b5e2faaaSDavid van Moolenbroek 	std::string originalName = value->getName();
152b5e2faaaSDavid van Moolenbroek 	std::string prefixString = "";
153b5e2faaaSDavid van Moolenbroek         if ("" != moduleName)
154b5e2faaaSDavid van Moolenbroek 	{
155b5e2faaaSDavid van Moolenbroek 	   prefixString = moduleName;
156b5e2faaaSDavid van Moolenbroek 	}
157b5e2faaaSDavid van Moolenbroek 	else
158b5e2faaaSDavid van Moolenbroek 	{
159b5e2faaaSDavid van Moolenbroek 	   prefixString = prefixOpt;
160b5e2faaaSDavid van Moolenbroek 	}
161b5e2faaaSDavid van Moolenbroek 	DEBUG(errs() << "Prefixing the " << (isa<Function>(value) ? "Function name " : "GlobalVariable name ") << originalName << " with " << prefixString << "\n");
162b5e2faaaSDavid van Moolenbroek 	std::string prefixedName = prefixString + originalName;
163b5e2faaaSDavid van Moolenbroek 	value->setName(prefixedName);
164b5e2faaaSDavid van Moolenbroek 	returnValue = true;
165b5e2faaaSDavid van Moolenbroek     }
166b5e2faaaSDavid van Moolenbroek 
167b5e2faaaSDavid van Moolenbroek     return returnValue;
168b5e2faaaSDavid van Moolenbroek }
169b5e2faaaSDavid van Moolenbroek 
sectionify(GlobalObject * value,std::vector<Regex * > & regexList,std::map<Regex *,std::string> & regexMap)170*bdb56518SDavid van Moolenbroek bool SectionifyPass::sectionify(GlobalObject *value, std::vector<Regex*> &regexList, std::map<Regex*, std::string> &regexMap)
171b5e2faaaSDavid van Moolenbroek {
172b5e2faaaSDavid van Moolenbroek     std::map<Regex*, std::string>::iterator regexMapIt;
173b5e2faaaSDavid van Moolenbroek     for (std::vector<Regex*>::iterator it = regexList.begin(); it != regexList.end(); ++it) {
174b5e2faaaSDavid van Moolenbroek 	Regex *regex = *it;
175b5e2faaaSDavid van Moolenbroek 	regexMapIt = regexMap.find(regex);
176b5e2faaaSDavid van Moolenbroek 	assert(regexMapIt != regexMap.end());
177b5e2faaaSDavid van Moolenbroek 	std::string section = regexMapIt->second;
178b5e2faaaSDavid van Moolenbroek 	if (sectionifyFromRegex(value, regex, section)) {
179b5e2faaaSDavid van Moolenbroek 		return true;
180b5e2faaaSDavid van Moolenbroek 	}
181b5e2faaaSDavid van Moolenbroek     }
182b5e2faaaSDavid van Moolenbroek 
183b5e2faaaSDavid van Moolenbroek     return false;
184b5e2faaaSDavid van Moolenbroek }
185b5e2faaaSDavid van Moolenbroek 
parseStringMapOpt(std::map<std::string,std::string> & map,std::vector<std::string> & keyList,std::vector<std::string> & stringList)186b5e2faaaSDavid van Moolenbroek bool SectionifyPass::parseStringMapOpt(std::map<std::string, std::string> &map, std::vector<std::string> &keyList, std::vector<std::string> &stringList)
187b5e2faaaSDavid van Moolenbroek {
188b5e2faaaSDavid van Moolenbroek     for (std::vector<std::string>::iterator it = stringList.begin(); it != stringList.end(); ++it) {
189b5e2faaaSDavid van Moolenbroek 	StringRef token = *it;
190b5e2faaaSDavid van Moolenbroek 	SmallVector< StringRef, 2 > tokenVector;
191b5e2faaaSDavid van Moolenbroek         token.split(tokenVector, "/");
192b5e2faaaSDavid van Moolenbroek         if(tokenVector.size() != 2) {
193b5e2faaaSDavid van Moolenbroek 	    return false;
194b5e2faaaSDavid van Moolenbroek         }
195b5e2faaaSDavid van Moolenbroek         StringRef value = tokenVector.pop_back_val();
196b5e2faaaSDavid van Moolenbroek         StringRef key = tokenVector.pop_back_val();
197b5e2faaaSDavid van Moolenbroek         map.insert( std::pair<std::string, std::string>(key, value) );
198b5e2faaaSDavid van Moolenbroek         keyList.push_back(key);
199b5e2faaaSDavid van Moolenbroek     }
200b5e2faaaSDavid van Moolenbroek 
201b5e2faaaSDavid van Moolenbroek     return true;
202b5e2faaaSDavid van Moolenbroek }
203b5e2faaaSDavid van Moolenbroek 
parseAndInitRegexMap(cl::list<std::string> & stringListOpt,std::vector<Regex * > & regexList,std::map<Regex *,std::string> & regexMap,std::string regexType)204b5e2faaaSDavid van Moolenbroek void SectionifyPass::parseAndInitRegexMap(cl::list<std::string> &stringListOpt, std::vector<Regex*> &regexList, std::map<Regex*, std::string> &regexMap, std::string regexType)
205b5e2faaaSDavid van Moolenbroek {
206b5e2faaaSDavid van Moolenbroek     std::map<std::string, std::string> sectionMap;
207b5e2faaaSDavid van Moolenbroek     std::vector<std::string> sectionList;
208b5e2faaaSDavid van Moolenbroek     if (!parseStringMapOpt(sectionMap, sectionList, stringListOpt) || !initRegexMap(regexMap, regexList, sectionMap, sectionList, regexType)) {
209b5e2faaaSDavid van Moolenbroek         stringListOpt.error("Invalid format!");
210b5e2faaaSDavid van Moolenbroek         exit(1);
211b5e2faaaSDavid van Moolenbroek     }
212b5e2faaaSDavid van Moolenbroek }
213b5e2faaaSDavid van Moolenbroek 
initRegexMap(std::map<Regex *,std::string> & regexMap,std::vector<Regex * > & regexList,std::map<std::string,std::string> & stringMap,std::vector<std::string> & stringList,std::string regexType)214b5e2faaaSDavid van Moolenbroek bool SectionifyPass::initRegexMap(std::map<Regex*, std::string> &regexMap, std::vector<Regex*> &regexList, std::map<std::string, std::string> &stringMap, std::vector<std::string> &stringList, std::string regexType)
215b5e2faaaSDavid van Moolenbroek {
216b5e2faaaSDavid van Moolenbroek     std::map<std::string, std::string>::iterator stringMapIt;
217b5e2faaaSDavid van Moolenbroek     for (std::vector<std::string>::iterator it = stringList.begin(); it != stringList.end(); ++it) {
218b5e2faaaSDavid van Moolenbroek 	std::string key = *it;
219b5e2faaaSDavid van Moolenbroek 	stringMapIt = stringMap.find(key);
220b5e2faaaSDavid van Moolenbroek 	assert(stringMapIt != stringMap.end());
221b5e2faaaSDavid van Moolenbroek 	std::string value = stringMapIt->second;
222b5e2faaaSDavid van Moolenbroek 	std::string error;
223b5e2faaaSDavid van Moolenbroek 	Regex *regex = new Regex(key, 0);
224b5e2faaaSDavid van Moolenbroek 	if(!regex->isValid(error)) {
225b5e2faaaSDavid van Moolenbroek 		return false;
226b5e2faaaSDavid van Moolenbroek 	}
227b5e2faaaSDavid van Moolenbroek 	DEBUG(errs() << "Using " << regexType << " regex " << key << " with section " << value << "\n");
228b5e2faaaSDavid van Moolenbroek         regexMap.insert(std::pair<Regex*, std::string>(regex, value));
229b5e2faaaSDavid van Moolenbroek         regexList.push_back(regex);
230b5e2faaaSDavid van Moolenbroek     }
231b5e2faaaSDavid van Moolenbroek 
232b5e2faaaSDavid van Moolenbroek     return true;
233b5e2faaaSDavid van Moolenbroek }
234b5e2faaaSDavid van Moolenbroek 
235b5e2faaaSDavid van Moolenbroek } // end namespace
236b5e2faaaSDavid van Moolenbroek 
237b5e2faaaSDavid van Moolenbroek char SectionifyPass::ID = 1;
238b5e2faaaSDavid van Moolenbroek static RegisterPass<SectionifyPass> AP("sectionify", "Sectionify Pass");
239