From fc82fabe00b0b820e3c0d7fc9e289bace0295f11 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Sun, 2 Mar 2008 02:48:09 +0000 Subject: [PATCH] Add an unwind_to field to basic blocks, making them Users instead of Values. This is the first checkin for PR1269, the new EH infrastructure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47802 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/BasicBlock.h | 16 +++++++- include/llvm/Bitcode/LLVMBitCodes.h | 4 +- lib/AsmParser/LLLexer.cpp | 1 + lib/AsmParser/llvmAsmParser.y | 42 +++++++++++--------- lib/Bitcode/Reader/BitcodeReader.cpp | 9 +++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 9 ++++- lib/VMCore/AsmWriter.cpp | 23 ++++++++--- lib/VMCore/BasicBlock.cpp | 23 ++++++++++- test/Feature/unwindto.ll | 48 +++++++++++++++++++++++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 1 + 10 files changed, 146 insertions(+), 30 deletions(-) create mode 100644 test/Feature/unwindto.ll diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h index d99271b196e..5a1c5a45b2b 100644 --- a/include/llvm/BasicBlock.h +++ b/include/llvm/BasicBlock.h @@ -49,13 +49,14 @@ template<> struct ilist_traits /// modifying a program. However, the verifier will ensure that basic blocks /// are "well formed". /// @brief LLVM Basic Block Representation -class BasicBlock : public Value { // Basic blocks are data objects also +class BasicBlock : public User { // Basic blocks are data objects also public: typedef iplist InstListType; private : InstListType InstList; BasicBlock *Prev, *Next; // Next and Prev links for our intrusive linked list Function *Parent; + Use unwindDest; void setParent(Function *parent); void setNext(BasicBlock *N) { Next = N; } @@ -75,9 +76,20 @@ public: /// InsertBefore is null), or before the specified basic block. /// explicit BasicBlock(const std::string &Name = "", Function *Parent = 0, - BasicBlock *InsertBefore = 0); + BasicBlock *InsertBefore = 0, BasicBlock *unwindDest = 0); ~BasicBlock(); + /// getUnwindDest - Returns the BasicBlock that flow will enter if an unwind + /// instruction occurs in this block. May be null, in which case unwinding + /// is undefined in this block. + const BasicBlock *getUnwindDest() const; + BasicBlock *getUnwindDest(); + + /// setUnwindDest - Set which BasicBlock flow will enter if an unwind is + /// executed within this block. It may be set to null if unwinding is not + /// permitted in this block. + void setUnwindDest(BasicBlock *unwindDest); + /// getParent - Return the enclosing method, or null if none /// const Function *getParent() const { return Parent; } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 5ef832e187c..377ff420fd4 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -202,7 +202,9 @@ namespace bitc { // this is so information only available in the pointer type (e.g. address // spaces) is retained. FUNC_CODE_INST_STORE2 = 24, // STORE: [ptrty,ptr,val, align, vol] - FUNC_CODE_INST_GETRESULT = 25 // GETRESULT: [ty, opval, n] + FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n] + + FUNC_CODE_INST_BB_UNWINDDEST = 26 // BB_UNWINDDEST: [bb#] }; } // End bitc namespace } // End llvm namespace diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index f78079b6062..18b774b1820 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -474,6 +474,7 @@ int LLLexer::LexIdentifier() { KEYWORD("asm", ASM_TOK); KEYWORD("sideeffect", SIDEEFFECT); KEYWORD("gc", GC); + KEYWORD("unwind_to", UNWIND_TO); KEYWORD("cc", CC_TOK); KEYWORD("ccc", CCC_TOK); diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 5a824ae8fe4..c5640698de9 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -518,7 +518,7 @@ static Value *getVal(const Type *Ty, const ValID &ID) { /// defineBBVal - This is a definition of a new basic block with the specified /// identifier which must be the same as CurFun.NextValNum, if its numeric. -static BasicBlock *defineBBVal(const ValID &ID) { +static BasicBlock *defineBBVal(const ValID &ID, BasicBlock *unwindDest) { assert(inFunctionScope() && "Can't get basic block at global scope!"); BasicBlock *BB = 0; @@ -548,21 +548,19 @@ static BasicBlock *defineBBVal(const ValID &ID) { assert(ID.Num == CurFun.NextValNum && "Invalid new block number"); InsertValue(BB); } - - ID.destroy(); - return BB; - } - - // We haven't seen this BB before and its first mention is a definition. - // Just create it and return it. - std::string Name (ID.Type == ValID::LocalName ? ID.getName() : ""); - BB = new BasicBlock(Name, CurFun.CurrentFunction); - if (ID.Type == ValID::LocalID) { - assert(ID.Num == CurFun.NextValNum && "Invalid new block number"); - InsertValue(BB); + } else { + // We haven't seen this BB before and its first mention is a definition. + // Just create it and return it. + std::string Name (ID.Type == ValID::LocalName ? ID.getName() : ""); + BB = new BasicBlock(Name, CurFun.CurrentFunction); + if (ID.Type == ValID::LocalID) { + assert(ID.Num == CurFun.NextValNum && "Invalid new block number"); + InsertValue(BB); + } } - ID.destroy(); // Free strdup'd memory + ID.destroy(); + BB->setUnwindDest(unwindDest); return BB; } @@ -1066,7 +1064,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) { %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN ADDRSPACE %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT %token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK -%token DATALAYOUT +%token DATALAYOUT UNWIND_TO %type OptCallingConv %type OptParamAttrs ParamAttr %type OptFuncAttrs FuncAttr @@ -2568,14 +2566,22 @@ InstructionList : InstructionList Inst { CHECK_FOR_ERROR } | /* empty */ { // Empty space between instruction lists - $$ = defineBBVal(ValID::createLocalID(CurFun.NextValNum)); + $$ = defineBBVal(ValID::createLocalID(CurFun.NextValNum), 0); + CHECK_FOR_ERROR + } + | UNWIND_TO ValueRef { // Only the unwind to block + $$ = defineBBVal(ValID::createLocalID(CurFun.NextValNum), getBBVal($2)); CHECK_FOR_ERROR } | LABELSTR { // Labelled (named) basic block - $$ = defineBBVal(ValID::createLocalName(*$1)); + $$ = defineBBVal(ValID::createLocalName(*$1), 0); + delete $1; + CHECK_FOR_ERROR + } + | LABELSTR UNWIND_TO ValueRef { + $$ = defineBBVal(ValID::createLocalName(*$1), getBBVal($3)); delete $1; CHECK_FOR_ERROR - }; BBTerminatorInst : diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 61e0ab98989..c1cfa975a71 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1216,6 +1216,15 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { CurBB = FunctionBBs[0]; continue; + case bitc::FUNC_CODE_INST_BB_UNWINDDEST: // BB_UNWINDDEST: [bb#] + if (CurBB->getUnwindDest()) + return Error("Only permit one BB_UNWINDDEST per BB"); + if (Record.size() != 1) + return Error("Invalid BB_UNWINDDEST record"); + + CurBB->setUnwindDest(getBasicBlock(Record[0])); + continue; + case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode] unsigned OpNum = 0; Value *LHS, *RHS; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 5de38b82156..67b13e30bad 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -969,13 +969,20 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE, unsigned InstID = CstEnd; // Finally, emit all the instructions, in order. - for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (const BasicBlock *unwindDest = BB->getUnwindDest()) { + Vals.push_back(VE.getValueID(unwindDest)); + Stream.EmitRecord(bitc::FUNC_CODE_INST_BB_UNWINDDEST, Vals); + Vals.clear(); + } + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { WriteInstruction(*I, InstID, VE, Stream, Vals); if (I->getType() != Type::VoidTy) ++InstID; } + } // Emit names for all the instructions etc. WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 55d037db141..595f478c72a 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1130,7 +1130,7 @@ void AssemblyWriter::printFunction(const Function *F) { if (F->isDeclaration()) { Out << "\n"; } else { - Out << " {"; + Out << " {\n"; // Output all of its basic blocks... for the function for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) @@ -1162,10 +1162,19 @@ void AssemblyWriter::printArgument(const Argument *Arg, /// printBasicBlock - This member is called for each basic block in a method. /// void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { - if (BB->hasName()) { // Print out the label if it exists... - Out << "\n" << getLLVMName(BB->getName(), LabelPrefix) << ':'; - } else if (!BB->use_empty()) { // Don't print block # of no uses... - Out << "\n;