From 3020664b33491f4022ef29c829e39e16cd06040d Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 2 Jul 2021 15:45:15 -0700 Subject: [PATCH] Revert "[DebugInfo] Enforce implicit constraints on `distinct` MDNodes" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8cd35ad854ab4458fd509447359066ea3578b494. It breaks `TestMembersAndLocalsWithSameName.py` on GreenDragon and Mikael Holmén points out in D104827 that bitcode files created with the patch cannot be parsed with binaries built before it. --- docs/LangRef.rst | 60 ++++++------- docs/SourceLevelDebugging.rst | 81 +++++++++--------- include/llvm/AsmParser/LLParser.h | 3 +- include/llvm/IR/Metadata.def | 79 ++--------------- lib/AsmParser/LLParser.cpp | 69 ++++++--------- lib/Bitcode/Reader/MetadataLoader.cpp | 10 +-- lib/Bitcode/Writer/BitcodeWriter.cpp | 17 +--- lib/CodeGen/MIRParser/MIParser.cpp | 2 - lib/IR/AsmWriter.cpp | 56 ++++++------ lib/IR/DebugInfoMetadata.cpp | 2 - lib/IR/LLVMContextImpl.cpp | 2 - lib/IR/LLVMContextImpl.h | 1 - lib/IR/Metadata.cpp | 3 - .../invalid-diarglist-outside-function.ll | 4 - .../invalid-diexpression-distinct.ll | 4 - .../DIExpression-is-distinct-upgrade.ll | 16 ---- .../DIExpression-is-distinct-upgrade.ll.bc | Bin 1424 -> 0 bytes 17 files changed, 134 insertions(+), 275 deletions(-) delete mode 100644 test/Assembler/invalid-diarglist-outside-function.ll delete mode 100644 test/Assembler/invalid-diexpression-distinct.ll delete mode 100644 test/Bitcode/DIExpression-is-distinct-upgrade.ll delete mode 100644 test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc diff --git a/docs/LangRef.rst b/docs/LangRef.rst index d87f791077e..98a18e8d093 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -5102,22 +5102,21 @@ metadata nodes are related to debug info. DICompileUnit """"""""""""" -``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. +``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. .. code-block:: text - !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) + !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) Compile unit descriptors provide the root scope for objects declared in a specific compilation unit. File descriptors are defined using this scope. These @@ -5528,14 +5527,12 @@ DIExpression """""""""""" ``DIExpression`` nodes represent expressions that are inspired by the DWARF -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. +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. The current supported opcode vocabulary is limited: @@ -5613,23 +5610,23 @@ The current supported opcode vocabulary is limited: IR for "*ptr = 4;" -------------- - call void @llvm.dbg.value(metadata i32 4, metadata !17, - metadata !DIExpression(DW_OP_LLVM_implicit_pointer))) + call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !20) !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 !DIExpression(DW_OP_LLVM_implicit_pointer, - DW_OP_LLVM_implicit_pointer))) + call void @llvm.dbg.value(metadata i32 4, metadata !17, metadata !21) !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 @@ -5670,13 +5667,12 @@ valid debug intrinsic. DIArgList """""""""""" -``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 +``DIArgList`` nodes hold a list of constant or SSA value references. These 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. +``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. .. code-block:: text diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst index 69b7f35fc7b..652eccb33f0 100644 --- a/docs/SourceLevelDebugging.rst +++ b/docs/SourceLevelDebugging.rst @@ -291,17 +291,17 @@ Compiled to LLVM, this function would be represented like this: %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 !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 + 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 } ; Function Attrs: nounwind readnone @@ -327,17 +327,18 @@ Compiled to LLVM, this function would be represented like this: !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 = !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) + !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) This example illustrates a few important details about LLVM debugging @@ -348,21 +349,21 @@ variable definitions, and the code used to implement the function. .. code-block:: llvm - call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !DIExpression()), !dbg !13 + call void @llvm.dbg.declare(metadata i32* %X, metadata !11, metadata !13), !dbg !14 ; [debug line = 2:7] [debug variable = X] The first intrinsic ``%llvm.dbg.declare`` encodes debugging information for the -variable ``X``. The metadata ``!dbg !13`` attached to the intrinsic provides +variable ``X``. The metadata ``!dbg !14`` attached to the intrinsic provides scope information for the variable ``X``. .. code-block:: text - !13 = !DILocation(line: 2, column: 9, scope: !4) + !14 = !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 ``!13`` is metadata providing `location information +Here ``!14`` 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 @@ -372,20 +373,20 @@ Now lets take another example. .. code-block:: llvm - call void @llvm.dbg.declare(metadata i32* %Z, metadata !16, metadata !DIExpression()), !dbg !18 + call void @llvm.dbg.declare(metadata i32* %Z, metadata !17, metadata !13), !dbg !19 ; [debug line = 5:9] [debug variable = Z] The third intrinsic ``%llvm.dbg.declare`` encodes debugging information for -variable ``Z``. The metadata ``!dbg !18`` attached to the intrinsic provides +variable ``Z``. The metadata ``!dbg !19`` attached to the intrinsic provides scope information for the variable ``Z``. .. code-block:: text - !17 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) - !18 = !DILocation(line: 5, column: 11, scope: !17) + !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) + !19 = !DILocation(line: 5, column: 11, scope: !18) -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 +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 inside of subprogram ``!4`` described above. The scope information attached with each instruction provides a straightforward @@ -799,14 +800,14 @@ presents several difficulties: br label %exit, !dbg !26 truebr: - 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 + 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 %value1 = add i32 %input, 1 br label %bb1 falsebr: - 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 + 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 %value = add i32 %input, 2 br label %bb1 @@ -817,7 +818,7 @@ presents several difficulties: Here the difficulties are: * The control flow is roughly the opposite of basic block order -* The value of the ``!22`` variable merges into ``%bb1``, but there is no PHI +* The value of the ``!23`` variable merges into ``%bb1``, but there is no PHI node As mentioned above, the ``llvm.dbg.value`` intrinsics essentially form an @@ -830,9 +831,9 @@ location, which would lead to a large number of debugging intrinsics being generated. Examining the example above, variable ``!30`` is assigned ``%input`` on both -conditional paths through the function, while ``!22`` is assigned differing +conditional paths through the function, while ``!23`` is assigned differing constant values on either path. Where control flow merges in ``%bb1`` we would -want ``!30`` to keep its location (``%input``), but ``!22`` to become undefined +want ``!30`` to keep its location (``%input``), but ``!23`` 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 @@ -851,7 +852,7 @@ DbgEntityHistoryCalculator) to build a map of each instruction to every 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 ``!22`` should not flow "down" into the ``%exit`` block. +of variable ``!23`` should not flow "down" into the ``%exit`` block. .. _ccxx_frontend: diff --git a/include/llvm/AsmParser/LLParser.h b/include/llvm/AsmParser/LLParser.h index 8b26b655289..e12278d21b0 100644 --- a/include/llvm/AsmParser/LLParser.h +++ b/include/llvm/AsmParser/LLParser.h @@ -533,8 +533,7 @@ namespace llvm { template bool parseMDFieldsImplBody(ParserTy ParseField); template bool parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc); - bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false, - LocTy DistinctLoc = LocTy()); + bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ bool parse##CLASS(MDNode *&Result, bool IsDistinct); diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index fdef80724de..bbf349e6b50 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -8,39 +8,12 @@ // // 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_LEAF_UNIQUED || \ - defined HANDLE_MDNODE_LEAF_DISTINCT || defined HANDLE_MDNODE_BRANCH || \ + defined HANDLE_MDNODE_LEAF_UNIQUABLE || 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*" @@ -61,7 +34,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 @@ -74,47 +47,11 @@ #endif #endif -// 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. +// Handler for 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) @@ -143,7 +80,7 @@ HANDLE_METADATA_LEAF(DistinctMDOperandPlaceholder) HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF_UNIQUABLE(MDTuple) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocation) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIExpression) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIExpression) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariableExpression) HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(GenericDINode) @@ -156,7 +93,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIDerivedType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICompositeType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubroutineType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIFile) -HANDLE_SPECIALIZED_MDNODE_LEAF_DISTINCT(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) @@ -177,7 +114,7 @@ HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) -HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUED(DIArgList) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIArgList) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIStringType) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange) @@ -186,11 +123,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGenericSubrange) #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/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 678bf822fe0..ecf264aa337 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -740,29 +740,27 @@ bool LLParser::parseNamedMetadata() { return true; NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name); - - 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)); + 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)); return parseToken(lltok::rbrace, "expected end of metadata node"); } @@ -782,10 +780,9 @@ bool LLParser::parseStandaloneMetadata() { 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, DistinctLoc)) + if (parseSpecializedMDNode(Init, IsDistinct)) return true; } else if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDTuple(Init, IsDistinct)) @@ -4681,25 +4678,12 @@ bool LLParser::parseMDField(StringRef Name, FieldTy &Result) { return parseMDField(Loc, Name, Result); } -bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct, - LocTy DistinctLoc) { +bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) { assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); -#define HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(CLASS) \ +#define HANDLE_SPECIALIZED_MDNODE_LEAF(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"); @@ -5043,6 +5027,9 @@ bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) { /// 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)); \ @@ -5406,7 +5393,7 @@ bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) { } bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct) { - return tokError("!DIArgList cannot appear outside of a function"); + return parseDIArgList(Result, IsDistinct, nullptr); } /// ParseDIArgList: /// ::= !DIArgList(i32 7, i64 %0) diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp index a2ad4a42079..8493eb7a28b 100644 --- a/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/lib/Bitcode/Reader/MetadataLoader.cpp @@ -555,7 +555,7 @@ class MetadataLoader::MetadataLoaderImpl { } /// Upgrade the expression from previous versions. - Error upgradeDIExpression(uint64_t FromVersion, bool &IsDistinct, + Error upgradeDIExpression(uint64_t FromVersion, MutableArrayRef &Expr, SmallVectorImpl &Buffer) { auto N = Expr.size(); @@ -629,9 +629,6 @@ class MetadataLoader::MetadataLoaderImpl { LLVM_FALLTHROUGH; } case 3: - IsDistinct = false; - LLVM_FALLTHROUGH; - case 4: // Up-to-date! break; } @@ -1984,12 +1981,9 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( auto Elts = MutableArrayRef(Record).slice(1); SmallVector Buffer; - if (Error Err = upgradeDIExpression(Version, IsDistinct, Elts, Buffer)) + if (Error Err = upgradeDIExpression(Version, Elts, Buffer)) return Err; - if (IsDistinct) - return error("Invalid record"); - MetadataList.assignValue( GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo); NextMetadataNo++; diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 1ad55e264ac..bdb973e8e42 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1758,6 +1758,7 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N, 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())); @@ -2008,7 +2009,7 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev) { Record.reserve(N->getElements().size() + 1); - const uint64_t Version = 4 << 1; + const uint64_t Version = 3 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); Record.append(N->elements_begin(), N->elements_end()); @@ -2153,20 +2154,6 @@ void ModuleBitcodeWriter::writeMetadataRecords( 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/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index fb3c34a9bc4..34e1f9225d4 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -1182,7 +1182,6 @@ bool MIParser::parseStandaloneMDNode(MDNode *&Node) { 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)) { @@ -2326,7 +2325,6 @@ bool MIParser::parseMetadataOperand(MachineOperand &Dest) { 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/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index d62f8f40b57..66c93b6e6af 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1235,11 +1235,10 @@ void SlotTracker::CreateFunctionSlot(const Value *V) { void SlotTracker::CreateMetadataSlot(const MDNode *N) { assert(N && "Can't insert a null Value into SlotTracker!"); - // Don't make slots for uniqued nodes. We just print them inline everywhere. -#define HANDLE_MDNODE_LEAF_UNIQUED(CLASS) \ - if (isa(N)) \ + // Don't make slots for DIExpressions or DIArgLists. We just print them inline + // everywhere. + if (isa(N) || isa(N)) return; -#include "llvm/IR/Metadata.def" unsigned DestSlot = mdnNext; if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) @@ -2357,7 +2356,9 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N, static void writeDIArgList(raw_ostream &Out, const DIArgList *N, TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + const Module *Context, bool FromValue = false) { + assert(FromValue && + "Unexpected DIArgList metadata outside of value argument"); Out << "!DIArgList("; FieldSeparator FS; MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); @@ -2515,16 +2516,16 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context, bool FromValue) { - 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; \ + // 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; } -#include "llvm/IR/Metadata.def" if (const MDNode *N = dyn_cast(MD)) { std::unique_ptr MachineStorage; @@ -2555,6 +2556,9 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, 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); @@ -3443,17 +3447,15 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { if (i) Out << ", "; - // Write UNIQUED nodes inline. + // Write DIExpressions 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"); -#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" + if (auto *Expr = dyn_cast(Op)) { + writeDIExpression(Out, Expr, nullptr, nullptr, nullptr); + continue; + } int Slot = Machine.getMetadataSlot(Op); if (Slot == -1) @@ -4710,18 +4712,12 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, TypePrinting TypePrinter(M); - WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M); + WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M, + /* FromValue */ true); auto *N = dyn_cast(&MD); - if (OnlyAsOperand || !N) { + if (OnlyAsOperand || !N || isa(MD) || isa(MD)) 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/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index eff01bffe76..7b0dab799e1 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -1053,7 +1053,6 @@ DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, 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)); } @@ -1584,7 +1583,6 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType, 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/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 2533ce83600..99819602c54 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -60,7 +60,6 @@ LLVMContextImpl::~LLVMContextImpl() { #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. @@ -75,7 +74,6 @@ LLVMContextImpl::~LLVMContextImpl() { #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/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 5caa8f60b69..2ae23fdc95a 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -1381,7 +1381,6 @@ public: #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/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 9ac388835be..4f87ef53776 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -672,7 +672,6 @@ MDNode *MDNode::replaceWithPermanentImpl() { #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" } @@ -813,7 +812,6 @@ MDNode *MDNode::uniquify() { 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" } } @@ -826,7 +824,6 @@ void MDNode::eraseFromStore() { 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/test/Assembler/invalid-diarglist-outside-function.ll b/test/Assembler/invalid-diarglist-outside-function.ll deleted file mode 100644 index 351cd0bc7b4..00000000000 --- a/test/Assembler/invalid-diarglist-outside-function.ll +++ /dev/null @@ -1,4 +0,0 @@ -; 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/test/Assembler/invalid-diexpression-distinct.ll b/test/Assembler/invalid-diexpression-distinct.ll deleted file mode 100644 index 96628e37479..00000000000 --- a/test/Assembler/invalid-diexpression-distinct.ll +++ /dev/null @@ -1,4 +0,0 @@ -; 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/test/Bitcode/DIExpression-is-distinct-upgrade.ll b/test/Bitcode/DIExpression-is-distinct-upgrade.ll deleted file mode 100644 index d888e9a9eb8..00000000000 --- a/test/Bitcode/DIExpression-is-distinct-upgrade.ll +++ /dev/null @@ -1,16 +0,0 @@ -; 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/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc b/test/Bitcode/DIExpression-is-distinct-upgrade.ll.bc deleted file mode 100644 index 088e1a4b448857eeb5a8bf26cf17b88146e57788..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1424 zcmXw34@?_n6#q&KcVpePBh3bKciy#ZHdEke8T7n18C*BJh_Q=i!GvXPY0Iiuj?zJ4 zYFY}p&UH&6BsK=)h|@(g4NHh(LJUxb9XXb5Q8Ob!D&1h(5wf9K;$r;D^pbn;-sQXZ z=lA=)YviYw4{87?1OT{{OvNj2eCK`l?}=B-(-l^kp%BnY05}-{I}2z~0MG1!Hxkhe zHKY|si_`{oST>;CSBRF8igT_odbpr*cxR(kZP1v|(wB=3+L%q4qjlC2F|KYHE^w#O zs~U%qhN#&z%zKsspcs1i8A`d10Q&igBuejtrtCT8;H88^ z>u#YcT>Xbi(WDN@!83Fd_D6W}>u*kOJska~su9gDu z0rW;RjL&6ouSRBx@uq=PyfKXQhLEmgr}7?9Jy2s?Va%v(Bxh%c8)LYaDcn95Etlk$ zG;fK^Em9~R6p%A0(rXh10qGOu-62t+#4>3&mP=q6M&)NztDD%S9W$!uh-DhTLld)3 z(#xFXrlQLZk)G3K%UH+vpg4rVJd#D7)~noz%;N0dH6EI=F|Zsq_@&6kgDr5T93LP3@P6*PxW|zzqQ78aVdJ5x4SXZF}R%qeV z^r1pE3K%)#VSr@d!D1J1+ru(DFe+n15<`hvU1Z0?;Q7U`76+ShlIMzlBz!%V4?lfy z{>p_frEBrZT)SV>@F7eFK8L$QL%*{)pof}7`kI9##32RQXK$wZ@8R=fyVe`>D+A$r z%JrVwRR^|ahZ0g{^FmUs*|Dwha0KbqZ!0_`LU!`}HVdOE(}aw>6t#?`3f_Xtf-hz8 zB?`|v^L9N#&N}g%V|e;0DY9GYr+bb_=1Wm-6bf5zxfnG=ktb3RPS8n#?f;qqQ)}}` zx#|xZ>*{I_dOW5&w${zovaUL&zNXG(G@4jr zYrVIgsb$;SyWg%3db)zujlN)Ohuc$aJ$g7K1Uy}NrYe11m2O{G(C2RrR-P8x0#3K5 Ks=Ym53j7Ogd-B=<