Decode metadata for global debug information

This commit is contained in:
baldurk
2020-06-18 17:22:39 +01:00
parent d28bab8c79
commit 25321e741f
6 changed files with 1624 additions and 276 deletions
+427 -270
View File
@@ -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<rdcstr, rdcstr> &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();
}
+75 -4
View File
@@ -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<Value> 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 <typename Derived>
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<Metadata *> 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<Value> m_Values;
rdcarray<Metadata> m_Metadata;
rdcarray<NamedMetadata> m_NamedMeta;
rdcarray<Metadata *> m_NumberedMeta;
rdcstr m_Triple, m_Datalayout;
rdcstr m_Disassembly;
};
}; // namespace DXIL
DECLARE_REFLECTION_ENUM(DXIL::Attribute);
@@ -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();
}
@@ -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);
@@ -102,6 +102,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dxil_bytecode.cpp" />
<ClCompile Include="dxil_debuginfo.cpp" />
<ClCompile Include="llvm_decoder.cpp" />
<ClCompile Include="precompiled.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
@@ -109,6 +110,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="dxil_bytecode.h" />
<ClInclude Include="dxil_debuginfo.h" />
<ClInclude Include="llvm_bitreader.h" />
<ClInclude Include="llvm_decoder.h" />
<ClInclude Include="precompiled.h" />
@@ -1,19 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="dxil_inspect.cpp" />
<ClCompile Include="precompiled.cpp">
<Filter>PCH</Filter>
</ClCompile>
<ClCompile Include="llvm_decoder.cpp" />
<ClCompile Include="dxil_bytecode.cpp" />
<ClCompile Include="dxil_debuginfo.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="dxil_inspect.h" />
<ClInclude Include="precompiled.h">
<Filter>PCH</Filter>
</ClInclude>
<ClInclude Include="llvm_bitreader.h" />
<ClInclude Include="llvm_decoder.h" />
<ClInclude Include="dxil_bytecode.h" />
<ClInclude Include="dxil_debuginfo.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="PCH">