mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 03:46:02 +03:00
Merge remote-tracking branch 'origin/master' into merge-2.096
Conflicts: gen/dibuilder.cpp
This commit is contained in:
commit
f39371a32d
8 changed files with 214 additions and 207 deletions
|
@ -568,6 +568,7 @@ public:
|
|||
// 4 if there's an assert(0)
|
||||
// 8 if there's inline asm
|
||||
// 16 if there are multiple return statements
|
||||
// IN_LLVM: 32 if there's DMD-style inline asm
|
||||
int hasReturnExp;
|
||||
|
||||
// Support for NRVO (named return value optimization)
|
||||
|
|
|
@ -109,6 +109,9 @@ Statement *asmSemantic(AsmStatement *s, Scope *sc) {
|
|||
return gccAsmSemantic(gas, sc);
|
||||
}
|
||||
|
||||
// this is DMD-style asm
|
||||
sc->func->hasReturnExp |= 32;
|
||||
|
||||
auto ias = createInlineAsmStatement(s->loc, s->tokens);
|
||||
s = ias;
|
||||
|
||||
|
@ -156,7 +159,7 @@ void AsmStatement_toIR(InlineAsmStatement *stmt, IRState *irs) {
|
|||
LOG_SCOPE;
|
||||
|
||||
// sanity check
|
||||
assert(irs->func()->decl->hasReturnExp & 8);
|
||||
assert((irs->func()->decl->hasReturnExp & 40) == 40);
|
||||
|
||||
// get asm block
|
||||
IRAsmBlock *asmblock = irs->asmBlock;
|
||||
|
|
|
@ -53,8 +53,6 @@ namespace ldc {
|
|||
const char *convertDIdentifierToCPlusPlus(const char *name, size_t nameLength);
|
||||
|
||||
namespace {
|
||||
DIType getNullDIType() { return nullptr; }
|
||||
|
||||
llvm::StringRef uniqueIdent(Type *t) {
|
||||
if (t->deco)
|
||||
return t->deco;
|
||||
|
@ -125,7 +123,7 @@ DIScope DIBuilder::GetSymbolScope(Dsymbol *s) {
|
|||
// parent composite types have to get declared
|
||||
while (!parent->isModule()) {
|
||||
if (parent->isAggregateDeclaration())
|
||||
CreateCompositeTypeDescription(parent->getType());
|
||||
CreateCompositeType(parent->getType());
|
||||
parent = parent->toParent();
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +133,7 @@ DIScope DIBuilder::GetSymbolScope(Dsymbol *s) {
|
|||
} else if (auto m = parent->isModule()) {
|
||||
return EmitModule(m);
|
||||
} else if (parent->isAggregateDeclaration()) {
|
||||
return CreateCompositeTypeDescription(parent->getType());
|
||||
return CreateCompositeType(parent->getType());
|
||||
} else if (auto fd = parent->isFuncDeclaration()) {
|
||||
DtoDeclareFunction(fd);
|
||||
return EmitSubProgram(fd);
|
||||
|
@ -144,7 +142,10 @@ DIScope DIBuilder::GetSymbolScope(Dsymbol *s) {
|
|||
} else if (auto fwd = parent->isForwardingScopeDsymbol()) {
|
||||
return GetSymbolScope(fwd);
|
||||
} else if (auto ed = parent->isEnumDeclaration()) {
|
||||
return CreateEnumType(ed->getType());
|
||||
auto et = CreateEnumType(ed->getType()->isTypeEnum());
|
||||
if (llvm::isa<llvm::DICompositeType>(et))
|
||||
return et;
|
||||
return EmitNamespace(ed, ed->toChars());
|
||||
} else {
|
||||
error(parent->loc, "unknown debuginfo scope `%s`; please file an LDC issue",
|
||||
parent->toChars());
|
||||
|
@ -313,34 +314,39 @@ DIType DIBuilder::CreateBasicType(Type *type) {
|
|||
Encoding);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateEnumType(Type *type) {
|
||||
assert(type->ty == Tenum);
|
||||
DIType DIBuilder::CreateEnumType(TypeEnum *type) {
|
||||
EnumDeclaration *const ed = type->sym;
|
||||
|
||||
llvm::Type *const T = DtoType(type);
|
||||
EnumDeclaration *const ed = static_cast<TypeEnum *>(type)->sym;
|
||||
assert(ed->memtype);
|
||||
if (!ed->memtype) // opaque enum
|
||||
return CreateUnspecifiedType(ed);
|
||||
|
||||
if (ed->isSpecial()) {
|
||||
return CreateBasicType(ed->memtype);
|
||||
}
|
||||
|
||||
llvm::SmallVector<LLMetadata *, 8> subscripts;
|
||||
for (auto m : *ed->members) {
|
||||
EnumMember *em = m->isEnumMember();
|
||||
if (auto ie = em->value()->isIntegerExp()) {
|
||||
subscripts.push_back(
|
||||
DBuilder.createEnumerator(em->toChars(), ie->toInteger()));
|
||||
} else {
|
||||
subscripts.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ed->isSpecial()) // magic enums: forward to base type
|
||||
return CreateTypeDescription(ed->memtype);
|
||||
|
||||
DIScope scope = nullptr;
|
||||
const auto name = GetNameAndScope(ed, scope);
|
||||
const auto lineNumber = ed->loc.linnum;
|
||||
const auto file = CreateFile(ed);
|
||||
|
||||
// just emit a typedef for non-integral base types
|
||||
auto tb = type->toBasetype();
|
||||
if (!tb->isintegral()) {
|
||||
auto tbase = CreateTypeDescription(tb);
|
||||
return DBuilder.createTypedef(tbase, name, file, lineNumber, scope);
|
||||
}
|
||||
|
||||
llvm::SmallVector<LLMetadata *, 8> subscripts;
|
||||
if (ed->members) {
|
||||
for (auto m : *ed->members) {
|
||||
EnumMember *em = m->isEnumMember();
|
||||
if (auto ie = em->value()->isIntegerExp()) {
|
||||
subscripts.push_back(
|
||||
DBuilder.createEnumerator(em->toChars(), ie->toInteger()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Type *const T = DtoType(type);
|
||||
return DBuilder.createEnumerationType(
|
||||
scope, name, file, lineNumber,
|
||||
getTypeAllocSize(T) * 8, // size (bits)
|
||||
|
@ -349,16 +355,8 @@ DIType DIBuilder::CreateEnumType(Type *type) {
|
|||
CreateTypeDescription(ed->memtype));
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreatePointerType(Type *type) {
|
||||
DIType DIBuilder::CreatePointerType(TypePointer *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
assert(t->ty == Tpointer);
|
||||
|
||||
// find base type
|
||||
Type *nt = t->nextOf();
|
||||
// translate void pointers to byte pointers
|
||||
if (nt->toBasetype()->ty == Tvoid)
|
||||
nt = Type::tuns8;
|
||||
|
||||
// TODO: The addressspace is important for dcompute targets. See e.g.
|
||||
// https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00326.html
|
||||
|
@ -366,24 +364,17 @@ DIType DIBuilder::CreatePointerType(Type *type) {
|
|||
|
||||
const auto name = processDIName(type->toPrettyChars(true));
|
||||
|
||||
return DBuilder.createPointerType(CreateTypeDescription(nt),
|
||||
return DBuilder.createPointerType(
|
||||
CreateTypeDescription(type->nextOf(), /*voidToUbyte=*/true),
|
||||
getTypeAllocSize(T) * 8, // size (bits)
|
||||
getABITypeAlign(T) * 8, // align (bits)
|
||||
DWARFAddressSpace, name);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateVectorType(Type *type) {
|
||||
DIType DIBuilder::CreateVectorType(TypeVector *type) {
|
||||
LLType *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
assert(t->ty == Tvector &&
|
||||
"Only vectors allowed for debug info in DIBuilder::CreateVectorType");
|
||||
TypeVector *tv = static_cast<TypeVector *>(t);
|
||||
Type *te = tv->elementType();
|
||||
// translate void vectors to byte vectors
|
||||
if (te->toBasetype()->ty == Tvoid)
|
||||
te = Type::tuns8;
|
||||
const auto dim = tv->size(Loc()) / te->size(Loc());
|
||||
const auto dim = type->basetype->isTypeSArray()->dim->toInteger();
|
||||
#if LDC_LLVM_VER >= 1100
|
||||
const auto Dim = llvm::ConstantAsMetadata::get(DtoConstSize_t(dim));
|
||||
auto subscript = DBuilder.getOrCreateSubrange(Dim, nullptr, nullptr, nullptr);
|
||||
|
@ -394,14 +385,14 @@ DIType DIBuilder::CreateVectorType(Type *type) {
|
|||
return DBuilder.createVectorType(
|
||||
getTypeAllocSize(T) * 8, // size (bits)
|
||||
getABITypeAlign(T) * 8, // align (bits)
|
||||
CreateTypeDescription(te), // element type
|
||||
CreateTypeDescription(type->elementType(), /*voidToUbyte=*/true),
|
||||
DBuilder.getOrCreateArray({subscript}) // subscripts
|
||||
);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateComplexType(Type *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
llvm::Type *T = DtoType(type);
|
||||
|
||||
Type *elemtype = nullptr;
|
||||
switch (t->ty) {
|
||||
|
@ -432,41 +423,21 @@ DIType DIBuilder::CreateComplexType(Type *type) {
|
|||
getTypeAllocSize(T) * 8, // size in bits
|
||||
getABITypeAlign(T) * 8, // alignment
|
||||
DIFlags::FlagZero, // What here?
|
||||
getNullDIType(), // derived from
|
||||
nullptr, // derived from
|
||||
DBuilder.getOrCreateArray(elems),
|
||||
0, // RunTimeLang
|
||||
getNullDIType(), // VTableHolder
|
||||
nullptr, // VTableHolder
|
||||
uniqueIdent(t)); // UniqueIdentifier
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateTypedef(unsigned linnum, Type *type, DIFile file,
|
||||
const char *c_name) {
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
// translate functions to function pointers
|
||||
if (t->ty == Tfunction)
|
||||
t = t->pointerTo();
|
||||
|
||||
// find base type
|
||||
DIType basetype = CreateTypeDescription(t);
|
||||
|
||||
return DBuilder.createTypedef(basetype, c_name, file, linnum, GetCU());
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateMemberType(unsigned linnum, Type *type, DIFile file,
|
||||
const char *c_name, unsigned offset,
|
||||
Visibility::Kind visibility, bool isStatic,
|
||||
DIScope scope) {
|
||||
Type *t = type->toBasetype();
|
||||
|
||||
// translate functions to function pointers
|
||||
if (t->ty == Tfunction)
|
||||
t = t->pointerTo();
|
||||
|
||||
llvm::Type *T = DtoType(t);
|
||||
llvm::Type *T = DtoType(type);
|
||||
|
||||
// find base type
|
||||
DIType basetype = CreateTypeDescription(t);
|
||||
DIType basetype = CreateTypeDescription(type);
|
||||
|
||||
auto Flags = DIFlags::FlagZero;
|
||||
switch (visibility) {
|
||||
|
@ -515,7 +486,7 @@ void DIBuilder::AddStaticMembers(AggregateDeclaration *ad, DIFile file,
|
|||
if (!members)
|
||||
return;
|
||||
|
||||
auto scope = CreateCompositeTypeDescription(ad->getType());
|
||||
auto scope = CreateCompositeType(ad->getType());
|
||||
|
||||
std::function<void(Dsymbols *)> visitMembers = [&](Dsymbols *members) {
|
||||
for (auto s : *members) {
|
||||
|
@ -547,19 +518,16 @@ void DIBuilder::AddStaticMembers(AggregateDeclaration *ad, DIFile file,
|
|||
visitMembers(members);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateCompositeType(Type *type) {
|
||||
Type *t = type->toBasetype();
|
||||
DIType DIBuilder::CreateCompositeType(Type *t) {
|
||||
assert((t->ty == Tstruct || t->ty == Tclass) &&
|
||||
"Unsupported type for debug info in DIBuilder::CreateCompositeType");
|
||||
|
||||
AggregateDeclaration *ad;
|
||||
if (t->ty == Tstruct) {
|
||||
TypeStruct *ts = static_cast<TypeStruct *>(t);
|
||||
ad = ts->sym;
|
||||
ad = static_cast<TypeStruct *>(t)->sym;
|
||||
} else {
|
||||
TypeClass *tc = static_cast<TypeClass *>(t);
|
||||
ad = tc->sym;
|
||||
ad = static_cast<TypeClass *>(t)->sym;
|
||||
}
|
||||
assert(ad);
|
||||
|
||||
// Use the actual type associated with the declaration, ignoring any
|
||||
// const/wrappers.
|
||||
|
@ -568,7 +536,7 @@ DIType DIBuilder::CreateCompositeType(Type *type) {
|
|||
T = T->getPointerElementType();
|
||||
IrAggr *irAggr = getIrAggr(ad, true);
|
||||
|
||||
if (static_cast<llvm::MDNode *>(irAggr->diCompositeType) != nullptr) {
|
||||
if (irAggr->diCompositeType) {
|
||||
return irAggr->diCompositeType;
|
||||
}
|
||||
|
||||
|
@ -578,7 +546,7 @@ DIType DIBuilder::CreateCompositeType(Type *type) {
|
|||
// if we don't know the aggregate's size, we don't know enough about it
|
||||
// to provide debug info. probably a forward-declared struct?
|
||||
if (ad->sizeok == Sizeok::none) {
|
||||
return DBuilder.createUnspecifiedType(name);
|
||||
return CreateUnspecifiedType(ad);
|
||||
}
|
||||
|
||||
assert(GetCU() && "Compilation unit missing or corrupted");
|
||||
|
@ -592,8 +560,8 @@ DIType DIBuilder::CreateCompositeType(Type *type) {
|
|||
const auto sizeInBits = T->isSized() ? getTypeAllocSize(T) * 8 : 0;
|
||||
const auto alignmentInBits = T->isSized() ? getABITypeAlign(T) * 8 : 0;
|
||||
const auto classOffsetInBits = 0;
|
||||
auto derivedFrom = getNullDIType();
|
||||
const auto vtableHolder = getNullDIType();
|
||||
DIType derivedFrom = nullptr;
|
||||
const auto vtableHolder = nullptr;
|
||||
const auto templateParams = nullptr;
|
||||
const auto uniqueIdentifier = uniqueIdent(t);
|
||||
|
||||
|
@ -645,15 +613,12 @@ DIType DIBuilder::CreateCompositeType(Type *type) {
|
|||
|
||||
irAggr->diCompositeType =
|
||||
DBuilder.replaceTemporary(llvm::TempDINode(irAggr->diCompositeType), ret);
|
||||
irAggr->diCompositeType = ret;
|
||||
|
||||
return ret;
|
||||
return irAggr->diCompositeType;
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateArrayType(Type *type) {
|
||||
DIType DIBuilder::CreateArrayType(TypeArray *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
assert(t->ty == Tarray);
|
||||
|
||||
const auto scope = GetCU();
|
||||
const auto name = processDIName(type->toPrettyChars(true));
|
||||
|
@ -661,7 +626,7 @@ DIType DIBuilder::CreateArrayType(Type *type) {
|
|||
|
||||
LLMetadata *elems[] = {CreateMemberType(0, Type::tsize_t, file, "length", 0,
|
||||
Visibility::public_),
|
||||
CreateMemberType(0, t->nextOf()->pointerTo(), file,
|
||||
CreateMemberType(0, type->nextOf()->pointerTo(), file,
|
||||
"ptr", global.params.is64bit ? 8 : 4,
|
||||
Visibility::public_)};
|
||||
|
||||
|
@ -670,22 +635,20 @@ DIType DIBuilder::CreateArrayType(Type *type) {
|
|||
getTypeAllocSize(T) * 8, // size in bits
|
||||
getABITypeAlign(T) * 8, // alignment in bits
|
||||
DIFlags::FlagZero, // What here?
|
||||
getNullDIType(), // derived from
|
||||
nullptr, // derived from
|
||||
DBuilder.getOrCreateArray(elems),
|
||||
0, // RunTimeLang
|
||||
getNullDIType(), // VTableHolder
|
||||
uniqueIdent(t)); // UniqueIdentifier
|
||||
nullptr, // VTableHolder
|
||||
uniqueIdent(type)); // UniqueIdentifier
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateSArrayType(Type *type) {
|
||||
DIType DIBuilder::CreateSArrayType(TypeSArray *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
assert(t->ty == Tsarray);
|
||||
|
||||
// find base type
|
||||
Type *te = type;
|
||||
llvm::SmallVector<LLMetadata *, 8> subscripts;
|
||||
while (t->ty == Tsarray) {
|
||||
TypeSArray *tsa = static_cast<TypeSArray *>(t);
|
||||
for (; te->ty == Tsarray; te = te->nextOf()) {
|
||||
TypeSArray *tsa = static_cast<TypeSArray *>(te);
|
||||
const auto count = tsa->dim->toInteger();
|
||||
#if LDC_LLVM_VER >= 1100
|
||||
const auto Count = llvm::ConstantAsMetadata::get(DtoConstSize_t(count));
|
||||
|
@ -695,41 +658,29 @@ DIType DIBuilder::CreateSArrayType(Type *type) {
|
|||
const auto subscript = DBuilder.getOrCreateSubrange(0, count);
|
||||
#endif
|
||||
subscripts.push_back(subscript);
|
||||
t = t->nextOf();
|
||||
}
|
||||
|
||||
// element type: void => byte, function => function pointer
|
||||
t = t->toBasetype();
|
||||
if (t->ty == Tvoid)
|
||||
t = Type::tuns8;
|
||||
else if (t->ty == Tfunction)
|
||||
t = t->pointerTo();
|
||||
|
||||
return DBuilder.createArrayType(
|
||||
getTypeAllocSize(T) * 8, // size (bits)
|
||||
getABITypeAlign(T) * 8, // align (bits)
|
||||
CreateTypeDescription(t), // element type
|
||||
CreateTypeDescription(te, /*voidToUbyte=*/true),
|
||||
DBuilder.getOrCreateArray(subscripts) // subscripts
|
||||
);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateAArrayType(Type *type) {
|
||||
DIType DIBuilder::CreateAArrayType(TypeAArray *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
Type *t = type->toBasetype();
|
||||
assert(t->ty == Taarray);
|
||||
|
||||
TypeAArray *typeAArray = static_cast<TypeAArray *>(t);
|
||||
|
||||
Type *index = typeAArray->index;
|
||||
Type *value = typeAArray->nextOf();
|
||||
auto tindex = CreateTypeDescription(type->index);
|
||||
auto tvalue = CreateTypeDescription(type->nextOf());
|
||||
|
||||
const auto scope = GetCU();
|
||||
const auto name = processDIName(type->toPrettyChars(true));
|
||||
const auto file = CreateFile();
|
||||
|
||||
LLMetadata *elems[] = {
|
||||
CreateTypedef(0, index, file, "__key_t"),
|
||||
CreateTypedef(0, value, file, "__val_t"),
|
||||
DBuilder.createTypedef(tindex, "__key_t", file, 0, scope),
|
||||
DBuilder.createTypedef(tvalue, "__val_t", file, 0, scope),
|
||||
CreateMemberType(0, Type::tvoidptr, file, "ptr", 0, Visibility::public_)};
|
||||
|
||||
return DBuilder.createStructType(scope, name, file,
|
||||
|
@ -737,11 +688,11 @@ DIType DIBuilder::CreateAArrayType(Type *type) {
|
|||
getTypeAllocSize(T) * 8, // size in bits
|
||||
getABITypeAlign(T) * 8, // alignment in bits
|
||||
DIFlags::FlagZero, // What here?
|
||||
getNullDIType(), // derived from
|
||||
nullptr, // derived from
|
||||
DBuilder.getOrCreateArray(elems),
|
||||
0, // RunTimeLang
|
||||
getNullDIType(), // VTableHolder
|
||||
uniqueIdent(t)); // UniqueIdentifier
|
||||
nullptr, // VTableHolder
|
||||
uniqueIdent(type)); // UniqueIdentifier
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -750,9 +701,9 @@ DIType DIBuilder::CreateAArrayType(Type *type) {
|
|||
const unsigned DW_CC_D_dmd = 0x43;
|
||||
|
||||
DISubroutineType DIBuilder::CreateFunctionType(Type *type) {
|
||||
assert(type->toBasetype()->ty == Tfunction);
|
||||
TypeFunction *t = type->isTypeFunction();
|
||||
assert(t);
|
||||
|
||||
TypeFunction *t = static_cast<TypeFunction *>(type);
|
||||
Type *retType = t->next;
|
||||
|
||||
// Create "dummy" subroutine type for the return type
|
||||
|
@ -772,52 +723,41 @@ DISubroutineType DIBuilder::CreateEmptyFunctionType() {
|
|||
return DBuilder.createSubroutineType(paramsArray);
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateDelegateType(Type *type) {
|
||||
Type *const tb = type->toBasetype();
|
||||
assert(tb->ty == Tdelegate);
|
||||
auto t = static_cast<TypeDelegate *>(tb);
|
||||
|
||||
DIType DIBuilder::CreateDelegateType(TypeDelegate *type) {
|
||||
llvm::Type *T = DtoType(type);
|
||||
|
||||
const auto scope = GetCU();
|
||||
const auto name = processDIName(type->toPrettyChars(true));
|
||||
const auto file = CreateFile();
|
||||
|
||||
LLMetadata *elems[] = {CreateMemberType(0, Type::tvoidptr, file, "context", 0,
|
||||
LLMetadata *elems[] = {
|
||||
CreateMemberType(0, Type::tvoidptr, file, "context", 0,
|
||||
Visibility::public_),
|
||||
CreateMemberType(0, t->next, file, "funcptr",
|
||||
global.params.is64bit ? 8 : 4,
|
||||
Visibility::public_)};
|
||||
CreateMemberType(0, type->next->pointerTo(), file, "funcptr",
|
||||
global.params.is64bit ? 8 : 4, Visibility::public_)};
|
||||
|
||||
return DBuilder.createStructType(scope, name, file,
|
||||
0, // line number where defined
|
||||
getTypeAllocSize(T) * 8, // size in bits
|
||||
getABITypeAlign(T) * 8, // alignment in bits
|
||||
DIFlags::FlagZero, // flags
|
||||
getNullDIType(), // derived from
|
||||
nullptr, // derived from
|
||||
DBuilder.getOrCreateArray(elems),
|
||||
0, // RunTimeLang
|
||||
getNullDIType(), // VTableHolder
|
||||
nullptr, // VTableHolder
|
||||
uniqueIdent(type)); // UniqueIdentifier
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateUnspecifiedType(Dsymbol *sym) {
|
||||
return DBuilder.createUnspecifiedType(
|
||||
processDIName(sym->toPrettyChars(true)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool isOpaqueEnumType(Type *type) {
|
||||
if (type->ty != Tenum)
|
||||
return false;
|
||||
|
||||
TypeEnum *te = static_cast<TypeEnum *>(type);
|
||||
return !te->sym->memtype;
|
||||
}
|
||||
|
||||
DIType DIBuilder::CreateTypeDescription(Type *type) {
|
||||
// Check for opaque enum first, Bugzilla 13792
|
||||
if (isOpaqueEnumType(type)) {
|
||||
const auto ed = static_cast<TypeEnum *>(type)->sym;
|
||||
return DBuilder.createUnspecifiedType(ed->toChars());
|
||||
}
|
||||
|
||||
Type *t = type->toBasetype();
|
||||
DIType DIBuilder::CreateTypeDescription(Type *t, bool voidToUbyte) {
|
||||
if (voidToUbyte && t->toBasetype()->ty == Tvoid)
|
||||
t = Type::tuns8;
|
||||
|
||||
if (t->ty == Tvoid || t->ty == Tnoreturn)
|
||||
return nullptr;
|
||||
|
@ -827,45 +767,40 @@ DIType DIBuilder::CreateTypeDescription(Type *type) {
|
|||
/* DWARFAddressSpace */ llvm::None,
|
||||
"typeof(null)");
|
||||
}
|
||||
if (t->ty == Tvector)
|
||||
return CreateVectorType(type);
|
||||
if (t->isintegral() || t->isfloating()) {
|
||||
if (type->ty == Tenum)
|
||||
return CreateEnumType(type);
|
||||
return CreateBasicType(type);
|
||||
}
|
||||
if (t->ty == Tpointer)
|
||||
return CreatePointerType(type);
|
||||
if (t->ty == Tarray)
|
||||
return CreateArrayType(type);
|
||||
if (t->ty == Tsarray)
|
||||
return CreateSArrayType(type);
|
||||
if (t->ty == Taarray)
|
||||
return CreateAArrayType(type);
|
||||
if (auto te = t->isTypeEnum())
|
||||
return CreateEnumType(te);
|
||||
if (auto tv = t->isTypeVector())
|
||||
return CreateVectorType(tv);
|
||||
if (t->isintegral() || t->isfloating())
|
||||
return CreateBasicType(t);
|
||||
if (auto tp = t->isTypePointer())
|
||||
return CreatePointerType(tp);
|
||||
if (auto ta = t->isTypeDArray())
|
||||
return CreateArrayType(ta);
|
||||
if (auto tsa = t->isTypeSArray())
|
||||
return CreateSArrayType(tsa);
|
||||
if (auto taa = t->isTypeAArray())
|
||||
return CreateAArrayType(taa);
|
||||
if (t->ty == Tstruct)
|
||||
return CreateCompositeType(type);
|
||||
if (t->ty == Tclass) {
|
||||
return CreateCompositeType(t);
|
||||
if (auto tc = t->isTypeClass()) {
|
||||
LLType *T = DtoType(t);
|
||||
const auto aggregateDIType = CreateCompositeType(type);
|
||||
const auto name = (aggregateDIType->getName() + "*").str();
|
||||
const auto aggregateDIType = CreateCompositeType(t);
|
||||
const auto name =
|
||||
(tc->sym->toPrettyChars(true) + llvm::StringRef("*")).str();
|
||||
return DBuilder.createPointerType(aggregateDIType, getTypeAllocSize(T) * 8,
|
||||
getABITypeAlign(T) * 8, llvm::None, name);
|
||||
getABITypeAlign(T) * 8, llvm::None,
|
||||
processDIName(name));
|
||||
}
|
||||
if (t->ty == Tfunction)
|
||||
return CreateFunctionType(type);
|
||||
if (t->ty == Tdelegate)
|
||||
return CreateDelegateType(type);
|
||||
if (auto tf = t->isTypeFunction())
|
||||
return CreateFunctionType(tf);
|
||||
if (auto td = t->isTypeDelegate())
|
||||
return CreateDelegateType(td);
|
||||
|
||||
// Crash if the type is not supported.
|
||||
llvm_unreachable("Unsupported type in debug info");
|
||||
}
|
||||
|
||||
DICompositeType DIBuilder::CreateCompositeTypeDescription(Type *type) {
|
||||
DIType ret = type->toBasetype()->ty == Tclass ? CreateCompositeType(type)
|
||||
: CreateTypeDescription(type);
|
||||
return llvm::cast<llvm::DICompositeType>(ret);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::DICompileUnit::DebugEmissionKind getDebugEmissionKind() {
|
||||
|
@ -998,7 +933,7 @@ DISubprogram DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
|
|||
if (emitCodeView && fd->toParent2()->isFuncDeclaration()) {
|
||||
// emit into module & use fully qualified name
|
||||
scope = GetCU();
|
||||
name = fd->toPrettyChars(true);
|
||||
name = processDIName(fd->toPrettyChars(true));
|
||||
} else if (fd->isMain()) {
|
||||
scope = GetSymbolScope(fd);
|
||||
name = fd->toPrettyChars(true); // `D main`
|
||||
|
@ -1040,7 +975,7 @@ DISubprogram DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
|
|||
);
|
||||
|
||||
// Now create subroutine type.
|
||||
diFnType = CreateFunctionType(static_cast<TypeFunction *>(fd->type));
|
||||
diFnType = CreateFunctionType(fd->type);
|
||||
}
|
||||
|
||||
// FIXME: duplicates?
|
||||
|
|
|
@ -167,12 +167,10 @@ private:
|
|||
DIFile CreateFile();
|
||||
DIFile CreateFile(Dsymbol* decl);
|
||||
DIType CreateBasicType(Type *type);
|
||||
DIType CreateEnumType(Type *type);
|
||||
DIType CreatePointerType(Type *type);
|
||||
DIType CreateVectorType(Type *type);
|
||||
DIType CreateEnumType(TypeEnum *type);
|
||||
DIType CreatePointerType(TypePointer *type);
|
||||
DIType CreateVectorType(TypeVector *type);
|
||||
DIType CreateComplexType(Type *type);
|
||||
DIType CreateTypedef(unsigned linnum, Type *type, DIFile file,
|
||||
const char *c_name);
|
||||
DIType CreateMemberType(unsigned linnum, Type *type, DIFile file,
|
||||
const char *c_name, unsigned offset, Visibility::Kind,
|
||||
bool isStatic = false, DIScope scope = nullptr);
|
||||
|
@ -183,14 +181,14 @@ private:
|
|||
bool isOptimized, unsigned scopeLine,
|
||||
DIFlags flags);
|
||||
DIType CreateCompositeType(Type *type);
|
||||
DIType CreateArrayType(Type *type);
|
||||
DIType CreateSArrayType(Type *type);
|
||||
DIType CreateAArrayType(Type *type);
|
||||
DIType CreateArrayType(TypeArray *type);
|
||||
DIType CreateSArrayType(TypeSArray *type);
|
||||
DIType CreateAArrayType(TypeAArray *type);
|
||||
DISubroutineType CreateFunctionType(Type *type);
|
||||
DISubroutineType CreateEmptyFunctionType();
|
||||
DIType CreateDelegateType(Type *type);
|
||||
DIType CreateTypeDescription(Type *type);
|
||||
DICompositeType CreateCompositeTypeDescription(Type *type);
|
||||
DIType CreateDelegateType(TypeDelegate *type);
|
||||
DIType CreateUnspecifiedType(Dsymbol *sym);
|
||||
DIType CreateTypeDescription(Type *type, bool voidToUbyte = false);
|
||||
|
||||
bool mustEmitFullDebugInfo();
|
||||
bool mustEmitLocationsDebugInfo();
|
||||
|
|
|
@ -1244,8 +1244,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
emitDMDStyleFunctionTrace(*gIR, fd, funcGen);
|
||||
}
|
||||
|
||||
// disable frame-pointer-elimination for functions with inline asm
|
||||
if (fd->hasReturnExp & 8) // has inline asm
|
||||
// disable frame-pointer-elimination for functions with DMD-style inline asm
|
||||
if (fd->hasReturnExp & 32)
|
||||
{
|
||||
#if LDC_LLVM_VER >= 800
|
||||
func->addFnAttr(
|
||||
|
|
21
tests/codegen/asm_gcc_no_fp.d
Normal file
21
tests/codegen/asm_gcc_no_fp.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Makes sure the frame pointer isn't enforced for GCC-style asm.
|
||||
|
||||
// REQUIRES: target_X86
|
||||
|
||||
// RUN: %ldc -mtriple=x86_64-linux-gnu -mattr=avx -O -output-s -of=%t.s %s
|
||||
// RUN: FileCheck %s < %t.s
|
||||
|
||||
alias byte32 = __vector(byte[32]);
|
||||
|
||||
// CHECK: _D13asm_gcc_no_fp3xorFNhG32gQgZQj:
|
||||
byte32 xor(byte32 a, byte32 b)
|
||||
{
|
||||
// CHECK-NEXT: .cfi_startproc
|
||||
byte32 r;
|
||||
// CHECK-NEXT: #APP
|
||||
// CHECK-NEXT: vxorps %ymm0, %ymm1, %ymm0
|
||||
// CHECK-NEXT: #NO_APP
|
||||
asm { "vxorps %0, %1, %2" : "=v" (r) : "v" (a), "v" (b); }
|
||||
// CHECK-NEXT: retq
|
||||
return r;
|
||||
}
|
|
@ -87,7 +87,8 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,
|
|||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr :
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
// CHECK-G-SAME: args_cdb.main.__lambda
|
||||
// CHECK-GC-SAME: args_cdb::main::__lambda
|
||||
|
||||
// CDB: ?? slice
|
||||
// CHECK-G: struct int[]
|
||||
|
@ -134,7 +135,7 @@ int byValue(ubyte ub, ushort us, uint ui, ulong ul,
|
|||
*/
|
||||
size_t byValueShort(Large large)
|
||||
{
|
||||
// CDB: bp1 /1 `args_cdb.d:137`
|
||||
// CDB: bp1 /1 `args_cdb.d:138`
|
||||
// CDB: g
|
||||
// CHECK: Breakpoint 1 hit
|
||||
// CHECK-G: !args_cdb.byValueShort
|
||||
|
@ -160,7 +161,7 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
|
|||
Small* small, Large* large,
|
||||
TypeInfo_Class* ti, typeof(null)* np)
|
||||
{
|
||||
// CDB: bp2 /1 `args_cdb.d:163`
|
||||
// CDB: bp2 /1 `args_cdb.d:164`
|
||||
// CDB: g
|
||||
// CHECK: Breakpoint 2 hit
|
||||
// CHECK-G: !args_cdb.byPtr
|
||||
|
@ -189,7 +190,8 @@ int byPtr(ubyte* ub, ushort* us, uint* ui, ulong* ul,
|
|||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr :
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
// CHECK-G-SAME: args_cdb.main.__lambda
|
||||
// CHECK-GC-SAME: args_cdb::main::__lambda
|
||||
// CDB: ?? *fun
|
||||
// CHECK: <function> *
|
||||
// CDB: ?? *slice
|
||||
|
@ -235,7 +237,7 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
ref Small small, ref Large large,
|
||||
ref TypeInfo_Class ti, ref typeof(null) np)
|
||||
{
|
||||
// CDB: bp3 /1 `args_cdb.d:238`
|
||||
// CDB: bp3 /1 `args_cdb.d:240`
|
||||
// CDB: g
|
||||
// CHECK: Breakpoint 3 hit
|
||||
// CHECK-G: !args_cdb.byRef
|
||||
|
@ -265,7 +267,8 @@ int byRef(ref ubyte ub, ref ushort us, ref uint ui, ref ulong ul,
|
|||
// CHECK: int delegate()
|
||||
// CHECK-NEXT: context :
|
||||
// CHECK-NEXT: funcptr : {{0x[0-9a-f`]*}}
|
||||
// CHECK-SAME: args_cdb.main.__lambda
|
||||
// CHECK-G-SAME: args_cdb.main.__lambda
|
||||
// CHECK-GC-SAME: args_cdb::main::__lambda
|
||||
// CDB: ?? *fun
|
||||
// CHECK: <function> * {{0x[0-9a-f`]*}}
|
||||
// CDB: ?? *slice
|
||||
|
|
46
tests/debuginfo/enums_cdb.d
Normal file
46
tests/debuginfo/enums_cdb.d
Normal file
|
@ -0,0 +1,46 @@
|
|||
// REQUIRES: Windows
|
||||
// REQUIRES: cdb
|
||||
|
||||
// RUN: %ldc -g -of=%t.exe %s
|
||||
// RUN: sed -e "/^\\/\\/ CDB:/!d" -e "s,// CDB:,," %s \
|
||||
// RUN: | %cdb -snul -lines -y . %t.exe >%t.out
|
||||
// RUN: FileCheck %s < %t.out
|
||||
|
||||
enum E : byte { x, y, z }
|
||||
|
||||
enum D : double { d0, d1, d123 = 123.0 };
|
||||
|
||||
struct S { E e; D d; }
|
||||
|
||||
void foo(E e, D d, S s)
|
||||
{
|
||||
auto bla = s; // somehow needed for s to show up...
|
||||
|
||||
// CDB: ld /f enums_cdb*
|
||||
// enable case sensitive symbol lookup
|
||||
// CDB: .symopt-1
|
||||
// CDB: bp0 /1 `enums_cdb.d:22`
|
||||
// CDB: g
|
||||
// CHECK: Breakpoint 0 hit
|
||||
// CHECK: !enums_cdb.foo
|
||||
|
||||
// CDB: ?? e
|
||||
// CHECK: enums_cdb.E y
|
||||
|
||||
// CDB: ?? d
|
||||
// CHECK-NEXT: double 1
|
||||
|
||||
// CDB: ?? s.e
|
||||
// CHECK-NEXT: enums_cdb.E z
|
||||
|
||||
// CDB: ?? s.d
|
||||
// CHECK-NEXT: double 123
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
foo(E.y, D.d1, S(E.z, D.d123));
|
||||
}
|
||||
|
||||
// CDB: q
|
||||
// CHECK: quit:
|
Loading…
Add table
Add a link
Reference in a new issue