mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
IR: Assembly and bitcode for GenericDebugNode
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228041 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
90eef42c8e
commit
6adbfa3815
@ -146,7 +146,8 @@ namespace bitc {
|
||||
METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)]
|
||||
METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)]
|
||||
METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes]
|
||||
METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]]
|
||||
METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]]
|
||||
METADATA_GENERIC_DEBUG = 12 // [distinct, tag, vers, header, n x md num]
|
||||
};
|
||||
|
||||
// The constants block (CONSTANTS_BLOCK_ID) describes emission for each
|
||||
|
@ -2945,6 +2945,24 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
|
||||
std::string S;
|
||||
if (ParseStringConstant(S))
|
||||
return true;
|
||||
|
||||
Result.assign(std::move(S));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) {
|
||||
SmallVector<Metadata *, 4> MDs;
|
||||
if (ParseMDNodeVector(MDs))
|
||||
return true;
|
||||
|
||||
Result.assign(std::move(MDs));
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class ParserTy>
|
||||
bool LLParser::ParseMDFieldsImplBody(ParserTy parseField) {
|
||||
do {
|
||||
@ -2990,6 +3008,7 @@ bool LLParser::ParseSpecializedMDNode(MDNode *&N, bool IsDistinct) {
|
||||
return Parse##CLASS(N, IsDistinct);
|
||||
|
||||
DISPATCH_TO_PARSER(MDLocation);
|
||||
DISPATCH_TO_PARSER(GenericDebugNode);
|
||||
#undef DISPATCH_TO_PARSER
|
||||
|
||||
return TokError("expected metadata type");
|
||||
@ -3014,6 +3033,8 @@ bool LLParser::ParseSpecializedMDNode(MDNode *&N, bool IsDistinct) {
|
||||
return true; \
|
||||
VISIT_MD_FIELDS(NOP_FIELD, REQUIRE_FIELD) \
|
||||
} while (false)
|
||||
#define GET_OR_DISTINCT(CLASS, ARGS) \
|
||||
(IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS)
|
||||
|
||||
/// ParseMDLocationFields:
|
||||
/// ::= !MDLocation(line: 43, column: 8, scope: !5, inlinedAt: !6)
|
||||
@ -3030,6 +3051,21 @@ bool LLParser::ParseMDLocation(MDNode *&Result, bool IsDistinct) {
|
||||
Result = get(Context, line.Val, column.Val, scope.Val, inlinedAt.Val);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseGenericDebugNode:
|
||||
/// ::= !GenericDebugNode(tag: 15, header: "...", operands: {...})
|
||||
bool LLParser::ParseGenericDebugNode(MDNode *&Result, bool IsDistinct) {
|
||||
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
||||
REQUIRED(tag, MDUnsignedField<uint32_t>, (0, ~0u >> 16)); \
|
||||
OPTIONAL(header, MDStringField, ); \
|
||||
OPTIONAL(operands, MDFieldList, );
|
||||
PARSE_MD_FIELDS();
|
||||
#undef VISIT_MD_FIELDS
|
||||
|
||||
Result = GET_OR_DISTINCT(GenericDebugNode,
|
||||
(Context, tag.Val, header.Val, operands.Val));
|
||||
return false;
|
||||
}
|
||||
#undef PARSE_MD_FIELD
|
||||
#undef NOP_FIELD
|
||||
#undef REQUIRE_FIELD
|
||||
|
@ -88,10 +88,11 @@ namespace llvm {
|
||||
|
||||
void assign(FieldTy Val) {
|
||||
Seen = true;
|
||||
this->Val = Val;
|
||||
this->Val = std::move(Val);
|
||||
}
|
||||
|
||||
explicit MDFieldImpl(FieldTy Default) : Val(Default), Seen(false) {}
|
||||
explicit MDFieldImpl(FieldTy Default)
|
||||
: Val(std::move(Default)), Seen(false) {}
|
||||
};
|
||||
template <class NumTy> struct MDUnsignedField : public MDFieldImpl<NumTy> {
|
||||
typedef typename MDUnsignedField::ImplTy ImplTy;
|
||||
@ -104,6 +105,12 @@ namespace llvm {
|
||||
struct MDField : public MDFieldImpl<Metadata *> {
|
||||
MDField() : ImplTy(nullptr) {}
|
||||
};
|
||||
struct MDStringField : public MDFieldImpl<std::string> {
|
||||
MDStringField() : ImplTy(std::string()) {}
|
||||
};
|
||||
struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> {
|
||||
MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {}
|
||||
};
|
||||
|
||||
class LLParser {
|
||||
public:
|
||||
@ -421,6 +428,8 @@ namespace llvm {
|
||||
bool ParseMDField(LocTy Loc, StringRef Name,
|
||||
MDUnsignedField<uint32_t> &Result);
|
||||
bool ParseMDField(LocTy Loc, StringRef Name, MDField &Result);
|
||||
bool ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result);
|
||||
bool ParseMDField(LocTy Loc, StringRef Name, MDFieldList &Result);
|
||||
template <class FieldTy> bool ParseMDField(StringRef Name, FieldTy &Result);
|
||||
template <class ParserTy>
|
||||
bool ParseMDFieldsImplBody(ParserTy parseField);
|
||||
@ -428,6 +437,7 @@ namespace llvm {
|
||||
bool ParseMDFieldsImpl(ParserTy parseField, LocTy &ClosingLoc);
|
||||
bool ParseSpecializedMDNode(MDNode *&N, bool IsDistinct = false);
|
||||
bool ParseMDLocation(MDNode *&Result, bool IsDistinct);
|
||||
bool ParseGenericDebugNode(MDNode *&Result, bool IsDistinct);
|
||||
|
||||
// Function Parsing.
|
||||
struct ArgInfo {
|
||||
|
@ -1181,6 +1181,17 @@ std::error_code BitcodeReader::ParseMetadata() {
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
|
||||
auto getMDString = [&](unsigned ID) -> MDString *{
|
||||
// This requires that the ID is not really a forward reference. In
|
||||
// particular, the MDString must already have been resolved.
|
||||
if (ID)
|
||||
return cast<MDString>(MDValueList.getValueFwdRef(ID - 1));
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
#define GET_OR_DISTINCT(CLASS, DISTINCT, ARGS) \
|
||||
(DISTINCT ? CLASS::getDistinct ARGS : CLASS::get ARGS)
|
||||
|
||||
// Read all the records.
|
||||
while (1) {
|
||||
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
|
||||
@ -1318,6 +1329,26 @@ std::error_code BitcodeReader::ParseMetadata() {
|
||||
NextMDValueNo++);
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_GENERIC_DEBUG: {
|
||||
if (Record.size() < 4)
|
||||
return Error("Invalid record");
|
||||
|
||||
unsigned Tag = Record[1];
|
||||
unsigned Version = Record[2];
|
||||
|
||||
if (Tag >= 1u << 16 || Version != 0)
|
||||
return Error("Invalid record");
|
||||
|
||||
auto *Header = getMDString(Record[3]);
|
||||
SmallVector<Metadata *, 8> DwarfOps;
|
||||
for (unsigned I = 4, E = Record.size(); I != E; ++I)
|
||||
DwarfOps.push_back(Record[I] ? MDValueList.getValueFwdRef(Record[I] - 1)
|
||||
: nullptr);
|
||||
MDValueList.AssignValue(GET_OR_DISTINCT(GenericDebugNode, Record[0],
|
||||
(Context, Tag, Header, DwarfOps)),
|
||||
NextMDValueNo++);
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_STRING: {
|
||||
std::string String(Record.begin(), Record.end());
|
||||
llvm::UpgradeMDStringConstant(String);
|
||||
@ -1339,6 +1370,7 @@ std::error_code BitcodeReader::ParseMetadata() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef GET_OR_DISTINCT
|
||||
}
|
||||
|
||||
/// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
|
||||
|
@ -792,10 +792,20 @@ static void WriteMDLocation(const MDLocation *N, const ValueEnumerator &VE,
|
||||
Record.clear();
|
||||
}
|
||||
|
||||
static void WriteGenericDebugNode(const GenericDebugNode *,
|
||||
const ValueEnumerator &, BitstreamWriter &,
|
||||
SmallVectorImpl<uint64_t> &, unsigned) {
|
||||
llvm_unreachable("unimplemented");
|
||||
static void WriteGenericDebugNode(const GenericDebugNode *N,
|
||||
const ValueEnumerator &VE,
|
||||
BitstreamWriter &Stream,
|
||||
SmallVectorImpl<uint64_t> &Record,
|
||||
unsigned Abbrev) {
|
||||
Record.push_back(N->isDistinct());
|
||||
Record.push_back(N->getTag());
|
||||
Record.push_back(0); // Per-tag version field; unused for now.
|
||||
|
||||
for (auto &I : N->operands())
|
||||
Record.push_back(VE.getMetadataOrNullID(I));
|
||||
|
||||
Stream.EmitRecord(bitc::METADATA_GENERIC_DEBUG, Record, Abbrev);
|
||||
Record.clear();
|
||||
}
|
||||
|
||||
static void WriteModuleMetadata(const Module *M,
|
||||
@ -833,6 +843,23 @@ static void WriteModuleMetadata(const Module *M,
|
||||
MDLocationAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
}
|
||||
|
||||
unsigned GenericDebugNodeAbbrev = 0;
|
||||
if (VE.hasGenericDebugNode()) {
|
||||
// Abbrev for METADATA_GENERIC_DEBUG.
|
||||
//
|
||||
// Assume the column is usually under 128, and always output the inlined-at
|
||||
// location (it's never more expensive than building an array size 1).
|
||||
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
||||
Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_GENERIC_DEBUG));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
|
||||
GenericDebugNodeAbbrev = Stream.EmitAbbrev(Abbv);
|
||||
}
|
||||
|
||||
unsigned NameAbbrev = 0;
|
||||
if (!M->named_metadata_empty()) {
|
||||
// Abbrev for METADATA_NAME.
|
||||
@ -844,7 +871,6 @@ static void WriteModuleMetadata(const Module *M,
|
||||
}
|
||||
|
||||
unsigned MDTupleAbbrev = 0;
|
||||
unsigned GenericDebugNodeAbbrev = 0;
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
for (const Metadata *MD : MDs) {
|
||||
if (const MDNode *N = dyn_cast<MDNode>(MD)) {
|
||||
|
@ -284,7 +284,7 @@ static bool isIntOrIntVectorValue(const std::pair<const Value*, unsigned> &V) {
|
||||
}
|
||||
|
||||
ValueEnumerator::ValueEnumerator(const Module &M)
|
||||
: HasMDString(false), HasMDLocation(false) {
|
||||
: HasMDString(false), HasMDLocation(false), HasGenericDebugNode(false) {
|
||||
if (shouldPreserveBitcodeUseListOrder())
|
||||
UseListOrders = predictUseListOrder(M);
|
||||
|
||||
@ -544,6 +544,7 @@ void ValueEnumerator::EnumerateMetadata(const Metadata *MD) {
|
||||
|
||||
HasMDString |= isa<MDString>(MD);
|
||||
HasMDLocation |= isa<MDLocation>(MD);
|
||||
HasGenericDebugNode |= isa<GenericDebugNode>(MD);
|
||||
|
||||
// Replace the dummy ID inserted above with the correct one. MDValueMap may
|
||||
// have changed by inserting operands, so we need a fresh lookup here.
|
||||
|
@ -66,6 +66,7 @@ private:
|
||||
MetadataMapType MDValueMap;
|
||||
bool HasMDString;
|
||||
bool HasMDLocation;
|
||||
bool HasGenericDebugNode;
|
||||
|
||||
typedef DenseMap<AttributeSet, unsigned> AttributeGroupMapType;
|
||||
AttributeGroupMapType AttributeGroupMap;
|
||||
@ -120,6 +121,7 @@ public:
|
||||
|
||||
bool hasMDString() const { return HasMDString; }
|
||||
bool hasMDLocation() const { return HasMDLocation; }
|
||||
bool hasGenericDebugNode() const { return HasGenericDebugNode; }
|
||||
|
||||
unsigned getTypeID(Type *T) const {
|
||||
TypeMapType::const_iterator I = TypeMap.find(T);
|
||||
|
@ -1286,10 +1286,32 @@ raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
|
||||
}
|
||||
} // end namespace
|
||||
|
||||
static void writeGenericDebugNode(raw_ostream &, const GenericDebugNode *,
|
||||
TypePrinting *, SlotTracker *,
|
||||
const Module *) {
|
||||
llvm_unreachable("Unimplemented write");
|
||||
static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N,
|
||||
TypePrinting *TypePrinter,
|
||||
SlotTracker *Machine, const Module *Context) {
|
||||
Out << "!GenericDebugNode(";
|
||||
FieldSeparator FS;
|
||||
// Always output the line, since 0 is a relevant and important value for it.
|
||||
Out << FS << "tag: " << N->getTag();
|
||||
if (!N->getHeader().empty()) {
|
||||
Out << FS << "header: \"";
|
||||
PrintEscapedString(N->getHeader(), Out);
|
||||
Out << "\"";
|
||||
}
|
||||
if (N->getNumDwarfOperands()) {
|
||||
Out << FS << "operands: {";
|
||||
FieldSeparator IFS;
|
||||
for (auto &I : N->dwarf_operands()) {
|
||||
Out << IFS;
|
||||
if (!I) {
|
||||
Out << "null";
|
||||
continue;
|
||||
}
|
||||
WriteAsOperandInternal(Out, I, TypePrinter, Machine, Context);
|
||||
}
|
||||
Out << "}";
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
|
||||
|
24
test/Assembler/generic-debug-node.ll
Normal file
24
test/Assembler/generic-debug-node.ll
Normal file
@ -0,0 +1,24 @@
|
||||
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
||||
; RUN: verify-uselistorder %s
|
||||
|
||||
; CHECK: !named = !{!0, !1, !1, !2, !2, !2, !2, !3, !4}
|
||||
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
|
||||
|
||||
; CHECK: !0 = !{}
|
||||
!0 = !{}
|
||||
|
||||
; CHECK-NEXT: !1 = !GenericDebugNode(tag: 3, header: "some\00header", operands: {!0, !2, !2})
|
||||
!1 = !GenericDebugNode(tag: 3, header: "some\00header", operands: {!0, !3, !4})
|
||||
!2 = !GenericDebugNode(tag: 3, header: "some\00header", operands: {!{}, !3, !4})
|
||||
|
||||
; CHECK-NEXT: !2 = !GenericDebugNode(tag: 3)
|
||||
!3 = !GenericDebugNode(tag: 3)
|
||||
!4 = !GenericDebugNode(tag: 3, header: "")
|
||||
!5 = !GenericDebugNode(tag: 3, operands: {})
|
||||
!6 = !GenericDebugNode(tag: 3, header: "", operands: {})
|
||||
|
||||
; CHECK-NEXT: !3 = distinct !GenericDebugNode(tag: 3)
|
||||
!7 = distinct !GenericDebugNode(tag: 3)
|
||||
|
||||
; CHECK-NEXT: !4 = !GenericDebugNode(tag: 65535)
|
||||
!8 = !GenericDebugNode(tag: 65535)
|
4
test/Assembler/invalid-generic-debug-node-tag-missing.ll
Normal file
4
test/Assembler/invalid-generic-debug-node-tag-missing.ll
Normal file
@ -0,0 +1,4 @@
|
||||
; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: <stdin>:[[@LINE+1]]:47: error: missing required field 'tag'
|
||||
!0 = !GenericDebugNode(header: "some\00header")
|
@ -0,0 +1,7 @@
|
||||
; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK-NOT: error
|
||||
!0 = !GenericDebugNode(tag: 65535)
|
||||
|
||||
; CHECK: <stdin>:[[@LINE+1]]:29: error: value for 'tag' too large, limit is 65535
|
||||
!1 = !GenericDebugNode(tag: 65536)
|
Loading…
Reference in New Issue
Block a user