mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-25 16:06:31 +00:00
Decode metadata for global debug information
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user