//
//===----------------------------------------------------------------------===//
+#include "LTOModule.h"
+#include "LTOCodeGenerator.h"
+
+
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Linker.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/LoadValueNumbering.h"
#include "llvm/CodeGen/FileWriters.h"
-#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
-#include "llvm/Analysis/LoadValueNumbering.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Config/config.h"
-#include "LTOModule.h"
-#include "LTOCodeGenerator.h"
#include <fstream>
#include <unistd.h>
LTOCodeGenerator::LTOCodeGenerator()
: _linker("LinkTimeOptimizer", "ld-temp.o"), _target(NULL),
_emitDwarfDebugInfo(false), _scopeRestrictionsDone(false),
- _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC)
+ _codeModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC),
+ _nativeObjectFile(NULL)
{
}
LTOCodeGenerator::~LTOCodeGenerator()
{
- // FIXME
+ delete _target;
+ delete _nativeObjectFile;
}
}
-void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
+const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg)
{
- // make unqiue temp .s file to put generated assembly code
+ // make unique temp .s file to put generated assembly code
sys::Path uniqueAsmPath("lto-llvm.s");
if ( uniqueAsmPath.createTemporaryFileOnDisk(true, &errMsg) )
return NULL;
return NULL;
}
- // make unqiue temp .o file to put generated object file
+ // make unique temp .o file to put generated object file
sys::PathWithStatus uniqueObjPath("lto-llvm.o");
if ( uniqueObjPath.createTemporaryFileOnDisk(true, &errMsg) ) {
if ( uniqueAsmPath.exists() )
sys::RemoveFileOnSignal(uniqueObjPath);
// assemble the assembly code
- void* buffer = NULL;
+ const std::string& uniqueObjStr = uniqueObjPath.toString();
bool asmResult = this->assemble(uniqueAsmPath.toString(),
- uniqueObjPath.toString(), errMsg);
+ uniqueObjStr, errMsg);
if ( !asmResult ) {
+ // remove old buffer if compile() called twice
+ delete _nativeObjectFile;
+
// read .o file into memory buffer
- const sys::FileStatus* objStatus;
- objStatus = uniqueObjPath.getFileStatus(false, &errMsg);
- if ( objStatus != NULL ) {
- *length = objStatus->getSize();
- // use malloc() because caller will own this buffer and free() it
- buffer = ::malloc(*length);
- if ( buffer != NULL ) {
- int fd = ::open(uniqueObjPath.c_str(), O_RDONLY, 0);
- if ( fd != -1 ) {
- // read object file contents into buffer
- if ( ::read(fd, buffer, *length) != (ssize_t)*length ) {
- errMsg = "error reading object file";
- free(buffer);
- buffer = NULL;
- }
- close(fd);
- }
- else {
- errMsg = "error opening object file";
- free(buffer);
- buffer = NULL;
- }
- }
- else {
- errMsg = "error mallocing space for object file";
- }
- }
- else {
- errMsg = "error stat'ing object file";
- }
+ _nativeObjectFile = MemoryBuffer::getFile(uniqueObjStr.c_str(),&errMsg);
}
- // clean up temp files
+
+ // remove temp files
uniqueAsmPath.eraseFromDisk();
uniqueObjPath.eraseFromDisk();
- return buffer;
+
+ // return buffer, unless error
+ if ( _nativeObjectFile == NULL )
+ return NULL;
+ *length = _nativeObjectFile->getBufferSize();
+ return _nativeObjectFile->getBufferStart();
}
// Add an appropriate TargetData instance for this module...
passes.add(new TargetData(*_target->getTargetData()));
+ // Propagate constants at call sites into the functions they call. This
+ // opens opportunities for globalopt (and inlining) by substituting function
+ // pointers passed as arguments to direct uses of functions.
+ passes.add(createIPSCCPPass());
+
// Now that we internalized some globals, see if we can hack on them!
passes.add(createGlobalOptimizerPass());
// If the -s command line option was specified, strip the symbols out of the
// resulting program to make it smaller. -s is a GLD option that we are
// supporting.
- if( !llvm::ExceptionHandling ) {
- // FIXME : This causes multiple nameless _.eh symbols on
- // darwin when EH is ON.
- passes.add(createStripSymbolsPass());
- }
+ passes.add(createStripSymbolsPass());
- // Propagate constants at call sites into the functions they call.
- passes.add(createIPConstantPropagationPass());
-
// Remove unused arguments from functions...
passes.add(createDeadArgEliminationPass());
+ // Reduce the code after globalopt and ipsccp. Both can open up significant
+ // simplification opportunities, and both can propagate functions through
+ // function pointers. When this happens, we often have to resolve varargs
+ // calls, etc, so let instcombine do this.
+ passes.add(createInstructionCombiningPass());
+
passes.add(createFunctionInliningPass()); // Inline small functions
passes.add(createPruneEHPass()); // Remove dead EH info
// The IPO passes may leave cruft around. Clean up after them.
passes.add(createInstructionCombiningPass());
-
+ passes.add(createJumpThreadingPass()); // Thread jumps.
passes.add(createScalarReplAggregatesPass()); // Break up allocas
// Run a few AA driven optimizations here and now, to cleanup the code.
passes.add(createGlobalsModRefPass()); // IP alias analysis
passes.add(createLICMPass()); // Hoist loop invariants
- passes.add(createLoadValueNumberingPass()); // GVN for load instrs
- passes.add(createGCSEPass()); // Remove common subexprs
+ passes.add(createGVNPass()); // Remove common subexprs
+ passes.add(createMemCpyOptPass()); // Remove dead memcpy's
passes.add(createDeadStoreEliminationPass()); // Nuke dead stores
// Cleanup and simplify the code after the scalar optimizations.
passes.add(createInstructionCombiningPass());
+ passes.add(createJumpThreadingPass()); // Thread jumps.
+
// Delete basic blocks, which optimization passes may have killed...
passes.add(createCFGSimplificationPass());