Introduce MCCodeGenInfo, which keeps information that can affect codegen
[oota-llvm.git] / tools / lto / LTOCodeGenerator.cpp
index 8db573e61fbfea94051a9b5a34034c21fd020f81..28cfa9cc750e1e42923db79a1d89f4d139d66941 100644 (file)
 
 #include "LTOModule.h"
 #include "LTOCodeGenerator.h"
-
-
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Linker.h"
+#include "llvm/LLVMContext.h"
 #include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
 #include "llvm/PassManager.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/Passes.h"
-#include "llvm/Analysis/LoopPass.h"
-#include "llvm/Analysis/Verifier.h"
 #include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/FileWriters.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/StandardPasses.h"
-#include "llvm/Support/SystemUtils.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Target/SubtargetFeature.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Target/Mangler.h"
 #include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetMachineRegistry.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetRegistry.h"
 #include "llvm/Target/TargetSelect.h"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PassManagerBuilder.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
 #include "llvm/Config/config.h"
-
-
 #include <cstdlib>
-#include <fstream>
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -70,14 +67,18 @@ const char* LTOCodeGenerator::getVersionString()
 
 
 LTOCodeGenerator::LTOCodeGenerator() 
-    : _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL),
+    : _context(getGlobalContext()),
+      _linker("LinkTimeOptimizer", "ld-temp.o", _context), _target(NULL),
       _emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
       _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
-      _nativeObjectFile(NULL), _gccPath(NULL), _assemblerPath(NULL)
+      _nativeObjectFile(NULL)
 {
-  InitializeAllTargets();
-  InitializeAllAsmPrinters();
-
+    InitializeAllTargets();
+    InitializeAllMCAsmInfos();
+    InitializeAllMCCodeGenInfos();
+    InitializeAllMCRegisterInfos();
+    InitializeAllMCSubtargetInfos();
+    InitializeAllAsmPrinters();
 }
 
 LTOCodeGenerator::~LTOCodeGenerator()
@@ -90,7 +91,17 @@ LTOCodeGenerator::~LTOCodeGenerator()
 
 bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg)
 {
-    return _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
+
+  if(mod->getLLVVMModule()->MaterializeAllPermanently(&errMsg))
+    return true;
+
+  bool ret = _linker.LinkInModule(mod->getLLVVMModule(), &errMsg);
+
+  const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
+  for (int i = 0, e = undefs.size(); i != e; ++i)
+    _asmUndefinedRefs[undefs[i]] = 1;
+
+  return ret;
 }
     
 
@@ -111,7 +122,7 @@ bool LTOCodeGenerator::setDebugInfo(lto_debug_model debug, std::string& errMsg)
 
 
 bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, 
-                                                        std::string& errMsg)
+                                       std::string& errMsg)
 {
     switch (model) {
         case LTO_CODEGEN_PIC_MODEL_STATIC:
@@ -124,18 +135,9 @@ bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model,
     return true;
 }
 
-void LTOCodeGenerator::setGccPath(const char* path)
+void LTOCodeGenerator::setCpu(const char* mCpu)
 {
-    if ( _gccPath )
-        delete _gccPath;
-    _gccPath = new sys::Path(path);
-}
-
-void LTOCodeGenerator::setAssemblerPath(const char* path)
-{
-    if ( _assemblerPath )
-        delete _assemblerPath;
-    _assemblerPath = new sys::Path(path);
+  _mCpu = mCpu;
 }
 
 void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
@@ -144,254 +146,225 @@ void LTOCodeGenerator::addMustPreserveSymbol(const char* sym)
 }
 
 
