mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-31 03:41:01 +00:00
Refactor DXIL parsing and handling to more closely mimic LLVM
* This file format is so obtuse that it enforces a code structure almost by design. This makes sense since it was never intended to be used anywhere outside of LLVM internals, so it makes sense that it maps precisely to LLVM's code structure and is hard to handle otherwise.
This commit is contained in:
@@ -386,6 +386,8 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
|
||||
if(dxil)
|
||||
{
|
||||
using namespace DXIL;
|
||||
|
||||
rdcstr stringTable;
|
||||
stringTable.push_back('\0');
|
||||
|
||||
@@ -394,26 +396,26 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
rdcarray<uint32_t> stringTableOffsets;
|
||||
rdcarray<uint32_t> semanticIndexTableOffsets;
|
||||
|
||||
// !!!NOTE!!!
|
||||
//
|
||||
// In the DXIL editing below we directly reference the raster feed DXIL metadata from the edited
|
||||
// metadata. This is fine as long as the metadata 'externally' passed into the editor has
|
||||
// lifetime longer than the editor
|
||||
{
|
||||
// use a local bytebuf so that if we error out, patchedPs above won't be modified
|
||||
DXIL::ProgramEditor editor(
|
||||
&quadOverdrawDXBC, rastFeedingDXBC.GetDXILByteCode()->GetMetadataCount() * 2, patchedDXBC);
|
||||
|
||||
const DXIL::Type *i32 = editor.GetInt32Type();
|
||||
const DXIL::Type *i8 = editor.GetInt8Type();
|
||||
ProgramEditor editor(&quadOverdrawDXBC, patchedDXBC);
|
||||
|
||||
// We need to make two changes: copy the raster-feeding shader's output signature wholesale
|
||||
// into
|
||||
// the pixel shader. It only needs position, which *must* have been written by definition, the
|
||||
// coverage input comes from an intrinsic. None of the properties should need to change, so
|
||||
// it's
|
||||
// a pure deep copy of metadata and properties to ensure a compatible signature.
|
||||
// into the pixel shader. It only needs position, which *must* have been written by
|
||||
// definition, the coverage input comes from an intrinsic. None of the properties should need
|
||||
// to change, so it's a pure deep copy of metadata and properties to ensure a compatible
|
||||
// signature.
|
||||
//
|
||||
// After that, we need to find the input load ops in the original shader, and patch the row it
|
||||
// refers to (it would have been 0 previously). Since position is a full float4 we shouldn't
|
||||
// have to change anything else
|
||||
|
||||
const DXIL::Metadata *rastEntryPoints =
|
||||
const Metadata *rastEntryPoints =
|
||||
rastFeedingDXBC.GetDXILByteCode()->GetMetadataByName("dx.entryPoints");
|
||||
|
||||
if(!rastEntryPoints)
|
||||
@@ -424,105 +426,68 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
|
||||
// TODO select the entry point for multiple entry points? RT only for now
|
||||
RDCASSERT(rastEntryPoints->children.size() > 0 && rastEntryPoints->children[0]);
|
||||
const DXIL::Metadata *rastEntry = rastEntryPoints->children[0];
|
||||
const Metadata *rastEntry = rastEntryPoints->children[0];
|
||||
|
||||
RDCASSERT(rastEntry->children.size() > 2 && rastEntry->children[2]);
|
||||
const DXIL::Metadata *rastSigs = rastEntry->children[2];
|
||||
const Metadata *rastSigs = rastEntry->children[2];
|
||||
|
||||
RDCASSERT(rastSigs->children.size() > 1 && rastSigs->children[1]);
|
||||
const DXIL::Metadata *rastOutSig = rastSigs->children[1];
|
||||
const Metadata *rastOutSig = rastSigs->children[1];
|
||||
|
||||
DXIL::Metadata *entryPoints = editor.GetMetadataByName("dx.entryPoints");
|
||||
Metadata *quadPSentryPoints = editor.GetMetadataByName("dx.entryPoints");
|
||||
|
||||
if(!entryPoints)
|
||||
if(!quadPSentryPoints)
|
||||
{
|
||||
RDCERR("Couldn't find entry point list");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO select the entry point for multiple entry points? RT only for now
|
||||
RDCASSERT(entryPoints->children.size() > 0 && entryPoints->children[0]);
|
||||
DXIL::Metadata *entry = entryPoints->children[0];
|
||||
RDCASSERT(quadPSentryPoints->children.size() > 0 && quadPSentryPoints->children[0]);
|
||||
Metadata *quadPSentry = quadPSentryPoints->children[0];
|
||||
|
||||
rdcstr entryName = entry->children[1]->str;
|
||||
rdcstr entryName = quadPSentry->children[1]->str;
|
||||
|
||||
RDCASSERT(entry->children.size() > 2 && entry->children[2]);
|
||||
DXIL::Metadata *sigs = entry->children[2];
|
||||
RDCASSERT(quadPSentry->children.size() > 2 && quadPSentry->children[2]);
|
||||
Metadata *quadPSsigs = quadPSentry->children[2];
|
||||
|
||||
RDCASSERT(sigs->children.size() > 0);
|
||||
RDCASSERT(quadPSsigs->children.size() > 0);
|
||||
|
||||
DXIL::Metadata inputSig;
|
||||
// just repoint input signature list to rast out sig
|
||||
quadPSsigs->children[0] = (Metadata *)rastOutSig;
|
||||
|
||||
uint32_t posID = ~0U;
|
||||
|
||||
#define DUPLICATE_META_CONSTANT(newConst, type_, oldConst) \
|
||||
{ \
|
||||
DXIL::Metadata m; \
|
||||
m.isConstant = true; \
|
||||
m.type = type_; \
|
||||
m.value = DXIL::Value( \
|
||||
editor.GetOrAddConstant(DXIL::Constant(type_, oldConst->value.constant->val.u32v[0]))); \
|
||||
newConst = editor.AddMetadata(m); \
|
||||
}
|
||||
|
||||
// process signature to get string table & index table for semantics
|
||||
for(size_t i = 0; i < rastOutSig->children.size(); i++)
|
||||
{
|
||||
const DXIL::Metadata *oldSigEl = rastOutSig->children[i];
|
||||
DXIL::Metadata newSigEl;
|
||||
const Metadata *sigEl = rastOutSig->children[i];
|
||||
|
||||
newSigEl.children.resize(oldSigEl->children.size());
|
||||
|
||||
// element ID
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[0], i32, oldSigEl->children[0]);
|
||||
|
||||
// semantic name
|
||||
// only append non-system values to the string table
|
||||
uint32_t systemValue = cast<Constant>(sigEl->children[3]->value)->getU32();
|
||||
if(systemValue == 0)
|
||||
{
|
||||
DXIL::Metadata m;
|
||||
m.isString = true;
|
||||
m.str = oldSigEl->children[1]->str;
|
||||
newSigEl.children[1] = editor.AddMetadata(m);
|
||||
|
||||
// only append non-system values to the string table
|
||||
if(oldSigEl->children[3]->value.constant->val.u32v[0] == 0)
|
||||
{
|
||||
stringTableOffsets.push_back((uint32_t)stringTable.size());
|
||||
stringTable.append(m.str);
|
||||
stringTable.push_back('\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
stringTableOffsets.push_back(0);
|
||||
}
|
||||
stringTableOffsets.push_back((uint32_t)stringTable.size());
|
||||
stringTable.append(sigEl->children[1]->str);
|
||||
stringTable.push_back('\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
stringTableOffsets.push_back(0);
|
||||
|
||||
// component type
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[2], i8, oldSigEl->children[2]);
|
||||
|
||||
// semantic kind
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[3], i8, oldSigEl->children[3]);
|
||||
|
||||
// SV_Position is 3
|
||||
if(oldSigEl->children[3]->value.constant->val.u32v[0] == 3)
|
||||
posID = oldSigEl->children[0]->value.constant->val.u32v[0];
|
||||
// SV_Position is 3
|
||||
if(systemValue == 3)
|
||||
posID = cast<Constant>(sigEl->children[0]->value)->getU32();
|
||||
}
|
||||
|
||||
rdcarray<uint32_t> semIndexValues;
|
||||
|
||||
// semantic indices
|
||||
const DXIL::Metadata *oldSemIdxs = oldSigEl->children[4];
|
||||
if(oldSemIdxs)
|
||||
if(const Metadata *semIdxs = sigEl->children[4])
|
||||
{
|
||||
DXIL::Metadata semanticIndices;
|
||||
|
||||
// the semantic index node is a list of constants
|
||||
semanticIndices.children.resize(oldSemIdxs->children.size());
|
||||
for(size_t sidx = 0; sidx < oldSemIdxs->children.size(); sidx++)
|
||||
{
|
||||
DUPLICATE_META_CONSTANT(semanticIndices.children[sidx], i32, oldSemIdxs->children[sidx]);
|
||||
semIndexValues.push_back(oldSemIdxs->children[sidx]->value.constant->val.u32v[0]);
|
||||
}
|
||||
|
||||
// copy the list
|
||||
newSigEl.children[4] = editor.AddMetadata(semanticIndices);
|
||||
for(size_t sidx = 0; sidx < semIdxs->children.size(); sidx++)
|
||||
semIndexValues.push_back(cast<Constant>(semIdxs->children[sidx]->value)->getU32());
|
||||
}
|
||||
|
||||
size_t tableOffset = ~0U;
|
||||
@@ -555,40 +520,6 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
}
|
||||
|
||||
semanticIndexTableOffsets.push_back((uint32_t)tableOffset);
|
||||
|
||||
// interpolation mode
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[5], i8, oldSigEl->children[5]);
|
||||
|
||||
// number of rows
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[6], i32, oldSigEl->children[6]);
|
||||
|
||||
// number of columns
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[7], i8, oldSigEl->children[7]);
|
||||
|
||||
// start row
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[8], i32, oldSigEl->children[8]);
|
||||
|
||||
// start column
|
||||
DUPLICATE_META_CONSTANT(newSigEl.children[9], i8, oldSigEl->children[9]);
|
||||
|
||||
// the extra tag/thing list is also a series of ints
|
||||
const DXIL::Metadata *oldTagList = oldSigEl->children[10];
|
||||
if(oldTagList)
|
||||
{
|
||||
DXIL::Metadata tagList;
|
||||
|
||||
// the semantic index node is a list of constants
|
||||
tagList.children.resize(oldTagList->children.size());
|
||||
for(size_t sidx = 0; sidx < oldTagList->children.size(); sidx++)
|
||||
{
|
||||
DUPLICATE_META_CONSTANT(tagList.children[sidx], i32, oldTagList->children[sidx]);
|
||||
}
|
||||
|
||||
// copy the list
|
||||
newSigEl.children[10] = editor.AddMetadata(tagList);
|
||||
}
|
||||
|
||||
inputSig.children.push_back(editor.AddMetadata(newSigEl));
|
||||
}
|
||||
|
||||
if(posID == ~0U)
|
||||
@@ -597,16 +528,7 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
return;
|
||||
}
|
||||
|
||||
// recreate input signature list, for backwards references
|
||||
sigs->children[0] = editor.AddMetadata(inputSig);
|
||||
|
||||
// recreate backwards upwards
|
||||
sigs = editor.AddMetadata(*sigs);
|
||||
entry->children[2] = sigs;
|
||||
entry = editor.AddMetadata(*entry);
|
||||
entryPoints->children[0] = entry;
|
||||
|
||||
DXIL::Function *f = editor.GetFunctionByName(entryName);
|
||||
Function *f = editor.GetFunctionByName(entryName);
|
||||
|
||||
if(!f)
|
||||
{
|
||||
@@ -614,15 +536,15 @@ void D3D12Replay::PatchQuadWritePS(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &pi
|
||||
return;
|
||||
}
|
||||
|
||||
DXIL::Value inputIDValue(editor.GetOrAddConstant(f, DXIL::Constant(i32, posID)));
|
||||
Value *inputIDValue = editor.CreateConstant(posID);
|
||||
|
||||
// now locate the loadInputs and patch the row they refer to. We can unconditionally patch
|
||||
// them all as there was only one input previously
|
||||
for(size_t i = 0; i < f->instructions.size(); i++)
|
||||
{
|
||||
DXIL::Instruction &inst = f->instructions[i];
|
||||
Instruction &inst = *f->instructions[i];
|
||||
|
||||
if(inst.op == DXIL::Operation::Call && inst.funcCall->name == "dx.op.loadInput.f32")
|
||||
if(inst.op == Operation::Call && inst.getFuncCall()->name == "dx.op.loadInput.f32")
|
||||
{
|
||||
if(inst.args.size() != 5)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "api/replay/apidefs.h"
|
||||
#include "api/replay/rdcstr.h"
|
||||
#include "common/common.h"
|
||||
#include "driver/dx/official/d3dcommon.h"
|
||||
#include "driver/shaders/dxbc/dxbc_common.h"
|
||||
|
||||
@@ -40,6 +41,25 @@ struct BlockOrRecord;
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
struct BumpAllocator
|
||||
{
|
||||
BumpAllocator(size_t totalSize);
|
||||
~BumpAllocator();
|
||||
void *alloc(size_t sz);
|
||||
|
||||
template <typename T>
|
||||
T *alloc()
|
||||
{
|
||||
void *mem = alloc(sizeof(T));
|
||||
return new(mem) T();
|
||||
}
|
||||
|
||||
private:
|
||||
byte *base, *cur;
|
||||
rdcarray<byte *> storage;
|
||||
size_t m_BlockSize;
|
||||
};
|
||||
|
||||
struct ProgramHeader
|
||||
{
|
||||
uint16_t ProgramVersion;
|
||||
@@ -88,9 +108,11 @@ struct Type
|
||||
ImmediateCBuffer = 5,
|
||||
};
|
||||
|
||||
static void *operator new(size_t count, BumpAllocator &b) { return b.alloc(count); }
|
||||
static void operator delete(void *ptr, BumpAllocator &b) {}
|
||||
bool isVoid() const { return type == Scalar && scalarType == Void; }
|
||||
rdcstr toString() const;
|
||||
rdcstr declFunction(rdcstr funcName, const rdcarray<Instruction> &args,
|
||||
rdcstr declFunction(rdcstr funcName, const rdcarray<Instruction *> &args,
|
||||
const AttributeSet *attrs) const;
|
||||
|
||||
// for scalars, arrays, vectors, pointers
|
||||
@@ -111,109 +133,6 @@ struct Type
|
||||
rdcarray<const Type *> members; // the members for a struct, the parameters for functions
|
||||
};
|
||||
|
||||
enum class ValueType
|
||||
{
|
||||
Unknown,
|
||||
Function,
|
||||
GlobalVar,
|
||||
Alias,
|
||||
Constant,
|
||||
Instruction,
|
||||
Metadata,
|
||||
Literal,
|
||||
BasicBlock,
|
||||
};
|
||||
|
||||
struct Function;
|
||||
struct GlobalVar;
|
||||
struct Alias;
|
||||
struct Constant;
|
||||
struct Instruction;
|
||||
struct Metadata;
|
||||
struct Block;
|
||||
struct Type;
|
||||
|
||||
struct Value
|
||||
{
|
||||
enum ForwardRefTag
|
||||
{
|
||||
ForwardRef
|
||||
};
|
||||
Value() : type(ValueType::Unknown), literal(0) {}
|
||||
explicit Value(ForwardRefTag, const Value *value) : type(ValueType::Unknown), value(value) {}
|
||||
explicit Value(const Function *function) : type(ValueType::Function), function(function) {}
|
||||
explicit Value(const GlobalVar *global) : type(ValueType::GlobalVar), global(global) {}
|
||||
explicit Value(const Alias *alias) : type(ValueType::Alias), alias(alias) {}
|
||||
explicit Value(const Constant *constant) : type(ValueType::Constant), constant(constant) {}
|
||||
explicit Value(const Instruction *instruction)
|
||||
: type(ValueType::Instruction), instruction(instruction)
|
||||
{
|
||||
}
|
||||
explicit Value(const Metadata *meta) : type(ValueType::Metadata), meta(meta) {}
|
||||
explicit Value(const Block *block) : type(ValueType::BasicBlock), block(block) {}
|
||||
explicit Value(uint64_t literal) : type(ValueType::Literal), literal(literal) {}
|
||||
bool empty() const { return type == ValueType::Unknown && literal == 0; }
|
||||
const Type *GetType() const;
|
||||
rdcstr toString(bool withType = false) const;
|
||||
|
||||
bool operator==(const Value &o) { return type == o.type && literal == o.literal; }
|
||||
ValueType type;
|
||||
union
|
||||
{
|
||||
const Value *value;
|
||||
const Function *function;
|
||||
const GlobalVar *global;
|
||||
const Alias *alias;
|
||||
const Constant *constant;
|
||||
const Instruction *instruction;
|
||||
const Metadata *meta;
|
||||
const Block *block;
|
||||
uint64_t literal;
|
||||
};
|
||||
};
|
||||
|
||||
enum class GlobalFlags : uint32_t
|
||||
{
|
||||
NoFlags = 0,
|
||||
ExternalLinkage = 1,
|
||||
AvailableExternallyLinkage = 2,
|
||||
LinkOnceAnyLinkage = 3,
|
||||
LinkOnceODRLinkage = 4,
|
||||
WeakAnyLinkage = 5,
|
||||
WeakODRLinkage = 6,
|
||||
AppendingLinkage = 7,
|
||||
InternalLinkage = 8,
|
||||
PrivateLinkage = 9,
|
||||
ExternalWeakLinkage = 10,
|
||||
CommonLinkage = 11,
|
||||
LinkageMask = 0xf,
|
||||
IsConst = 0x10,
|
||||
IsExternal = 0x20,
|
||||
LocalUnnamedAddr = 0x40,
|
||||
GlobalUnnamedAddr = 0x80,
|
||||
IsAppending = 0x100,
|
||||
ExternallyInitialised = 0x200,
|
||||
};
|
||||
|
||||
BITMASK_OPERATORS(GlobalFlags);
|
||||
|
||||
struct GlobalVar
|
||||
{
|
||||
rdcstr name;
|
||||
const Type *type = NULL;
|
||||
uint64_t align = 0;
|
||||
int32_t section = -1;
|
||||
GlobalFlags flags = GlobalFlags::NoFlags;
|
||||
const Constant *initialiser = NULL;
|
||||
};
|
||||
|
||||
struct Alias
|
||||
{
|
||||
rdcstr name;
|
||||
const Type *type = NULL;
|
||||
Value val;
|
||||
};
|
||||
|
||||
// this enum is ordered to match the serialised order of these attributes
|
||||
enum class Attribute : uint64_t
|
||||
{
|
||||
@@ -430,22 +349,392 @@ inline uint64_t EncodeCast(Operation op)
|
||||
}
|
||||
}
|
||||
|
||||
struct Constant
|
||||
enum class ValueKind : uint32_t
|
||||
{
|
||||
Constant() = default;
|
||||
Constant(const Type *t, uint32_t v) : type(t) { val.u32v[0] = v; }
|
||||
ForwardReferencePlaceholder,
|
||||
Literal,
|
||||
Alias,
|
||||
Constant,
|
||||
GlobalVar,
|
||||
Metadata,
|
||||
Instruction,
|
||||
Function,
|
||||
BasicBlock,
|
||||
};
|
||||
|
||||
struct Type;
|
||||
|
||||
struct PlaceholderValue;
|
||||
|
||||
struct Value
|
||||
{
|
||||
const Type *type = NULL;
|
||||
ShaderValue val = {};
|
||||
rdcarray<Value> members;
|
||||
Value inner;
|
||||
rdcstr str;
|
||||
bool undef = false, nullconst = false, data = false;
|
||||
Operation op = Operation::NoOp;
|
||||
|
||||
// the ID for this value (two namespaces: values, and metadata)
|
||||
// note, not all derived classes from Value have an id - e.g. void instructions, blocks, these
|
||||
// don't have IDs because they don't go in the values array
|
||||
//
|
||||
// this ID is very close but different to the number displayed in disassembly. This ID is only
|
||||
// used internally for encoding
|
||||
static constexpr uint32_t NoID = 0x00ffffff;
|
||||
uint32_t id : 24;
|
||||
|
||||
// steal the last unused part of ShaderValue, used for identifying constants under patching
|
||||
uint32_t getID() { return val.u32v[15]; }
|
||||
void setID(uint32_t id) { val.u32v[15] = id; }
|
||||
rdcstr toString(bool withType = false) const;
|
||||
|
||||
static void *operator new(size_t count, BumpAllocator &b) { return b.alloc(count); }
|
||||
static void operator delete(void *ptr, BumpAllocator &b) {}
|
||||
static void *operator new(size_t count, PlaceholderValue *v) { return v; }
|
||||
static void operator delete(void *ptr, PlaceholderValue *v) {}
|
||||
static void operator delete(void *ptr) {}
|
||||
ValueKind kind() const { return valKind; }
|
||||
protected:
|
||||
Value(ValueKind k) : valKind(k), id(NoID) {}
|
||||
ValueKind valKind : 8;
|
||||
uint32_t flags = 0;
|
||||
};
|
||||
|
||||
struct PlaceholderValue : public Value
|
||||
{
|
||||
private:
|
||||
friend struct ValueList;
|
||||
|
||||
PlaceholderValue() : Value(ValueKind::ForwardReferencePlaceholder) {}
|
||||
byte storage[64 - sizeof(Value)];
|
||||
};
|
||||
|
||||
// helper class to check at compile time that values will be able to be forward referenced as
|
||||
// we conservatively allocate room for them.
|
||||
template <typename T>
|
||||
struct ForwardReferencableValue : public Value
|
||||
{
|
||||
static constexpr bool IsForwardReferenceable = true;
|
||||
|
||||
protected:
|
||||
ForwardReferencableValue(ValueKind k) : Value(k)
|
||||
{
|
||||
RDCCOMPILE_ASSERT(sizeof(T) <= sizeof(PlaceholderValue),
|
||||
"Type is too large to be forward referenceable in-place");
|
||||
}
|
||||
};
|
||||
|
||||
// loose wrapper around an array for value pointers. This doesn't use the underlying array size for
|
||||
// anything but instead tracks the current latest value, so relative indices can be resolved against
|
||||
// it while we can still future-allocate in the array for forward reference placeholders.
|
||||
struct ValueList : private rdcarray<Value *>
|
||||
{
|
||||
ValueList(BumpAllocator &alloc) : rdcarray(), alloc(alloc) {}
|
||||
Value *&operator[](size_t i)
|
||||
{
|
||||
resize_for_index(i);
|
||||
RDCASSERT(at(i));
|
||||
return at(i);
|
||||
}
|
||||
void hintExpansion(size_t newValues) { reserve(lastValue + newValues); }
|
||||
void beginFunction() { functionWatermark = lastValue; }
|
||||
void endFunction()
|
||||
{
|
||||
resize(functionWatermark);
|
||||
lastValue = functionWatermark;
|
||||
}
|
||||
size_t curValueIndex() const { return lastValue; }
|
||||
Value *createPlaceholderValue(size_t i)
|
||||
{
|
||||
resize_for_index(i);
|
||||
Value *ret = at(i);
|
||||
if(ret)
|
||||
{
|
||||
RDCASSERT(ret->kind() == ValueKind::ForwardReferencePlaceholder);
|
||||
return ret;
|
||||
}
|
||||
at(i) = ret = new(alloc) PlaceholderValue();
|
||||
return ret;
|
||||
}
|
||||
Value *getOrCreatePlaceholder(size_t i)
|
||||
{
|
||||
resize_for_index(i);
|
||||
Value *ret = at(i);
|
||||
if(ret)
|
||||
return ret;
|
||||
return createPlaceholderValue(i);
|
||||
}
|
||||
// alloc a value in-place to resolve forward references. Should always be paired with a call to
|
||||
// addAllocedValue() once you're done creating the value
|
||||
// if you're creating a 'Value' that isn't actually a value (e.g. instruction with no return
|
||||
// value) then you can new it directly
|
||||
template <typename T>
|
||||
T *nextValue()
|
||||
{
|
||||
RDCASSERT(!pendingValue);
|
||||
RDCCOMPILE_ASSERT(typename T::IsForwardReferenceable,
|
||||
"alloc'ing next value for non-forward-referenceable type");
|
||||
|
||||
pendingValue = true;
|
||||
|
||||
// if this value was already allocated as a placeholder, re-use the memory to keep any pointers
|
||||
// to it valid
|
||||
if(lastValue < size() && at(lastValue))
|
||||
{
|
||||
Value *v = at(lastValue);
|
||||
RDCASSERT(v->kind() == ValueKind::ForwardReferencePlaceholder);
|
||||
PlaceholderValue *memory = (PlaceholderValue *)v;
|
||||
return new(memory) T();
|
||||
}
|
||||
|
||||
// no placeholder, put it in place now and addValue() will be called to bump the count below
|
||||
resize_for_index(lastValue);
|
||||
T *ret = new(alloc) T();
|
||||
at(lastValue) = ret;
|
||||
return ret;
|
||||
}
|
||||
void addValue(Value *v = NULL)
|
||||
{
|
||||
// either pendingValue should be true, or v should be true, but they shouldn't both be
|
||||
if(pendingValue)
|
||||
{
|
||||
RDCASSERT(v == NULL);
|
||||
pendingValue = false;
|
||||
lastValue++;
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCASSERT(v);
|
||||
v->id = lastValue;
|
||||
resize_for_index(lastValue);
|
||||
RDCASSERTMSG("Forward reference being overwritten with new pointer", at(lastValue) == NULL);
|
||||
at(lastValue) = v;
|
||||
lastValue++;
|
||||
}
|
||||
}
|
||||
size_t getRelativeBackwards(uint64_t ref) { return lastValue - (size_t)ref; }
|
||||
size_t getRelativeForwards(uint64_t ref) { return lastValue + (size_t)ref; }
|
||||
private:
|
||||
BumpAllocator &alloc;
|
||||
size_t functionWatermark = 0;
|
||||
size_t lastValue = 0;
|
||||
bool pendingValue = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T *cast(Value *v)
|
||||
{
|
||||
if(v && v->kind() == T::Kind)
|
||||
return (T *)v;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T *cast(const Value *v)
|
||||
{
|
||||
if(v && v->kind() == T::Kind)
|
||||
return (const T *)v;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum class GlobalFlags : uint32_t
|
||||
{
|
||||
NoFlags = 0,
|
||||
ExternalLinkage = 1,
|
||||
AvailableExternallyLinkage = 2,
|
||||
LinkOnceAnyLinkage = 3,
|
||||
LinkOnceODRLinkage = 4,
|
||||
WeakAnyLinkage = 5,
|
||||
WeakODRLinkage = 6,
|
||||
AppendingLinkage = 7,
|
||||
InternalLinkage = 8,
|
||||
PrivateLinkage = 9,
|
||||
ExternalWeakLinkage = 10,
|
||||
CommonLinkage = 11,
|
||||
LinkageMask = 0xf,
|
||||
IsConst = 0x10,
|
||||
IsExternal = 0x20,
|
||||
LocalUnnamedAddr = 0x40,
|
||||
GlobalUnnamedAddr = 0x80,
|
||||
IsAppending = 0x100,
|
||||
ExternallyInitialised = 0x200,
|
||||
};
|
||||
|
||||
BITMASK_OPERATORS(GlobalFlags);
|
||||
|
||||
struct Literal : public ForwardReferencableValue<Literal>
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::Literal;
|
||||
Literal(uint64_t v) : ForwardReferencableValue(Kind), literal(v) {}
|
||||
uint64_t literal;
|
||||
};
|
||||
|
||||
struct Alias : public ForwardReferencableValue<Alias>
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::Alias;
|
||||
Alias() : ForwardReferencableValue(Kind) {}
|
||||
rdcstr name;
|
||||
Value *val = NULL;
|
||||
};
|
||||
|
||||
struct Constant : public ForwardReferencableValue<Constant>
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::Constant;
|
||||
Constant() : ForwardReferencableValue(Kind) { u64 = 0; }
|
||||
Constant(const Type *t, uint32_t v) : ForwardReferencableValue(ValueKind::Constant)
|
||||
{
|
||||
type = t;
|
||||
u64 = 0;
|
||||
setValue(v);
|
||||
}
|
||||
Operation op = Operation::NoOp;
|
||||
rdcstr str;
|
||||
// used during encoding to sort constants by number of uses...
|
||||
uint32_t refCount = 0;
|
||||
|
||||
bool isUndef() const { return (flags & 0x1) != 0; }
|
||||
bool isNULL() const { return (flags & 0x2) != 0; }
|
||||
bool isData() const { return (flags & 0x4) != 0; }
|
||||
bool isLiteral() const { return (flags & 0x10) != 0; }
|
||||
bool isShaderVal() const { return (flags & 0x20) != 0; }
|
||||
bool isCast() const { return (flags & 0x40) != 0; }
|
||||
bool isCompound() const { return (flags & 0x80) != 0; }
|
||||
void setUndef(bool u)
|
||||
{
|
||||
flags &= ~0x1;
|
||||
flags |= u ? 0x1 : 0x0;
|
||||
}
|
||||
void setNULL(bool n)
|
||||
{
|
||||
flags &= ~0x2;
|
||||
flags |= n ? 0x2 : 0x0;
|
||||
}
|
||||
void setData(bool d)
|
||||
{
|
||||
flags &= ~0x4;
|
||||
flags |= d ? 0x4 : 0x0;
|
||||
}
|
||||
void setValue(uint32_t l)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x10;
|
||||
u32 = l;
|
||||
}
|
||||
void setValue(uint64_t l)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x10;
|
||||
u64 = l;
|
||||
}
|
||||
void setValue(int64_t l)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x10;
|
||||
s64 = l;
|
||||
}
|
||||
void setValue(BumpAllocator &alloc, const ShaderValue &v)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x20;
|
||||
val = alloc.alloc<ShaderValue>();
|
||||
*val = v;
|
||||
}
|
||||
void setInner(Value *i)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x40;
|
||||
inner = i;
|
||||
}
|
||||
void setCompound(BumpAllocator &alloc, rdcarray<Value *> &&m)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x80;
|
||||
members = alloc.alloc<rdcarray<Value *>>();
|
||||
new(members) rdcarray<Value *>(m);
|
||||
}
|
||||
void setCompound(BumpAllocator &alloc, const rdcarray<Value *> &m)
|
||||
{
|
||||
flags &= ~0xf0;
|
||||
flags |= 0x80;
|
||||
members = alloc.alloc<rdcarray<Value *>>();
|
||||
new(members) rdcarray<Value *>(m);
|
||||
}
|
||||
|
||||
uint32_t getU32() const
|
||||
{
|
||||
if(flags & 0x10)
|
||||
return u32;
|
||||
// silently return 0 for NULL/Undef constants
|
||||
if(flags & 0x06)
|
||||
return 0U;
|
||||
RDCERR("Wrong type of constant being accessed");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint64_t getU64() const
|
||||
{
|
||||
if(flags & 0x10)
|
||||
return u64;
|
||||
// silently return 0 for NULL/Undef constants
|
||||
if(flags & 0x06)
|
||||
return 0U;
|
||||
RDCERR("Wrong type of constant being accessed");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
int64_t getS64() const
|
||||
{
|
||||
if(flags & 0x10)
|
||||
return s64;
|
||||
// silently return 0 for NULL/Undef constants
|
||||
if(flags & 0x06)
|
||||
return 0;
|
||||
RDCERR("Wrong type of constant being accessed");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
const ShaderValue &getShaderVal() const
|
||||
{
|
||||
if(flags & 0x20)
|
||||
return *val;
|
||||
static ShaderValue empty;
|
||||
RDCERR("Wrong type of constant being accessed");
|
||||
return empty;
|
||||
}
|
||||
|
||||
Value *getInner() const
|
||||
{
|
||||
if(flags & 0x40)
|
||||
return inner;
|
||||
RDCERR("No inner available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const rdcarray<Value *> &getMembers() const
|
||||
{
|
||||
if(flags & 0x80)
|
||||
return *members;
|
||||
static rdcarray<Value *> empty;
|
||||
RDCERR("No members available");
|
||||
return empty;
|
||||
}
|
||||
|
||||
rdcstr toString(bool withType = false) const;
|
||||
|
||||
private:
|
||||
union
|
||||
{
|
||||
uint64_t u64;
|
||||
int64_t s64;
|
||||
uint32_t u32;
|
||||
ShaderValue *val;
|
||||
Value *inner;
|
||||
rdcarray<Value *> *members;
|
||||
};
|
||||
};
|
||||
|
||||
struct GlobalVar : public ForwardReferencableValue<GlobalVar>
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::GlobalVar;
|
||||
GlobalVar() : ForwardReferencableValue(Kind) {}
|
||||
rdcstr name;
|
||||
uint64_t align = 0;
|
||||
int32_t section = -1;
|
||||
GlobalFlags flags = GlobalFlags::NoFlags;
|
||||
const Constant *initialiser = NULL;
|
||||
};
|
||||
|
||||
struct DIBase
|
||||
@@ -480,9 +769,11 @@ struct DIBase
|
||||
}
|
||||
};
|
||||
|
||||
struct Metadata;
|
||||
|
||||
struct DebugLocation
|
||||
{
|
||||
uint32_t id = ~0U;
|
||||
uint32_t slot = ~0U;
|
||||
|
||||
uint64_t line = 0;
|
||||
uint64_t col = 0;
|
||||
@@ -497,16 +788,20 @@ struct DebugLocation
|
||||
rdcstr toString() const;
|
||||
};
|
||||
|
||||
struct Metadata
|
||||
struct Metadata : public Value
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::Metadata;
|
||||
Metadata(size_t idx = 0xffffff) : Value(Kind) { id = idx; }
|
||||
~Metadata();
|
||||
|
||||
uint32_t id = ~0U;
|
||||
bool isDistinct = false, isConstant = false, isString = false;
|
||||
|
||||
Value value;
|
||||
// only used for disassembly, the number given to metadata that's directly referenced. NOT the
|
||||
// same as it's id (ha ha)
|
||||
uint32_t slot = ~0U;
|
||||
|
||||
Value *value = NULL;
|
||||
|
||||
const Type *type = NULL;
|
||||
rdcstr str;
|
||||
rdcarray<Metadata *> children;
|
||||
DIBase *dwarf = NULL;
|
||||
@@ -516,6 +811,39 @@ struct Metadata
|
||||
rdcstr valString() const;
|
||||
};
|
||||
|
||||
// loose wrapper around an array for metadata pointer. This creates metadata nodes on demand because
|
||||
// they can be forward referenced (sigh...)
|
||||
struct MetadataList : private rdcarray<Metadata *>
|
||||
{
|
||||
MetadataList(BumpAllocator &alloc) : rdcarray(), alloc(&alloc) {}
|
||||
MetadataList() : rdcarray(), alloc(NULL) {}
|
||||
Metadata *&operator[](size_t i)
|
||||
{
|
||||
resize_for_index(i);
|
||||
if(at(i))
|
||||
return at(i);
|
||||
RDCASSERT(alloc);
|
||||
at(i) = new(*alloc) Metadata(i);
|
||||
return at(i);
|
||||
}
|
||||
void hintExpansion(size_t newValues) { reserve(size() + newValues); }
|
||||
void beginFunction() { functionWatermark = size(); }
|
||||
void endFunction() { resize(functionWatermark); }
|
||||
using rdcarray<Metadata *>::size;
|
||||
using rdcarray<Metadata *>::back;
|
||||
using rdcarray<Metadata *>::empty;
|
||||
using rdcarray<Metadata *>::contains;
|
||||
|
||||
Metadata *getDirect(uint64_t id) { return (*this)[size_t(id)]; }
|
||||
Metadata *getOrNULL(uint64_t id) { return id ? (*this)[size_t(id - 1)] : NULL; }
|
||||
rdcstr *getStringOrNULL(uint64_t id) { return id ? &(*this)[size_t(id - 1)]->str : NULL; }
|
||||
private:
|
||||
BumpAllocator *alloc = NULL;
|
||||
size_t functionWatermark = 0;
|
||||
size_t lastValue = 0;
|
||||
bool pendingValue = false;
|
||||
};
|
||||
|
||||
struct NamedMetadata : public Metadata
|
||||
{
|
||||
rdcstr name;
|
||||
@@ -573,62 +901,112 @@ enum class InstructionFlags : uint32_t
|
||||
|
||||
BITMASK_OPERATORS(InstructionFlags);
|
||||
|
||||
// pair of <kind, Metadata>
|
||||
typedef rdcarray<rdcpair<uint64_t, Metadata *>> AttachedMetadata;
|
||||
|
||||
struct Instruction
|
||||
struct Function;
|
||||
|
||||
struct Instruction : public ForwardReferencableValue<Instruction>
|
||||
{
|
||||
Operation op = Operation::NoOp;
|
||||
InstructionFlags opFlags = InstructionFlags::NoFlags;
|
||||
|
||||
// common to all instructions
|
||||
rdcstr name;
|
||||
static constexpr ValueKind Kind = ValueKind::Instruction;
|
||||
Instruction() : ForwardReferencableValue(Kind) {}
|
||||
uint32_t disassemblyLine = 0;
|
||||
uint32_t resultID = ~0U;
|
||||
uint32_t debugLoc = ~0U;
|
||||
uint32_t align = 0;
|
||||
const Type *type = NULL;
|
||||
rdcarray<Value> args;
|
||||
AttachedMetadata attachedMeta;
|
||||
Operation op = Operation::NoOp;
|
||||
uint8_t align = 0;
|
||||
// number assigned to instructions that don't have names and return a value, for disassembly
|
||||
uint32_t slot = ~0U;
|
||||
InstructionFlags &opFlags() { return (InstructionFlags &)flags; }
|
||||
InstructionFlags opFlags() const { return (InstructionFlags)flags; }
|
||||
rdcarray<Value *> args;
|
||||
|
||||
// function calls
|
||||
const AttributeSet *paramAttrs = NULL;
|
||||
const Function *funcCall = NULL;
|
||||
struct ExtraInstructionInfo
|
||||
{
|
||||
rdcstr name;
|
||||
AttachedMetadata attachedMeta;
|
||||
|
||||
// function calls
|
||||
const AttributeSet *paramAttrs = NULL;
|
||||
const Function *funcCall = NULL;
|
||||
};
|
||||
|
||||
const rdcstr &getName() const
|
||||
{
|
||||
static rdcstr empty;
|
||||
if(extraData)
|
||||
return extraData->name;
|
||||
return empty;
|
||||
}
|
||||
|
||||
const AttachedMetadata &getAttachedMeta() const
|
||||
{
|
||||
static AttachedMetadata empty;
|
||||
if(extraData)
|
||||
return extraData->attachedMeta;
|
||||
return empty;
|
||||
}
|
||||
|
||||
const AttributeSet *getParamAttrs() const
|
||||
{
|
||||
if(extraData)
|
||||
return extraData->paramAttrs;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Function *getFuncCall() const
|
||||
{
|
||||
if(extraData)
|
||||
return extraData->funcCall;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ExtraInstructionInfo &extra(BumpAllocator &alloc)
|
||||
{
|
||||
if(!extraData)
|
||||
extraData = alloc.alloc<ExtraInstructionInfo>();
|
||||
return *extraData;
|
||||
}
|
||||
|
||||
private:
|
||||
ExtraInstructionInfo *extraData = NULL;
|
||||
};
|
||||
|
||||
struct Block
|
||||
struct Block : public ForwardReferencableValue<Block>
|
||||
{
|
||||
uint32_t resultID = ~0U;
|
||||
rdcstr name;
|
||||
static constexpr ValueKind Kind = ValueKind::BasicBlock;
|
||||
Block(const Type *labelType) : ForwardReferencableValue(Kind) { type = labelType; }
|
||||
rdcinflexiblestr name;
|
||||
rdcarray<const Block *> preds;
|
||||
uint32_t slot = ~0U;
|
||||
};
|
||||
|
||||
struct UselistEntry
|
||||
{
|
||||
bool block = false;
|
||||
Value value;
|
||||
Value *value;
|
||||
rdcarray<uint64_t> shuffle;
|
||||
};
|
||||
|
||||
struct Function
|
||||
// functions are deliberately not forward referenceable since they're larger, and we shouldn't need
|
||||
// to
|
||||
struct Function : public Value
|
||||
{
|
||||
static constexpr ValueKind Kind = ValueKind::Function;
|
||||
Function() : Value(Kind) {}
|
||||
rdcstr name;
|
||||
|
||||
const Type *funcType = NULL;
|
||||
bool external = false;
|
||||
bool sortedSymtab = true;
|
||||
const AttributeSet *attrs = NULL;
|
||||
|
||||
uint64_t align = 0;
|
||||
|
||||
rdcarray<Instruction> args;
|
||||
rdcarray<Instruction> instructions;
|
||||
rdcarray<Value> values;
|
||||
rdcarray<Instruction *> args;
|
||||
rdcarray<Instruction *> instructions;
|
||||
|
||||
rdcarray<Value> valueSymtabOrder;
|
||||
bool sortedSymtab = true;
|
||||
rdcarray<Value *> valueSymtabOrder;
|
||||
|
||||
rdcarray<Block> blocks;
|
||||
rdcarray<Constant> constants;
|
||||
rdcarray<Metadata> metadata;
|
||||
rdcarray<Block *> blocks;
|
||||
|
||||
rdcarray<UselistEntry> uselist;
|
||||
|
||||
@@ -674,27 +1052,33 @@ public:
|
||||
rdcarray<SourceVariableMapping> &locals) const override;
|
||||
|
||||
const Metadata *GetMetadataByName(const rdcstr &name) const;
|
||||
size_t GetMetadataCount() const { return m_Metadata.size() + m_NamedMeta.size(); }
|
||||
uint32_t GetDirectHeapAcessCount() const { return m_directHeapAccessCount; }
|
||||
protected:
|
||||
void MakeDisassemblyString();
|
||||
|
||||
bool ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta);
|
||||
void ParseConstant(ValueList &values, const LLVMBC::BlockOrRecord &constant);
|
||||
bool ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOrRecord &metaRecord,
|
||||
Metadata &meta);
|
||||
rdcstr GetDebugVarName(const DIBase *d);
|
||||
rdcstr GetFunctionScopeName(const DIBase *d);
|
||||
|
||||
rdcstr &GetValueSymtabString(const Value &v);
|
||||
rdcstr GetValueSymtabString(Value *v);
|
||||
void SetValueSymtabString(Value *v, const rdcstr &s);
|
||||
|
||||
uint32_t GetOrAssignMetaID(Metadata *m);
|
||||
uint32_t GetOrAssignMetaID(DebugLocation &l);
|
||||
const Type *GetVoidType(bool precache = false);
|
||||
const Type *GetBoolType(bool precache = false);
|
||||
const Type *GetInt32Type(bool precache = false);
|
||||
const Type *GetInt8Type();
|
||||
uint32_t GetOrAssignMetaSlot(rdcarray<Metadata *> &metaSlots, uint32_t &nextMetaSlot, Metadata *m);
|
||||
uint32_t GetOrAssignMetaSlot(rdcarray<Metadata *> &metaSlots, uint32_t &nextMetaSlot,
|
||||
DebugLocation &l);
|
||||
|
||||
const Type *GetVoidType() { return m_VoidType; }
|
||||
const Type *GetBoolType() { return m_BoolType; }
|
||||
const Type *GetInt32Type() { return m_Int32Type; }
|
||||
const Type *GetInt8Type() { return m_Int8Type; }
|
||||
const Type *GetPointerType(const Type *type, Type::PointerAddrSpace addrSpace) const;
|
||||
|
||||
bytebuf m_Bytes;
|
||||
|
||||
BumpAllocator alloc;
|
||||
|
||||
DXBC::ShaderType m_Type;
|
||||
uint32_t m_Major, m_Minor;
|
||||
uint32_t m_DXILVersion;
|
||||
@@ -702,47 +1086,91 @@ protected:
|
||||
rdcstr m_CompilerSig, m_EntryPoint, m_Profile;
|
||||
ShaderCompileFlags m_CompileFlags;
|
||||
|
||||
rdcarray<GlobalVar> m_GlobalVars;
|
||||
rdcarray<Function> m_Functions;
|
||||
rdcarray<Alias> m_Aliases;
|
||||
rdcarray<Value> m_Values;
|
||||
const Type *m_CurParseType = NULL;
|
||||
|
||||
rdcarray<GlobalVar *> m_GlobalVars;
|
||||
rdcarray<Function *> m_Functions;
|
||||
rdcarray<Alias *> m_Aliases;
|
||||
rdcarray<rdcstr> m_Sections;
|
||||
uint32_t m_directHeapAccessCount = 0;
|
||||
|
||||
rdcarray<rdcstr> m_Kinds;
|
||||
|
||||
rdcarray<Value> m_ValueSymtabOrder;
|
||||
rdcarray<Value *> m_ValueSymtabOrder;
|
||||
bool m_SortedSymtab = true;
|
||||
|
||||
rdcarray<Type> m_Types;
|
||||
rdcarray<Type *> m_Types;
|
||||
const Type *m_VoidType = NULL;
|
||||
const Type *m_BoolType = NULL;
|
||||
const Type *m_Int32Type = NULL;
|
||||
const Type *m_Int8Type = NULL;
|
||||
const Type *m_MetaType = NULL;
|
||||
const Type *m_LabelType = NULL;
|
||||
|
||||
rdcarray<AttributeGroup> m_AttributeGroups;
|
||||
rdcarray<AttributeSet> m_AttributeSets;
|
||||
|
||||
rdcarray<Constant> m_Constants;
|
||||
|
||||
rdcarray<Metadata> m_Metadata;
|
||||
rdcarray<NamedMetadata> m_NamedMeta;
|
||||
rdcarray<Metadata *> m_NumberedMeta;
|
||||
uint32_t m_NextMetaID = 0;
|
||||
rdcarray<NamedMetadata *> m_NamedMeta;
|
||||
|
||||
rdcarray<DebugLocation> m_DebugLocations;
|
||||
|
||||
bool m_Uselists = false;
|
||||
|
||||
rdcstr m_Triple, m_Datalayout;
|
||||
|
||||
rdcstr m_Disassembly;
|
||||
|
||||
friend struct OpReader;
|
||||
friend class LLVMOrderAccumulator;
|
||||
};
|
||||
|
||||
bool needsEscaping(const rdcstr &name);
|
||||
rdcstr escapeString(const rdcstr &str);
|
||||
rdcstr escapeStringIfNeeded(const rdcstr &name);
|
||||
|
||||
class LLVMOrderAccumulator
|
||||
{
|
||||
public:
|
||||
// types in id order
|
||||
rdcarray<const Type *> types;
|
||||
// types in disassembly print order
|
||||
rdcarray<const Type *> printOrderTypes;
|
||||
// values in id order
|
||||
rdcarray<const Value *> values;
|
||||
// metadata in id order
|
||||
rdcarray<const Metadata *> metadata;
|
||||
|
||||
size_t firstConst;
|
||||
size_t numConsts;
|
||||
|
||||
void processGlobals(Program *p);
|
||||
|
||||
size_t firstFuncConst;
|
||||
size_t numFuncConsts;
|
||||
|
||||
void processFunction(Function *f);
|
||||
void exitFunction();
|
||||
|
||||
private:
|
||||
size_t functionWaterMark;
|
||||
bool sortConsts = true;
|
||||
|
||||
void reset(GlobalVar *g);
|
||||
void reset(Alias *a);
|
||||
void reset(Constant *c);
|
||||
void reset(Metadata *m);
|
||||
void reset(Function *f);
|
||||
void reset(Block *b);
|
||||
void reset(Instruction *i);
|
||||
void reset(Value *v);
|
||||
|
||||
void accumulate(const Value *v);
|
||||
void accumulate(const Metadata *m);
|
||||
void accumulateTypePrintOrder(const Type *t);
|
||||
void accumulateTypePrintOrder(rdcarray<const Metadata *> &visited, const Metadata *m);
|
||||
void assignTypeId(const Type *t);
|
||||
};
|
||||
|
||||
}; // namespace DXIL
|
||||
|
||||
DECLARE_REFLECTION_ENUM(DXIL::Attribute);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@ enum class HandleKind
|
||||
class ProgramEditor : public Program
|
||||
{
|
||||
public:
|
||||
ProgramEditor(const DXBC::DXBCContainer *container, size_t reservationSize, bytebuf &outBlob);
|
||||
ProgramEditor(const DXBC::DXBCContainer *container, bytebuf &outBlob);
|
||||
~ProgramEditor();
|
||||
|
||||
// publish these interfaces
|
||||
@@ -75,25 +75,33 @@ public:
|
||||
using Program::GetPointerType;
|
||||
|
||||
const rdcarray<AttributeSet> &GetAttributeSets() { return m_AttributeSets; }
|
||||
// find existing type or metadata by name, returns NULL if not found
|
||||
const rdcarray<Type> &GetTypes() const { return m_Types; }
|
||||
const Type *GetTypeByName(const rdcstr &name);
|
||||
const rdcarray<Type *> &GetTypes() const { return m_Types; }
|
||||
Type *CreateNamedStructType(const rdcstr &name, rdcarray<const Type *> members);
|
||||
Type *CreateFunctionType(const Type *ret, rdcarray<const Type *> params);
|
||||
Type *CreatePointerType(const Type *inner, Type::PointerAddrSpace addrSpace);
|
||||
Function *GetFunctionByName(const rdcstr &name);
|
||||
Metadata *GetMetadataByName(const rdcstr &name);
|
||||
|
||||
// add a type, function, or metadata, and return the pointer to the stored one (which can be
|
||||
// referenced from elsewhere)
|
||||
const Type *AddType(const Type &t);
|
||||
const Function *DeclareFunction(const Function &f);
|
||||
Metadata *AddMetadata(const Metadata &m);
|
||||
NamedMetadata *AddNamedMetadata(const NamedMetadata &m);
|
||||
Function *DeclareFunction(const Function &f);
|
||||
Metadata *CreateMetadata();
|
||||
Metadata *CreateConstantMetadata(Constant *val);
|
||||
Metadata *CreateConstantMetadata(uint32_t val);
|
||||
Metadata *CreateConstantMetadata(uint8_t val);
|
||||
Metadata *CreateConstantMetadata(bool val);
|
||||
Metadata *CreateConstantMetadata(const char *str) { return CreateConstantMetadata(rdcstr(str)); }
|
||||
Metadata *CreateConstantMetadata(const rdcstr &str);
|
||||
NamedMetadata *CreateNamedMetadata(const rdcstr &name);
|
||||
|
||||
// I think constants have to be unique, so this will return an existing constant (for simple cases
|
||||
// like integers or NULL) if it exists
|
||||
const Constant *GetOrAddConstant(const Constant &c);
|
||||
const Constant *GetOrAddConstant(Function *f, const Constant &c);
|
||||
Constant *CreateConstant(const Constant &c);
|
||||
Constant *CreateConstant(const Type *t, const rdcarray<Value *> &members);
|
||||
|
||||
Instruction *AddInstruction(Function *f, size_t idx, const Instruction &inst);
|
||||
Constant *CreateConstant(uint32_t u) { return CreateConstant(Constant(m_Int32Type, u)); }
|
||||
Constant *CreateConstant(uint8_t u) { return CreateConstant(Constant(m_Int8Type, u)); }
|
||||
Constant *CreateConstant(bool b) { return CreateConstant(Constant(m_BoolType, b)); }
|
||||
Instruction *CreateInstruction(Operation op);
|
||||
Instruction *CreateInstruction(const Function *f);
|
||||
|
||||
void RegisterUAV(DXILResourceType type, uint32_t space, uint32_t regBase, uint32_t regEnd,
|
||||
ResourceKind kind);
|
||||
@@ -101,63 +109,15 @@ public:
|
||||
private:
|
||||
bytebuf &m_OutBlob;
|
||||
|
||||
void Fixup(Type *&t);
|
||||
void Fixup(Function *&f);
|
||||
void Fixup(Block *&b, Function *oldf = NULL, Function *newf = NULL);
|
||||
void Fixup(Instruction *&i, Function *oldf = NULL, Function *newf = NULL);
|
||||
void Fixup(Constant *&c, Function *oldf = NULL, Function *newf = NULL);
|
||||
void Fixup(Metadata *&m, Function *oldf = NULL, Function *newf = NULL);
|
||||
void Fixup(Value &v, Function *oldf = NULL, Function *newf = NULL);
|
||||
rdcarray<Constant *> m_Constants;
|
||||
|
||||
void Fixup(const Type *&t) { Fixup((Type *&)t); }
|
||||
void Fixup(const Function *&f) { Fixup((Function *&)f); }
|
||||
void Fixup(const Block *&b, Function *oldf = NULL, Function *newf = NULL)
|
||||
{
|
||||
Fixup((Block *&)b, oldf, newf);
|
||||
}
|
||||
void Fixup(const Instruction *&i, Function *oldf = NULL, Function *newf = NULL)
|
||||
{
|
||||
Fixup((Instruction *&)i, oldf, newf);
|
||||
}
|
||||
void Fixup(const Constant *&c, Function *oldf = NULL, Function *newf = NULL)
|
||||
{
|
||||
Fixup((Constant *&)c, oldf, newf);
|
||||
}
|
||||
Type *CreateNewType();
|
||||
|
||||
bytebuf EncodeProgram() const;
|
||||
bytebuf EncodeProgram();
|
||||
|
||||
void EncodeConstants(LLVMBC::BitcodeWriter &writer, const rdcarray<Value> &values,
|
||||
const rdcarray<Constant> &constants) const;
|
||||
void EncodeMetadata(LLVMBC::BitcodeWriter &writer, const rdcarray<Value> &values,
|
||||
const rdcarray<Metadata> &meta) const;
|
||||
|
||||
// these are arrays which hold the original program's storage, so all pointers remain valid. We
|
||||
// then duplicate into the editable arrays
|
||||
|
||||
// in the destructor before encoding we will look up any pointers that still point here and find
|
||||
// the element in the current arrays
|
||||
|
||||
// every array which might be mutated by editing must be here
|
||||
rdcarray<Function> m_OldFunctions;
|
||||
rdcarray<Type> m_OldTypes;
|
||||
rdcarray<Constant> m_OldConstants;
|
||||
rdcarray<Metadata> m_OldMetadata;
|
||||
|
||||
uint32_t m_InsertedInstructionID = 0xfffffff0;
|
||||
|
||||
#if ENABLED(RDOC_DEVEL)
|
||||
Function *m_DebugFunctionsData;
|
||||
Type *m_DebugTypesData;
|
||||
Constant *m_DebugConstantsData;
|
||||
Metadata *m_DebugMetadataData;
|
||||
|
||||
struct DebugFunctionData
|
||||
{
|
||||
Instruction *instructions;
|
||||
Constant *constants;
|
||||
};
|
||||
rdcarray<DebugFunctionData> m_DebugFunctions;
|
||||
#endif
|
||||
void EncodeConstants(LLVMBC::BitcodeWriter &writer, const rdcarray<const Value *> &values,
|
||||
size_t firstIdx, size_t count) const;
|
||||
void EncodeMetadata(LLVMBC::BitcodeWriter &writer, const rdcarray<const Metadata *> &meta) const;
|
||||
};
|
||||
|
||||
}; // namespace DXIL
|
||||
|
||||
@@ -29,20 +29,18 @@
|
||||
|
||||
namespace DXIL
|
||||
{
|
||||
bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Metadata &meta)
|
||||
bool Program::ParseDebugMetaRecord(MetadataList &metadata, const LLVMBC::BlockOrRecord &metaRecord,
|
||||
Metadata &meta)
|
||||
{
|
||||
LLVMBC::MetaDataRecord id = (LLVMBC::MetaDataRecord)metaRecord.id;
|
||||
|
||||
#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)
|
||||
{
|
||||
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])};
|
||||
meta.dwarf =
|
||||
new DIFile(metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]));
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::COMPILE_UNIT)
|
||||
{
|
||||
@@ -54,35 +52,39 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
meta.isDistinct = true;
|
||||
|
||||
meta.dwarf = new DICompileUnit(
|
||||
DW_LANG(metaRecord.ops[1]), getMeta(metaRecord.ops[2]), getMetaString(metaRecord.ops[3]),
|
||||
metaRecord.ops[4] != 0, getMetaString(metaRecord.ops[5]), metaRecord.ops[6],
|
||||
getMetaString(metaRecord.ops[7]), metaRecord.ops[8], getMeta(metaRecord.ops[9]),
|
||||
getMeta(metaRecord.ops[10]), getMeta(metaRecord.ops[11]), getMeta(metaRecord.ops[12]),
|
||||
getMeta(metaRecord.ops[13]));
|
||||
meta.children = {getMeta(metaRecord.ops[2]), getMeta(metaRecord.ops[9]),
|
||||
getMeta(metaRecord.ops[10]), getMeta(metaRecord.ops[11]),
|
||||
getMeta(metaRecord.ops[12]), getMeta(metaRecord.ops[13])};
|
||||
DW_LANG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]),
|
||||
metadata.getStringOrNULL(metaRecord.ops[3]), metaRecord.ops[4] != 0,
|
||||
metadata.getStringOrNULL(metaRecord.ops[5]), metaRecord.ops[6],
|
||||
metadata.getStringOrNULL(metaRecord.ops[7]), metaRecord.ops[8],
|
||||
metadata.getOrNULL(metaRecord.ops[9]), metadata.getOrNULL(metaRecord.ops[10]),
|
||||
metadata.getOrNULL(metaRecord.ops[11]), metadata.getOrNULL(metaRecord.ops[12]),
|
||||
metadata.getOrNULL(metaRecord.ops[13]));
|
||||
meta.children = {
|
||||
metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[9]),
|
||||
metadata.getOrNULL(metaRecord.ops[10]), metadata.getOrNULL(metaRecord.ops[11]),
|
||||
metadata.getOrNULL(metaRecord.ops[12]), metadata.getOrNULL(metaRecord.ops[13])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::BASIC_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf =
|
||||
new DIBasicType(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
new DIBasicType(DW_TAG(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metaRecord.ops[3], metaRecord.ops[4], DW_ENCODING(metaRecord.ops[5]));
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::DERIVED_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DIDerivedType(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
getMeta(metaRecord.ops[3]), metaRecord.ops[4],
|
||||
getMeta(metaRecord.ops[5]), getMeta(metaRecord.ops[6]),
|
||||
metaRecord.ops[7], metaRecord.ops[8], metaRecord.ops[9],
|
||||
DIFlags(metaRecord.ops[10]), getMeta(metaRecord.ops[11]));
|
||||
meta.dwarf = new DIDerivedType(
|
||||
DW_TAG(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metadata.getOrNULL(metaRecord.ops[3]), metaRecord.ops[4],
|
||||
metadata.getOrNULL(metaRecord.ops[5]), metadata.getOrNULL(metaRecord.ops[6]),
|
||||
metaRecord.ops[7], metaRecord.ops[8], metaRecord.ops[9], DIFlags(metaRecord.ops[10]),
|
||||
metadata.getOrNULL(metaRecord.ops[11]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[5]),
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[5]),
|
||||
metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[11])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::COMPOSITE_TYPE)
|
||||
{
|
||||
@@ -90,58 +92,62 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
|
||||
// TODO handle forward declarations?
|
||||
meta.dwarf = new DICompositeType(
|
||||
DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]), getMeta(metaRecord.ops[3]),
|
||||
metaRecord.ops[4], getMeta(metaRecord.ops[5]), getMeta(metaRecord.ops[6]),
|
||||
DW_TAG(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metadata.getOrNULL(metaRecord.ops[3]), metaRecord.ops[4],
|
||||
metadata.getOrNULL(metaRecord.ops[5]), metadata.getOrNULL(metaRecord.ops[6]),
|
||||
metaRecord.ops[7], metaRecord.ops[8], metaRecord.ops[9], DIFlags(metaRecord.ops[10]),
|
||||
getMeta(metaRecord.ops[11]), getMeta(metaRecord.ops[14]));
|
||||
metadata.getOrNULL(metaRecord.ops[11]), metadata.getOrNULL(metaRecord.ops[14]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[5]),
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[11]),
|
||||
getMeta(metaRecord.ops[14])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[5]),
|
||||
metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[11]),
|
||||
metadata.getOrNULL(metaRecord.ops[14])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::TEMPLATE_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf =
|
||||
new DITemplateTypeParameter(getMetaString(metaRecord.ops[1]), getMeta(metaRecord.ops[2]));
|
||||
meta.dwarf = new DITemplateTypeParameter(metadata.getStringOrNULL(metaRecord.ops[1]),
|
||||
metadata.getOrNULL(metaRecord.ops[2]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[2])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::TEMPLATE_VALUE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf =
|
||||
new DITemplateValueParameter(DW_TAG(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4]));
|
||||
meta.dwarf = new DITemplateValueParameter(
|
||||
DW_TAG(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metadata.getOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBPROGRAM)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DISubprogram(
|
||||
getMeta(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
getMetaString(metaRecord.ops[3]), getMeta(metaRecord.ops[4]), metaRecord.ops[5],
|
||||
getMeta(metaRecord.ops[6]), metaRecord.ops[7] != 0, metaRecord.ops[8] != 0, metaRecord.ops[9],
|
||||
getMeta(metaRecord.ops[10]), DW_VIRTUALITY(metaRecord.ops[11]), metaRecord.ops[12],
|
||||
DIFlags(metaRecord.ops[13]), metaRecord.ops[14] != 0, getMeta(metaRecord.ops[15]),
|
||||
getMeta(metaRecord.ops[16]), getMeta(metaRecord.ops[17]), getMeta(metaRecord.ops[18]));
|
||||
metadata.getOrNULL(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metadata.getStringOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metaRecord.ops[5], metadata.getOrNULL(metaRecord.ops[6]), metaRecord.ops[7] != 0,
|
||||
metaRecord.ops[8] != 0, metaRecord.ops[9], metadata.getOrNULL(metaRecord.ops[10]),
|
||||
DW_VIRTUALITY(metaRecord.ops[11]), metaRecord.ops[12], DIFlags(metaRecord.ops[13]),
|
||||
metaRecord.ops[14] != 0, metadata.getOrNULL(metaRecord.ops[15]),
|
||||
metadata.getOrNULL(metaRecord.ops[16]), metadata.getOrNULL(metaRecord.ops[17]),
|
||||
metadata.getOrNULL(metaRecord.ops[18]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[4]),
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[10]),
|
||||
getMeta(metaRecord.ops[14]), getMeta(metaRecord.ops[15]),
|
||||
getMeta(metaRecord.ops[16]), getMeta(metaRecord.ops[17])};
|
||||
meta.children = {
|
||||
metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[10]),
|
||||
metadata.getOrNULL(metaRecord.ops[14]), metadata.getOrNULL(metaRecord.ops[15]),
|
||||
metadata.getOrNULL(metaRecord.ops[16]), metadata.getOrNULL(metaRecord.ops[17])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBROUTINE_TYPE)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DISubroutineType(getMeta(metaRecord.ops[2]));
|
||||
meta.dwarf = new DISubroutineType(metadata.getOrNULL(metaRecord.ops[2]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[2])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::GLOBAL_VAR)
|
||||
{
|
||||
@@ -152,14 +158,15 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
if(version == 0)
|
||||
{
|
||||
meta.dwarf = new DIGlobalVariable(
|
||||
getMeta(metaRecord.ops[1]), getMetaString(metaRecord.ops[2]),
|
||||
getMetaString(metaRecord.ops[3]), getMeta(metaRecord.ops[4]), metaRecord.ops[5],
|
||||
getMeta(metaRecord.ops[6]), metaRecord.ops[7] != 0, metaRecord.ops[8] != 0,
|
||||
getMeta(metaRecord.ops[9]), getMeta(metaRecord.ops[10]));
|
||||
metadata.getOrNULL(metaRecord.ops[1]), metadata.getStringOrNULL(metaRecord.ops[2]),
|
||||
metadata.getStringOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metaRecord.ops[5], metadata.getOrNULL(metaRecord.ops[6]), metaRecord.ops[7] != 0,
|
||||
metaRecord.ops[8] != 0, metadata.getOrNULL(metaRecord.ops[9]),
|
||||
metadata.getOrNULL(metaRecord.ops[10]));
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[4]),
|
||||
getMeta(metaRecord.ops[6]), getMeta(metaRecord.ops[9]),
|
||||
getMeta(metaRecord.ops[10])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metadata.getOrNULL(metaRecord.ops[6]), metadata.getOrNULL(metaRecord.ops[9]),
|
||||
metadata.getOrNULL(metaRecord.ops[10])};
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -173,31 +180,33 @@ bool Program::ParseDebugMetaRecord(const LLVMBC::BlockOrRecord &metaRecord, Meta
|
||||
meta.debugLoc = new DebugLocation;
|
||||
meta.debugLoc->line = metaRecord.ops[1];
|
||||
meta.debugLoc->col = metaRecord.ops[2];
|
||||
meta.debugLoc->scope = getNonNullMeta(metaRecord.ops[3]);
|
||||
meta.debugLoc->inlinedAt = getMeta(metaRecord.ops[4]);
|
||||
meta.debugLoc->scope = metadata.getDirect(metaRecord.ops[3]);
|
||||
meta.debugLoc->inlinedAt = metadata.getOrNULL(metaRecord.ops[4]);
|
||||
|
||||
meta.children = {getNonNullMeta(metaRecord.ops[3]), getMeta(metaRecord.ops[4])};
|
||||
meta.children = {metadata.getDirect(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::LOCAL_VAR)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DILocalVariable(
|
||||
DW_TAG(metaRecord.ops[1]), getMeta(metaRecord.ops[2]), getMetaString(metaRecord.ops[3]),
|
||||
getMeta(metaRecord.ops[4]), metaRecord.ops[5], getMeta(metaRecord.ops[6]),
|
||||
metaRecord.ops[7], DIFlags(metaRecord.ops[8]), metaRecord.ops[8]);
|
||||
DW_TAG(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2]),
|
||||
metadata.getStringOrNULL(metaRecord.ops[3]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metaRecord.ops[5], metadata.getOrNULL(metaRecord.ops[6]), metaRecord.ops[7],
|
||||
DIFlags(metaRecord.ops[8]), metaRecord.ops[8]);
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[2]), getMeta(metaRecord.ops[4]),
|
||||
getMeta(metaRecord.ops[6])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[2]), metadata.getOrNULL(metaRecord.ops[4]),
|
||||
metadata.getOrNULL(metaRecord.ops[6])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::LEXICAL_BLOCK)
|
||||
{
|
||||
meta.isDistinct = (metaRecord.ops[0] & 0x1);
|
||||
|
||||
meta.dwarf = new DILexicalBlock(getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2]),
|
||||
metaRecord.ops[3], metaRecord.ops[4]);
|
||||
meta.dwarf = new DILexicalBlock(metadata.getOrNULL(metaRecord.ops[1]),
|
||||
metadata.getOrNULL(metaRecord.ops[2]), metaRecord.ops[3],
|
||||
metaRecord.ops[4]);
|
||||
|
||||
meta.children = {getMeta(metaRecord.ops[1]), getMeta(metaRecord.ops[2])};
|
||||
meta.children = {metadata.getOrNULL(metaRecord.ops[1]), metadata.getOrNULL(metaRecord.ops[2])};
|
||||
}
|
||||
else if(id == LLVMBC::MetaDataRecord::SUBRANGE)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,13 +51,18 @@ enum class StructMemberAnnotation
|
||||
template <typename T>
|
||||
T getival(const Metadata *m)
|
||||
{
|
||||
return T(m->value.constant->val.u32v[0]);
|
||||
Constant *c = cast<Constant>(m->value);
|
||||
if(c && c->isLiteral())
|
||||
return T(c->getU32());
|
||||
return T();
|
||||
}
|
||||
|
||||
void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
{
|
||||
for(const Function &f : m_Functions)
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = *m_Functions[i];
|
||||
|
||||
if(f.name.beginsWith("dx.op.threadId"))
|
||||
{
|
||||
SigParameter param;
|
||||
@@ -98,12 +103,13 @@ void Program::FetchComputeProperties(DXBC::Reflection *reflection)
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
if(m_NamedMeta[i].name == "dx.entryPoints")
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m_NamedMeta[i].children.size(), 1);
|
||||
Metadata &entry = *m_NamedMeta[i].children[0];
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
@@ -139,12 +145,13 @@ D3D_PRIMITIVE_TOPOLOGY Program::GetOutputTopology()
|
||||
|
||||
for(size_t i = 0; i < m_NamedMeta.size(); i++)
|
||||
{
|
||||
if(m_NamedMeta[i].name == "dx.entryPoints")
|
||||
const NamedMetadata &m = *m_NamedMeta[i];
|
||||
if(m.name == "dx.entryPoints")
|
||||
{
|
||||
// expect only one child for this, DX doesn't support multiple entry points for compute
|
||||
// shaders
|
||||
RDCASSERTEQUAL(m_NamedMeta[i].children.size(), 1);
|
||||
Metadata &entry = *m_NamedMeta[i].children[0];
|
||||
RDCASSERTEQUAL(m.children.size(), 1);
|
||||
Metadata &entry = *m.children[0];
|
||||
RDCASSERTEQUAL(entry.children.size(), 5);
|
||||
Metadata &tags = *entry.children[4];
|
||||
|
||||
@@ -189,16 +196,16 @@ struct DXMeta
|
||||
// technically llvm.ident
|
||||
const Metadata *ident = NULL;
|
||||
|
||||
DXMeta(const rdcarray<NamedMetadata> &namedMeta)
|
||||
DXMeta(const rdcarray<NamedMetadata *> &namedMeta)
|
||||
{
|
||||
DXMeta &dx = *this;
|
||||
DXMeta &llvm = *this;
|
||||
|
||||
for(size_t i = 0; i < namedMeta.size(); i++)
|
||||
{
|
||||
#define GRAB_META(metaname) \
|
||||
if(namedMeta[i].name == #metaname) \
|
||||
metaname = &namedMeta[i];
|
||||
#define GRAB_META(metaname) \
|
||||
if(namedMeta[i]->name == #metaname) \
|
||||
metaname = namedMeta[i];
|
||||
|
||||
GRAB_META(llvm.ident);
|
||||
GRAB_META(dx.source.contents);
|
||||
@@ -780,9 +787,10 @@ DXBC::Reflection *Program::GetReflection()
|
||||
|
||||
if(dx.valver && dx.valver->children.size() == 1 && dx.valver->children[0]->children.size() == 2)
|
||||
{
|
||||
m_CompilerSig += StringFormat::Fmt(
|
||||
" (Validation version %s.%s)", dx.valver->children[0]->children[0]->value.toString().c_str(),
|
||||
dx.valver->children[0]->children[1]->value.toString().c_str());
|
||||
m_CompilerSig +=
|
||||
StringFormat::Fmt(" (Validation version %s.%s)",
|
||||
dx.valver->children[0]->children[0]->value->toString().c_str(),
|
||||
dx.valver->children[0]->children[1]->value->toString().c_str());
|
||||
}
|
||||
|
||||
if(dx.entryPoints && dx.entryPoints->children.size() > 0 &&
|
||||
@@ -801,8 +809,8 @@ DXBC::Reflection *Program::GetReflection()
|
||||
{
|
||||
m_Profile =
|
||||
StringFormat::Fmt("%s_%s_%s", dx.shaderModel->children[0]->children[0]->str.c_str(),
|
||||
dx.shaderModel->children[0]->children[1]->value.toString().c_str(),
|
||||
dx.shaderModel->children[0]->children[2]->value.toString().c_str());
|
||||
dx.shaderModel->children[0]->children[1]->value->toString().c_str(),
|
||||
dx.shaderModel->children[0]->children[2]->value->toString().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1001,11 +1009,13 @@ void Program::GetLineInfo(size_t instruction, uintptr_t offset, LineColumnInfo &
|
||||
{
|
||||
lineInfo = LineColumnInfo();
|
||||
|
||||
for(const Function &f : m_Functions)
|
||||
for(size_t i = 0; i < m_Functions.size(); i++)
|
||||
{
|
||||
const Function &f = *m_Functions[i];
|
||||
|
||||
if(instruction < f.instructions.size())
|
||||
{
|
||||
lineInfo.disassemblyLine = f.instructions[instruction].disassemblyLine;
|
||||
lineInfo.disassemblyLine = f.instructions[instruction]->disassemblyLine;
|
||||
break;
|
||||
}
|
||||
instruction -= f.instructions.size();
|
||||
|
||||
Reference in New Issue
Block a user