| 1 |
#include "gen/llvm.h" |
|---|
| 2 |
#include "llvm/Support/Dwarf.h" |
|---|
| 3 |
#include "llvm/CodeGen/MachineModuleInfo.h" |
|---|
| 4 |
#include "llvm/System/Path.h" |
|---|
| 5 |
|
|---|
| 6 |
#include "declaration.h" |
|---|
| 7 |
#include "module.h" |
|---|
| 8 |
#include "mars.h" |
|---|
| 9 |
|
|---|
| 10 |
#include "gen/todebug.h" |
|---|
| 11 |
#include "gen/irstate.h" |
|---|
| 12 |
#include "gen/tollvm.h" |
|---|
| 13 |
#include "gen/logger.h" |
|---|
| 14 |
#include "gen/llvmhelpers.h" |
|---|
| 15 |
#include "gen/linkage.h" |
|---|
| 16 |
#include "gen/utils.h" |
|---|
| 17 |
|
|---|
| 18 |
#include "ir/irmodule.h" |
|---|
| 19 |
|
|---|
| 20 |
using namespace llvm::dwarf; |
|---|
| 21 |
|
|---|
| 22 |
#ifndef DISABLE_DEBUG_INFO |
|---|
| 23 |
|
|---|
| 24 |
#define DBG_NULL ( LLConstant::getNullValue(DBG_TYPE) ) |
|---|
| 25 |
#define DBG_TYPE ( getPtrToType(llvm::StructType::get(gIR->context(),NULL,NULL)) ) |
|---|
| 26 |
#define DBG_CAST(X) ( llvm::ConstantExpr::getBitCast(X, DBG_TYPE) ) |
|---|
| 27 |
|
|---|
| 28 |
#define DBG_TAG(X) ( llvm::ConstantExpr::getAdd( DtoConstUint( X ), DtoConstUint( llvm::LLVMDebugVersion ) ) ) |
|---|
| 29 |
|
|---|
| 30 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 31 |
|
|---|
| 32 |
/** |
|---|
| 33 |
* Emits a global variable, LLVM Dwarf style, only declares. |
|---|
| 34 |
* @param type Type of variable. |
|---|
| 35 |
* @param name Name. |
|---|
| 36 |
* @return The global variable. |
|---|
| 37 |
*/ |
|---|
| 38 |
static LLGlobalVariable* emitDwarfGlobalDecl(const LLStructType* type, const char* name, bool linkonce=false) |
|---|
| 39 |
{ |
|---|
| 40 |
LLGlobalValue::LinkageTypes linkage = linkonce |
|---|
| 41 |
? DEBUGINFO_LINKONCE_LINKAGE_TYPE |
|---|
| 42 |
: LLGlobalValue::InternalLinkage; |
|---|
| 43 |
LLGlobalVariable* gv = new LLGlobalVariable(*gIR->module, type, true, linkage, NULL, name); |
|---|
| 44 |
gv->setSection("llvm.metadata"); |
|---|
| 45 |
return gv; |
|---|
| 46 |
} |
|---|
| 47 |
|
|---|
| 48 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 49 |
|
|---|
| 50 |
static const llvm::StructType* getDwarfCompileUnitType() { |
|---|
| 51 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.compile_unit.type")); |
|---|
| 52 |
} |
|---|
| 53 |
|
|---|
| 54 |
static const llvm::StructType* getDwarfSubProgramType() { |
|---|
| 55 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.subprogram.type")); |
|---|
| 56 |
} |
|---|
| 57 |
|
|---|
| 58 |
static const llvm::StructType* getDwarfVariableType() { |
|---|
| 59 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.variable.type")); |
|---|
| 60 |
} |
|---|
| 61 |
|
|---|
| 62 |
static const llvm::StructType* getDwarfDerivedTypeType() { |
|---|
| 63 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.derivedtype.type")); |
|---|
| 64 |
} |
|---|
| 65 |
|
|---|
| 66 |
static const llvm::StructType* getDwarfBasicTypeType() { |
|---|
| 67 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.basictype.type")); |
|---|
| 68 |
} |
|---|
| 69 |
|
|---|
| 70 |
static const llvm::StructType* getDwarfCompositeTypeType() { |
|---|
| 71 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.compositetype.type")); |
|---|
| 72 |
} |
|---|
| 73 |
|
|---|
| 74 |
static const llvm::StructType* getDwarfGlobalVariableType() { |
|---|
| 75 |
return isaStruct(gIR->module->getTypeByName("llvm.dbg.global_variable.type")); |
|---|
| 76 |
} |
|---|
| 77 |
|
|---|
| 78 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 79 |
|
|---|
| 80 |
// get the module the symbol is in, or - for template instances - the current module |
|---|
| 81 |
static Module* getDefinedModule(Dsymbol* s) |
|---|
| 82 |
{ |
|---|
| 83 |
// templates are defined in current module |
|---|
| 84 |
if (DtoIsTemplateInstance(s)) |
|---|
| 85 |
{ |
|---|
| 86 |
return gIR->dmodule; |
|---|
| 87 |
} |
|---|
| 88 |
// array operations as well |
|---|
| 89 |
else if (FuncDeclaration* fd = s->isFuncDeclaration()) |
|---|
| 90 |
{ |
|---|
| 91 |
if (fd->isArrayOp) |
|---|
| 92 |
return gIR->dmodule; |
|---|
| 93 |
} |
|---|
| 94 |
// otherwise use the symbol's module |
|---|
| 95 |
return s->getModule(); |
|---|
| 96 |
} |
|---|
| 97 |
|
|---|
| 98 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 99 |
|
|---|
| 100 |
static llvm::DIType dwarfTypeDescription_impl(Type* type, llvm::DICompileUnit cu, const char* c_name); |
|---|
| 101 |
static llvm::DIType dwarfTypeDescription(Type* type, llvm::DICompileUnit cu, const char* c_name); |
|---|
| 102 |
|
|---|
| 103 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 104 |
|
|---|
| 105 |
static llvm::DIBasicType dwarfBasicType(Type* type, llvm::DICompileUnit compileUnit) |
|---|
| 106 |
{ |
|---|
| 107 |
Type* t = type->toBasetype(); |
|---|
| 108 |
const LLType* T = DtoType(type); |
|---|
| 109 |
|
|---|
| 110 |
// find encoding |
|---|
| 111 |
unsigned id; |
|---|
| 112 |
if (t->isintegral()) |
|---|
| 113 |
{ |
|---|
| 114 |
if (type->isunsigned()) |
|---|
| 115 |
id = DW_ATE_unsigned; |
|---|
| 116 |
else |
|---|
| 117 |
id = DW_ATE_signed; |
|---|
| 118 |
} |
|---|
| 119 |
else if (t->isfloating()) |
|---|
| 120 |
{ |
|---|
| 121 |
id = DW_ATE_float; |
|---|
| 122 |
} |
|---|
| 123 |
else |
|---|
| 124 |
{ |
|---|
| 125 |
assert(0 && "unsupported basictype for debug info"); |
|---|
| 126 |
} |
|---|
| 127 |
|
|---|
| 128 |
return gIR->difactory.CreateBasicType( |
|---|
| 129 |
compileUnit, // context |
|---|
| 130 |
type->toChars(), // name |
|---|
| 131 |
llvm::DICompileUnit(NULL), // compile unit |
|---|
| 132 |
0, // line number |
|---|
| 133 |
getTypeBitSize(T), // size (bits) |
|---|
| 134 |
getABITypeAlign(T)*8, // align (bits) |
|---|
| 135 |
0, // offset (bits) |
|---|
| 136 |
//FIXME: need flags? |
|---|
| 137 |
0, // flags |
|---|
| 138 |
id // encoding |
|---|
| 139 |
); |
|---|
| 140 |
} |
|---|
| 141 |
|
|---|
| 142 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 143 |
|
|---|
| 144 |
static llvm::DIDerivedType dwarfDerivedType(Type* type, llvm::DICompileUnit compileUnit) |
|---|
| 145 |
{ |
|---|
| 146 |
const LLType* T = DtoType(type); |
|---|
| 147 |
Type* t = type->toBasetype(); |
|---|
| 148 |
|
|---|
| 149 |
assert(t->ty == Tpointer && "unsupported derivedtype for debug info, only pointers allowed"); |
|---|
| 150 |
|
|---|
| 151 |
// find base type |
|---|
| 152 |
llvm::DIType basetype; |
|---|
| 153 |
Type* nt = t->nextOf(); |
|---|
| 154 |
basetype = dwarfTypeDescription_impl(nt, compileUnit, NULL); |
|---|
| 155 |
if (nt->ty == Tvoid) |
|---|
| 156 |
basetype = llvm::DIType(NULL); |
|---|
| 157 |
|
|---|
| 158 |
return gIR->difactory.CreateDerivedType( |
|---|
| 159 |
DW_TAG_pointer_type, // tag |
|---|
| 160 |
compileUnit, // context |
|---|
| 161 |
"", // name |
|---|
| 162 |
llvm::DICompileUnit(NULL), // compile unit |
|---|
| 163 |
0, // line number |
|---|
| 164 |
getTypeBitSize(T), // size (bits) |
|---|
| 165 |
getABITypeAlign(T)*8, // align (bits) |
|---|
| 166 |
0, // offset (bits) |
|---|
| 167 |
//FIXME: need flags? |
|---|
| 168 |
0, // flags |
|---|
| 169 |
basetype // derived from |
|---|
| 170 |
); |
|---|
| 171 |
} |
|---|
| 172 |
|
|---|
| 173 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 174 |
|
|---|
| 175 |
static llvm::DIDerivedType dwarfMemberType(unsigned linnum, Type* type, llvm::DICompileUnit compileUnit, llvm::DICompileUnit definedCU, const char* c_name, unsigned offset) |
|---|
| 176 |
{ |
|---|
| 177 |
const LLType* T = DtoType(type); |
|---|
| 178 |
Type* t = type->toBasetype(); |
|---|
| 179 |
|
|---|
| 180 |
// find base type |
|---|
| 181 |
llvm::DIType basetype; |
|---|
| 182 |
basetype = dwarfTypeDescription(t, compileUnit, NULL); |
|---|
| 183 |
if (t->ty == Tvoid) |
|---|
| 184 |
basetype = llvm::DIType(NULL); |
|---|
| 185 |
|
|---|
| 186 |
return gIR->difactory.CreateDerivedType( |
|---|
| 187 |
DW_TAG_member, // tag |
|---|
| 188 |
compileUnit, // context |
|---|
| 189 |
c_name, // name |
|---|
| 190 |
definedCU, // compile unit |
|---|
| 191 |
linnum, // line number |
|---|
| 192 |
getTypeBitSize(T), // size (bits) |
|---|
| 193 |
getABITypeAlign(T)*8, // align (bits) |
|---|
| 194 |
offset*8, // offset (bits) |
|---|
| 195 |
//FIXME: need flags? |
|---|
| 196 |
0, // flags |
|---|
| 197 |
basetype // derived from |
|---|
| 198 |
); |
|---|
| 199 |
} |
|---|
| 200 |
|
|---|
| 201 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 202 |
|
|---|
| 203 |
static void add_base_fields( |
|---|
| 204 |
ClassDeclaration* sd, |
|---|
| 205 |
llvm::DICompileUnit compileUnit, |
|---|
| 206 |
llvm::DICompileUnit definedCU, |
|---|
| 207 |
std::vector<LLConstant*>& elems) |
|---|
| 208 |
{ |
|---|
| 209 |
if (sd->baseClass) |
|---|
| 210 |
{ |
|---|
| 211 |
add_base_fields(sd->baseClass, compileUnit, definedCU, elems); |
|---|
| 212 |
} |
|---|
| 213 |
|
|---|
| 214 |
ArrayIter<VarDeclaration> it(sd->fields); |
|---|
| 215 |
size_t narr = sd->fields.dim; |
|---|
| 216 |
elems.reserve(narr); |
|---|
| 217 |
for (; !it.done(); it.next()) |
|---|
| 218 |
{ |
|---|
| 219 |
VarDeclaration* vd = it.get(); |
|---|
| 220 |
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV(); |
|---|
| 221 |
elems.push_back(DBG_CAST(ptr)); |
|---|
| 222 |
} |
|---|
| 223 |
} |
|---|
| 224 |
|
|---|
| 225 |
//FIXME: This does not use llvm's DIFactory as it can't |
|---|
| 226 |
// handle recursive types properly. |
|---|
| 227 |
static llvm::DICompositeType dwarfCompositeType(Type* type, llvm::DICompileUnit compileUnit) |
|---|
| 228 |
{ |
|---|
| 229 |
const LLType* T = DtoType(type); |
|---|
| 230 |
Type* t = type->toBasetype(); |
|---|
| 231 |
|
|---|
| 232 |
// defaults |
|---|
| 233 |
LLConstant* name = getNullPtr(getVoidPtrType()); |
|---|
| 234 |
LLGlobalVariable* members = NULL; |
|---|
| 235 |
unsigned linnum = 0; |
|---|
| 236 |
llvm::DICompileUnit definedCU; |
|---|
| 237 |
|
|---|
| 238 |
// prepare tag and members |
|---|
| 239 |
unsigned tag; |
|---|
| 240 |
|
|---|
| 241 |
// declare final global variable |
|---|
| 242 |
LLGlobalVariable* gv = NULL; |
|---|
| 243 |
|
|---|
| 244 |
// dynamic array |
|---|
| 245 |
if (t->ty == Tarray) |
|---|
| 246 |
{ |
|---|
| 247 |
tag = DW_TAG_structure_type; |
|---|
| 248 |
|
|---|
| 249 |
LLGlobalVariable* len = dwarfMemberType(0, Type::tsize_t, compileUnit, llvm::DICompileUnit(NULL), "length", 0).getGV(); |
|---|
| 250 |
assert(len); |
|---|
| 251 |
LLGlobalVariable* ptr = dwarfMemberType(0, t->nextOf()->pointerTo(), compileUnit, llvm::DICompileUnit(NULL), "ptr", global.params.is64bit?8:4).getGV(); |
|---|
| 252 |
assert(ptr); |
|---|
| 253 |
|
|---|
| 254 |
const LLArrayType* at = LLArrayType::get(DBG_TYPE, 2); |
|---|
| 255 |
|
|---|
| 256 |
std::vector<LLConstant*> elems(2); |
|---|
| 257 |
elems[0] = DBG_CAST(len); |
|---|
| 258 |
elems[1] = DBG_CAST(ptr); |
|---|
| 259 |
|
|---|
| 260 |
LLConstant* ca = LLConstantArray::get(at, elems); |
|---|
| 261 |
members = new LLGlobalVariable(*gIR->module, ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array"); |
|---|
| 262 |
members->setSection("llvm.metadata"); |
|---|
| 263 |
|
|---|
| 264 |
name = DtoConstStringPtr(t->toChars(), "llvm.metadata"); |
|---|
| 265 |
} |
|---|
| 266 |
|
|---|
| 267 |
// struct/class |
|---|
| 268 |
else if (t->ty == Tstruct || t->ty == Tclass) |
|---|
| 269 |
{ |
|---|
| 270 |
AggregateDeclaration* sd; |
|---|
| 271 |
if (t->ty == Tstruct) |
|---|
| 272 |
{ |
|---|
| 273 |
TypeStruct* ts = (TypeStruct*)t; |
|---|
| 274 |
sd = ts->sym; |
|---|
| 275 |
} |
|---|
| 276 |
else |
|---|
| 277 |
{ |
|---|
| 278 |
TypeClass* tc = (TypeClass*)t; |
|---|
| 279 |
sd = tc->sym; |
|---|
| 280 |
} |
|---|
| 281 |
assert(sd); |
|---|
| 282 |
|
|---|
| 283 |
// make sure it's resolved |
|---|
| 284 |
sd->codegen(Type::sir); |
|---|
| 285 |
|
|---|
| 286 |
// if we don't know the aggregate's size, we don't know enough about it |
|---|
| 287 |
// to provide debug info. probably a forward-declared struct? |
|---|
| 288 |
if (sd->sizeok == 0) |
|---|
| 289 |
return llvm::DICompositeType(NULL); |
|---|
| 290 |
|
|---|
| 291 |
IrStruct* ir = sd->ir.irStruct; |
|---|
| 292 |
assert(ir); |
|---|
| 293 |
if (!ir->diCompositeType.isNull()) |
|---|
| 294 |
return ir->diCompositeType; |
|---|
| 295 |
|
|---|
| 296 |
// set to handle recursive types properly |
|---|
| 297 |
gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype"); |
|---|
| 298 |
// set bogus initializer to satisfy asserts in DICompositeType constructor |
|---|
| 299 |
std::vector<LLConstant*> initvals(11); |
|---|
| 300 |
initvals[0] = DBG_TAG(DW_TAG_structure_type); |
|---|
| 301 |
for (int i = 1; i < initvals.size(); ++i) |
|---|
| 302 |
initvals[i] = LLConstant::getNullValue(getDwarfCompositeTypeType()->getContainedType(i)); |
|---|
| 303 |
gv->setInitializer(LLConstantStruct::get(getDwarfCompositeTypeType(), initvals)); |
|---|
| 304 |
ir->diCompositeType = llvm::DICompositeType(gv); |
|---|
| 305 |
|
|---|
| 306 |
tag = DW_TAG_structure_type; |
|---|
| 307 |
|
|---|
| 308 |
name = DtoConstStringPtr(sd->toChars(), "llvm.metadata"); |
|---|
| 309 |
linnum = sd->loc.linnum; |
|---|
| 310 |
definedCU = DtoDwarfCompileUnit(getDefinedModule(sd)); |
|---|
| 311 |
|
|---|
| 312 |
std::vector<LLConstant*> elems; |
|---|
| 313 |
if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one |
|---|
| 314 |
{ |
|---|
| 315 |
if (t->ty == Tstruct) |
|---|
| 316 |
{ |
|---|
| 317 |
ArrayIter<VarDeclaration> it(sd->fields); |
|---|
| 318 |
size_t narr = sd->fields.dim; |
|---|
| 319 |
elems.reserve(narr); |
|---|
| 320 |
for (; !it.done(); it.next()) |
|---|
| 321 |
{ |
|---|
| 322 |
VarDeclaration* vd = it.get(); |
|---|
| 323 |
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV(); |
|---|
| 324 |
elems.push_back(DBG_CAST(ptr)); |
|---|
| 325 |
} |
|---|
| 326 |
} |
|---|
| 327 |
else |
|---|
| 328 |
{ |
|---|
| 329 |
add_base_fields(ir->aggrdecl->isClassDeclaration(), compileUnit, definedCU, elems); |
|---|
| 330 |
} |
|---|
| 331 |
} |
|---|
| 332 |
|
|---|
| 333 |
const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size()); |
|---|
| 334 |
LLConstant* ca = LLConstantArray::get(at, elems); |
|---|
| 335 |
members = new LLGlobalVariable(*gIR->module, ca->getType(), true, LLGlobalValue::InternalLinkage, ca, ".array"); |
|---|
| 336 |
members->setSection("llvm.metadata"); |
|---|
| 337 |
} |
|---|
| 338 |
|
|---|
| 339 |
// unsupported composite type |
|---|
| 340 |
else |
|---|
| 341 |
{ |
|---|
| 342 |
assert(0 && "unsupported compositetype for debug info"); |
|---|
| 343 |
} |
|---|
| 344 |
|
|---|
| 345 |
std::vector<LLConstant*> vals(11); |
|---|
| 346 |
|
|---|
| 347 |
// tag |
|---|
| 348 |
vals[0] = DBG_TAG(tag); |
|---|
| 349 |
|
|---|
| 350 |
// context |
|---|
| 351 |
vals[1] = DBG_CAST(compileUnit.getGV()); |
|---|
| 352 |
|
|---|
| 353 |
// name |
|---|
| 354 |
vals[2] = name; |
|---|
| 355 |
|
|---|
| 356 |
// compile unit where defined |
|---|
| 357 |
if (definedCU.getGV()) |
|---|
| 358 |
vals[3] = DBG_CAST(definedCU.getGV()); |
|---|
| 359 |
else |
|---|
| 360 |
vals[3] = DBG_NULL; |
|---|
| 361 |
|
|---|
| 362 |
// line number where defined |
|---|
| 363 |
vals[4] = DtoConstInt(linnum); |
|---|
| 364 |
|
|---|
| 365 |
// size in bits |
|---|
| 366 |
vals[5] = LLConstantInt::get(LLType::getInt64Ty(gIR->context()), getTypeBitSize(T), false); |
|---|
| 367 |
|
|---|
| 368 |
// alignment in bits |
|---|
| 369 |
vals[6] = LLConstantInt::get(LLType::getInt64Ty(gIR->context()), getABITypeAlign(T)*8, false); |
|---|
| 370 |
|
|---|
| 371 |
// offset in bits |
|---|
| 372 |
vals[7] = LLConstantInt::get(LLType::getInt64Ty(gIR->context()), 0, false); |
|---|
| 373 |
|
|---|
| 374 |
// FIXME: dont know what this is |
|---|
| 375 |
vals[8] = DtoConstUint(0); |
|---|
| 376 |
|
|---|
| 377 |
// FIXME: ditto |
|---|
| 378 |
vals[9] = DBG_NULL; |
|---|
| 379 |
|
|---|
| 380 |
// members array |
|---|
| 381 |
if (members) |
|---|
| 382 |
vals[10] = DBG_CAST(members); |
|---|
| 383 |
else |
|---|
| 384 |
vals[10] = DBG_NULL; |
|---|
| 385 |
|
|---|
| 386 |
// set initializer |
|---|
| 387 |
if (!gv) |
|---|
| 388 |
gv = emitDwarfGlobalDecl(getDwarfCompositeTypeType(), "llvm.dbg.compositetype"); |
|---|
| 389 |
LLConstant* initia = LLConstantStruct::get(getDwarfCompositeTypeType(), vals); |
|---|
| 390 |
gv->setInitializer(initia); |
|---|
| 391 |
|
|---|
| 392 |
return llvm::DICompositeType(gv); |
|---|
| 393 |
} |
|---|
| 394 |
|
|---|
| 395 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 396 |
|
|---|
| 397 |
static llvm::DIGlobalVariable dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) |
|---|
| 398 |
{ |
|---|
| 399 |
#if DMDV2 |
|---|
| 400 |
assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init)); |
|---|
| 401 |
#else |
|---|
| 402 |
assert(vd->isDataseg()); |
|---|
| 403 |
#endif |
|---|
| 404 |
llvm::DICompileUnit compileUnit = DtoDwarfCompileUnit(gIR->dmodule); |
|---|
| 405 |
|
|---|
| 406 |
return gIR->difactory.CreateGlobalVariable( |
|---|
| 407 |
compileUnit, // context |
|---|
| 408 |
vd->mangle(), // name |
|---|
| 409 |
vd->toPrettyChars(), // displayname |
|---|
| 410 |
vd->toChars(), // linkage name |
|---|
| 411 |
DtoDwarfCompileUnit(getDefinedModule(vd)), // compile unit |
|---|
| 412 |
vd->loc.linnum, // line num |
|---|
| 413 |
dwarfTypeDescription_impl(vd->type, compileUnit, NULL), // type |
|---|
| 414 |
vd->protection == PROTprivate, // is local to unit |
|---|
| 415 |
getDefinedModule(vd) == gIR->dmodule, // is definition |
|---|
| 416 |
ll // value |
|---|
| 417 |
); |
|---|
| 418 |
} |
|---|
| 419 |
|
|---|
| 420 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 421 |
|
|---|
| 422 |
static llvm::DIVariable dwarfVariable(VarDeclaration* vd, llvm::DIType type) |
|---|
| 423 |
{ |
|---|
| 424 |
assert(!vd->isDataseg() && "static variable"); |
|---|
| 425 |
|
|---|
| 426 |
unsigned tag; |
|---|
| 427 |
if (vd->isParameter()) |
|---|
| 428 |
tag = DW_TAG_arg_variable; |
|---|
| 429 |
else |
|---|
| 430 |
tag = DW_TAG_auto_variable; |
|---|
| 431 |
|
|---|
| 432 |
return gIR->difactory.CreateVariable( |
|---|
| 433 |
tag, // tag |
|---|
| 434 |
gIR->func()->diSubprogram, // context |
|---|
| 435 |
vd->toChars(), // name |
|---|
| 436 |
DtoDwarfCompileUnit(getDefinedModule(vd)), // compile unit |
|---|
| 437 |
vd->loc.linnum, // line num |
|---|
| 438 |
type // type |
|---|
| 439 |
); |
|---|
| 440 |
} |
|---|
| 441 |
|
|---|
| 442 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 443 |
|
|---|
| 444 |
static void dwarfDeclare(LLValue* var, llvm::DIVariable divar) |
|---|
| 445 |
{ |
|---|
| 446 |
gIR->difactory.InsertDeclare(var, divar, gIR->scopebb()); |
|---|
| 447 |
} |
|---|
| 448 |
|
|---|
| 449 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 450 |
|
|---|
| 451 |
static llvm::DIType dwarfTypeDescription_impl(Type* type, llvm::DICompileUnit cu, const char* c_name) |
|---|
| 452 |
{ |
|---|
| 453 |
Type* t = type->toBasetype(); |
|---|
| 454 |
if (t->ty == Tvoid) |
|---|
| 455 |
return llvm::DIType(NULL); |
|---|
| 456 |
else if (t->isintegral() || t->isfloating()) |
|---|
| 457 |
return dwarfBasicType(type, cu); |
|---|
| 458 |
else if (t->ty == Tpointer) |
|---|
| 459 |
return dwarfDerivedType(type, cu); |
|---|
| 460 |
else if (t->ty == Tarray || t->ty == Tstruct || t->ty == Tclass) |
|---|
| 461 |
return dwarfCompositeType(type, cu); |
|---|
| 462 |
|
|---|
| 463 |
return llvm::DIType(NULL); |
|---|
| 464 |
} |
|---|
| 465 |
|
|---|
| 466 |
static llvm::DIType dwarfTypeDescription(Type* type, llvm::DICompileUnit cu, const char* c_name) |
|---|
| 467 |
{ |
|---|
| 468 |
Type* t = type->toBasetype(); |
|---|
| 469 |
if (t->ty == Tclass) |
|---|
| 470 |
return dwarfTypeDescription_impl(type->pointerTo(), cu, c_name); |
|---|
| 471 |
else |
|---|
| 472 |
return dwarfTypeDescription_impl(type, cu, c_name); |
|---|
| 473 |
} |
|---|
| 474 |
|
|---|
| 475 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 476 |
|
|---|
| 477 |
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd) |
|---|
| 478 |
{ |
|---|
| 479 |
Logger::println("D to dwarf local variable"); |
|---|
| 480 |
LOG_SCOPE; |
|---|
| 481 |
|
|---|
| 482 |
// get compile units |
|---|
| 483 |
llvm::DICompileUnit thisCU = DtoDwarfCompileUnit(gIR->dmodule); |
|---|
| 484 |
llvm::DICompileUnit varCU = DtoDwarfCompileUnit(getDefinedModule(vd)); |
|---|
| 485 |
|
|---|
| 486 |
// get type description |
|---|
| 487 |
llvm::DIType TD = dwarfTypeDescription(vd->type, thisCU, NULL); |
|---|
| 488 |
if (TD.isNull()) |
|---|
| 489 |
return; // unsupported |
|---|
| 490 |
|
|---|
| 491 |
// get variable description |
|---|
| 492 |
llvm::DIVariable VD = dwarfVariable(vd, TD); |
|---|
| 493 |
|
|---|
| 494 |
// declare |
|---|
| 495 |
dwarfDeclare(ll, VD); |
|---|
| 496 |
} |
|---|
| 497 |
|
|---|
| 498 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 499 |
|
|---|
| 500 |
llvm::DICompileUnit DtoDwarfCompileUnit(Module* m) |
|---|
| 501 |
{ |
|---|
| 502 |
Logger::println("D to dwarf compile_unit"); |
|---|
| 503 |
LOG_SCOPE; |
|---|
| 504 |
|
|---|
| 505 |
// we might be generating for an import |
|---|
| 506 |
IrModule* irmod = getIrModule(m); |
|---|
| 507 |
|
|---|
| 508 |
if (!irmod->diCompileUnit.isNull()) |
|---|
| 509 |
{ |
|---|
| 510 |
assert (irmod->diCompileUnit.getGV()->getParent() == gIR->module |
|---|
| 511 |
&& "debug info compile unit belongs to incorrect llvm module!"); |
|---|
| 512 |
return irmod->diCompileUnit; |
|---|
| 513 |
} |
|---|
| 514 |
|
|---|
| 515 |
// prepare srcpath |
|---|
| 516 |
std::string srcpath(FileName::path(m->srcfile->name->toChars())); |
|---|
| 517 |
if (!FileName::absolute(srcpath.c_str())) { |
|---|
| 518 |
llvm::sys::Path tmp = llvm::sys::Path::GetCurrentDirectory(); |
|---|
| 519 |
tmp.appendComponent(srcpath); |
|---|
| 520 |
srcpath = tmp.toString(); |
|---|
| 521 |
if (!srcpath.empty() && *srcpath.rbegin() != '/' && *srcpath.rbegin() != '\\') |
|---|
| 522 |
srcpath = srcpath + '/'; |
|---|
| 523 |
} |
|---|
| 524 |
|
|---|
| 525 |
// make compile unit |
|---|
| 526 |
irmod->diCompileUnit = gIR->difactory.CreateCompileUnit( |
|---|
| 527 |
global.params.symdebug == 2 ? DW_LANG_C : DW_LANG_D, |
|---|
| 528 |
m->srcfile->name->toChars(), |
|---|
| 529 |
srcpath, |
|---|
| 530 |
"LDC (http://www.dsource.org/projects/ldc)", |
|---|
| 531 |
//FIXME: What do these two mean? |
|---|
| 532 |
false, // isMain, |
|---|
| 533 |
false // isOptimized |
|---|
| 534 |
); |
|---|
| 535 |
|
|---|
| 536 |
// if the linkage stays internal, we can't llvm-link the generated modules together: |
|---|
| 537 |
// llvm's DwarfWriter uses path and filename to determine the symbol name and we'd |
|---|
| 538 |
// end up with duplicate symbols |
|---|
| 539 |
irmod->diCompileUnit.getGV()->setLinkage(DEBUGINFO_LINKONCE_LINKAGE_TYPE); |
|---|
| 540 |
irmod->diCompileUnit.getGV()->setName(std::string("llvm.dbg.compile_unit_") + srcpath + m->srcfile->name->toChars()); |
|---|
| 541 |
|
|---|
| 542 |
return irmod->diCompileUnit; |
|---|
| 543 |
} |
|---|
| 544 |
|
|---|
| 545 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 546 |
|
|---|
| 547 |
llvm::DISubprogram DtoDwarfSubProgram(FuncDeclaration* fd) |
|---|
| 548 |
{ |
|---|
| 549 |
Logger::println("D to dwarf subprogram"); |
|---|
| 550 |
LOG_SCOPE; |
|---|
| 551 |
|
|---|
| 552 |
llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule); |
|---|
| 553 |
llvm::DICompileUnit definition = DtoDwarfCompileUnit(getDefinedModule(fd)); |
|---|
| 554 |
|
|---|
| 555 |
// FIXME: duplicates ? |
|---|
| 556 |
return gIR->difactory.CreateSubprogram( |
|---|
| 557 |
context, // context |
|---|
| 558 |
fd->toPrettyChars(), // name |
|---|
| 559 |
fd->toPrettyChars(), // display name |
|---|
| 560 |
fd->mangle(), // linkage name |
|---|
| 561 |
definition, // compile unit |
|---|
| 562 |
fd->loc.linnum, // line no |
|---|
| 563 |
//FIXME: what's this type for? |
|---|
| 564 |
llvm::DIType(NULL), // type |
|---|
| 565 |
fd->protection == PROTprivate, // is local to unit |
|---|
| 566 |
context.getGV() == definition.getGV() // isdefinition |
|---|
| 567 |
); |
|---|
| 568 |
} |
|---|
| 569 |
|
|---|
| 570 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 571 |
|
|---|
| 572 |
llvm::DISubprogram DtoDwarfSubProgramInternal(const char* prettyname, const char* mangledname) |
|---|
| 573 |
{ |
|---|
| 574 |
Logger::println("D to dwarf subprogram"); |
|---|
| 575 |
LOG_SCOPE; |
|---|
| 576 |
|
|---|
| 577 |
llvm::DICompileUnit context = DtoDwarfCompileUnit(gIR->dmodule); |
|---|
| 578 |
|
|---|
| 579 |
// FIXME: duplicates ? |
|---|
| 580 |
return gIR->difactory.CreateSubprogram( |
|---|
| 581 |
context, // context |
|---|
| 582 |
prettyname, // name |
|---|
| 583 |
prettyname, // display name |
|---|
| 584 |
mangledname, // linkage name |
|---|
| 585 |
context, // compile unit |
|---|
| 586 |
0, // line no |
|---|
| 587 |
//FIXME: what's this type for? |
|---|
| 588 |
llvm::DIType(NULL), // type |
|---|
| 589 |
true, // is local to unit |
|---|
| 590 |
true // isdefinition |
|---|
| 591 |
); |
|---|
| 592 |
} |
|---|
| 593 |
|
|---|
| 594 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 595 |
|
|---|
| 596 |
llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) |
|---|
| 597 |
{ |
|---|
| 598 |
Logger::println("D to dwarf global_variable"); |
|---|
| 599 |
LOG_SCOPE; |
|---|
| 600 |
|
|---|
| 601 |
// FIXME: duplicates ? |
|---|
| 602 |
return dwarfGlobalVariable(ll, vd); |
|---|
| 603 |
} |
|---|
| 604 |
|
|---|
| 605 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 606 |
|
|---|
| 607 |
void DtoDwarfFuncStart(FuncDeclaration* fd) |
|---|
| 608 |
{ |
|---|
| 609 |
Logger::println("D to dwarf funcstart"); |
|---|
| 610 |
LOG_SCOPE; |
|---|
| 611 |
|
|---|
| 612 |
assert(!fd->ir.irFunc->diSubprogram.isNull()); |
|---|
| 613 |
gIR->difactory.InsertSubprogramStart(fd->ir.irFunc->diSubprogram, gIR->scopebb()); |
|---|
| 614 |
} |
|---|
| 615 |
|
|---|
| 616 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 617 |
|
|---|
| 618 |
void DtoDwarfFuncEnd(FuncDeclaration* fd) |
|---|
| 619 |
{ |
|---|
| 620 |
Logger::println("D to dwarf funcend"); |
|---|
| 621 |
LOG_SCOPE; |
|---|
| 622 |
|
|---|
| 623 |
assert(!fd->ir.irFunc->diSubprogram.isNull()); |
|---|
| 624 |
gIR->difactory.InsertRegionEnd(fd->ir.irFunc->diSubprogram, gIR->scopebb()); |
|---|
| 625 |
} |
|---|
| 626 |
|
|---|
| 627 |
////////////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 628 |
|
|---|
| 629 |
void DtoDwarfStopPoint(unsigned ln) |
|---|
| 630 |
{ |
|---|
| 631 |
Logger::println("D to dwarf stoppoint at line %u", ln); |
|---|
| 632 |
LOG_SCOPE; |
|---|
| 633 |
|
|---|
| 634 |
gIR->difactory.InsertStopPoint( |
|---|
| 635 |
DtoDwarfCompileUnit(getDefinedModule(gIR->func()->decl)), // compile unit |
|---|
| 636 |
ln, // line no |
|---|
| 637 |
0, // col no |
|---|
| 638 |
gIR->scopebb() |
|---|
| 639 |
); |
|---|
| 640 |
} |
|---|
| 641 |
|
|---|
| 642 |
#endif |
|---|