-bool LTOCodeGenerator::writeMergedModules(const char* path, std::string& errMsg)
-{
-    if ( this->determineTarget(errMsg) ) 
-        return true;
+bool LTOCodeGenerator::writeMergedModules(const char *path,
+                                          std::string &errMsg) {
+  if (determineTarget(errMsg))
+    return true;
 
-    // mark which symbols can not be internalized 
-    this->applyScopeRestrictions();
+  // mark which symbols can not be internalized 
+  applyScopeRestrictions();
 
-    // create output file
-    std::ofstream out(path, std::ios_base::out|std::ios::trunc|std::ios::binary);
-    if ( out.fail() ) {
-        errMsg = "could not open bitcode file for writing: ";
-        errMsg += path;
-        return true;
-    }
-    
-    // write bitcode to it
-    WriteBitcodeToFile(_linker.getModule(), out);
-    if ( out.fail() ) {
-        errMsg = "could not write bitcode file: ";
-        errMsg += path;
-        return true;
-    }
+  // create output file
+  std::string ErrInfo;
+  tool_output_file Out(path, ErrInfo,
+                       raw_fd_ostream::F_Binary);
+  if (!ErrInfo.empty()) {
+    errMsg = "could not open bitcode file for writing: ";
+    errMsg += path;
+    return true;
+  }
     
-    return false;
+  // write bitcode to it
+  WriteBitcodeToFile(_linker.getModule(), Out.os());
+  Out.os().close();
+
+  if (Out.os().has_error()) {
+    errMsg = "could not write bitcode file: ";
+    errMsg += path;
+    Out.os().clear_error();
+    return true;
+  }
+  
+  Out.keep();
+  return false;
 }
 
 
-const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
+bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg)
 {
-    // make unique temp .s file to put generated assembly code
-    sys::Path uniqueAsmPath("lto-llvm.s");
-    if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) )
-        return NULL;
-    sys::RemoveFileOnSignal(uniqueAsmPath);
-       
-    // generate assembly code
-    bool genResult = false;
-    {
-      raw_fd_ostream asmFile(uniqueAsmPath.c_str(), false, errMsg);
-      if (!errMsg.empty())
-        return NULL;
-      genResult = this->generateAssemblyCode(asmFile, errMsg);
-    }
-    if ( genResult ) {
-        if ( uniqueAsmPath.exists() )
-            uniqueAsmPath.eraseFromDisk();
-        return NULL;
-    }
-    
-    // make unique temp .o file to put generated object file
-    sys::PathWithStatus uniqueObjPath("lto-llvm.o");
-    if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) {
-        if ( uniqueAsmPath.exists() )
-            uniqueAsmPath.eraseFromDisk();
-        return NULL;
-    }
-    sys::RemoveFileOnSignal(uniqueObjPath);
-
-    // assemble the assembly code
-    const std::string& uniqueObjStr = uniqueObjPath.toString();
-    bool asmResult = this->assemble(uniqueAsmPath.toString(), 
-                                                        uniqueObjStr, errMsg);
-    if ( !asmResult ) {
-        // remove old buffer if compile() called twice
-        delete _nativeObjectFile;
-        
-        // read .o file into memory buffer
-        _nativeObjectFile = MemoryBuffer::getFile(uniqueObjStr.c_str(),&errMsg);
-    }
-
-    // remove temp files
-    uniqueAsmPath.eraseFromDisk();
+  // make unique temp .o file to put generated object file
+  sys::PathWithStatus uniqueObjPath("lto-llvm.o");
+  if ( uniqueObjPath.createTemporaryFileOnDisk(false, &errMsg) ) {
     uniqueObjPath.eraseFromDisk();
+    return true;
+  }
+  sys::RemoveFileOnSignal(uniqueObjPath);
+
+  // generate object file
+  bool genResult = false;
+  tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
+  if (!errMsg.empty())
+    return NULL;
+  genResult = this->generateObjectFile(objFile.os(), errMsg);
+  objFile.os().close();
+  if (objFile.os().has_error()) {
+    objFile.os().clear_error();
+    return true;
+  }
+  objFile.keep();
+  if ( genResult ) {
+    uniqueObjPath.eraseFromDisk();
+    return true;
+  }
 
