mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
Add simple arg passing to MC-JIT and support for exit() call.
Support argument passing simple, common, prototypes directly. More complicated scenarios will require building up a stub function, which the MC-JIT isn't set up to handle yet. Add Intercept.cpp, which is just a copy from ExecutionEngine/JIT for now, to handle looking looking up external symbol names. This probably more properly belongs as part of RuntimeDyld. It'll migrate there as things flesh out more fully. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128090 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8bf0ecdbf6
commit
34714a0609
@ -1,4 +1,5 @@
|
||||
add_llvm_library(LLVMMCJIT
|
||||
MCJIT.cpp
|
||||
TargetSelect.cpp
|
||||
Intercept.cpp
|
||||
)
|
||||
|
@ -8,6 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCJIT.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||
@ -101,6 +102,13 @@ void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
|
||||
}
|
||||
|
||||
void *MCJIT::getPointerToFunction(Function *F) {
|
||||
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
|
||||
bool AbortOnFailure = !F->hasExternalWeakLinkage();
|
||||
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
|
||||
addGlobalMapping(F, Addr);
|
||||
return Addr;
|
||||
}
|
||||
|
||||
Twine Name = TM->getMCAsmInfo()->getGlobalPrefix() + F->getName();
|
||||
return Dyld.getSymbolAddress(Name.str());
|
||||
}
|
||||
@ -115,10 +123,102 @@ void MCJIT::freeMachineCodeForFunction(Function *F) {
|
||||
|
||||
GenericValue MCJIT::runFunction(Function *F,
|
||||
const std::vector<GenericValue> &ArgValues) {
|
||||
assert(ArgValues.size() == 0 && "JIT arg passing not supported yet");
|
||||
assert(F && "Function *F was null at entry to run()");
|
||||
|
||||
void *FPtr = getPointerToFunction(F);
|
||||
if (!FPtr)
|
||||
report_fatal_error("Unable to locate function: '" + F->getName() + "'");
|
||||
((void(*)(void))(intptr_t)FPtr)();
|
||||
assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
|
||||
const FunctionType *FTy = F->getFunctionType();
|
||||
const Type *RetTy = FTy->getReturnType();
|
||||
|
||||
assert((FTy->getNumParams() == ArgValues.size() ||
|
||||
(FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
|
||||
"Wrong number of arguments passed into function!");
|
||||
assert(FTy->getNumParams() == ArgValues.size() &&
|
||||
"This doesn't support passing arguments through varargs (yet)!");
|
||||
|
||||
// Handle some common cases first. These cases correspond to common `main'
|
||||
// prototypes.
|
||||
if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
|
||||
switch (ArgValues.size()) {
|
||||
case 3:
|
||||
if (FTy->getParamType(0)->isIntegerTy(32) &&
|
||||
FTy->getParamType(1)->isPointerTy() &&
|
||||
FTy->getParamType(2)->isPointerTy()) {
|
||||
int (*PF)(int, char **, const char **) =
|
||||
(int(*)(int, char **, const char **))(intptr_t)FPtr;
|
||||
|
||||
// Call the function.
|
||||
GenericValue rv;
|
||||
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
|
||||
(char **)GVTOP(ArgValues[1]),
|
||||
(const char **)GVTOP(ArgValues[2])));
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (FTy->getParamType(0)->isIntegerTy(32) &&
|
||||
FTy->getParamType(1)->isPointerTy()) {
|
||||
int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
|
||||
|
||||
// Call the function.
|
||||
GenericValue rv;
|
||||
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
|
||||
(char **)GVTOP(ArgValues[1])));
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (FTy->getNumParams() == 1 &&
|
||||
FTy->getParamType(0)->isIntegerTy(32)) {
|
||||
GenericValue rv;
|
||||
int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
|
||||
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle cases where no arguments are passed first.
|
||||
if (ArgValues.empty()) {
|
||||
GenericValue rv;
|
||||
switch (RetTy->getTypeID()) {
|
||||
default: llvm_unreachable("Unknown return type for function call!");
|
||||
case Type::IntegerTyID: {
|
||||
unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
|
||||
if (BitWidth == 1)
|
||||
rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
|
||||
else if (BitWidth <= 8)
|
||||
rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
|
||||
else if (BitWidth <= 16)
|
||||
rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
|
||||
else if (BitWidth <= 32)
|
||||
rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
|
||||
else if (BitWidth <= 64)
|
||||
rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
|
||||
else
|
||||
llvm_unreachable("Integer types > 64 bits not supported");
|
||||
return rv;
|
||||
}
|
||||
case Type::VoidTyID:
|
||||
rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
|
||||
return rv;
|
||||
case Type::FloatTyID:
|
||||
rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
|
||||
return rv;
|
||||
case Type::DoubleTyID:
|
||||
rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
|
||||
return rv;
|
||||
case Type::X86_FP80TyID:
|
||||
case Type::FP128TyID:
|
||||
case Type::PPC_FP128TyID:
|
||||
llvm_unreachable("long double not supported yet");
|
||||
return rv;
|
||||
case Type::PointerTyID:
|
||||
return PTOGV(((void*(*)())(intptr_t)FPtr)());
|
||||
}
|
||||
}
|
||||
|
||||
assert("Full-featured argument passing not supported yet!");
|
||||
return GenericValue();
|
||||
}
|
||||
|
@ -57,6 +57,16 @@ public:
|
||||
virtual GenericValue runFunction(Function *F,
|
||||
const std::vector<GenericValue> &ArgValues);
|
||||
|
||||
/// getPointerToNamedFunction - This method returns the address of the
|
||||
/// specified function by using the dlsym function call. As such it is only
|
||||
/// useful for resolving library symbols, not code generated symbols.
|
||||
///
|
||||
/// If AbortOnFailure is false and no function with the given name is
|
||||
/// found, this function silently returns a null pointer. Otherwise,
|
||||
/// it prints a message to stderr and aborts.
|
||||
///
|
||||
void *getPointerToNamedFunction(const std::string &Name,
|
||||
bool AbortOnFailure = true);
|
||||
/// @}
|
||||
/// @name (Private) Registration Interfaces
|
||||
/// @{
|
||||
|
Loading…
Reference in New Issue
Block a user