diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -5094,21 +5094,22 @@ DICompileUnit """"""""""""" -``DICompileUnit`` nodes represent a compile unit. The ``enums:``, -``retainedTypes:``, ``globals:``, ``imports:`` and ``macros:`` fields are tuples -containing the debug info to be emitted along with the compile unit, regardless -of code optimizations (some nodes are only emitted if there are references to -them from instructions). The ``debugInfoForProfiling:`` field is a boolean -indicating whether or not line-table discriminators are updated to provide -more-accurate debug info for profiling results. +``DICompileUnit`` nodes represent a compile unit. ``DICompileUnit`` nodes must +be ``distinct``. The ``enums:``, ``retainedTypes:``, ``globals:``, ``imports:`` +and ``macros:`` fields are tuples containing the debug info to be emitted along +with the compile unit, regardless of code optimizations (some nodes are only +emitted if there are references to them from instructions). The +``debugInfoForProfiling:`` field is a boolean indicating whether or not +line-table discriminators are updated to provide more-accurate debug info for +profiling results. .. code-block:: text - !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", - isOptimized: true, flags: "-O2", runtimeVersion: 2, - splitDebugFilename: "abc.debug", emissionKind: FullDebug, - enums: !2, retainedTypes: !3, globals: !4, imports: !5, - macros: !6, dwoId: 0x0abcd) + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", + isOptimized: true, flags: "-O2", runtimeVersion: 2, + splitDebugFilename: "abc.debug", emissionKind: FullDebug, + enums: !2, retainedTypes: !3, globals: !4, imports: !5, + macros: !6, dwoId: 0x0abcd) Compile unit descriptors provide the root scope for objects declared in a specific compilation unit. File descriptors are defined using this scope. These @@ -5519,12 +5520,14 @@ """""""""""" ``DIExpression`` nodes represent expressions that are inspired by the DWARF -expression language. They are used in :ref:`debug intrinsics` -(such as ``llvm.dbg.declare`` and ``llvm.dbg.value``) to describe how the -referenced LLVM variable relates to the source language variable. Debug -intrinsics are interpreted left-to-right: start by pushing the value/address -operand of the intrinsic onto a stack, then repeatedly push and evaluate -opcodes from the DIExpression until the final variable description is produced. +expression language. ``DIExpression`` nodes must not be ``distinct``, and are +canonically printed inline at each use. They are used in :ref:`debug +intrinsics` (such as ``llvm.dbg.declare`` and +``llvm.dbg.value``) to describe how the referenced LLVM variable relates to the +source language variable. Debug intrinsics are interpreted left-to-right: start +by pushing the value/address operand of the intrinsic onto a stack, then +repeatedly push and evaluate opcodes from the DIExpression until the final +variable description is produced. The current supported opcode vocabulary is limited: @@ -5602,23 +5605,23 @@ IR for "*ptr = 4;" -------------- - call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !20) + call void @llvm.dbg.value(metadata i32 4, metadata !17, + metadata !DIExpression(DW_OP_LLVM_implicit_pointer))) !17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5, type: !18) !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64) !19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !20 = !DIExpression(DW_OP_LLVM_implicit_pointer)) IR for "**ptr = 4;" -------------- - call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !21) + call void @llvm.dbg.value(metadata i32 4, metadata !17, + metadata !DIExpression(DW_OP_LLVM_implicit_pointer, + DW_OP_LLVM_implicit_pointer))) !17 = !DILocalVariable(name: "ptr1", scope: !12, file: !3, line: 5, type: !18) !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64) !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64) !20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) - !21 = !DIExpression(DW_OP_LLVM_implicit_pointer, - DW_OP_LLVM_implicit_pointer)) DWARF specifies three kinds of simple location descriptions: Register, memory, and implicit location descriptions. Note that a location description is @@ -5659,12 +5662,13 @@ DIArgList """""""""""" -``DIArgList`` nodes hold a list of constant or SSA value references. These are -used in :ref:`debug intrinsics` (currently only in +``DIArgList`` nodes hold a list of constant or SSA value references. +``DIArgList`` must not be ``distinct``, must only be used as an argument to a +function call, and must appear inline at each use. ``DIArgList`` may refer to +function-local values of the containing function. ``DIArgList`` nodes are used +in :ref:`debug intrinsics` (currently only in ``llvm.dbg.value``) in combination with a ``DIExpression`` that uses the -``DW_OP_LLVM_arg`` operator. Because a DIArgList may refer to local values -within a function, it must only be used as a function argument, must always be -inlined, and cannot appear in named metadata. +``DW_OP_LLVM_arg`` operator. .. code-block:: text diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst --- a/llvm/docs/SourceLevelDebugging.rst +++ b/llvm/docs/SourceLevelDebugging.rst @@ -291,17 +291,17 @@ %X = alloca i32, align 4 %Y = alloca i32, align 4 %Z = alloca i32, align 4 - call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14 - store i32 21, i32* %X, align 4, !dbg !14 - call void @llvm.dbg.declare(metadata i32* %Y, metadata !15, metadata !13), !dbg !16 - store i32 22, i32* %Y, align 4, !dbg !16 - call void @llvm.dbg.declare(metadata i32* %Z, metadata !17, metadata !13), !dbg !19 - store i32 23, i32* %Z, align 4, !dbg !19 - %0 = load i32, i32* %X, align 4, !dbg !20 - store i32 %0, i32* %Z, align 4, !dbg !21 - %1 = load i32, i32* %Y, align 4, !dbg !22 - store i32 %1, i32* %X, align 4, !dbg !23 - ret void, !dbg !24 + call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !DIExpression()), !dbg !13 + store i32 21, i32* %X, align 4, !dbg !13 + call void @llvm.dbg.declare(metadata i32* %Y, metadata !14, metadata !DIExpression()), !dbg !15 + store i32 22, i32* %Y, align 4, !dbg !15 + call void @llvm.dbg.declare(metadata i32* %Z, metadata !16, metadata !DIExpression()), !dbg !18 + store i32 23, i32* %Z, align 4, !dbg !18 + %0 = load i32, i32* %X, align 4, !dbg !19 + store i32 %0, i32* %Z, align 4, !dbg !20 + %1 = load i32, i32* %Y, align 4, !dbg !21 + store i32 %1, i32* %X, align 4, !dbg !22 + ret void, !dbg !23 } ; Function Attrs: nounwind readnone @@ -327,18 +327,17 @@ !10 = !{!"clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)"} !11 = !DILocalVariable(name: "X", scope: !4, file: !1, line: 2, type: !12) !12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) - !13 = !DIExpression() - !14 = !DILocation(line: 2, column: 9, scope: !4) - !15 = !DILocalVariable(name: "Y", scope: !4, file: !1, line: 3, type: !12) - !16 = !DILocation(line: 3, column: 9, scope: !4) - !17 = !DILocalVariable(name: "Z", scope: !18, file: !1, line: 5, type: !12) - !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) - !19 = !DILocation(line: 5, column: 11, scope: !18) - !20 = !DILocation(line: 6, column: 11, scope: !18) - !21 = !DILocation(line: 6, column: 9, scope: !18) - !22 = !DILocation(line: 8, column: 9, scope: !4) - !23 = !DILocation(line: 8, column: 7, scope: !4) - !24 = !DILocation(line: 9, column: 3, scope: !4) + !13 = !DILocation(line: 2, column: 9, scope: !4) + !14 = !DILocalVariable(name: "Y", scope: !4, file: !1, line: 3, type: !12) + !15 = !DILocation(line: 3, column: 9, scope: !4) + !16 = !DILocalVariable(name: "Z", scope: !17, file: !1, line: 5, type: !12) + !17 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) + !18 = !DILocation(line: 5, column: 11, scope: !17) + !19 = !DILocation(line: 6, column: 11, scope: !17) + !20 = !DILocation(line: 6, column: 9, scope: !17) + !21 = !DILocation(line: 8, column: 9, scope: !4) + !22 = !DILocation(line: 8, column: 7, scope: !4) + !23 = !DILocation(line: 9, column: 3, scope: !4) This example illustrates a few important details about LLVM debugging @@ -349,21 +348,21 @@ .. code-block:: llvm - call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14 + call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !DIExpression()), !dbg !13 ; [debug line = 2:7] [debug variable = X] The first intrinsic ``%llvm.dbg.declare`` encodes debugging information for the -variable ``X``. The metadata ``!dbg !14`` attached to the intrinsic provides +variable ``X``. The metadata ``!dbg !13`` attached to the intrinsic provides scope information for the variable ``X``. .. code-block:: text - !14 = !DILocation(line: 2, column: 9, scope: !4) + !13 = !DILocation(line: 2, column: 9, scope: !4) !4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) -Here ``!14`` is metadata providing `location information +Here ``!13`` is metadata providing `location information `_. In this example, scope is encoded by ``!4``, a `subprogram descriptor `_. This way the location information attached to the intrinsics indicates that the variable ``X`` is @@ -373,20 +372,20 @@ .. code-block:: llvm - call void @llvm.dbg.declare(metadata i32* %Z, metadata !17, metadata !13), !dbg !19 + call void @llvm.dbg.declare(metadata i32* %Z, metadata !16, metadata !DIExpression()), !dbg !18 ; [debug line = 5:9] [debug variable = Z] The third intrinsic ``%llvm.dbg.declare`` encodes debugging information for -variable ``Z``. The metadata ``!dbg !19`` attached to the intrinsic provides +variable ``Z``. The metadata ``!dbg !18`` attached to the intrinsic provides scope information for the variable ``Z``. .. code-block:: text - !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) - !19 = !DILocation(line: 5, column: 11, scope: !18) + !17 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) + !18 = !DILocation(line: 5, column: 11, scope: !17) -Here ``!19`` indicates that ``Z`` is declared at line number 5 and column -number 11 inside of lexical scope ``!18``. The lexical scope itself resides +Here ``!18`` indicates that ``Z`` is declared at line number 5 and column +number 11 inside of lexical scope ``!17``. The lexical scope itself resides inside of subprogram ``!4`` described above. The scope information attached with each instruction provides a straightforward @@ -800,14 +799,14 @@ br label %exit, !dbg !26 truebr: - call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !24 - call void @llvm.dbg.value(metadata i32 1, metadata !23, metadata !DIExpression()), !dbg !24 + call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !23 + call void @llvm.dbg.value(metadata i32 1, metadata !22, metadata !DIExpression()), !dbg !23 %value1 = add i32 %input, 1 br label %bb1 falsebr: - call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !24 - call void @llvm.dbg.value(metadata i32 2, metadata !23, metadata !DIExpression()), !dbg !24 + call void @llvm.dbg.value(metadata i32 %input, metadata !30, metadata !DIExpression()), !dbg !23 + call void @llvm.dbg.value(metadata i32 2, metadata !22, metadata !DIExpression()), !dbg !23 %value = add i32 %input, 2 br label %bb1 @@ -818,7 +817,7 @@ Here the difficulties are: * The control flow is roughly the opposite of basic block order -* The value of the ``!23`` variable merges into ``%bb1``, but there is no PHI +* The value of the ``!22`` variable merges into ``%bb1``, but there is no PHI node As mentioned above, the ``llvm.dbg.value`` intrinsics essentially form an @@ -831,9 +830,9 @@ generated. Examining the example above, variable ``!30`` is assigned ``%input`` on both -conditional paths through the function, while ``!23`` is assigned differing +conditional paths through the function, while ``!22`` is assigned differing constant values on either path. Where control flow merges in ``%bb1`` we would -want ``!30`` to keep its location (``%input``), but ``!23`` to become undefined +want ``!30`` to keep its location (``%input``), but ``!22`` to become undefined as we cannot determine at runtime what value it should have in %bb1 without inserting a PHI node. mem2reg does not insert the PHI node to avoid changing codegen when debugging is enabled, and does not insert the other dbg.values @@ -852,7 +851,7 @@ valid variable location, without the need to consider control flow. From the example above, it is otherwise difficult to determine that the location of variable ``!30`` should flow "up" into block ``%bb1``, but that the location -of variable ``!23`` should not flow "down" into the ``%exit`` block. +of variable ``!22`` should not flow "down" into the ``%exit`` block. .. _ccxx_frontend: diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -532,7 +532,8 @@ template bool parseMDFieldsImplBody(ParserTy ParseField); template bool parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc); - bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false); + bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false, + LocTy DistinctLoc = LocTy()); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ bool parse##CLASS(MDNode *&Result, bool IsDistinct); diff --git a/llvm/include/llvm/IR/Metadata.def b/llvm/include/llvm/IR/Metadata.def --- a/llvm/include/llvm/IR/Metadata.def +++ b/llvm/include/llvm/IR/Metadata.def @@ -8,12 +8,39 @@ // // Macros for running through all types of metadata. // +// Definitions for terms used to describe metadata include: +// +// * BRANCH: refers to an "abstract" metadata kind, which exists only in the +// C++ class hierarchy. These cannot appear directly in IR/bitcode. +// * LEAF: refers to a "concrete" metadata kind. These can appear directly in +// IR/bitcode. +// * SPECIALIZED: refers to non-MDTuple MDNodes, i.e. those that use the +// syntax "!CLASS(...)" in IR. +// * UNIQUABLE: refers to nodes which can use uniqued, distinct, or temporary +// storage without any restrictions. +// * UNIQUED: refers to nodes which must use uniqued or temporary storage. +// * DISTINCT: refers to nodes which must use distinct or temporary storage. +// +// In LLVM IR, UNIQUABLE and DISTINCT nodes must be referred to by MDNode ID, +// as in `!0`, whereas UNIQUED nodes canonically appear inline at each use, as +// in `DIExpression(...)`. This is because `distinct` nodes maintain their +// identity irrespective of contents, making the inline syntax ambiguous in +// some cases. +// +// Note: UNIQUABLE, UNIQUED, and DISTINCT are mutually exclusive. For example, +// code which intends to consider all nodes which can use uniqued storage must +// consider both UNIQUABLE and UNIQUED nodes. +// //===----------------------------------------------------------------------===// #if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ defined HANDLE_METADATA_BRANCH || defined HANDLE_MDNODE_LEAF || \ - defined HANDLE_MDNODE_LEAF_UNIQUABLE || defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_MDNODE_LEAF_UNIQUABLE || \ + defined HANDLE_MDNODE_LEAF_UNIQUED || \ + defined HANDLE_MDNODE_LEAF_DISTINCT || defined HANDLE_MDNODE_BRANCH || \ defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED || \ + defined HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT || \ defined HANDLE_SPECIALIZED_MDNODE_LEAF || \ defined HANDLE_SPECIALIZED_MDNODE_BRANCH) #error "Missing macro definition of HANDLE_METADATA*" @@ -34,7 +61,7 @@ #define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) #endif -// Handler for specialized and uniquable leaf nodes under MDNode. Defers to +// Handler for specialized and uniquable leaf nodes under MDNode. Defers to // HANDLE_MDNODE_LEAF_UNIQUABLE if it's defined, otherwise to // HANDLE_SPECIALIZED_MDNODE_LEAF. #ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE @@ -47,11 +74,47 @@ #endif #endif -// Handler for leaf nodes under MDNode. +// Handler for specialized and always-uniqued leaf nodes under MDNode. Defers to +// HANDLE_MDNODE_LEAF_UNIQUED if it's defined, otherwise to +// HANDLE_SPECIALIZED_MDNODE_LEAF. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED +#ifdef HANDLE_MDNODE_LEAF_UNIQUED +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS) \ + HANDLE_MDNODE_LEAF_UNIQUED(CLASS) +#else +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS) \ + HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) +#endif +#endif + +// Handler for specialized and always-distinct leaf nodes under MDNode. Defers +// to HANDLE_MDNODE_LEAF_DISTINCT if it's defined, otherwise to +// HANDLE_SPECIALIZED_MDNODE_LEAF. +#ifndef HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT +#ifdef HANDLE_MDNODE_LEAF_DISTINCT +#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS) \ + HANDLE_MDNODE_LEAF_DISTINCT(CLASS) +#else +#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS) \ + HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) +#endif +#endif + +// Handler for uniquable leaf nodes under MDNode. #ifndef HANDLE_MDNODE_LEAF_UNIQUABLE #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) HANDLE_MDNODE_LEAF(CLASS) #endif +// Handler for uniqued leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF_UNIQUED +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + +// Handler for distinct leaf nodes under MDNode. +#ifndef HANDLE_MDNODE_LEAF_DISTINCT +#define HANDLE_MDNODE_LEAF_DISTINCT(CLASS) HANDLE_MDNODE_LEAF(CLASS) +#endif + // Handler for leaf nodes under MDNode. #ifndef HANDLE_MDNODE_LEAF #define HANDLE_MDNODE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) @@ -80,7 +143,7 @@ HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIExpression) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression) HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode) @@ -93,7 +156,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile) -HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(DICompileUnit) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) @@ -114,7 +177,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIArgList) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIArgList) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange) @@ -123,7 +186,11 @@ #undef HANDLE_METADATA_BRANCH #undef HANDLE_MDNODE_LEAF #undef HANDLE_MDNODE_LEAF_UNIQUABLE +#undef HANDLE_MDNODE_LEAF_UNIQUED +#undef HANDLE_MDNODE_LEAF_DISTINCT #undef HANDLE_MDNODE_BRANCH #undef HANDLE_SPECIALIZED_MDNODE_LEAF #undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE +#undef HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED +#undef HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT #undef HANDLE_SPECIALIZED_MDNODE_BRANCH diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -740,27 +740,29 @@ return true; NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name); - if (Lex.getKind() != lltok::rbrace) - do { - MDNode *N = nullptr; - // parse DIExpressions inline as a special case. They are still MDNodes, - // so they can still appear in named metadata. Remove this logic if they - // become plain Metadata. - if (Lex.getKind() == lltok::MetadataVar && - Lex.getStrVal() == "DIExpression") { - if (parseDIExpression(N, /*IsDistinct=*/false)) - return true; - // DIArgLists should only appear inline in a function, as they may - // contain LocalAsMetadata arguments which require a function context. - } else if (Lex.getKind() == lltok::MetadataVar && - Lex.getStrVal() == "DIArgList") { - return tokError("found DIArgList outside of function"); - } else if (parseToken(lltok::exclaim, "Expected '!' here") || - parseMDNodeID(N)) { - return true; - } - NMD->addOperand(N); - } while (EatIfPresent(lltok::comma)); + + if (Lex.getKind() == lltok::rbrace) { + Lex.Lex(); + return false; + } + + do { + MDNode *N = nullptr; + // Parse uniqued MDNodes inline as a special case. +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + if (Lex.getKind() == lltok::MetadataVar && Lex.getStrVal() == #CLASS) { \ + if (parse##CLASS(N, /*IsDistinct=*/false)) \ + return true; \ + NMD->addOperand(N); \ + continue; \ + } +#include "llvm/IR/Metadata.def" + // Parse all other MDNodes as an MDNodeID. + if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDNodeID(N)) { + return true; + } + NMD->addOperand(N); + } while (EatIfPresent(lltok::comma)); return parseToken(lltok::rbrace, "expected end of metadata node"); } @@ -780,9 +782,10 @@ if (Lex.getKind() == lltok::Type) return tokError("unexpected type in metadata definition"); + auto DistinctLoc = Lex.getLoc(); bool IsDistinct = EatIfPresent(lltok::kw_distinct); if (Lex.getKind() == lltok::MetadataVar) { - if (parseSpecializedMDNode(Init, IsDistinct)) + if (parseSpecializedMDNode(Init, IsDistinct, DistinctLoc)) return true; } else if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDTuple(Init, IsDistinct)) @@ -4641,12 +4644,25 @@ return parseMDField(Loc, Name, Result); } -bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) { +bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct, + LocTy DistinctLoc) { assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); -#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ if (Lex.getStrVal() == #CLASS) \ return parse##CLASS(N, IsDistinct); +#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(CLASS) \ + if (Lex.getStrVal() == #CLASS) { \ + if (IsDistinct) \ + return error(DistinctLoc, "'distinct' not allowed for !" #CLASS); \ + return parse##CLASS(N, IsDistinct); \ + } +#define HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(CLASS) \ + if (Lex.getStrVal() == #CLASS) { \ + if (!IsDistinct) \ + return error(DistinctLoc, "missing 'distinct', required for !" #CLASS); \ + return parse##CLASS(N, IsDistinct); \ + } #include "llvm/IR/Metadata.def" return tokError("expected metadata type"); @@ -4990,9 +5006,6 @@ /// globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd, /// sysroot: "/", sdk: "MacOSX.sdk") bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) { - if (!IsDistinct) - return Lex.Error("missing 'distinct', required for !DICompileUnit"); - #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(language, DwarfLangField, ); \ REQUIRED(file, MDField, (/* AllowNull */ false)); \ @@ -5356,7 +5369,7 @@ } bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct) { - return parseDIArgList(Result, IsDistinct, nullptr); + return tokError("!DIArgList cannot appear outside of a function"); } /// ParseDIArgList: /// ::= !DIArgList(i32 7, i64 %0) diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -555,7 +555,7 @@ } /// Upgrade the expression from previous versions. - Error upgradeDIExpression(uint64_t FromVersion, + Error upgradeDIExpression(uint64_t FromVersion, bool &IsDistinct, MutableArrayRef &Expr, SmallVectorImpl &Buffer) { auto N = Expr.size(); @@ -629,6 +629,9 @@ LLVM_FALLTHROUGH; } case 3: + IsDistinct = false; + LLVM_FALLTHROUGH; + case 4: // Up-to-date! break; } @@ -1981,9 +1984,12 @@ auto Elts = MutableArrayRef(Record).slice(1); SmallVector Buffer; - if (Error Err = upgradeDIExpression(Version, Elts, Buffer)) + if (Error Err = upgradeDIExpression(Version, IsDistinct, Elts, Buffer)) return Err; + if (IsDistinct) + return error("Invalid record"); + MetadataList.assignValue( GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo); NextMetadataNo++; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1758,7 +1758,6 @@ void ModuleBitcodeWriter::writeDICompileUnit(const DICompileUnit *N, SmallVectorImpl &Record, unsigned Abbrev) { - assert(N->isDistinct() && "Expected distinct compile units"); Record.push_back(/* IsDistinct */ true); Record.push_back(N->getSourceLanguage()); Record.push_back(VE.getMetadataOrNullID(N->getFile())); @@ -2009,7 +2008,7 @@ SmallVectorImpl &Record, unsigned Abbrev) { Record.reserve(N->getElements().size() + 1); - const uint64_t Version = 3 << 1; + const uint64_t Version = 4 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); Record.append(N->elements_begin(), N->elements_end()); @@ -2154,6 +2153,20 @@ if (const MDNode *N = dyn_cast(MD)) { assert(N->isResolved() && "Expected forward references to be resolved"); +#ifndef NDEBUG + switch (N->getMetadataID()) { +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + case Metadata::CLASS##Kind: \ + assert(!N->isDistinct() && "Expected non-distinct " #CLASS); \ + break; +#define HANDLE_MDNODE_LEAF_DISTINCT(CLASS) \ + case Metadata::CLASS##Kind: \ + assert(N->isDistinct() && "Expected distinct " #CLASS); \ + break; +#include "llvm/IR/Metadata.def" + } +#endif + switch (N->getMetadataID()) { default: llvm_unreachable("Invalid MDNode subclass"); diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1159,6 +1159,7 @@ if (parseMDNode(Node)) return true; } else if (Token.is(MIToken::md_diexpr)) { + // FIXME: This should be driven off of the UNIQUED property in Metadata.def if (parseDIExpression(Node)) return true; } else if (Token.is(MIToken::md_dilocation)) { @@ -2175,6 +2176,7 @@ if (parseMDNode(Node)) return true; } else if (Token.is(MIToken::md_diexpr)) { + // FIXME: This should be driven off of the UNIQUED property in Metadata.def if (parseDIExpression(Node)) return true; } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1233,10 +1233,11 @@ void SlotTracker::CreateMetadataSlot(const MDNode *N) { assert(N && "Can't insert a null Value into SlotTracker!"); - // Don't make slots for DIExpressions or DIArgLists. We just print them inline - // everywhere. - if (isa(N) || isa(N)) + // Don't make slots for uniqued nodes. We just print them inline everywhere. +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + if (isa(N)) \ return; +#include "llvm/IR/Metadata.def" unsigned DestSlot = mdnNext; if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) @@ -2354,9 +2355,7 @@ static void writeDIArgList(raw_ostream &Out, const DIArgList *N, TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context, bool FromValue = false) { - assert(FromValue && - "Unexpected DIArgList metadata outside of value argument"); + const Module *Context) { Out << "!DIArgList("; FieldSeparator FS; MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); @@ -2514,16 +2513,16 @@ TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context, bool FromValue) { - // Write DIExpressions and DIArgLists inline when used as a value. Improves - // readability of debug info intrinsics. - if (const DIExpression *Expr = dyn_cast(MD)) { - writeDIExpression(Out, Expr, TypePrinter, Machine, Context); - return; - } - if (const DIArgList *ArgList = dyn_cast(MD)) { - writeDIArgList(Out, ArgList, TypePrinter, Machine, Context, FromValue); - return; + assert((FromValue || !(isa(MD) || isa(MD))) && + "Unexpected function-local metadata outside of value argument"); + + // Write uniqued MDNodes inline when used as a value. +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + if (const CLASS *N = dyn_cast(MD)) { \ + write##CLASS(Out, N, TypePrinter, Machine, Context); \ + return; \ } +#include "llvm/IR/Metadata.def" if (const MDNode *N = dyn_cast(MD)) { std::unique_ptr MachineStorage; @@ -2554,9 +2553,6 @@ auto *V = cast(MD); assert(TypePrinter && "TypePrinter required for metadata values"); - assert((FromValue || !isa(V)) && - "Unexpected function-local metadata outside of value argument"); - TypePrinter->print(V->getValue()->getType(), Out); Out << ' '; WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context); @@ -3445,15 +3441,17 @@ if (i) Out << ", "; - // Write DIExpressions inline. + // Write UNIQUED nodes inline. // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose. MDNode *Op = NMD->getOperand(i); assert(!isa(Op) && "DIArgLists should not appear in NamedMDNodes"); - if (auto *Expr = dyn_cast(Op)) { - writeDIExpression(Out, Expr, nullptr, nullptr, nullptr); - continue; - } +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + if (auto *N = dyn_cast(Op)) { \ + write##CLASS(Out, N, nullptr, nullptr, nullptr); \ + continue; \ + } +#include "llvm/IR/Metadata.def" int Slot = Machine.getMetadataSlot(Op); if (Slot == -1) @@ -4710,12 +4708,18 @@ TypePrinting TypePrinter(M); - WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M, - /* FromValue */ true); + WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M); auto *N = dyn_cast(&MD); - if (OnlyAsOperand || !N || isa(MD) || isa(MD)) + if (OnlyAsOperand || !N) { + return; + } + // Uniqued MDNodes are always treated as if OnlyAsOperand, as they are + // printed inline. +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ + if (isa(MD)) \ return; +#include "llvm/IR/Metadata.def" OS << " = "; WriteMDNodeBodyInternal(OS, N, &TypePrinter, MST.getMachine(), M); diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1053,6 +1053,7 @@ DIExpression *DIExpression::getImpl(LLVMContext &Context, ArrayRef Elements, StorageType Storage, bool ShouldCreate) { + assert(Storage != Distinct && "DIExpression cannot be distinct"); DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements)); DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements)); } @@ -1583,6 +1584,7 @@ DIArgList *DIArgList::getImpl(LLVMContext &Context, ArrayRef Args, StorageType Storage, bool ShouldCreate) { + assert(Storage != Distinct && "DIArgList cannot be distinct"); DEFINE_GETIMPL_LOOKUP(DIArgList, (Args)); DEFINE_GETIMPL_STORE_NO_OPS(DIArgList, (Args)); } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1381,6 +1381,7 @@ #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ DenseSet CLASS##s; +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" // Optional map for looking up composite types by identifier. diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -60,6 +60,7 @@ #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ for (auto *I : CLASS##s) \ I->dropAllReferences(); +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" // Also drop references that come from the Value bridges. @@ -74,6 +75,7 @@ #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ for (CLASS * I : CLASS##s) \ delete I; +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" // Free the constants. diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -672,6 +672,7 @@ #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ case CLASS##Kind: \ break; +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" } @@ -812,6 +813,7 @@ dispatchRecalculateHash(SubclassThis, ShouldRecalculateHash); \ return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s); \ } +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" } } @@ -824,6 +826,7 @@ case CLASS##Kind: \ getContext().pImpl->CLASS##s.erase(cast(this)); \ break; +#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) #include "llvm/IR/Metadata.def" } } diff --git a/llvm/test/Assembler/invalid-diarglist-outside-function.ll b/llvm/test/Assembler/invalid-diarglist-outside-function.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/invalid-diarglist-outside-function.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:6: error: !DIArgList cannot appear outside of a function +!0 = !DIArgList() diff --git a/llvm/test/Assembler/invalid-diexpression-distinct.ll b/llvm/test/Assembler/invalid-diexpression-distinct.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/invalid-diexpression-distinct.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:6: error: 'distinct' not allowed for !DIExpression +!0 = distinct !DIExpression() diff --git a/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll @@ -0,0 +1,16 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!8, !9} + +!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true) +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) +!2 = !DIFile(filename: "a.c", directory: "/") +!3 = !{} +!4 = !{!7} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +; CHECK: expr: !DIExpression() +!6 = distinct !DIExpression() +!7 = !DIGlobalVariableExpression(var: !0, expr: !6) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc b/llvm/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@