-    // return buffer, unless error
-    if ( _nativeObjectFile == NULL )
-        return NULL;
-    *length = _nativeObjectFile->getBufferSize();
-    return _nativeObjectFile->getBufferStart();
+  _nativeObjectPath = uniqueObjPath.str();
+  *name = _nativeObjectPath.c_str();
+  return false;
 }
 
-
-bool LTOCodeGenerator::assemble(const std::string& asmPath, 
-                                const std::string& objPath, std::string& errMsg)
+const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
 {
-    sys::Path tool;
-    bool needsCompilerOptions = true;
-    if ( _assemblerPath ) {
-        tool = *_assemblerPath;
-        needsCompilerOptions = false;
-    }
-    else if ( _gccPath ) {
-        tool = *_gccPath;
-    } else {
-        // find compiler driver
-        tool = sys::Program::FindProgramByName("gcc");
-        if ( tool.isEmpty() ) {
-            errMsg = "can't locate gcc";
-            return true;
-        }
-    }
-
-    // build argument list
-    std::vector<const char*> args;
-    std::string targetTriple = _linker.getModule()->getTargetTriple();
-    args.push_back(tool.c_str());
-    if ( targetTriple.find("darwin") != std::string::npos ) {
-        // darwin specific command line options
-        if (strncmp(targetTriple.c_str(), "i386-apple-", 11) == 0) {
-            args.push_back("-arch");
-            args.push_back("i386");
-        }
-        else if (strncmp(targetTriple.c_str(), "x86_64-apple-", 13) == 0) {
-            args.push_back("-arch");
-            args.push_back("x86_64");
-        }
-        else if (strncmp(targetTriple.c_str(), "powerpc-apple-", 14) == 0) {
-            args.push_back("-arch");
-            args.push_back("ppc");
-        }
-        else if (strncmp(targetTriple.c_str(), "powerpc64-apple-", 16) == 0) {
-            args.push_back("-arch");
-            args.push_back("ppc64");
-        }
-        else if (strncmp(targetTriple.c_str(), "arm-apple-", 10) == 0) {
-            args.push_back("-arch");
-            args.push_back("arm");
-        }
-        else if ((strncmp(targetTriple.c_str(), "armv4t-apple-", 13) == 0) ||
-                 (strncmp(targetTriple.c_str(), "thumbv4t-apple-", 15) == 0)) {
-            args.push_back("-arch");
-            args.push_back("armv4t");
-        }
-        else if ((strncmp(targetTriple.c_str(), "armv5-apple-", 12) == 0) ||
-                 (strncmp(targetTriple.c_str(), "armv5e-apple-", 13) == 0) ||
-                 (strncmp(targetTriple.c_str(), "thumbv5-apple-", 14) == 0) ||
-                 (strncmp(targetTriple.c_str(), "thumbv5e-apple-", 15) == 0)) {
-            args.push_back("-arch");
-            args.push_back("armv5");
-        }
-        else if ((strncmp(targetTriple.c_str(), "armv6-apple-", 12) == 0) ||
-                 (strncmp(targetTriple.c_str(), "thumbv6-apple-", 14) == 0)) {
-            args.push_back("-arch");
-            args.push_back("armv6");
-        }
-        else if ((strncmp(targetTriple.c_str(), "armv7-apple-", 12) == 0) ||
-                 (strncmp(targetTriple.c_str(), "thumbv7-apple-", 14) == 0)) {
-            args.push_back("-arch");
-            args.push_back("armv7");
-        }
-        // add -static to assembler command line when code model requires
-        if ( (_assemblerPath != NULL) && (_codeModel == LTO_CODEGEN_PIC_MODEL_STATIC) )
-            args.push_back("-static");
-    }
-    if ( needsCompilerOptions ) {
-        args.push_back("-c");
-        args.push_back("-x");
-        args.push_back("assembler");
-    }
-    args.push_back("-o");
-    args.push_back(objPath.c_str());
-    args.push_back(asmPath.c_str());
-    args.push_back(0);
-
-    // invoke assembler
-    if ( sys::Program::ExecuteAndWait(tool, &args[0], 0, 0, 0, 0, &errMsg) ) {
-        errMsg = "error in assembly";    
-        return true;
-    }
-    return false; // success
+  const char *name;
+  if (compile_to_file(&name, errMsg))
+    return NULL;
+
+  // remove old buffer if compile() called twice
+  delete _nativeObjectFile;
+
+  // read .o file into memory buffer
+  OwningPtr<MemoryBuffer> BuffPtr;
+  if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
+    errMsg = ec.message();
+    return NULL;
+  }
+  _nativeObjectFile = BuffPtr.take();
+
+  // remove temp files
+  sys::Path(_nativeObjectPath).eraseFromDisk();
+
+  // return buffer, unless error
+  if ( _nativeObjectFile == NULL )
+    return NULL;
+  *length = _nativeObjectFile->getBufferSize();
+  return _nativeObjectFile->getBufferStart();
 }
 
