mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 13:00:32 +00:00
Emit the global constants block in DXIL
This commit is contained in:
@@ -84,8 +84,8 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
Constant v;
|
||||
v.op = DecodeCast(constant.ops[0]);
|
||||
v.type = curType;
|
||||
// getType(constant.ops[1]); type of the constant, which we ignore
|
||||
v.inner = getConstant(constant.ops[2]);
|
||||
RDCASSERT(getType(constant.ops[1]) == v.inner->type);
|
||||
addConstant(v);
|
||||
}
|
||||
else if(IS_KNOWN(constant.id, ConstantsRecord::EVAL_GEP))
|
||||
@@ -104,26 +104,28 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
const Constant *a = getConstant(constant.ops[idx + 1]);
|
||||
RDCASSERT(t == a->type);
|
||||
|
||||
v.members.push_back(*a);
|
||||
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.members[0]->type;
|
||||
|
||||
// walk the type list to get the return type
|
||||
for(idx = 2; idx < v.members.size(); idx++)
|
||||
{
|
||||
v.type = v.type->inner;
|
||||
}
|
||||
else if(v.type->type == Type::Struct)
|
||||
{
|
||||
v.type = v.type->members[v.members[idx].val.u32v[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected type %d encountered in GEP", v.type->type);
|
||||
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.u32v[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCERR("Unexpected type %d encountered in GEP", v.type->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +147,8 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
|
||||
if(member)
|
||||
{
|
||||
v.members.push_back(member);
|
||||
|
||||
if(v.type->bitWidth <= 32)
|
||||
v.val.u32v[m] = member->val.u32v[m];
|
||||
else
|
||||
@@ -164,13 +168,13 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
|
||||
if(member && member->type)
|
||||
{
|
||||
v.members.push_back(*member);
|
||||
v.members.push_back(member);
|
||||
}
|
||||
else
|
||||
{
|
||||
Constant c;
|
||||
c.type = NULL;
|
||||
c.val.u64v[0] = m;
|
||||
Constant *c = new Constant();
|
||||
c->type = NULL;
|
||||
c->val.u64v[0] = m;
|
||||
v.members.push_back(c);
|
||||
RDCWARN("Index %llu out of bounds for constants array, possible forward reference", m);
|
||||
}
|
||||
@@ -182,6 +186,7 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
{
|
||||
Constant v;
|
||||
v.type = curType;
|
||||
v.data = true;
|
||||
if(v.type->type == Type::Vector)
|
||||
{
|
||||
for(size_t m = 0; m < constant.ops.size(); m++)
|
||||
@@ -196,12 +201,12 @@ void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
{
|
||||
for(size_t m = 0; m < constant.ops.size(); m++)
|
||||
{
|
||||
Constant el;
|
||||
el.type = v.type->inner;
|
||||
if(el.type->bitWidth <= 32)
|
||||
el.val.u32v[0] = constant.ops[m] & ((1ULL << el.type->bitWidth) - 1);
|
||||
Constant *el = new Constant();
|
||||
el->type = v.type->inner;
|
||||
if(el->type->bitWidth <= 32)
|
||||
el->val.u32v[0] = constant.ops[m] & ((1ULL << el->type->bitWidth) - 1);
|
||||
else
|
||||
el.val.u64v[m] = constant.ops[m];
|
||||
el->val.u64v[0] = constant.ops[m];
|
||||
v.members.push_back(el);
|
||||
}
|
||||
}
|
||||
@@ -474,16 +479,23 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, ModuleRecord::ALIAS))
|
||||
{
|
||||
// [alias value type, addrspace, aliasee val#, linkage, visibility]
|
||||
// [alias type, aliasee val#, linkage, visibility]
|
||||
Alias a;
|
||||
|
||||
a.type = &m_Types[(size_t)rootchild.ops[0]];
|
||||
a.valID = rootchild.ops[1];
|
||||
|
||||
// ignore rest of properties, assert that if present they are 0
|
||||
for(size_t p = 2; p < rootchild.ops.size(); p++)
|
||||
RDCASSERT(rootchild.ops[p] == 0, p, rootchild.ops[p]);
|
||||
|
||||
// symbols refer into any of N types in declaration order
|
||||
m_Symbols.push_back({SymbolType::Alias, m_Aliases.size()});
|
||||
|
||||
// all global symbols are 'values' in LLVM, we don't need this but need to keep indexing the
|
||||
// same
|
||||
Constant v;
|
||||
v.type = &m_Types[(size_t)rootchild.ops[0]];
|
||||
v.type = a.type;
|
||||
v.symbol = true;
|
||||
m_Constants.push_back(v);
|
||||
|
||||
@@ -800,25 +812,30 @@ Program::Program(const byte *bytes, size_t length)
|
||||
if(c.members.empty())
|
||||
continue;
|
||||
|
||||
for(Constant &m : c.members)
|
||||
for(size_t m = 0; m < c.members.size(); m++)
|
||||
{
|
||||
if(m.type == NULL)
|
||||
const Constant *mem = c.members[m];
|
||||
if(mem->type == NULL)
|
||||
{
|
||||
if(m.val.u64v[0] > 0)
|
||||
size_t idx = (size_t)mem->val.u64v[0];
|
||||
|
||||
delete mem;
|
||||
|
||||
if(idx > 0)
|
||||
{
|
||||
size_t idx = (size_t)m.val.u64v[0];
|
||||
if(idx < m_Constants.size())
|
||||
{
|
||||
m = m_Constants[idx];
|
||||
c.members[m] = &m_Constants[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
m = Constant();
|
||||
c.members[m] = &m_Constants[0];
|
||||
RDCERR("Couldn't resolve constant %zu", idx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c.members[m] = &m_Constants[0];
|
||||
RDCERR("Unexpected member with no type but no forward-index constant value");
|
||||
}
|
||||
}
|
||||
@@ -1017,16 +1034,21 @@ Program::Program(const byte *bytes, size_t length)
|
||||
if(c.members.empty())
|
||||
continue;
|
||||
|
||||
for(Constant &m : c.members)
|
||||
for(size_t m = 0; m < c.members.size(); m++)
|
||||
{
|
||||
if(m.type == NULL)
|
||||
const Constant *mem = c.members[m];
|
||||
if(mem->type == NULL)
|
||||
{
|
||||
if(m.val.u64v[0] > 0)
|
||||
uint64_t idx = mem->val.u64v[0];
|
||||
delete mem;
|
||||
|
||||
if(idx > 0)
|
||||
{
|
||||
m = *getConstant(m.val.u64v[0]);
|
||||
c.members[m] = getConstant(idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.members[m] = getConstant(0);
|
||||
RDCERR("Unexpected member with no type but no forward-index constant value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,14 +355,68 @@ inline Operation DecodeCast(uint64_t opcode)
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64_t EncodeCast(Operation op)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case Operation::Trunc: return 0; break;
|
||||
case Operation::ZExt: return 1; break;
|
||||
case Operation::SExt: return 2; break;
|
||||
case Operation::FToU: return 3; break;
|
||||
case Operation::FToS: return 4; break;
|
||||
case Operation::UToF: return 5; break;
|
||||
case Operation::SToF: return 6; break;
|
||||
case Operation::FPTrunc: return 7; break;
|
||||
case Operation::FPExt: return 8; break;
|
||||
case Operation::PtrToI: return 9; break;
|
||||
case Operation::IToPtr: return 10; break;
|
||||
case Operation::Bitcast: return 11; break;
|
||||
case Operation::AddrSpaceCast: return 12; break;
|
||||
default: return ~0U;
|
||||
}
|
||||
}
|
||||
|
||||
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<Constant> members;
|
||||
rdcarray<const Constant *> members;
|
||||
const Constant *inner = NULL;
|
||||
rdcstr str;
|
||||
bool undef = false, nullconst = false, symbol = false;
|
||||
bool undef = false, nullconst = false, symbol = false, data = false;
|
||||
Operation op = Operation::NoOp;
|
||||
|
||||
rdcstr toString(bool withType = false) const;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "dxil_bytecode_editor.h"
|
||||
#include "driver/shaders/dxbc/dxbc_container.h"
|
||||
#include "maths/half_convert.h"
|
||||
#include "dxil_bytecode.h"
|
||||
#include "llvm_encoder.h"
|
||||
|
||||
@@ -51,18 +52,31 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
uint64_t maxAlign = 0;
|
||||
uint32_t maxGlobalType = 0;
|
||||
|
||||
auto getTypeID = [this](const Type *t) { return uint64_t(t - m_Types.begin()); };
|
||||
|
||||
for(size_t i = 0; i < m_GlobalVars.size(); i++)
|
||||
{
|
||||
maxAlign = RDCMAX(m_GlobalVars[i].align, maxAlign);
|
||||
RDCASSERT(m_GlobalVars[i].type->type == Type::Pointer);
|
||||
uint32_t typeIndex = uint32_t(m_GlobalVars[i].type->inner - m_Types.begin());
|
||||
uint32_t typeIndex = uint32_t(getTypeID(m_GlobalVars[i].type->inner));
|
||||
maxGlobalType = RDCMAX(typeIndex, maxGlobalType);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
maxAlign = RDCMAX(m_Functions[i].align, maxAlign);
|
||||
|
||||
writer.ConfigureSizes(m_Types.size(), m_Sections.size(), maxAlign, maxGlobalType);
|
||||
size_t numGlobalConsts = 0;
|
||||
|
||||
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Symbols.size(); i++)
|
||||
{
|
||||
// stop once we pass constants
|
||||
if(m_Symbols[i].type != SymbolType::Constant)
|
||||
break;
|
||||
|
||||
numGlobalConsts++;
|
||||
}
|
||||
|
||||
writer.ConfigureSizes(m_Types.size(), numGlobalConsts, m_Sections.size(), maxAlign, maxGlobalType);
|
||||
|
||||
writer.BeginBlock(LLVMBC::KnownBlock::MODULE_BLOCK);
|
||||
|
||||
@@ -206,18 +220,17 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
}
|
||||
else if(m_Types[i].type == Type::Vector)
|
||||
{
|
||||
size_t innerTypeIndex = m_Types[i].inner - m_Types.begin();
|
||||
writer.Record(LLVMBC::TypeRecord::VECTOR, {m_Types[i].elemCount, innerTypeIndex});
|
||||
writer.Record(LLVMBC::TypeRecord::VECTOR,
|
||||
{m_Types[i].elemCount, getTypeID(m_Types[i].inner)});
|
||||
}
|
||||
else if(m_Types[i].type == Type::Array)
|
||||
{
|
||||
size_t innerTypeIndex = m_Types[i].inner - m_Types.begin();
|
||||
writer.Record(LLVMBC::TypeRecord::ARRAY, {m_Types[i].elemCount, innerTypeIndex});
|
||||
writer.Record(LLVMBC::TypeRecord::ARRAY, {m_Types[i].elemCount, getTypeID(m_Types[i].inner)});
|
||||
}
|
||||
else if(m_Types[i].type == Type::Pointer)
|
||||
{
|
||||
size_t innerTypeIndex = m_Types[i].inner - m_Types.begin();
|
||||
writer.Record(LLVMBC::TypeRecord::POINTER, {innerTypeIndex, (uint64_t)m_Types[i].addrSpace});
|
||||
writer.Record(LLVMBC::TypeRecord::POINTER,
|
||||
{getTypeID(m_Types[i].inner), (uint64_t)m_Types[i].addrSpace});
|
||||
}
|
||||
else if(m_Types[i].type == Type::Struct)
|
||||
{
|
||||
@@ -240,7 +253,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
vals.push_back(m_Types[i].packedStruct ? 1 : 0);
|
||||
|
||||
for(const Type *t : m_Types[i].members)
|
||||
vals.push_back(t - m_Types.begin());
|
||||
vals.push_back(getTypeID(t));
|
||||
|
||||
writer.Record(type, vals);
|
||||
}
|
||||
@@ -251,10 +264,10 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
|
||||
vals.push_back(m_Types[i].vararg ? 1 : 0);
|
||||
|
||||
vals.push_back(m_Types[i].inner - m_Types.begin());
|
||||
vals.push_back(getTypeID(m_Types[i].inner));
|
||||
|
||||
for(const Type *t : m_Types[i].members)
|
||||
vals.push_back(t - m_Types.begin());
|
||||
vals.push_back(getTypeID(t));
|
||||
|
||||
writer.Record(LLVMBC::TypeRecord::FUNCTION, vals);
|
||||
}
|
||||
@@ -285,7 +298,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
const GlobalVar &g = m_GlobalVars[i];
|
||||
|
||||
// global vars write the value type, not the pointer
|
||||
size_t typeIndex = g.type->inner - m_Types.begin();
|
||||
uint64_t typeIndex = getTypeID(g.type->inner);
|
||||
|
||||
uint64_t linkageValue = 0;
|
||||
|
||||
@@ -334,7 +347,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = m_Functions[i];
|
||||
size_t typeIndex = f.funcType - m_Types.begin();
|
||||
uint64_t typeIndex = getTypeID(f.funcType);
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::FUNCTION,
|
||||
{
|
||||
@@ -373,7 +386,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
for(size_t i = 0; i < m_Aliases.size(); i++)
|
||||
{
|
||||
const Alias &a = m_Aliases[i];
|
||||
size_t typeIndex = a.type - m_Types.begin();
|
||||
uint64_t typeIndex = getTypeID(a.type);
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::ALIAS, {
|
||||
typeIndex, a.valID,
|
||||
@@ -384,6 +397,120 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
});
|
||||
}
|
||||
|
||||
// the symbols for constants start after the global variables and functions which we just
|
||||
// outputted
|
||||
{
|
||||
bool inblock = false;
|
||||
|
||||
const Type *curType = NULL;
|
||||
|
||||
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Symbols.size(); i++)
|
||||
{
|
||||
// stop once we pass constants
|
||||
if(m_Symbols[i].type != SymbolType::Constant)
|
||||
break;
|
||||
|
||||
if(!inblock)
|
||||
{
|
||||
inblock = true;
|
||||
writer.BeginBlock(LLVMBC::KnownBlock::CONSTANTS_BLOCK);
|
||||
}
|
||||
|
||||
const Constant &c = m_Constants[i];
|
||||
if(c.type != curType)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::SETTYPE, getTypeID(c.type));
|
||||
curType = c.type;
|
||||
}
|
||||
|
||||
if(c.nullconst)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::CONST_NULL);
|
||||
}
|
||||
else if(c.undef)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::UNDEF);
|
||||
}
|
||||
else if(c.op == Operation::GetElementPtr)
|
||||
{
|
||||
rdcarray<uint64_t> vals;
|
||||
vals.reserve(c.members.size() * 2 + 1);
|
||||
|
||||
// DXC's version of llvm always writes the explicit type here
|
||||
vals.push_back(getTypeID(c.type));
|
||||
|
||||
for(size_t m = 0; m < c.members.size(); m++)
|
||||
{
|
||||
vals.push_back(getTypeID(c.members[m]->type));
|
||||
vals.push_back(c.members[m] - m_Constants.begin());
|
||||
}
|
||||
|
||||
writer.Record(LLVMBC::ConstantsRecord::EVAL_GEP, vals);
|
||||
}
|
||||
else if(c.op != Operation::NoOp)
|
||||
{
|
||||
uint64_t cast = EncodeCast(c.op);
|
||||
RDCASSERT(cast != ~0U);
|
||||
|
||||
writer.Record(LLVMBC::ConstantsRecord::EVAL_CAST,
|
||||
{EncodeCast(c.op), getTypeID(c.type), getTypeID(c.inner->type),
|
||||
uint64_t(c.inner - m_Constants.begin())});
|
||||
}
|
||||
else if(c.type->scalarType == Type::Int)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::INTEGER, LLVMBC::BitWriter::svbr(c.val.s64v[0]));
|
||||
}
|
||||
else if(c.type->scalarType == Type::Float)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::FLOAT, c.val.u64v[0]);
|
||||
}
|
||||
else if(!c.str.empty())
|
||||
{
|
||||
if(c.str.indexOf('\0') < 0)
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::CSTRING, c.str);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Record(LLVMBC::ConstantsRecord::STRING, c.str);
|
||||
}
|
||||
}
|
||||
else if(c.data)
|
||||
{
|
||||
rdcarray<uint64_t> vals;
|
||||
vals.reserve(c.members.size());
|
||||
|
||||
if(c.type->type == Type::Vector)
|
||||
{
|
||||
for(uint32_t m = 0; m < c.type->elemCount; m++)
|
||||
vals.push_back(c.type->bitWidth <= 32 ? c.val.u32v[m] : c.val.u64v[m]);
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
writer.Record(LLVMBC::ConstantsRecord::DATA, vals);
|
||||
}
|
||||
else if(c.type->type == Type::Vector || c.type->type == Type::Array ||
|
||||
c.type->type == Type::Struct)
|
||||
{
|
||||
rdcarray<uint64_t> vals;
|
||||
vals.reserve(c.members.size());
|
||||
|
||||
for(size_t m = 0; m < c.members.size(); m++)
|
||||
vals.push_back(c.members[m] - m_Constants.begin());
|
||||
|
||||
writer.Record(LLVMBC::ConstantsRecord::AGGREGATE, vals);
|
||||
}
|
||||
}
|
||||
|
||||
if(inblock)
|
||||
writer.EndBlock();
|
||||
}
|
||||
|
||||
writer.EndBlock();
|
||||
|
||||
ProgramHeader header;
|
||||
|
||||
@@ -1265,8 +1265,8 @@ void Program::MakeDisassemblyString()
|
||||
|
||||
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]->val.u32v[0];
|
||||
packedProps[1] = props->members[1]->val.u32v[0];
|
||||
}
|
||||
|
||||
ComponentType compType = ComponentType(packedProps[0] & 0x1f);
|
||||
@@ -1742,14 +1742,14 @@ rdcstr Constant::toString(bool withType) const
|
||||
{
|
||||
ret += "getelementptr inbounds (";
|
||||
|
||||
const Type *baseType = members[0].type;
|
||||
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 += members[i]->toString(withType);
|
||||
}
|
||||
ret += ")";
|
||||
break;
|
||||
@@ -1849,7 +1849,7 @@ rdcstr Constant::toString(bool withType) const
|
||||
if(i > 0)
|
||||
ret += ", ";
|
||||
|
||||
ret += members[i].toString(withType);
|
||||
ret += members[i]->toString(withType);
|
||||
}
|
||||
ret += "]";
|
||||
}
|
||||
@@ -1861,7 +1861,7 @@ rdcstr Constant::toString(bool withType) const
|
||||
if(i > 0)
|
||||
ret += ", ";
|
||||
|
||||
ret += members[i].toString(withType);
|
||||
ret += members[i]->toString(withType);
|
||||
}
|
||||
ret += " }";
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ enum class ModuleRecord : uint32_t
|
||||
SECTIONNAME = 5,
|
||||
GLOBALVAR = 7,
|
||||
FUNCTION = 8,
|
||||
ALIAS = 14,
|
||||
ALIAS = 9,
|
||||
};
|
||||
|
||||
enum class ConstantsRecord : uint32_t
|
||||
|
||||
@@ -57,8 +57,6 @@ static uint32_t GetBlockAbbrevSize(KnownBlock block)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MagicFixedSizeNumTypes 99
|
||||
|
||||
#define AbbFixed(n) \
|
||||
{ \
|
||||
AbbrevEncoding::Fixed, n \
|
||||
@@ -80,7 +78,11 @@ static uint32_t GetBlockAbbrevSize(KnownBlock block)
|
||||
AbbrevEncoding::Char6, 0 \
|
||||
}
|
||||
|
||||
#define MagicFixedSizeNumTypes 99
|
||||
#define MagicFixedSizeNumConstants 999
|
||||
|
||||
#define AbbFixedTypes() AbbFixed(MagicFixedSizeNumTypes)
|
||||
#define AbbFixedConstants() AbbFixed(MagicFixedSizeNumConstants)
|
||||
|
||||
using AbbrevDefinition = AbbrevParam[8];
|
||||
|
||||
@@ -119,6 +121,11 @@ enum class ConstantsAbbrev
|
||||
Integer,
|
||||
EvalCast,
|
||||
Null,
|
||||
// the ones below are only used in the global constants block
|
||||
Aggregate,
|
||||
String,
|
||||
CString7,
|
||||
CString6,
|
||||
};
|
||||
|
||||
AbbrevDefinition ConstantsAbbrevDefs[] = {
|
||||
@@ -140,6 +147,25 @@ AbbrevDefinition ConstantsAbbrevDefs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
AbbrevDefinition ConstantsGlobalAbbrevDefs[] = {
|
||||
// Aggregate
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::AGGREGATE), AbbArray(), AbbFixedConstants(),
|
||||
},
|
||||
// String
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::STRING), AbbArray(), AbbFixed(8),
|
||||
},
|
||||
// CString7
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::CSTRING), AbbArray(), AbbFixed(7),
|
||||
},
|
||||
// CString6
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::CSTRING), AbbArray(), AbbChar6(),
|
||||
},
|
||||
};
|
||||
|
||||
enum class FunctionAbbrev
|
||||
{
|
||||
Load,
|
||||
@@ -263,8 +289,6 @@ BitcodeWriter::BitcodeWriter(bytebuf &buf) : b(buf)
|
||||
curBlock = KnownBlock::Count;
|
||||
abbrevSize = 2;
|
||||
|
||||
numAbbrevs = 0;
|
||||
|
||||
m_GlobalVarAbbrev = ~0U;
|
||||
}
|
||||
|
||||
@@ -294,16 +318,32 @@ void BitcodeWriter::BeginBlock(KnownBlock block)
|
||||
|
||||
curBlock = block;
|
||||
abbrevSize = newAbbrevSize;
|
||||
blockStack.push_back({block, offs, numAbbrevs});
|
||||
blockStack.push_back({block, offs});
|
||||
|
||||
curAbbrevs.swap(blockStack.back().abbrevs);
|
||||
|
||||
// emit known abbrevs here that aren't in blockinfo
|
||||
switch(block)
|
||||
{
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK:
|
||||
case KnownBlock::CONSTANTS_BLOCK:
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK:
|
||||
case KnownBlock::FUNCTION_BLOCK:
|
||||
{
|
||||
// these blocks have abbrevs but we shouldn't emit them as they're handled in blockinfo
|
||||
// these blocks have abbrevs from the blockinfo. Don't write them, but add them to our abbrev
|
||||
// dictionary
|
||||
uint32_t numAbbrevDefs = GetNumAbbrevDefs(block);
|
||||
AbbrevDefinition *abbrevs = GetAbbrevDefs(block);
|
||||
for(uint32_t i = 0; i < numAbbrevDefs; i++)
|
||||
curAbbrevs.push_back(abbrevs[i]);
|
||||
|
||||
// the global constants block has some extra abbrevs
|
||||
// blockStack[0] is always the module block
|
||||
if(block == KnownBlock::CONSTANTS_BLOCK && blockStack.size() == 2)
|
||||
{
|
||||
for(size_t i = 0; i < ARRAY_COUNT(ConstantsGlobalAbbrevDefs); i++)
|
||||
WriteAbbrevDefinition(ConstantsGlobalAbbrevDefs[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -338,14 +378,14 @@ void BitcodeWriter::EndBlock()
|
||||
else
|
||||
{
|
||||
curBlock = blockStack.back().block;
|
||||
numAbbrevs = blockStack.back().numAbbrevs;
|
||||
curAbbrevs = blockStack.back().abbrevs;
|
||||
abbrevSize = GetBlockAbbrevSize(curBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
|
||||
{
|
||||
numAbbrevs++;
|
||||
curAbbrevs.push_back(abbrev);
|
||||
|
||||
b.fixed(abbrevSize, DEFINE_ABBREV);
|
||||
|
||||
@@ -361,6 +401,8 @@ void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
|
||||
|
||||
if(param.value == MagicFixedSizeNumTypes)
|
||||
param.value = m_NumTypeBits;
|
||||
if(param.value == MagicFixedSizeNumConstants)
|
||||
param.value = m_NumConstantBits;
|
||||
|
||||
const bool lit = param.encoding == AbbrevEncoding::Literal;
|
||||
b.fixed<bool>(1, lit);
|
||||
@@ -377,10 +419,11 @@ void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::ConfigureSizes(size_t numTypes, size_t numSections, uint64_t maxAlign,
|
||||
uint32_t maxGlobalType)
|
||||
void BitcodeWriter::ConfigureSizes(size_t numTypes, size_t numGlobalConsts, size_t numSections,
|
||||
uint64_t maxAlign, uint32_t maxGlobalType)
|
||||
{
|
||||
m_NumTypeBits = 32 - Bits::CountLeadingZeroes((uint32_t)numTypes);
|
||||
m_NumConstantBits = 32 - Bits::CountLeadingZeroes((uint32_t)numGlobalConsts);
|
||||
|
||||
m_GlobalTypeBits = 32 - Bits::CountLeadingZeroes(maxGlobalType);
|
||||
|
||||
@@ -410,7 +453,7 @@ void BitcodeWriter::ModuleBlockInfo()
|
||||
for(KnownBlock block :
|
||||
{KnownBlock::VALUE_SYMTAB_BLOCK, KnownBlock::CONSTANTS_BLOCK, KnownBlock::FUNCTION_BLOCK})
|
||||
{
|
||||
Unabbrev((uint32_t)BlockInfoRecord::SETBID, (uint32_t)block);
|
||||
Unabbrev((uint32_t)BlockInfoRecord::SETBID, true, (uint32_t)block);
|
||||
AbbrevDefinition *abbrevs = GetAbbrevDefs(block);
|
||||
uint32_t numAbbrevDefs = GetNumAbbrevDefs(block);
|
||||
|
||||
@@ -423,7 +466,7 @@ void BitcodeWriter::ModuleBlockInfo()
|
||||
|
||||
void BitcodeWriter::EmitGlobalVarAbbrev()
|
||||
{
|
||||
m_GlobalVarAbbrev = numAbbrevs;
|
||||
m_GlobalVarAbbrev = (uint32_t)curAbbrevs.size();
|
||||
|
||||
AbbrevParam align = AbbFixed(m_AlignBits);
|
||||
if(m_AlignBits == 0)
|
||||
@@ -447,21 +490,13 @@ void BitcodeWriter::EmitGlobalVarAbbrev()
|
||||
uint32_t BitcodeWriter::GetAbbrevID(uint32_t id)
|
||||
{
|
||||
// the id is a block-local index, starting from 0, of the abbrevs defined for that block.
|
||||
|
||||
// when we begin a block, we store the number of previously defined abbrevs from earlier blocks so
|
||||
// we add that on
|
||||
id += blockStack.back().numAbbrevs;
|
||||
|
||||
// the ID we need to encode starts at APPLICATION_ABBREV for the first one, so add that
|
||||
return APPLICATION_ABBREV + id;
|
||||
}
|
||||
|
||||
void BitcodeWriter::AutoRecord(uint32_t record, bool param, uint64_t val)
|
||||
{
|
||||
AbbrevDefinition *abbrevs = GetAbbrevDefs(curBlock);
|
||||
uint32_t numAbbrevDefs = GetNumAbbrevDefs(curBlock);
|
||||
|
||||
uint32_t idx = numAbbrevDefs;
|
||||
uint32_t idx = ~0U;
|
||||
|
||||
// the records with abbrevs are hardcoded, so just determine if this record in this block has an
|
||||
// abbrev and select it here
|
||||
@@ -477,6 +512,33 @@ void BitcodeWriter::AutoRecord(uint32_t record, bool param, uint64_t val)
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case KnownBlock::CONSTANTS_BLOCK:
|
||||
{
|
||||
// blockStack[0] is always the module block
|
||||
const bool globalConsts = blockStack.size() == 2;
|
||||
switch(ConstantsRecord(record))
|
||||
{
|
||||
// global only abbrevs
|
||||
case ConstantsRecord::AGGREGATE:
|
||||
if(globalConsts)
|
||||
idx = (uint32_t)ConstantsAbbrev::Aggregate;
|
||||
break;
|
||||
case ConstantsRecord::STRING:
|
||||
if(globalConsts)
|
||||
idx = (uint32_t)ConstantsAbbrev::String;
|
||||
break;
|
||||
// these abbrevs are available in all constants blocks
|
||||
case ConstantsRecord::SETTYPE: idx = (uint32_t)ConstantsAbbrev::SetType; break;
|
||||
case ConstantsRecord::INTEGER: idx = (uint32_t)ConstantsAbbrev::Integer; break;
|
||||
case ConstantsRecord::EVAL_CAST:
|
||||
idx = (uint32_t)ConstantsAbbrev::EvalCast;
|
||||
break;
|
||||
// LLVM doesn't seem to use this abbrev?
|
||||
// case ConstantsRecord::CONST_NULL: idx = (uint32_t)ConstantsAbbrev::Null; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlock::TYPE_BLOCK:
|
||||
switch(TypeRecord(record))
|
||||
{
|
||||
@@ -493,17 +555,21 @@ void BitcodeWriter::AutoRecord(uint32_t record, bool param, uint64_t val)
|
||||
}
|
||||
|
||||
// if we got a valid abbrev, use it, otherwise emit unabbrev
|
||||
if(idx < numAbbrevDefs)
|
||||
Abbrev(abbrevs[idx], GetAbbrevID(record), val);
|
||||
if(idx < curAbbrevs.size())
|
||||
{
|
||||
// write the abbrev ID
|
||||
b.fixed(abbrevSize, GetAbbrevID(idx));
|
||||
|
||||
Abbrev(curAbbrevs[idx], record, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unabbrev(record, param, val);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
{
|
||||
AbbrevDefinition *abbrevs = GetAbbrevDefs(curBlock);
|
||||
uint32_t numAbbrevDefs = GetNumAbbrevDefs(curBlock);
|
||||
|
||||
uint32_t idx = ~0U;
|
||||
|
||||
// the records with abbrevs are hardcoded, so just determine if this record in this block has an
|
||||
@@ -528,6 +594,48 @@ void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case KnownBlock::CONSTANTS_BLOCK:
|
||||
{
|
||||
// blockStack[0] is always the module block
|
||||
const bool globalConsts = blockStack.size() == 2;
|
||||
switch(ConstantsRecord(record))
|
||||
{
|
||||
// global only abbrevs
|
||||
case ConstantsRecord::AGGREGATE:
|
||||
if(globalConsts)
|
||||
idx = (uint32_t)ConstantsAbbrev::Aggregate;
|
||||
break;
|
||||
case ConstantsRecord::STRING:
|
||||
if(globalConsts)
|
||||
idx = (uint32_t)ConstantsAbbrev::String;
|
||||
break;
|
||||
case ConstantsRecord::CSTRING:
|
||||
if(globalConsts)
|
||||
{
|
||||
bool c6 = true, c7 = true;
|
||||
for(size_t i = 0; (c6 || c7) && i < vals.size(); i++)
|
||||
{
|
||||
if(!isChar6(char(vals[i])))
|
||||
c6 = false;
|
||||
if(vals[i] >= 128)
|
||||
c7 = false;
|
||||
}
|
||||
|
||||
if(c6)
|
||||
idx = (uint32_t)ConstantsAbbrev::CString6;
|
||||
else if(c7)
|
||||
idx = (uint32_t)ConstantsAbbrev::CString7;
|
||||
}
|
||||
break;
|
||||
// these abbrevs are available in all constants blocks
|
||||
case ConstantsRecord::SETTYPE: idx = (uint32_t)ConstantsAbbrev::SetType; break;
|
||||
case ConstantsRecord::INTEGER: idx = (uint32_t)ConstantsAbbrev::Integer; break;
|
||||
case ConstantsRecord::EVAL_CAST: idx = (uint32_t)ConstantsAbbrev::EvalCast; break;
|
||||
case ConstantsRecord::CONST_NULL: idx = (uint32_t)ConstantsAbbrev::Null; break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KnownBlock::TYPE_BLOCK:
|
||||
switch(TypeRecord(record))
|
||||
{
|
||||
@@ -560,23 +668,16 @@ void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
}
|
||||
|
||||
// if we got a valid abbrev, use it, otherwise emit unabbrev
|
||||
if(idx == m_GlobalVarAbbrev && idx != ~0U)
|
||||
{
|
||||
// write the abbrev ID
|
||||
b.fixed(abbrevSize, GetAbbrevID(m_GlobalVarAbbrev));
|
||||
|
||||
Abbrev(m_GlobalVarAbbrevDef, record, vals);
|
||||
}
|
||||
else if(idx < numAbbrevDefs)
|
||||
if(idx < curAbbrevs.size())
|
||||
{
|
||||
// write the abbrev ID
|
||||
b.fixed(abbrevSize, GetAbbrevID(idx));
|
||||
|
||||
Abbrev(abbrevs[idx], record, vals);
|
||||
Abbrev(curAbbrevs[idx], record, vals);
|
||||
}
|
||||
else
|
||||
{
|
||||
Unabbrev(record, vals);
|
||||
Unabbrev(record, false, vals);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,9 +735,16 @@ void BitcodeWriter::WriteAbbrevParam(const AbbrevParam &abbrev, uint64_t val)
|
||||
return;
|
||||
|
||||
if(abbrev.encoding == AbbrevEncoding::Fixed)
|
||||
b.fixed(abbrev.value == MagicFixedSizeNumTypes ? m_NumTypeBits : abbrev.value, val);
|
||||
{
|
||||
uint64_t width = abbrev.value;
|
||||
if(abbrev.value == MagicFixedSizeNumTypes)
|
||||
width = m_NumTypeBits;
|
||||
else if(abbrev.value == MagicFixedSizeNumConstants)
|
||||
width = m_NumConstantBits;
|
||||
b.fixed((size_t)width, val);
|
||||
}
|
||||
else if(abbrev.encoding == AbbrevEncoding::VBR)
|
||||
b.vbr(abbrev.value, val);
|
||||
b.vbr((size_t)abbrev.value, val);
|
||||
else if(abbrev.encoding == AbbrevEncoding::Char6)
|
||||
b.c6(char(val));
|
||||
else
|
||||
@@ -652,7 +760,7 @@ void BitcodeWriter::Unabbrev(uint32_t record, bool param, uint64_t val)
|
||||
b.vbr(6, val);
|
||||
}
|
||||
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, bool, const rdcarray<uint64_t> &vals)
|
||||
{
|
||||
b.fixed(abbrevSize, UNABBREV_RECORD);
|
||||
b.vbr(6, record);
|
||||
|
||||
@@ -37,7 +37,8 @@ public:
|
||||
BitcodeWriter(bytebuf &buf);
|
||||
~BitcodeWriter();
|
||||
|
||||
void ConfigureSizes(size_t numTypes, size_t numSections, uint64_t maxAlign, uint32_t maxGlobalType);
|
||||
void ConfigureSizes(size_t numTypes, size_t numGlobalConsts, size_t numSections,
|
||||
uint64_t maxAlign, uint32_t maxGlobalType);
|
||||
|
||||
void BeginBlock(KnownBlock block);
|
||||
void EndBlock();
|
||||
@@ -77,7 +78,7 @@ private:
|
||||
void WriteAbbrevDefinition(AbbrevParam *abbrev);
|
||||
|
||||
void Unabbrev(uint32_t record, bool param, uint64_t val);
|
||||
void Unabbrev(uint32_t record, const rdcarray<uint64_t> &vals);
|
||||
void Unabbrev(uint32_t record, bool, const rdcarray<uint64_t> &vals);
|
||||
|
||||
void Abbrev(AbbrevParam *abbrev, uint32_t record, uint64_t val);
|
||||
void Abbrev(AbbrevParam *abbrev, uint32_t record, const rdcarray<uint64_t> &vals);
|
||||
@@ -89,12 +90,13 @@ private:
|
||||
BitWriter b;
|
||||
|
||||
uint32_t m_NumTypeBits;
|
||||
uint32_t m_NumConstantBits;
|
||||
uint32_t m_GlobalTypeBits;
|
||||
uint32_t m_NumSectionBits;
|
||||
uint32_t m_AlignBits;
|
||||
|
||||
size_t abbrevSize;
|
||||
uint32_t numAbbrevs;
|
||||
rdcarray<AbbrevParam *> curAbbrevs;
|
||||
KnownBlock curBlock;
|
||||
|
||||
uint32_t m_GlobalVarAbbrev;
|
||||
@@ -104,7 +106,7 @@ private:
|
||||
{
|
||||
KnownBlock block;
|
||||
size_t offset;
|
||||
uint32_t numAbbrevs;
|
||||
rdcarray<AbbrevParam *> abbrevs;
|
||||
};
|
||||
|
||||
rdcarray<BlockContext> blockStack;
|
||||
|
||||
Reference in New Issue
Block a user