Emit the global constants block in DXIL

This commit is contained in:
baldurk
2021-09-01 18:22:29 +01:00
parent f6e8e78bbf
commit a2a5d8ec8a
7 changed files with 417 additions and 104 deletions
+59 -37
View File
@@ -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");
}
}
+56 -2
View File
@@ -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 += " }";
}
+1 -1
View File
@@ -95,7 +95,7 @@ enum class ModuleRecord : uint32_t
SECTIONNAME = 5,
GLOBALVAR = 7,
FUNCTION = 8,
ALIAS = 14,
ALIAS = 9,
};
enum class ConstantsRecord : uint32_t
+148 -40
View File
@@ -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);
+6 -4
View File
@@ -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;