Refactor DXIL handling to rely on pointers instead of indexing

* The indexing works fine and handles forward references nicer, but once we
  start modifying things all the indices will need to be rebased.
This commit is contained in:
baldurk
2021-09-02 18:08:46 +01:00
parent 606c011aac
commit 3b8dee0233
5 changed files with 536 additions and 602 deletions
File diff suppressed because it is too large Load Diff
+51 -62
View File
@@ -104,31 +104,65 @@ struct Type
rdcarray<const Type *> members; // the members for a struct, the parameters for functions
};
enum class SymbolType
enum class ValueType
{
Unknown,
Function,
GlobalVar,
Alias,
Constant,
Argument,
Instruction,
Metadata,
Literal,
BasicBlock,
};
struct Symbol
struct Function;
struct GlobalVar;
struct Alias;
struct Constant;
struct Instruction;
struct Metadata;
struct Block;
struct Type;
struct Value
{
Symbol(SymbolType type = SymbolType::Unknown, uint64_t idx = 0) : type(type), idx(idx) {}
SymbolType type;
uint64_t idx;
bool operator<(const Symbol &o) const
enum ForwardRefTag
{
ForwardRef
};
Value() : type(ValueType::Unknown), literal(0) {}
explicit Value(ForwardRefTag, const Value *value) : type(ValueType::Unknown), value(value) {}
explicit Value(const Function *function) : type(ValueType::Function), function(function) {}
explicit Value(const GlobalVar *global) : type(ValueType::GlobalVar), global(global) {}
explicit Value(const Alias *alias) : type(ValueType::Alias), alias(alias) {}
explicit Value(const Constant *constant) : type(ValueType::Constant), constant(constant) {}
explicit Value(const Instruction *instruction)
: type(ValueType::Instruction), instruction(instruction)
{
if(type != o.type)
return type < o.type;
return idx < o.idx;
}
explicit Value(const Metadata *meta) : type(ValueType::Metadata), meta(meta) {}
explicit Value(const Block *block) : type(ValueType::BasicBlock), block(block) {}
explicit Value(uint64_t literal) : type(ValueType::Literal), literal(literal) {}
bool empty() const { return type == ValueType::Unknown && literal == 0; }
const Type *GetType() const;
rdcstr toString(bool withType = false) const;
bool operator==(const Value &o) { return type == o.type && literal == o.literal; }
ValueType type;
union
{
const Value *value;
const Function *function;
const GlobalVar *global;
const Alias *alias;
const Constant *constant;
const Instruction *instruction;
const Metadata *meta;
const Block *block;
uint64_t literal;
};
};
enum class GlobalFlags : uint32_t
@@ -163,7 +197,7 @@ struct GlobalVar
uint64_t align = 0;
int32_t section = -1;
GlobalFlags flags = GlobalFlags::NoFlags;
Symbol initialiser;
const Constant *initialiser = NULL;
};
struct Alias
@@ -378,45 +412,12 @@ inline uint64_t EncodeCast(Operation op)
struct Constant
{
Constant() = default;
Constant &operator=(const Constant &o) = delete;
Constant(const Constant &o)
{
type = o.type;
val = o.val;
inner = o.inner;
str = o.str;
undef = o.undef;
nullconst = o.nullconst;
symbol = o.symbol;
data = o.data;
op = o.op;
if(data)
{
members.resize(o.members.size());
for(size_t i = 0; i < members.size(); i++)
members[i] = new Constant(*o.members[i]);
}
else
{
members = o.members;
}
}
~Constant()
{
// data constants own their members, they aren't pointers to other constants
if(data)
{
for(size_t i = 0; i < members.size(); i++)
delete members[i];
}
}
const Type *type = NULL;
ShaderValue val = {};
rdcarray<const Constant *> members;
rdcarray<Value> members;
const Constant *inner = NULL;
rdcstr str;
bool undef = false, nullconst = false, symbol = false, data = false;
bool undef = false, nullconst = false, data = false;
Operation op = Operation::NoOp;
rdcstr toString(bool withType = false) const;
@@ -454,10 +455,6 @@ struct DIBase
}
};
struct Function;
struct Metadata;
struct DebugLocation
{
uint32_t id = ~0U;
@@ -482,10 +479,9 @@ struct Metadata
uint32_t id = ~0U;
bool isDistinct = false, isConstant = false, isString = false;
const Constant *constant = NULL;
Value value;
const Function *func = NULL;
size_t instruction = ~0U;
const Instruction *const *inst = NULL;
const Type *type = NULL;
rdcstr str;
@@ -502,8 +498,6 @@ struct NamedMetadata : public Metadata
rdcstr name;
};
struct Function;
enum class InstructionFlags : uint32_t
{
NoFlags = 0,
@@ -556,8 +550,6 @@ BITMASK_OPERATORS(InstructionFlags);
typedef rdcarray<rdcpair<uint64_t, Metadata *>> AttachedMetadata;
struct Block;
struct Instruction
{
Operation op = Operation::NoOp;
@@ -570,7 +562,7 @@ struct Instruction
uint32_t debugLoc = ~0U;
uint32_t align = 0;
const Type *type = NULL;
rdcarray<Symbol> args;
rdcarray<Value> args;
AttachedMetadata attachedMeta;
// function calls
@@ -651,9 +643,6 @@ protected:
uint32_t GetOrAssignMetaID(Metadata *m);
uint32_t GetOrAssignMetaID(DebugLocation &l);
const Type *GetSymbolType(const Function &f, Symbol s);
const Constant *GetFunctionConstant(const Function &f, uint64_t v);
const Metadata *GetFunctionMetadata(const Function &f, uint64_t v);
const Type *GetVoidType();
const Type *GetBoolType();
const Type *GetPointerType(const Type *type, Type::PointerAddrSpace addrSpace) const;
@@ -670,7 +659,7 @@ protected:
rdcarray<GlobalVar> m_GlobalVars;
rdcarray<Function> m_Functions;
rdcarray<Alias> m_Aliases;
rdcarray<Symbol> m_Symbols;
rdcarray<Value> m_Values;
rdcarray<rdcstr> m_Sections;
rdcarray<rdcstr> m_Kinds;
@@ -45,16 +45,14 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
{
bytebuf ret;
std::map<Symbol, uint32_t> valueId;
LLVMBC::BitcodeWriter writer(ret);
LLVMBC::BitcodeWriter::Config cfg = {};
#define getTypeID(t) uint64_t(t - m_Types.begin())
#define getConstantID(c) uint64_t(c - m_Constants.begin())
#define getMetaID(m) uint64_t(m - m_Metadata.begin())
#define getMetaIDOrNull(m) (m ? (uint64_t(m - m_Metadata.begin()) + 1) : 0)
#define getValueID(v) uint64_t(123)
for(size_t i = 0; i < m_GlobalVars.size(); i++)
{
@@ -87,10 +85,10 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
cfg.hasNamedMeta = !m_NamedMeta.empty();
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Symbols.size(); i++)
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Values.size(); i++)
{
// stop once we pass constants
if(m_Symbols[i].type != SymbolType::Constant)
if(m_Values[i].type != ValueType::Constant)
break;
cfg.numGlobalConsts++;
@@ -352,8 +350,8 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
{
typeIndex, uint64_t(((g.flags & GlobalFlags::IsConst) ? 1 : 0) | 0x2 |
((uint32_t)g.type->addrSpace << 2)),
g.initialiser.type != SymbolType::Unknown ? valueId[g.initialiser] + 1 : 0,
linkageValue, 32 - Bits::CountLeadingZeroes(g.align), uint64_t(g.section + 1),
g.initialiser ? getValueID(Value(g.initialiser)) + 1 : 0, linkageValue,
32 - Bits::CountLeadingZeroes(g.align), uint64_t(g.section + 1),
// visibility
0U,
// TLS mode
@@ -370,7 +368,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
for(size_t i = 0; i < m_Functions.size(); i++)
{
const Function &f = m_Functions[i];
uint64_t typeIndex = getTypeID(f.funcType);
uint64_t typeIndex = getTypeID(f.funcType->inner);
writer.Record(LLVMBC::ModuleRecord::FUNCTION,
{
@@ -427,12 +425,8 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
const Type *curType = NULL;
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Symbols.size(); i++)
for(size_t i = 0; i < m_Constants.size(); i++)
{
// stop once we pass constants
if(m_Symbols[i].type != SymbolType::Constant)
break;
if(!inblock)
{
inblock = true;
@@ -464,8 +458,8 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
for(size_t m = 0; m < c.members.size(); m++)
{
vals.push_back(getTypeID(c.members[m]->type));
vals.push_back(getConstantID(c.members[m]));
vals.push_back(getTypeID(c.members[m].GetType()));
vals.push_back(getValueID(c.members[m]));
}
writer.Record(LLVMBC::ConstantsRecord::EVAL_GEP, vals);
@@ -477,7 +471,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
writer.Record(
LLVMBC::ConstantsRecord::EVAL_CAST,
{EncodeCast(c.op), getTypeID(c.type), getTypeID(c.inner->type), getConstantID(c.inner)});
{EncodeCast(c.op), getTypeID(c.type), getTypeID(c.inner->type), getValueID(c.inner)});
}
else if(c.type->scalarType == Type::Int)
{
@@ -511,8 +505,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
else
{
for(size_t m = 0; m < c.members.size(); m++)
vals.push_back(c.type->inner->bitWidth <= 32 ? c.members[m]->val.u32v[0]
: c.members[m]->val.u64v[0]);
vals.push_back(c.members[m].literal);
}
writer.Record(LLVMBC::ConstantsRecord::DATA, vals);
@@ -524,7 +517,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
vals.reserve(c.members.size());
for(size_t m = 0; m < c.members.size(); m++)
vals.push_back(getConstantID(c.members[m]));
vals.push_back(getValueID(c.members[m]));
writer.Record(LLVMBC::ConstantsRecord::AGGREGATE, vals);
}
@@ -553,7 +546,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
else if(m_Metadata[i].isConstant)
{
writer.Record(LLVMBC::MetaDataRecord::VALUE,
{getTypeID(m_Metadata[i].type), getConstantID(m_Metadata[i].constant)});
{getTypeID(m_Metadata[i].type), getValueID(m_Metadata[i].value)});
}
else if(m_Metadata[i].dwarf || m_Metadata[i].debugLoc)
{
@@ -624,19 +617,19 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
rdcarray<rdcpair<size_t, const rdcstr *>> entries;
for(size_t s = 0; s < m_Symbols.size(); s++)
for(size_t s = 0; s < m_Values.size(); s++)
{
bool symtab = false;
switch(m_Symbols[s].type)
const rdcstr *str = NULL;
switch(m_Values[s].type)
{
case SymbolType::GlobalVar:
case SymbolType::Function:
case SymbolType::Alias: symtab = true; break;
case ValueType::GlobalVar: str = &m_Values[s].global->name; break;
case ValueType::Function: str = &m_Values[s].function->name; break;
case ValueType::Alias: str = &m_Values[s].alias->name; break;
default: break;
}
if(symtab)
entries.push_back({s, &m_Constants[s].str});
if(str)
entries.push_back({s, str});
}
// sort the entries by string in order
+173 -132
View File
@@ -94,8 +94,8 @@ struct TypeOrderer
if(m->type)
accumulate(m->type);
if(m->constant)
accumulate(m->constant->type);
if(!m->value.empty())
accumulate(m->value.GetType());
for(const Metadata *c : m->children)
if(c)
@@ -383,8 +383,8 @@ void Program::MakeDisassemblyString()
const GlobalVar &g = m_GlobalVars[i];
typeOrderer.accumulate(g.type);
if(g.initialiser.type == SymbolType::Constant)
typeOrderer.accumulate(m_Constants[(size_t)g.initialiser.idx].type);
if(g.initialiser)
typeOrderer.accumulate(g.initialiser->type);
}
for(size_t i = 0; i < m_Functions.size(); i++)
@@ -399,8 +399,8 @@ void Program::MakeDisassemblyString()
typeOrderer.accumulate(inst.type);
for(size_t a = 0; a < inst.args.size(); a++)
{
if(inst.args[a].type != SymbolType::Literal && inst.args[a].type != SymbolType::BasicBlock)
typeOrderer.accumulate(GetSymbolType(func, inst.args[a]));
if(inst.args[a].type != ValueType::Literal && inst.args[a].type != ValueType::BasicBlock)
typeOrderer.accumulate(inst.args[a].GetType());
}
for(size_t m = 0; m < inst.attachedMeta.size(); m++)
@@ -453,7 +453,7 @@ void Program::MakeDisassemblyString()
switch(g.flags & GlobalFlags::LinkageMask)
{
case GlobalFlags::ExternalLinkage:
if(g.initialiser.type != SymbolType::Constant)
if(!g.initialiser)
m_Disassembly += "external ";
break;
case GlobalFlags::PrivateLinkage: m_Disassembly += "private "; break;
@@ -480,8 +480,8 @@ void Program::MakeDisassemblyString()
else
m_Disassembly += "global ";
if(g.initialiser.type == SymbolType::Constant)
m_Disassembly += m_Constants[(size_t)g.initialiser.idx].toString(true);
if(g.initialiser)
m_Disassembly += g.initialiser->toString(true);
else
m_Disassembly += g.type->inner->toString();
@@ -526,78 +526,72 @@ void Program::MakeDisassemblyString()
{
Function &func = m_Functions[i];
auto argToString = [this, &func](Symbol s, bool withTypes) {
auto argToString = [this, &func](Value v, bool withTypes) {
rdcstr ret;
switch(s.type)
switch(v.type)
{
case SymbolType::Unknown:
case SymbolType::Alias: ret = "???"; break;
case SymbolType::Literal:
case ValueType::Unknown:
case ValueType::Alias: ret = "???"; break;
case ValueType::Literal:
if(withTypes)
ret += "i32 ";
ret += StringFormat::Fmt("%lld", s.idx);
ret += StringFormat::Fmt("%llu", v.literal);
break;
case SymbolType::Metadata:
case ValueType::Metadata:
if(withTypes)
ret += "metadata ";
if(s.idx < m_Metadata.size())
if(m_Metadata.begin() <= v.meta && v.meta < m_Metadata.end())
{
Metadata &m = m_Metadata[(size_t)s.idx];
if(m.isConstant && m.constant && m.constant->symbol)
ret += m.constant->toString(withTypes);
else if(m.isConstant && m.constant &&
(m.constant->type->type == Type::Scalar ||
m.constant->type->type == Type::Vector || m.constant->undef ||
m.constant->nullconst || m.constant->type->name.beginsWith("class.matrix.")))
const Metadata &m = *v.meta;
if(m.isConstant && m.value.type == ValueType::Constant &&
(m.value.constant->type->type == Type::Scalar ||
m.value.constant->type->type == Type::Vector || m.value.constant->undef ||
m.value.constant->nullconst ||
m.value.constant->type->name.beginsWith("class.matrix.")))
{
ret += m.constant->toString(withTypes);
ret += m.value.constant->toString(withTypes);
}
else if(m.isConstant && m.value.type == ValueType::GlobalVar)
{
if(withTypes)
ret += m.value.global->type->toString() + " ";
ret += "@" + escapeStringIfNeeded(m.value.global->name);
}
else
{
ret += StringFormat::Fmt("!%u", GetOrAssignMetaID(&m));
ret += StringFormat::Fmt("!%u", GetOrAssignMetaID((Metadata *)&m));
}
}
else
{
ret += GetFunctionMetadata(func, s.idx)->refString();
ret += v.meta->refString();
}
break;
case SymbolType::Function:
ret = "@" + escapeStringIfNeeded(m_Functions[(size_t)s.idx].name);
break;
case SymbolType::GlobalVar:
case ValueType::Function: ret = "@" + escapeStringIfNeeded(v.function->name); break;
case ValueType::GlobalVar:
if(withTypes)
ret = m_GlobalVars[(size_t)s.idx].type->toString() + " ";
ret += "@" + escapeStringIfNeeded(m_GlobalVars[(size_t)s.idx].name);
ret = v.global->type->toString() + " ";
ret += "@" + escapeStringIfNeeded(v.global->name);
break;
case SymbolType::Constant:
ret = GetFunctionConstant(func, s.idx)->toString(withTypes);
break;
case SymbolType::Argument:
if(withTypes)
ret = func.args[(size_t)s.idx].type->toString() + " ";
ret += "%" + escapeStringIfNeeded(func.args[(size_t)s.idx].name);
break;
case SymbolType::Instruction:
case ValueType::Constant: ret = v.constant->toString(withTypes); break;
case ValueType::Instruction:
{
const Instruction &refinst = func.instructions[(size_t)s.idx];
if(withTypes)
ret = refinst.type->toString() + " ";
if(refinst.name.empty())
ret += StringFormat::Fmt("%%%u", refinst.resultID);
ret = v.instruction->type->toString() + " ";
if(v.instruction->name.empty())
ret += StringFormat::Fmt("%%%u", v.instruction->resultID);
else
ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(refinst.name).c_str());
ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(v.instruction->name).c_str());
break;
}
case SymbolType::BasicBlock:
case ValueType::BasicBlock:
{
const Block &block = func.blocks[(size_t)s.idx];
if(withTypes)
ret = "label ";
if(block.name.empty())
ret += StringFormat::Fmt("%%%u", block.resultID);
if(v.block->name.empty())
ret += StringFormat::Fmt("%%%u", v.block->resultID);
else
ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(block.name).c_str());
ret += StringFormat::Fmt("%%%s", escapeStringIfNeeded(v.block->name).c_str());
}
}
return ret;
@@ -610,7 +604,7 @@ void Program::MakeDisassemblyString()
}
m_Disassembly += (func.external ? "declare " : "define ");
m_Disassembly += func.funcType->declFunction("@" + escapeStringIfNeeded(func.name));
m_Disassembly += func.funcType->inner->declFunction("@" + escapeStringIfNeeded(func.name));
if(func.attrs)
m_Disassembly += StringFormat::Fmt(" #%u", func.attrs->index);
@@ -652,7 +646,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += " @" + escapeStringIfNeeded(inst.funcCall->name);
m_Disassembly += "(";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -708,7 +702,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += "extractvalue ";
m_Disassembly += argToString(inst.args[0], true);
for(size_t n = 1; n < inst.args.size(); n++)
m_Disassembly += StringFormat::Fmt(", %llu", inst.args[n].idx);
m_Disassembly += StringFormat::Fmt(", %llu", inst.args[n].literal);
break;
}
case Operation::FAdd:
@@ -767,7 +761,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += " ";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -793,10 +787,10 @@ void Program::MakeDisassemblyString()
m_Disassembly += "getelementptr ";
if(inst.opFlags & InstructionFlags::InBounds)
m_Disassembly += "inbounds ";
m_Disassembly += GetSymbolType(func, inst.args[0])->inner->toString();
m_Disassembly += inst.args[0].GetType()->inner->toString();
m_Disassembly += ", ";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -814,7 +808,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += inst.type->toString();
m_Disassembly += ", ";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -970,7 +964,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += argToString(inst.args[1], true);
for(size_t a = 2; a < inst.args.size(); a++)
{
m_Disassembly += ", " + ToStr(inst.args[a].idx);
m_Disassembly += ", " + ToStr(inst.args[a].literal);
}
break;
}
@@ -1050,7 +1044,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += inst.type->toString();
m_Disassembly += ", ";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -1081,7 +1075,7 @@ void Program::MakeDisassemblyString()
m_Disassembly += "volatile ";
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -1152,7 +1146,7 @@ void Program::MakeDisassemblyString()
}
bool first = true;
for(Symbol &s : inst.args)
for(Value &s : inst.args)
{
if(!first)
m_Disassembly += ", ";
@@ -1223,21 +1217,19 @@ void Program::MakeDisassemblyString()
if(varIdx > 0)
{
RDCASSERT(inst.args[varIdx].type == SymbolType::Metadata);
RDCASSERT(inst.args[exprIdx].type == SymbolType::Metadata);
RDCASSERT(inst.args[varIdx].type == ValueType::Metadata);
RDCASSERT(inst.args[exprIdx].type == ValueType::Metadata);
m_Disassembly += StringFormat::Fmt(
" ; var:%s ",
escapeString(GetDebugVarName(GetFunctionMetadata(func, inst.args[varIdx].idx)->dwarf))
.c_str());
m_Disassembly += GetFunctionMetadata(func, inst.args[exprIdx].idx)->valString();
" ; var:%s ", escapeString(GetDebugVarName(inst.args[varIdx].meta->dwarf)).c_str());
m_Disassembly += inst.args[exprIdx].meta->valString();
}
}
if(inst.funcCall && inst.funcCall->name.beginsWith("dx.op."))
{
if(inst.args[0].type == SymbolType::Constant)
if(inst.args[0].type == ValueType::Constant)
{
uint32_t opcode = GetFunctionConstant(func, inst.args[0].idx)->val.u32v[0];
uint32_t opcode = inst.args[0].constant->val.u32v[0];
if(opcode < ARRAY_COUNT(funcSigs))
{
m_Disassembly += " ; ";
@@ -1248,12 +1240,10 @@ void Program::MakeDisassemblyString()
if(inst.funcCall && inst.funcCall->name.beginsWith("dx.op.annotateHandle"))
{
if(inst.args[2].type == SymbolType::Constant && inst.args[3].type == SymbolType::Constant)
if(inst.args[2].type == ValueType::Constant && inst.args[3].type == ValueType::Constant)
{
ResourceClass resClass =
(ResourceClass)GetFunctionConstant(func, inst.args[2].idx)->val.u32v[0];
ResourceKind resKind =
(ResourceKind)GetFunctionConstant(func, inst.args[3].idx)->val.u32v[0];
ResourceClass resClass = (ResourceClass)inst.args[2].constant->val.u32v[0];
ResourceKind resKind = (ResourceKind)inst.args[3].constant->val.u32v[0];
m_Disassembly += " resource: ";
@@ -1261,12 +1251,12 @@ void Program::MakeDisassemblyString()
uint32_t packedProps[2] = {};
const Constant *props = GetFunctionConstant(func, inst.args[4].idx);
const Constant *props = inst.args[4].constant;
if(props && !props->nullconst)
{
packedProps[0] = props->members[0]->val.u32v[0];
packedProps[1] = props->members[1]->val.u32v[0];
packedProps[0] = props->members[0].constant->val.u32v[0];
packedProps[1] = props->members[1].constant->val.u32v[0];
}
ComponentType compType = ComponentType(packedProps[0] & 0x1f);
@@ -1635,28 +1625,29 @@ rdcstr Metadata::valString() const
}
else
{
if(constant)
const Instruction *i = NULL;
if(inst && *inst)
i = *inst;
else if(value.type == ValueType::Instruction)
i = value.instruction;
if(i)
{
if(type != constant->type)
RDCERR("Type mismatch in metadata");
return constant->toString(true);
if(i->name.empty())
return StringFormat::Fmt("%s %%%u", i->type->toString().c_str(), i->resultID);
else
return StringFormat::Fmt("%s %%%s", i->type->toString().c_str(),
escapeStringIfNeeded(i->name).c_str());
}
else if(!value.empty())
{
return value.toString(true);
}
else
{
if(func && instruction < func->instructions.size())
{
const Instruction &inst = func->instructions[instruction];
if(inst.name.empty())
return StringFormat::Fmt("%s %%%u", inst.type->toString().c_str(), inst.resultID);
else
return StringFormat::Fmt("%s %%%s", inst.type->toString().c_str(),
escapeStringIfNeeded(inst.name).c_str());
}
else
{
RDCERR("No instruction symbol for value-less metadata");
return "???";
}
RDCERR("No instruction for value-less metadata");
return "???";
}
}
}
@@ -1717,6 +1708,62 @@ static void floatAppendToString(const Type *t, const ShaderValue &val, uint32_t
ret += StringFormat::Fmt("0x%llX", d);
}
void shaderValAppendToString(const Type *type, const ShaderValue &val, uint32_t i, rdcstr &ret)
{
if(type->scalarType == Type::Float)
{
floatAppendToString(type, val, i, ret);
}
else if(type->scalarType == Type::Int)
{
// LLVM seems to always interpret these as signed? :(
if(type->bitWidth > 32)
ret += StringFormat::Fmt("%lld", val.s64v[i]);
else if(type->bitWidth == 1)
ret += val.u32v[i] ? "true" : "false";
else
ret += StringFormat::Fmt("%d", val.s32v[i]);
}
}
rdcstr Value::toString(bool withType) const
{
rdcstr ret;
if(withType)
{
const Type *t = GetType();
if(t)
ret += t->toString() + " ";
else
RDCERR("Type requested in value string, but no type available");
}
switch(type)
{
case ValueType::Function:
ret += StringFormat::Fmt("@%s", escapeStringIfNeeded(function->name).c_str());
break;
case ValueType::GlobalVar:
ret += StringFormat::Fmt("@%s", escapeStringIfNeeded(global->name).c_str());
break;
case ValueType::Alias:
ret += StringFormat::Fmt("@%s", escapeStringIfNeeded(alias->name).c_str());
break;
case ValueType::Constant: return constant->toString(withType); break;
case ValueType::Unknown:
RDCERR("Invalid or forward-reference value being stringised");
ret += "???";
break;
case ValueType::Instruction:
case ValueType::Metadata:
case ValueType::Literal:
case ValueType::BasicBlock:
RDCERR("Unexpected value being stringised");
ret += "???";
break;
}
return ret;
}
rdcstr Constant::toString(bool withType) const
{
if(type == NULL)
@@ -1729,10 +1776,6 @@ rdcstr Constant::toString(bool withType) const
{
ret += "undef";
}
else if(symbol)
{
ret += StringFormat::Fmt("@%s", escapeStringIfNeeded(str).c_str());
}
else if(op != Operation::NoOp)
{
switch(op)
@@ -1742,14 +1785,14 @@ rdcstr Constant::toString(bool withType) const
{
ret += "getelementptr inbounds (";
const Type *baseType = members[0]->type;
const Type *baseType = members[0].GetType();
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 += members[i].toString(withType);
}
ret += ")";
break;
@@ -1797,20 +1840,7 @@ rdcstr Constant::toString(bool withType) const
}
else if(type->type == Type::Scalar)
{
if(type->scalarType == Type::Float)
{
floatAppendToString(type, val, 0, ret);
}
else if(type->scalarType == Type::Int)
{
// LLVM seems to always interpret these as signed? :(
if(type->bitWidth > 32)
ret += StringFormat::Fmt("%lld", val.s64v[0]);
else if(type->bitWidth == 1)
ret += val.u32v[0] ? "true" : "false";
else
ret += StringFormat::Fmt("%d", val.s32v[0]);
}
shaderValAppendToString(type, val, 0, ret);
}
else if(nullconst)
{
@@ -1825,19 +1855,7 @@ rdcstr Constant::toString(bool withType) const
ret += ", ";
if(withType)
ret += type->inner->toString() + " ";
if(type->scalarType == Type::Float)
{
floatAppendToString(type, val, i, ret);
}
else if(type->scalarType == Type::Int)
{
if(type->bitWidth > 32)
ret += StringFormat::Fmt("%lld", val.s64v[i]);
else if(type->bitWidth == 1)
ret += val.u32v[i] ? "true" : "false";
else
ret += StringFormat::Fmt("%d", val.s32v[i]);
}
shaderValAppendToString(type, val, i, ret);
}
ret += ">";
}
@@ -1849,7 +1867,20 @@ rdcstr Constant::toString(bool withType) const
if(i > 0)
ret += ", ";
ret += members[i]->toString(withType);
if(members[i].type == ValueType::Literal)
{
if(withType)
ret += type->inner->toString() + " ";
ShaderValue v;
v.u64v[0] = members[i].literal;
shaderValAppendToString(type->inner, v, 0, ret);
}
else
{
ret += members[i].toString(withType);
}
}
ret += "]";
}
@@ -1861,7 +1892,17 @@ rdcstr Constant::toString(bool withType) const
if(i > 0)
ret += ", ";
ret += members[i]->toString(withType);
if(members[i].type == ValueType::Literal)
{
ShaderValue v;
v.u64v[0] = members[i].literal;
shaderValAppendToString(members[i].GetType(), v, 0, ret);
}
else
{
ret += members[i].toString(withType);
}
}
ret += " }";
}
@@ -90,7 +90,7 @@ enum class StructMemberAnnotation
template <typename T>
T getival(const Metadata *m)
{
return T(m->constant->val.u32v[0]);
return T(m->value.constant->val.u32v[0]);
}
void Program::FetchComputeProperties(DXBC::Reflection *reflection)
@@ -815,10 +815,9 @@ DXBC::Reflection *Program::GetReflection()
if(dx.valver && dx.valver->children.size() == 1 && dx.valver->children[0]->children.size() == 2)
{
m_CompilerSig +=
StringFormat::Fmt(" (Validation version %s.%s)",
dx.valver->children[0]->children[0]->constant->toString().c_str(),
dx.valver->children[0]->children[1]->constant->toString().c_str());
m_CompilerSig += StringFormat::Fmt(
" (Validation version %s.%s)", dx.valver->children[0]->children[0]->value.toString().c_str(),
dx.valver->children[0]->children[1]->value.toString().c_str());
}
if(dx.entryPoints && dx.entryPoints->children.size() > 0 &&
@@ -837,8 +836,8 @@ DXBC::Reflection *Program::GetReflection()
{
m_Profile =
StringFormat::Fmt("%s_%s_%s", dx.shaderModel->children[0]->children[0]->str.c_str(),
dx.shaderModel->children[0]->children[1]->constant->toString().c_str(),
dx.shaderModel->children[0]->children[2]->constant->toString().c_str());
dx.shaderModel->children[0]->children[1]->value.toString().c_str(),
dx.shaderModel->children[0]->children[2]->value.toString().c_str());
}
else
{