diff options
author | Chris Lattner <sabre@nondot.org> | 2009-10-29 05:26:09 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-10-29 05:26:09 +0000 |
commit | f32a6a3091e0b01d17926f4b1cf78972854b8cb5 (patch) | |
tree | 12a35a7b53cc71961a5eecc2913bb06842e142af /lib/ExecutionEngine | |
parent | 7a8b33a9a4da1724a652585ad805ea84a59b90e7 (diff) |
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
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 5 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Execution.cpp | 31 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.h | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.h | 4 |
4 files changed, 29 insertions, 13 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index c61ab87597..21499e5f64 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -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; diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 7ceb8e8c54..01bd2c7f89 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -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; diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index eaa8ec5c38..038830cc08 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -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(); diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index 1e907f181c..a5b728a1c5 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -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. |