diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 1a85852d5f8..eb16608ad1e 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -738,6 +738,12 @@ lltok::Kind LLLexer::LexIdentifier() { INSTKEYWORD(landingpad, LandingPad); #undef INSTKEYWORD + if (Len >= strlen("DW_TAG_") && + !memcmp(StartChar, "DW_TAG_", strlen("DW_TAG_"))) { + StrVal.assign(StartChar, CurPtr); + return lltok::DwarfTag; + } + // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by // the CFE to avoid forcing it to deal with 64-bit numbers. if ((TokStart[0] == 'u' || TokStart[0] == 's') && diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 8ef8d664457..1f5087c152c 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" @@ -2936,6 +2937,28 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, return false; } +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DwarfTagField &Result) { + if (Lex.getKind() == lltok::APSInt) + return ParseMDField(Loc, Name, + static_cast &>(Result)); + + if (Result.Seen) + return Error(Loc, + "field '" + Name + "' cannot be specified more than once"); + + if (Lex.getKind() != lltok::DwarfTag) + return TokError("expected DWARF tag"); + + unsigned Tag = dwarf::getTag(Lex.getStrVal()); + if (Tag == dwarf::DW_TAG_invalid) + return TokError("invalid DWARF tag" + Twine(" '") + Lex.getStrVal() + "'"); + assert(Tag < 1u << 16 && "Expected valid DWARF tag"); + + Result.assign(Tag); + Lex.Lex(); + return false; +} + bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { Metadata *MD; if (ParseMetadata(MD, nullptr)) @@ -3056,7 +3079,7 @@ bool LLParser::ParseMDLocation(MDNode *&Result, bool IsDistinct) { /// ::= !GenericDebugNode(tag: 15, header: "...", operands: {...}) bool LLParser::ParseGenericDebugNode(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(tag, MDUnsignedField, (0, ~0u >> 16)); \ + REQUIRED(tag, DwarfTagField, ); \ OPTIONAL(header, MDStringField, ); \ OPTIONAL(operands, MDFieldList, ); PARSE_MD_FIELDS(); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 6e410d05cd2..240fb608138 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -102,6 +102,9 @@ namespace llvm { NumTy Max = std::numeric_limits::max()) : ImplTy(Default), Max(Max) {} }; + struct DwarfTagField : public MDUnsignedField { + DwarfTagField() : MDUnsignedField(0, ~0u >> 16) {} + }; struct MDField : public MDFieldImpl { MDField() : ImplTy(nullptr) {} }; @@ -427,6 +430,7 @@ namespace llvm { bool ParseMDField(LocTy Loc, StringRef Name, MDUnsignedField &Result); + bool ParseMDField(LocTy Loc, StringRef Name, DwarfTagField &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); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 5b3463bf4ab..4e5af1e89bd 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -198,6 +198,7 @@ namespace lltok { LocalVar, // %foo %"foo" MetadataVar, // !foo StringConstant, // "foo" + DwarfTag, // DW_TAG_foo (includes "DW_TAG_") // Type valued tokens (TyVal). Type, diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index ba1c5260074..46f26c579ac 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1291,8 +1291,11 @@ static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N, 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(); + Out << FS << "tag: "; + if (const char *Tag = dwarf::TagString(N->getTag())) + Out << Tag; + else + Out << N->getTag(); if (!N->getHeader().empty()) { Out << FS << "header: \""; PrintEscapedString(N->getHeader(), Out); diff --git a/test/Assembler/generic-debug-node.ll b/test/Assembler/generic-debug-node.ll index e8b169170ac..cb7222b043d 100644 --- a/test/Assembler/generic-debug-node.ll +++ b/test/Assembler/generic-debug-node.ll @@ -1,24 +1,27 @@ ; 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: !named = !{!0, !1, !1, !2, !2, !2, !2, !3, !4, !2} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} ; CHECK: !0 = !{} !0 = !{} -; CHECK-NEXT: !1 = !GenericDebugNode(tag: 3, header: "some\00header", operands: {!0, !2, !2}) +; CHECK-NEXT: !1 = !GenericDebugNode(tag: DW_TAG_entry_point, 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) +; CHECK-NEXT: !2 = !GenericDebugNode(tag: DW_TAG_entry_point) !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) +; CHECK-NEXT: !3 = distinct !GenericDebugNode(tag: DW_TAG_entry_point) !7 = distinct !GenericDebugNode(tag: 3) ; CHECK-NEXT: !4 = !GenericDebugNode(tag: 65535) !8 = !GenericDebugNode(tag: 65535) + +; CHECK-NOT: ! +!9 = !GenericDebugNode(tag: DW_TAG_entry_point) diff --git a/test/Assembler/invalid-generic-debug-node-tag-bad.ll b/test/Assembler/invalid-generic-debug-node-tag-bad.ll new file mode 100644 index 00000000000..98c10b6a878 --- /dev/null +++ b/test/Assembler/invalid-generic-debug-node-tag-bad.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:29: error: invalid DWARF tag 'DW_TAG_badtag' +!0 = !GenericDebugNode(tag: DW_TAG_badtag) diff --git a/test/Assembler/invalid-generic-debug-node-tag-wrong-type.ll b/test/Assembler/invalid-generic-debug-node-tag-wrong-type.ll new file mode 100644 index 00000000000..fca24a70bf0 --- /dev/null +++ b/test/Assembler/invalid-generic-debug-node-tag-wrong-type.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:29: error: expected DWARF tag +!0 = !GenericDebugNode(tag: "string") diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index b7411c3cd31..57c71331105 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -77,6 +77,7 @@ syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/ syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/ syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/ syn match llvmType /!\zs\a\+\ze\s*(/ +syn match llvmConstant /\/ " Syntax-highlight dejagnu test commands. syn match llvmSpecialComment /;\s*RUN:.*$/