AsmParser/Writer: Handle symbolic constants in DI 'flags:'
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Sat, 21 Feb 2015 01:02:18 +0000 (01:02 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Sat, 21 Feb 2015 01:02:18 +0000 (01:02 +0000)
Parse (and write) symbolic constants in debug info `flags:` fields.
This prevents a readability (and CHECK-ability) regression with the new
debug info hierarchy.

Old (well, current) assembly, with pretty-printing:

    !{!"...\\0016387", ...} ; ... [public] [rvalue reference]

Flags field without this change:

   !MDDerivedType(flags: 16387, ...)

Flags field with this change:

   !MDDerivedType(flags: DIFlagPublic | DIFlagRValueReference, ...)

As discussed in the review thread, this isn't a final state.  Most of
these flags correspond to `DW_AT_` symbolic constants, and we might
eventually want to support arbitrary attributes in some form.  However,
as it stands now, some of the flags correspond to other concepts (like
`FlagStaticMember`); until things are refactored this is the simplest
way to move forward without regressing assembly.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230111 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLToken.h
lib/IR/AsmWriter.cpp
test/Assembler/debug-info.ll
test/Assembler/invalid-mdsubroutinetype-missing-types.ll
test/Assembler/mdlocalvariable.ll
test/Assembler/mdsubprogram.ll
utils/vim/llvm.vim

index 656b16921820bd7b53ac49f03e052014b2f818c0..3bf090a4b33702c3953d573fc58f5762826ee5cb 100644 (file)
@@ -241,6 +241,7 @@ lltok::Kind LLLexer::LexToken() {
   case ')': return lltok::rparen;
   case ',': return lltok::comma;
   case '*': return lltok::star;
+  case '|': return lltok::bar;
   }
 }
 
@@ -760,6 +761,11 @@ lltok::Kind LLLexer::LexIdentifier() {
   DWKEYWORD(OP, DwarfOp);
 #undef DWKEYWORD
 
+  if (Keyword.startswith("DIFlag")) {
+    StrVal.assign(Keyword.begin(), Keyword.end());
+    return lltok::DIFlag;
+  }
+
   // 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') &&
index 28b8d22e5794a56a3b9861afb4edd235198bfa80..fa4653b30bca9157158f874a777dd057cda83b06 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/InlineAsm.h"
@@ -2957,6 +2958,10 @@ struct DwarfLangField : public MDUnsignedField {
   DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {}
 };
 
+struct DIFlagField : public MDUnsignedField {
+  DIFlagField() : MDUnsignedField(0, UINT32_MAX) {}
+};
+
 struct MDSignedField : public MDFieldImpl<int64_t> {
   int64_t Min;
   int64_t Max;
@@ -3086,6 +3091,43 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
   return false;
 }
 
+/// DIFlagField
+///  ::= uint32
+///  ::= DIFlagVector
+///  ::= DIFlagVector '|' DIFlagFwdDecl '|' uint32 '|' DIFlagPublic
+template <>
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name, DIFlagField &Result) {
+  assert(Result.Max == UINT32_MAX && "Expected only 32-bits");
+
+  // Parser for a single flag.
+  auto parseFlag = [&](unsigned &Val) {
+    if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned())
+      return ParseUInt32(Val);
+
+    if (Lex.getKind() != lltok::DIFlag)
+      return TokError("expected debug info flag");
+
+    Val = DIDescriptor::getFlag(Lex.getStrVal());
+    if (!Val)
+      return TokError(Twine("invalid debug info flag flag '") +
+                      Lex.getStrVal() + "'");
+    Lex.Lex();
+    return false;
+  };
+
+  // Parse the flags and combine them together.
+  unsigned Combined = 0;
+  do {
+    unsigned Val;
+    if (parseFlag(Val))
+      return true;
+    Combined |= Val;
+  } while (EatIfPresent(lltok::bar));
+
+  Result.assign(Combined);
+  return false;
+}
+
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name,
                             MDSignedField &Result) {
@@ -3330,7 +3372,7 @@ bool LLParser::ParseMDDerivedType(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX));                            \
   OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX));                           \
   OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX));                          \
-  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(extraData, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
@@ -3353,7 +3395,7 @@ bool LLParser::ParseMDCompositeType(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX));                            \
   OPTIONAL(align, MDUnsignedField, (0, UINT64_MAX));                           \
   OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX));                          \
-  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(elements, MDField, );                                               \
   OPTIONAL(runtimeLang, DwarfLangField, );                                     \
   OPTIONAL(vtableHolder, MDField, );                                           \
