From 25321e741f289c11e4c795626592936259b8ac91 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 3 Jun 2020 16:14:49 +0100 Subject: [PATCH] Decode metadata for global debug information --- .../driver/shaders/dxil/dxil_bytecode.cpp | 697 +++++++++++------- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 79 +- .../driver/shaders/dxil/dxil_debuginfo.cpp | 643 ++++++++++++++++ .../driver/shaders/dxil/dxil_debuginfo.h | 473 ++++++++++++ .../shaders/dxil/renderdoc_dxil.vcxproj | 2 + .../dxil/renderdoc_dxil.vcxproj.filters | 6 +- 6 files changed, 1624 insertions(+), 276 deletions(-) create mode 100644 renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp create mode 100644 renderdoc/driver/shaders/dxil/dxil_debuginfo.h diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 7b91cc937..1b09e78e7 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -458,40 +458,31 @@ static rdcstr getName(uint32_t parentBlock, const LLVMBC::BlockOrRecord &block) } } -static rdcstr escapeString(rdcstr str) +bool needsEscaping(const rdcstr &name) +{ + return name.find_first_not_of( + "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789") >= 0; +} + +rdcstr escapeString(rdcstr str) { for(size_t i = 0; i < str.size(); i++) { - if(str[i] == '\r') - { - str[i] = 'r'; - str.insert(i, "\\", 1); - i++; - } - else if(str[i] == '\n') - { - str[i] = 'n'; - str.insert(i, "\\", 1); - i++; - } - else if(str[i] == '\t') - { - str[i] = 't'; - str.insert(i, "\\", 1); - i++; - } - else if(str[i] == '\'' || str[i] == '\\') + if(str[i] == '\'' || str[i] == '\\') { str.insert(i, "\\", 1); i++; } - else if(!isprint(str[i])) + else if(str[i] == '\r' || str[i] == '\n' || str[i] == '\t' || !isprint(str[i])) { - str.insert(i + 1, StringFormat::Fmt("x%02x", str[i])); + str.insert(i + 1, StringFormat::Fmt("%02X", str[i])); str[i] = '\\'; } } + str.push_back('"'); + str.insert(0, '"'); + return str; } @@ -510,7 +501,7 @@ static void dumpRecord(size_t idx, uint32_t parentBlock, const LLVMBC::BlockOrRe MetaDataRecord(record.id) == MetaDataRecord::NAME || MetaDataRecord(record.id) == MetaDataRecord::KIND)) { - line += " record string = '" + escapeString(record.getString()) + "'"; + line += " record string = " + escapeString(record.getString()); } else { @@ -525,7 +516,7 @@ static void dumpRecord(size_t idx, uint32_t parentBlock, const LLVMBC::BlockOrRe } if(allASCII && record.ops.size() > 3) - line += " record string = '" + escapeString(record.getString()) + "'"; + line += " record string = " + escapeString(record.getString()); for(size_t i = 0; i < record.ops.size(); i++) line += StringFormat::Fmt(" op%u=%llu", (uint32_t)i, record.ops[i]); @@ -642,15 +633,47 @@ Program::Program(const byte *bytes, size_t length) } else if(IS_KNOWN(rootchild.id, ModuleRecord::GLOBALVAR)) { + // [pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, + // unnamed_addr, externally_initialized, dllstorageclass, comdat] GlobalVar g; + g.type = &m_Types[(size_t)rootchild.ops[0]]; + g.isconst = (rootchild.ops[1] & 0x1); + + switch(rootchild.ops[3]) + { + case 0: + case 5: + case 6: + case 7: + case 15: g.external = true; break; + default: g.external = false; break; + } + + g.align = (1U << rootchild.ops[4]) >> 1; + // symbols refer into any of N types in declaration order m_Symbols.push_back({SymbolType::GlobalVar, m_GlobalVars.size()}); // all global symbols are 'values' in LLVM, we don't need this but need to keep indexing the // same - m_Values.push_back(Value()); + Value v; + v.type = g.type; + v.symbol = true; + for(size_t ty = 0; ty < m_Types.size(); ty++) + { + if(m_Types[ty].type == Type::Pointer && m_Types[ty].inner == g.type) + { + v.type = &m_Types[ty]; + break; + } + } + + if(v.type == g.type) + RDCERR("Expected to find pointer type for global variable"); + + m_Values.push_back(v); m_GlobalVars.push_back(g); } else if(IS_KNOWN(rootchild.id, ModuleRecord::FUNCTION)) @@ -672,7 +695,23 @@ Program::Program(const byte *bytes, size_t length) // all global symbols are 'values' in LLVM, we don't need this but need to keep indexing the // same - m_Values.push_back(Value()); + Value v; + v.symbol = true; + v.type = f.funcType; + + for(size_t ty = 0; ty < m_Types.size(); ty++) + { + if(m_Types[ty].type == Type::Pointer && m_Types[ty].inner == f.funcType) + { + v.type = &m_Types[ty]; + break; + } + } + + if(v.type == f.funcType) + RDCERR("Expected to find pointer type for function"); + + m_Values.push_back(v); if(!f.external) functionDecls.push_back(m_Functions.size()); @@ -689,7 +728,10 @@ Program::Program(const byte *bytes, size_t length) // all global symbols are 'values' in LLVM, we don't need this but need to keep indexing the // same - m_Values.push_back(Value()); + Value v; + v.type = &m_Types[(size_t)rootchild.ops[0]]; + v.symbol = true; + m_Values.push_back(v); m_Aliases.push_back(a); } @@ -876,7 +918,7 @@ Program::Program(const byte *bytes, size_t length) } else if(IS_KNOWN(typ.id, TypeRecord::ARRAY)) { - m_Types[typeIndex].type = Type::Vector; + m_Types[typeIndex].type = Type::Array; m_Types[typeIndex].elemCount = typ.ops[0] & 0xffffffff; m_Types[typeIndex].inner = &m_Types[(size_t)typ.ops[1]]; @@ -887,8 +929,8 @@ Program::Program(const byte *bytes, size_t length) m_Types[typeIndex].type = Type::Pointer; m_Types[typeIndex].inner = &m_Types[(size_t)typ.ops[0]]; - if(typ.ops.size() > 1) - RDCWARN("Ignoring address space on pointer type"); + if(typ.ops.size() > 1 && typ.ops[1] != 0) + RDCERR("Ignoring address space on pointer type"); typeIndex++; } @@ -964,13 +1006,18 @@ Program::Program(const byte *bytes, size_t length) { Value v; v.type = t; + v.undef = IS_KNOWN(constant.id, ConstantsRecord::UNDEF); m_Values.push_back(v); } else if(IS_KNOWN(constant.id, ConstantsRecord::INTEGER)) { Value v; v.type = t; - v.val.value.u64v[0] = constant.ops[0]; + v.val.u64v[0] = constant.ops[0]; + if(v.val.u64v[0] & 0x1) + v.val.s64v[0] = -int64_t(v.val.u64v[0] >> 1); + else + v.val.u64v[0] >>= 1; m_Values.push_back(v); } else if(IS_KNOWN(constant.id, ConstantsRecord::FLOAT)) @@ -978,11 +1025,11 @@ Program::Program(const byte *bytes, size_t length) Value v; v.type = t; if(t->bitWidth == 16) - v.val.value.fv[0] = ConvertFromHalf(uint16_t(constant.ops[0] & 0xffff)); + v.val.fv[0] = ConvertFromHalf(uint16_t(constant.ops[0] & 0xffff)); else if(t->bitWidth == 32) - memcpy(&v.val.value.fv[0], &constant.ops[0], sizeof(float)); + memcpy(&v.val.fv[0], &constant.ops[0], sizeof(float)); else - memcpy(&v.val.value.dv[0], &constant.ops[0], sizeof(float)); + memcpy(&v.val.dv[0], &constant.ops[0], sizeof(float)); m_Values.push_back(v); } else if(IS_KNOWN(constant.id, ConstantsRecord::STRING)) @@ -1005,9 +1052,9 @@ Program::Program(const byte *bytes, size_t length) if(idx < m_Values.size()) { if(v.type->bitWidth <= 32) - v.val.value.uv[m] = m_Values[idx].val.value.uv[m]; + v.val.uv[m] = m_Values[idx].val.uv[m]; else - v.val.value.u64v[m] = m_Values[idx].val.value.u64v[m]; + v.val.u64v[m] = m_Values[idx].val.u64v[m]; } else { @@ -1022,11 +1069,11 @@ Program::Program(const byte *bytes, size_t length) size_t idx = (size_t)m; if(idx < m_Values.size()) { - v.val.members.push_back(m_Values[idx].val); + v.members.push_back(m_Values[idx]); } else { - v.val.members.push_back(ShaderVariable()); + v.members.push_back(Value()); RDCERR("Index %zu out of bounds for values array", idx); } } @@ -1042,21 +1089,22 @@ Program::Program(const byte *bytes, size_t length) for(size_t m = 0; m < constant.ops.size(); m++) { if(v.type->bitWidth <= 32) - v.val.value.uv[m] = constant.ops[m] & ((1ULL << v.type->bitWidth) - 1); + v.val.uv[m] = constant.ops[m] & ((1ULL << v.type->bitWidth) - 1); else - v.val.value.u64v[m] = constant.ops[m]; + v.val.u64v[m] = constant.ops[m]; } } else { for(size_t m = 0; m < constant.ops.size(); m++) { - ShaderVariable el; - if(v.type->bitWidth <= 32) - el.value.uv[0] = constant.ops[m] & ((1ULL << v.type->bitWidth) - 1); + Value el; + el.type = v.type->inner; + if(el.type->bitWidth <= 32) + el.val.uv[0] = constant.ops[m] & ((1ULL << el.type->bitWidth) - 1); else - el.value.u64v[m] = constant.ops[m]; - v.val.members.push_back(el); + el.val.u64v[m] = constant.ops[m]; + v.members.push_back(el); } } m_Values.push_back(v); @@ -1083,9 +1131,15 @@ Program::Program(const byte *bytes, size_t length) size_t idx = m_Symbols[s].idx; switch(m_Symbols[s].type) { - case SymbolType::GlobalVar: m_GlobalVars[idx].name = symtab.getString(1); break; - case SymbolType::Function: m_Functions[idx].name = symtab.getString(1); break; - case SymbolType::Alias: m_Aliases[idx].name = symtab.getString(1); break; + case SymbolType::GlobalVar: + m_Values[s].str = m_GlobalVars[idx].name = symtab.getString(1); + break; + case SymbolType::Function: + m_Values[s].str = m_Functions[idx].name = symtab.getString(1); + break; + case SymbolType::Alias: + m_Values[s].str = m_Aliases[idx].name = symtab.getString(1); + break; } } else @@ -1096,176 +1150,68 @@ Program::Program(const byte *bytes, size_t length) } else if(IS_KNOWN(rootchild.id, KnownBlocks::METADATA_BLOCK)) { + m_Metadata.resize_for_index(rootchild.children.size() - 1); for(size_t i = 0; i < rootchild.children.size(); i++) { - const LLVMBC::BlockOrRecord &meta = rootchild.children[i]; - if(IS_KNOWN(meta.id, MetaDataRecord::NAME)) + const LLVMBC::BlockOrRecord &metaRecord = rootchild.children[i]; + if(IS_KNOWN(metaRecord.id, MetaDataRecord::NAME)) { - rdcstr metaName = meta.getString(); + NamedMetadata meta; + + meta.name = metaRecord.getString(); i++; const LLVMBC::BlockOrRecord &namedNode = rootchild.children[i]; RDCASSERT(IS_KNOWN(namedNode.id, MetaDataRecord::NAMED_NODE)); - rdcstr namedMeta = StringFormat::Fmt("!%s = !{", metaName.c_str()); - - bool first = true; for(uint64_t op : namedNode.ops) - { - if(!first) - namedMeta += ", "; - namedMeta += ToStr(op); - first = false; - } - namedMeta += "}"; + meta.children.push_back(&m_Metadata[(size_t)op]); - RDCLOG("%s", namedMeta.c_str()); + m_NamedMeta.push_back(meta); + } + else if(IS_KNOWN(metaRecord.id, MetaDataRecord::KIND)) + { + size_t kind = (size_t)metaRecord.ops[0]; + m_Kinds.resize(RDCMAX(m_Kinds.size(), kind + 1)); + m_Kinds[kind] = metaRecord.getString(1); + continue; } else { - if(IS_KNOWN(meta.id, MetaDataRecord::KIND)) - { - size_t kind = (size_t)meta.ops[0]; - m_Kinds.resize(RDCMAX(m_Kinds.size(), kind + 1)); - m_Kinds[kind] = meta.getString(1); - continue; - } + Metadata &meta = m_Metadata[i]; - rdcstr metastr = StringFormat::Fmt("!%u = ", (uint32_t)i); - - auto getMetaString = [&rootchild](uint64_t id) -> rdcstr { - return id ? rootchild.children[size_t(id - 1)].getString() : "NULL"; + auto getMeta = [this](uint64_t id) { return id ? &m_Metadata[size_t(id - 1)] : NULL; }; + auto getMetaString = [this](uint64_t id) { + return id ? &m_Metadata[size_t(id - 1)].str : NULL; }; - if(IS_KNOWN(meta.id, MetaDataRecord::STRING_OLD)) + if(IS_KNOWN(metaRecord.id, MetaDataRecord::STRING_OLD)) { - metastr += "\"" + escapeString(meta.getString()) + "\""; + meta.value = true; + meta.str = metaRecord.getString(); } - else if(IS_KNOWN(meta.id, MetaDataRecord::FILE)) + else if(IS_KNOWN(metaRecord.id, MetaDataRecord::VALUE)) { - if(meta.ops[0]) - metastr += "distinct "; + meta.value = true; + meta.val = &m_Values[(size_t)metaRecord.ops[1]]; + meta.type = &m_Types[(size_t)metaRecord.ops[0]]; + } + else if(IS_KNOWN(metaRecord.id, MetaDataRecord::NODE) || + IS_KNOWN(metaRecord.id, MetaDataRecord::DISTINCT_NODE)) + { + if(IS_KNOWN(metaRecord.id, MetaDataRecord::DISTINCT_NODE)) + meta.distinct = true; - metastr += "!DIFile("; - metastr += StringFormat::Fmt("filename: \"%s\"", - escapeString(getMetaString(meta.ops[1])).c_str()); - metastr += StringFormat::Fmt(", directory: \"%s\"", - escapeString(getMetaString(meta.ops[2])).c_str()); - metastr += ")"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::NODE) || - IS_KNOWN(meta.id, MetaDataRecord::DISTINCT_NODE)) - { - if(IS_KNOWN(meta.id, MetaDataRecord::DISTINCT_NODE)) - metastr += "distinct "; - - metastr += "!{"; - bool first = true; - for(uint64_t op : meta.ops) - { - if(!first) - metastr += ", "; - metastr += ToStr(op - 1); - first = false; - } - metastr += "}"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::BASIC_TYPE)) - { - metastr += "!DIBasicType()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::DERIVED_TYPE)) - { - metastr += "!DIDerivedType()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::COMPOSITE_TYPE)) - { - metastr += "!DICompositeType()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::SUBROUTINE_TYPE)) - { - metastr += "!DISubroutineType()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::TEMPLATE_TYPE)) - { - metastr += "!DITemplateTypeParameter()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::TEMPLATE_VALUE)) - { - metastr += "!DITemplateValueParameter()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::SUBPROGRAM)) - { - metastr += "!DISubprogram()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::LOCATION)) - { - metastr += "!DILocation()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::LOCAL_VAR)) - { - metastr += "!DILocalVariable()"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::VALUE)) - { - // need to decode CONSTANTS_BLOCK and TYPE_BLOCK for this - metastr += StringFormat::Fmt("!{values[%llu] interpreted as types[%llu]}", - meta.ops[1], meta.ops[0]); - } - else if(IS_KNOWN(meta.id, MetaDataRecord::EXPRESSION)) - { - // don't decode this yet - metastr += "!DIExpression("; - bool first = true; - for(uint64_t op : meta.ops) - { - if(!first) - metastr += ", "; - metastr += ToStr(op); - first = false; - } - metastr += ")"; - } - else if(IS_KNOWN(meta.id, MetaDataRecord::COMPILE_UNIT)) - { - // should be at least 14 parameters - RDCASSERT(meta.ops.size() >= 14); - - // we expect it to be marked as distinct, but we'll always treat it that way - if(meta.ops[0]) - metastr += "distinct "; - else - metastr += "distinct? "; - - metastr += "!DICompileUnit("; - { - metastr += StringFormat::Fmt( - "language: %s", meta.ops[1] == 0x4 ? "DW_LANG_C_plus_plus" : "DW_LANG_unknown"); - metastr += StringFormat::Fmt(", file: !%llu", meta.ops[2] - 1); - metastr += StringFormat::Fmt(", producer: \"%s\"", - escapeString(getMetaString(meta.ops[3])).c_str()); - metastr += StringFormat::Fmt(", isOptimized: %s", meta.ops[4] ? "true" : "false"); - metastr += StringFormat::Fmt(", flags: \"%s\"", - escapeString(getMetaString(meta.ops[5])).c_str()); - metastr += StringFormat::Fmt(", runtimeVersion: %llu", meta.ops[6]); - metastr += StringFormat::Fmt(", splitDebugFilename: \"%s\"", - escapeString(getMetaString(meta.ops[7])).c_str()); - metastr += StringFormat::Fmt(", emissionKind: %llu", meta.ops[8]); - metastr += StringFormat::Fmt(", enums: !%llu", meta.ops[9] - 1); - metastr += StringFormat::Fmt(", retainedTypes: !%llu", meta.ops[10] - 1); - metastr += StringFormat::Fmt(", subprograms: !%llu", meta.ops[11] - 1); - metastr += StringFormat::Fmt(", globals: !%llu", meta.ops[12] - 1); - metastr += StringFormat::Fmt(", imports: !%llu", meta.ops[13] - 1); - if(meta.ops.size() >= 15) - metastr += StringFormat::Fmt(", dwoId: 0x%llu", meta.ops[14]); - } - metastr += ")"; + for(uint64_t op : metaRecord.ops) + meta.children.push_back(getMeta(op)); } else { - RDCERR("unhandled metadata type %u", meta.id); + bool parsed = ParseDebugMetaRecord(metaRecord, meta); + if(!parsed) + { + RDCERR("unhandled metadata type %u", metaRecord.id); + } } - - RDCLOG("%s", metastr.c_str()); } } } @@ -1281,7 +1227,7 @@ Program::Program(const byte *bytes, size_t length) } } - dumpBlock(root, 0); + (void)&dumpBlock; } void Program::FetchComputeProperties(DXBC::Reflection *reflection) @@ -1311,8 +1257,6 @@ uint32_t Program::GetDisassemblyLine(uint32_t instruction) const void Program::MakeDisassemblyString() { - RDCWARN("Unimplemented DXIL::Program::MakeDisassemblyString()"); - const char *shaderName[] = { "Pixel", "Vertex", "Geometry", "Hull", "Domain", "Compute", "Library", "RayGeneration", "Intersection", "AnyHit", @@ -1321,8 +1265,8 @@ void Program::MakeDisassemblyString() m_Disassembly = StringFormat::Fmt("; %s Shader, compiled under SM%u.%u\n\n", shaderName[int(m_Type)], m_Major, m_Minor); - m_Disassembly += StringFormat::Fmt("target triple = \"%s\"\n", m_Triple.c_str()); - m_Disassembly += StringFormat::Fmt("target datalayout = \"%s\"\n\n", m_Datalayout.c_str()); + m_Disassembly += StringFormat::Fmt("target datalayout = \"%s\"\n", m_Datalayout.c_str()); + m_Disassembly += StringFormat::Fmt("target triple = \"%s\"\n\n", m_Triple.c_str()); bool typesPrinted = false; @@ -1332,7 +1276,7 @@ void Program::MakeDisassemblyString() if(typ.type == Type::Struct && !typ.name.empty()) { - rdcstr name = typ.getTypeName(); + rdcstr name = typ.toString(); m_Disassembly += StringFormat::Fmt("%s = type {", name.c_str()); bool first = true; for(const Type *t : typ.members) @@ -1340,7 +1284,7 @@ void Program::MakeDisassemblyString() if(!first) m_Disassembly += ", "; first = false; - m_Disassembly += StringFormat::Fmt(" %s", t->getTypeName().c_str()); + m_Disassembly += StringFormat::Fmt(" %s", t->toString().c_str()); } m_Disassembly += " }\n"; typesPrinted = true; @@ -1350,6 +1294,27 @@ void Program::MakeDisassemblyString() if(typesPrinted) m_Disassembly += "\n"; + for(size_t i = 0; i < m_GlobalVars.size(); i++) + { + const GlobalVar &g = m_GlobalVars[i]; + + m_Disassembly += StringFormat::Fmt( + "@%s = ", needsEscaping(g.name) ? escapeString(g.name).c_str() : g.name.c_str()); + if(g.external) + m_Disassembly += "external "; + if(g.isconst) + m_Disassembly += "constant "; + m_Disassembly += g.type->toString(); + + if(g.align > 0) + m_Disassembly += StringFormat::Fmt(", align %u", g.align); + + m_Disassembly += "\n"; + } + + if(!m_GlobalVars.empty()) + m_Disassembly += "\n"; + for(size_t i = 0; i < m_Functions.size(); i++) { const Function &func = m_Functions[i]; @@ -1377,21 +1342,65 @@ void Program::MakeDisassemblyString() for(size_t i = 0; i < m_Attributes.size(); i++) m_Disassembly += - StringFormat::Fmt("attributes #%zu = %s\n", i, m_Attributes[i].toString().c_str()); + StringFormat::Fmt("attributes #%zu = { %s }\n", i, m_Attributes[i].toString().c_str()); - m_Disassembly += "; No disassembly implemented"; + if(!m_Attributes.empty()) + m_Disassembly += "\n"; + + for(size_t i = 0; i < m_NamedMeta.size(); i++) + { + m_Disassembly += StringFormat::Fmt("!%s = %s!{", m_NamedMeta[i].name.c_str(), + m_NamedMeta[i].distinct ? "distinct " : ""); + for(size_t m = 0; m < m_NamedMeta[i].children.size(); m++) + { + if(m != 0) + m_Disassembly += ", "; + if(m_NamedMeta[i].children[m]) + m_Disassembly += StringFormat::Fmt("!%u", GetOrAssignMetaID(m_NamedMeta[i].children[m])); + else + m_Disassembly += "null"; + } + + m_Disassembly += "}\n"; + } + + m_Disassembly += "\n"; + + for(size_t i = 0; i < m_NumberedMeta.size(); i++) + m_Disassembly += StringFormat::Fmt("%s = %s%s\n", m_NumberedMeta[i]->refString(), + m_NumberedMeta[i]->distinct ? "distinct " : "", + m_NumberedMeta[i]->valString().c_str()); + + m_Disassembly += "\n"; } -rdcstr Type::getTypeName() const +uint32_t Program::GetOrAssignMetaID(Metadata *m) +{ + if(m->id != ~0U) + return m->id; + + m->id = (uint32_t)m_NumberedMeta.size(); + m_NumberedMeta.push_back(m); + + // assign meta IDs to the children now + for(Metadata *c : m->children) + { + if(!c || c->value) + continue; + + GetOrAssignMetaID(c); + } + + return m->id; +} + +rdcstr Type::toString() const { if(!name.empty()) { // needs escaping - if(name.find_first_not_of( - "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789") >= 0) - { - return "%\"" + escapeString(name) + "\""; - } + if(needsEscaping(name)) + return "%" + escapeString(name); return "%" + name; } @@ -1415,9 +1424,9 @@ rdcstr Type::getTypeName() const } } } - case Vector: return StringFormat::Fmt("<%u x %s>", elemCount, inner->getTypeName().c_str()); - case Pointer: return StringFormat::Fmt("%s*", inner->getTypeName().c_str()); - case Array: return StringFormat::Fmt("[%u x %s]", elemCount, inner->getTypeName().c_str()); + case Vector: return StringFormat::Fmt("<%u x %s>", elemCount, inner->toString().c_str()); + case Pointer: return StringFormat::Fmt("%s*", inner->toString().c_str()); + case Array: return StringFormat::Fmt("[%u x %s]", elemCount, inner->toString().c_str()); case Function: return declFunction(rdcstr()); case Struct: { @@ -1430,7 +1439,7 @@ rdcstr Type::getTypeName() const { if(i > 0) ret += ", "; - ret += members[i]->getTypeName(); + ret += members[i]->toString(); } if(packedStruct) ret += "}>"; @@ -1447,13 +1456,13 @@ rdcstr Type::getTypeName() const rdcstr Type::declFunction(rdcstr funcName) const { - rdcstr ret = inner->getTypeName(); + rdcstr ret = inner->toString(); ret += " " + funcName + "("; for(size_t i = 0; i < members.size(); i++) { if(i > 0) ret += ", "; - ret += members[i]->getTypeName(); + ret += members[i]->toString(); } ret += ")"; return ret; @@ -1461,40 +1470,188 @@ rdcstr Type::declFunction(rdcstr funcName) const rdcstr Attributes::toString() const { - rdcstr ret = "{"; + rdcstr ret = ""; Attribute p = params; if(p & Attribute::Alignment) { - ret += StringFormat::Fmt(" Alignment(%llu)", align); + ret += StringFormat::Fmt(" align=%llu", align); p &= ~Attribute::Alignment; } if(p & Attribute::StackAlignment) { - ret += StringFormat::Fmt(" StackAlignment(%llu)", stackAlign); + ret += StringFormat::Fmt(" alignstack=%llu", stackAlign); p &= ~Attribute::StackAlignment; } if(p & Attribute::Dereferenceable) { - ret += StringFormat::Fmt(" Dereferenceable(%llu)", derefBytes); + ret += StringFormat::Fmt(" dereferenceable=%llu", derefBytes); p &= ~Attribute::Dereferenceable; } if(p & Attribute::DereferenceableOrNull) { - ret += StringFormat::Fmt(" DereferenceableOrNull(%llu)", derefOrNullBytes); + ret += StringFormat::Fmt(" dereferenceable_or_null=%llu", derefOrNullBytes); p &= ~Attribute::DereferenceableOrNull; } if(p != Attribute::None) - ret += " " + ToStr(p); + { + ret = ToStr(p) + " " + ret; + int offs = ret.indexOf('|'); + while(offs >= 0) + { + ret.erase((size_t)offs, 2); + offs = ret.indexOf('|'); + } + } for(const rdcpair &str : strs) - ret += " " + str.first + "=" + str.second; - ret += " }"; + ret += " " + escapeString(str.first) + "=" + escapeString(str.second); + + return ret.trimmed(); +} + +Metadata::~Metadata() +{ + SAFE_DELETE(dwarf); +} + +rdcstr Metadata::refString() const +{ + if(id == ~0U) + return valString(); + return StringFormat::Fmt("!%u", id); +} + +rdcstr Metadata::valString() const +{ + if(dwarf) + { + return dwarf->toString(); + } + else if(value) + { + if(type == NULL) + { + return StringFormat::Fmt("!%s", escapeString(str).c_str()); + } + else + { + if(type != val->type) + RDCERR("Type mismatch in metadata"); + return val->toString(); + } + } + else + { + rdcstr ret = "!{"; + for(size_t i = 0; i < children.size(); i++) + { + if(i > 0) + ret += ", "; + if(!children[i]) + ret += "null"; + else if(children[i]->value) + ret += children[i]->valString(); + else + ret += StringFormat::Fmt("!%u", children[i]->id); + } + ret += "}"; + + return ret; + } +} + +rdcstr Value::toString() const +{ + if(type == NULL) + return escapeString(str); + + rdcstr ret; + ret += type->toString() + " "; + if(undef) + { + ret += "undef"; + } + else if(symbol) + { + ret += StringFormat::Fmt("@%s", needsEscaping(str) ? escapeString(str).c_str() : str.c_str()); + } + else if(type->type == Type::Scalar) + { + if(type->scalarType == Type::Float) + { + // TODO need to know how to determine signedness here + if(type->bitWidth > 32) + ret += StringFormat::Fmt("%lf", val.dv[0]); + else + ret += StringFormat::Fmt("%f", val.fv[0]); + } + else if(type->scalarType == Type::Int) + { + // TODO need to know how to determine signedness here + if(type->bitWidth > 32) + ret += StringFormat::Fmt("%llu", val.u64v[0]); + else + ret += StringFormat::Fmt("%u", val.uv[0]); + } + } + else if(type->type == Type::Vector) + { + ret += "<"; + for(uint32_t i = 0; i < type->elemCount; i++) + { + if(type->scalarType == Type::Float) + { + // TODO need to know how to determine signedness here + if(type->bitWidth > 32) + ret += StringFormat::Fmt("%lf", val.dv[i]); + else + ret += StringFormat::Fmt("%f", val.fv[i]); + } + else if(type->scalarType == Type::Int) + { + // TODO need to know how to determine signedness here + if(type->bitWidth > 32) + ret += StringFormat::Fmt("%llu", val.u64v[i]); + else + ret += StringFormat::Fmt("%u", val.uv[i]); + } + } + ret += ">"; + } + else if(type->type == Type::Array) + { + ret += "["; + for(size_t i = 0; i < members.size(); i++) + { + if(i > 0) + ret += ", "; + + ret += members[i].toString(); + } + ret += "]"; + } + else if(type->type == Type::Struct) + { + ret += "{"; + for(size_t i = 0; i < members.size(); i++) + { + if(i > 0) + ret += ", "; + + ret += members[i].toString(); + } + ret += "}"; + } + else + { + ret += StringFormat::Fmt("unsupported type %u", type->type); + } return ret; } -}; +}; // namespace DXIL template <> rdcstr DoStringise(const DXIL::Attribute &el) @@ -1503,51 +1660,51 @@ rdcstr DoStringise(const DXIL::Attribute &el) { STRINGISE_BITFIELD_CLASS_VALUE_NAMED(None, ""); - STRINGISE_BITFIELD_CLASS_BIT(Alignment); - STRINGISE_BITFIELD_CLASS_BIT(AlwaysInline); - STRINGISE_BITFIELD_CLASS_BIT(ByVal); - STRINGISE_BITFIELD_CLASS_BIT(InlineHint); - STRINGISE_BITFIELD_CLASS_BIT(InReg); - STRINGISE_BITFIELD_CLASS_BIT(MinSize); - STRINGISE_BITFIELD_CLASS_BIT(Naked); - STRINGISE_BITFIELD_CLASS_BIT(Nest); - STRINGISE_BITFIELD_CLASS_BIT(NoAlias); - STRINGISE_BITFIELD_CLASS_BIT(NoBuiltin); - STRINGISE_BITFIELD_CLASS_BIT(NoCapture); - STRINGISE_BITFIELD_CLASS_BIT(NoDuplicate); - STRINGISE_BITFIELD_CLASS_BIT(NoImplicitFloat); - STRINGISE_BITFIELD_CLASS_BIT(NoInline); - STRINGISE_BITFIELD_CLASS_BIT(NonLazyBind); - STRINGISE_BITFIELD_CLASS_BIT(NoRedZone); - STRINGISE_BITFIELD_CLASS_BIT(NoReturn); - STRINGISE_BITFIELD_CLASS_BIT(NoUnwind); - STRINGISE_BITFIELD_CLASS_BIT(OptimizeForSize); - STRINGISE_BITFIELD_CLASS_BIT(ReadNone); - STRINGISE_BITFIELD_CLASS_BIT(ReadOnly); - STRINGISE_BITFIELD_CLASS_BIT(Returned); - STRINGISE_BITFIELD_CLASS_BIT(ReturnsTwice); - STRINGISE_BITFIELD_CLASS_BIT(SExt); - STRINGISE_BITFIELD_CLASS_BIT(StackAlignment); - STRINGISE_BITFIELD_CLASS_BIT(StackProtect); - STRINGISE_BITFIELD_CLASS_BIT(StackProtectReq); - STRINGISE_BITFIELD_CLASS_BIT(StackProtectStrong); - STRINGISE_BITFIELD_CLASS_BIT(StructRet); - STRINGISE_BITFIELD_CLASS_BIT(SanitizeAddress); - STRINGISE_BITFIELD_CLASS_BIT(SanitizeThread); - STRINGISE_BITFIELD_CLASS_BIT(SanitizeMemory); - STRINGISE_BITFIELD_CLASS_BIT(UWTable); - STRINGISE_BITFIELD_CLASS_BIT(ZExt); - STRINGISE_BITFIELD_CLASS_BIT(Builtin); - STRINGISE_BITFIELD_CLASS_BIT(Cold); - STRINGISE_BITFIELD_CLASS_BIT(OptimizeNone); - STRINGISE_BITFIELD_CLASS_BIT(InAlloca); - STRINGISE_BITFIELD_CLASS_BIT(NonNull); - STRINGISE_BITFIELD_CLASS_BIT(JumpTable); - STRINGISE_BITFIELD_CLASS_BIT(Dereferenceable); - STRINGISE_BITFIELD_CLASS_BIT(DereferenceableOrNull); - STRINGISE_BITFIELD_CLASS_BIT(Convergent); - STRINGISE_BITFIELD_CLASS_BIT(SafeStack); - STRINGISE_BITFIELD_CLASS_BIT(ArgMemOnly); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Alignment, "align"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(AlwaysInline, "alwaysinline"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ByVal, "byval"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(InlineHint, "inlinehint"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(InReg, "inreg"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(MinSize, "minsize"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Naked, "naked"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Nest, "nest"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoAlias, "noalias"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoBuiltin, "nobuiltin"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoCapture, "nocapture"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoDuplicate, "noduplicate"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoImplicitFloat, "noimplicitfloat"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoInline, "noinline"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NonLazyBind, "nonlazybind"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoRedZone, "noredzone"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoReturn, "noreturn"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NoUnwind, "nounwind"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(OptimizeForSize, "optsize"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ReadNone, "readnone"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ReadOnly, "readonly"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Returned, "returned"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ReturnsTwice, "returns_twice"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(SExt, "signext"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(StackAlignment, "alignstack"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(StackProtect, "ssp"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(StackProtectReq, "sspreq"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(StackProtectStrong, "sspstrong"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(StructRet, "sret"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(SanitizeAddress, "sanitize_address"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(SanitizeThread, "sanitize_thread"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(SanitizeMemory, "sanitize_memory"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(UWTable, "uwtable"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ZExt, "zeroext"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Builtin, "builtin"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Cold, "cold"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(OptimizeNone, "optnone"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(InAlloca, "inalloca"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(NonNull, "nonnull"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(JumpTable, "jumptable"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Dereferenceable, "dereferenceable"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(DereferenceableOrNull, "dereferenceable_or_null"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(Convergent, "convergent"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(SafeStack, "safestack"); + STRINGISE_BITFIELD_CLASS_BIT_NAMED(ArgMemOnly, "argmemonly"); } END_BITFIELD_STRINGISE(); } diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index 8b0f0167f..39420171b 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -31,6 +31,11 @@ #include "driver/dx/official/d3dcommon.h" #include "driver/shaders/dxbc/dxbc_common.h" +namespace LLVMBC +{ +struct BlockOrRecord; +}; + namespace DXIL { struct Type @@ -57,7 +62,7 @@ struct Type Int, } scalarType = Void; - rdcstr getTypeName() const; + rdcstr toString() const; rdcstr declFunction(rdcstr funcName) const; // for scalars, arrays, vectors @@ -75,6 +80,10 @@ struct Type struct GlobalVar { rdcstr name; + const Type *type = NULL; + bool isconst = false; + bool external = false; + uint64_t align = 0; }; struct Alias @@ -172,8 +181,64 @@ struct Function struct Value { const Type *type = NULL; - ShaderVariable val; + ShaderValue val = {}; + rdcarray members; rdcstr str; + bool undef = false, symbol = false; + + rdcstr toString() const; +}; + +struct DIBase +{ + enum Type + { + File, + CompileUnit, + BasicType, + DerivedType, + CompositeType, + TemplateTypeParameter, + TemplateValueParameter, + Subprogram, + SubroutineType, + GlobalVariable, + LocalVariable, + Location, + Expression, + } type; + + DIBase(Type t) : type(t) {} + virtual ~DIBase() = default; + virtual rdcstr toString() const = 0; + + template + const Derived As() + { + RDCASSERT(type == Derived::DIType); + return (Derived *)this; + } +}; + +struct Metadata +{ + ~Metadata(); + + uint32_t id = ~0U; + bool distinct = false, value = false; + const Value *val = NULL; + const Type *type = NULL; + rdcstr str; + rdcarray children; + DIBase *dwarf = NULL; + + rdcstr refString() const; + rdcstr valString() const; +}; + +struct NamedMetadata : public Metadata +{ + rdcstr name; }; class Program @@ -203,6 +268,10 @@ public: private: void MakeDisassemblyString(); + bool ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta); + + uint32_t GetOrAssignMetaID(Metadata *m); + DXBC::ShaderType m_Type; uint32_t m_Major, m_Minor; @@ -220,11 +289,13 @@ private: rdcarray m_Values; + rdcarray m_Metadata; + rdcarray m_NamedMeta; + rdcarray m_NumberedMeta; + rdcstr m_Triple, m_Datalayout; rdcstr m_Disassembly; }; }; // namespace DXIL - -DECLARE_REFLECTION_ENUM(DXIL::Attribute); diff --git a/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp b/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp new file mode 100644 index 000000000..742aa3b34 --- /dev/null +++ b/renderdoc/driver/shaders/dxil/dxil_debuginfo.cpp @@ -0,0 +1,643 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "dxil_debuginfo.h" +#include "common/formatting.h" +#include "llvm_decoder.h" + +namespace DXIL +{ +enum class MetaDataRecord : uint32_t +{ + STRING_OLD = 1, + VALUE = 2, + NODE = 3, + NAME = 4, + DISTINCT_NODE = 5, + KIND = 6, + LOCATION = 7, + OLD_NODE = 8, + OLD_FN_NODE = 9, + NAMED_NODE = 10, + ATTACHMENT = 11, + GENERIC_DEBUG = 12, + SUBRANGE = 13, + ENUMERATOR = 14, + BASIC_TYPE = 15, + FILE = 16, + DERIVED_TYPE = 17, + COMPOSITE_TYPE = 18, + SUBROUTINE_TYPE = 19, + COMPILE_UNIT = 20, + SUBPROGRAM = 21, + LEXICAL_BLOCK = 22, + LEXICAL_BLOCK_FILE = 23, + NAMESPACE = 24, + TEMPLATE_TYPE = 25, + TEMPLATE_VALUE = 26, + GLOBAL_VAR = 27, + LOCAL_VAR = 28, + EXPRESSION = 29, + OBJC_PROPERTY = 30, + IMPORTED_ENTITY = 31, + MODULE = 32, + MACRO = 33, + MACRO_FILE = 34, + STRINGS = 35, + GLOBAL_DECL_ATTACHMENT = 36, + GLOBAL_VAR_EXPR = 37, + INDEX_OFFSET = 38, + INDEX = 39, + LABEL = 40, + COMMON_BLOCK = 44, +}; + +bool needsEscaping(const rdcstr &name); +rdcstr escapeString(rdcstr str); + +bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta) +{ + MetaDataRecord id = (MetaDataRecord)metaRecord.id; + + auto getMeta = [this](uint64_t id) { return id ? &m_Metadata[size_t(id - 1)] : NULL; }; + auto getMetaString = [this](uint64_t id) { return id ? &m_Metadata[size_t(id - 1)].str : NULL; }; + + if(id == MetaDataRecord::FILE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = new DIFile(getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2])); + meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2])}; + } + else if(id == MetaDataRecord::COMPILE_UNIT) + { + // should be at least 14 parameters + RDCASSERT(metaRecord.ops.size() >= 14); + + // we expect it to be marked as distinct, but we'll always treat it that way + RDCASSERT(metaRecord.ops[0] & 0x1); + meta.distinct = true; + + meta.dwarf = new DICompileUnit( + DW_LANG(metaRecord.ops[1]), getMeta(metaRecord.ops[2]), getMetaString(metaRecord.ops[3]), + metaRecord.ops[4] != 0, getMetaString(metaRecord.ops[5]), metaRecord.ops[6], + getMetaString(metaRecord.ops[7]), metaRecord.ops[8], getMeta(metaRecord.ops[9]), + getMeta(metaRecord.ops[10]), getMeta(metaRecord.ops[11]), getMeta(metaRecord.ops[12]), + getMeta(metaRecord.ops[13])); + meta.children = {getMeta(metaRecord.ops[2]), getMeta(metaRecord.ops[9]), + getMeta(metaRecord.ops[10]), getMeta(metaRecord.ops[11]), + getMeta(metaRecord.ops[12]), getMeta(metaRecord.ops[13])}; + } + else if(id == MetaDataRecord::BASIC_TYPE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = + new DIBasicType(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), + metaRecord.ops[3], metaRecord.ops[4], DW_ENCODING(metaRecord.ops[5])); + } + else if(id == MetaDataRecord::DERIVED_TYPE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = new DIDerivedType(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), + getMeta(metaRecord.ops[3]), metaRecord.ops[4], + getMeta(metaRecord.ops[5]), getMeta(metaRecord.ops[6]), + metaRecord.ops[7], metaRecord.ops[8], metaRecord.ops[9], + DIFlags(metaRecord.ops[10]), getMeta(metaRecord.ops[11])); + + meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[5]), + getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11])}; + } + else if(id == MetaDataRecord::COMPOSITE_TYPE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + // TODO handle forward declarations? + meta.dwarf = new DICompositeType( + DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), getMeta(metaRecord.ops[3]), + metaRecord.ops[4], getMeta(metaRecord.ops[5]), getMeta(metaRecord.ops[6]), + metaRecord.ops[7], metaRecord.ops[8], metaRecord.ops[9], DIFlags(metaRecord.ops[10]), + getMeta(metaRecord.ops[11]), getMeta(metaRecord.ops[14])); + + meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[5]), + getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11]), + getMeta(metaRecord.ops[14])}; + } + else if(id == MetaDataRecord::TEMPLATE_TYPE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = + new DITemplateTypeParameter(getMetaString(metaRecord.ops[1]), getMeta(metaRecord.ops[2])); + + meta.children = {getMeta(metaRecord.ops[2])}; + } + else if(id == MetaDataRecord::TEMPLATE_VALUE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = + new DITemplateValueParameter(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), + getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])); + + meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])}; + } + else if(id == MetaDataRecord::SUBPROGRAM) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = new DISubprogram( + getMeta(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), + getMetaString(metaRecord.ops[3]), getMeta(metaRecord.ops[4]), metaRecord.ops[5], + getMeta(metaRecord.ops[6]), metaRecord.ops[7] != 0, metaRecord.ops[8] != 0, metaRecord.ops[9], + getMeta(metaRecord.ops[10]), DW_VIRTUALITY(metaRecord.ops[11]), metaRecord.ops[12], + DIFlags(metaRecord.ops[13]), metaRecord.ops[14] != 0, getMeta(metaRecord.ops[15]), + getMeta(metaRecord.ops[16]), getMeta(metaRecord.ops[17]), getMeta(metaRecord.ops[18])); + + meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[4]), + getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[10]), + getMeta(metaRecord.ops[14]), getMeta(metaRecord.ops[15]), + getMeta(metaRecord.ops[16]), getMeta(metaRecord.ops[17])}; + } + else if(id == MetaDataRecord::SUBROUTINE_TYPE) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + meta.dwarf = new DISubroutineType(getMeta(metaRecord.ops[2])); + + meta.children = {getMeta(metaRecord.ops[2])}; + } + else if(id == MetaDataRecord::GLOBAL_VAR) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + + uint64_t version = metaRecord.ops[0] >> 1; + + if(version == 0) + { + meta.dwarf = new DIGlobalVariable( + getMeta(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), + getMetaString(metaRecord.ops[3]), getMeta(metaRecord.ops[4]), metaRecord.ops[5], + getMeta(metaRecord.ops[6]), metaRecord.ops[7] != 0, metaRecord.ops[8] != 0, + getMeta(metaRecord.ops[9]), getMeta(metaRecord.ops[10])); + + meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[4]), + getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[9]), + getMeta(metaRecord.ops[10])}; + } + else + { + RDCERR("Unsupported version of global variable metadata"); + } + } + else if(id == MetaDataRecord::LOCATION) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + // metastr += "!DILocation()"; + } + else if(id == MetaDataRecord::LOCAL_VAR) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + // metastr += "!DILocalVariable()"; + } + else if(id == MetaDataRecord::EXPRESSION) + { + meta.distinct = (metaRecord.ops[0] & 0x1); + // DIExpression + } + else + { + return false; + } + + return true; +}; + +rdcstr getOptMetaString(const Metadata *meta) +{ + return meta ? escapeString(meta->str).c_str() : "\"\""; +} + +rdcstr DIFile::toString() const +{ + return StringFormat::Fmt("!DIFile(filename: %s, directory: %s)", getOptMetaString(file), + getOptMetaString(dir)); +} + +rdcstr DICompileUnit::toString() const +{ + rdcstr ret = StringFormat::Fmt("!DICompileUnit(language: %s, file: %s", ToStr(lang).c_str(), + file ? file->refString() : "null"); + + if(producer) + ret += ", producer: " + escapeString(*producer); + ret += (isOptimized ? ", isOptimized: true" : ", isOptimized: false"); + if(flags) + ret += ", flags: " + escapeString(*flags); + ret += StringFormat::Fmt(", runtimeVersion: %llu", runtimeVersion); + if(splitDebugFilename) + ret += ", splitDebugFilename: " + escapeString(*splitDebugFilename); + ret += StringFormat::Fmt(", emissionKind: %llu", emissionKind); + if(enums) + ret += ", enums: " + enums->refString(); + if(retainedTypes) + ret += ", retainedTypes: " + retainedTypes->refString(); + if(subprograms) + ret += ", subprograms: " + subprograms->refString(); + if(globals) + ret += ", globals: " + globals->refString(); + if(imports) + ret += ", imports: " + imports->refString(); + + ret += ")"; + + return ret; +} + +rdcstr DIBasicType::toString() const +{ + rdcstr ret = "!DIBasicType("; + if(tag != DW_TAG_base_type) + ret += StringFormat::Fmt("tag: %s, ", ToStr(tag).c_str()); + ret += StringFormat::Fmt("name: %s, ", escapeString(name ? *name : rdcstr()).c_str()); + ret += StringFormat::Fmt("size: %llu, ", sizeInBits); + ret += StringFormat::Fmt("align: %llu, ", alignInBits); + ret += StringFormat::Fmt("encoding: %s", ToStr(encoding).c_str()); + ret += ")"; + return ret; +} + +rdcstr DIDerivedType::toString() const +{ + rdcstr ret = StringFormat::Fmt("!DIDerivedType(tag: %s, name: %s", ToStr(tag).c_str(), + escapeString(name ? *name : rdcstr()).c_str()); + if(scope) + ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + if(file) + ret += StringFormat::Fmt(", file: %s", file->refString().c_str()); + else + ret += ", file: null"; + if(line) + ret += StringFormat::Fmt(", line: %llu", line); + if(base) + ret += StringFormat::Fmt(", baseType: %s", base->refString().c_str()); + else + ret += ", baseType: null"; + if(sizeInBits) + ret += StringFormat::Fmt(", size: %llu", sizeInBits); + if(alignInBits) + ret += StringFormat::Fmt(", align: %llu", alignInBits); + if(offsetInBits) + ret += StringFormat::Fmt(", offset: %llu", offsetInBits); + if(flags) + ret += StringFormat::Fmt(", flags: %s", ToStr(flags).c_str()); + if(extra) + ret += StringFormat::Fmt(", extraData: %s", extra->refString().c_str()); + ret += ")"; + return ret; +} + +rdcstr DICompositeType::toString() const +{ + rdcstr ret = StringFormat::Fmt("!DICompositeType(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()); + if(file) + ret += StringFormat::Fmt(", file: %s", file->refString().c_str()); + if(line) + ret += StringFormat::Fmt(", line: %llu", line); + if(base) + ret += StringFormat::Fmt(", baseType: %s", base->refString().c_str()); + if(sizeInBits) + ret += StringFormat::Fmt(", size: %llu", sizeInBits); + if(alignInBits) + ret += StringFormat::Fmt(", align: %llu", alignInBits); + if(offsetInBits) + ret += StringFormat::Fmt(", offset: %llu", offsetInBits); + if(flags) + ret += StringFormat::Fmt(", flags: %s", ToStr(flags).c_str()); + if(elements) + ret += StringFormat::Fmt(", elements: %s", elements->refString().c_str()); + if(templateParams) + ret += StringFormat::Fmt(", templateParams: %s", templateParams->refString().c_str()); + ret += ")"; + return ret; +} + +rdcstr DITemplateTypeParameter::toString() const +{ + return StringFormat::Fmt("!DITemplateTypeParameter(name: %s, type: %s)", + escapeString(name ? *name : rdcstr()).c_str(), + type ? type->refString().c_str() : "null"); +} + +rdcstr DITemplateValueParameter::toString() const +{ + return StringFormat::Fmt("!DITemplateValueParameter(name: %s, type: %s, value: %s)", + escapeString(name ? *name : rdcstr()).c_str(), + type ? type->refString().c_str() : "null", + value ? value->refString().c_str() : "null"); +} + +rdcstr DISubprogram::toString() const +{ + rdcstr ret = + StringFormat::Fmt("!DISubprogram(name: %s", escapeString(name ? *name : rdcstr()).c_str()); + if(linkageName) + ret += StringFormat::Fmt(", linkageName: %s", escapeString(*linkageName).c_str()); + if(scope) + ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + 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()); + ret += StringFormat::Fmt(", isLocal: %s", isLocal ? "true" : "false"); + ret += StringFormat::Fmt(", isDefinition: %s", isDefinition ? "true" : "false"); + if(scopeLine) + ret += StringFormat::Fmt(", scopeLine: %llu", scopeLine); + if(containingType) + ret += StringFormat::Fmt(", containingType: %s", containingType->refString().c_str()); + + if(virtuality) + { + ret += StringFormat::Fmt(", virtuality: %s", ToStr(virtuality).c_str()); + if(virtualIndex) + ret += StringFormat::Fmt(", virtualIndex: %llu", virtualIndex); + } + + if(flags) + ret += StringFormat::Fmt(", flags: %s", ToStr(flags).c_str()); + + ret += StringFormat::Fmt(", isOptimized: %s", isOptimized ? "true" : "false"); + + if(function) + ret += StringFormat::Fmt(", function: %s", function->refString().c_str()); + if(templateParams) + ret += StringFormat::Fmt(", templateParams: %s", templateParams->refString().c_str()); + if(declaration) + ret += StringFormat::Fmt(", declaration: %s", declaration->refString().c_str()); + if(variables) + ret += StringFormat::Fmt(", variables: %s", variables->refString().c_str()); + + ret += ")"; + return ret; +} + +rdcstr DISubroutineType::toString() const +{ + return StringFormat::Fmt("!DISubroutineType(types: %s)", + types ? types->refString().c_str() : "null"); +} + +rdcstr DIGlobalVariable::toString() const +{ + rdcstr ret = + StringFormat::Fmt("!DIGlobalVariable(name: %s", escapeString(name ? *name : rdcstr()).c_str()); + if(linkageName) + ret += StringFormat::Fmt(", linkageName: %s", escapeString(*linkageName).c_str()); + if(scope) + ret += StringFormat::Fmt(", scope: %s", scope->refString().c_str()); + 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()); + ret += StringFormat::Fmt(", isLocal: %s", isLocal ? "true" : "false"); + ret += StringFormat::Fmt(", isDefinition: %s", isDefinition ? "true" : "false"); + if(variable) + ret += StringFormat::Fmt(", variable: %s", variable->refString().c_str()); + ret += ")"; + return ret; +} +}; // namespace DXIL + +template <> +rdcstr DoStringise(const DXIL::DW_LANG &el) +{ + using namespace DXIL; + BEGIN_ENUM_STRINGISE(DW_LANG); + { + STRINGISE_ENUM_NAMED(DW_LANG_Unknown, "unknown"); + STRINGISE_ENUM(DW_LANG_C89); + STRINGISE_ENUM(DW_LANG_C); + STRINGISE_ENUM(DW_LANG_Ada83); + STRINGISE_ENUM(DW_LANG_C_plus_plus); + STRINGISE_ENUM(DW_LANG_Cobol74); + STRINGISE_ENUM(DW_LANG_Cobol85); + STRINGISE_ENUM(DW_LANG_Fortran77); + STRINGISE_ENUM(DW_LANG_Fortran90); + STRINGISE_ENUM(DW_LANG_Pascal83); + STRINGISE_ENUM(DW_LANG_Modula2); + STRINGISE_ENUM(DW_LANG_Java); + STRINGISE_ENUM(DW_LANG_C99); + STRINGISE_ENUM(DW_LANG_Ada95); + STRINGISE_ENUM(DW_LANG_Fortran95); + STRINGISE_ENUM(DW_LANG_PLI); + STRINGISE_ENUM(DW_LANG_ObjC); + STRINGISE_ENUM(DW_LANG_ObjC_plus_plus); + STRINGISE_ENUM(DW_LANG_UPC); + STRINGISE_ENUM(DW_LANG_D); + STRINGISE_ENUM(DW_LANG_Python); + STRINGISE_ENUM(DW_LANG_OpenCL); + STRINGISE_ENUM(DW_LANG_Go); + STRINGISE_ENUM(DW_LANG_Modula3); + STRINGISE_ENUM(DW_LANG_Haskell); + STRINGISE_ENUM(DW_LANG_C_plus_plus_03); + STRINGISE_ENUM(DW_LANG_C_plus_plus_11); + STRINGISE_ENUM(DW_LANG_OCaml); + STRINGISE_ENUM(DW_LANG_Rust); + STRINGISE_ENUM(DW_LANG_C11); + STRINGISE_ENUM(DW_LANG_Swift); + STRINGISE_ENUM(DW_LANG_Julia); + STRINGISE_ENUM(DW_LANG_Dylan); + STRINGISE_ENUM(DW_LANG_C_plus_plus_14); + STRINGISE_ENUM(DW_LANG_Fortran03); + STRINGISE_ENUM(DW_LANG_Fortran08); + STRINGISE_ENUM(DW_LANG_Mips_Assembler); + } + END_ENUM_STRINGISE(); +} + +template <> +rdcstr DoStringise(const DXIL::DW_TAG &el) +{ + using namespace DXIL; + BEGIN_ENUM_STRINGISE(DW_TAG); + { + STRINGISE_ENUM(DW_TAG_array_type); + STRINGISE_ENUM(DW_TAG_class_type); + STRINGISE_ENUM(DW_TAG_entry_point); + STRINGISE_ENUM(DW_TAG_enumeration_type); + STRINGISE_ENUM(DW_TAG_formal_parameter); + STRINGISE_ENUM(DW_TAG_imported_declaration); + STRINGISE_ENUM(DW_TAG_label); + STRINGISE_ENUM(DW_TAG_lexical_block); + STRINGISE_ENUM(DW_TAG_member); + STRINGISE_ENUM(DW_TAG_pointer_type); + STRINGISE_ENUM(DW_TAG_reference_type); + STRINGISE_ENUM(DW_TAG_compile_unit); + STRINGISE_ENUM(DW_TAG_string_type); + STRINGISE_ENUM(DW_TAG_structure_type); + STRINGISE_ENUM(DW_TAG_subroutine_type); + STRINGISE_ENUM(DW_TAG_typedef); + STRINGISE_ENUM(DW_TAG_union_type); + STRINGISE_ENUM(DW_TAG_unspecified_parameters); + STRINGISE_ENUM(DW_TAG_variant); + STRINGISE_ENUM(DW_TAG_common_block); + STRINGISE_ENUM(DW_TAG_common_inclusion); + STRINGISE_ENUM(DW_TAG_inheritance); + STRINGISE_ENUM(DW_TAG_inlined_subroutine); + STRINGISE_ENUM(DW_TAG_module); + STRINGISE_ENUM(DW_TAG_ptr_to_member_type); + STRINGISE_ENUM(DW_TAG_set_type); + STRINGISE_ENUM(DW_TAG_subrange_type); + STRINGISE_ENUM(DW_TAG_with_stmt); + STRINGISE_ENUM(DW_TAG_access_declaration); + STRINGISE_ENUM(DW_TAG_base_type); + STRINGISE_ENUM(DW_TAG_catch_block); + STRINGISE_ENUM(DW_TAG_const_type); + STRINGISE_ENUM(DW_TAG_constant); + STRINGISE_ENUM(DW_TAG_enumerator); + STRINGISE_ENUM(DW_TAG_file_type); + STRINGISE_ENUM(DW_TAG_friend); + STRINGISE_ENUM(DW_TAG_namelist); + STRINGISE_ENUM(DW_TAG_namelist_item); + STRINGISE_ENUM(DW_TAG_packed_type); + STRINGISE_ENUM(DW_TAG_subprogram); + STRINGISE_ENUM(DW_TAG_template_type_parameter); + STRINGISE_ENUM(DW_TAG_template_value_parameter); + STRINGISE_ENUM(DW_TAG_thrown_type); + STRINGISE_ENUM(DW_TAG_try_block); + STRINGISE_ENUM(DW_TAG_variant_part); + STRINGISE_ENUM(DW_TAG_variable); + STRINGISE_ENUM(DW_TAG_volatile_type); + STRINGISE_ENUM(DW_TAG_dwarf_procedure); + STRINGISE_ENUM(DW_TAG_restrict_type); + STRINGISE_ENUM(DW_TAG_interface_type); + STRINGISE_ENUM(DW_TAG_namespace); + STRINGISE_ENUM(DW_TAG_imported_module); + STRINGISE_ENUM(DW_TAG_unspecified_type); + STRINGISE_ENUM(DW_TAG_partial_unit); + STRINGISE_ENUM(DW_TAG_imported_unit); + STRINGISE_ENUM(DW_TAG_condition); + STRINGISE_ENUM(DW_TAG_shared_type); + STRINGISE_ENUM(DW_TAG_type_unit); + STRINGISE_ENUM(DW_TAG_rvalue_reference_type); + STRINGISE_ENUM(DW_TAG_template_alias); + STRINGISE_ENUM(DW_TAG_auto_variable); + STRINGISE_ENUM(DW_TAG_arg_variable); + STRINGISE_ENUM(DW_TAG_coarray_type); + STRINGISE_ENUM(DW_TAG_generic_subrange); + STRINGISE_ENUM(DW_TAG_dynamic_type); + STRINGISE_ENUM(DW_TAG_MIPS_loop); + STRINGISE_ENUM(DW_TAG_format_label); + STRINGISE_ENUM(DW_TAG_function_template); + STRINGISE_ENUM(DW_TAG_class_template); + STRINGISE_ENUM(DW_TAG_GNU_template_template_param); + STRINGISE_ENUM(DW_TAG_GNU_template_parameter_pack); + STRINGISE_ENUM(DW_TAG_GNU_formal_parameter_pack); + STRINGISE_ENUM(DW_TAG_APPLE_property); + } + END_ENUM_STRINGISE(); +} + +template <> +rdcstr DoStringise(const DXIL::DW_ENCODING &el) +{ + using namespace DXIL; + BEGIN_ENUM_STRINGISE(DW_ENCODING); + { + STRINGISE_ENUM(DW_ATE_address); + STRINGISE_ENUM(DW_ATE_boolean); + STRINGISE_ENUM(DW_ATE_complex_float); + STRINGISE_ENUM(DW_ATE_float); + STRINGISE_ENUM(DW_ATE_signed); + STRINGISE_ENUM(DW_ATE_signed_char); + STRINGISE_ENUM(DW_ATE_unsigned); + STRINGISE_ENUM(DW_ATE_unsigned_char); + STRINGISE_ENUM(DW_ATE_imaginary_float); + STRINGISE_ENUM(DW_ATE_packed_decimal); + STRINGISE_ENUM(DW_ATE_numeric_string); + STRINGISE_ENUM(DW_ATE_edited); + STRINGISE_ENUM(DW_ATE_signed_fixed); + STRINGISE_ENUM(DW_ATE_unsigned_fixed); + STRINGISE_ENUM(DW_ATE_decimal_float); + STRINGISE_ENUM(DW_ATE_UTF); + } + END_ENUM_STRINGISE(); +} + +template <> +rdcstr DoStringise(const DXIL::DW_VIRTUALITY &el) +{ + using namespace DXIL; + BEGIN_ENUM_STRINGISE(DW_VIRTUALITY); + { + STRINGISE_ENUM(DW_VIRTUALITY_none); + STRINGISE_ENUM(DW_VIRTUALITY_virtual); + STRINGISE_ENUM(DW_VIRTUALITY_pure_virtual); + } + END_ENUM_STRINGISE(); +} + +template <> +rdcstr DoStringise(const DXIL::DIFlags &el) +{ + using namespace DXIL; + BEGIN_BITFIELD_STRINGISE(DIFlags); + { + // these are manual because they're a non-bitfield within a bitfield + if((el & DXIL::DIFlagPublic) == DXIL::DIFlagPublic) + ret += " | DIFlagPublic"; + else if((el & DXIL::DIFlagPublic) == DXIL::DIFlagPrivate) + ret += " | DIFlagPrivate"; + else if((el & DXIL::DIFlagPublic) == DXIL::DIFlagProtected) + ret += " | DIFlagProtected"; + local &= ~DXIL::DIFlagPublic; + STRINGISE_BITFIELD_BIT(DIFlagFwdDecl); + STRINGISE_BITFIELD_BIT(DIFlagAppleBlock); + STRINGISE_BITFIELD_BIT(DIFlagBlockByrefStruct); + STRINGISE_BITFIELD_BIT(DIFlagVirtual); + STRINGISE_BITFIELD_BIT(DIFlagArtificial); + STRINGISE_BITFIELD_BIT(DIFlagExplicit); + STRINGISE_BITFIELD_BIT(DIFlagPrototyped); + STRINGISE_BITFIELD_BIT(DIFlagObjcClassComplete); + STRINGISE_BITFIELD_BIT(DIFlagObjectPointer); + STRINGISE_BITFIELD_BIT(DIFlagVector); + STRINGISE_BITFIELD_BIT(DIFlagStaticMember); + STRINGISE_BITFIELD_BIT(DIFlagLValueReference); + STRINGISE_BITFIELD_BIT(DIFlagRValueReference); + } + END_BITFIELD_STRINGISE(); +} diff --git a/renderdoc/driver/shaders/dxil/dxil_debuginfo.h b/renderdoc/driver/shaders/dxil/dxil_debuginfo.h new file mode 100644 index 000000000..ccdbd838f --- /dev/null +++ b/renderdoc/driver/shaders/dxil/dxil_debuginfo.h @@ -0,0 +1,473 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2020 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include "dxil_bytecode.h" + +namespace DXIL +{ +enum DW_LANG +{ + DW_LANG_Unknown = 0, + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_Python = 0x0014, + DW_LANG_OpenCL = 0x0015, + DW_LANG_Go = 0x0016, + DW_LANG_Modula3 = 0x0017, + DW_LANG_Haskell = 0x0018, + DW_LANG_C_plus_plus_03 = 0x0019, + DW_LANG_C_plus_plus_11 = 0x001a, + DW_LANG_OCaml = 0x001b, + DW_LANG_Rust = 0x001c, + DW_LANG_C11 = 0x001d, + DW_LANG_Swift = 0x001e, + DW_LANG_Julia = 0x001f, + DW_LANG_Dylan = 0x0020, + DW_LANG_C_plus_plus_14 = 0x0021, + DW_LANG_Fortran03 = 0x0022, + DW_LANG_Fortran08 = 0x0023, + DW_LANG_Mips_Assembler = 0x8001, +}; + +enum DW_TAG +{ + DW_TAG_array_type = 0x0001, + DW_TAG_class_type = 0x0002, + DW_TAG_entry_point = 0x0003, + DW_TAG_enumeration_type = 0x0004, + DW_TAG_formal_parameter = 0x0005, + DW_TAG_imported_declaration = 0x0008, + DW_TAG_label = 0x000a, + DW_TAG_lexical_block = 0x000b, + DW_TAG_member = 0x000d, + DW_TAG_pointer_type = 0x000f, + DW_TAG_reference_type = 0x0010, + DW_TAG_compile_unit = 0x0011, + DW_TAG_string_type = 0x0012, + DW_TAG_structure_type = 0x0013, + DW_TAG_subroutine_type = 0x0015, + DW_TAG_typedef = 0x0016, + DW_TAG_union_type = 0x0017, + DW_TAG_unspecified_parameters = 0x0018, + DW_TAG_variant = 0x0019, + DW_TAG_common_block = 0x001a, + DW_TAG_common_inclusion = 0x001b, + DW_TAG_inheritance = 0x001c, + DW_TAG_inlined_subroutine = 0x001d, + DW_TAG_module = 0x001e, + DW_TAG_ptr_to_member_type = 0x001f, + DW_TAG_set_type = 0x0020, + DW_TAG_subrange_type = 0x0021, + DW_TAG_with_stmt = 0x0022, + DW_TAG_access_declaration = 0x0023, + DW_TAG_base_type = 0x0024, + DW_TAG_catch_block = 0x0025, + DW_TAG_const_type = 0x0026, + DW_TAG_constant = 0x0027, + DW_TAG_enumerator = 0x0028, + DW_TAG_file_type = 0x0029, + DW_TAG_friend = 0x002a, + DW_TAG_namelist = 0x002b, + DW_TAG_namelist_item = 0x002c, + DW_TAG_packed_type = 0x002d, + DW_TAG_subprogram = 0x002e, + DW_TAG_template_type_parameter = 0x002f, + DW_TAG_template_value_parameter = 0x0030, + DW_TAG_thrown_type = 0x0031, + DW_TAG_try_block = 0x0032, + DW_TAG_variant_part = 0x0033, + DW_TAG_variable = 0x0034, + DW_TAG_volatile_type = 0x0035, + DW_TAG_dwarf_procedure = 0x0036, + DW_TAG_restrict_type = 0x0037, + DW_TAG_interface_type = 0x0038, + DW_TAG_namespace = 0x0039, + DW_TAG_imported_module = 0x003a, + DW_TAG_unspecified_type = 0x003b, + DW_TAG_partial_unit = 0x003c, + DW_TAG_imported_unit = 0x003d, + DW_TAG_condition = 0x003f, + DW_TAG_shared_type = 0x0040, + DW_TAG_type_unit = 0x0041, + DW_TAG_rvalue_reference_type = 0x0042, + DW_TAG_template_alias = 0x0043, + DW_TAG_auto_variable = 0x0100, + DW_TAG_arg_variable = 0x0101, + DW_TAG_coarray_type = 0x0044, + DW_TAG_generic_subrange = 0x0045, + DW_TAG_dynamic_type = 0x0046, + DW_TAG_MIPS_loop = 0x4081, + DW_TAG_format_label = 0x4101, + DW_TAG_function_template = 0x4102, + DW_TAG_class_template = 0x4103, + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, + DW_TAG_APPLE_property = 0x4200, +}; + +enum DW_ENCODING +{ + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f, + DW_ATE_UTF = 0x10, +}; + +enum DW_VIRTUALITY +{ + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02, +}; + +enum DIFlags +{ + DIFlagPrivate = 1, + DIFlagProtected = 2, + DIFlagPublic = 3, + DIFlagFwdDecl = (1 << 2), + DIFlagAppleBlock = (1 << 3), + DIFlagBlockByrefStruct = (1 << 4), + DIFlagVirtual = (1 << 5), + DIFlagArtificial = (1 << 6), + DIFlagExplicit = (1 << 7), + DIFlagPrototyped = (1 << 8), + DIFlagObjcClassComplete = (1 << 9), + DIFlagObjectPointer = (1 << 10), + DIFlagVector = (1 << 11), + DIFlagStaticMember = (1 << 12), + DIFlagLValueReference = (1 << 13), + DIFlagRValueReference = (1 << 14), +}; + +struct DIFile : public DIBase +{ + static const DIBase::Type DIType = DIBase::File; + DIFile(const Metadata *file, const Metadata *dir) : DIBase(DIType), file(file), dir(dir) {} + const Metadata *file; + const Metadata *dir; + + virtual rdcstr toString() const; +}; + +struct DICompileUnit : public DIBase +{ + static const DIBase::Type DIType = DIBase::CompileUnit; + DICompileUnit(DW_LANG lang, const Metadata *file, const rdcstr *producer, bool isOptimized, + const rdcstr *flags, uint64_t runtimeVersion, const rdcstr *splitDebugFilename, + uint64_t emissionKind, const Metadata *enums, const Metadata *retainedTypes, + const Metadata *subprograms, const Metadata *globals, const Metadata *imports) + : DIBase(DIType), + lang(lang), + file(file), + producer(producer), + isOptimized(isOptimized), + flags(flags), + runtimeVersion(runtimeVersion), + splitDebugFilename(splitDebugFilename), + emissionKind(emissionKind), + enums(enums), + retainedTypes(retainedTypes), + subprograms(subprograms), + globals(globals), + imports(imports) + { + } + + DW_LANG lang; + const Metadata *file; + const rdcstr *producer; + bool isOptimized; + const rdcstr *flags; + uint64_t runtimeVersion; + const rdcstr *splitDebugFilename; + uint64_t emissionKind; + const Metadata *enums; + const Metadata *retainedTypes; + const Metadata *subprograms; + const Metadata *globals; + const Metadata *imports; + + virtual rdcstr toString() const; +}; + +struct DIBasicType : public DIBase +{ + static const DIBase::Type DIType = DIBase::BasicType; + DIBasicType(DW_TAG tag, const rdcstr *name, uint64_t sizeInBits, uint64_t alignInBits, + DW_ENCODING encoding) + : DIBase(DIType), + tag(tag), + name(name), + sizeInBits(sizeInBits), + alignInBits(alignInBits), + encoding(encoding) + { + } + + DW_TAG tag; + const rdcstr *name; + uint64_t sizeInBits; + uint64_t alignInBits; + DW_ENCODING encoding; + + virtual rdcstr toString() const; +}; + +struct DIDerivedType : public DIBase +{ + static const DIBase::Type DIType = DIBase::DerivedType; + DIDerivedType(DW_TAG tag, const rdcstr *name, const Metadata *file, uint64_t line, + const Metadata *scope, const Metadata *base, uint64_t sizeInBits, + uint64_t alignInBits, uint64_t offsetInBits, DIFlags flags, const Metadata *extra) + : DIBase(DIType), + tag(tag), + name(name), + file(file), + line(line), + scope(scope), + base(base), + sizeInBits(sizeInBits), + alignInBits(alignInBits), + offsetInBits(offsetInBits), + flags(flags), + extra(extra) + { + } + + DW_TAG tag; + const rdcstr *name; + const Metadata *file; + uint64_t line; + const Metadata *scope; + const Metadata *base; + uint64_t sizeInBits; + uint64_t alignInBits; + uint64_t offsetInBits; + DIFlags flags; + const Metadata *extra; + + virtual rdcstr toString() const; +}; + +struct DICompositeType : public DIBase +{ + static const DIBase::Type DIType = DIBase::CompositeType; + DICompositeType(DW_TAG tag, const rdcstr *name, const Metadata *file, uint64_t line, + const Metadata *scope, const Metadata *base, uint64_t sizeInBits, + uint64_t alignInBits, uint64_t offsetInBits, DIFlags flags, + const Metadata *elements, const Metadata *templateParams) + : DIBase(DIType), + tag(tag), + name(name), + file(file), + line(line), + scope(scope), + base(base), + sizeInBits(sizeInBits), + alignInBits(alignInBits), + offsetInBits(offsetInBits), + flags(flags), + elements(elements), + templateParams(templateParams) + { + } + + DW_TAG tag; + const rdcstr *name; + const Metadata *file; + uint64_t line; + const Metadata *scope; + const Metadata *base; + uint64_t sizeInBits; + uint64_t alignInBits; + uint64_t offsetInBits; + DIFlags flags; + const Metadata *elements; + const Metadata *templateParams; + + virtual rdcstr toString() const; +}; + +struct DITemplateTypeParameter : public DIBase +{ + static const DIBase::Type DIType = DIBase::TemplateTypeParameter; + DITemplateTypeParameter(const rdcstr *name, const Metadata *type) + : DIBase(DIType), name(name), type(type) + { + } + const rdcstr *name; + const Metadata *type; + + virtual rdcstr toString() const; +}; + +struct DITemplateValueParameter : public DIBase +{ + static const DIBase::Type DIType = DIBase::TemplateValueParameter; + DITemplateValueParameter(DW_TAG tag, const rdcstr *name, const Metadata *type, const Metadata *value) + : DIBase(DIType), tag(tag), name(name), type(type), value(value) + { + } + + DW_TAG tag; + const rdcstr *name; + const Metadata *type; + const Metadata *value; + + virtual rdcstr toString() const; +}; + +struct DISubprogram : public DIBase +{ + static const DIBase::Type DIType = DIBase::Subprogram; + DISubprogram(const Metadata *scope, const rdcstr *name, const rdcstr *linkageName, + const Metadata *file, uint64_t line, const Metadata *type, bool isLocal, + bool isDefinition, uint64_t scopeLine, const Metadata *containingType, + DW_VIRTUALITY virtuality, uint64_t virtualIndex, DIFlags flags, bool isOptimized, + const Metadata *function, const Metadata *templateParams, + const Metadata *declaration, const Metadata *variables) + : DIBase(DIType), + scope(scope), + name(name), + linkageName(linkageName), + file(file), + line(line), + type(type), + isLocal(isLocal), + isDefinition(isDefinition), + scopeLine(scopeLine), + containingType(containingType), + virtuality(virtuality), + virtualIndex(virtualIndex), + flags(flags), + isOptimized(isOptimized), + function(function), + templateParams(templateParams), + declaration(declaration), + variables(variables) + { + } + + const Metadata *scope; + const rdcstr *name; + const rdcstr *linkageName; + const Metadata *file; + uint64_t line; + const Metadata *type; + bool isLocal; + bool isDefinition; + uint64_t scopeLine; + const Metadata *containingType; + DW_VIRTUALITY virtuality; + uint64_t virtualIndex; + DIFlags flags; + bool isOptimized; + const Metadata *function; + const Metadata *templateParams; + const Metadata *declaration; + const Metadata *variables; + + virtual rdcstr toString() const; +}; + +struct DISubroutineType : public DIBase +{ + static const DIBase::Type DIType = DIBase::SubroutineType; + DISubroutineType(const Metadata *types) : DIBase(DIType), types(types) {} + const Metadata *types; + + virtual rdcstr toString() const; +}; + +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) + : DIBase(DIType), + scope(scope), + name(name), + linkageName(linkageName), + file(file), + line(line), + type(type), + isLocal(isLocal), + isDefinition(isDefinition), + variable(variable), + staticData(staticData) + { + } + + 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; + + virtual rdcstr toString() const; +}; + +}; // namespace DXIL + +DECLARE_REFLECTION_ENUM(DXIL::Attribute); +DECLARE_REFLECTION_ENUM(DXIL::DW_LANG); diff --git a/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj b/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj index 06fd7946b..132448783 100644 --- a/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj +++ b/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj @@ -102,6 +102,7 @@ + Create @@ -109,6 +110,7 @@ + diff --git a/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj.filters b/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj.filters index f2a87609f..363c4f101 100644 --- a/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj.filters +++ b/renderdoc/driver/shaders/dxil/renderdoc_dxil.vcxproj.filters @@ -1,19 +1,21 @@  - PCH + + - PCH + +