mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-22 05:35:48 +00:00
Emit global var and function records in module
* The value IDs currently aren't fetched in LLVM-matching order so we don't have those yet for global var initialisers
This commit is contained in:
@@ -123,6 +123,12 @@ struct Symbol
|
||||
Symbol(SymbolType type = SymbolType::Unknown, uint64_t idx = 0) : type(type), idx(idx) {}
|
||||
SymbolType type;
|
||||
uint64_t idx;
|
||||
bool operator<(const Symbol &o) const
|
||||
{
|
||||
if(type != o.type)
|
||||
return type < o.type;
|
||||
return idx < o.idx;
|
||||
}
|
||||
};
|
||||
|
||||
enum class GlobalFlags : uint32_t
|
||||
@@ -163,6 +169,8 @@ struct GlobalVar
|
||||
struct Alias
|
||||
{
|
||||
rdcstr name;
|
||||
const Type *type = NULL;
|
||||
uint64_t valID = 0;
|
||||
};
|
||||
|
||||
// this enum is ordered to match the serialised order of these attributes
|
||||
|
||||
@@ -44,14 +44,32 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
{
|
||||
bytebuf ret;
|
||||
|
||||
std::map<Symbol, uint32_t> valueId;
|
||||
|
||||
LLVMBC::BitcodeWriter writer(ret);
|
||||
|
||||
uint64_t maxAlign = 0;
|
||||
uint32_t maxGlobalType = 0;
|
||||
|
||||
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());
|
||||
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);
|
||||
|
||||
writer.BeginBlock(LLVMBC::KnownBlock::MODULE_BLOCK);
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::VERSION, 1U);
|
||||
|
||||
{
|
||||
writer.ModuleBlockInfo((uint32_t)m_Types.size());
|
||||
writer.ModuleBlockInfo();
|
||||
}
|
||||
|
||||
if(!m_AttributeGroups.empty())
|
||||
@@ -245,6 +263,127 @@ bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
writer.EndBlock();
|
||||
}
|
||||
|
||||
// COMDAT would be next, but we don't read these (DXIL seems not to use them...?)
|
||||
|
||||
if(!m_Triple.empty())
|
||||
writer.Record(LLVMBC::ModuleRecord::TRIPLE, m_Triple);
|
||||
|
||||
if(!m_Datalayout.empty())
|
||||
writer.Record(LLVMBC::ModuleRecord::DATALAYOUT, m_Datalayout);
|
||||
|
||||
// inline asm would go here
|
||||
|
||||
// write the sections
|
||||
for(size_t i = 0; i < m_Sections.size(); i++)
|
||||
writer.Record(LLVMBC::ModuleRecord::SECTIONNAME, m_Sections[i]);
|
||||
|
||||
if(!m_GlobalVars.empty())
|
||||
writer.EmitGlobalVarAbbrev();
|
||||
|
||||
for(size_t i = 0; i < m_GlobalVars.size(); i++)
|
||||
{
|
||||
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 linkageValue = 0;
|
||||
|
||||
switch(g.flags & GlobalFlags::LinkageMask)
|
||||
{
|
||||
case GlobalFlags::ExternalLinkage: linkageValue = 0; break;
|
||||
case GlobalFlags::WeakAnyLinkage: linkageValue = 16; break;
|
||||
case GlobalFlags::AppendingLinkage: linkageValue = 2; break;
|
||||
case GlobalFlags::InternalLinkage: linkageValue = 3; break;
|
||||
case GlobalFlags::LinkOnceAnyLinkage: linkageValue = 18; break;
|
||||
case GlobalFlags::ExternalWeakLinkage: linkageValue = 7; break;
|
||||
case GlobalFlags::CommonLinkage: linkageValue = 8; break;
|
||||
case GlobalFlags::PrivateLinkage: linkageValue = 9; break;
|
||||
case GlobalFlags::WeakODRLinkage: linkageValue = 17; break;
|
||||
case GlobalFlags::LinkOnceODRLinkage: linkageValue = 19; break;
|
||||
case GlobalFlags::AvailableExternallyLinkage: linkageValue = 12; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
uint64_t unnamedAddr = 0;
|
||||
|
||||
if(g.flags & GlobalFlags::GlobalUnnamedAddr)
|
||||
unnamedAddr = 1;
|
||||
else if(g.flags & GlobalFlags::LocalUnnamedAddr)
|
||||
unnamedAddr = 2;
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::GLOBALVAR,
|
||||
{
|
||||
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),
|
||||
// visibility
|
||||
0U,
|
||||
// TLS mode
|
||||
0U,
|
||||
// unnamed addr
|
||||
unnamedAddr, (g.flags & GlobalFlags::ExternallyInitialised) ? 1U : 0U,
|
||||
// DLL storage class
|
||||
0U,
|
||||
// comdat
|
||||
0U,
|
||||
});
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = m_Functions[i];
|
||||
size_t typeIndex = f.funcType - m_Types.begin();
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::FUNCTION,
|
||||
{
|
||||
typeIndex,
|
||||
// calling convention
|
||||
0U,
|
||||
// external/declaration
|
||||
f.external ? 1U : 0U,
|
||||
// linkage
|
||||
0U,
|
||||
// attributes
|
||||
uint64_t(f.attrs ? 1U + (f.attrs - m_Attributes.begin()) : 0U),
|
||||
// alignment
|
||||
f.align,
|
||||
// section
|
||||
0U,
|
||||
// visibility
|
||||
0U,
|
||||
// gc
|
||||
0U,
|
||||
// unnamed_addr
|
||||
0U,
|
||||
// prologuedata
|
||||
0U,
|
||||
// dllstorageclass
|
||||
0U,
|
||||
// comdat
|
||||
0U,
|
||||
// prefixdata
|
||||
0U,
|
||||
// personality
|
||||
0U,
|
||||
});
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < m_Aliases.size(); i++)
|
||||
{
|
||||
const Alias &a = m_Aliases[i];
|
||||
size_t typeIndex = a.type - m_Types.begin();
|
||||
|
||||
writer.Record(LLVMBC::ModuleRecord::ALIAS, {
|
||||
typeIndex, a.valID,
|
||||
// linkage
|
||||
0U,
|
||||
// visibility
|
||||
0U,
|
||||
});
|
||||
}
|
||||
|
||||
writer.EndBlock();
|
||||
|
||||
ProgramHeader header;
|
||||
|
||||
@@ -262,6 +262,10 @@ BitcodeWriter::BitcodeWriter(bytebuf &buf) : b(buf)
|
||||
|
||||
curBlock = KnownBlock::Count;
|
||||
abbrevSize = 2;
|
||||
|
||||
numAbbrevs = 0;
|
||||
|
||||
m_GlobalVarAbbrev = ~0U;
|
||||
}
|
||||
|
||||
BitcodeWriter::~BitcodeWriter()
|
||||
@@ -373,10 +377,31 @@ void BitcodeWriter::WriteAbbrevDefinition(AbbrevParam *abbrev)
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::ModuleBlockInfo(uint32_t numTypes)
|
||||
void BitcodeWriter::ConfigureSizes(size_t numTypes, size_t numSections, uint64_t maxAlign,
|
||||
uint32_t maxGlobalType)
|
||||
{
|
||||
m_NumTypeBits = 32 - Bits::CountLeadingZeroes(numTypes);
|
||||
m_NumTypeBits = 32 - Bits::CountLeadingZeroes((uint32_t)numTypes);
|
||||
|
||||
m_GlobalTypeBits = 32 - Bits::CountLeadingZeroes(maxGlobalType);
|
||||
|
||||
if(numSections == 0)
|
||||
m_NumSectionBits = 0;
|
||||
else
|
||||
m_NumSectionBits = 32 - Bits::CountLeadingZeroes((uint32_t)numSections);
|
||||
|
||||
if(maxAlign == 0)
|
||||
{
|
||||
m_AlignBits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t encodedAlign = 32 - Bits::CountLeadingZeroes((uint32_t)maxAlign);
|
||||
m_AlignBits = 32 - Bits::CountLeadingZeroes(encodedAlign);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::ModuleBlockInfo()
|
||||
{
|
||||
// these abbrevs are hardcoded in llvm, at least at dxc's version
|
||||
BeginBlock(KnownBlock::BLOCKINFO);
|
||||
|
||||
@@ -396,6 +421,29 @@ void BitcodeWriter::ModuleBlockInfo(uint32_t numTypes)
|
||||
EndBlock();
|
||||
}
|
||||
|
||||
void BitcodeWriter::EmitGlobalVarAbbrev()
|
||||
{
|
||||
m_GlobalVarAbbrev = numAbbrevs;
|
||||
|
||||
AbbrevParam align = AbbFixed(m_AlignBits);
|
||||
if(m_AlignBits == 0)
|
||||
align = AbbLiteral(0);
|
||||
|
||||
AbbrevParam section = AbbFixed(m_NumSectionBits);
|
||||
if(m_NumSectionBits == 0)
|
||||
section = AbbLiteral(0);
|
||||
|
||||
m_GlobalVarAbbrevDef[0] = AbbLiteral(ModuleRecord::GLOBALVAR);
|
||||
m_GlobalVarAbbrevDef[1] = AbbFixed(m_GlobalTypeBits);
|
||||
m_GlobalVarAbbrevDef[2] = AbbVBR(6);
|
||||
m_GlobalVarAbbrevDef[3] = AbbVBR(6);
|
||||
m_GlobalVarAbbrevDef[4] = AbbFixed(5);
|
||||
m_GlobalVarAbbrevDef[5] = align;
|
||||
m_GlobalVarAbbrevDef[6] = section;
|
||||
|
||||
WriteAbbrevDefinition(m_GlobalVarAbbrevDef);
|
||||
}
|
||||
|
||||
uint32_t BitcodeWriter::GetAbbrevID(uint32_t id)
|
||||
{
|
||||
// the id is a block-local index, starting from 0, of the abbrevs defined for that block.
|
||||
@@ -422,6 +470,13 @@ void BitcodeWriter::AutoRecord(uint32_t record, bool param, uint64_t val)
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK:
|
||||
RDCERR("Symbol table entry needs multiple parameters");
|
||||
break;
|
||||
case KnownBlock::MODULE_BLOCK:
|
||||
switch(ModuleRecord(record))
|
||||
{
|
||||
case ModuleRecord::GLOBALVAR: RDCERR("global var needs multiple parameters"); break;
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case KnownBlock::TYPE_BLOCK:
|
||||
switch(TypeRecord(record))
|
||||
{
|
||||
@@ -458,6 +513,21 @@ void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK:
|
||||
// the selection of abbrev here depends on the data
|
||||
break;
|
||||
case KnownBlock::MODULE_BLOCK:
|
||||
switch(ModuleRecord(record))
|
||||
{
|
||||
case ModuleRecord::GLOBALVAR:
|
||||
{
|
||||
idx = m_GlobalVarAbbrev;
|
||||
// if any of the later values are non-zero, can't use the global var abbrev
|
||||
for(size_t i = 6; i < vals.size(); i++)
|
||||
if(vals[i] != 0)
|
||||
idx = ~0U;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
case KnownBlock::TYPE_BLOCK:
|
||||
switch(TypeRecord(record))
|
||||
{
|
||||
@@ -490,7 +560,14 @@ void BitcodeWriter::AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
}
|
||||
|
||||
// if we got a valid abbrev, use it, otherwise emit unabbrev
|
||||
if(idx < numAbbrevDefs)
|
||||
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)
|
||||
{
|
||||
// write the abbrev ID
|
||||
b.fixed(abbrevSize, GetAbbrevID(idx));
|
||||
|
||||
@@ -37,11 +37,13 @@ public:
|
||||
BitcodeWriter(bytebuf &buf);
|
||||
~BitcodeWriter();
|
||||
|
||||
void BeginBlock(KnownBlock block);
|
||||
void ConfigureSizes(size_t numTypes, size_t numSections, uint64_t maxAlign, uint32_t maxGlobalType);
|
||||
|
||||
void BeginBlock(KnownBlock block);
|
||||
void EndBlock();
|
||||
|
||||
void ModuleBlockInfo(uint32_t numTypes);
|
||||
void ModuleBlockInfo();
|
||||
void EmitGlobalVarAbbrev();
|
||||
|
||||
void AutoRecord(uint32_t record, bool param, uint64_t val);
|
||||
void AutoRecord(uint32_t record, const rdcarray<uint64_t> &vals);
|
||||
@@ -87,11 +89,17 @@ private:
|
||||
BitWriter b;
|
||||
|
||||
uint32_t m_NumTypeBits;
|
||||
uint32_t m_GlobalTypeBits;
|
||||
uint32_t m_NumSectionBits;
|
||||
uint32_t m_AlignBits;
|
||||
|
||||
size_t abbrevSize;
|
||||
uint32_t numAbbrevs;
|
||||
KnownBlock curBlock;
|
||||
|
||||
uint32_t m_GlobalVarAbbrev;
|
||||
AbbrevParam m_GlobalVarAbbrevDef[10] = {};
|
||||
|
||||
struct BlockContext
|
||||
{
|
||||
KnownBlock block;
|
||||
|
||||
Reference in New Issue
Block a user