-
-
 bool LTOCodeGenerator::determineTarget(std::string& errMsg)
 {
     if ( _target == NULL ) {
+        std::string Triple = _linker.getModule()->getTargetTriple();
+        if (Triple.empty())
+          Triple = sys::getHostTriple();
+
         // create target machine from info for merged modules
-        Module* mergedModule = _linker.getModule();
-        const TargetMachineRegistry::entry* march = 
-          TargetMachineRegistry::getClosestStaticTargetForModule(
-                                                       *mergedModule, errMsg);
+        const Target *march = TargetRegistry::lookupTarget(Triple, errMsg);
         if ( march == NULL )
             return true;
 
         // The relocation model is actually a static member of TargetMachine
         // and needs to be set before the TargetMachine is instantiated.
+        Reloc::Model RelocModel = Reloc::Default;
         switch( _codeModel ) {
         case LTO_CODEGEN_PIC_MODEL_STATIC:
-            TargetMachine::setRelocationModel(Reloc::Static);
+            RelocModel = Reloc::Static;
             break;
         case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
-            TargetMachine::setRelocationModel(Reloc::PIC_);
+            RelocModel = Reloc::PIC_;
             break;
         case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
-            TargetMachine::setRelocationModel(Reloc::DynamicNoPIC);
+            RelocModel = Reloc::DynamicNoPIC;
             break;
         }
 
         // construct LTModule, hand over ownership of module and target
-        std::string FeatureStr =
-          getFeatureString(_linker.getModule()->getTargetTriple().c_str());
-        _target = march->CtorFn(*mergedModule, FeatureStr.c_str());
+        SubtargetFeatures Features;
+        Features.getDefaultSubtargetFeatures(llvm::Triple(Triple));
+        std::string FeatureStr = Features.getString();
+        _target = march->createTargetMachine(Triple, _mCpu, FeatureStr,
+                                             RelocModel);
     }
     return false;
 }
 
