From 9225961462a555dd66d2a5ee476f5172068f7bd6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 18 Jun 2020 13:16:45 +0100 Subject: [PATCH] Add support for GEP constant ops --- .../driver/shaders/dxil/dxil_bytecode.cpp | 98 ++++++++++++++----- renderdoc/driver/shaders/dxil/dxil_bytecode.h | 6 ++ .../driver/shaders/dxil/dxil_disassemble.cpp | 22 +++++ 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp index 6a9c70214..df15ce280 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.cpp @@ -88,6 +88,8 @@ enum class ConstantsRecord : uint32_t FLOAT = 6, AGGREGATE = 7, STRING = 8, + CSTRING = 9, + EVAL_GEP = 20, DATA = 22, }; @@ -222,7 +224,8 @@ enum class TypeRecord : uint32_t #define IS_KNOWN(val, KnownID) (decltype(KnownID)(val) == KnownID) void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType, - std::function getType, + std::function getType, + std::function getPtrType, std::function getValue, std::function addValue) { @@ -258,13 +261,58 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType, memcpy(&v.val.dv[0], &constant.ops[0], sizeof(double)); addValue(v); } - else if(IS_KNOWN(constant.id, ConstantsRecord::STRING)) + else if(IS_KNOWN(constant.id, ConstantsRecord::STRING) || + IS_KNOWN(constant.id, ConstantsRecord::CSTRING)) { Value v; v.type = curType; v.str = constant.getString(0); addValue(v); } + else if(IS_KNOWN(constant.id, ConstantsRecord::EVAL_GEP)) + { + Value v; + + v.op = Value::GEP; + + size_t idx = 0; + if(constant.ops.size() & 1) + v.type = getType(constant.ops[idx++]); + + for(; idx < constant.ops.size(); idx += 2) + { + const Type *t = getType(constant.ops[idx]); + const Value *a = getValue(constant.ops[idx + 1]); + RDCASSERT(t == a->type); + + v.members.push_back(*a); + } + + if(!v.type) + v.type = v.members[0].type; + + // walk the type list to get the return type + for(idx = 2; idx < v.members.size(); idx++) + { + if(v.type->type == Type::Vector || v.type->type == Type::Array) + { + v.type = v.type->inner; + } + else if(v.type->type == Type::Struct) + { + v.type = v.type->members[v.members[idx].val.uv[0]]; + } + else + { + RDCERR("Unexpected type %d encountered in GEP", v.type->type); + } + } + + // the result is a pointer to the return type + v.type = getPtrType(v.type); + + addValue(v); + } else if(IS_KNOWN(constant.id, ConstantsRecord::AGGREGATE)) { Value v; @@ -454,14 +502,7 @@ Program::Program(const byte *bytes, size_t length) 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; - } - } + v.type = GetPointerType(g.type); if(v.type == g.type) RDCERR("Expected to find pointer type for global variable"); @@ -815,6 +856,7 @@ Program::Program(const byte *bytes, size_t length) } ParseConstant(constant, t, [this](uint64_t op) { return &m_Types[(size_t)op]; }, + [this](const Type *t) { return GetPointerType(t); }, [this](uint64_t v) { size_t idx = (size_t)v; return idx < m_Values.size() ? &m_Values[idx] : NULL; @@ -1006,7 +1048,8 @@ Program::Program(const byte *bytes, size_t length) } ParseConstant( - constant, t, [this](uint64_t op) { return &m_Types[(size_t)op]; }, getValue, + constant, t, [this](uint64_t op) { return &m_Types[(size_t)op]; }, + [this](const Type *t) { return GetPointerType(t); }, getValue, [this, &f](const Value &v) { m_Symbols.push_back({SymbolType::Constant, m_Values.size() + f.values.size()}); f.values.push_back(v); @@ -1401,14 +1444,7 @@ Program::Program(const byte *bytes, size_t length) // we now have the inner type, but this instruction returns a pointer to that type so // adjust - for(const Type &t : m_Types) - { - if(t.type == Type::Pointer && t.inner == inst.type) - { - inst.type = &t; - break; - } - } + inst.type = GetPointerType(inst.type); RDCASSERT(inst.type->type == Type::Pointer); @@ -1471,14 +1507,7 @@ Program::Program(const byte *bytes, size_t length) } // get the pointer type - for(const Type &t : m_Types) - { - if(t.type == Type::Pointer && t.inner == inst.type) - { - inst.type = &t; - break; - } - } + inst.type = GetPointerType(inst.type); RDCASSERT(inst.type->type == Type::Pointer); @@ -2328,6 +2357,21 @@ const DXIL::Type *Program::GetBoolType() return m_BoolType; } +const Type *Program::GetPointerType(const Type *type) +{ + for(const Type &t : m_Types) + { + if(t.type == Type::Pointer && t.inner == type) + { + return &t; + } + } + + RDCERR("Couldn't find pointer type"); + + return type; +} + Metadata::~Metadata() { SAFE_DELETE(dwarf); diff --git a/renderdoc/driver/shaders/dxil/dxil_bytecode.h b/renderdoc/driver/shaders/dxil/dxil_bytecode.h index fa490a9e1..8fca90c51 100644 --- a/renderdoc/driver/shaders/dxil/dxil_bytecode.h +++ b/renderdoc/driver/shaders/dxil/dxil_bytecode.h @@ -211,6 +211,11 @@ struct Value rdcarray members; rdcstr str; bool undef = false, nullconst = false, symbol = false; + enum ValueOp : uint8_t + { + NoOp = 0, + GEP, + } op = NoOp; rdcstr toString(bool withType = false) const; }; @@ -524,6 +529,7 @@ private: const Metadata *GetFunctionMetadata(const Function &f, uint64_t v); const Type *GetVoidType(); const Type *GetBoolType(); + const Type *GetPointerType(const Type *type); DXBC::ShaderType m_Type; uint32_t m_Major, m_Minor; diff --git a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp index d762eef4d..37741efcd 100644 --- a/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp +++ b/renderdoc/driver/shaders/dxil/dxil_disassemble.cpp @@ -1621,6 +1621,28 @@ rdcstr Value::toString(bool withType) const { ret += StringFormat::Fmt("@%s", escapeStringIfNeeded(str).c_str()); } + else if(op != Value::NoOp) + { + switch(op) + { + case Value::NoOp: break; + case Value::GEP: + { + ret += "getelementptr inbounds ("; + + const Type *baseType = members[0].type; + RDCASSERT(baseType->type == Type::Pointer); + ret += baseType->inner->toString(); + for(size_t i = 0; i < members.size(); i++) + { + ret += ", "; + + ret += members[i].toString(withType); + } + ret += ")"; + } + } + } else if(type->type == Type::Scalar) { if(type->scalarType == Type::Float)