lto.cpp revision f2ca21f88f4e38996b6804dfa25fe7a72814736d
12385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch//===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// This file was developed by Devang Patel and is distributed under 6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// the University of Illinois Open Source License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implementes link time optimization library. This library is 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// intended to be used by linker to optimize code at link time. 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 152385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Module.h" 162385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/PassManager.h" 172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Linker.h" 182385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Constants.h" 192385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/DerivedTypes.h" 202385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/SymbolTable.h" 212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Bytecode/Reader.h" 222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Bytecode/Writer.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/Support/CommandLine.h" 242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Support/FileUtilities.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/SystemUtils.h" 262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/Support/Mangler.h" 272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "llvm/System/Program.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/System/Signals.h" 29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "llvm/Analysis/Passes.h" 30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "llvm/Analysis/Verifier.h" 31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "llvm/Target/SubtargetFeature.h" 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "llvm/Target/TargetData.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Target/TargetMachine.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Target/TargetMachineRegistry.h" 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Transforms/IPO.h" 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Transforms/Scalar.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Analysis/LoadValueNumbering.h" 38a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "llvm/LinkTimeOptimizer.h" 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <fstream> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace llvm; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)llvm::LinkTimeOptimizer *createLLVMOptimizer() 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) llvm::LTO *l = new llvm::LTO(); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// If symbol is not used then make it internal and let optimizer takes 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// care of it. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LLVMSymbol::mayBeNotUsed() { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gv->setLinkage(GlobalValue::InternalLinkage); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper routine 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FIXME : Take advantage of GlobalPrefix from AsmPrinter 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char *addUnderscore(const char *name) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t namelen = strlen(name); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *symName = (char*)malloc(namelen+2); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symName[0] = '_'; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(&symName[1], name); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return symName; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map LLVM LinkageType to LTO LinakgeType 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LTOLinkageTypes 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)getLTOLinkageType(GlobalValue *v) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LTOLinkageTypes lt; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (v->hasExternalLinkage()) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lt = LTOExternalLinkage; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (v->hasLinkOnceLinkage()) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lt = LTOLinkOnceLinkage; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (v->hasWeakLinkage()) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lt = LTOWeakLinkage; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise it is internal linkage for link time optimizer 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lt = LTOInternalLinkage; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lt; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Find exeternal symbols referenced by VALUE. This is a recursive function. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)findExternalRefs(Value *value, std::set<std::string> &references, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mangler &mangler) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (GlobalValue *gv = dyn_cast<GlobalValue>(value)) { 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LTOLinkageTypes lt = getLTOLinkageType(gv); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lt != LTOInternalLinkage && strncmp (gv->getName().c_str(), "llvm.", 5)) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) references.insert(mangler.getValueName(gv)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // GlobalValue, even with InternalLinkage type, may have operands with 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExternalLinkage type. Do not ignore these operands. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Constant *c = dyn_cast<Constant>(value)) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle ConstantExpr, ConstantStruct, ConstantArry etc.. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = c->getNumOperands(); i != e; ++i) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) findExternalRefs(c->getOperand(i), references, mangler); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// If Moduel with InputFilename is available then remove it. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 107a3f7b4e666c476898878fa745f637129375cd889Ben MurdochLTO::removeModule (const std::string &InputFilename) 108a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch{ 109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NameToModuleMap::iterator pos = allModules.find(InputFilename.c_str()); 110a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch if (pos != allModules.end()) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Module *m = allModules[InputFilename.c_str()]; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allModules.erase(pos); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete m; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// InputFilename is a LLVM bytecode file. If Module with InputFilename is 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// available then return it. Otherwise parseInputFilename. 119a3f7b4e666c476898878fa745f637129375cd889Ben MurdochModule * 120a3f7b4e666c476898878fa745f637129375cd889Ben MurdochLTO::getModule(const std::string &InputFilename) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Module *m = NULL; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NameToModuleMap::iterator pos = allModules.find(InputFilename.c_str()); 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pos != allModules.end()) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = allModules[InputFilename.c_str()]; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) m = ParseBytecodeFile(InputFilename); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allModules[InputFilename.c_str()] = m; 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return m; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// InputFilename is a LLVM bytecode file. Reade this bytecode file and 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// set corresponding target triplet string. 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LTO::getTargetTriple(const std::string &InputFilename, 138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) std::string &targetTriple) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Module *m = getModule(InputFilename); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (m) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) targetTriple = m->getTargetTriple(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// InputFilename is a LLVM bytecode file. Read it using bytecode reader. 146a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch/// Collect global functions and symbol names in symbols vector. 147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)/// Collect external references in references vector. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Return LTO_READ_SUCCESS if there is no error. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum LTOStatus 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LTO::readLLVMObjectFile(const std::string &InputFilename, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NameToSymbolMap &symbols, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> &references) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Module *m = getModule(InputFilename); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!m) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_READ_FAILURE; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use mangler to add GlobalPrefix to names to match linker names. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME : Instead of hard coding "-" use GlobalPrefix. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mangler mangler(*m, "_"); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modules.push_back(m); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Module::iterator f = m->begin(), e = m->end(); f != e; ++f) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LTOLinkageTypes lt = getLTOLinkageType(f); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!f->isExternal() && lt != LTOInternalLinkage 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && strncmp (f->getName().c_str(), "llvm.", 5)) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LLVMSymbol *newSymbol = new LLVMSymbol(lt, f, f->getName(), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mangler.getValueName(f)); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) symbols[newSymbol->getMangledName()] = newSymbol; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allSymbols[newSymbol->getMangledName()] = newSymbol; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Collect external symbols referenced by this function. 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (Function::iterator b = f->begin(), fe = f->end(); b != fe; ++b) 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (BasicBlock::iterator i = b->begin(), be = b->end(); 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) i != be; ++i) 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (unsigned count = 0, total = i->getNumOperands(); 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) count != total; ++count) 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) findExternalRefs(i->getOperand(count), references, mangler); 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (Module::global_iterator v = m->global_begin(), e = m->global_end(); 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) v != e; ++v) { 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LTOLinkageTypes lt = getLTOLinkageType(v); 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!v->isExternal() && lt != LTOInternalLinkage 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) && strncmp (v->getName().c_str(), "llvm.", 5)) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LLVMSymbol *newSymbol = new LLVMSymbol(lt, v, v->getName(), 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mangler.getValueName(v)); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) symbols[newSymbol->getMangledName()] = newSymbol; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allSymbols[newSymbol->getMangledName()] = newSymbol; 194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned count = 0, total = v->getNumOperands(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count != total; ++count) 197a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch findExternalRefs(v->getOperand(count), references, mangler); 198a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_READ_SUCCESS; 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Optimize module M using various IPO passes. Use exportList to 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// internalize selected symbols. Target platform is selected 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// based on information available to module M. No new target 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// features are selected. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static enum LTOStatus lto_optimize(Module *M, std::ostream &Out, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const char *> &exportList) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Instantiate the pass manager to organize the passes. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PassManager Passes; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Collect Target info 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string Err; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const TargetMachineRegistry::Entry* March = 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) TargetMachineRegistry::getClosestStaticTargetForModule(*M, Err); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (March == 0) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_NO_TARGET; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create target 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string Features; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::auto_ptr<TargetMachine> target(March->CtorFn(*M, Features)); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!target.get()) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LTO_NO_TARGET; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TargetMachine &Target = *target.get(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start off with a verification pass. 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createVerifierPass()); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add an appropriate TargetData instance for this module... 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(new TargetData(*Target.getTargetData())); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Often if the programmer does not specify proper prototypes for the 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // functions they are calling, they end up calling a vararg version of the 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function that does not get a body filled in (the real function has typed 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // arguments). This pass merges the two functions. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createFunctionResolvingPass()); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Internalize symbols if export list is nonemty 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!exportList.empty()) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createInternalizePass(exportList)); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now that we internalized some globals, see if we can hack on them! 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createGlobalOptimizerPass()); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Linking modules together can lead to duplicated global constants, only 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keep one copy of each constant... 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Passes.add(createConstantMergePass()); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the -s command line option was specified, strip the symbols out of the 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // resulting program to make it smaller. -s is a GLD option that we are 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // supporting. 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createStripSymbolsPass()); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Propagate constants at call sites into the functions they call. 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createIPConstantPropagationPass()); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove unused arguments from functions... 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createDeadArgEliminationPass()); 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createFunctionInliningPass()); // Inline small functions 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Passes.add(createPruneEHPass()); // Remove dead EH info 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createGlobalDCEPass()); // Remove dead functions 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't decide to inline a function, check to see if we can 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transform it to pass arguments by value instead of by reference. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createArgumentPromotionPass()); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The IPO passes may leave cruft around. Clean up after them. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createInstructionCombiningPass()); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createScalarReplAggregatesPass()); // Break up allocas 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run a few AA driven optimizations here and now, to cleanup the code. 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Passes.add(createGlobalsModRefPass()); // IP alias analysis 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createLICMPass()); // Hoist loop invariants 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createLoadValueNumberingPass()); // GVN for load instrs 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createGCSEPass()); // Remove common subexprs 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createDeadStoreEliminationPass()); // Nuke dead stores 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Cleanup and simplify the code after the scalar optimizations. 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createInstructionCombiningPass()); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Delete basic blocks, which optimization passes may have killed... 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createCFGSimplificationPass()); 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now that we have optimized the program, discard unreachable functions... 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Passes.add(createGlobalDCEPass()); 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure everything is still good. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.add(createVerifierPass()); 299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 300a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch FunctionPassManager *CodeGenPasses = 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new FunctionPassManager(new ExistingModuleProvider(M)); 302a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 303a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch CodeGenPasses->add(new TargetData(*Target.getTargetData())); 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Target.addPassesToEmitFile(*CodeGenPasses, Out, TargetMachine::AssemblyFile, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Run our queue of passes all at once now, efficiently. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Passes.run(*M); 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run the code generator, if present. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CodeGenPasses->doInitialization(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!I->isExternal()) 314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CodeGenPasses->run(*I); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CodeGenPasses->doFinalization(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_OPT_SUCCESS; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///Link all modules together and optimize them using IPO. Generate 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// native object file using OutputFilename 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/// Return appropriate LTOStatus. 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum LTOStatus 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LTO::optimizeModules(const std::string &OutputFilename, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const char *> &exportList, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string &targetTriple) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (modules.empty()) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_NO_WORK; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::ios::openmode io_mode = 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::ios::out | std::ios::trunc | std::ios::binary; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string *errMsg = NULL; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Module *bigOne = modules[0]; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Linker theLinker("LinkTimeOptimizer", bigOne, false); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 1, e = modules.size(); i != e; ++i) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (theLinker.LinkModules(bigOne, modules[i], errMsg)) 339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return LTO_MODULE_MERGE_FAILURE; 340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#if 0 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enable this when -save-temps is used 343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::ofstream Out("big.bc", io_mode); 344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) WriteBytecodeToFile(bigOne, Out, true); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Strip leading underscore because it was added to match names 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // seen by linker. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = exportList.size(); i != e; ++i) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *name = exportList[i]; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NameToSymbolMap::iterator itr = allSymbols.find(name); 352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (itr != allSymbols.end()) 3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) exportList[i] = allSymbols[name]->getName(); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::string ErrMsg; 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys::Path TempDir = sys::Path::GetTemporaryDirectory(&ErrMsg); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (TempDir.isEmpty()) { 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::cerr << "lto: " << ErrMsg << "\n"; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LTO_WRITE_FAILURE; 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys::Path tmpAsmFilePath(TempDir); 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!tmpAsmFilePath.appendComponent("lto")) { 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::cerr << "lto: " << ErrMsg << "\n"; 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TempDir.eraseFromDisk(true); 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LTO_WRITE_FAILURE; 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tmpAsmFilePath.createTemporaryFileOnDisk(&ErrMsg)) { 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::cerr << "lto: " << ErrMsg << "\n"; 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TempDir.eraseFromDisk(true); 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return LTO_WRITE_FAILURE; 373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sys::RemoveFileOnSignal(tmpAsmFilePath); 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::ofstream asmFile(tmpAsmFilePath.c_str(), io_mode); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!asmFile.is_open() || asmFile.bad()) { 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tmpAsmFilePath.exists()) { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tmpAsmFilePath.eraseFromDisk(); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempDir.eraseFromDisk(true); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_WRITE_FAILURE; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum LTOStatus status = lto_optimize(bigOne, asmFile, exportList); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) asmFile.close(); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != LTO_OPT_SUCCESS) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmpAsmFilePath.eraseFromDisk(); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempDir.eraseFromDisk(true); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) targetTriple = bigOne->getTargetTriple(); 394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run GCC to assemble and link the program into native code. 396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Note: 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't just assemble and link the file with the system assembler 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and linker because we don't know where to put the _start symbol. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GCC mysteriously knows how to do it. 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const sys::Path gcc = sys::Program::FindProgramByName("gcc"); 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (gcc.isEmpty()) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmpAsmFilePath.eraseFromDisk(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempDir.eraseFromDisk(true); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_ASM_FAILURE; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const char*> args; 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.push_back(gcc.c_str()); 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.push_back("-c"); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.push_back("-x"); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("assembler"); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("-o"); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.push_back(OutputFilename.c_str()); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back(tmpAsmFilePath.c_str()); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args.push_back(0); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys::Program::ExecuteAndWait(gcc, &args[0], 0, 0, 1, &ErrMsg)) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cerr << "lto: " << ErrMsg << "\n"; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_ASM_FAILURE; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmpAsmFilePath.eraseFromDisk(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TempDir.eraseFromDisk(true); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LTO_OPT_SUCCESS; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)