aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/gold/Makefile4
-rw-r--r--tools/lli/CMakeLists.txt2
-rw-r--r--tools/lli/RecordingMemoryManager.cpp87
-rw-r--r--tools/lli/RecordingMemoryManager.h78
-rw-r--r--tools/lli/RemoteTarget.cpp61
-rw-r--r--tools/lli/RemoteTarget.h101
-rw-r--r--tools/lli/lli.cpp200
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp30
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp47
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp17
-rw-r--r--tools/lto/LTOCodeGenerator.cpp6
-rw-r--r--tools/lto/LTOModule.cpp4
-rw-r--r--tools/opt/opt.cpp4
13 files changed, 579 insertions, 62 deletions
diff --git a/tools/gold/Makefile b/tools/gold/Makefile
index 02f66d7..496e31c 100644
--- a/tools/gold/Makefile
+++ b/tools/gold/Makefile
@@ -24,6 +24,8 @@ include $(LEVEL)/Makefile.config
# Because off_t is used in the public API, the largefile parts are required for
# ABI compatibility.
CXXFLAGS += -I$(BINUTILS_INCDIR) -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-CXXFLAGS += -L$(SharedLibDir)/$(SharedPrefix) -lLTO
+LDFLAGS += -L$(SharedLibDir)/$(SharedPrefix)
include $(LEVEL)/Makefile.common
+
+LIBS += -lLTO
diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt
index a5d2e61..68cb921 100644
--- a/tools/lli/CMakeLists.txt
+++ b/tools/lli/CMakeLists.txt
@@ -19,4 +19,6 @@ endif( LLVM_USE_INTEL_JITEVENTS )
add_llvm_tool(lli
lli.cpp
+ RecordingMemoryManager.cpp
+ RemoteTarget.cpp
)
diff --git a/tools/lli/RecordingMemoryManager.cpp b/tools/lli/RecordingMemoryManager.cpp
new file mode 100644
index 0000000..9e1cff5
--- /dev/null
+++ b/tools/lli/RecordingMemoryManager.cpp
@@ -0,0 +1,87 @@
+//===- RecordingMemoryManager.cpp - Recording memory manager --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This memory manager allocates local storage and keeps a record of each
+// allocation. Iterators are provided for all data and code allocations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RecordingMemoryManager.h"
+using namespace llvm;
+
+uint8_t *RecordingMemoryManager::
+allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
+ // The recording memory manager is just a local copy of the remote target.
+ // The alignment requirement is just stored here for later use. Regular
+ // heap storage is sufficient here.
+ void *Addr = malloc(Size);
+ assert(Addr && "malloc() failure!");
+ sys::MemoryBlock Block(Addr, Size);
+ AllocatedCodeMem.push_back(Allocation(Block, Alignment));
+ return (uint8_t*)Addr;
+}
+
+uint8_t *RecordingMemoryManager::
+allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
+ // The recording memory manager is just a local copy of the remote target.
+ // The alignment requirement is just stored here for later use. Regular
+ // heap storage is sufficient here.
+ void *Addr = malloc(Size);
+ assert(Addr && "malloc() failure!");
+ sys::MemoryBlock Block(Addr, Size);
+ AllocatedDataMem.push_back(Allocation(Block, Alignment));
+ return (uint8_t*)Addr;
+}
+void RecordingMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
+void RecordingMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
+void RecordingMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
+void RecordingMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
+uint8_t *RecordingMemoryManager::getGOTBase() const {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RecordingMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RecordingMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+void RecordingMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
+ uint8_t *FunctionEnd) {
+ llvm_unreachable("Unexpected!");
+}
+uint8_t *RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+uint8_t *RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+void RecordingMemoryManager::deallocateFunctionBody(void *Body) {
+ llvm_unreachable("Unexpected!");
+}
+uint8_t* RecordingMemoryManager::startExceptionTable(const Function* F, uintptr_t &ActualSize) {
+ llvm_unreachable("Unexpected!");
+ return 0;
+}
+void RecordingMemoryManager::endExceptionTable(const Function *F, uint8_t *TableStart,
+ uint8_t *TableEnd, uint8_t* FrameRegister) {
+ llvm_unreachable("Unexpected!");
+}
+void RecordingMemoryManager::deallocateExceptionTable(void *ET) {
+ llvm_unreachable("Unexpected!");
+}
+void *RecordingMemoryManager::getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure) {
+ return NULL;
+}
diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h
new file mode 100644
index 0000000..1590235
--- /dev/null
+++ b/tools/lli/RecordingMemoryManager.h
@@ -0,0 +1,78 @@
+//===- RecordingMemoryManager.h - LLI MCJIT recording memory manager ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This memory manager allocates local storage and keeps a record of each
+// allocation. Iterators are provided for all data and code allocations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef RECORDINGMEMORYMANAGER_H
+#define RECORDINGMEMORYMANAGER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include <utility>
+
+namespace llvm {
+
+class RecordingMemoryManager : public JITMemoryManager {
+public:
+ typedef std::pair<sys::MemoryBlock, unsigned> Allocation;
+
+private:
+ SmallVector<Allocation, 16> AllocatedDataMem;
+ SmallVector<Allocation, 16> AllocatedCodeMem;
+
+public:
+ RecordingMemoryManager() {}
+ virtual ~RecordingMemoryManager() {}
+
+ typedef SmallVectorImpl<Allocation>::const_iterator const_data_iterator;
+ typedef SmallVectorImpl<Allocation>::const_iterator const_code_iterator;
+
+ const_data_iterator data_begin() const { return AllocatedDataMem.begin(); }
+ const_data_iterator data_end() const { return AllocatedDataMem.end(); }
+ const_code_iterator code_begin() const { return AllocatedCodeMem.begin(); }
+ const_code_iterator code_end() const { return AllocatedCodeMem.end(); }
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID);
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID);
+
+ void *getPointerToNamedFunction(const std::string &Name,
+ bool AbortOnFailure = true);
+ // The following obsolete JITMemoryManager calls are stubbed out for
+ // this model.
+ void setMemoryWritable();
+ void setMemoryExecutable();
+ void setPoisonMemory(bool poison);
+ void AllocateGOT();
+ uint8_t *getGOTBase() const;
+ uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize);
+ uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
+ unsigned Alignment);
+ void endFunctionBody(const Function *F, uint8_t *FunctionStart,
+ uint8_t *FunctionEnd);
+ uint8_t *allocateSpace(intptr_t Size, unsigned Alignment);
+ uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
+ void deallocateFunctionBody(void *Body);
+ uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize);
+ void endExceptionTable(const Function *F, uint8_t *TableStart,
+ uint8_t *TableEnd, uint8_t* FrameRegister);
+ void deallocateExceptionTable(void *ET);
+
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/tools/lli/RemoteTarget.cpp b/tools/lli/RemoteTarget.cpp
new file mode 100644
index 0000000..918f157
--- /dev/null
+++ b/tools/lli/RemoteTarget.cpp
@@ -0,0 +1,61 @@
+//===- RemoteTarget.cpp - LLVM Remote process JIT execution --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of the RemoteTarget class which executes JITed code in a
+// separate address range from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RemoteTarget.h"
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/Memory.h>
+#include <stdlib.h>
+#include <string>
+using namespace llvm;
+
+bool RemoteTarget::allocateSpace(size_t Size, unsigned Alignment,
+ uint64_t &Address) {
+ sys::MemoryBlock *Prev = Allocations.size() ? &Allocations.back() : NULL;
+ sys::MemoryBlock Mem = sys::Memory::AllocateRWX(Size, Prev, &ErrorMsg);
+ if (Mem.base() == NULL)
+ return true;
+ if ((uintptr_t)Mem.base() % Alignment) {
+ ErrorMsg = "unable to allocate sufficiently aligned memory";
+ return true;
+ }
+ Address = reinterpret_cast<uint64_t>(Mem.base());
+ return false;
+}
+
+bool RemoteTarget::loadData(uint64_t Address, const void *Data, size_t Size) {
+ memcpy ((void*)Address, Data, Size);
+ sys::MemoryBlock Mem((void*)Address, Size);
+ sys::Memory::setExecutable(Mem, &ErrorMsg);
+ return false;
+}
+
+bool RemoteTarget::loadCode(uint64_t Address, const void *Data, size_t Size) {
+ memcpy ((void*)Address, Data, Size);
+ return false;
+}
+
+bool RemoteTarget::executeCode(uint64_t Address, int &RetVal) {
+ int (*fn)(void) = (int(*)(void))Address;
+ RetVal = fn();
+ return false;
+}
+
+void RemoteTarget::create() {
+}
+
+void RemoteTarget::stop() {
+ for (unsigned i = 0, e = Allocations.size(); i != e; ++i)
+ sys::Memory::ReleaseRWX(Allocations[i]);
+}
diff --git a/tools/lli/RemoteTarget.h b/tools/lli/RemoteTarget.h
new file mode 100644
index 0000000..c584526
--- /dev/null
+++ b/tools/lli/RemoteTarget.h
@@ -0,0 +1,101 @@
+//===- RemoteTarget.h - LLVM Remote process JIT execution ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of the RemoteTarget class which executes JITed code in a
+// separate address range from where it was built.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef REMOTEPROCESS_H
+#define REMOTEPROCESS_H
+
+#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/Memory.h>
+#include <stdlib.h>
+#include <string>
+
+namespace llvm {
+
+class RemoteTarget {
+ std::string ErrorMsg;
+ bool IsRunning;
+
+ SmallVector<sys::MemoryBlock, 16> Allocations;
+
+public:
+ StringRef getErrorMsg() const { return ErrorMsg; }
+
+ /// Allocate space in the remote target address space.
+ ///
+ /// @param Size Amount of space, in bytes, to allocate.
+ /// @param Alignment Required minimum alignment for allocated space.
+ /// @param[out] Address Remote address of the allocated memory.
+ ///
+ /// @returns False on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ bool allocateSpace(size_t Size, unsigned Alignment, uint64_t &Address);
+
+ /// Load data into the target address space.
+ ///
+ /// @param Address Destination address in the target process.
+ /// @param Data Source address in the host process.
+ /// @param Size Number of bytes to copy.
+ ///
+ /// @returns False on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ bool loadData(uint64_t Address, const void *Data, size_t Size);
+
+ /// Load code into the target address space and prepare it for execution.
+ ///
+ /// @param Address Destination address in the target process.
+ /// @param Data Source address in the host process.
+ /// @param Size Number of bytes to copy.
+ ///
+ /// @returns False on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ bool loadCode(uint64_t Address, const void *Data, size_t Size);
+
+ /// Execute code in the target process. The called function is required
+ /// to be of signature int "(*)(void)".
+ ///
+ /// @param Address Address of the loaded function in the target
+ /// process.
+ /// @param[out] RetVal The integer return value of the called function.
+ ///
+ /// @returns False on success. On failure, ErrorMsg is updated with
+ /// descriptive text of the encountered error.
+ bool executeCode(uint64_t Address, int &RetVal);
+
+ /// Minimum alignment for memory permissions. Used to seperate code and
+ /// data regions to make sure data doesn't get marked as code or vice
+ /// versa.
+ ///
+ /// @returns Page alignment return value. Default of 4k.
+ unsigned getPageAlignment() { return 4096; }
+
+ /// Start the remote process.
+ void create();
+
+ /// Terminate the remote process.
+ void stop();
+
+ RemoteTarget() : ErrorMsg(""), IsRunning(false) {}
+ ~RemoteTarget() { if (IsRunning) stop(); }
+
+private:
+ // Main processing function for the remote target process. Command messages
+ // are received on file descriptor CmdFD and responses come back on OutFD.
+ static void doRemoteTargeting(int CmdFD, int OutFD);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index b6c9299..4004b6c 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -13,6 +13,9 @@
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "lli"
+#include "RecordingMemoryManager.h"
+#include "RemoteTarget.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
@@ -32,9 +35,11 @@
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Memory.h"
#include <cerrno>
@@ -73,6 +78,13 @@ namespace {
"use-mcjit", cl::desc("Enable use of the MC-based JIT (if available)"),
cl::init(false));
+ // The MCJIT supports building for a target address space separate from
+ // the JIT compilation process. Use a forked process and a copying
+ // memory manager with IPC to execute using this functionality.
+ cl::opt<bool> RemoteMCJIT("remote-mcjit",
+ cl::desc("Execute MCJIT'ed code in a separate process."),
+ cl::init(false));
+
// Determine optimization level.
cl::opt<char>
OptLevel("O",
@@ -372,6 +384,79 @@ LLIMCJITMemoryManager::~LLIMCJITMemoryManager() {
free(AllocatedDataMem[i].base());
}
+
+void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) {
+ // Lay out our sections in order, with all the code sections first, then
+ // all the data sections.
+ uint64_t CurOffset = 0;
+ unsigned MaxAlign = T->getPageAlignment();
+ SmallVector<std::pair<const void*, uint64_t>, 16> Offsets;
+ SmallVector<unsigned, 16> Sizes;
+ for (RecordingMemoryManager::const_code_iterator I = JMM->code_begin(),
+ E = JMM->code_end();
+ I != E; ++I) {
+ DEBUG(dbgs() << "code region: size " << I->first.size()
+ << ", alignment " << I->second << "\n");
+ // Align the current offset up to whatever is needed for the next
+ // section.
+ unsigned Align = I->second;
+ CurOffset = (CurOffset + Align - 1) / Align * Align;
+ // Save off the address of the new section and allocate its space.
+ Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset));
+ Sizes.push_back(I->first.size());
+ CurOffset += I->first.size();
+ }
+ // Adjust to keep code and data aligned on seperate pages.
+ CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
+ unsigned FirstDataIndex = Offsets.size();
+ for (RecordingMemoryManager::const_data_iterator I = JMM->data_begin(),
+ E = JMM->data_end();
+ I != E; ++I) {
+ DEBUG(dbgs() << "data region: size " << I->first.size()
+ << ", alignment " << I->second << "\n");
+ // Align the current offset up to whatever is needed for the next
+ // section.
+ unsigned Align = I->second;
+ CurOffset = (CurOffset + Align - 1) / Align * Align;
+ // Save off the address of the new section and allocate its space.
+ Offsets.push_back(std::pair<const void*,uint64_t>(I->first.base(), CurOffset));
+ Sizes.push_back(I->first.size());
+ CurOffset += I->first.size();
+ }
+
+ // Allocate space in the remote target.
+ uint64_t RemoteAddr;
+ if (T->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
+ report_fatal_error(T->getErrorMsg());
+ // Map the section addresses so relocations will get updated in the local
+ // copies of the sections.
+ for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
+ uint64_t Addr = RemoteAddr + Offsets[i].second;
+ EE->mapSectionAddress(const_cast<void*>(Offsets[i].first), Addr);
+
+ DEBUG(dbgs() << " Mapping local: " << Offsets[i].first
+ << " to remote: " << format("%#018x", Addr) << "\n");
+
+ }
+ // Now load it all to the target.
+ for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
+ uint64_t Addr = RemoteAddr + Offsets[i].second;
+
+ if (i < FirstDataIndex) {
+ T->loadCode(Addr, Offsets[i].first, Sizes[i]);
+
+ DEBUG(dbgs() << " loading code: " << Offsets[i].first
+ << " to remote: " << format("%#018x", Addr) << "\n");
+ } else {
+ T->loadData(Addr, Offsets[i].first, Sizes[i]);
+
+ DEBUG(dbgs() << " loading data: " << Offsets[i].first
+ << " to remote: " << format("%#018x", Addr) << "\n");
+ }
+
+ }
+}
+
//===----------------------------------------------------------------------===//
// main Driver function
//
@@ -428,12 +513,19 @@ int main(int argc, char **argv, char * const *envp) {
Mod->setTargetTriple(Triple::normalize(TargetTriple));
// Enable MCJIT if desired.
- LLIMCJITMemoryManager *JMM = 0;
+ JITMemoryManager *JMM = 0;
if (UseMCJIT && !ForceInterpreter) {
builder.setUseMCJIT(true);
- JMM = new LLIMCJITMemoryManager();
+ if (RemoteMCJIT)
+ JMM = new RecordingMemoryManager();
+ else
+ JMM = new LLIMCJITMemoryManager();
builder.setJITMemoryManager(JMM);
} else {
+ if (RemoteMCJIT) {
+ errs() << "error: Remote process execution requires -use-mcjit\n";
+ exit(1);
+ }
builder.setJITMemoryManager(ForceInterpreter ? 0 :
JITMemoryManager::CreateDefaultMemManager());
}
@@ -451,11 +543,14 @@ int main(int argc, char **argv, char * const *envp) {
}
builder.setOptLevel(OLvl);
- TargetOptions Options;
- Options.JITExceptionHandling = EnableJITExceptionHandling;
- Options.JITEmitDebugInfo = EmitJitDebugInfo;
- Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
- builder.setTargetOptions(Options);
+ // Remote target execution doesn't handle EH or debug registration.
+ if (!RemoteMCJIT) {
+ TargetOptions Options;
+ Options.JITExceptionHandling = EnableJITExceptionHandling;
+ Options.JITEmitDebugInfo = EmitJitDebugInfo;
+ Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
+ builder.setTargetOptions(Options);
+ }
EE = builder.create();
if (!EE) {
@@ -466,10 +561,6 @@ int main(int argc, char **argv, char * const *envp) {
exit(1);
}
- // Clear instruction cache before code will be executed.
- if (JMM)
- JMM->invalidateInstructionCache();
-
// The following functions have no effect if their respective profiling
// support wasn't enabled in the build configuration.
EE->RegisterJITEventListener(
@@ -477,6 +568,10 @@ int main(int argc, char **argv, char * const *envp) {
EE->RegisterJITEventListener(
JITEventListener::createIntelJITEventListener());
+ if (!NoLazyCompilation && RemoteMCJIT) {
+ errs() << "warning: remote mcjit does not support lazy compilation\n";
+ NoLazyCompilation = true;
+ }
EE->DisableLazyCompilation(NoLazyCompilation);
// If the user specifically requested an argv[0] to pass into the program,
@@ -513,8 +608,13 @@ int main(int argc, char **argv, char * const *envp) {
// Reset errno to zero on entry to main.
errno = 0;
+ // Remote target MCJIT doesn't (yet) support static constructors. No reason
+ // it couldn't. This is a limitation of the LLI implemantation, not the
+ // MCJIT itself. FIXME.
+ //
// Run static constructors.
- EE->runStaticConstructorsDestructors(false);
+ if (!RemoteMCJIT)
+ EE->runStaticConstructorsDestructors(false);
if (NoLazyCompilation) {
for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
@@ -524,24 +624,66 @@ int main(int argc, char **argv, char * const *envp) {
}
}
- // Run main.
- int Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
+ int Result;
+ if (RemoteMCJIT) {
+ RecordingMemoryManager *MM = static_cast<RecordingMemoryManager*>(JMM);
+ // Everything is prepared now, so lay out our program for the target
+ // address space, assign the section addresses to resolve any relocations,
+ // and send it to the target.
+ RemoteTarget Target;
+ Target.create();
+
+ // Ask for a pointer to the entry function. This triggers the actual
+ // compilation.
+ (void)EE->getPointerToFunction(EntryFn);
+
+ // Enough has been compiled to execute the entry function now, so
+ // layout the target memory.
+ layoutRemoteTargetMemory(&Target, MM);
+
+ // Since we're executing in a (at least simulated) remote address space,
+ // we can't use the ExecutionEngine::runFunctionAsMain(). We have to
+ // grab the function address directly here and tell the remote target
+ // to execute the function.
+ // FIXME: argv and envp handling.
+ uint64_t Entry = (uint64_t)EE->getPointerToFunction(EntryFn);
+
+ DEBUG(dbgs() << "Executing '" << EntryFn->getName() << "' at "
+ << format("%#18x", Entry) << "\n");
+
+ if (Target.executeCode(Entry, Result))
+ errs() << "ERROR: " << Target.getErrorMsg() << "\n";
+
+ Target.stop();
+ } else {
+ // Clear instruction cache before code will be executed.
+ if (JMM)
+ static_cast<LLIMCJITMemoryManager*>(JMM)->invalidateInstructionCache();
- // Run static destructors.
- EE->runStaticConstructorsDestructors(true);
+ // Run main.
+ Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
+ }
- // If the program didn't call exit explicitly, we should call it now.
- // This ensures that any atexit handlers get called correctly.
- if (Function *ExitF = dyn_cast<Function>(Exit)) {
- std::vector<GenericValue> Args;
- GenericValue ResultGV;
- ResultGV.IntVal = APInt(32, Result);
- Args.push_back(ResultGV);
- EE->runFunction(ExitF, Args);
- errs() << "ERROR: exit(" << Result << ") returned!\n";
- abort();
- } else {
- errs() << "ERROR: exit defined with wrong prototype!\n";
- abort();
+ // Like static constructors, the remote target MCJIT support doesn't handle
+ // this yet. It could. FIXME.
+ if (!RemoteMCJIT) {
+ // Run static destructors.
+ EE->runStaticConstructorsDestructors(true);
+
+ // If the program didn't call exit explicitly, we should call it now.
+ // This ensures that any atexit handlers get called correctly.
+ if (Function *ExitF = dyn_cast<Function>(Exit)) {
+ std::vector<GenericValue> Args;
+ GenericValue ResultGV;
+ ResultGV.IntVal = APInt(32, Result);
+ Args.push_back(ResultGV);
+ EE->runFunction(ExitF, Args);
+ errs() << "ERROR: exit(" << Result << ") returned!\n";
+ abort();
+ } else {
+ errs() << "ERROR: exit defined with wrong prototype!\n";
+ abort();
+ }
}
+ return Result;
}
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index d630087..8109ca4 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -40,7 +40,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/system_error.h"
-#include <cstdio>
+
#include <map>
#include <algorithm>
using namespace llvm;
@@ -463,11 +463,11 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
}
static void PrintSize(double Bits) {
- fprintf(stderr, "%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32));
+ outs() << format("%.2f/%.2fB/%luW", Bits, Bits/8,(unsigned long)(Bits/32));
}
static void PrintSize(uint64_t Bits) {
- fprintf(stderr, "%lub/%.2fB/%luW", (unsigned long)Bits,
- (double)Bits/8, (unsigned long)(Bits/32));
+ outs() << format("%lub/%.2fB/%luW", (unsigned long)Bits,
+ (double)Bits/8, (unsigned long)(Bits/32));
}
@@ -483,7 +483,7 @@ static int AnalyzeBitcode() {
if (MemBuf->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
- const unsigned char *BufPtr = (unsigned char *)MemBuf->getBufferStart();
+ const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
const unsigned char *EndBufPtr = BufPtr+MemBuf->getBufferSize();
// If we have a wrapper header, parse it and ignore the non-bc file contents.
@@ -556,7 +556,7 @@ static int AnalyzeBitcode() {
PrintSize(Stats.NumBits);
outs() << "\n";
double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
- errs() << " Percent of file: " << format("%2.4f%%", pct) << "\n";
+ outs() << " Percent of file: " << format("%2.4f%%", pct) << "\n";
if (Stats.NumInstances > 1) {
outs() << " Average Size: ";
PrintSize(Stats.NumBits/(double)Stats.NumInstances);
@@ -588,24 +588,26 @@ static int AnalyzeBitcode() {
std::reverse(FreqPairs.begin(), FreqPairs.end());
outs() << "\tRecord Histogram:\n";
- fprintf(stderr, "\t\t Count # Bits %% Abv Record Kind\n");
+ outs() << "\t\t Count # Bits %% Abv Record Kind\n";
for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
- fprintf(stderr, "\t\t%7d %9lu ", RecStats.NumInstances,
- (unsigned long)RecStats.TotalBits);
+ outs() << format("\t\t%7d %9lu",
+ RecStats.NumInstances,
+ (unsigned long)RecStats.TotalBits);
if (RecStats.NumAbbrev)
- fprintf(stderr, "%7.2f ",
- (double)RecStats.NumAbbrev/RecStats.NumInstances*100);
+ outs() <<
+ format("%7.2f ",
+ (double)RecStats.NumAbbrev/RecStats.NumInstances*100);
else
- fprintf(stderr, " ");
+ outs() << " ";
if (const char *CodeName =
GetCodeName(FreqPairs[i].second, I->first, StreamFile))
- fprintf(stderr, "%s\n", CodeName);
+ outs() << CodeName << "\n";
else
- fprintf(stderr, "UnknownCode%d\n", FreqPairs[i].second);
+ outs() << "UnknownCode" << FreqPairs[i].second << "\n";
}
outs() << "\n";
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index ec0b4ae..38c3a1e 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -44,6 +44,18 @@ PrintFunctions("functions", cl::init(false),
cl::desc("Print function names as well as line information "
"for a given address"));
+static cl::opt<bool>
+PrintInlining("inlining", cl::init(false),
+ cl::desc("Print all inlined frames for a given address"));
+
+static void PrintDILineInfo(DILineInfo dli) {
+ if (PrintFunctions)
+ outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>")
+ << "\n";
+ outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':'
+ << dli.getLine() << ':' << dli.getColumn() << '\n';
+}
+
static void DumpInput(const StringRef &Filename) {
OwningPtr<MemoryBuffer> Buff;
@@ -59,6 +71,7 @@ static void DumpInput(const StringRef &Filename) {
StringRef DebugLineSection;
StringRef DebugArangesSection;
StringRef DebugStringSection;
+ StringRef DebugRangesSection;
error_code ec;
for (section_iterator i = Obj->begin_sections(),
@@ -82,6 +95,8 @@ static void DumpInput(const StringRef &Filename) {
DebugArangesSection = data;
else if (name == "debug_str")
DebugStringSection = data;
+ else if (name == "debug_ranges")
+ DebugRangesSection = data;
}
OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
@@ -89,7 +104,8 @@ static void DumpInput(const StringRef &Filename) {
DebugAbbrevSection,
DebugArangesSection,
DebugLineSection,
- DebugStringSection));
+ DebugStringSection,
+ DebugRangesSection));
if (Address == -1ULL) {
outs() << Filename
<< ":\tfile format " << Obj->getFileFormatName() << "\n\n";
@@ -97,16 +113,27 @@ static void DumpInput(const StringRef &Filename) {
dictx->dump(outs());
} else {
// Print line info for the specified address.
- int spec_flags = DILineInfoSpecifier::FileLineInfo |
- DILineInfoSpecifier::AbsoluteFilePath;
- if (PrintFunctions)
- spec_flags |= DILineInfoSpecifier::FunctionName;
- DILineInfo dli = dictx->getLineInfoForAddress(Address, spec_flags);
+ int SpecFlags = DILineInfoSpecifier::FileLineInfo |
+ DILineInfoSpecifier::AbsoluteFilePath;
if (PrintFunctions)
- outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>")
- << "\n";
- outs() << (dli.getFileName() ? dli.getFileName() : "<unknown>") << ':'
- << dli.getLine() << ':' << dli.getColumn() << '\n';
+ SpecFlags |= DILineInfoSpecifier::FunctionName;
+ if (PrintInlining) {
+ DIInliningInfo InliningInfo = dictx->getInliningInfoForAddress(
+ Address, SpecFlags);
+ uint32_t n = InliningInfo.getNumberOfFrames();
+ if (n == 0) {
+ // Print one empty debug line info in any case.
+ PrintDILineInfo(DILineInfo());
+ } else {
+ for (uint32_t i = 0; i < n; i++) {
+ DILineInfo dli = InliningInfo.getFrame(i);
+ PrintDILineInfo(dli);
+ }
+ }
+ } else {
+ DILineInfo dli = dictx->getLineInfoForAddress(Address, SpecFlags);
+ PrintDILineInfo(dli);
+ }
}
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index b431c76..13ea4e3 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -94,6 +94,12 @@ static cl::alias
SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
+static cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
static StringRef ToolName;
static bool error(error_code ec) {
@@ -169,6 +175,15 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
if (!TheTarget)
return;
+ // Package up features to be passed to target/subtarget
+ std::string FeaturesStr;
+ if (MAttrs.size()) {
+ SubtargetFeatures Features;
+ for (unsigned i = 0; i != MAttrs.size(); ++i)
+ Features.AddFeature(MAttrs[i]);
+ FeaturesStr = Features.getString();
+ }
+
error_code ec;
for (section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
@@ -233,7 +248,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
OwningPtr<const MCSubtargetInfo> STI(
- TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
if (!STI) {
errs() << "error: no subtarget info for target " << TripleName << "\n";
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index b80bc34..f8b07b2 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -163,13 +163,16 @@ bool LTOCodeGenerator::compile_to_file(const char** name, std::string& errMsg) {
// generate object file
bool genResult = false;
tool_output_file objFile(uniqueObjPath.c_str(), errMsg);
- if (!errMsg.empty())
+ if (!errMsg.empty()) {
+ uniqueObjPath.eraseFromDisk();
return true;
+ }
genResult = this->generateObjectFile(objFile.os(), errMsg);
objFile.os().close();
if (objFile.os().has_error()) {
objFile.os().clear_error();
+ uniqueObjPath.eraseFromDisk();
return true;
}
@@ -196,6 +199,7 @@ const void* LTOCodeGenerator::compile(size_t* length, std::string& errMsg) {
OwningPtr<MemoryBuffer> BuffPtr;
if (error_code ec = MemoryBuffer::getFile(name, BuffPtr, -1, false)) {
errMsg = ec.message();
+ sys::Path(_nativeObjectPath).eraseFromDisk();
return NULL;
}
_nativeObjectFile = BuffPtr.take();
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index d588f6a..b98bfab 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -163,7 +163,7 @@ LTOModule::LTOModule(llvm::Module *m, llvm::TargetMachine *t)
/// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM
/// bitcode.
bool LTOModule::isBitcodeFile(const void *mem, size_t length) {
- return llvm::sys::IdentifyFileType((char*)mem, length)
+ return llvm::sys::IdentifyFileType((const char*)mem, length)
== llvm::sys::Bitcode_FileType;
}
@@ -307,7 +307,7 @@ LTOModule *LTOModule::makeLTOModule(MemoryBuffer *buffer,
/// makeBuffer - Create a MemoryBuffer from a memory range.
MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length) {
- const char *startPtr = (char*)mem;
+ const char *startPtr = (const char*)mem;
return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), "", false);
}
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 4ada7d1..7ecd25c 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -513,10 +513,6 @@ int main(int argc, char **argv) {
return 1;
}
- // Allocate a full target machine description only if necessary.
- // FIXME: The choice of target should be controllable on the command line.
- std::auto_ptr<TargetMachine> target;
-
SMDiagnostic Err;
// Load the input module...