mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
add interpreter support for indirect goto / blockaddress. The interpreter
now correctly runs clang's test/CodeGen/indirect-goto.c. The JIT will abort on it until someone feels compelled to implement this. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85488 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7a8b33a9a4
commit
f32a6a3091
@ -268,6 +268,12 @@ public:
|
||||
///
|
||||
virtual void *getPointerToFunction(Function *F) = 0;
|
||||
|
||||
/// getPointerToBasicBlock - The different EE's represent basic blocks in
|
||||
/// different ways. Return the representation for a blockaddress of the
|
||||
/// specified block.
|
||||
///
|
||||
virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0;
|
||||
|
||||
/// getPointerToFunctionOrStub - If the specified function has been
|
||||
/// code-gen'd, return a pointer to the function. If not, compile it, or use
|
||||
/// a stub to implement lazy compilation if available. See
|
||||
|
@ -760,8 +760,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||
Result.PointerVal = 0;
|
||||
else if (const Function *F = dyn_cast<Function>(C))
|
||||
Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F)));
|
||||
else if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C))
|
||||
else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
|
||||
Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV)));
|
||||
else if (const BlockAddress *BA = dyn_cast<BlockAddress>(C))
|
||||
Result = PTOGV(getPointerToBasicBlock(const_cast<BasicBlock*>(
|
||||
BA->getBasicBlock())));
|
||||
else
|
||||
llvm_unreachable("Unknown constant pointer type!");
|
||||
break;
|
||||
|
@ -572,9 +572,9 @@ void Interpreter::exitCalled(GenericValue GV) {
|
||||
// runAtExitHandlers() assumes there are no stack frames, but
|
||||
// if exit() was called, then it had a stack frame. Blow away
|
||||
// the stack before interpreting atexit handlers.
|
||||
ECStack.clear ();
|
||||
runAtExitHandlers ();
|
||||
exit (GV.IntVal.zextOrTrunc(32).getZExtValue());
|
||||
ECStack.clear();
|
||||
runAtExitHandlers();
|
||||
exit(GV.IntVal.zextOrTrunc(32).getZExtValue());
|
||||
}
|
||||
|
||||
/// Pop the last stack frame off of ECStack and then copy the result
|
||||
@ -585,8 +585,8 @@ void Interpreter::exitCalled(GenericValue GV) {
|
||||
/// care of switching to the normal destination BB, if we are returning
|
||||
/// from an invoke.
|
||||
///
|
||||
void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy,
|
||||
GenericValue Result) {
|
||||
void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy,
|
||||
GenericValue Result) {
|
||||
// Pop the current stack frame.
|
||||
ECStack.pop_back();
|
||||
|
||||
@ -629,15 +629,15 @@ void Interpreter::visitUnwindInst(UnwindInst &I) {
|
||||
// Unwind stack
|
||||
Instruction *Inst;
|
||||
do {
|
||||
ECStack.pop_back ();
|
||||
if (ECStack.empty ())
|
||||
ECStack.pop_back();
|
||||
if (ECStack.empty())
|
||||
llvm_report_error("Empty stack during unwind!");
|
||||
Inst = ECStack.back ().Caller.getInstruction ();
|
||||
} while (!(Inst && isa<InvokeInst> (Inst)));
|
||||
Inst = ECStack.back().Caller.getInstruction();
|
||||
} while (!(Inst && isa<InvokeInst>(Inst)));
|
||||
|
||||
// Return from invoke
|
||||
ExecutionContext &InvokingSF = ECStack.back ();
|
||||
InvokingSF.Caller = CallSite ();
|
||||
ExecutionContext &InvokingSF = ECStack.back();
|
||||
InvokingSF.Caller = CallSite();
|
||||
|
||||
// Go to exceptional destination BB of invoke instruction
|
||||
SwitchToNewBasicBlock(cast<InvokeInst>(Inst)->getUnwindDest(), InvokingSF);
|
||||
@ -678,6 +678,13 @@ void Interpreter::visitSwitchInst(SwitchInst &I) {
|
||||
SwitchToNewBasicBlock(Dest, SF);
|
||||
}
|
||||
|
||||
void Interpreter::visitIndirectBrInst(IndirectBrInst &I) {
|
||||
ExecutionContext &SF = ECStack.back();
|
||||
void *Dest = GVTOP(getOperandValue(I.getAddress(), SF));
|
||||
SwitchToNewBasicBlock((BasicBlock*)Dest, SF);
|
||||
}
|
||||
|
||||
|
||||
// SwitchToNewBasicBlock - This method is used to jump to a new basic block.
|
||||
// This function handles the actual updating of block and instruction iterators
|
||||
// as well as execution of all of the PHI nodes in the destination block.
|
||||
@ -827,7 +834,7 @@ void Interpreter::visitCallSite(CallSite CS) {
|
||||
|
||||
// Check to see if this is an intrinsic function call...
|
||||
Function *F = CS.getCalledFunction();
|
||||
if (F && F->isDeclaration ())
|
||||
if (F && F->isDeclaration())
|
||||
switch (F->getIntrinsicID()) {
|
||||
case Intrinsic::not_intrinsic:
|
||||
break;
|
||||
|
@ -135,6 +135,7 @@ public:
|
||||
void visitReturnInst(ReturnInst &I);
|
||||
void visitBranchInst(BranchInst &I);
|
||||
void visitSwitchInst(SwitchInst &I);
|
||||
void visitIndirectBrInst(IndirectBrInst &I);
|
||||
|
||||
void visitBinaryOperator(BinaryOperator &I);
|
||||
void visitICmpInst(ICmpInst &I);
|
||||
@ -202,6 +203,7 @@ private: // Helper functions
|
||||
void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF);
|
||||
|
||||
void *getPointerToFunction(Function *F) { return (void*)F; }
|
||||
void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; }
|
||||
|
||||
void initializeExecutionEngine() { }
|
||||
void initializeExternalFunctions();
|
||||
|
@ -128,6 +128,10 @@ public:
|
||||
///
|
||||
void *getPointerToFunction(Function *F);
|
||||
|
||||
void *getPointerToBasicBlock(BasicBlock *BB) {
|
||||
assert(0 && "JIT does not support address-of-label yet!");
|
||||
}
|
||||
|
||||
/// getOrEmitGlobalVariable - Return the address of the specified global
|
||||
/// variable, possibly emitting it to memory if needed. This is used by the
|
||||
/// Emitter.
|
||||
|
Loading…
Reference in New Issue
Block a user