mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-01 19:29:22 +00:00
Modules and ModuleProviders. Because the "ModuleProvider" simply materializes GlobalValues now, and doesn't provide modules, it's renamed to "GVMaterializer". Code that used to need a ModuleProvider to materialize Functions can now materialize the Functions directly. Functions no longer use a magic linkage to record that they're materializable; they simply ask the GVMaterializer. Because the C ABI must never change, we can't remove LLVMModuleProviderRef or the functions that refer to it. Instead, because Module now exposes the same functionality ModuleProvider used to, we store a Module* in any LLVMModuleProviderRef and translate in the wrapper methods. The bindings to other languages still use the ModuleProvider concept. It would probably be worth some time to update them to follow the C++ more closely, but I don't intend to do it. Fixes http://llvm.org/PR5737 and http://llvm.org/PR5735. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94686 91177308-0d34-0410-b5e6-96231b3b80d8
235 lines
7.6 KiB
C++
235 lines
7.6 KiB
C++
//===- lli.cpp - LLVM Interpreter / Dynamic compiler ----------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This utility provides a simple wrapper around the LLVM Execution Engines,
|
|
// which allow the direct execution of LLVM programs through a Just-In-Time
|
|
// compiler, or through an interpreter if no JIT is available for this platform.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/LLVMContext.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/Type.h"
|
|
#include "llvm/Bitcode/ReaderWriter.h"
|
|
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
|
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
|
#include "llvm/ExecutionEngine/Interpreter.h"
|
|
#include "llvm/ExecutionEngine/JIT.h"
|
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/PluginLoader.h"
|
|
#include "llvm/Support/PrettyStackTrace.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/System/Process.h"
|
|
#include "llvm/System/Signals.h"
|
|
#include "llvm/Target/TargetSelect.h"
|
|
#include <cerrno>
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
cl::opt<std::string>
|
|
InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
|
|
|
|
cl::list<std::string>
|
|
InputArgv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
|
|
|
|
cl::opt<bool> ForceInterpreter("force-interpreter",
|
|
cl::desc("Force interpretation: disable JIT"),
|
|
cl::init(false));
|
|
|
|
// Determine optimization level.
|
|
cl::opt<char>
|
|
OptLevel("O",
|
|
cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
|
|
"(default = '-O2')"),
|
|
cl::Prefix,
|
|
cl::ZeroOrMore,
|
|
cl::init(' '));
|
|
|
|
cl::opt<std::string>
|
|
TargetTriple("mtriple", cl::desc("Override target triple for module"));
|
|
|
|
cl::opt<std::string>
|
|
EntryFunc("entry-function",
|
|
cl::desc("Specify the entry function (default = 'main') "
|
|
"of the executable"),
|
|
cl::value_desc("function"),
|
|
cl::init("main"));
|
|
|
|
cl::opt<std::string>
|
|
FakeArgv0("fake-argv0",
|
|
cl::desc("Override the 'argv[0]' value passed into the executing"
|
|
" program"), cl::value_desc("executable"));
|
|
|
|
cl::opt<bool>
|
|
DisableCoreFiles("disable-core-files", cl::Hidden,
|
|
cl::desc("Disable emission of core files if possible"));
|
|
|
|
cl::opt<bool>
|
|
NoLazyCompilation("disable-lazy-compilation",
|
|
cl::desc("Disable JIT lazy compilation"),
|
|
cl::init(false));
|
|
}
|
|
|
|
static ExecutionEngine *EE = 0;
|
|
|
|
static void do_shutdown() {
|
|
delete EE;
|
|
llvm_shutdown();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// main Driver function
|
|
//
|
|
int main(int argc, char **argv, char * const *envp) {
|
|
sys::PrintStackTraceOnErrorSignal();
|
|
PrettyStackTraceProgram X(argc, argv);
|
|
|
|
LLVMContext &Context = getGlobalContext();
|
|
atexit(do_shutdown); // Call llvm_shutdown() on exit.
|
|
|
|
// If we have a native target, initialize it to ensure it is linked in and
|
|
// usable by the JIT.
|
|
InitializeNativeTarget();
|
|
|
|
cl::ParseCommandLineOptions(argc, argv,
|
|
"llvm interpreter & dynamic compiler\n");
|
|
|
|
// If the user doesn't want core files, disable them.
|
|
if (DisableCoreFiles)
|
|
sys::Process::PreventCoreFiles();
|
|
|
|
// Load the bitcode...
|
|
std::string ErrorMsg;
|
|
Module *Mod = NULL;
|
|
if (MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFile,&ErrorMsg)){
|
|
Mod = getLazyBitcodeModule(Buffer, Context, &ErrorMsg);
|
|
if (!Mod) delete Buffer;
|
|
}
|
|
|
|
if (!Mod) {
|
|
errs() << argv[0] << ": error loading program '" << InputFile << "': "
|
|
<< ErrorMsg << "\n";
|
|
exit(1);
|
|
}
|
|
|
|
// If not jitting lazily, load the whole bitcode file eagerly too.
|
|
if (NoLazyCompilation) {
|
|
if (Mod->MaterializeAllPermanently(&ErrorMsg)) {
|
|
errs() << argv[0] << ": bitcode didn't read correctly.\n";
|
|
errs() << "Reason: " << ErrorMsg << "\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
EngineBuilder builder(Mod);
|
|
builder.setErrorStr(&ErrorMsg);
|
|
builder.setEngineKind(ForceInterpreter
|
|
? EngineKind::Interpreter
|
|
: EngineKind::JIT);
|
|
|
|
// If we are supposed to override the target triple, do so now.
|
|
if (!TargetTriple.empty())
|
|
Mod->setTargetTriple(TargetTriple);
|
|
|
|
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
|
|
switch (OptLevel) {
|
|
default:
|
|
errs() << argv[0] << ": invalid optimization level.\n";
|
|
return 1;
|
|
case ' ': break;
|
|
case '0': OLvl = CodeGenOpt::None; break;
|
|
case '1': OLvl = CodeGenOpt::Less; break;
|
|
case '2': OLvl = CodeGenOpt::Default; break;
|
|
case '3': OLvl = CodeGenOpt::Aggressive; break;
|
|
}
|
|
builder.setOptLevel(OLvl);
|
|
|
|
EE = builder.create();
|
|
if (!EE) {
|
|
if (!ErrorMsg.empty())
|
|
errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
|
|
else
|
|
errs() << argv[0] << ": unknown error creating EE!\n";
|
|
exit(1);
|
|
}
|
|
|
|
EE->RegisterJITEventListener(createOProfileJITEventListener());
|
|
|
|
EE->DisableLazyCompilation(NoLazyCompilation);
|
|
|
|
// If the user specifically requested an argv[0] to pass into the program,
|
|
// do it now.
|
|
if (!FakeArgv0.empty()) {
|
|
InputFile = FakeArgv0;
|
|
} else {
|
|
// Otherwise, if there is a .bc suffix on the executable strip it off, it
|
|
// might confuse the program.
|
|
if (InputFile.rfind(".bc") == InputFile.length() - 3)
|
|
InputFile.erase(InputFile.length() - 3);
|
|
}
|
|
|
|
// Add the module's name to the start of the vector of arguments to main().
|
|
InputArgv.insert(InputArgv.begin(), InputFile);
|
|
|
|
// Call the main function from M as if its signature were:
|
|
// int main (int argc, char **argv, const char **envp)
|
|
// using the contents of Args to determine argc & argv, and the contents of
|
|
// EnvVars to determine envp.
|
|
//
|
|
Function *EntryFn = Mod->getFunction(EntryFunc);
|
|
if (!EntryFn) {
|
|
errs() << '\'' << EntryFunc << "\' function not found in module.\n";
|
|
return -1;
|
|
}
|
|
|
|
// If the program doesn't explicitly call exit, we will need the Exit
|
|
// function later on to make an explicit call, so get the function now.
|
|
Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
|
|
Type::getInt32Ty(Context),
|
|
NULL);
|
|
|
|
// Reset errno to zero on entry to main.
|
|
errno = 0;
|
|
|
|
// Run static constructors.
|
|
EE->runStaticConstructorsDestructors(false);
|
|
|
|
if (NoLazyCompilation) {
|
|
for (Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
|
|
Function *Fn = &*I;
|
|
if (Fn != EntryFn && !Fn->isDeclaration())
|
|
EE->getPointerToFunction(Fn);
|
|
}
|
|
}
|
|
|
|
// Run main.
|
|
int Result = EE->runFunctionAsMain(EntryFn, InputArgv, envp);
|
|
|
|
// 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();
|
|
}
|
|
}
|