@@ -3372,7 +3414,7 @@ bool LLParser::ParseMDCompositeType(MDNode *&Result, bool IsDistinct) {
 
 bool LLParser::ParseMDSubroutineType(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
-  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(flags, DIFlagField, );                                              \
   REQUIRED(types, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
@@ -3449,7 +3491,7 @@ bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(containingType, MDField, );                                         \
   OPTIONAL(virtuality, DwarfVirtualityField, );                                \
   OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX));                    \
-  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(isOptimized, MDBoolField, );                                        \
   OPTIONAL(function, MDConstant, );                                            \
   OPTIONAL(templateParams, MDField, );                                         \
@@ -3585,7 +3627,7 @@ bool LLParser::ParseMDLocalVariable(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(line, LineField, );                                                 \
   OPTIONAL(type, MDField, );                                                   \
   OPTIONAL(arg, MDUnsignedField, (0, UINT8_MAX));                              \
-  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(inlinedAt, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
index 57218dafbb9ba4f8404e3ee93025810744996faf..a7aa17c37cc486aa7953ca1dcd5b663c26e46f00 100644 (file)
@@ -29,6 +29,7 @@ namespace lltok {
     less, greater,     // <  >
     lparen, rparen,    // (  )
     exclaim,           // !
+    bar,               // |
 
     kw_x,
     kw_true,    kw_false,
@@ -203,6 +204,7 @@ namespace lltok {
     DwarfVirtuality,   // DW_VIRTUALITY_foo
     DwarfLang,         // DW_LANG_foo
     DwarfOp,           // DW_OP_foo
+    DIFlag,            // DIFlagFoo
 
     // Type valued tokens (TyVal).
     Type,
index 47a1b5512a99496802efe191f18bceb8efef1a3a..104ad4f0be3d8449fc55aa8ce07092cff2cf6d33 100644 (file)
@@ -1275,14 +1275,15 @@ static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
 namespace {
 struct FieldSeparator {
   bool Skip;
-  FieldSeparator() : Skip(true) {}
+  const char *Sep;
+  FieldSeparator(const char *Sep = ", ") : Skip(true), Sep(Sep) {}
 };
 raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
   if (FS.Skip) {
     FS.Skip = false;
     return OS;
   }
-  return OS << ", ";
+  return OS << FS.Sep;
 }
 } // end namespace
 
@@ -1387,6 +1388,20 @@ static void writeMDBasicType(raw_ostream &Out, const MDBasicType *N,
   Out << ")";
 }
 
+static void writeDIFlags(raw_ostream &Out, unsigned Flags) {
+  SmallVector<unsigned, 8> SplitFlags;
+  unsigned Extra = DIDescriptor::splitFlags(Flags, SplitFlags);
+
+  FieldSeparator FS(" | ");
+  for (unsigned F : SplitFlags) {
+    const char *StringF = DIDescriptor::getFlagString(F);
+    assert(StringF && "Expected valid flag");
+    Out << FS << StringF;
+  }
+  if (Extra || SplitFlags.empty())
+    Out << FS << Extra;
+}
+
 static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N,
                                TypePrinting *TypePrinter, SlotTracker *Machine,
                                const Module *Context) {
@@ -1414,8 +1429,10 @@ static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N,
     Out << FS << "align: " << N->getAlignInBits();
   if (N->getOffsetInBits())
     Out << FS << "offset: " << N->getOffsetInBits();
-  if (N->getFlags())
-    Out << FS << "flags: " << N->getFlags();
+  if (auto Flags = N->getFlags()) {
+    Out << FS << "flags: ";
+    writeDIFlags(Out, Flags);
+  }
   if (N->getExtraData()) {
     Out << FS << "extraData: ";
     writeMetadataAsOperand(Out, N->getExtraData(), TypePrinter, Machine,
@@ -1454,8 +1471,10 @@ static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N,
     Out << FS << "align: " << N->getAlignInBits();
   if (N->getOffsetInBits())
     Out << FS << "offset: " << N->getOffsetInBits();
-  if (N->getFlags())
-    Out << FS << "flags: " << N->getFlags();
+  if (auto Flags = N->getFlags()) {
+    Out << FS << "flags: ";
+    writeDIFlags(Out, Flags);
+  }
   if (N->getElements()) {
     Out << FS << "elements: ";
     writeMetadataAsOperand(Out, N->getElements(), TypePrinter, Machine,
@@ -1489,8 +1508,10 @@ static void writeMDSubroutineType(raw_ostream &Out, const MDSubroutineType *N,
                                   SlotTracker *Machine, const Module *Context) {
   Out << "!MDSubroutineType(";
   FieldSeparator FS;
-  if (N->getFlags())
-    Out << FS << "flags: " << N->getFlags();
+  if (auto Flags = N->getFlags()) {
+    Out << FS << "flags: ";
+    writeDIFlags(Out, Flags);
+  }
   Out << FS << "types: ";
   writeMetadataAsOperand(Out, N->getTypeArray(), TypePrinter, Machine, Context);
   Out << ")";
@@ -1594,8 +1615,10 @@ static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N,
   }
   if (N->getVirtualIndex())
     Out << FS << "virtualIndex: " << N->getVirtualIndex();
-  if (N->getFlags())
-    Out << FS << "flags: " << N->getFlags();
+  if (auto Flags = N->getFlags()) {
+    Out << FS << "flags: ";
+    writeDIFlags(Out, Flags);
+  }
   Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false");
   if (N->getFunction()) {
     Out << FS << "function: ";
@@ -1764,8 +1787,10 @@ static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N,
   }
   if (N->getTag() == dwarf::DW_TAG_arg_variable || N->getArg())
     Out << FS << "arg: " << N->getArg();
-  if (N->getFlags())
-    Out << FS << "flags: " << N->getFlags();
+  if (auto Flags = N->getFlags()) {
+    Out << FS << "flags: ";
+    writeDIFlags(Out, Flags);
+  }
   if (N->getInlinedAt()) {
     Out << FS << "inlinedAt: ";
     writeMetadataAsOperand(Out, N->getInlinedAt(), TypePrinter, Machine,
index 9b808bd2355f2e84b893ced325364975bcf03aac..435b892594c57582dc4c0adfbd5ae7bc2c8669bf 100644 (file)
 !15 = !MDDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32)
 
 ; CHECK-NEXT: !14 = !MDCompositeType(tag: DW_TAG_structure_type, name: "MyType", file: !10, line: 2, size: 32, align: 32, identifier: "MangledMyType")
-; CHECK-NEXT: !15 = distinct !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !10, line: 3, scope: !14, size: 128, align: 32, offset: 64, flags: 3, elements: !16, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !15, templateParams: !18, identifier: "MangledBase")
+; CHECK-NEXT: !15 = distinct !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !10, line: 3, scope: !14, size: 128, align: 32, offset: 64, flags: DIFlagPublic, elements: !16, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !15, templateParams: !18, identifier: "MangledBase")
 ; CHECK-NEXT: !16 = !{!17}
-; CHECK-NEXT: !17 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !10, line: 4, scope: !15, baseType: !6, size: 32, align: 32, offset: 32, flags: 3)
+; CHECK-NEXT: !17 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !10, line: 4, scope: !15, baseType: !6, size: 32, align: 32, offset: 32, flags: DIFlagPublic)
 ; CHECK-NEXT: !18 = !{!6}
-; CHECK-NEXT: !19 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !10, line: 3, scope: !14, baseType: !15, size: 128, align: 32, offset: 64, flags: 3, elements: !20, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !15, templateParams: !18, identifier: "MangledBase")
+; CHECK-NEXT: !19 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !10, line: 3, scope: !14, baseType: !15, size: 128, align: 32, offset: 64, flags: DIFlagPublic, elements: !20, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !15, templateParams: !18, identifier: "MangledBase")
 ; CHECK-NEXT: !20 = !{!21}
 ; CHECK-NEXT: !21 = !MDDerivedType(tag: DW_TAG_inheritance, scope: !19, baseType: !15)
 ; CHECK-NEXT: !22 = !MDDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !6, size: 32, align: 32, extraData: !15)
 ; CHECK-NEXT: !23 = !MDCompositeType(tag: DW_TAG_structure_type)
 ; CHECK-NEXT: !24 = !MDCompositeType(tag: DW_TAG_structure_type, runtimeLang: DW_LANG_Cobol85)
 !16 = !MDCompositeType(tag: DW_TAG_structure_type, name: "MyType", file: !12, line: 2, size: 32, align: 32, identifier: "MangledMyType")
-!17 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !12, line: 3, scope: !16, size: 128, align: 32, offset: 64, flags: 3, elements: !18, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !17, templateParams: !20, identifier: "MangledBase")
+!17 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !12, line: 3, scope: !16, size: 128, align: 32, offset: 64, flags: DIFlagPublic, elements: !18, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !17, templateParams: !20, identifier: "MangledBase")
 !18 = !{!19}
