view gen/todebug.cpp @ 783:d268bf419a09

hgignore updates for CMake.
author Christian Kamm <kamm incasoftware de>
date Sat, 22 Nov 2008 21:11:26 +0100
parents e4e50f4b58cd
children 340acf1535d0
line wrap: on
line source

#include "gen/llvm.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/System/Path.h"

#include "declaration.h"
#include "module.h"
#include "mars.h"

#include "gen/todebug.h"
#include "gen/irstate.h"
#include "gen/tollvm.h"
#include "gen/logger.h"

#include "ir/irmodule.h"

using namespace llvm::dwarf;

#define DBG_NULL    ( LLConstant::getNullValue(DBG_TYPE) )
#define DBG_TYPE    ( getPtrToType(llvm::StructType::get(NULL,NULL)) )
#define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) )

#define DBG_TAG(X)  ( llvm::ConstantExpr::getAdd( DtoConstUint( X ), DtoConstUint( llvm::LLVMDebugVersion ) ) )

//////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Emits a global variable, LLVM Dwarf style.
 * @param type Type of variable.
 * @param values Initializers.
 * @param name Name.
 * @return The global variable.
 */
static LLGlobalVariable* emitDwarfGlobal(const LLStructType* type, const std::vector<LLConstant*> values, const char* name, bool linkonce=false)
{
    LLConstant* c = llvm::ConstantStruct::get(type, values);
    LLGlobalValue::LinkageTypes linkage = linkonce ? LLGlobalValue::LinkOnceLinkage : LLGlobalValue::InternalLinkage;
    LLGlobalVariable* gv = new LLGlobalVariable(type, true, linkage, c, name, gIR->module);
    gv->setSection("llvm.metadata");
    return gv;
}

/**
 * Emits a global variable, LLVM Dwarf style, only declares.
 * @param type Type of variable.
 * @param name Name.
 * @return The global variable.
 */
static LLGlobalVariable* emitDwarfGlobalDecl(const LLStructType* type, const char* name, bool linkonce=false)
{
    LLGlobalValue::LinkageTypes linkage = linkonce ? LLGlobalValue::LinkOnceLinkage : LLGlobalValue::InternalLinkage;
    LLGlobalVariable* gv = new LLGlobalVariable(type, true, linkage, NULL, name, gIR->module);
    gv->setSection("llvm.metadata");
    return gv;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Emits the Dwarf anchors that are used repeatedly by LLVM debug info.
 */
static void emitDwarfAnchors()
{
    const llvm::StructType* anchorTy = isaStruct(gIR->module->getTypeByName("llvm.dbg.anchor.type"));
    std::vector<LLConstant*> vals(2);

    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
    vals[1] = DtoConstUint(DW_TAG_compile_unit);
    gIR->dwarfCUs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.compile_units", true);

    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
    vals[1] = DtoConstUint(DW_TAG_variable);
    gIR->dwarfGVs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.global_variables", true);

    vals[0] = DtoConstUint(llvm::LLVMDebugVersion);
    vals[1] = DtoConstUint(DW_TAG_subprogram);
    gIR->dwarfSPs = emitDwarfGlobal(anchorTy, vals, "llvm.dbg.subprograms", true);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLConstant* getDwarfAnchor(dwarf_constants c)
{
    if (!gIR->dwarfCUs)
        emitDwarfAnchors();
    switch (c)
    {
    case DW_TAG_compile_unit:
        return gIR->dwarfCUs;
    case DW_TAG_variable:
        return gIR->dwarfGVs;
    case DW_TAG_subprogram:
        return gIR->dwarfSPs;
    default:
        assert(0);
    }
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static const llvm::StructType* getDwarfCompileUnitType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.compile_unit.type"));
}

static const llvm::StructType* getDwarfSubProgramType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.subprogram.type"));
}

static const llvm::StructType* getDwarfVariableType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.variable.type"));
}

static const llvm::StructType* getDwarfDerivedTypeType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.derivedtype.type"));
}

static const llvm::StructType* getDwarfBasicTypeType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.basictype.type"));
}

static const llvm::StructType* getDwarfCompositeTypeType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.compositetype.type"));
}

