summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-03 21:54:14 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2015-02-03 21:54:14 +0000
commit6adbfa381528b1042c7f86b0aa59308485509560 (patch)
tree03924140ded5a6cbd47aee1b6bd65e5be8b18a01
parent90eef42c8e2ff4bcc883826b6aea1659fcdba916 (diff)
IR: Assembly and bitcode for GenericDebugNode
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228041 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h3
-rw-r--r--lib/AsmParser/LLParser.cpp36
-rw-r--r--lib/AsmParser/LLParser.h14
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp32
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp36
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp3
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.h2
-rw-r--r--lib/IR/AsmWriter.cpp30
-rw-r--r--test/Assembler/generic-debug-node.ll24
-rw-r--r--test/Assembler/invalid-generic-debug-node-tag-missing.ll4
-rw-r--r--test/Assembler/invalid-generic-debug-node-tag-overflow.ll7
11 files changed, 178 insertions, 13 deletions
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 043ecd3d65d..e5f7f7ec88f 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -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
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 2ae869a7f77..8ef8d664457 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -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
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 235e2642ef2..6e410d05cd2 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -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 {
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index d2ee73f61cc..b4831d921cf 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -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
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 2f1c74ae01d..3aa1ef9a707 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -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)) {
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index 2a7916b6da0..24b077bbcef 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -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.
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index 043c4925b39..ab61584baad 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -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);
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index d52ac87c983..ba1c5260074 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -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,
diff --git a/test/Assembler/generic-debug-node.ll b/test/Assembler/generic-debug-node.ll
new file mode 100644
index 00000000000..e8b169170ac
--- /dev/null
+++ b/test/Assembler/generic-debug-node.ll
@@ -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)
diff --git a/test/Assembler/invalid-generic-debug-node-tag-missing.ll b/test/Assembler/invalid-generic-debug-node-tag-missing.ll
new file mode 100644
index 00000000000..5372cbb0880
--- /dev/null
+++ b/test/Assembler/invalid-generic-debug-node-tag-missing.ll
@@ -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")
diff --git a/test/Assembler/invalid-generic-debug-node-tag-overflow.ll b/test/Assembler/invalid-generic-debug-node-tag-overflow.ll
new file mode 100644
index 00000000000..1722caa0a73
--- /dev/null
+++ b/test/Assembler/invalid-generic-debug-node-tag-overflow.ll
@@ -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)