-void LTOCodeGenerator::applyScopeRestrictions()
-{
-    if ( !_scopeRestrictionsDone ) {
-        Module* mergedModule = _linker.getModule();
-
-        // Start off with a verification pass.
-        PassManager passes;
-        passes.add(createVerifierPass());
-
-        // mark which symbols can not be internalized 
-        if ( !_mustPreserveSymbols.empty() ) {
-            Mangler mangler(*mergedModule, 
-                                _target->getTargetAsmInfo()->getGlobalPrefix());
-            std::vector<const char*> mustPreserveList;
-            for (Module::iterator f = mergedModule->begin(), 
-                                        e = mergedModule->end(); f != e; ++f) {
-                if ( !f->isDeclaration() 
-                  && _mustPreserveSymbols.count(mangler.getValueName(f)) )
-                    mustPreserveList.push_back(::strdup(f->getName().c_str()));
-            }
-            for (Module::global_iterator v = mergedModule->global_begin(), 
-                                 e = mergedModule->global_end(); v !=  e; ++v) {
-                if ( !v->isDeclaration()
-                  && _mustPreserveSymbols.count(mangler.getValueName(v)) )
-                    mustPreserveList.push_back(::strdup(v->getName().c_str()));
-            }
-            passes.add(createInternalizePass(mustPreserveList));
-        }
-        // apply scope restrictions
-        passes.run(*mergedModule);
-        
-        _scopeRestrictionsDone = true;
-    }
+void LTOCodeGenerator::applyRestriction(GlobalValue &GV,
+                                     std::vector<const char*> &mustPreserveList,
+                                        SmallPtrSet<GlobalValue*, 8> &asmUsed,
+                                        Mangler &mangler) {
+  SmallString<64> Buffer;
+  mangler.getNameWithPrefix(Buffer, &GV, false);
+
+  if (GV.isDeclaration())
+    return;
+  if (_mustPreserveSymbols.count(Buffer))
+    mustPreserveList.push_back(GV.getName().data());
+  if (_asmUndefinedRefs.count(Buffer))
+    asmUsed.insert(&GV);
+}
+
+static void findUsedValues(GlobalVariable *LLVMUsed,
+                           SmallPtrSet<GlobalValue*, 8> &UsedValues) {
+  if (LLVMUsed == 0) return;
+
+  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
+  if (Inits == 0) return;
+
+  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
+    if (GlobalValue *GV = 
+          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
+      UsedValues.insert(GV);
+}
+
+void LTOCodeGenerator::applyScopeRestrictions() {
+  if (_scopeRestrictionsDone) return;
+  Module *mergedModule = _linker.getModule();
+
+  // Start off with a verification pass.
+  PassManager passes;
+  passes.add(createVerifierPass());
+
+  // mark which symbols can not be internalized 
+  MCContext Context(*_target->getMCAsmInfo(), *_target->getRegisterInfo(),
+                    NULL);
+  Mangler mangler(Context, *_target->getTargetData());
+  std::vector<const char*> mustPreserveList;
+  SmallPtrSet<GlobalValue*, 8> asmUsed;
+
+  for (Module::iterator f = mergedModule->begin(),
+         e = mergedModule->end(); f != e; ++f)
+    applyRestriction(*f, mustPreserveList, asmUsed, mangler);
+  for (Module::global_iterator v = mergedModule->global_begin(), 
+         e = mergedModule->global_end(); v !=  e; ++v)
+    applyRestriction(*v, mustPreserveList, asmUsed, mangler);
+  for (Module::alias_iterator a = mergedModule->alias_begin(),
+         e = mergedModule->alias_end(); a != e; ++a)
+    applyRestriction(*a, mustPreserveList, asmUsed, mangler);
+
+  GlobalVariable *LLVMCompilerUsed =
+    mergedModule->getGlobalVariable("llvm.compiler.used");
+  findUsedValues(LLVMCompilerUsed, asmUsed);
+  if (LLVMCompilerUsed)
+    LLVMCompilerUsed->eraseFromParent();
+
+  llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(_context);
+  std::vector<Constant*> asmUsed2;
+  for (SmallPtrSet<GlobalValue*, 16>::const_iterator i = asmUsed.begin(),
+         e = asmUsed.end(); i !=e; ++i) {
+    GlobalValue *GV = *i;
+    Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
+    asmUsed2.push_back(c);
+  }
+
+  llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
+  LLVMCompilerUsed =
+    new llvm::GlobalVariable(*mergedModule, ATy, false,
+                             llvm::GlobalValue::AppendingLinkage,
+                             llvm::ConstantArray::get(ATy, asmUsed2),
+                             "llvm.compiler.used");
+
+  LLVMCompilerUsed->setSection("llvm.metadata");
+
+  passes.add(createInternalizePass(mustPreserveList));
+
+  // apply scope restrictions
+  passes.run(*mergedModule);
+  
+  _scopeRestrictionsDone = true;
 }
 
 /// Optimize merged modules using various IPO passes
-bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
-                                            std::string& errMsg)
-{
-    if (  this->determineTarget(errMsg) ) 
+bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
+                                          std::string &errMsg) {
+    if ( this->determineTarget(errMsg) ) 
         return true;
 
     // mark which symbols can not be internalized 
@@ -399,14 +372,10 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
 
     Module* mergedModule = _linker.getModule();
 
-     // If target supports exception handling then enable it now.
-    if ( _target->getTargetAsmInfo()->doesSupportExceptionHandling() )
-        llvm::ExceptionHandling = true;
-
     // if options were requested, set them
     if ( !_codegenOptions.empty() )
         cl::ParseCommandLineOptions(_codegenOptions.size(), 
-                                                (char**)&_codegenOptions[0]);
+                                    const_cast<char **>(&_codegenOptions[0]));
 
     // Instantiate the pass manager to organize the passes.
     PassManager passes;
@@ -417,40 +386,23 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
     // Add an appropriate TargetData instance for this module...
     passes.add(new TargetData(*_target->getTargetData()));
     
-    createStandardLTOPasses(&passes, /*Internalize=*/ false, !DisableInline,
-                            /*VerifyEach=*/ false);
+    PassManagerBuilder().populateLTOPassManager(passes, /*Internalize=*/ false,
+                                                !DisableInline);
 
     // Make sure everything is still good.
     passes.add(createVerifierPass());
 
-    FunctionPassManager* codeGenPasses =
-            new FunctionPassManager(new ExistingModuleProvider(mergedModule));
+    FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule);
 
     codeGenPasses->add(new TargetData(*_target->getTargetData()));
 
