From 6adbfa381528b1042c7f86b0aa59308485509560 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Tue, 3 Feb 2015 21:54:14 +0000 Subject: [PATCH] IR: Assembly and bitcode for GenericDebugNode git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228041 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Bitcode/LLVMBitCodes.h | 3 +- lib/AsmParser/LLParser.cpp | 36 +++++++++++++++++++ lib/AsmParser/LLParser.h | 14 ++++++-- lib/Bitcode/Reader/BitcodeReader.cpp | 32 +++++++++++++++++ lib/Bitcode/Writer/BitcodeWriter.cpp | 36 ++++++++++++++++--- lib/Bitcode/Writer/ValueEnumerator.cpp | 3 +- lib/Bitcode/Writer/ValueEnumerator.h | 2 ++ lib/IR/AsmWriter.cpp | 30 +++++++++++++--- test/Assembler/generic-debug-node.ll | 24 +++++++++++++ .../invalid-generic-debug-node-tag-missing.ll | 4 +++ ...invalid-generic-debug-node-tag-overflow.ll | 7 ++++ 11 files changed, 178 insertions(+), 13 deletions(-) create mode 100644 test/Assembler/generic-debug-node.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-missing.ll create mode 100644 test/Assembler/invalid-generic-debug-node-tag-overflow.ll 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 MDs; + if (ParseMDNodeVector(MDs)) + return true; + + Result.assign(std::move(MDs)); + return false; +} + template 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, (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 struct MDUnsignedField : public MDFieldImpl { typedef typename MDUnsignedField::ImplTy ImplTy; @@ -104,6 +105,12 @@ namespace llvm { struct MDField : public MDFieldImpl { MDField() : ImplTy(nullptr) {} }; + struct MDStringField : public MDFieldImpl { + MDStringField() : ImplTy(std::string()) {} + }; + struct MDFieldList : public MDFieldImpl> { + MDFieldList() : ImplTy(SmallVector()) {} + }; class LLParser { public: @@ -421,6 +428,8 @@ namespace llvm { bool ParseMDField(LocTy Loc, StringRef Name, MDUnsignedField &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 bool ParseMDField(StringRef Name, FieldTy &Result); template 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 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(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 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 &, unsigned) { - llvm_unreachable("unimplemented"); +static void WriteGenericDebugNode(const GenericDebugNode *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &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 Record; for (const Metadata *MD : MDs) { if (const MDNode *N = dyn_cast(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 &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(MD); HasMDLocation |= isa(MD); + HasGenericDebugNode |= isa(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 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: :[[@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: :[[@LINE+1]]:29: error: value for 'tag' too large, limit is 65535 +!1 = !GenericDebugNode(tag: 65536) -- 2.34.1