Add support for GEP constant ops

This commit is contained in:
baldurk
2020-06-18 17:22:44 +01:00
parent 213ce9c43a
commit 9225961462
3 changed files with 99 additions and 27 deletions
+71 -27
View File
@@ -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<Type *(uint64_t)> getType,
std::function<const Type *(uint64_t)> getType,
std::function<const Type *(const Type *)> getPtrType,
std::function<const Value *(uint64_t)> getValue,
std::function<void(const Value &)> 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);
@@ -211,6 +211,11 @@ struct Value
rdcarray<Value> 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;
@@ -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)