-    MachineCodeEmitter* mce = NULL;
+    formatted_raw_ostream Out(out);
 
-    switch (_target->addPassesToEmitFile(*codeGenPasses, out,
-                                         TargetMachine::AssemblyFile,
-                                         CodeGenOpt::Aggressive)) {
-        case FileModel::MachOFile:
-            mce = AddMachOWriter(*codeGenPasses, out, *_target);
-            break;
-        case FileModel::ElfFile:
-            mce = AddELFWriter(*codeGenPasses, out, *_target);
-            break;
-        case FileModel::AsmFile:
-            break;
-        case FileModel::Error:
-        case FileModel::None:
-            errMsg = "target file type not supported";
-            return true;
-    }
-
-    if (_target->addPassesToEmitFileFinish(*codeGenPasses, mce,
-                                           CodeGenOpt::Aggressive)) {
-        errMsg = "target does not support generation of this file type";
-        return true;
+    if (_target->addPassesToEmitFile(*codeGenPasses, Out,
+                                     TargetMachine::CGFT_ObjectFile,
+                                     CodeGenOpt::Aggressive)) {
+      errMsg = "target file type not supported";
+      return true;
     }
 
     // Run our queue of passes all at once now, efficiently.
@@ -465,6 +417,8 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
         codeGenPasses->run(*it);
 
     codeGenPasses->doFinalization();
+    delete codeGenPasses;
+
     return false; // success
 }
 
@@ -472,12 +426,12 @@ bool LTOCodeGenerator::generateAssemblyCode(raw_ostream& out,
 /// Optimize merged modules using various IPO passes
 void LTOCodeGenerator::setCodeGenDebugOptions(const char* options)
 {
-    std::string ops(options);
-    for (std::string o = getToken(ops); !o.empty(); o = getToken(ops)) {
+    for (std::pair<StringRef, StringRef> o = getToken(options);
+         !o.first.empty(); o = getToken(o.second)) {
         // ParseCommandLineOptions() expects argv[0] to be program name.
         // Lazily add that.
         if ( _codegenOptions.empty() ) 
             _codegenOptions.push_back("libLTO");
-        _codegenOptions.push_back(strdup(o.c_str()));
+        _codegenOptions.push_back(strdup(o.first.str().c_str()));
     }
 }