mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Emit root module block and blockinfo subblock
* It looks like LLVM (at DXC's version anyway) hardcodes a series of abbreviations, so we do the same
This commit is contained in:
@@ -29,12 +29,15 @@
|
||||
#include "common/common.h"
|
||||
#include "common/formatting.h"
|
||||
#include "os/os_specific.h"
|
||||
#include "llvm_common.h"
|
||||
#include "llvm_decoder.h"
|
||||
|
||||
#define IS_KNOWN(val, KnownID) (decltype(KnownID)(val) == KnownID)
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
using namespace LLVMBC;
|
||||
|
||||
void ParseConstant(const LLVMBC::BlockOrRecord &constant, const Type *&curType,
|
||||
std::function<const Type *(uint64_t)> getType,
|
||||
std::function<const Type *(const Type *, Type::PointerAddrSpace)> getPtrType,
|
||||
@@ -302,7 +305,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
LLVMBC::BlockOrRecord root = reader.ReadToplevelBlock();
|
||||
|
||||
// the top-level block should be MODULE_BLOCK
|
||||
RDCASSERT(KnownBlocks(root.id) == KnownBlocks::MODULE_BLOCK);
|
||||
RDCASSERT(KnownBlock(root.id) == KnownBlock::MODULE_BLOCK);
|
||||
|
||||
// we should have consumed all bits, only one top-level block
|
||||
RDCASSERT(reader.AtEndOfStream());
|
||||
@@ -497,11 +500,11 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
else if(rootchild.IsBlock())
|
||||
{
|
||||
if(IS_KNOWN(rootchild.id, KnownBlocks::BLOCKINFO))
|
||||
if(IS_KNOWN(rootchild.id, KnownBlock::BLOCKINFO))
|
||||
{
|
||||
// do nothing, this is internal parse data
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::PARAMATTR_GROUP_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::PARAMATTR_GROUP_BLOCK))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord &attrgroup : rootchild.children)
|
||||
{
|
||||
@@ -562,7 +565,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
m_AttributeGroups[id] = group;
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::PARAMATTR_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::PARAMATTR_BLOCK))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord ¶mattr : rootchild.children)
|
||||
{
|
||||
@@ -602,7 +605,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
m_Attributes.push_back(attrs);
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::TYPE_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::TYPE_BLOCK))
|
||||
{
|
||||
rdcstr structname;
|
||||
|
||||
@@ -763,7 +766,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::CONSTANTS_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::CONSTANTS_BLOCK))
|
||||
{
|
||||
const Type *t = NULL;
|
||||
m_Constants.reserve(m_Constants.size() + rootchild.children.size());
|
||||
@@ -820,7 +823,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::VALUE_SYMTAB_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::VALUE_SYMTAB_BLOCK))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord &symtab : rootchild.children)
|
||||
{
|
||||
@@ -868,7 +871,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::METADATA_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::METADATA_BLOCK))
|
||||
{
|
||||
m_Metadata.reserve(rootchild.children.size());
|
||||
for(size_t i = 0; i < rootchild.children.size(); i++)
|
||||
@@ -945,7 +948,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlocks::FUNCTION_BLOCK))
|
||||
else if(IS_KNOWN(rootchild.id, KnownBlock::FUNCTION_BLOCK))
|
||||
{
|
||||
Function &f = m_Functions[functionDecls[0]];
|
||||
functionDecls.erase(0);
|
||||
@@ -980,7 +983,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
{
|
||||
if(funcChild.IsBlock())
|
||||
{
|
||||
if(IS_KNOWN(funcChild.id, KnownBlocks::CONSTANTS_BLOCK))
|
||||
if(IS_KNOWN(funcChild.id, KnownBlock::CONSTANTS_BLOCK))
|
||||
{
|
||||
f.constants.reserve(funcChild.children.size());
|
||||
|
||||
@@ -1030,7 +1033,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
|
||||
instrSymbolStart = m_Symbols.size();
|
||||
}
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlocks::METADATA_BLOCK))
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlock::METADATA_BLOCK))
|
||||
{
|
||||
f.metadata.resize(funcChild.children.size());
|
||||
|
||||
@@ -1080,7 +1083,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
m++;
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlocks::VALUE_SYMTAB_BLOCK))
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlock::VALUE_SYMTAB_BLOCK))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord &symtab : funcChild.children)
|
||||
{
|
||||
@@ -1141,7 +1144,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlocks::METADATA_ATTACHMENT))
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlock::METADATA_ATTACHMENT))
|
||||
{
|
||||
for(const LLVMBC::BlockOrRecord &meta : funcChild.children)
|
||||
{
|
||||
@@ -1173,7 +1176,7 @@ Program::Program(const byte *bytes, size_t length)
|
||||
f.instructions[(size_t)meta.ops[0]].attachedMeta.swap(attach);
|
||||
}
|
||||
}
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlocks::USELIST_BLOCK))
|
||||
else if(IS_KNOWN(funcChild.id, KnownBlock::USELIST_BLOCK))
|
||||
{
|
||||
RDCDEBUG("Ignoring uselist block");
|
||||
}
|
||||
|
||||
@@ -31,12 +31,6 @@
|
||||
#include "driver/dx/official/d3dcommon.h"
|
||||
#include "driver/shaders/dxbc/dxbc_common.h"
|
||||
|
||||
// undef some annoying defines that might come from OS headers
|
||||
#undef VOID
|
||||
#undef FLOAT
|
||||
#undef LABEL
|
||||
#undef OPAQUE
|
||||
|
||||
namespace LLVMBC
|
||||
{
|
||||
struct BlockOrRecord;
|
||||
@@ -55,179 +49,6 @@ struct ProgramHeader
|
||||
uint32_t BitcodeSize; // Size of LLVM bitcode.
|
||||
};
|
||||
|
||||
enum class KnownBlocks : uint32_t
|
||||
{
|
||||
BLOCKINFO = 0,
|
||||
|
||||
// 1-7 reserved,
|
||||
|
||||
MODULE_BLOCK = 8,
|
||||
PARAMATTR_BLOCK = 9,
|
||||
PARAMATTR_GROUP_BLOCK = 10,
|
||||
CONSTANTS_BLOCK = 11,
|
||||
FUNCTION_BLOCK = 12,
|
||||
TYPE_SYMTAB_BLOCK = 13,
|
||||
VALUE_SYMTAB_BLOCK = 14,
|
||||
METADATA_BLOCK = 15,
|
||||
METADATA_ATTACHMENT = 16,
|
||||
TYPE_BLOCK = 17,
|
||||
USELIST_BLOCK = 18,
|
||||
};
|
||||
|
||||
enum class ModuleRecord : uint32_t
|
||||
{
|
||||
VERSION = 1,
|
||||
TRIPLE = 2,
|
||||
DATALAYOUT = 3,
|
||||
SECTIONNAME = 5,
|
||||
GLOBALVAR = 7,
|
||||
FUNCTION = 8,
|
||||
ALIAS = 14,
|
||||
};
|
||||
|
||||
enum class ConstantsRecord : uint32_t
|
||||
{
|
||||
SETTYPE = 1,
|
||||
CONST_NULL = 2,
|
||||
UNDEF = 3,
|
||||
INTEGER = 4,
|
||||
FLOAT = 6,
|
||||
AGGREGATE = 7,
|
||||
STRING = 8,
|
||||
CSTRING = 9,
|
||||
EVAL_CAST = 11,
|
||||
EVAL_GEP = 20,
|
||||
DATA = 22,
|
||||
};
|
||||
|
||||
enum class FunctionRecord : uint32_t
|
||||
{
|
||||
DECLAREBLOCKS = 1,
|
||||
INST_BINOP = 2,
|
||||
INST_CAST = 3,
|
||||
INST_GEP_OLD = 4,
|
||||
INST_SELECT = 5,
|
||||
INST_EXTRACTELT = 6,
|
||||
INST_INSERTELT = 7,
|
||||
INST_SHUFFLEVEC = 8,
|
||||
INST_CMP = 9,
|
||||
INST_RET = 10,
|
||||
INST_BR = 11,
|
||||
INST_SWITCH = 12,
|
||||
INST_INVOKE = 13,
|
||||
INST_UNREACHABLE = 15,
|
||||
INST_PHI = 16,
|
||||
INST_ALLOCA = 19,
|
||||
INST_LOAD = 20,
|
||||
INST_VAARG = 23,
|
||||
INST_STORE_OLD = 24,
|
||||
INST_EXTRACTVAL = 26,
|
||||
INST_INSERTVAL = 27,
|
||||
INST_CMP2 = 28,
|
||||
INST_VSELECT = 29,
|
||||
INST_INBOUNDS_GEP_OLD = 30,
|
||||
INST_INDIRECTBR = 31,
|
||||
DEBUG_LOC_AGAIN = 33,
|
||||
INST_CALL = 34,
|
||||
DEBUG_LOC = 35,
|
||||
INST_FENCE = 36,
|
||||
INST_CMPXCHG_OLD = 37,
|
||||
INST_ATOMICRMW = 38,
|
||||
INST_RESUME = 39,
|
||||
INST_LANDINGPAD_OLD = 40,
|
||||
INST_LOADATOMIC = 41,
|
||||
INST_STOREATOMIC_OLD = 42,
|
||||
INST_GEP = 43,
|
||||
INST_STORE = 44,
|
||||
INST_STOREATOMIC = 45,
|
||||
INST_CMPXCHG = 46,
|
||||
INST_LANDINGPAD = 47,
|
||||
};
|
||||
|
||||
enum class ParamAttrRecord : uint32_t
|
||||
{
|
||||
ENTRY = 2,
|
||||
};
|
||||
|
||||
enum class ParamAttrGroupRecord : uint32_t
|
||||
{
|
||||
ENTRY = 3,
|
||||
};
|
||||
|
||||
enum class ValueSymtabRecord : uint32_t
|
||||
{
|
||||
ENTRY = 1,
|
||||
BBENTRY = 2,
|
||||
FNENTRY = 3,
|
||||
COMBINED_ENTRY = 5,
|
||||
};
|
||||
|
||||
enum class MetaDataRecord : uint32_t
|
||||
{
|
||||
STRING_OLD = 1,
|
||||
VALUE = 2,
|
||||
NODE = 3,
|
||||
NAME = 4,
|
||||
DISTINCT_NODE = 5,
|
||||
KIND = 6,
|
||||
LOCATION = 7,
|
||||
OLD_NODE = 8,
|
||||
OLD_FN_NODE = 9,
|
||||
NAMED_NODE = 10,
|
||||
ATTACHMENT = 11,
|
||||
GENERIC_DEBUG = 12,
|
||||
SUBRANGE = 13,
|
||||
ENUMERATOR = 14,
|
||||
BASIC_TYPE = 15,
|
||||
FILE = 16,
|
||||
DERIVED_TYPE = 17,
|
||||
COMPOSITE_TYPE = 18,
|
||||
SUBROUTINE_TYPE = 19,
|
||||
COMPILE_UNIT = 20,
|
||||
SUBPROGRAM = 21,
|
||||
LEXICAL_BLOCK = 22,
|
||||
LEXICAL_BLOCK_FILE = 23,
|
||||
NAMESPACE = 24,
|
||||
TEMPLATE_TYPE = 25,
|
||||
TEMPLATE_VALUE = 26,
|
||||
GLOBAL_VAR = 27,
|
||||
LOCAL_VAR = 28,
|
||||
EXPRESSION = 29,
|
||||
OBJC_PROPERTY = 30,
|
||||
IMPORTED_ENTITY = 31,
|
||||
MODULE = 32,
|
||||
MACRO = 33,
|
||||
MACRO_FILE = 34,
|
||||
STRINGS = 35,
|
||||
GLOBAL_DECL_ATTACHMENT = 36,
|
||||
GLOBAL_VAR_EXPR = 37,
|
||||
INDEX_OFFSET = 38,
|
||||
INDEX = 39,
|
||||
LABEL = 40,
|
||||
COMMON_BLOCK = 44,
|
||||
};
|
||||
|
||||
enum class TypeRecord : uint32_t
|
||||
{
|
||||
NUMENTRY = 1,
|
||||
VOID = 2,
|
||||
FLOAT = 3,
|
||||
DOUBLE = 4,
|
||||
LABEL = 5,
|
||||
OPAQUE = 6,
|
||||
INTEGER = 7,
|
||||
POINTER = 8,
|
||||
FUNCTION_OLD = 9,
|
||||
HALF = 10,
|
||||
ARRAY = 11,
|
||||
VECTOR = 12,
|
||||
METADATA = 16,
|
||||
STRUCT_ANON = 18,
|
||||
STRUCT_NAME = 19,
|
||||
STRUCT_NAMED = 20,
|
||||
FUNCTION = 21,
|
||||
};
|
||||
|
||||
struct Type
|
||||
{
|
||||
enum TypeKind
|
||||
|
||||
@@ -40,12 +40,20 @@ DXIL::ProgramEditor::~ProgramEditor()
|
||||
DXBC::DXBCContainer::ReplaceDXILBytecode(m_OutBlob, EncodeProgram());
|
||||
}
|
||||
|
||||
bytebuf DXIL::ProgramEditor::EncodeProgram()
|
||||
bytebuf DXIL::ProgramEditor::EncodeProgram() const
|
||||
{
|
||||
bytebuf ret;
|
||||
|
||||
LLVMBC::BitcodeWriter writer(ret);
|
||||
|
||||
writer.BeginBlock(LLVMBC::KnownBlock::MODULE_BLOCK);
|
||||
|
||||
writer.Unabbrev((uint32_t)LLVMBC::ModuleRecord::VERSION, 1U);
|
||||
|
||||
writer.ModuleBlockInfo((uint32_t)m_Types.size());
|
||||
|
||||
writer.EndBlock();
|
||||
|
||||
ProgramHeader header;
|
||||
|
||||
header.ProgramVersion = ((m_Major & 0xf) << 4) | (m_Minor & 0xf);
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
private:
|
||||
bytebuf &m_OutBlob;
|
||||
|
||||
bytebuf EncodeProgram();
|
||||
bytebuf EncodeProgram() const;
|
||||
};
|
||||
|
||||
}; // namespace DXIL
|
||||
|
||||
@@ -24,26 +24,27 @@
|
||||
|
||||
#include "dxil_debuginfo.h"
|
||||
#include "common/formatting.h"
|
||||
#include "llvm_common.h"
|
||||
#include "llvm_decoder.h"
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta)
|
||||
{
|
||||
MetaDataRecord id = (MetaDataRecord)metaRecord.id;
|
||||
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; };
|
||||
|
||||
if(id == MetaDataRecord::FILE)
|
||||
if(id == LLVMBC::MetaDataRecord::FILE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DIFile(getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2]));
|
||||
meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == MetaDataRecord::COMPILE_UNIT)
|
||||
else if(id == LLVMBC::MetaDataRecord::COMPILE_UNIT)
|
||||
{
|
||||
// should be at least 14 parameters
|
||||
RDCASSERT(metaRecord.ops.size() >= 14);
|
||||
@@ -62,7 +63,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
getMeta(metaRecord.ops[10]), getMeta(metaRecord.ops[11]),
|
||||
getMeta(metaRecord.ops[12]), getMeta(metaRecord.ops[13])};
|
||||
}
|
||||
else if(id == MetaDataRecord::BASIC_TYPE)
|
||||
else if(id == LLVMBC::MetaDataRecord::BASIC_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -70,7 +71,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
new DIBasicType(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
metaRecord.ops[3], metaRecord.ops[4], DW_ENCODING(metaRecord.ops[5]));
|
||||
}
|
||||
else if(id == MetaDataRecord::DERIVED_TYPE)
|
||||
else if(id == LLVMBC::MetaDataRecord::DERIVED_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -83,7 +84,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[5]),
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11])};
|
||||
}
|
||||
else if(id == MetaDataRecord::COMPOSITE_TYPE)
|
||||
else if(id == LLVMBC::MetaDataRecord::COMPOSITE_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -98,7 +99,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11]),
|
||||
getMeta(metaRecord.ops[14])};
|
||||
}
|
||||
else if(id == MetaDataRecord::TEMPLATE_TYPE)
|
||||
else if(id == LLVMBC::MetaDataRecord::TEMPLATE_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -107,7 +108,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == MetaDataRecord::TEMPLATE_VALUE)
|
||||
else if(id == LLVMBC::MetaDataRecord::TEMPLATE_VALUE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -117,7 +118,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])};
|
||||
}
|
||||
else if(id == MetaDataRecord::SUBPROGRAM)
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBPROGRAM)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -134,7 +135,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
getMeta(metaRecord.ops[14]), getMeta(metaRecord.ops[15]),
|
||||
getMeta(metaRecord.ops[16]), getMeta(metaRecord.ops[17])};
|
||||
}
|
||||
else if(id == MetaDataRecord::SUBROUTINE_TYPE)
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBROUTINE_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -142,7 +143,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == MetaDataRecord::GLOBAL_VAR)
|
||||
else if(id == LLVMBC::MetaDataRecord::GLOBAL_VAR)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -165,7 +166,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
RDCERR("Unsupported version of global variable metadata");
|
||||
}
|
||||
}
|
||||
else if(id == MetaDataRecord::LOCATION)
|
||||
else if(id == LLVMBC::MetaDataRecord::LOCATION)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -177,7 +178,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
meta.children = {getNonNullMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])};
|
||||
}
|
||||
else if(id == MetaDataRecord::LOCAL_VAR)
|
||||
else if(id == LLVMBC::MetaDataRecord::LOCAL_VAR)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -189,7 +190,7 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
meta.children = {getMeta(metaRecord.ops[2]), getMeta(metaRecord.ops[4]),
|
||||
getMeta(metaRecord.ops[6])};
|
||||
}
|
||||
else if(id == MetaDataRecord::LEXICAL_BLOCK)
|
||||
else if(id == LLVMBC::MetaDataRecord::LEXICAL_BLOCK)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
@@ -198,13 +199,13 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == MetaDataRecord::SUBRANGE)
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBRANGE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DISubrange(metaRecord.ops[1], LLVMBC::BitReader::svbr(metaRecord.ops[2]));
|
||||
}
|
||||
else if(id == MetaDataRecord::EXPRESSION)
|
||||
else if(id == LLVMBC::MetaDataRecord::EXPRESSION)
|
||||
{
|
||||
DIExpression *expr = new DIExpression;
|
||||
|
||||
|
||||
@@ -24,10 +24,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/replay/rdcarray.h"
|
||||
#include "common/common.h"
|
||||
|
||||
// undef some annoying defines that might come from OS headers
|
||||
#undef VOID
|
||||
#undef FLOAT
|
||||
#undef LABEL
|
||||
#undef OPAQUE
|
||||
|
||||
namespace LLVMBC
|
||||
{
|
||||
static const uint32_t BitcodeMagic = MAKE_FOURCC('B', 'C', 0xC0, 0xDE);
|
||||
|
||||
enum class AbbrevEncoding : uint8_t
|
||||
{
|
||||
Unknown = 0,
|
||||
Fixed = 1,
|
||||
VBR = 2,
|
||||
Array = 3,
|
||||
@@ -54,5 +66,189 @@ enum class BlockInfoRecord
|
||||
SETRECORDNAME = 3,
|
||||
};
|
||||
|
||||
static const uint32_t BitcodeMagic = MAKE_FOURCC('B', 'C', 0xC0, 0xDE);
|
||||
enum class KnownBlock : uint32_t
|
||||
{
|
||||
BLOCKINFO = 0,
|
||||
|
||||
// 1-7 reserved,
|
||||
|
||||
MODULE_BLOCK = 8,
|
||||
PARAMATTR_BLOCK = 9,
|
||||
PARAMATTR_GROUP_BLOCK = 10,
|
||||
CONSTANTS_BLOCK = 11,
|
||||
FUNCTION_BLOCK = 12,
|
||||
// TYPE_SYMTAB_BLOCK deprecated?
|
||||
VALUE_SYMTAB_BLOCK = 14,
|
||||
METADATA_BLOCK = 15,
|
||||
METADATA_ATTACHMENT = 16,
|
||||
TYPE_BLOCK = 17,
|
||||
USELIST_BLOCK = 18,
|
||||
|
||||
Count,
|
||||
};
|
||||
|
||||
enum class ModuleRecord : uint32_t
|
||||
{
|
||||
VERSION = 1,
|
||||
TRIPLE = 2,
|
||||
DATALAYOUT = 3,
|
||||
SECTIONNAME = 5,
|
||||
GLOBALVAR = 7,
|
||||
FUNCTION = 8,
|
||||
ALIAS = 14,
|
||||
};
|
||||
|
||||
enum class ConstantsRecord : uint32_t
|
||||
{
|
||||
SETTYPE = 1,
|
||||
CONST_NULL = 2,
|
||||
UNDEF = 3,
|
||||
INTEGER = 4,
|
||||
FLOAT = 6,
|
||||
AGGREGATE = 7,
|
||||
STRING = 8,
|
||||
CSTRING = 9,
|
||||
EVAL_CAST = 11,
|
||||
EVAL_GEP = 20,
|
||||
DATA = 22,
|
||||
};
|
||||
|
||||
enum class FunctionRecord : uint32_t
|
||||
{
|
||||
DECLAREBLOCKS = 1,
|
||||
INST_BINOP = 2,
|
||||
INST_CAST = 3,
|
||||
INST_GEP_OLD = 4,
|
||||
INST_SELECT = 5,
|
||||
INST_EXTRACTELT = 6,
|
||||
INST_INSERTELT = 7,
|
||||
INST_SHUFFLEVEC = 8,
|
||||
INST_CMP = 9,
|
||||
INST_RET = 10,
|
||||
INST_BR = 11,
|
||||
INST_SWITCH = 12,
|
||||
INST_INVOKE = 13,
|
||||
INST_UNREACHABLE = 15,
|
||||
INST_PHI = 16,
|
||||
INST_ALLOCA = 19,
|
||||
INST_LOAD = 20,
|
||||
INST_VAARG = 23,
|
||||
INST_STORE_OLD = 24,
|
||||
INST_EXTRACTVAL = 26,
|
||||
INST_INSERTVAL = 27,
|
||||
INST_CMP2 = 28,
|
||||
INST_VSELECT = 29,
|
||||
INST_INBOUNDS_GEP_OLD = 30,
|
||||
INST_INDIRECTBR = 31,
|
||||
DEBUG_LOC_AGAIN = 33,
|
||||
INST_CALL = 34,
|
||||
DEBUG_LOC = 35,
|
||||
INST_FENCE = 36,
|
||||
INST_CMPXCHG_OLD = 37,
|
||||
INST_ATOMICRMW = 38,
|
||||
INST_RESUME = 39,
|
||||
INST_LANDINGPAD_OLD = 40,
|
||||
INST_LOADATOMIC = 41,
|
||||
INST_STOREATOMIC_OLD = 42,
|
||||
INST_GEP = 43,
|
||||
INST_STORE = 44,
|
||||
INST_STOREATOMIC = 45,
|
||||
INST_CMPXCHG = 46,
|
||||
INST_LANDINGPAD = 47,
|
||||
};
|
||||
|
||||
enum class ParamAttrRecord : uint32_t
|
||||
{
|
||||
ENTRY = 2,
|
||||
};
|
||||
|
||||
enum class ParamAttrGroupRecord : uint32_t
|
||||
{
|
||||
ENTRY = 3,
|
||||
};
|
||||
|
||||
enum class ValueSymtabRecord : uint32_t
|
||||
{
|
||||
ENTRY = 1,
|
||||
BBENTRY = 2,
|
||||
FNENTRY = 3,
|
||||
COMBINED_ENTRY = 5,
|
||||
};
|
||||
|
||||
enum class MetaDataRecord : uint32_t
|
||||
{
|
||||
STRING_OLD = 1,
|
||||
VALUE = 2,
|
||||
NODE = 3,
|
||||
NAME = 4,
|
||||
DISTINCT_NODE = 5,
|
||||
KIND = 6,
|
||||
LOCATION = 7,
|
||||
OLD_NODE = 8,
|
||||
OLD_FN_NODE = 9,
|
||||
NAMED_NODE = 10,
|
||||
ATTACHMENT = 11,
|
||||
GENERIC_DEBUG = 12,
|
||||
SUBRANGE = 13,
|
||||
ENUMERATOR = 14,
|
||||
BASIC_TYPE = 15,
|
||||
FILE = 16,
|
||||
DERIVED_TYPE = 17,
|
||||
COMPOSITE_TYPE = 18,
|
||||
SUBROUTINE_TYPE = 19,
|
||||
COMPILE_UNIT = 20,
|
||||
SUBPROGRAM = 21,
|
||||
LEXICAL_BLOCK = 22,
|
||||
LEXICAL_BLOCK_FILE = 23,
|
||||
NAMESPACE = 24,
|
||||
TEMPLATE_TYPE = 25,
|
||||
TEMPLATE_VALUE = 26,
|
||||
GLOBAL_VAR = 27,
|
||||
LOCAL_VAR = 28,
|
||||
EXPRESSION = 29,
|
||||
OBJC_PROPERTY = 30,
|
||||
IMPORTED_ENTITY = 31,
|
||||
MODULE = 32,
|
||||
MACRO = 33,
|
||||
MACRO_FILE = 34,
|
||||
STRINGS = 35,
|
||||
GLOBAL_DECL_ATTACHMENT = 36,
|
||||
GLOBAL_VAR_EXPR = 37,
|
||||
INDEX_OFFSET = 38,
|
||||
INDEX = 39,
|
||||
LABEL = 40,
|
||||
COMMON_BLOCK = 44,
|
||||
};
|
||||
|
||||
enum class TypeRecord : uint32_t
|
||||
{
|
||||
NUMENTRY = 1,
|
||||
VOID = 2,
|
||||
FLOAT = 3,
|
||||
DOUBLE = 4,
|
||||
LABEL = 5,
|
||||
OPAQUE = 6,
|
||||
INTEGER = 7,
|
||||
POINTER = 8,
|
||||
FUNCTION_OLD = 9,
|
||||
HALF = 10,
|
||||
ARRAY = 11,
|
||||
VECTOR = 12,
|
||||
METADATA = 16,
|
||||
STRUCT_ANON = 18,
|
||||
STRUCT_NAME = 19,
|
||||
STRUCT_NAMED = 20,
|
||||
FUNCTION = 21,
|
||||
};
|
||||
|
||||
struct AbbrevParam
|
||||
{
|
||||
AbbrevEncoding encoding;
|
||||
uint64_t value; // this is also the bitwidth for Fixed/VBR
|
||||
};
|
||||
|
||||
struct AbbrevDesc
|
||||
{
|
||||
rdcarray<AbbrevParam> params;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -28,22 +28,12 @@
|
||||
|
||||
namespace LLVMBC
|
||||
{
|
||||
struct AbbrevParam
|
||||
{
|
||||
AbbrevEncoding encoding;
|
||||
uint64_t value; // this is also the bitwidth for Fixed/VBR
|
||||
};
|
||||
|
||||
struct AbbrevDesc
|
||||
{
|
||||
rdcarray<AbbrevParam> params;
|
||||
};
|
||||
|
||||
// the temporary context while pushing/popping blocks
|
||||
struct BlockContext
|
||||
{
|
||||
BlockContext(size_t size = 2) : abbrevSize(size) {}
|
||||
BlockContext(size_t size, size_t offs = 0) : abbrevSize(size), lengthOffset(offs) {}
|
||||
size_t abbrevSize;
|
||||
size_t lengthOffset;
|
||||
rdcarray<AbbrevDesc> abbrevs;
|
||||
};
|
||||
|
||||
@@ -62,6 +52,8 @@ bool BitcodeReader::Valid(const byte *bitcode, size_t length)
|
||||
|
||||
BitcodeReader::BitcodeReader(const byte *bitcode, size_t length) : b(bitcode, length)
|
||||
{
|
||||
abbrevSize = 2;
|
||||
|
||||
uint32_t magic = b.Read<uint32_t>();
|
||||
|
||||
RDCASSERT(magic == BitcodeMagic);
|
||||
@@ -78,7 +70,7 @@ BlockOrRecord BitcodeReader::ReadToplevelBlock()
|
||||
BlockOrRecord ret;
|
||||
|
||||
// should hit ENTER_SUBBLOCK first for top-level block
|
||||
uint32_t abbrevID = b.fixed<uint32_t>(abbrevSize());
|
||||
uint32_t abbrevID = b.fixed<uint32_t>(abbrevSize);
|
||||
RDCASSERT(abbrevID == ENTER_SUBBLOCK);
|
||||
|
||||
ReadBlockContents(ret);
|
||||
@@ -95,7 +87,8 @@ void BitcodeReader::ReadBlockContents(BlockOrRecord &block)
|
||||
{
|
||||
block.id = b.vbr<uint32_t>(8);
|
||||
|
||||
blockStack.push_back(new BlockContext(b.vbr<size_t>(4)));
|
||||
abbrevSize = b.vbr<size_t>(4);
|
||||
blockStack.push_back(new BlockContext(abbrevSize));
|
||||
|
||||
b.align32bits();
|
||||
block.blockDwordLength = b.Read<uint32_t>();
|
||||
@@ -106,7 +99,7 @@ void BitcodeReader::ReadBlockContents(BlockOrRecord &block)
|
||||
uint32_t abbrevID = ~0U;
|
||||
do
|
||||
{
|
||||
abbrevID = b.fixed<uint32_t>(abbrevSize());
|
||||
abbrevID = b.fixed<uint32_t>(abbrevSize);
|
||||
|
||||
if(abbrevID == END_BLOCK)
|
||||
{
|
||||
@@ -254,6 +247,8 @@ void BitcodeReader::ReadBlockContents(BlockOrRecord &block)
|
||||
|
||||
delete blockStack.back();
|
||||
blockStack.erase(blockStack.size() - 1);
|
||||
|
||||
abbrevSize = blockStack.empty() ? 2 : blockStack.back()->abbrevSize;
|
||||
}
|
||||
|
||||
uint64_t BitcodeReader::decodeAbbrevParam(const AbbrevParam ¶m)
|
||||
@@ -267,19 +262,13 @@ uint64_t BitcodeReader::decodeAbbrevParam(const AbbrevParam ¶m)
|
||||
case AbbrevEncoding::Char6: return b.c6();
|
||||
case AbbrevEncoding::Literal: return param.value;
|
||||
case AbbrevEncoding::Array:
|
||||
case AbbrevEncoding::Blob: RDCERR("Array and blob types must be decoded specially");
|
||||
case AbbrevEncoding::Blob: RDCERR("Array and blob types must be decoded specially"); break;
|
||||
case AbbrevEncoding::Unknown: RDCERR("Unexpected abbrev encoding"); break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t BitcodeReader::abbrevSize() const
|
||||
{
|
||||
if(blockStack.empty())
|
||||
return 2;
|
||||
return blockStack.back()->abbrevSize;
|
||||
}
|
||||
|
||||
const AbbrevDesc &BitcodeReader::getAbbrev(uint32_t blockId, uint32_t abbrevID)
|
||||
{
|
||||
const BlockInfo *info = blockInfo[blockId];
|
||||
|
||||
@@ -68,10 +68,10 @@ public:
|
||||
|
||||
private:
|
||||
BitReader b;
|
||||
size_t abbrevSize;
|
||||
|
||||
void ReadBlockContents(BlockOrRecord &block);
|
||||
const AbbrevDesc &getAbbrev(uint32_t blockId, uint32_t abbrevID);
|
||||
size_t abbrevSize() const;
|
||||
uint64_t decodeAbbrevParam(const AbbrevParam ¶m);
|
||||
|
||||
rdcarray<BlockContext *> blockStack;
|
||||
|
||||
@@ -24,18 +24,342 @@
|
||||
|
||||
#include "llvm_encoder.h"
|
||||
#include "os/os_specific.h"
|
||||
#include "llvm_common.h"
|
||||
|
||||
namespace LLVMBC
|
||||
{
|
||||
static uint32_t GetBlockAbbrevSize(KnownBlock block)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
// the abbrev sizes seem to be hardcoded in llvm? At least this matches dxc's llvm
|
||||
switch(block)
|
||||
{
|
||||
case KnownBlock::BLOCKINFO: ret = 2; break;
|
||||
case KnownBlock::MODULE_BLOCK: ret = 3; break;
|
||||
case KnownBlock::PARAMATTR_BLOCK: ret = 3; break;
|
||||
case KnownBlock::PARAMATTR_GROUP_BLOCK: ret = 3; break;
|
||||
case KnownBlock::CONSTANTS_BLOCK: ret = 4; break;
|
||||
case KnownBlock::FUNCTION_BLOCK: ret = 4; break;
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK: ret = 4; break;
|
||||
case KnownBlock::METADATA_BLOCK: ret = 3; break;
|
||||
case KnownBlock::METADATA_ATTACHMENT: ret = 3; break;
|
||||
case KnownBlock::TYPE_BLOCK: ret = 4; break;
|
||||
case KnownBlock::USELIST_BLOCK: ret = 3; break;
|
||||
case KnownBlock::Count: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MagicFixedSizeNumTypes 99
|
||||
|
||||
#define AbbFixed(n) \
|
||||
{ \
|
||||
AbbrevEncoding::Fixed, n \
|
||||
}
|
||||
#define AbbVBR(n) \
|
||||
{ \
|
||||
AbbrevEncoding::VBR, n \
|
||||
}
|
||||
#define AbbArray() \
|
||||
{ \
|
||||
AbbrevEncoding::Array, 0 \
|
||||
}
|
||||
#define AbbLiteral(lit) \
|
||||
{ \
|
||||
AbbrevEncoding::Literal, uint64_t(lit) \
|
||||
}
|
||||
#define AbbChar6() \
|
||||
{ \
|
||||
AbbrevEncoding::Char6, 0 \
|
||||
}
|
||||
|
||||
#define AbbFixedTypes() AbbFixed(MagicFixedSizeNumTypes)
|
||||
|
||||
using AbbrevDefinition = AbbrevParam[8];
|
||||
|
||||
// known abbreviations. Encoded as an array of abbrevs, with each one being an array of params (the
|
||||
// last param will have AbbrevEncoding::Unknown == 0)
|
||||
enum class ValueSymtabAbbrev
|
||||
{
|
||||
Entry8,
|
||||
Entry7,
|
||||
Entry6,
|
||||
BBEntry6,
|
||||
};
|
||||
|
||||
AbbrevDefinition ValueSymtabAbbrevDefs[] = {
|
||||
// Entry8
|
||||
{
|
||||
AbbFixed(3), AbbVBR(8), AbbArray(), AbbFixed(8),
|
||||
},
|
||||
// Entry7
|
||||
{
|
||||
AbbLiteral(ValueSymtabRecord::ENTRY), AbbVBR(8), AbbArray(), AbbFixed(7),
|
||||
},
|
||||
// Entry6
|
||||
{
|
||||
AbbLiteral(ValueSymtabRecord::ENTRY), AbbVBR(8), AbbArray(), AbbChar6(),
|
||||
},
|
||||
// BBEntry6
|
||||
{
|
||||
AbbLiteral(ValueSymtabRecord::BBENTRY), AbbVBR(8), AbbArray(), AbbChar6(),
|
||||
},
|
||||
};
|
||||
|
||||
enum class ConstantsAbbrev
|
||||
{
|
||||
SetType,
|
||||
Integer,
|
||||
EvalCast,
|
||||
Null,
|
||||
};
|
||||
|
||||
AbbrevDefinition ConstantsAbbrevDefs[] = {
|
||||
// SetType
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::SETTYPE), AbbFixedTypes(),
|
||||
},
|
||||
// Integer
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::INTEGER), AbbVBR(8),
|
||||
},
|
||||
// EvalCast
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::EVAL_CAST), AbbFixed(4), AbbFixedTypes(), AbbVBR(8),
|
||||
},
|
||||
// Null
|
||||
{
|
||||
AbbLiteral(ConstantsRecord::CONST_NULL),
|
||||
},
|
||||
};
|
||||
|
||||
enum class FunctionAbbrev
|
||||
{
|
||||
Load,
|
||||
BinOp,
|
||||
BinOpFlags,
|
||||
Cast,
|
||||
RetVoid,
|
||||
RetValue,
|
||||
Unreachable,
|
||||
GEP,
|
||||
};
|
||||
|
||||
AbbrevDefinition FunctionAbbrevDefs[] = {
|
||||
// Load
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_LOAD), AbbVBR(6), AbbFixedTypes(), AbbVBR(4), AbbFixed(1),
|
||||
},
|
||||
// BinOp
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_BINOP), AbbVBR(6), AbbVBR(6), AbbFixed(4),
|
||||
},
|
||||
// BinOpFlags
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_BINOP), AbbVBR(6), AbbVBR(6), AbbFixed(4), AbbFixed(7),
|
||||
},
|
||||
// Cast
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_CAST), AbbVBR(6), AbbFixedTypes(), AbbFixed(4),
|
||||
},
|
||||
// RetVoid
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_RET),
|
||||
},
|
||||
// RetValue
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_RET), AbbVBR(6),
|
||||
},
|
||||
// Unreachable
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_UNREACHABLE),
|
||||
},
|
||||
// GEP
|
||||
{
|
||||
AbbLiteral(FunctionRecord::INST_GEP), AbbFixed(1), AbbFixedTypes(), AbbArray(), AbbVBR(6),
|
||||
},
|
||||
};
|
||||
|
||||
static AbbrevDefinition *GetAbbrevs(KnownBlock block)
|
||||
{
|
||||
AbbrevDefinition *ret = NULL;
|
||||
|
||||
switch(block)
|
||||
{
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK: ret = ValueSymtabAbbrevDefs; break;
|
||||
case KnownBlock::CONSTANTS_BLOCK: ret = ConstantsAbbrevDefs; break;
|
||||
case KnownBlock::FUNCTION_BLOCK: ret = FunctionAbbrevDefs; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t GetNumAbbrevs(KnownBlock block)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
switch(block)
|
||||
{
|
||||
case KnownBlock::VALUE_SYMTAB_BLOCK: ret = ARRAY_COUNT(ValueSymtabAbbrevDefs); break;
|
||||
case KnownBlock::CONSTANTS_BLOCK: ret = ARRAY_COUNT(ConstantsAbbrevDefs); break;
|
||||
case KnownBlock::FUNCTION_BLOCK: ret = ARRAY_COUNT(FunctionAbbrevDefs); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BitcodeWriter::BitcodeWriter(bytebuf &buf) : b(buf)
|
||||
{
|
||||
b.Write(LLVMBC::BitcodeMagic);
|
||||
|
||||
curBlock = KnownBlock::Count;
|
||||
abbrevSize = 2;
|
||||
}
|
||||
|
||||
BitcodeWriter::~BitcodeWriter()
|
||||
{
|
||||
}
|
||||
|
||||
void BitcodeWriter::BeginBlock(KnownBlock block)
|
||||
{
|
||||
uint32_t newAbbrevSize = GetBlockAbbrevSize(block);
|
||||
|
||||
if(newAbbrevSize == 0)
|
||||
{
|
||||
RDCERR("Encoding error: unrecognised block %u", block);
|
||||
return;
|
||||
}
|
||||
|
||||
b.fixed(abbrevSize, ENTER_SUBBLOCK);
|
||||
b.vbr(8, block);
|
||||
b.vbr(4, newAbbrevSize);
|
||||
b.align32bits();
|
||||
|
||||
size_t offs = b.GetByteOffset();
|
||||
|
||||
// write a placeholder length
|
||||
b.Write<uint32_t>(0U);
|
||||
|
||||
curBlock = block;
|
||||
abbrevSize = newAbbrevSize;
|
||||
blockStack.push_back({block, offs});
|
||||
}
|
||||
|
||||
void BitcodeWriter::EndBlock()
|
||||
{
|
||||
b.vbr(abbrevSize, END_BLOCK);
|
||||
b.align32bits();
|
||||
|
||||
size_t offs = blockStack.back().second;
|
||||
|
||||
// -4 because we don't include the word with the length itself
|
||||
size_t lengthInBytes = b.GetByteOffset() - offs - 4;
|
||||
|
||||
b.PatchLengthWord(offs, uint32_t(lengthInBytes / 4));
|
||||
|
||||
blockStack.pop_back();
|
||||
if(blockStack.empty())
|
||||
{
|
||||
curBlock = KnownBlock::Count;
|
||||
abbrevSize = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
curBlock = blockStack.back().first;
|
||||
abbrevSize = GetBlockAbbrevSize(curBlock);
|
||||
}
|
||||
}
|
||||
|
||||
void BitcodeWriter::ModuleBlockInfo(uint32_t numTypes)
|
||||
{
|
||||
// these abbrevs are hardcoded in llvm, at least at dxc's version
|
||||
BeginBlock(KnownBlock::BLOCKINFO);
|
||||
|
||||
// the module-level blockinfo contains abbrevs for these block types that can be repeated
|
||||
// subblocks
|
||||
for(KnownBlock block :
|
||||
{KnownBlock::VALUE_SYMTAB_BLOCK, KnownBlock::CONSTANTS_BLOCK, KnownBlock::FUNCTION_BLOCK})
|
||||
{
|
||||
Unabbrev((uint32_t)BlockInfoRecord::SETBID, (uint32_t)block);
|
||||
AbbrevDefinition *abbrevs = GetAbbrevs(block);
|
||||
uint32_t numAbbrevs = GetNumAbbrevs(block);
|
||||
|
||||
for(uint32_t i = 0; i < numAbbrevs; i++)
|
||||
{
|
||||
b.fixed(abbrevSize, DEFINE_ABBREV);
|
||||
|
||||
AbbrevParam *abbrev = abbrevs[i];
|
||||
|
||||
uint32_t numParams = 0;
|
||||
while(abbrev[numParams].encoding != AbbrevEncoding::Unknown)
|
||||
numParams++;
|
||||
|
||||
b.vbr(5, numParams);
|
||||
|
||||
for(uint32_t p = 0; p < numParams; p++)
|
||||
{
|
||||
AbbrevParam param = abbrev[p];
|
||||
|
||||
if(param.value == MagicFixedSizeNumTypes)
|
||||
{
|
||||
param.value = 32 - Bits::CountLeadingZeroes(numTypes);
|
||||
}
|
||||
|
||||
const bool lit = param.encoding == AbbrevEncoding::Literal;
|
||||
b.fixed<bool>(1, lit);
|
||||
if(lit)
|
||||
{
|
||||
b.vbr(8, param.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.fixed(3, param.encoding);
|
||||
if(param.encoding == AbbrevEncoding::VBR || param.encoding == AbbrevEncoding::Fixed)
|
||||
b.vbr(5, param.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndBlock();
|
||||
}
|
||||
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, uint32_t val)
|
||||
{
|
||||
b.fixed(abbrevSize, UNABBREV_RECORD);
|
||||
b.vbr(6, record);
|
||||
b.vbr(6, 1U); // num parameters
|
||||
b.vbr(6, val);
|
||||
}
|
||||
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, uint64_t val)
|
||||
{
|
||||
b.fixed(abbrevSize, UNABBREV_RECORD);
|
||||
b.vbr(6, record);
|
||||
b.vbr(6, 1U); // num parameters
|
||||
b.vbr(6, val);
|
||||
}
|
||||
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, const rdcarray<uint32_t> &vals)
|
||||
{
|
||||
b.fixed(abbrevSize, UNABBREV_RECORD);
|
||||
b.vbr(6, record);
|
||||
b.vbr(6, vals.size());
|
||||
for(uint32_t v : vals)
|
||||
b.vbr(6, v);
|
||||
}
|
||||
|
||||
void BitcodeWriter::Unabbrev(uint32_t record, const rdcarray<uint64_t> &vals)
|
||||
{
|
||||
b.fixed(abbrevSize, UNABBREV_RECORD);
|
||||
b.vbr(6, record);
|
||||
b.vbr(6, vals.size());
|
||||
for(uint64_t v : vals)
|
||||
b.vbr(6, v);
|
||||
}
|
||||
};
|
||||
|
||||
#if ENABLED(ENABLE_UNIT_TESTS)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "api/replay/rdcarray.h"
|
||||
#include "api/replay/rdcstr.h"
|
||||
#include "llvm_bitwriter.h"
|
||||
#include "llvm_common.h"
|
||||
|
||||
namespace LLVMBC
|
||||
{
|
||||
@@ -36,8 +37,24 @@ public:
|
||||
BitcodeWriter(bytebuf &buf);
|
||||
~BitcodeWriter();
|
||||
|
||||
void BeginBlock(KnownBlock block);
|
||||
|
||||
void EndBlock();
|
||||
|
||||
void ModuleBlockInfo(uint32_t numTypes);
|
||||
|
||||
void Unabbrev(uint32_t record, uint32_t val);
|
||||
void Unabbrev(uint32_t record, uint64_t val);
|
||||
void Unabbrev(uint32_t record, const rdcarray<uint32_t> &vals);
|
||||
void Unabbrev(uint32_t record, const rdcarray<uint64_t> &vals);
|
||||
|
||||
private:
|
||||
BitWriter b;
|
||||
|
||||
size_t abbrevSize;
|
||||
KnownBlock curBlock;
|
||||
|
||||
rdcarray<rdcpair<KnownBlock, size_t>> blockStack;
|
||||
};
|
||||
|
||||
}; // namespace LLVMBC
|
||||
|
||||
Reference in New Issue
Block a user