-!19 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !12, line: 4, scope: !17, baseType: !7, size: 32, align: 32, offset: 32, flags: 3)
+!19 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !12, line: 4, scope: !17, baseType: !7, size: 32, align: 32, offset: 32, flags: DIFlagPublic)
 !20 = !{!7}
-!21 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !12, line: 3, scope: !16, baseType: !17, size: 128, align: 32, offset: 64, flags: 3, elements: !22, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !17, templateParams: !20, identifier: "MangledBase")
+!21 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !12, line: 3, scope: !16, baseType: !17, size: 128, align: 32, offset: 64, flags: DIFlagPublic, elements: !22, runtimeLang: DW_LANG_C_plus_plus_11, vtableHolder: !17, templateParams: !20, identifier: "MangledBase")
 !22 = !{!23}
 !23 = !MDDerivedType(tag: DW_TAG_inheritance, scope: !21, baseType: !17)
 !24 = !MDDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !7, size: 32, align: 32, extraData: !17)
@@ -64,9 +64,9 @@
 !26 = !MDCompositeType(tag: DW_TAG_structure_type, runtimeLang: 6)
 
 ; !25 = !{!7, !7}
-; !26 = !MDSubroutineType(flags: 7, types: !25)
+; !26 = !MDSubroutineType(flags: DIFlagPublic | DIFlagStaticMember, types: !25)
 ; !27 = !MDSubroutineType(types: !25)
 !27 = !{!7, !7}
