From f05c4efde8bb82a275b2f81883298e33ef2edd86 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 16 Feb 2023 12:54:58 +0000 Subject: [PATCH] Tweak and extend handling of DWARF debug metadata --- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 3 + .../driver/shaders/dxil/dxil_debuginfo.cpp | 108 +++++++++++++++--- .../driver/shaders/dxil/dxil_debuginfo.h | 59 ++++++++-- 3 files changed, 147 insertions(+), 23 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index cd66631bd..e96c3c0ca 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -755,6 +755,9 @@ struct DIBase Expression, LexicalBlock, Subrange, + Namespace, + ImportedEntity, + Enum, } type; DIBase(Type t) : type(t) {} diff --git a/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp b/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp index 8fe08dfda..b65e40f06 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp @@ -29,6 +29,15 @@ namespace DXIL { +// DXIL is SO AWFUL. There is an svbr encoding used for the bitcode which negates and shifts. This +// encoding bitwise-nots and shifts, for no reason? +static int64_t debug_only_svbr(uint64_t val) +{ + if(val & 0x1) + return int64_t(~(val >> 1)); + return val >> 1; +} + bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta) { @@ -102,6 +111,13 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[11]), metadata.getOrNULL(metaRecord.ops[14])}; } + else if(id == LLVMBC::MetaDataRecord::ENUMERATOR) + { + meta.isDistinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = + new DIEnum(debug_only_svbr(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2])); + } else if(id == LLVMBC::MetaDataRecord::TEMPLATE_TYPE) { meta.isDistinct = (metaRecord.ops[0] & 0x1); @@ -193,7 +209,7 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr DW_TAG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]), metadata.getStringOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]), metaRecord.ops[5], metadata.getOrNULL(metaRecord.ops[6]), metaRecord.ops[7], - DIFlags(metaRecord.ops[8]), metaRecord.ops[8]); + DIFlags(metaRecord.ops[8])); meta.children = {metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[4]), metadata.getOrNULL(metaRecord.ops[6])}; @@ -212,7 +228,28 @@ bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOr { meta.isDistinct = (metaRecord.ops[0] & 0x1); - meta.dwarf = new DISubrange(metaRecord.ops[1], LLVMBC::BitReader::svbr(metaRecord.ops[2])); + meta.dwarf = new DISubrange(int64_t(metaRecord.ops[1]), debug_only_svbr(metaRecord.ops[2])); + } + else if(id == LLVMBC::MetaDataRecord::NAMESPACE) + { + meta.isDistinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = new DINamespace(metadata.getOrNULL(metaRecord.ops[1]), + metadata.getOrNULL(metaRecord.ops[2]), + metadata.getStringOrNULL(metaRecord.ops[3]), metaRecord.ops[4]); + + meta.children = {metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2])}; + } + else if(id == LLVMBC::MetaDataRecord::IMPORTED_ENTITY) + { + meta.isDistinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = + new DIImportedEntity(DW_TAG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]), + metadata.getOrNULL(metaRecord.ops[3]), metaRecord.ops[4], + metadata.getStringOrNULL(metaRecord.ops[5])); + + meta.children = {metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[3])}; } else if(id == LLVMBC::MetaDataRecord::EXPRESSION) { @@ -393,6 +430,15 @@ rdcstr DICompositeType::toString() const return ret; } +rdcstr DIEnum::toString() const +{ + rdcstr ret = "!DIEnumerator("; + ret += StringFormat::Fmt("name: %s", escapeString(*name).c_str()); + ret += StringFormat::Fmt(", value: %lld", value); + ret += ")"; + return ret; +} + rdcstr DITemplateTypeParameter::toString() const { return StringFormat::Fmt("!DITemplateTypeParameter(name: %s, type: %s)", @@ -410,16 +456,17 @@ rdcstr DITemplateValueParameter::toString() const rdcstr DISubprogram::toString() const { - rdcstr ret = - StringFormat::Fmt("!DISubprogram(name: %s", escapeString(name ? *name : rdcstr()).c_str()); + rdcstr ret = "!DISubprogram("; + if(name) + ret += StringFormat::Fmt("name: %s, ", escapeString(*name).c_str()); if(linkageName) - ret += StringFormat::Fmt(", linkageName: %s", escapeString(*linkageName).c_str()); + ret += StringFormat::Fmt("linkageName: %s, ", escapeString(*linkageName).c_str()); if(scope) - ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + ret += StringFormat::Fmt("scope: %s, ", scope->refString().c_str()); if(file) - ret += StringFormat::Fmt(", file: %s", file->refString().c_str()); + ret += StringFormat::Fmt("file: %s", file->refString().c_str()); else - ret += ", file: null"; + ret += "file: null"; if(line) ret += StringFormat::Fmt(", line: %llu", line); if(type) @@ -480,6 +527,8 @@ rdcstr DIGlobalVariable::toString() const ret += StringFormat::Fmt(", type: %s", type->refString().c_str()); ret += StringFormat::Fmt(", isLocal: %s", isLocal ? "true" : "false"); ret += StringFormat::Fmt(", isDefinition: %s", isDefinition ? "true" : "false"); + if(declaration) + ret += StringFormat::Fmt(", declaration: %s", declaration->refString().c_str()); if(variable) ret += StringFormat::Fmt(", variable: %s", variable->refString().c_str()); ret += ")"; @@ -490,22 +539,20 @@ rdcstr DILocalVariable::toString() const { rdcstr ret = StringFormat::Fmt("!DILocalVariable(tag: %s, name: %s", ToStr(tag).c_str(), escapeString(name ? *name : rdcstr()).c_str()); - if(arg) + if(arg || tag != DW_TAG_auto_variable) ret += StringFormat::Fmt(", arg: %llu", arg); if(scope) ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + else + ret += ", scope: null"; if(file) ret += StringFormat::Fmt(", file: %s", file->refString().c_str()); - else - ret += ", file: null"; if(line) ret += StringFormat::Fmt(", line: %llu", line); if(type) ret += StringFormat::Fmt(", type: %s", type->refString().c_str()); if(flags != DIFlagNone) ret += StringFormat::Fmt(", flags: %s", ToStr(flags).c_str()); - if(alignInBits) - ret += StringFormat::Fmt(", align: %llu", alignInBits); ret += ")"; return ret; } @@ -553,13 +600,46 @@ rdcstr DILexicalBlock::toString() const rdcstr DISubrange::toString() const { rdcstr ret = "!DISubrange("; - ret += StringFormat::Fmt("count: %llu", count); + ret += StringFormat::Fmt("count: %lld", count); if(lowerBound) ret += StringFormat::Fmt(", lowerBound: %lld", lowerBound); ret += ")"; return ret; } +rdcstr DINamespace::toString() const +{ + rdcstr ret = "!DINamespace("; + if(name) + ret += StringFormat::Fmt("name: %s, ", escapeString(*name).c_str()); + if(scope) + ret += StringFormat::Fmt("scope: %s", scope->refString().c_str()); + else + ret += "scope: null"; + if(file) + ret += StringFormat::Fmt(", file: %s", file->refString().c_str()); + ret += StringFormat::Fmt(", line: %llu", line); + ret += ")"; + return ret; +} + +rdcstr DIImportedEntity::toString() const +{ + rdcstr ret = StringFormat::Fmt("!DIImportedEntity(tag: %s", ToStr(tag).c_str()); + if(name) + ret += StringFormat::Fmt(", name: %s, ", escapeString(*name).c_str()); + if(scope) + ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + else + ret += ", scope: null"; + if(entity) + ret += StringFormat::Fmt(", entity: %s", entity->refString().c_str()); + if(line) + ret += StringFormat::Fmt(", line: %llu", line); + ret += ")"; + return ret; +} + }; // namespace DXIL template <> diff --git a/renderdoc/driver/shaders/dxil/dxil_debuginfo.h b/renderdoc/driver/shaders/dxil/dxil_debuginfo.h index 58d347c51..00b6f7bba 100644 --- a/renderdoc/driver/shaders/dxil/dxil_debuginfo.h +++ b/renderdoc/driver/shaders/dxil/dxil_debuginfo.h @@ -505,6 +505,16 @@ struct DICompositeType : public DIBase virtual rdcstr toString() const; }; +struct DIEnum : public DIBase +{ + static const DIBase::Type DIType = DIBase::Enum; + DIEnum(int64_t value, const rdcstr *name) : DIBase(DIType), value(value), name(name) {} + int64_t value; + const rdcstr *name; + + virtual rdcstr toString() const; +}; + struct DITemplateTypeParameter : public DIBase { static const DIBase::Type DIType = DIBase::TemplateTypeParameter; @@ -607,7 +617,7 @@ struct DIGlobalVariable : public DIBase static const DIBase::Type DIType = DIBase::GlobalVariable; DIGlobalVariable(const Metadata *scope, const rdcstr *name, const rdcstr *linkageName, const Metadata *file, uint64_t line, const Metadata *type, bool isLocal, - bool isDefinition, const Metadata *variable, const Metadata *staticData) + bool isDefinition, const Metadata *variable, const Metadata *declaration) : DIBase(DIType), scope(scope), name(name), @@ -618,7 +628,7 @@ struct DIGlobalVariable : public DIBase isLocal(isLocal), isDefinition(isDefinition), variable(variable), - staticData(staticData) + declaration(declaration) { } @@ -631,7 +641,7 @@ struct DIGlobalVariable : public DIBase bool isLocal; bool isDefinition; const Metadata *variable; - const Metadata *staticData; + const Metadata *declaration; virtual rdcstr toString() const; }; @@ -640,8 +650,7 @@ struct DILocalVariable : public DIBase { static const DIBase::Type DIType = DIBase::LocalVariable; DILocalVariable(DW_TAG tag, const Metadata *scope, const rdcstr *name, const Metadata *file, - uint64_t line, const Metadata *type, uint64_t arg, DIFlags flags, - uint64_t alignInBits) + uint64_t line, const Metadata *type, uint64_t arg, DIFlags flags) : DIBase(DIType), tag(tag), scope(scope), @@ -650,8 +659,7 @@ struct DILocalVariable : public DIBase line(line), type(type), arg(arg), - flags(flags), - alignInBits(alignInBits) + flags(flags) { } @@ -705,17 +713,50 @@ struct DILexicalBlock : public DIBase struct DISubrange : public DIBase { static const DIBase::Type DIType = DIBase::Subrange; - DISubrange(uint64_t count, int64_t lowerBound) + DISubrange(int64_t count, int64_t lowerBound) : DIBase(DIType), count(count), lowerBound(lowerBound) { } - uint64_t count; + int64_t count; int64_t lowerBound; virtual rdcstr toString() const; }; +struct DINamespace : public DIBase +{ + static const DIBase::Type DIType = DIBase::Namespace; + DINamespace(const Metadata *scope, const Metadata *file, const rdcstr *name, uint64_t line) + : DIBase(DIType), scope(scope), file(file), name(name), line(line) + { + } + + const Metadata *scope; + const Metadata *file; + const rdcstr *name; + uint64_t line; + + virtual rdcstr toString() const; +}; + +struct DIImportedEntity : public DIBase +{ + static const DIBase::Type DIType = DIBase::ImportedEntity; + DIImportedEntity(DW_TAG tag, const Metadata *scope, const Metadata *entity, uint64_t line, + const rdcstr *name) + : DIBase(DIType), tag(tag), scope(scope), entity(entity), line(line), name(name) + { + } + + DW_TAG tag; + const Metadata *scope; + const Metadata *entity; + uint64_t line; + const rdcstr *name; + + virtual rdcstr toString() const; +}; }; // namespace DXIL DECLARE_REFLECTION_ENUM(DXIL::DW_LANG);