From c28c7fb134b7a48dc7a26b6040319d74f2f89c9c Mon Sep 17 00:00:00 2001 From: kai Date: Sun, 28 Jul 2013 23:32:51 +0200 Subject: [PATCH] Introduce a debug info builder. Moves all code from todebug into a new class. Also caches the compilation unit in order to fix a LLVM 3.4 compile error. --- gen/asmstmt.cpp | 3 +- gen/declarations.cpp | 3 +- gen/{todebug.cpp => dibuilder.cpp} | 554 +++++++++++++---------------- gen/dibuilder.h | 184 ++++++++++ gen/functions.cpp | 11 +- gen/irstate.cpp | 2 +- gen/irstate.h | 8 +- gen/llvmhelpers.cpp | 9 +- gen/module.cpp | 11 +- gen/nested.cpp | 15 +- gen/statements.cpp | 109 +++--- gen/todebug.h | 95 ----- gen/toir.cpp | 1 - ir/irlandingpad.cpp | 9 +- 14 files changed, 521 insertions(+), 493 deletions(-) rename gen/{todebug.cpp => dibuilder.cpp} (51%) create mode 100644 gen/dibuilder.h delete mode 100644 gen/todebug.h diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 2108fa91..56ab74e3 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -35,7 +35,6 @@ #include "gen/dvalue.h" #include "gen/tollvm.h" #include "gen/logger.h" -#include "gen/todebug.h" #include "gen/llvmhelpers.h" #include "gen/functions.h" @@ -230,7 +229,7 @@ AsmStatement::toIR(IRState * irs) assert(asmblock); // debug info - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); if (!asmcode) return; diff --git a/gen/declarations.cpp b/gen/declarations.cpp index dcb710bb..5357baac 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -18,7 +18,6 @@ #include "gen/llvm.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "ir/ir.h" #include "ir/irtype.h" @@ -190,7 +189,7 @@ void VarDeclaration::codegen(Ir* p) gvar->setInitializer(initVal); // Also set up the edbug info. - DtoDwarfGlobalVariable(gvar, this); + gIR->DBuilder.EmitGlobalVariable(gvar, this); } // Set the alignment (it is important not to use type->alignsize because diff --git a/gen/todebug.cpp b/gen/dibuilder.cpp similarity index 51% rename from gen/todebug.cpp rename to gen/dibuilder.cpp index fc55a4a4..2437f1fd 100644 --- a/gen/todebug.cpp +++ b/gen/dibuilder.cpp @@ -1,92 +1,92 @@ -//===-- todebug.cpp -------------------------------------------------------===// +//===-- gen/dibuilder.h - Debug information builder -------------*- C++ -*-===// // -// LDC – the LLVM D compiler +// LDC – the LLVM D compiler // // This file is distributed under the BSD-style LDC license. See the LICENSE // file for details. // //===----------------------------------------------------------------------===// -#include "gen/todebug.h" -#include "arraytypes.h" -#include "declaration.h" -#include "dsymbol.h" -#include "enum.h" -#include "mars.h" -#include "module.h" -#include "mtype.h" +#include "gen/dibuilder.h" #include "gen/irstate.h" -#include "gen/linkage.h" -#include "gen/llvm.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/tollvm.h" #include "gen/utils.h" -#include "ir/irmodule.h" #include "ir/irtypeaggr.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/Support/Dwarf.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "enum.h" +#include "module.h" +#include "mtype.h" -using namespace llvm::dwarf; - -////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // get the module the symbol is in, or - for template instances - the current module -static Module* getDefinedModule(Dsymbol* s) +Module *ldc::DIBuilder::getDefinedModule(Dsymbol *s) { // templates are defined in current module if (DtoIsTemplateInstance(s, true)) { - return gIR->dmodule; + return IR->dmodule; } // array operations as well else if (FuncDeclaration* fd = s->isFuncDeclaration()) { if (fd->isArrayOp == 1) - return gIR->dmodule; + return IR->dmodule; } // otherwise use the symbol's module return s->getModule(); } -////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// -static llvm::DIDescriptor getCurrentScope() +ldc::DIBuilder::DIBuilder(IRState *const IR, llvm::Module &M) + : IR(IR), DBuilder(M) { - IrFunction *fn = gIR->func(); - if (fn->diLexicalBlocks.empty()) { - assert(static_cast(fn->diSubprogram) != 0); +} + +llvm::LLVMContext &ldc::DIBuilder::getContext() +{ + return IR->context(); +} + +llvm::DIDescriptor ldc::DIBuilder::GetCurrentScope() +{ + IrFunction *fn = IR->func(); + if (fn->diLexicalBlocks.empty()) + { + assert(static_cast(fn->diSubprogram) != 0); return fn->diSubprogram; } return fn->diLexicalBlocks.top(); } -////////////////////////////////////////////////////////////////////////////////////////////////// +void ldc::DIBuilder::Declare(llvm::Value *var, llvm::DIVariable divar) +{ + llvm::Instruction *instr = DBuilder.insertDeclare(var, divar, IR->scopebb()); + instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); +} -static llvm::DIType dwarfTypeDescription_impl(Type* type, const char* c_name); -static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name); - -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIFile DtoDwarfFile(Loc loc) +llvm::DIFile ldc::DIBuilder::CreateFile(Loc loc) { llvm::SmallString<128> path(loc.filename ? loc.filename : ""); llvm::sys::fs::make_absolute(path); - return gIR->dibuilder.createFile( + return DBuilder.createFile( llvm::sys::path::filename(path), llvm::sys::path::parent_path(path) ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfBasicType(Type* type) +llvm::DIType ldc::DIBuilder::CreateBasicType(Type *type) { - Type* t = type->toBasetype(); - LLType* T = DtoType(type); + using namespace llvm::dwarf; + + Type *t = type->toBasetype(); + llvm::Type *T = DtoType(type); // find encoding unsigned Encoding; @@ -131,10 +131,10 @@ static llvm::DIType dwarfBasicType(Type* type) Encoding = DW_ATE_complex_float; break; default: - llvm_unreachable("Unsupported basic type for debug info"); + llvm_unreachable("Unsupported basic type for debug info in DIBuilder::CreateBasicType"); } - return gIR->dibuilder.createBasicType( + return DBuilder.createBasicType( type->toChars(), // name getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) @@ -142,9 +142,7 @@ static llvm::DIType dwarfBasicType(Type* type) ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfEnumType(Type *type) +llvm::DIType ldc::DIBuilder::CreateEnumType(Type *type) { llvm::Type *T = DtoType(type); @@ -154,47 +152,44 @@ static llvm::DIType dwarfEnumType(Type *type) for (ArrayIter it(te->sym->members); it.more(); it.next()) { EnumMember *em = it->isEnumMember(); - llvm::StringRef Name(em->toChars() /*em->ident->string*/); + llvm::StringRef Name(em->toChars()); uint64_t Val = em->value->toInteger(); - llvm::Value *Subscript = gIR->dibuilder.createEnumerator(Name, Val); + llvm::Value *Subscript = DBuilder.createEnumerator(Name, Val); subscripts.push_back(Subscript); } llvm::StringRef Name = te->toChars(); unsigned LineNumber = te->sym->loc.linnum; - llvm::DIFile File = DtoDwarfFile(te->sym->loc); + llvm::DIFile File = CreateFile(te->sym->loc); - return gIR->dibuilder.createEnumerationType( - llvm::DICompileUnit(gIR->dibuilder.getCU()), + return DBuilder.createEnumerationType( + llvm::DICompileUnit(GetCU()), Name, File, LineNumber, getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) - gIR->dibuilder.getOrCreateArray(subscripts) // subscripts + DBuilder.getOrCreateArray(subscripts) // subscripts #if LDC_LLVM_VER >= 302 - , dwarfTypeDescription_impl(te->sym->memtype, NULL) + , CreateTypeDescription(te->sym->memtype, NULL) #endif ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfPointerType(Type* type) +llvm::DIType ldc::DIBuilder::CreatePointerType(Type *type) { - LLType* T = DtoType(type); - Type* t = type->toBasetype(); + llvm::Type *T = DtoType(type); + Type *t = type->toBasetype(); - assert(t->ty == Tpointer && "only pointers allowed for debug info in dwarfPointerType"); + assert(t->ty == Tpointer && "Only pointers allowed for debug info in DIBuilder::CreatePointerType"); // find base type - llvm::DIType basetype; - Type* nt = t->nextOf(); - basetype = dwarfTypeDescription_impl(nt, NULL); + Type *nt = t->nextOf(); + llvm::DIType basetype = CreateTypeDescription(nt, NULL); if (nt->ty == Tvoid) basetype = llvm::DIType(NULL); - return gIR->dibuilder.createPointerType( + return DBuilder.createPointerType( basetype, getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) @@ -202,46 +197,44 @@ static llvm::DIType dwarfPointerType(Type* type) ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfVectorType(Type* type) +llvm::DIType ldc::DIBuilder::CreateVectorType(Type *type) { LLType* T = DtoType(type); Type* t = type->toBasetype(); - assert(t->ty == Tvector && "only vectors allowed for debug info in dwarfVectorType"); + assert(t->ty == Tvector && "Only vectors allowed for debug info in DIBuilder::CreateVectorType"); TypeVector *tv = static_cast(t); Type *te = tv->elementType(); int64_t Dim = tv->size(Loc()) / te->size(Loc()); llvm::Value *subscripts[] = { - gIR->dibuilder.getOrCreateSubrange(0, Dim) + DBuilder.getOrCreateSubrange(0, Dim) }; - llvm::DIType basetype = dwarfTypeDescription_impl(te, NULL); + llvm::DIType basetype = CreateTypeDescription(te, NULL); - return gIR->dibuilder.createVectorType( + return DBuilder.createVectorType( getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) basetype, // element type - gIR->dibuilder.getOrCreateArray(subscripts) // subscripts + DBuilder.getOrCreateArray(subscripts) // subscripts ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfMemberType(unsigned linnum, Type* type, llvm::DIFile file, const char* c_name, unsigned offset) +llvm::DIType ldc::DIBuilder::CreateMemberType(unsigned linnum, Type *type, + llvm::DIFile file, + const char* c_name, + unsigned offset) { - LLType* T = DtoType(type); - Type* t = type->toBasetype(); + llvm::Type *T = DtoType(type); + Type *t = type->toBasetype(); // find base type - llvm::DIType basetype; - basetype = dwarfTypeDescription(t, NULL); + llvm::DIType basetype = CreateTypeDescription(t, NULL, true); if (t->ty == Tvoid) basetype = llvm::DIType(NULL); - return gIR->dibuilder.createMemberType( - llvm::DICompileUnit(gIR->dibuilder.getCU()), + return DBuilder.createMemberType( + llvm::DICompileUnit(GetCU()), c_name, // name file, // file linnum, // line number @@ -254,16 +247,12 @@ static llvm::DIType dwarfMemberType(unsigned linnum, Type* type, llvm::DIFile fi ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static void add_base_fields( - ClassDeclaration* sd, - llvm::DIFile file, - std::vector& elems) +void ldc::DIBuilder::AddBaseFields(ClassDeclaration *sd, llvm::DIFile file, + std::vector &elems) { if (sd->baseClass) { - add_base_fields(sd->baseClass, file, elems); + AddBaseFields(sd->baseClass, file, elems); } ArrayIter it(sd->fields); @@ -272,16 +261,15 @@ static void add_base_fields( for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); - elems.push_back(dwarfMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset)); + elems.push_back(CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset)); } } - -static llvm::DIType dwarfCompositeType(Type* type) +llvm::DIType ldc::DIBuilder::CreateCompositeType(Type *type) { Type* t = type->toBasetype(); assert((t->ty == Tstruct || t->ty == Tclass) && - "unsupported type for dwarfCompositeType"); + "Unsupported type for debug info in DIBuilder::CreateCompositeType"); AggregateDeclaration* sd; if (t->ty == Tstruct) { @@ -296,12 +284,12 @@ static llvm::DIType dwarfCompositeType(Type* type) assert(sd); // Use the actual type associated with the declaration, ignoring any - // const/… wrappers. - LLType* T = DtoType(sd->type); - IrTypeAggr* ir = sd->type->irtype->isAggr(); + // const/… wrappers. + LLType *T = DtoType(sd->type); + IrTypeAggr *ir = sd->type->irtype->isAggr(); assert(ir); - if (static_cast(ir->diCompositeType) != 0) + if (static_cast(ir->diCompositeType) != 0) return ir->diCompositeType; // if we don't know the aggregate's size, we don't know enough about it @@ -310,22 +298,22 @@ static llvm::DIType dwarfCompositeType(Type* type) return llvm::DICompositeType(NULL); // elements - std::vector elems; + std::vector elems; // defaults llvm::StringRef name = sd->toChars(); unsigned linnum = sd->loc.linnum; - llvm::DICompileUnit CU(gIR->dibuilder.getCU()); + llvm::DICompileUnit CU(GetCU()); assert(CU && CU.Verify() && "Compilation unit missing or corrupted"); - llvm::DIFile file = DtoDwarfFile(sd->loc); + llvm::DIFile file = CreateFile(sd->loc); llvm::DIType derivedFrom; // set diCompositeType to handle recursive types properly unsigned tag = (t->ty == Tstruct) ? llvm::dwarf::DW_TAG_structure_type : llvm::dwarf::DW_TAG_class_type; - ir->diCompositeType = gIR->dibuilder.createForwardDecl(tag, name, + ir->diCompositeType = DBuilder.createForwardDecl(tag, name, #if LDC_LLVM_VER >= 302 - llvm::DICompileUnit(gIR->dibuilder.getCU()), + CU, #endif file, linnum); @@ -339,24 +327,24 @@ static llvm::DIType dwarfCompositeType(Type* type) for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); - llvm::DIType dt = dwarfMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset); + llvm::DIType dt = CreateMemberType(vd->loc.linnum, vd->type, file, vd->toChars(), vd->offset); elems.push_back(dt); } } else { ClassDeclaration *classDecl = sd->isClassDeclaration(); - add_base_fields(classDecl, file, elems); + AddBaseFields(classDecl, file, elems); if (classDecl->baseClass) - derivedFrom = dwarfCompositeType(classDecl->baseClass->getType()); + derivedFrom = CreateCompositeType(classDecl->baseClass->getType()); } } - llvm::DIArray elemsArray = gIR->dibuilder.getOrCreateArray(elems); + llvm::DIArray elemsArray = DBuilder.getOrCreateArray(elems); llvm::DIType ret; if (t->ty == Tclass) { - ret = gIR->dibuilder.createClassType( + ret = DBuilder.createClassType( CU, // compile unit where defined name, // name file, // file where defined @@ -369,7 +357,7 @@ static llvm::DIType dwarfCompositeType(Type* type) elemsArray ); } else { - ret = gIR->dibuilder.createStructType( + ret = DBuilder.createStructType( CU, // compile unit where defined name, // name file, // file where defined @@ -390,53 +378,25 @@ static llvm::DIType dwarfCompositeType(Type* type) return ret; } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIGlobalVariable dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) +llvm::DIType ldc::DIBuilder::CreateArrayType(Type *type) { - assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init)); + llvm::Type *T = DtoType(type); + Type *t = type->toBasetype(); - return gIR->dibuilder.createGlobalVariable( - vd->toChars(), // name -#if LDC_LLVM_VER >= 303 - vd->mangle(), // linkage name -#endif - DtoDwarfFile(vd->loc), // file - vd->loc.linnum, // line num - dwarfTypeDescription_impl(vd->type, NULL), // type - vd->protection == PROTprivate, // is local to unit - ll // value - ); -} + assert(t->ty == Tarray && "Only arrays allowed for debug info in DIBuilder::CreateArrayType"); + llvm::DIFile file = CreateFile(Loc(IR->dmodule, 0)); -////////////////////////////////////////////////////////////////////////////////////////////////// - -static void dwarfDeclare(LLValue* var, llvm::DIVariable divar) -{ - llvm::Instruction *instr = gIR->dibuilder.insertDeclare(var, divar, gIR->scopebb()); - instr->setDebugLoc(gIR->ir->getCurrentDebugLocation()); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - - -static llvm::DIType dwarfArrayType(Type* type) { - LLType* T = DtoType(type); - Type* t = type->toBasetype(); - - llvm::DIFile file = DtoDwarfFile(Loc(gIR->dmodule, 0)); - - llvm::Value* elems[] = { - dwarfMemberType(0, Type::tsize_t, file, "length", 0), - dwarfMemberType(0, t->nextOf()->pointerTo(), file, "ptr", - global.params.is64bit ? 8 : 4) + llvm::Value *elems[] = { + CreateMemberType(0, Type::tsize_t, file, "length", 0), + CreateMemberType(0, t->nextOf()->pointerTo(), file, "ptr", + global.params.is64bit ? 8 : 4) }; - return gIR->dibuilder.createStructType + return DBuilder.createStructType ( - llvm::DICompileUnit(gIR->dibuilder.getCU()), - llvm::StringRef(), // Name TODO: Really no name for arrays? + llvm::DICompileUnit(GetCU()), + llvm::StringRef(), // Name TODO: Really no name for arrays? t->toChars()? file, // File 0, // LineNo getTypeBitSize(T), // size in bits @@ -445,14 +405,11 @@ static llvm::DIType dwarfArrayType(Type* type) { #if LDC_LLVM_VER >= 303 llvm::DIType(), // DerivedFrom #endif - gIR->dibuilder.getOrCreateArray(elems) + DBuilder.getOrCreateArray(elems) ); - } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfSArrayType(Type *type) +llvm::DIType ldc::DIBuilder::CreateSArrayType(Type *type) { llvm::Type *T = DtoType(type); Type *t = type->toBasetype(); @@ -463,113 +420,56 @@ static llvm::DIType dwarfSArrayType(Type *type) { TypeSArray *tsa = static_cast(t); int64_t Count = tsa->dim->toInteger(); - llvm::Value *subscript = gIR->dibuilder.getOrCreateSubrange(0, Count-1); + llvm::Value *subscript = DBuilder.getOrCreateSubrange(0, Count-1); subscripts.push_back(subscript); t = t->nextOf(); } - llvm::DIType basetype = dwarfTypeDescription_impl(t, NULL); + llvm::DIType basetype = CreateTypeDescription(t, NULL); - return gIR->dibuilder.createArrayType( + return DBuilder.createArrayType( getTypeBitSize(T), // size (bits) getABITypeAlign(T)*8, // align (bits) basetype, // element type - gIR->dibuilder.getOrCreateArray(subscripts) // subscripts + DBuilder.getOrCreateArray(subscripts) // subscripts ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -static llvm::DIType dwarfTypeDescription_impl(Type* type, const char* c_name) +llvm::DIType ldc::DIBuilder::CreateTypeDescription(Type* type, + const char* c_name, + bool derefclass) { - Type* t = type->toBasetype(); + Type *t = type->toBasetype(); + if (derefclass && t->ty == Tclass) + { + type = type->pointerTo(); + t = type->toBasetype(); + } + if (t->ty == Tvoid) return llvm::DIType(NULL); else if (t->isintegral() || t->isfloating()) { if (t->ty == Tvector) - return dwarfVectorType(type); + return CreateVectorType(type); if (type->ty == Tenum) - return dwarfEnumType(type); - return dwarfBasicType(type); + return CreateEnumType(type); + return CreateBasicType(type); } else if (t->ty == Tpointer) - return dwarfPointerType(type); + return CreatePointerType(type); else if (t->ty == Tarray) - return dwarfArrayType(type); + return CreateArrayType(type); else if (t->ty == Tsarray) - return dwarfSArrayType(type); + return CreateSArrayType(type); else if (t->ty == Tstruct || t->ty == Tclass) - return dwarfCompositeType(type); + return CreateCompositeType(type); return llvm::DIType(NULL); } -static llvm::DIType dwarfTypeDescription(Type* type, const char* c_name) -{ - Type* t = type->toBasetype(); - if (t->ty == Tclass) - return dwarfTypeDescription_impl(type->pointerTo(), c_name); - else - return dwarfTypeDescription_impl(type, c_name); -} +//////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, llvm::ArrayRef addr) -{ - if (!global.params.symdebug) - return; - - Logger::println("D to dwarf local variable"); - LOG_SCOPE; - - if (gIR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once - return; - - // get type description - llvm::DIType TD = dwarfTypeDescription(vd->type, NULL); - if (static_cast(TD) == 0) - return; // unsupported - - // get variable description - assert(!vd->isDataseg() && "static variable"); - - unsigned tag; - if (vd->isParameter()) - tag = DW_TAG_arg_variable; - else - tag = DW_TAG_auto_variable; - - if (addr.empty()) { - vd->debugVariable = gIR->dibuilder.createLocalVariable( - tag, // tag - getCurrentScope(), // scope - vd->toChars(), // name - DtoDwarfFile(vd->loc), // file - vd->loc.linnum, // line num - TD, // type - true // preserve - ); - } else { - vd->debugVariable = gIR->dibuilder.createComplexVariable( - tag, // tag - getCurrentScope(), // scope - vd->toChars(), // name - DtoDwarfFile(vd->loc), // file - vd->loc.linnum, // line num - TD, // type - addr - ); - } - vd->debugFunc = gIR->func()->diSubprogram; - - // declare - dwarfDeclare(ll, vd->debugVariable); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfCompileUnit(Module* m) +void ldc::DIBuilder::EmitCompileUnit(Module *m) { if (!global.params.symdebug) return; @@ -581,8 +481,12 @@ void DtoDwarfCompileUnit(Module* m) llvm::SmallString<128> srcpath(m->srcfile->name->toChars()); llvm::sys::fs::make_absolute(srcpath); - gIR->dibuilder.createCompileUnit( - global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D, +#if LDC_LLVM_VER >= 304 + CUNode = +#endif + DBuilder.createCompileUnit( + global.params.symdebug == 2 ? llvm::dwarf::DW_LANG_C + : llvm::dwarf::DW_LANG_D, llvm::sys::path::filename(srcpath), llvm::sys::path::parent_path(srcpath), "LDC (http://wiki.dlang.org/LDC)", @@ -590,11 +494,12 @@ void DtoDwarfCompileUnit(Module* m) llvm::StringRef(), // Flags TODO 1 // Runtime Version TODO ); +#if LDC_LLVM_VER < 304 + CUNode = DBuilder.getCU(); +#endif } -////////////////////////////////////////////////////////////////////////////////////////////////// - -llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) +llvm::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) { if (!global.params.symdebug) return llvm::DISubprogram(); @@ -602,25 +507,25 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) Logger::println("D to dwarf subprogram"); LOG_SCOPE; - llvm::DICompileUnit CU(gIR->dibuilder.getCU()); - assert(CU && CU.Verify() && "Compilation unit missing or corrupted"); + llvm::DICompileUnit CU(GetCU()); + assert(CU && CU.Verify() && "Compilation unit missing or corrupted in DIBuilder::EmitSubProgram"); - llvm::DIFile file = DtoDwarfFile(fd->loc); + llvm::DIFile file = CreateFile(fd->loc); Type *retType = static_cast(fd->type)->next; // Create "dummy" subroutine type for the return type llvm::SmallVector Elts; - Elts.push_back(dwarfTypeDescription(retType, NULL)); - llvm::DIArray EltTypeArray = gIR->dibuilder.getOrCreateArray(Elts); + Elts.push_back(CreateTypeDescription(retType, NULL, true)); + llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); #if LDC_LLVM_VER >= 304 llvm::DICompositeType #else - llvm::DIType + llvm::DIType #endif - DIFnType = gIR->dibuilder.createSubroutineType(file, EltTypeArray); + DIFnType = DBuilder.createSubroutineType(file, EltTypeArray); // FIXME: duplicates ? - return gIR->dibuilder.createFunction( + return DBuilder.createFunction( CU, // context fd->toPrettyChars(), // name fd->mangle(), // linkage name @@ -628,7 +533,7 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) fd->loc.linnum, // line no DIFnType, // type fd->protection == PROTprivate, // is local to unit - gIR->dmodule == getDefinedModule(fd), // isdefinition + IR->dmodule == getDefinedModule(fd), // isdefinition fd->loc.linnum, // FIXME: scope line 0, // Flags false, // isOptimized @@ -636,9 +541,8 @@ llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname) +llvm::DISubprogram ldc::DIBuilder::EmitSubProgramInternal(llvm::StringRef prettyname, + llvm::StringRef mangledname) { if (!global.params.symdebug) return llvm::DISubprogram(); @@ -646,21 +550,21 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char Logger::println("D to dwarf subprogram"); LOG_SCOPE; - llvm::DIFile file(DtoDwarfFile(Loc(gIR->dmodule, 0))); + llvm::DIFile file(CreateFile(Loc(IR->dmodule, 0))); // Create "dummy" subroutine type for the return type - llvm::SmallVector Elts; + llvm::SmallVector Elts; Elts.push_back(llvm::DIType(NULL)); - llvm::DIArray EltTypeArray = gIR->dibuilder.getOrCreateArray(Elts); + llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts); #if LDC_LLVM_VER >= 304 - llvm::DICompositeType + llvm::DICompositeType #else llvm::DIType #endif - DIFnType = gIR->dibuilder.createSubroutineType(file, EltTypeArray); + DIFnType = DBuilder.createSubroutineType(file, EltTypeArray); // FIXME: duplicates ? - return gIR->dibuilder.createFunction( + return DBuilder.createFunction( llvm::DIDescriptor(file), // context prettyname, // name mangledname, // linkage name @@ -673,23 +577,7 @@ llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char ); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) -{ - if (!global.params.symdebug) - return llvm::DIGlobalVariable(); - - Logger::println("D to dwarf global_variable"); - LOG_SCOPE; - - // FIXME: duplicates ? - return dwarfGlobalVariable(ll, vd); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfFuncStart(FuncDeclaration* fd) +void ldc::DIBuilder::EmitFuncStart(FuncDeclaration *fd) { if (!global.params.symdebug) return; @@ -697,13 +585,11 @@ void DtoDwarfFuncStart(FuncDeclaration* fd) Logger::println("D to dwarf funcstart"); LOG_SCOPE; - assert(static_cast(fd->ir.irFunc->diSubprogram) != 0); - DtoDwarfStopPoint(fd->loc.linnum); + assert(static_cast(fd->ir.irFunc->diSubprogram) != 0); + EmitStopPoint(fd->loc.linnum); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfFuncEnd(FuncDeclaration* fd) +void ldc::DIBuilder::EmitFuncEnd(FuncDeclaration *fd) { if (!global.params.symdebug) return; @@ -711,12 +597,10 @@ void DtoDwarfFuncEnd(FuncDeclaration* fd) Logger::println("D to dwarf funcend"); LOG_SCOPE; - assert(static_cast(fd->ir.irFunc->diSubprogram) != 0); + assert(static_cast(fd->ir.irFunc->diSubprogram) != 0); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfBlockStart(Loc loc) +void ldc::DIBuilder::EmitBlockStart(Loc loc) { if (!global.params.symdebug) return; @@ -724,19 +608,17 @@ void DtoDwarfBlockStart(Loc loc) Logger::println("D to dwarf block start"); LOG_SCOPE; - llvm::DILexicalBlock block = gIR->dibuilder.createLexicalBlock( - getCurrentScope(), // scope - DtoDwarfFile(loc), // file + llvm::DILexicalBlock block = DBuilder.createLexicalBlock( + GetCurrentScope(), // scope + CreateFile(loc), // file loc.linnum, // line 0 // column ); - gIR->func()->diLexicalBlocks.push(block); - DtoDwarfStopPoint(loc.linnum); + IR->func()->diLexicalBlocks.push(block); + EmitStopPoint(loc.linnum); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfBlockEnd() +void ldc::DIBuilder::EmitBlockEnd() { if (!global.params.symdebug) return; @@ -744,41 +626,111 @@ void DtoDwarfBlockEnd() Logger::println("D to dwarf block end"); LOG_SCOPE; - IrFunction *fn = gIR->func(); + IrFunction *fn = IR->func(); assert(!fn->diLexicalBlocks.empty()); fn->diLexicalBlocks.pop(); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfStopPoint(unsigned ln) +void ldc::DIBuilder::EmitStopPoint(unsigned ln) { if (!global.params.symdebug) return; Logger::println("D to dwarf stoppoint at line %u", ln); LOG_SCOPE; - llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, getCurrentScope()); - gIR->ir->SetCurrentDebugLocation(loc); + llvm::DebugLoc loc = llvm::DebugLoc::get(ln, 0, GetCurrentScope()); + IR->ir->SetCurrentDebugLocation(loc); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfValue(LLValue *val, VarDeclaration* vd) +void ldc::DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) { if (!global.params.symdebug || !vd->debugVariable) return; - llvm::Instruction *instr = gIR->dibuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, gIR->scopebb()); - instr->setDebugLoc(gIR->ir->getCurrentDebugLocation()); + llvm::Instruction *instr = DBuilder.insertDbgValueIntrinsic(val, 0, vd->debugVariable, IR->scopebb()); + instr->setDebugLoc(IR->ir->getCurrentDebugLocation()); } -////////////////////////////////////////////////////////////////////////////////////////////////// - -void DtoDwarfModuleEnd() +void ldc::DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, + llvm::ArrayRef addr) { if (!global.params.symdebug) return; - gIR->dibuilder.finalize(); + Logger::println("D to dwarf local variable"); + LOG_SCOPE; + + if (IR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once + return; + + // get type description + llvm::DIType TD = CreateTypeDescription(vd->type, NULL, true); + if (static_cast(TD) == 0) + return; // unsupported + + // get variable description + assert(!vd->isDataseg() && "static variable"); + + unsigned tag; + if (vd->isParameter()) + tag = llvm::dwarf::DW_TAG_arg_variable; + else + tag = llvm::dwarf::DW_TAG_auto_variable; + + if (addr.empty()) { + vd->debugVariable = DBuilder.createLocalVariable( + tag, // tag + GetCurrentScope(), // scope + vd->toChars(), // name + CreateFile(vd->loc), // file + vd->loc.linnum, // line num + TD, // type + true // preserve + ); + } else { + vd->debugVariable = DBuilder.createComplexVariable( + tag, // tag + GetCurrentScope(), // scope + vd->toChars(), // name + CreateFile(vd->loc), // file + vd->loc.linnum, // line num + TD, // type + addr + ); + } + vd->debugFunc = IR->func()->diSubprogram; + + // declare + Declare(ll, vd->debugVariable); +} + +llvm::DIGlobalVariable ldc::DIBuilder::EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd) +{ + if (!global.params.symdebug) + return llvm::DIGlobalVariable(); + + Logger::println("D to dwarf global_variable"); + LOG_SCOPE; + + assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init)); + + return DBuilder.createGlobalVariable( + vd->toChars(), // name +#if LDC_LLVM_VER >= 303 + vd->mangle(), // linkage name +#endif + CreateFile(vd->loc), // file + vd->loc.linnum, // line num + CreateTypeDescription(vd->type, NULL), // type + vd->protection == PROTprivate, // is local to unit + ll // value + ); +} + +void ldc::DIBuilder::EmitModuleEnd() +{ + if (!global.params.symdebug) + return; + + DBuilder.finalize(); } diff --git a/gen/dibuilder.h b/gen/dibuilder.h new file mode 100644 index 00000000..7d05d58a --- /dev/null +++ b/gen/dibuilder.h @@ -0,0 +1,184 @@ +//===-- gen/dibuilder.h - Debug information builder -------------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_GEN_DIBUILDER_H +#define LDC_GEN_DIBUILDER_H + +#if LDC_LLVM_VER >= 303 +#include "llvm/IR/Constants.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/DebugInfo.h" +#include "llvm/DIBuilder.h" +#else +#if LDC_LLVM_VER == 302 +#include "llvm/DataLayout.h" +#include "llvm/DebugInfo.h" +#include "llvm/DIBuilder.h" +#else +#include "llvm/Constants.h" +#include "llvm/Type.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/Target/TargetData.h" +#endif +#endif + +#include "gen/tollvm.h" +#include "mars.h" + +struct IRState; + +struct ClassDeclaration; +struct Dsymbol; +struct FuncDeclaration; +struct Module; +struct Type; +struct VarDeclaration; + +namespace llvm { + class GlobalVariable; + class StructType; + class LLVMContext; + +// Only for the OpXXX templates, see below. +#if LDC_LLVM_VER >= 302 + class DataLayout; +#else + class TargetData; +#endif +} + +// Only for the OpXXX templates, see below. +#if LDC_LLVM_VER >= 302 +extern const llvm::DataLayout* gDataLayout; +#else +extern const llvm::TargetData* gDataLayout; +#endif + +namespace ldc { + +class DIBuilder +{ + IRState *const IR; + const llvm::MDNode *CUNode; + llvm::DIBuilder DBuilder; + + const llvm::MDNode *GetCU() + { + return CUNode; + } + +public: + DIBuilder(IRState *const IR, llvm::Module &M); + + /// \brief Emit the Dwarf compile_unit global for a Module m. + /// \param m Module to emit as compile unit. + void EmitCompileUnit(Module *m); + + /// \brief Emit the Dwarf subprogram global for a function declaration fd. + /// \param fd Function declaration to emit as subprogram. + /// \returns the Dwarf subprogram global. + llvm::DISubprogram EmitSubProgram(FuncDeclaration *fd); // FIXME + + /// \brief Emit the Dwarf subprogram global for a internal function. + /// This is used for generated functions like moduleinfoctors, + /// module ctors/dtors and unittests. + /// \param prettyname The name as seen in the source. + /// \param mangledname The mangled name in the object file. + /// \returns the Dwarf subprogram global. + llvm::DISubprogram EmitSubProgramInternal(llvm::StringRef prettyname, llvm::StringRef mangledname); // FIXME + + /// \brief Emits debug info for function start + void EmitFuncStart(FuncDeclaration *fd); + + /// \brief Emits debug info for function end + void EmitFuncEnd(FuncDeclaration *fd); + + /// \brief Emits debug info for block start + void EmitBlockStart(Loc loc); + + /// \brief Emits debug info for block end + void EmitBlockEnd(); + + void EmitStopPoint(unsigned ln); + + void EmitValue(llvm::Value *val, VarDeclaration* vd); + + /// \brief Emits all things necessary for making debug info for a local variable vd. + /// \param ll LLVM Value of the variable. + /// \param vd Variable declaration to emit debug info for. + /// \param addr An array of complex address operations. + void EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd, + llvm::ArrayRef addr = llvm::ArrayRef()); + + /// \brief Emits all things necessary for making debug info for a global variable vd. + /// \param ll LLVM global variable + /// \param vd Variable declaration to emit debug info for. + llvm::DIGlobalVariable EmitGlobalVariable(llvm::GlobalVariable *ll, VarDeclaration *vd); // FIXME + + void EmitModuleEnd(); + +private: + llvm::LLVMContext &getContext(); + Module *getDefinedModule(Dsymbol *s); + llvm::DIDescriptor GetCurrentScope(); + void Declare(llvm::Value *var, llvm::DIVariable divar); + void AddBaseFields(ClassDeclaration *sd, llvm::DIFile file, + std::vector &elems); + llvm::DIFile CreateFile(Loc loc); + llvm::DIType CreateBasicType(Type *type); + llvm::DIType CreateEnumType(Type *type); + llvm::DIType CreatePointerType(Type *type); + llvm::DIType CreateVectorType(Type *type); + llvm::DIType CreateMemberType(unsigned linnum, Type *type, llvm::DIFile file, const char* c_name, unsigned offset); + llvm::DIType CreateCompositeType(Type *type); + llvm::DIType CreateArrayType(Type *type); + llvm::DIType CreateSArrayType(Type *type); + llvm::DIType CreateTypeDescription(Type* type, const char* c_name, bool derefclass = false); + +public: + template + void OpOffset(T &addr, llvm::StructType *type, int index) + { + if (!global.params.symdebug) + return; + + uint64_t offset = gDataLayout->getStructLayout(type)->getElementOffset(index); + llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext()); + addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus)); + addr.push_back(llvm::ConstantInt::get(int64Ty, offset)); + } + + template + void OpOffset(T &addr, llvm::Value *val, int index) + { + if (!global.params.symdebug) + return; + + llvm::StructType *type = isaStruct(val->getType()->getContainedType(0)); + assert(type); + OpOffset(addr, type, index); + } + + template + void OpDeref(T &addr) + { + if (!global.params.symdebug) + return; + + llvm::Type *int64Ty = llvm::Type::getInt64Ty(getContext()); + addr.push_back(llvm::ConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref)); + } +}; + + +} // namespace ldc + +#endif \ No newline at end of file diff --git a/gen/functions.cpp b/gen/functions.cpp index 20759dd4..9f49a91e 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -27,7 +27,6 @@ #include "gen/nested.h" #include "gen/pragma.h" #include "gen/runtime.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #if LDC_LLVM_VER >= 303 #include "llvm/IR/Intrinsics.h" @@ -942,7 +941,7 @@ void DtoDefineFunction(FuncDeclaration* fd) } // debug info - fd->ir.irFunc->diSubprogram = DtoDwarfSubProgram(fd); + fd->ir.irFunc->diSubprogram = gIR->DBuilder.EmitSubProgram(fd); Type* t = fd->type->toBasetype(); TypeFunction* f = static_cast(t); @@ -995,7 +994,7 @@ void DtoDefineFunction(FuncDeclaration* fd) irfunction->allocapoint = allocaPoint; // debug info - after all allocas, but before any llvm.dbg.declare etc - DtoDwarfFuncStart(fd); + gIR->DBuilder.EmitFuncStart(fd); // this hack makes sure the frame pointer elimination optimization is disabled. // this this eliminates a bunch of inline asm related issues. @@ -1023,7 +1022,7 @@ void DtoDefineFunction(FuncDeclaration* fd) assert(fd->vthis->ir.irParam->value == thisvar); fd->vthis->ir.irParam->value = thismem; - DtoDwarfLocalVariable(thismem, fd->vthis); + gIR->DBuilder.EmitLocalVariable(thismem, fd->vthis); } // give the 'nestArg' storage @@ -1071,7 +1070,7 @@ void DtoDefineFunction(FuncDeclaration* fd) } if (global.params.symdebug && !(isaArgument(irparam->value) && isaArgument(irparam->value)->hasByValAttr()) && !refout) - DtoDwarfLocalVariable(irparam->value, vd); + gIR->DBuilder.EmitLocalVariable(irparam->value, vd); } } @@ -1120,7 +1119,7 @@ void DtoDefineFunction(FuncDeclaration* fd) // in automatically, so we do it here. // pass the previous block into this block - DtoDwarfFuncEnd(fd); + gIR->DBuilder.EmitFuncEnd(fd); if (func->getReturnType() == LLType::getVoidTy(gIR->context())) { llvm::ReturnInst::Create(gIR->context(), gIR->scopebb()); } diff --git a/gen/irstate.cpp b/gen/irstate.cpp index be6f1840..68182962 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -68,7 +68,7 @@ IRTargetScope::IRTargetScope( ////////////////////////////////////////////////////////////////////////////////////////// IRState::IRState(llvm::Module* m) - : module(m), dibuilder(*m) + : module(m), DBuilder(this, *m) { interfaceInfoType = NULL; mutexType = NULL; diff --git a/gen/irstate.h b/gen/irstate.h index 8ac8efe8..0a4df787 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -20,16 +20,12 @@ #include "ir/irfunction.h" #include "ir/iraggr.h" #include "ir/irvar.h" +#include "gen/dibuilder.h" #include #include #include #include -#if LDC_LLVM_VER >= 302 -#include "llvm/DIBuilder.h" -#else -#include "llvm/Analysis/DIBuilder.h" -#endif #include "llvm/Support/CallSite.h" namespace llvm { @@ -178,7 +174,7 @@ struct IRState IRBuilderHelper ir; // debug info helper - llvm::DIBuilder dibuilder; + ldc::DIBuilder DBuilder; // static ctors/dtors/unittests typedef std::list FuncDeclList; diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index ba95a272..5517c0c0 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -26,7 +26,6 @@ #include "gen/nested.h" #include "gen/pragma.h" #include "gen/runtime.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "gen/typeinf.h" #include "ir/irmodule.h" @@ -208,7 +207,7 @@ void DtoAssert(Module* M, Loc loc, DValue* msg) gIR->CreateCallOrInvoke(fn, args); // end debug info - DtoDwarfFuncEnd(gIR->func()->decl); + gIR->DBuilder.EmitFuncEnd(gIR->func()->decl); // after assert is always unreachable gIR->ir->CreateUnreachable(); @@ -515,7 +514,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op, bool canSkipPostblit) DVarValue *var = lhs->isVar(); VarDeclaration *vd = var ? var->var : 0; if (vd) - DtoDwarfValue(DtoLoad(var->getLVal()), vd); + gIR->DBuilder.EmitValue(DtoLoad(var->getLVal()), vd); } /****************************************************************************************/ @@ -1090,7 +1089,7 @@ void DtoVarDeclaration(VarDeclaration* vd) vd->ir.irLocal->value = allocainst; - DtoDwarfLocalVariable(allocainst, vd); + gIR->DBuilder.EmitLocalVariable(allocainst, vd); } if (Logger::enabled()) @@ -1217,7 +1216,7 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr) { addr = DtoAlloca(var->type, var->toChars()); // add debug info - DtoDwarfLocalVariable(addr, var); + gIR->DBuilder.EmitLocalVariable(addr, var); } // referenced by nested function? diff --git a/gen/module.cpp b/gen/module.cpp index 7ff40101..b9389942 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -34,7 +34,6 @@ #include "gen/rttibuilder.h" #include "gen/runtime.h" #include "gen/structs.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "ir/irdsymbol.h" #include "ir/irmodule.h" @@ -78,7 +77,7 @@ static llvm::Function* build_module_function(const std::string &name, const std: IRBuilder<> builder(bb); // debug info - DtoDwarfSubProgramInternal(name.c_str(), symbolName.c_str()); + gIR->DBuilder.EmitSubProgramInternal(name.c_str(), symbolName.c_str()); // Call ctor's typedef std::list::const_iterator FuncIterator; @@ -193,7 +192,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) IRBuilder<> builder(bb); // debug info - DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()); + gIR->DBuilder.EmitSubProgramInternal(fname.c_str(), fname.c_str()); // get current beginning LLValue* curbeg = builder.CreateLoad(mref, "current"); @@ -262,7 +261,7 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) gABI = TargetABI::getTarget(); // debug info - DtoDwarfCompileUnit(this); + gIR->DBuilder.EmitCompileUnit(this); // handle invalid 'objectø module if (!ClassDeclaration::object) { @@ -301,8 +300,8 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) } } - // finilize debug info - DtoDwarfModuleEnd(); + // finalize debug info + gIR->DBuilder.EmitModuleEnd(); // generate ModuleInfo genmoduleinfo(); diff --git a/gen/nested.cpp b/gen/nested.cpp index 2b7e7785..cf961bd6 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -14,7 +14,6 @@ #include "gen/irstate.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CommandLine.h" @@ -114,7 +113,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) ctx = DtoLoad(irfunc->nestArg); dwarfValue = irfunc->nestArg; if (global.params.symdebug) - dwarfOpDeref(dwarfAddr); + gIR->DBuilder.OpDeref(dwarfAddr); } assert(ctx); @@ -143,8 +142,8 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) } else { // Load frame pointer and index that... if (dwarfValue && global.params.symdebug) { - dwarfOpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth); - dwarfOpDeref(dwarfAddr); + gIR->DBuilder.OpOffset(dwarfAddr, val, vd->ir.irLocal->nestedDepth); + gIR->DBuilder.OpDeref(dwarfAddr); } Logger::println("Lower depth"); val = DtoGEPi(val, 0, vd->ir.irLocal->nestedDepth); @@ -157,7 +156,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) assert(idx != -1 && "Nested context not yet resolved for variable."); if (dwarfValue && global.params.symdebug) - dwarfOpOffset(dwarfAddr, val, idx); + gIR->DBuilder.OpOffset(dwarfAddr, val, idx); val = DtoGEPi(val, 0, idx, vd->toChars()); Logger::cout() << "Addr: " << *val << '\n'; @@ -170,7 +169,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) } if (dwarfValue && global.params.symdebug) - DtoDwarfLocalVariable(dwarfValue, vd, dwarfAddr); + gIR->DBuilder.EmitLocalVariable(dwarfValue, vd, dwarfAddr); return new DVarValue(astype, vd, val); } @@ -493,8 +492,8 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { if (global.params.symdebug) { LLSmallVector addr; - dwarfOpOffset(addr, frameType, vd->ir.irLocal->nestedIndex); - DtoDwarfLocalVariable(frame, vd, addr); + gIR->DBuilder.OpOffset(addr, frameType, vd->ir.irLocal->nestedIndex); + gIR->DBuilder.EmitLocalVariable(frame, vd, addr); } } } diff --git a/gen/statements.cpp b/gen/statements.cpp index b2b0b806..bab4124b 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -20,7 +20,6 @@ #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/runtime.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "ir/irfunction.h" #include "ir/irlandingpad.h" @@ -63,7 +62,7 @@ void ReturnStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); // is there a return value expression? if (exp || (!exp && (p->topfunc() == p->mainFunc)) ) @@ -93,7 +92,7 @@ void ReturnStatement::toIR(IRState* p) DtoEnclosingHandlers(loc, NULL); // emit dbg end function - DtoDwarfFuncEnd(f->decl); + gIR->DBuilder.EmitFuncEnd(f->decl); // emit ret llvm::ReturnInst::Create(gIR->context(), p->scopebb()); @@ -159,7 +158,7 @@ void ReturnStatement::toIR(IRState* p) // emit scopes DtoEnclosingHandlers(loc, NULL); - DtoDwarfFuncEnd(p->func()->decl); + gIR->DBuilder.EmitFuncEnd(p->func()->decl); llvm::ReturnInst::Create(gIR->context(), v, p->scopebb()); } } @@ -168,7 +167,7 @@ void ReturnStatement::toIR(IRState* p) { assert(p->topfunc()->getReturnType() == LLType::getVoidTy(gIR->context())); DtoEnclosingHandlers(loc, NULL); - DtoDwarfFuncEnd(p->func()->decl); + gIR->DBuilder.EmitFuncEnd(p->func()->decl); llvm::ReturnInst::Create(gIR->context(), p->scopebb()); } @@ -186,7 +185,7 @@ void ExpStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); if (exp) { elem* e; @@ -232,7 +231,7 @@ void IfStatement::toIR(IRState* p) LOG_SCOPE; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); if (match) DtoRawVarDeclaration(match); @@ -258,9 +257,9 @@ void IfStatement::toIR(IRState* p) // do scoped statements if (ifbody) { - DtoDwarfBlockStart(ifbody->loc); + gIR->DBuilder.EmitBlockStart(ifbody->loc); ifbody->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } if (!gIR->scopereturned()) { llvm::BranchInst::Create(endbb,gIR->scopebb()); @@ -269,16 +268,16 @@ void IfStatement::toIR(IRState* p) if (elsebody) { //assert(0); gIR->scope() = IRScope(elsebb,endbb); - DtoDwarfBlockStart(elsebody->loc); + gIR->DBuilder.EmitBlockStart(elsebody->loc); elsebody->toIR(p); if (!gIR->scopereturned()) { llvm::BranchInst::Create(endbb,gIR->scopebb()); } - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); // rewrite the scope gIR->scope() = IRScope(endbb,oldend); @@ -313,9 +312,9 @@ void ScopeStatement::toIR(IRState* p) p->scope().end = endbb;*/ if (statement) { - DtoDwarfBlockStart(statement->loc); + gIR->DBuilder.EmitBlockStart(statement->loc); statement->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } /*p->scope().end = oldend; @@ -331,7 +330,7 @@ void WhileStatement::toIR(IRState* p) LOG_SCOPE; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); // create while blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -371,7 +370,7 @@ void WhileStatement::toIR(IRState* p) gIR->scope() = IRScope(endbb,oldend); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -382,7 +381,7 @@ void DoStatement::toIR(IRState* p) LOG_SCOPE; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); // create while blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -419,7 +418,7 @@ void DoStatement::toIR(IRState* p) gIR->scope() = IRScope(endbb,oldend); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -430,7 +429,7 @@ void ForStatement::toIR(IRState* p) LOG_SCOPE; // start new dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); // create for blocks llvm::BasicBlock* oldend = gIR->scopeend(); @@ -497,7 +496,7 @@ void ForStatement::toIR(IRState* p) gIR->scope() = IRScope(endbb,oldend); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -513,7 +512,7 @@ void BreakStatement::toIR(IRState* p) return; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); if (ident != 0) { Logger::println("ident = %s", ident->toChars()); @@ -568,7 +567,7 @@ void ContinueStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); if (ident != 0) { Logger::println("ident = %s", ident->toChars()); @@ -634,21 +633,21 @@ void TryFinallyStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); // if there's no finalbody or no body, things are simple if (!finalbody) { if (body) { - DtoDwarfBlockStart(body->loc); + gIR->DBuilder.EmitBlockStart(body->loc); body->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } return; } if (!body) { - DtoDwarfBlockStart(finalbody->loc); + gIR->DBuilder.EmitBlockStart(finalbody->loc); finalbody->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); return; } @@ -690,9 +689,9 @@ void TryFinallyStatement::toIR(IRState* p) p->scope() = IRScope(trybb,finallybb); assert(body); - DtoDwarfBlockStart(body->loc); + gIR->DBuilder.EmitBlockStart(body->loc); body->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); // terminate try BB if (!p->scopereturned()) @@ -705,9 +704,9 @@ void TryFinallyStatement::toIR(IRState* p) // do finally block // p->scope() = IRScope(finallybb,landingpadbb); - DtoDwarfBlockStart(finalbody->loc); + gIR->DBuilder.EmitBlockStart(finalbody->loc); finalbody->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); // terminate finally //TODO: isn't it an error to have a 'returned' finally block? @@ -727,7 +726,7 @@ void TryCatchStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); // create basic blocks llvm::BasicBlock* oldend = p->scopeend(); @@ -762,9 +761,9 @@ void TryCatchStatement::toIR(IRState* p) p->scope() = IRScope(trybb,landingpadbb); assert(body); - DtoDwarfBlockStart(body->loc); + gIR->DBuilder.EmitBlockStart(body->loc); body->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); if (!gIR->scopereturned()) llvm::BranchInst::Create(endbb, p->scopebb()); @@ -783,12 +782,12 @@ void ThrowStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); assert(exp); DValue* e = exp->toElemDtor(p); - DtoDwarfFuncEnd(gIR->func()->decl); + gIR->DBuilder.EmitFuncEnd(gIR->func()->decl); llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception"); //Logger::cout() << "calling: " << *fn << '\n'; @@ -865,7 +864,7 @@ void SwitchStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); llvm::BasicBlock* oldbb = gIR->scopebb(); llvm::BasicBlock* oldend = gIR->scopeend(); @@ -1038,9 +1037,9 @@ void CaseStatement::toIR(IRState* p) p->scope() = IRScope(bodyBB, p->scopeend()); assert(statement); - DtoDwarfBlockStart(statement->loc); + gIR->DBuilder.EmitBlockStart(statement->loc); statement->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1065,9 +1064,9 @@ void DefaultStatement::toIR(IRState* p) p->scope() = IRScope(bodyBB, p->scopeend()); assert(statement); - DtoDwarfBlockStart(statement->loc); + gIR->DBuilder.EmitBlockStart(statement->loc); statement->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1082,7 +1081,7 @@ void UnrolledLoopStatement::toIR(IRState* p) return; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); // DMD doesn't fold stuff like continue/break, and since this isn't really a loop // we have to keep track of each statement and jump to the next/end on continue/break @@ -1140,7 +1139,7 @@ void UnrolledLoopStatement::toIR(IRState* p) p->scope() = IRScope(endbb,oldend); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1151,7 +1150,7 @@ void ForeachStatement::toIR(IRState* p) LOG_SCOPE; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); //assert(arguments->dim == 1); assert(value != 0); @@ -1267,7 +1266,7 @@ void ForeachStatement::toIR(IRState* p) llvm::BranchInst::Create(condbb, p->scopebb()); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); // end p->scope() = IRScope(endbb,oldend); @@ -1281,7 +1280,7 @@ void ForeachRangeStatement::toIR(IRState* p) LOG_SCOPE; // start a dwarf lexical block - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); // evaluate lwr/upr assert(lwr->type->isintegral()); @@ -1371,7 +1370,7 @@ void ForeachRangeStatement::toIR(IRState* p) llvm::BranchInst::Create(condbb, p->scopebb()); // end the dwarf lexical block - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); // END p->scope() = IRScope(endbb,oldend); @@ -1430,7 +1429,7 @@ void GotoStatement::toIR(IRState* p) Logger::println("GotoStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergoto", p->topfunc(), oldend); @@ -1447,7 +1446,7 @@ void GotoDefaultStatement::toIR(IRState* p) Logger::println("GotoDefaultStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotodefault", p->topfunc(), oldend); @@ -1468,7 +1467,7 @@ void GotoCaseStatement::toIR(IRState* p) Logger::println("GotoCaseStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "aftergotocase", p->topfunc(), oldend); @@ -1492,7 +1491,7 @@ void WithStatement::toIR(IRState* p) Logger::println("WithStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - DtoDwarfBlockStart(loc); + gIR->DBuilder.EmitBlockStart(loc); assert(exp); @@ -1507,7 +1506,7 @@ void WithStatement::toIR(IRState* p) if (body) body->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } ////////////////////////////////////////////////////////////////////////////// @@ -1524,7 +1523,7 @@ void SynchronizedStatement::toIR(IRState* p) LOG_SCOPE; // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); + gIR->DBuilder.EmitStopPoint(loc.linnum); // enter lock if (exp) @@ -1540,9 +1539,9 @@ void SynchronizedStatement::toIR(IRState* p) // emit body p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingSynchro(this),NULL,NULL)); - DtoDwarfBlockStart(body->loc); + gIR->DBuilder.EmitBlockStart(body->loc); body->toIR(p); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); p->func()->gen->targetScopes.pop_back(); // exit lock diff --git a/gen/todebug.h b/gen/todebug.h deleted file mode 100644 index 822f97f6..00000000 --- a/gen/todebug.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- gen/todebug.h - Symbolic debug information generation ---*- C++ -*-===// -// -// LDC – the LLVM D compiler -// -// This file is distributed under the BSD-style LDC license. See the LICENSE -// file for details. -// -//===----------------------------------------------------------------------===// -// -// Handles generation of symbolic debug information using LLVM's DWARF support. -// -//===----------------------------------------------------------------------===// - -#ifndef LDC_GEN_TODEBUG_H -#define LDC_GEN_TODEBUG_H - -#include "gen/irstate.h" -#include "gen/tollvm.h" - - -/// \brief Emit the Dwarf compile_unit global for a Module m. -/// \param m Module to emit as compile unit. -void DtoDwarfCompileUnit(Module* m); - -/// \brief Emit the Dwarf subprogram global for a function declaration fd. -/// \param fd Function declaration to emit as subprogram. -/// \returns the Dwarf subprogram global. -llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd); - -/// \brief Emit the Dwarf subprogram global for a internal function. -/// This is used for generated functions like moduleinfoctors, -/// module ctors/dtors and unittests. -/// \param prettyname The name as seen in the source. -/// \param mangledname The mangled name in the object file. -/// \returns the Dwarf subprogram global. -llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname); - -void DtoDwarfFuncStart(FuncDeclaration* fd); -void DtoDwarfFuncEnd(FuncDeclaration* fd); -void DtoDwarfBlockStart(Loc loc); -void DtoDwarfBlockEnd(); - -void DtoDwarfStopPoint(unsigned ln); - -void DtoDwarfValue(LLValue *val, VarDeclaration* vd); - -/// \brief Emits all things necessary for making debug info for a local variable vd. -/// \param ll LLVM Value of the variable. -/// \param vd Variable declaration to emit debug info for. -/// \param addr An array of complex address operations. -void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, - llvm::ArrayRef addr = llvm::ArrayRef()); - -/// \brief Emits all things necessary for making debug info for a global variable vd. -/// \param ll LLVM global variable -/// \param vd Variable declaration to emit debug info for. -/// \returns Created debug info -llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd); - -void DtoDwarfModuleEnd(); - -template -void dwarfOpOffset(T &addr, LLStructType *type, int index) -{ - if (!global.params.symdebug) - return; - - uint64_t offset = gDataLayout->getStructLayout(type)->getElementOffset(index); - LLType *int64Ty = LLType::getInt64Ty(gIR->context()); - addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpPlus)); - addr.push_back(LLConstantInt::get(int64Ty, offset)); -} - -template -void dwarfOpOffset(T &addr, LLValue *val, int index) -{ - if (!global.params.symdebug) - return; - - LLStructType *type = isaStruct(val->getType()->getContainedType(0)); - assert(type); - dwarfOpOffset(addr, type, index); -} - -template -void dwarfOpDeref(T &addr) -{ - if (!global.params.symdebug) - return; - - LLType *int64Ty = LLType::getInt64Ty(gIR->context()); - addr.push_back(LLConstantInt::get(int64Ty, llvm::DIBuilder::OpDeref)); -} - -#endif // LDC_GEN_TODEBUG_H diff --git a/gen/toir.cpp b/gen/toir.cpp index 99247fe8..d098f2ff 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -31,7 +31,6 @@ #include "gen/pragma.h" #include "gen/runtime.h" #include "gen/structs.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "gen/typeinf.h" #include "gen/utils.h" diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 684b7be1..69a1e96f 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -13,7 +13,6 @@ #include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/runtime.h" -#include "gen/todebug.h" #include "gen/tollvm.h" #include "ir/irlandingpad.h" @@ -50,7 +49,7 @@ void IRLandingPadCatchInfo::toIR() return; gIR->scope() = IRScope(target, target); - DtoDwarfBlockStart(catchStmt->loc); + gIR->DBuilder.EmitBlockStart(catchStmt->loc); // assign storage to catch var if (catchStmt->var) { @@ -81,7 +80,7 @@ void IRLandingPadCatchInfo::toIR() if (!gIR->scopereturned()) gIR->ir->CreateBr(end); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } IRLandingPadFinallyStatementInfo::IRLandingPadFinallyStatementInfo(Statement *finallyBody_) : @@ -107,13 +106,13 @@ void IRLandingPadFinallyStatementInfo::toIR(LLValue *eh_ptr) gIR->scope() = IRScope(bb, gIR->scopeend()); // set collision landing pad as unwind target and emit the body of the finally - DtoDwarfBlockStart(finallyBody->loc); + gIR->DBuilder.EmitBlockStart(finallyBody->loc); padInfo.scopeStack.push(IRLandingPadScope(collision)); pad = collision; finallyBody->toIR(gIR); padInfo.scopeStack.pop(); pad = padInfo.get(); - DtoDwarfBlockEnd(); + gIR->DBuilder.EmitBlockEnd(); } void IRLandingPad::addCatch(Catch* catchstmt, llvm::BasicBlock* end)