-!28 = !MDSubroutineType(flags: 7, types: !27)
+!28 = !MDSubroutineType(flags: DIFlagPublic | DIFlagStaticMember, types: !27)
 !29 = !MDSubroutineType(flags: 0, types: !27)
 !30 = !MDSubroutineType(types: !27)
index 6c976edc828620e5b02229b1ecb639b4acad1368..7342417d1ca37fb79bda91aa6e39740c6d945106 100644 (file)
@@ -1,4 +1,4 @@
 ; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
 
-; CHECK: [[@LINE+1]]:33: error: missing required field 'types'
-!29 = !MDSubroutineType(flags: 7)
+; CHECK: [[@LINE+1]]:65: error: missing required field 'types'
+!29 = !MDSubroutineType(flags: DIFlagPublic | DIFlagStaticMember)
index 00e350dbf6f53a9660e0fc95dcf0076c01631ce4..7a4185fd6ee636dd7ddfdc8257746ebcdb5e1c55 100644 (file)
 !3 = distinct !{}
 !4 = distinct !{}
 
-; CHECK: !5 = !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo", file: !2, line: 7, type: !3, arg: 3, flags: 8, inlinedAt: !4)
-; CHECK: !6 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: !0, name: "foo", file: !2, line: 7, type: !3, flags: 8, inlinedAt: !4)
+; CHECK: !5 = !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo", file: !2, line: 7, type: !3, arg: 3, flags: DIFlagArtificial, inlinedAt: !4)
+; CHECK: !6 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: !0, name: "foo", file: !2, line: 7, type: !3, flags: DIFlagArtificial, inlinedAt: !4)
 !5 = !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !0, name: "foo",
                       file: !2, line: 7, type: !3, arg: 3,
-                      flags: 8, inlinedAt: !4)
+                      flags: DIFlagArtificial, inlinedAt: !4)
 !6 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: !0, name: "foo",
-                      file: !2, line: 7, type: !3, flags: 8, inlinedAt: !4)
+                      file: !2, line: 7, type: !3, flags: DIFlagArtificial, inlinedAt: !4)
 
 ; CHECK: !7 = !MDLocalVariable(tag: DW_TAG_arg_variable, scope: null, name: "", arg: 0)
 ; CHECK: !8 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: null, name: "")
index 7915a29fa37bd0969495968f41d437b3e715e164..aecfefc3c8f7197aa72336a26c9066691dabbf2c 100644 (file)
@@ -15,12 +15,12 @@ declare void @_Z3foov()
 !6 = distinct !{}
 !7 = distinct !{}
 
-; CHECK: !8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov", file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, flags: 11, isOptimized: true, function: void ()* @_Z3foov, templateParams: !5, declaration: !6, variables: !7)
+; CHECK: !8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov", file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @_Z3foov, templateParams: !5, declaration: !6, variables: !7)
 !8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov",
                    file: !2, line: 7, type: !3, isLocal: true,
                    isDefinition: false, scopeLine: 8, containingType: !4,
                    virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10,
-                   flags: 11, isOptimized: true, function: void ()* @_Z3foov,
+                   flags: DIFlagPrototyped, isOptimized: true, function: void ()* @_Z3foov,
                    templateParams: !5, declaration: !6, variables: !7)
 
 ; CHECK: !9 = !MDSubprogram(scope: null, name: "bar", isLocal: false, isDefinition: true, isOptimized: false)
index 6b4b8bbd12b28d1aaf5850de74eaa16add65698c..913d0f5f1c3b2f0dae97fb6d1c69a850e3194572 100644 (file)
@@ -82,6 +82,7 @@ syn match   llvmConstant /\<DW_ATE_[a-zA-Z_]\+\>/
 syn match   llvmConstant /\<DW_OP_[a-zA-Z0-9_]\+\>/
 syn match   llvmConstant /\<DW_LANG_[a-zA-Z0-9_]\+\>/
 syn match   llvmConstant /\<DW_VIRTUALITY_[a-z_]\+\>/
+syn match   llvmConstant /\<DIFlag[A-Za-z]\+\>/
 
 " Syntax-highlight dejagnu test commands.
 syn match  llvmSpecialComment /;\s*RUN:.*$/