Emit metadata block

This commit is contained in:
baldurk
2021-09-21 18:04:57 +01:00
parent a2a5d8ec8a
commit 3ce8d68fba
8 changed files with 267 additions and 61 deletions
@@ -714,7 +714,7 @@ void DXBCContainer::ReplaceDXBCBytecode(bytebuf &ByteCode, const rdcarray<uint32
HashContainer(ByteCode.data(), ByteCode.size());
}
void DXBCContainer::ReplaceDXILBytecode(bytebuf &ByteCode, const bytebuf &replacement)
void DXBCContainer::StripDXILDebugInfo(bytebuf &ByteCode)
{
FileHeader *header = (FileHeader *)ByteCode.data();
@@ -736,15 +736,44 @@ void DXBCContainer::ReplaceDXILBytecode(bytebuf &ByteCode, const bytebuf &replac
if(*fourcc == FOURCC_ILDB)
{
uint32_t size = 8 + *chunkSize;
// strip ILDB because it's valid code (with debug info) and who knows what might use it
ByteCode.erase(offs, 8 + *chunkSize);
for(uint32_t c = chunkIdx; c < header->numChunks; c++)
chunkOffsets[c + 1] = chunkOffsets[c];
chunkOffsets[c] = chunkOffsets[c + 1] - size;
header->numChunks--;
header->fileLength -= size;
ByteCode.erase(offs, size);
break;
}
else if(*fourcc == FOURCC_DXIL)
}
HashContainer(ByteCode.data(), ByteCode.size());
}
void DXBCContainer::ReplaceDXILBytecode(bytebuf &ByteCode, const bytebuf &replacement)
{
FileHeader *header = (FileHeader *)ByteCode.data();
if(header->fourcc != FOURCC_DXBC)
return;
if(header->fileLength != (uint32_t)ByteCode.size())
return;
uint32_t *chunkOffsets =
(uint32_t *)(ByteCode.data() + sizeof(FileHeader)); // right after the header
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
{
uint32_t offs = chunkOffsets[chunkIdx];
uint32_t *fourcc = (uint32_t *)(ByteCode.data() + offs);
uint32_t *chunkSize = (uint32_t *)(fourcc + 1);
if(*fourcc == FOURCC_DXIL)
{
int32_t diff = int32_t(replacement.size()) - int32_t(*chunkSize);
@@ -164,6 +164,7 @@ public:
void FillStateInstructionInfo(ShaderDebugState &state) const;
static void ReplaceDXBCBytecode(bytebuf &ByteCode, const rdcarray<uint32_t> &replacement);
static void StripDXILDebugInfo(bytebuf &ByteCode);
static void ReplaceDXILBytecode(bytebuf &ByteCode, const bytebuf &replacement);
const DXBCBytecode::Program *GetDXBCByteCode() const { return m_DXBCByteCode; }
@@ -920,7 +920,7 @@ Program::Program(const byte *bytes, size_t length)
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.resize_for_index(kind);
m_Kinds[kind] = metaRecord.getString(1);
continue;
}
@@ -939,6 +939,7 @@ Program::Program(const byte *bytes, size_t length)
if(IS_KNOWN(metaRecord.id, MetaDataRecord::STRING_OLD))
{
meta.isConstant = true;
meta.isString = true;
meta.str = metaRecord.getString();
}
else if(IS_KNOWN(metaRecord.id, MetaDataRecord::VALUE))
@@ -480,7 +480,7 @@ struct Metadata
~Metadata();
uint32_t id = ~0U;
bool isDistinct = false, isConstant = false;
bool isDistinct = false, isConstant = false, isString = false;
const Constant *constant = NULL;
@@ -49,23 +49,43 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
LLVMBC::BitcodeWriter writer(ret);
uint64_t maxAlign = 0;
uint32_t maxGlobalType = 0;
LLVMBC::BitcodeWriter::Config cfg = {};
auto getTypeID = [this](const Type *t) { return uint64_t(t - m_Types.begin()); };
#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)
for(size_t i = 0; i < m_GlobalVars.size(); i++)
{
maxAlign = RDCMAX(m_GlobalVars[i].align, maxAlign);
cfg.maxAlign = RDCMAX(m_GlobalVars[i].align, cfg.maxAlign);
RDCASSERT(m_GlobalVars[i].type->type == Type::Pointer);
uint32_t typeIndex = uint32_t(getTypeID(m_GlobalVars[i].type->inner));
maxGlobalType = RDCMAX(typeIndex, maxGlobalType);
cfg.maxGlobalType = RDCMAX(typeIndex, cfg.maxGlobalType);
}
for(size_t i = 0; i < m_Functions.size(); i++)
maxAlign = RDCMAX(m_Functions[i].align, maxAlign);
cfg.maxAlign = RDCMAX(m_Functions[i].align, cfg.maxAlign);
size_t numGlobalConsts = 0;
for(size_t i = 0; i < m_Metadata.size(); i++)
{
if(m_Metadata[i].isString)
cfg.hasMetaString = true;
if(m_Metadata[i].debugLoc)
cfg.hasDebugLoc = true;
}
for(size_t i = 0; i < m_NamedMeta.size(); i++)
{
if(m_NamedMeta[i].isString)
cfg.hasMetaString = true;
if(m_NamedMeta[i].debugLoc)
cfg.hasDebugLoc = true;
}
cfg.hasNamedMeta = !m_NamedMeta.empty();
for(size_t i = m_GlobalVars.size() + m_Functions.size(); i < m_Symbols.size(); i++)
{
@@ -73,10 +93,13 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
if(m_Symbols[i].type != SymbolType::Constant)
break;
numGlobalConsts++;
cfg.numGlobalConsts++;
}
writer.ConfigureSizes(m_Types.size(), numGlobalConsts, m_Sections.size(), maxAlign, maxGlobalType);
cfg.numTypes = m_Types.size();
cfg.numSections = m_Sections.size();
writer.ConfigureSizes(cfg);
writer.BeginBlock(LLVMBC::KnownBlock::MODULE_BLOCK);
@@ -442,7 +465,7 @@ 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(c.members[m] - m_Constants.begin());
vals.push_back(getConstantID(c.members[m]));
}
writer.Record(LLVMBC::ConstantsRecord::EVAL_GEP, vals);
@@ -452,9 +475,9 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
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())});
writer.Record(
LLVMBC::ConstantsRecord::EVAL_CAST,
{EncodeCast(c.op), getTypeID(c.type), getTypeID(c.inner->type), getConstantID(c.inner)});
}
else if(c.type->scalarType == Type::Int)
{
@@ -501,7 +524,7 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
vals.reserve(c.members.size());
for(size_t m = 0; m < c.members.size(); m++)
vals.push_back(c.members[m] - m_Constants.begin());
vals.push_back(getConstantID(c.members[m]));
writer.Record(LLVMBC::ConstantsRecord::AGGREGATE, vals);
}
@@ -511,6 +534,91 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
writer.EndBlock();
}
if(!m_Metadata.empty())
{
writer.BeginBlock(LLVMBC::KnownBlock::METADATA_BLOCK);
writer.EmitMetaDataAbbrev();
rdcarray<uint64_t> vals;
bool errored = false;
for(size_t i = 0; i < m_Metadata.size(); i++)
{
if(m_Metadata[i].isString)
{
writer.Record(LLVMBC::MetaDataRecord::STRING_OLD, m_Metadata[i].str);
}
else if(m_Metadata[i].isConstant)
{
writer.Record(LLVMBC::MetaDataRecord::VALUE,
{getTypeID(m_Metadata[i].type), getConstantID(m_Metadata[i].constant)});
}
else if(m_Metadata[i].dwarf || m_Metadata[i].debugLoc)
{
if(!errored)
RDCERR("Unexpected debug metadata node - expect to only encode stripped DXIL chunks");
errored = true;
// replace this with the first NULL constant value
for(size_t c = 0; c < m_Constants.size(); c++)
{
if(m_Constants[c].nullconst)
{
writer.Record(LLVMBC::MetaDataRecord::VALUE,
{getTypeID(m_Constants[c].type), (uint64_t)c});
}
}
}
else
{
vals.clear();
for(size_t m = 0; m < m_Metadata[i].children.size(); m++)
vals.push_back(getMetaIDOrNull(m_Metadata[i].children[m]));
writer.Record(m_Metadata[i].isDistinct ? LLVMBC::MetaDataRecord::DISTINCT_NODE
: LLVMBC::MetaDataRecord::NODE,
vals);
}
}
for(size_t i = 0; i < m_NamedMeta.size(); i++)
{
writer.Record(LLVMBC::MetaDataRecord::NAME, m_NamedMeta[i].name);
vals.clear();
for(size_t m = 0; m < m_NamedMeta[i].children.size(); m++)
vals.push_back(getMetaID(m_NamedMeta[i].children[m]));
writer.Record(LLVMBC::MetaDataRecord::NAMED_NODE, vals);
}
writer.EndBlock();
}
if(!m_Kinds.empty())
{
writer.BeginBlock(LLVMBC::KnownBlock::METADATA_BLOCK);
rdcarray<uint64_t> vals;
for(size_t i = 0; i < m_Kinds.size(); i++)
{
if(m_Kinds[i].empty())
continue;
vals.clear();
vals.push_back(i);
for(char c : m_Kinds[i])
vals.push_back(c);
writer.Record(LLVMBC::MetaDataRecord::KIND, vals);
}
writer.EndBlock();
}
writer.EndBlock();
ProgramHeader header;
@@ -33,9 +33,9 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
{
LLVMBC::MetaDataRecord id = (LLVMBC::MetaDataRecord)metaRecord.id;
auto getNonNullMeta = [this](uint64_t id) { return &m_Metadata[size_t(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; };
#define getNonNullMeta(id) &m_Metadata[size_t(id)]
#define getMeta(id) (id ? &m_Metadata[size_t(id - 1)] : NULL)
#define getMetaString(id) (id ? &m_Metadata[size_t(id - 1)].str : NULL)
if(id == LLVMBC::MetaDataRecord::FILE)
{
+83 -29
View File
@@ -250,6 +250,28 @@ AbbrevDefinition TypeAbbrevDefs[] = {
},
};
enum class MetadataAbbrev
{
String,
DebugLocation,
Name,
};
AbbrevDefinition MetadataAbbrevDefs[] = {
// String
{
AbbLiteral(MetaDataRecord::STRING_OLD), AbbArray(), AbbFixed(8),
},
// DebugLocation
{
AbbLiteral(MetaDataRecord::LOCATION), AbbFixed(1), AbbVBR(6), AbbVBR(8), AbbVBR(6), AbbVBR(6),
},
// Name
{
AbbLiteral(MetaDataRecord::NAME), AbbArray(), AbbFixed(8),
},
};
static AbbrevDefinition *GetAbbrevDefs(KnownBlock block)
{
AbbrevDefinition *ret = NULL;
@@ -260,6 +282,7 @@ static AbbrevDefinition *GetAbbrevDefs(KnownBlock block)
case KnownBlock::CONSTANTS_BLOCK: ret = ConstantsAbbrevDefs; break;
case KnownBlock::FUNCTION_BLOCK: ret = FunctionAbbrevDefs; break;
case KnownBlock::TYPE_BLOCK: ret = TypeAbbrevDefs; break;
case KnownBlock::METADATA_BLOCK: ret = MetadataAbbrevDefs; break;
default: break;
}
@@ -276,6 +299,7 @@ static uint32_t GetNumAbbrevDefs(KnownBlock block)
case KnownBlock::CONSTANTS_BLOCK: ret = ARRAY_COUNT(ConstantsAbbrevDefs); break;
case KnownBlock::FUNCTION_BLOCK: ret = ARRAY_COUNT(FunctionAbbrevDefs); break;
case KnownBlock::TYPE_BLOCK: ret = ARRAY_COUNT(TypeAbbrevDefs); break;
case KnownBlock::METADATA_BLOCK: ret = ARRAY_COUNT(MetadataAbbrevDefs); break;
default: break;
}
@@ -288,8 +312,6 @@ BitcodeWriter::BitcodeWriter(bytebuf &buf) : b(buf)
curBlock = KnownBlock::Count;
abbrevSize = 2;
m_GlobalVarAbbrev = ~0U;
}
BitcodeWriter::~BitcodeWriter()
@@ -346,6 +368,11 @@ void BitcodeWriter::BeginBlock(KnownBlock block)
break;
}
case KnownBlock::METADATA_BLOCK:
{
// this is handled manually, only in the first global metadata block
break;
}
default:
{
uint32_t numAbbrevDefs = GetNumAbbrevDefs(block);
@@ -400,9 +427,9 @@ void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
AbbrevParam param = abbrev[p];
if(param.value == MagicFixedSizeNumTypes)
param.value = m_NumTypeBits;
param.value = m_Cfg.numTypes;
if(param.value == MagicFixedSizeNumConstants)
param.value = m_NumConstantBits;
param.value = m_Cfg.numGlobalConsts;
const bool lit = param.encoding == AbbrevEncoding::Literal;
b.fixed<bool>(1, lit);
@@ -419,27 +446,22 @@ void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
}
}
void BitcodeWriter::ConfigureSizes(size_t numTypes, size_t numGlobalConsts, size_t numSections,
uint64_t maxAlign, uint32_t maxGlobalType)
void BitcodeWriter::ConfigureSizes(Config cfg)
{
m_NumTypeBits = 32 - Bits::CountLeadingZeroes((uint32_t)numTypes);
m_NumConstantBits = 32 - Bits::CountLeadingZeroes((uint32_t)numGlobalConsts);
m_Cfg = cfg;
m_GlobalTypeBits = 32 - Bits::CountLeadingZeroes(maxGlobalType);
m_Cfg.numTypes = 32 - Bits::CountLeadingZeroes((uint32_t)m_Cfg.numTypes);
m_Cfg.numGlobalConsts = 32 - Bits::CountLeadingZeroes((uint32_t)m_Cfg.numGlobalConsts);
if(numSections == 0)
m_NumSectionBits = 0;
else
m_NumSectionBits = 32 - Bits::CountLeadingZeroes((uint32_t)numSections);
m_Cfg.maxGlobalType = 32 - Bits::CountLeadingZeroes(m_Cfg.maxGlobalType);
if(maxAlign == 0)
if(m_Cfg.numSections > 0)
m_Cfg.numSections = 32 - Bits::CountLeadingZeroes((uint32_t)m_Cfg.numSections);
if(m_Cfg.maxAlign > 0)
{
m_AlignBits = 0;
}
else
{
uint32_t encodedAlign = 32 - Bits::CountLeadingZeroes((uint32_t)maxAlign);
m_AlignBits = 32 - Bits::CountLeadingZeroes(encodedAlign);
uint32_t encodedAlign = 32 - Bits::CountLeadingZeroes((uint32_t)cfg.maxAlign);
m_Cfg.maxAlign = 32 - Bits::CountLeadingZeroes(encodedAlign);
}
}
@@ -468,16 +490,16 @@ void BitcodeWriter::EmitGlobalVarAbbrev()
{
m_GlobalVarAbbrev = (uint32_t)curAbbrevs.size();
AbbrevParam align = AbbFixed(m_AlignBits);
if(m_AlignBits == 0)
AbbrevParam align = AbbFixed(m_Cfg.maxAlign);
if(m_Cfg.maxAlign == 0)
align = AbbLiteral(0);
AbbrevParam section = AbbFixed(m_NumSectionBits);
if(m_NumSectionBits == 0)
AbbrevParam section = AbbFixed(m_Cfg.numSections);
if(m_Cfg.numSections == 0)
section = AbbLiteral(0);
m_GlobalVarAbbrevDef[0] = AbbLiteral(ModuleRecord::GLOBALVAR);
m_GlobalVarAbbrevDef[1] = AbbFixed(m_GlobalTypeBits);
m_GlobalVarAbbrevDef[1] = AbbFixed(m_Cfg.maxGlobalType);
m_GlobalVarAbbrevDef[2] = AbbVBR(6);
m_GlobalVarAbbrevDef[3] = AbbVBR(6);
m_GlobalVarAbbrevDef[4] = AbbFixed(5);
@@ -487,6 +509,28 @@ void BitcodeWriter::EmitGlobalVarAbbrev()
WriteAbbrevDefinition(m_GlobalVarAbbrevDef);
}
void BitcodeWriter::EmitMetaDataAbbrev()
{
// metadata only emits its abbrev if there are the relevant nodes
if(m_Cfg.hasMetaString)
{
m_MetaStringAbbrev = (uint32_t)curAbbrevs.size();
WriteAbbrevDefinition(MetadataAbbrevDefs[(uint32_t)MetadataAbbrev::String]);
}
if(m_Cfg.hasDebugLoc)
{
m_MetaLocationAbbrev = (uint32_t)curAbbrevs.size();
WriteAbbrevDefinition(MetadataAbbrevDefs[(uint32_t)MetadataAbbrev::DebugLocation]);
}
if(m_Cfg.hasNamedMeta)
{
m_MetaNameAbbrev = (uint32_t)curAbbrevs.size();
WriteAbbrevDefinition(MetadataAbbrevDefs[(uint32_t)MetadataAbbrev::Name]);
}
// we don't handle GENERIC_DEBUG
}
uint32_t BitcodeWriter::GetAbbrevID(uint32_t id)
{
// the id is a block-local index, starting from 0, of the abbrevs defined for that block.
@@ -664,6 +708,14 @@ void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
default: break;
}
break;
case KnownBlock::METADATA_BLOCK:
switch(MetaDataRecord(record))
{
case MetaDataRecord::STRING_OLD: idx = (uint32_t)m_MetaStringAbbrev; break;
case MetaDataRecord::LOCATION: idx = (uint32_t)m_MetaLocationAbbrev; break;
case MetaDataRecord::NAME: idx = (uint32_t)m_MetaNameAbbrev; break;
default: break;
}
default: break;
}
@@ -697,8 +749,6 @@ void BitcodeWriter::Abbrev(AbbrevParam *abbr, uint32_t record, const rdcarray<ui
abbr++;
while(abbr->encoding != AbbrevEncoding::Unknown)
{
RDCASSERT(i < vals.size());
// only one array per abbrev, consume the rest of the vals
if(abbr->encoding == AbbrevEncoding::Array)
{
@@ -715,6 +765,8 @@ void BitcodeWriter::Abbrev(AbbrevParam *abbr, uint32_t record, const rdcarray<ui
}
else if(abbr->encoding == AbbrevEncoding::Blob)
{
RDCASSERT(i < vals.size());
// expect vals to be length then blob pointer packed into uint64_t
size_t length = (size_t)vals[i];
byte *blob = (byte *)vals[i + 1];
@@ -722,6 +774,8 @@ void BitcodeWriter::Abbrev(AbbrevParam *abbr, uint32_t record, const rdcarray<ui
}
else
{
RDCASSERT(i < vals.size());
WriteAbbrevParam(abbr[0], vals[i++]);
abbr++;
}
@@ -738,9 +792,9 @@ void BitcodeWriter::WriteAbbrevParam(const AbbrevParam &abbrev, uint64_t val)
{
uint64_t width = abbrev.value;
if(abbrev.value == MagicFixedSizeNumTypes)
width = m_NumTypeBits;
width = m_Cfg.numTypes;
else if(abbrev.value == MagicFixedSizeNumConstants)
width = m_NumConstantBits;
width = m_Cfg.numGlobalConsts;
b.fixed((size_t)width, val);
}
else if(abbrev.encoding == AbbrevEncoding::VBR)
+21 -8
View File
@@ -37,14 +37,27 @@ public:
BitcodeWriter(bytebuf &buf);
~BitcodeWriter();
void ConfigureSizes(size_t numTypes, size_t numGlobalConsts, size_t numSections,
uint64_t maxAlign, uint32_t maxGlobalType);
struct Config
{
size_t numTypes;
size_t numGlobalConsts;
size_t numSections;
uint64_t maxAlign;
uint32_t maxGlobalType;
bool hasMetaString;
bool hasDebugLoc;
bool hasNamedMeta;
};
void ConfigureSizes(Config cfg);
void BeginBlock(KnownBlock block);
void EndBlock();
void ModuleBlockInfo();
void EmitGlobalVarAbbrev();
void EmitMetaDataAbbrev();
void AutoRecord(uint32_t record, bool param, uint64_t val);
void AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals);
@@ -89,17 +102,17 @@ private:
BitWriter b;
uint32_t m_NumTypeBits;
uint32_t m_NumConstantBits;
uint32_t m_GlobalTypeBits;
uint32_t m_NumSectionBits;
uint32_t m_AlignBits;
Config m_Cfg;
size_t abbrevSize;
rdcarray<AbbrevParam *> curAbbrevs;
KnownBlock curBlock;
uint32_t m_GlobalVarAbbrev;
uint32_t m_GlobalVarAbbrev = ~0U;
uint32_t m_MetaStringAbbrev = ~0U;
uint32_t m_MetaLocationAbbrev = ~0U;
uint32_t m_MetaNameAbbrev = ~0U;
AbbrevParam m_GlobalVarAbbrevDef[10] = {};
struct BlockContext