diff options
| author | Stephen Hines <srhines@google.com> | 2012-09-13 19:09:19 -0700 |
|---|---|---|
| committer | Android Git Automerger <android-git-automerger@android.com> | 2012-09-13 19:09:19 -0700 |
| commit | 78c041bd883d86c81c42b98f326660277e6d0d9a (patch) | |
| tree | 52800183ec2d22164b8f396842142c3a8aab912a /tools/lli/lli.cpp | |
| parent | 828ded66831c0caaeecd2291a6bfb084f373d0e4 (diff) | |
| parent | 1c4ad5ef4fab105f0c8af7edd026e00502fb6279 (diff) | |
| download | external_llvm-78c041bd883d86c81c42b98f326660277e6d0d9a.zip external_llvm-78c041bd883d86c81c42b98f326660277e6d0d9a.tar.gz external_llvm-78c041bd883d86c81c42b98f326660277e6d0d9a.tar.bz2 | |
am 1c4ad5ef: Merge branch \'upstream\' into merge-2012_09_10
* commit '1c4ad5ef4fab105f0c8af7edd026e00502fb6279': (446 commits)
Revert r163556. Missed updates to tablegen files.
Update function names to conform to guidelines. No functional change intended.
test/CodeGen/X86/ms-inline-asm.ll: Relax for non-darwin x86 targets. '##InlineAsm' could not be seen in other hosts.
[ms-inline asm] Properly emit the asm directives when the AsmPrinterVariant and InlineAsmVariant don't match.
Update test case for Release builds.
Remove redundant semicolons which are null statements.
Disable stack coloring because it makes dragonegg fail bootstrapping.
[ms-inline asm] Pass the correct AsmVariant to the PrintAsmOperand() function and update the printOperand() function accordingly.
[ms-inline asm] Add support for .att_syntax directive.
Enable stack coloring.
Don't attempt to use flags from predicated instructions.
[Object] Extract Elf_Ehdr. Patch by Hemant Kulkarni!
Stack Coloring: Handle the case where END markers come before BEGIN markers properly.
Enhance PR11334 fix to support extload from v2f32/v4f32
Add "blocked" heuristic to the Hexagon MI scheduler.
Fold multiply by 0 or 1 when in UnsafeFPMath mode in SelectionDAG::getNode().
whitespace
Add boolean simplification support from CMOV
Fix an assertion failure when optimising a shufflevector incorrectly into concat_vectors, and a followup bug with SelectionDAG::getNode() creating nodes with invalid types.
Minor cleanup. No functional change.
...
Diffstat (limited to 'tools/lli/lli.cpp')
| -rw-r--r-- | tools/lli/lli.cpp | 200 |
1 files changed, 171 insertions, 29 deletions
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; } |
