From f32a6a3091e0b01d17926f4b1cf78972854b8cb5 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 29 Oct 2009 05:26:09 +0000 Subject: [PATCH] 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 --- .../llvm/ExecutionEngine/ExecutionEngine.h | 6 ++++ lib/ExecutionEngine/ExecutionEngine.cpp | 5 ++- lib/ExecutionEngine/Interpreter/Execution.cpp | 31 ++++++++++++------- lib/ExecutionEngine/Interpreter/Interpreter.h | 2 ++ lib/ExecutionEngine/JIT/JIT.h | 4 +++ 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 47c10b328de..4b828e4666f 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -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 diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index c61ab875972..21499e5f64e 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(C)) Result = PTOGV(getPointerToFunctionOrStub(const_cast(F))); - else if (const GlobalVariable* GV = dyn_cast(C)) + else if (const GlobalVariable *GV = dyn_cast(C)) Result = PTOGV(getOrEmitGlobalVariable(const_cast(GV))); + else if (const BlockAddress *BA = dyn_cast(C)) + Result = PTOGV(getPointerToBasicBlock(const_cast( + 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 7ceb8e8c54b..01bd2c7f899 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 (Inst))); + Inst = ECStack.back().Caller.getInstruction(); + } while (!(Inst && isa(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(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 eaa8ec5c38b..038830cc082 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 1e907f181c9..a5b728a1c53 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.