static const llvm::StructType* getDwarfGlobalVariableType() {
    return isaStruct(gIR->module->getTypeByName("llvm.dbg.global_variable.type"));
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfCompileUnit(Module* m)
{
    std::vector<LLConstant*> vals(6);
    vals[0] = DBG_TAG(DW_TAG_compile_unit);
    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_compile_unit));

    vals[2] = DtoConstUint(DW_LANG_C);// _D)); // doesn't seem to work
    vals[3] = DtoConstStringPtr(FileName::name(m->srcfile->name->toChars()), "llvm.metadata");
    std::string srcpath(FileName::path(m->srcfile->name->toChars()));
    if (!FileName::absolute(srcpath.c_str())) {
        llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory();
        tmp.appendComponent(srcpath);
        srcpath = tmp.toString();
        if (!srcpath.empty() && *srcpath.rbegin() != '/' && *srcpath.rbegin() != '\\')
            srcpath = srcpath + '/';
    }
    vals[4] = DtoConstStringPtr(srcpath.c_str(), "llvm.metadata");
    vals[5] = DtoConstStringPtr("LDC (http://www.dsource.org/projects/ldc)", "llvm.metadata");

    LLGlobalVariable* gv = emitDwarfGlobal(getDwarfCompileUnitType(), vals, "llvm.dbg.compile_unit");
    m->ir.irModule->dwarfCompileUnit = gv;
    return gv;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfSubProgram(llvm::GlobalVariable* emitUnit, llvm::GlobalVariable* defineUnit, const char* prettyname, const char* mangledname, unsigned int linenum, bool isprivate)
{
    std::vector<LLConstant*> vals(11);
    vals[0] = DBG_TAG(DW_TAG_subprogram);
    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram));

    vals[2] = DBG_CAST(emitUnit);
    vals[3] = DtoConstStringPtr(prettyname, "llvm.metadata");
    vals[4] = vals[3];
    vals[5] = DtoConstStringPtr(mangledname, "llvm.metadata");
    vals[6] = DBG_CAST(defineUnit);
    vals[7] = DtoConstUint(linenum);
    vals[8] = DBG_NULL;
    vals[9] = DtoConstBool(isprivate);
    vals[10] = DtoConstBool(emitUnit == defineUnit);

    Logger::println("emitting subprogram global");

    return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram");
}

