From 36143fc4440ac1fc2a0fc95a4999bcadc3ec207d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 8 Sep 2003 18:54:55 +0000 Subject: [PATCH] Add support for the unwind instruction git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8408 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/Lexer.l | 1 + lib/AsmParser/llvmAsmParser.y | 7 +++++-- lib/Bytecode/Reader/InstructionReader.cpp | 3 +++ lib/Target/CBackend/CBackend.cpp | 14 ++++++++++++++ lib/Target/CBackend/Writer.cpp | 14 ++++++++++++++ lib/Target/X86/InstSelectSimple.cpp | 5 +++++ lib/Target/X86/X86ISelSimple.cpp | 5 +++++ lib/Transforms/IPO/MutateStructTypes.cpp | 1 + lib/Transforms/Scalar/SCCP.cpp | 1 + 9 files changed, 49 insertions(+), 2 deletions(-) diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index a1566290a90..6e69262c5f2 100644 --- a/lib/AsmParser/Lexer.l +++ b/lib/AsmParser/Lexer.l @@ -229,6 +229,7 @@ ret { RET_TOK(TermOpVal, Ret, RET); } br { RET_TOK(TermOpVal, Br, BR); } switch { RET_TOK(TermOpVal, Switch, SWITCH); } invoke { RET_TOK(TermOpVal, Invoke, INVOKE); } +unwind { RET_TOK(TermOpVal, Unwind, UNWIND); } malloc { RET_TOK(MemOpVal, Malloc, MALLOC); } diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 6971ebe2f30..930f1aa4526 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -701,7 +701,7 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) { %token OPAQUE NOT EXTERNAL TARGET ENDIAN POINTERSIZE LITTLE BIG // Basic Block Terminating Operators -%token RET BR SWITCH +%token RET BR SWITCH INVOKE UNWIND // Binary Operators %type BinaryOps // all the binary operators @@ -714,7 +714,7 @@ Module *RunVMAsmParser(const std::string &Filename, FILE *F) { // Other Operators %type ShiftOps -%token PHI CALL INVOKE CAST SHL SHR VA_ARG +%token PHI CALL CAST SHL SHR VA_ARG %start Module %% @@ -1535,6 +1535,9 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... $$ = new InvokeInst(V, Normal, Except, *$5); } delete $5; + } + | UNWIND { + $$ = new UnwindInst(); }; diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp index 603c20564ca..8f256e4220e 100644 --- a/lib/Bytecode/Reader/InstructionReader.cpp +++ b/lib/Bytecode/Reader/InstructionReader.cpp @@ -421,6 +421,9 @@ bool BytecodeParser::ParseInstruction(const unsigned char *&Buf, Res = new StoreInst(getValue(ValTy, Raw.Arg1), Ptr, Raw.Opcode == 63); return false; } + case Instruction::Unwind: + if (Raw.NumOperands != 0) return true; + return new UnwindInst(); } // end switch(Raw.Opcode) std::cerr << "Unrecognized instruction! " << Raw.Opcode diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 721ead091c2..073ce19189f 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -117,6 +117,7 @@ namespace { void visitBranchInst(BranchInst &I); void visitSwitchInst(SwitchInst &I); void visitInvokeInst(InvokeInst &I); + void visitUnwindInst(UnwindInst &I); void visitPHINode(PHINode &I); void visitBinaryOperator(Instruction &I); @@ -980,6 +981,19 @@ void CWriter::visitInvokeInst(InvokeInst &II) { } +void CWriter::visitUnwindInst(UnwindInst &I) { + // The unwind instructions causes a control flow transfer out of the current + // function, unwinding the stack until a caller who used the invoke + // instruction is found. In this context, we code generated the invoke + // instruction to add an entry to the top of the jmpbuf_list. Thus, here we + // just have to longjmp to the specified handler. + Out << " if (__llvm_jmpbuf_list == 0) { /* llvm.unwind */\n" + << " printf(\"throw found with no handler!\\n\"); abort();\n" + << " }\n" + << " longjmp(__llvm_jmpbuf_list->buf, 1);\n"; + emittedInvoke = true; +} + static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) { // If PHI nodes need copies, we need the copy code... if (isa(To->front()) || diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 721ead091c2..073ce19189f 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -117,6 +117,7 @@ namespace { void visitBranchInst(BranchInst &I); void visitSwitchInst(SwitchInst &I); void visitInvokeInst(InvokeInst &I); + void visitUnwindInst(UnwindInst &I); void visitPHINode(PHINode &I); void visitBinaryOperator(Instruction &I); @@ -980,6 +981,19 @@ void CWriter::visitInvokeInst(InvokeInst &II) { } +void CWriter::visitUnwindInst(UnwindInst &I) { + // The unwind instructions causes a control flow transfer out of the current + // function, unwinding the stack until a caller who used the invoke + // instruction is found. In this context, we code generated the invoke + // instruction to add an entry to the top of the jmpbuf_list. Thus, here we + // just have to longjmp to the specified handler. + Out << " if (__llvm_jmpbuf_list == 0) { /* llvm.unwind */\n" + << " printf(\"throw found with no handler!\\n\"); abort();\n" + << " }\n" + << " longjmp(__llvm_jmpbuf_list->buf, 1);\n"; + emittedInvoke = true; +} + static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) { // If PHI nodes need copies, we need the copy code... if (isa(To->front()) || diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp index f754d11066f..6712d94f324 100644 --- a/lib/Target/X86/InstSelectSimple.cpp +++ b/lib/Target/X86/InstSelectSimple.cpp @@ -132,6 +132,7 @@ namespace { const std::vector &Args); void visitCallInst(CallInst &I); void visitInvokeInst(InvokeInst &II); + void visitUnwindInst(UnwindInst &UI); void visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &I); // Arithmetic operators @@ -1020,6 +1021,10 @@ void ISel::visitInvokeInst(InvokeInst &II) { BuildMI(BB, X86::JMP, 1).addPCDisp(II.getNormalDest()); } +void ISel::visitUnwindInst(UnwindInst &UI) { + // unwind is not supported yet! Just abort when the unwind inst is executed! + BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); +} void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2; diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp index f754d11066f..6712d94f324 100644 --- a/lib/Target/X86/X86ISelSimple.cpp +++ b/lib/Target/X86/X86ISelSimple.cpp @@ -132,6 +132,7 @@ namespace { const std::vector &Args); void visitCallInst(CallInst &I); void visitInvokeInst(InvokeInst &II); + void visitUnwindInst(UnwindInst &UI); void visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &I); // Arithmetic operators @@ -1020,6 +1021,10 @@ void ISel::visitInvokeInst(InvokeInst &II) { BuildMI(BB, X86::JMP, 1).addPCDisp(II.getNormalDest()); } +void ISel::visitUnwindInst(UnwindInst &UI) { + // unwind is not supported yet! Just abort when the unwind inst is executed! + BuildMI(BB, X86::CALLpcrel32, 1).addExternalSymbol("abort", true); +} void ISel::visitIntrinsicCall(LLVMIntrinsic::ID ID, CallInst &CI) { unsigned TmpReg1, TmpReg2; diff --git a/lib/Transforms/IPO/MutateStructTypes.cpp b/lib/Transforms/IPO/MutateStructTypes.cpp index 370b6be8940..2ea6938be25 100644 --- a/lib/Transforms/IPO/MutateStructTypes.cpp +++ b/lib/Transforms/IPO/MutateStructTypes.cpp @@ -352,6 +352,7 @@ void MutateStructTypes::transformFunction(Function *m) { } case Instruction::Switch: case Instruction::Invoke: + case Instruction::Unwind: assert(0 && "Insn not implemented!"); // Binary Instructions diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 5938c2a5851..b9aba13915d 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -196,6 +196,7 @@ private: markOverdefined(&I); visitTerminatorInst(I); } + void visitUnwindInst (TerminatorInst &I) { /*returns void*/ } void visitAllocationInst(Instruction &I) { markOverdefined(&I); } void visitVarArgInst (Instruction &I) { markOverdefined(&I); } void visitFreeInst (Instruction &I) { /*returns void*/ }