mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Beginnings of MC-JIT code generation.
Proof-of-concept code that code-gens a module to an in-memory MachO object. This will be hooked up to a run-time dynamic linker library (see: llvm-rtdyld for similarly conceptual work for that part) which will take the compiled object and link it together with the rest of the system, providing back to the JIT a table of available symbols which will be used to respond to the getPointerTo*() queries. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127916 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -38,6 +38,7 @@ class PassManager;
|
|||||||
class Pass;
|
class Pass;
|
||||||
class TargetELFWriterInfo;
|
class TargetELFWriterInfo;
|
||||||
class formatted_raw_ostream;
|
class formatted_raw_ostream;
|
||||||
|
class raw_ostream;
|
||||||
|
|
||||||
// Relocation model types.
|
// Relocation model types.
|
||||||
namespace Reloc {
|
namespace Reloc {
|
||||||
@@ -267,6 +268,7 @@ public:
|
|||||||
///
|
///
|
||||||
virtual bool addPassesToEmitMC(PassManagerBase &,
|
virtual bool addPassesToEmitMC(PassManagerBase &,
|
||||||
MCContext *&,
|
MCContext *&,
|
||||||
|
raw_ostream &OS,
|
||||||
CodeGenOpt::Level,
|
CodeGenOpt::Level,
|
||||||
bool = true) {
|
bool = true) {
|
||||||
return true;
|
return true;
|
||||||
@@ -324,6 +326,7 @@ public:
|
|||||||
///
|
///
|
||||||
virtual bool addPassesToEmitMC(PassManagerBase &PM,
|
virtual bool addPassesToEmitMC(PassManagerBase &PM,
|
||||||
MCContext *&Ctx,
|
MCContext *&Ctx,
|
||||||
|
raw_ostream &OS,
|
||||||
CodeGenOpt::Level OptLevel,
|
CodeGenOpt::Level OptLevel,
|
||||||
bool DisableVerify = true);
|
bool DisableVerify = true);
|
||||||
|
|
||||||
|
@@ -224,11 +224,37 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM,
|
|||||||
///
|
///
|
||||||
bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
|
bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
|
||||||
MCContext *&Ctx,
|
MCContext *&Ctx,
|
||||||
|
raw_ostream &Out,
|
||||||
CodeGenOpt::Level OptLevel,
|
CodeGenOpt::Level OptLevel,
|
||||||
bool DisableVerify) {
|
bool DisableVerify) {
|
||||||
// Add common CodeGen passes.
|
// Add common CodeGen passes.
|
||||||
if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx))
|
if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Create the code emitter for the target if it exists. If not, .o file
|
||||||
|
// emission fails.
|
||||||
|
MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Ctx);
|
||||||
|
TargetAsmBackend *TAB = getTarget().createAsmBackend(TargetTriple);
|
||||||
|
if (MCE == 0 || TAB == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
OwningPtr<MCStreamer> AsmStreamer;
|
||||||
|
AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Ctx,
|
||||||
|
*TAB, Out, MCE,
|
||||||
|
hasMCRelaxAll(),
|
||||||
|
hasMCNoExecStack()));
|
||||||
|
AsmStreamer.get()->InitSections();
|
||||||
|
|
||||||
|
// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
|
||||||
|
FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer);
|
||||||
|
if (Printer == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// If successful, createAsmPrinter took ownership of AsmStreamer.
|
||||||
|
AsmStreamer.take();
|
||||||
|
|
||||||
|
PM.add(Printer);
|
||||||
|
|
||||||
// Make sure the code model is set.
|
// Make sure the code model is set.
|
||||||
setCodeModelForJIT();
|
setCodeModelForJIT();
|
||||||
|
|
||||||
|
@@ -8,10 +8,12 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MCJIT.h"
|
#include "MCJIT.h"
|
||||||
|
#include "llvm/Function.h"
|
||||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/DynamicLibrary.h"
|
#include "llvm/Support/DynamicLibrary.h"
|
||||||
|
#include "llvm/Target/TargetData.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -51,17 +53,34 @@ ExecutionEngine *MCJIT::createJIT(Module *M,
|
|||||||
|
|
||||||
// If the target supports JIT code generation, create the JIT.
|
// If the target supports JIT code generation, create the JIT.
|
||||||
if (TargetJITInfo *TJ = TM->getJITInfo())
|
if (TargetJITInfo *TJ = TM->getJITInfo())
|
||||||
return new MCJIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode);
|
return new MCJIT(M, TM, *TJ, JMM, OptLevel, GVsWithCode);
|
||||||
|
|
||||||
if (ErrorStr)
|
if (ErrorStr)
|
||||||
*ErrorStr = "target does not support JIT code generation";
|
*ErrorStr = "target does not support JIT code generation";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCJIT::MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji,
|
MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
|
||||||
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
||||||
bool AllocateGVsWithCode)
|
bool AllocateGVsWithCode)
|
||||||
: ExecutionEngine(M) {
|
: ExecutionEngine(m), TM(tm), M(m), OS(Buffer) {
|
||||||
|
|
||||||
|
PM.add(new TargetData(*TM->getTargetData()));
|
||||||
|
|
||||||
|
// Turn the machine code intermediate representation into bytes in memory
|
||||||
|
// that may be executed.
|
||||||
|
if (TM->addPassesToEmitMC(PM, Ctx, OS, CodeGenOpt::Default, false)) {
|
||||||
|
report_fatal_error("Target does not support MC emission!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize passes.
|
||||||
|
ExecutionEngine::addModule(M);
|
||||||
|
// FIXME: When we support multiple modules, we'll want to move the code
|
||||||
|
// gen and finalization out of the constructor here and do it more
|
||||||
|
// on-demand as part of getPointerToFunction().
|
||||||
|
PM.run(*M);
|
||||||
|
// Flush the output buffer so the SmallVector gets its data.
|
||||||
|
OS.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
MCJIT::~MCJIT() {
|
MCJIT::~MCJIT() {
|
||||||
@@ -73,7 +92,6 @@ void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *MCJIT::getPointerToFunction(Function *F) {
|
void *MCJIT::getPointerToFunction(Function *F) {
|
||||||
report_fatal_error("not yet implemented");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +105,10 @@ void MCJIT::freeMachineCodeForFunction(Function *F) {
|
|||||||
|
|
||||||
GenericValue MCJIT::runFunction(Function *F,
|
GenericValue MCJIT::runFunction(Function *F,
|
||||||
const std::vector<GenericValue> &ArgValues) {
|
const std::vector<GenericValue> &ArgValues) {
|
||||||
report_fatal_error("not yet implemented");
|
assert(ArgValues.size() == 0 && "JIT arg passing not supported yet");
|
||||||
|
void *FPtr = getPointerToFunction(F);
|
||||||
|
if (!FPtr)
|
||||||
|
report_fatal_error("Unable to locate function: '" + F->getName() + "'");
|
||||||
|
((void(*)(void))FPtr)();
|
||||||
return GenericValue();
|
return GenericValue();
|
||||||
}
|
}
|
||||||
|
@@ -10,14 +10,33 @@
|
|||||||
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H
|
#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H
|
||||||
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_H
|
#define LLVM_LIB_EXECUTIONENGINE_MCJIT_H
|
||||||
|
|
||||||
|
#include "llvm/PassManager.h"
|
||||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
// FIXME: This makes all kinds of horrible assumptions for the time being,
|
||||||
|
// like only having one module, not needing to worry about multi-threading,
|
||||||
|
// blah blah. Purely in get-it-up-and-limping mode for now.
|
||||||
|
|
||||||
class MCJIT : public ExecutionEngine {
|
class MCJIT : public ExecutionEngine {
|
||||||
MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji,
|
MCJIT(Module *M, TargetMachine *tm, TargetJITInfo &tji,
|
||||||
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
JITMemoryManager *JMM, CodeGenOpt::Level OptLevel,
|
||||||
bool AllocateGVsWithCode);
|
bool AllocateGVsWithCode);
|
||||||
|
|
||||||
|
TargetMachine *TM;
|
||||||
|
MCContext *Ctx;
|
||||||
|
|
||||||
|
// FIXME: These may need moved to a separate 'jitstate' member like the
|
||||||
|
// non-MC JIT does for multithreading and such. Just keep them here for now.
|
||||||
|
PassManager PM;
|
||||||
|
Module *M;
|
||||||
|
// FIXME: This really doesn't belong here.
|
||||||
|
SmallVector<char, 4096> Buffer; // Working buffer into which we JIT.
|
||||||
|
raw_svector_ostream OS;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~MCJIT();
|
~MCJIT();
|
||||||
|
|
||||||
|
@@ -133,6 +133,7 @@ int main(int argc, char **argv, char * const *envp) {
|
|||||||
// If we have a native target, initialize it to ensure it is linked in and
|
// If we have a native target, initialize it to ensure it is linked in and
|
||||||
// usable by the JIT.
|
// usable by the JIT.
|
||||||
InitializeNativeTarget();
|
InitializeNativeTarget();
|
||||||
|
InitializeNativeTargetAsmPrinter();
|
||||||
|
|
||||||
cl::ParseCommandLineOptions(argc, argv,
|
cl::ParseCommandLineOptions(argc, argv,
|
||||||
"llvm interpreter & dynamic compiler\n");
|
"llvm interpreter & dynamic compiler\n");
|
||||||
|
Reference in New Issue
Block a user