/*
static LLGlobalVariable* dwarfSubProgram(FuncDeclaration* fd, llvm::GlobalVariable* compileUnit)
{
    std::vector<LLConstant*> vals(11);
    vals[0] = DBG_TAG(DW_TAG_subprogram);
    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_subprogram));

    vals[2] = DBG_CAST(compileUnit);
    vals[3] = DtoConstStringPtr(fd->toPrettyChars(), "llvm.metadata");
    vals[4] = vals[3];
    vals[5] = DtoConstStringPtr(fd->mangle(), "llvm.metadata");
    vals[6] = DBG_CAST( DtoDwarfCompileUnit(fd->getModule()) );
    vals[7] = DtoConstUint(fd->loc.linnum);
    vals[8] = DBG_NULL;
    vals[9] = DtoConstBool(fd->protection == PROTprivate);
    vals[10] = DtoConstBool(fd->getModule() == gIR->dmodule);

    Logger::println("emitting subprogram global");

    return emitDwarfGlobal(getDwarfSubProgramType(), vals, "llvm.dbg.subprogram");
}*/

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name);
static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name);

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compileUnit)
{
    Type* t = type->toBasetype();

    const LLType* T = DtoType(type);

    std::vector<LLConstant*> vals(10);

    // tag
    vals[0] = DBG_TAG(DW_TAG_base_type);

    // context
    vals[1] = DBG_CAST(compileUnit);

    // name
    vals[2] = DtoConstStringPtr(type->toChars(), "llvm.metadata");

    // compile unit where defined
    vals[3] = DBG_NULL;

    // line number where defined
    vals[4] = DtoConstInt(0);

    // size in bits
    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);

    // alignment in bits
    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);

    // offset in bits
    vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);

    // FIXME: dont know what this is
    vals[8] = DtoConstUint(0);

    // dwarf type
    unsigned id;
    if (t->isintegral())
    {
        if (type->isunsigned())
            id = DW_ATE_unsigned;
        else
            id = DW_ATE_signed;
    }
    else if (t->isfloating())
    {
        id = DW_ATE_float;
    }
    else
    {
        assert(0 && "unsupported basictype for debug info");
    }
    vals[9] = DtoConstUint(id);

    return emitDwarfGlobal(getDwarfBasicTypeType(), vals, "llvm.dbg.basictype");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit)
{
    const LLType* T = DtoType(type);
    Type* t = type->toBasetype();

    // defaults
    LLConstant* name = getNullPtr(getVoidPtrType());

    // find tag
    unsigned tag;
    if (t->ty == Tpointer)
    {
        tag = DW_TAG_pointer_type;
    }
    else
    {
        assert(0 && "unsupported derivedtype for debug info");
    }

    std::vector<LLConstant*> vals(10);

    // tag
    vals[0] = DBG_TAG(tag);

    // context
    vals[1] = DBG_CAST(compileUnit);

    // name
    vals[2] = name;

    // compile unit where defined
    vals[3] = DBG_NULL;

    // line number where defined
    vals[4] = DtoConstInt(0);

    // size in bits
    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);

    // alignment in bits
    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);

    // offset in bits
    vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);

    // FIXME: dont know what this is
    vals[8] = DtoConstUint(0);

    // base type
    Type* nt = t->nextOf();
    LLGlobalVariable* nTD = dwarfTypeDescription_impl(nt, compileUnit, NULL);
    if (nt->ty == Tvoid || !nTD)
        vals[9] = DBG_NULL;
    else
        vals[9] = DBG_CAST(nTD);

    return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset)
{
    const LLType* T = DtoType(type);
    Type* t = type->toBasetype();

    // defaults
    LLConstant* name;
    if (c_name)
        name = DtoConstStringPtr(c_name, "llvm.metadata");
    else
        name = getNullPtr(getVoidPtrType());

    std::vector<LLConstant*> vals(10);

    // tag
    vals[0] = DBG_TAG(DW_TAG_member);

    // context
    vals[1] = DBG_CAST(compileUnit);

    // name
    vals[2] = name;

    // compile unit where defined
    if (definedCU)
        vals[3] = DBG_CAST(definedCU);
    else
        vals[3] = DBG_NULL;

    // line number where defined
    vals[4] = DtoConstInt(linnum);

    // size in bits
    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);

    // alignment in bits
    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);

    // offset in bits
    vals[7] = LLConstantInt::get(LLType::Int64Ty, offset*8, false);

    // FIXME: dont know what this is
    vals[8] = DtoConstUint(0);

    // base type
    LLGlobalVariable* nTD = dwarfTypeDescription(t, compileUnit, NULL);
    if (t->ty == Tvoid || !nTD)
        vals[9] = DBG_NULL;
    else
        vals[9] = DBG_CAST(nTD);

    return emitDwarfGlobal(getDwarfDerivedTypeType(), vals, "llvm.dbg.derivedtype");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit)
{
    const LLType* T = DtoType(type);
    Type* t = type->toBasetype();

    // defaults
    LLConstant* name = getNullPtr(getVoidPtrType());
    LLGlobalVariable* members = NULL;
    unsigned linnum = 0;
    LLGlobalVariable* definedCU = NULL;

    // prepare tag and members
    unsigned tag;

    // declare final global variable
    LLGlobalVariable* gv = NULL;

    // dynamic array
    if (t->ty == Tarray)
    {
        tag = DW_TAG_structure_type;

        LLGlobalVariable* len = dwarfMemberType(0, Type::tsize_t, compileUnit, NULL, "length", 0);
        assert(len);
        LLGlobalVariable* ptr = dwarfMemberType(0, t->nextOf()->pointerTo(), compileUnit, NULL, "ptr", global.params.is64bit?8:4);
        assert(ptr);

        const LLArrayType* at = LLArrayType::get(DBG_TYPE, 2);

        std::vector<LLConstant*> elems(2);
        elems[0] = DBG_CAST(len);
        elems[1] = DBG_CAST(ptr);

        LLConstant* ca = LLConstantArray::get(at, elems);
        members = new LLGlobalVariable(ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array", gIR->module);
        members->setSection("llvm.metadata");

        name = DtoConstStringPtr(t->toChars(), "llvm.metadata");
    }

    // struct/class
    else if (t->ty == Tstruct || t->ty == Tclass)
    {
        AggregateDeclaration* sd;
        if (t->ty == Tstruct)
        {
            TypeStruct* ts = (TypeStruct*)t;
            sd = ts->sym;
        }
        else
        {
            TypeClass* tc = (TypeClass*)t;
            sd = tc->sym;
        }
        assert(sd);

        IrStruct* ir = sd->ir.irStruct;
        assert(ir);
        if (ir->dwarfComposite)
            return ir->dwarfComposite;

        // set to handle recursive types properly
        gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype");
        ir->dwarfComposite = gv;

        tag = DW_TAG_structure_type;

        name = DtoConstStringPtr(sd->toChars(), "llvm.metadata");
        linnum = sd->loc.linnum;
        definedCU = DtoDwarfCompileUnit(sd->getModule());

        std::vector<LLConstant*> elems;
        elems.reserve(ir->offsets.size());
        for (IrStruct::OffsetMap::iterator i=ir->offsets.begin(); i!=ir->offsets.end(); ++i)
        {
            unsigned offset = i->first;
            IrStruct::Offset& o = i->second;

            LLGlobalVariable* ptr = dwarfMemberType(o.var->loc.linnum, o.var->type, compileUnit, definedCU, o.var->toChars(), offset);
            elems.push_back(DBG_CAST(ptr));
        }

        const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size());
        LLConstant* ca = LLConstantArray::get(at, elems);
        members = new LLGlobalVariable(ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array", gIR->module);
        members->setSection("llvm.metadata");
    }

    // unsupported composite type
    else
    {
        assert(0 && "unsupported compositetype for debug info");
    }

    std::vector<LLConstant*> vals(11);

    // tag
    vals[0] = DBG_TAG(tag);

    // context
    vals[1] = DBG_CAST(compileUnit);

    // name
    vals[2] = name;

    // compile unit where defined
    if (definedCU)
        vals[3] = DBG_CAST(definedCU);
    else
        vals[3] = DBG_NULL;

    // line number where defined
    vals[4] = DtoConstInt(linnum);

    // size in bits
    vals[5] = LLConstantInt::get(LLType::Int64Ty, getTypeBitSize(T), false);

    // alignment in bits
    vals[6] = LLConstantInt::get(LLType::Int64Ty, getABITypeAlign(T)*8, false);

    // offset in bits
    vals[7] = LLConstantInt::get(LLType::Int64Ty, 0, false);

    // FIXME: dont know what this is
    vals[8] = DtoConstUint(0);

    // FIXME: ditto
    vals[9] = DBG_NULL;

    // members array
    if (members)
        vals[10] = DBG_CAST(members);
    else
        vals[10] = DBG_NULL;

    // set initializer
    if (!gv)
        gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype");
    LLConstant* initia = LLConstantStruct::get(getDwarfCompositeTypeType(), vals);
    gv->setInitializer(initia);

    return gv;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
{
    assert(vd->isDataseg());
    LLGlobalVariable* compileUnit = DtoDwarfCompileUnit(gIR->dmodule);

    std::vector<LLConstant*> vals(12);
    vals[0] = DBG_TAG(DW_TAG_variable);
    vals[1] = DBG_CAST(getDwarfAnchor(DW_TAG_variable));

    vals[2] = DBG_CAST(compileUnit);

    vals[3] = DtoConstStringPtr(vd->mangle(), "llvm.metadata");
    vals[4] = DtoConstStringPtr(vd->toPrettyChars(), "llvm.metadata");
    vals[5] = DtoConstStringPtr(vd->toChars(), "llvm.metadata");

    vals[6] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule()));
    vals[7] = DtoConstUint(vd->loc.linnum);

    LLGlobalVariable* TY = dwarfTypeDescription_impl(vd->type, compileUnit, NULL);
    vals[8] = TY ? DBG_CAST(TY) : DBG_NULL;
    vals[9] = DtoConstBool(vd->protection == PROTprivate);
    vals[10] = DtoConstBool(vd->getModule() == gIR->dmodule);

    vals[11] = DBG_CAST(ll);

    return emitDwarfGlobal(getDwarfGlobalVariableType(), vals, "llvm.dbg.global_variable");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfVariable(VarDeclaration* vd, LLGlobalVariable* typeDescr)
{
    assert(!vd->isDataseg() && "static variable");

    unsigned tag;
    if (vd->isParameter())
        tag = DW_TAG_arg_variable;
    else
        tag = DW_TAG_auto_variable;

    std::vector<LLConstant*> vals(6);
    // tag
    vals[0] = DBG_TAG(tag);
    // context
    vals[1] = DBG_CAST(gIR->func()->dwarfSubProg);
    // name
    vals[2] = DtoConstStringPtr(vd->toChars(), "llvm.metadata");
    // compile unit where defined
    vals[3] = DBG_CAST(DtoDwarfCompileUnit(vd->getModule()));
    // line number where defined
    vals[4] = DtoConstUint(vd->loc.linnum);
    // type descriptor
    vals[5] = DBG_CAST(typeDescr);

    return emitDwarfGlobal(getDwarfVariableType(), vals, "llvm.dbg.variable");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static void dwarfDeclare(LLValue* var, LLGlobalVariable* varDescr)
{
    LLSmallVector<LLValue*,2> args(2);
    args[0] = DtoBitCast(var, DBG_TYPE);
    args[1] = DBG_CAST(varDescr);
    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.declare"), args.begin(), args.end());
}

//////////////////////////////////////////////////////////////////////////////////////////////////

static LLGlobalVariable* dwarfTypeDescription_impl(Type* type, LLGlobalVariable* cu, const char* c_name)
{
    Type* t = type->toBasetype();
    if (t->ty == Tvoid)
        return NULL;
    else if (t->isintegral() || t->isfloating())
        return dwarfBasicType(type, cu);
    else if (t->ty == Tpointer)
        return dwarfDerivedType(type, cu);
    else if (t->ty == Tarray || t->ty == Tstruct || t->ty == Tclass)
        return dwarfCompositeType(type, cu);

    return NULL;
}

static LLGlobalVariable* dwarfTypeDescription(Type* type, LLGlobalVariable* cu, const char* c_name)
{
    Type* t = type->toBasetype();
    if (t->ty == Tclass)
        return dwarfTypeDescription_impl(type->pointerTo(), cu, c_name);
    else
        return dwarfTypeDescription_impl(type, cu, c_name);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd)
{
    Logger::println("D to dwarf local variable");
    LOG_SCOPE;

    // get compile units
    LLGlobalVariable* thisCU = DtoDwarfCompileUnit(gIR->dmodule);
    LLGlobalVariable* varCU = thisCU;
    if (vd->getModule() != gIR->dmodule)
        varCU = DtoDwarfCompileUnit(vd->getModule());

    // get type description
    Type* t = vd->type->toBasetype();
    LLGlobalVariable* TD = dwarfTypeDescription(vd->type, thisCU, NULL);
    if (TD == NULL)
        return; // unsupported

    // get variable description
    LLGlobalVariable* VD;
    VD = dwarfVariable(vd, TD);

    // declare
    dwarfDeclare(ll, VD);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

LLGlobalVariable* DtoDwarfCompileUnit(Module* m)
{
    Logger::println("D to dwarf compile_unit");
    LOG_SCOPE;

    // we might be generating for an import
    if (!m->ir.irModule)
        m->ir.irModule = new IrModule(m, m->srcfile->toChars());
    else if (m->ir.irModule->dwarfCompileUnit)
    {
        if (m->ir.irModule->dwarfCompileUnit->getParent() == gIR->module)
            return m->ir.irModule->dwarfCompileUnit;
    }

    LLGlobalVariable* gv = dwarfCompileUnit(m);
    m->ir.irModule->dwarfCompileUnit = gv;
    return gv;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

LLGlobalVariable* DtoDwarfSubProgram(FuncDeclaration* fd)
{
    Logger::println("D to dwarf subprogram");
    LOG_SCOPE;

    // FIXME: duplicates ?
    return dwarfSubProgram(
        DtoDwarfCompileUnit(gIR->dmodule),
        DtoDwarfCompileUnit(fd->getModule()),
        fd->toPrettyChars(), fd->mangle(),
        fd->loc.linnum,
        fd->protection == PROTprivate);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

LLGlobalVariable* DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname)
{
    Logger::println("D to dwarf subprogram");
    LOG_SCOPE;

    // FIXME: duplicates ?
    return dwarfSubProgram(
        DtoDwarfCompileUnit(gIR->dmodule),
        DtoDwarfCompileUnit(gIR->dmodule),
        prettyname, mangledname,
        0,
        true);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

LLGlobalVariable* DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd)
{
    Logger::println("D to dwarf global_variable");
    LOG_SCOPE;

    // FIXME: duplicates ?
    return dwarfGlobalVariable(ll, vd);
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void DtoDwarfFuncStart(FuncDeclaration* fd)
{
    Logger::println("D to dwarf funcstart");
    LOG_SCOPE;

    assert(fd->ir.irFunc->dwarfSubProg);
    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void DtoDwarfFuncEnd(FuncDeclaration* fd)
{
    Logger::println("D to dwarf funcend");
    LOG_SCOPE;

    assert(fd->ir.irFunc->dwarfSubProg);
    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(fd->ir.irFunc->dwarfSubProg));
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void DtoDwarfStopPoint(unsigned ln)
{
    Logger::println("D to dwarf stoppoint at line %u", ln);
    LOG_SCOPE;

    LLSmallVector<LLValue*,3> args(3);
    args[0] = DtoConstUint(ln);
    args[1] = DtoConstUint(0);
    FuncDeclaration* fd = gIR->func()->decl;
    args[2] = DBG_CAST(DtoDwarfCompileUnit(fd->getModule()));
    gIR->ir->CreateCall(gIR->module->getFunction("llvm.dbg.stoppoint"), args.begin(), args.end());
}