diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -4821,6 +4821,9 @@ metadata !DIExpression(DW_OP_LLVM_arg0, DW_OP_LLVM_arg1, DW_OP_plus))`` ``DW_OP_LLVM_arg0`` represents ``DILocalVariable("x")`` and ``DW_OP_LLVM_arg1`` represents ``DILocalVariable("y")``. +- ``DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0 N`` can only appear at the + beginning of a ``DIExpression``, and it specifies the value of variable + represented by first operand at offset N. DWARF specifies three kinds of simple location descriptions: Register, memory, and implicit location descriptions. Note that a location description is diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h --- a/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -121,6 +121,7 @@ DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata. DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata. DW_OP_LLVM_entry_value = 0x1003, ///< Only used in LLVM metadata. + DW_OP_LLVM_implicit_pointer = 0x1004, ///< Only used in LLVM metadata. }; enum TypeKind : uint8_t { diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp --- a/llvm/lib/BinaryFormat/Dwarf.cpp +++ b/llvm/lib/BinaryFormat/Dwarf.cpp @@ -151,6 +151,8 @@ return "DW_OP_LLVM_tag_offset"; case DW_OP_LLVM_entry_value: return "DW_OP_LLVM_entry_value"; + case DW_OP_LLVM_implicit_pointer: + return "DW_OP_LLVM_implicit_pointer"; } } @@ -163,6 +165,7 @@ .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment) .Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset) .Case("DW_OP_LLVM_entry_value", DW_OP_LLVM_entry_value) + .Case("DW_OP_LLVM_implicit_pointer", DW_OP_LLVM_implicit_pointer) .Default(0); } 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 @@ -2150,6 +2150,9 @@ if (I->getOp() == dwarf::DW_OP_LLVM_convert) { Out << FS << I->getArg(0); Out << FS << dwarf::AttributeEncodingString(I->getArg(1)); + } else if (I->getOp() == dwarf::DW_OP_LLVM_implicit_pointer) { + Out << FS << dwarf::OperationEncodingString(I->getArg(0)); + Out << FS << I->getArg(1); } else { for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A) Out << FS << I->getArg(A); 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 @@ -837,6 +837,7 @@ case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_fragment: case dwarf::DW_OP_bregx: + case dwarf::DW_OP_LLVM_implicit_pointer: return 3; case dwarf::DW_OP_constu: case dwarf::DW_OP_consts: @@ -899,6 +900,10 @@ return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 && getNumElements() == 2; } + case dwarf::DW_OP_LLVM_implicit_pointer: { + // A DW_OP_LLVM_implicit_pointer operator must appear at the beginning + return I == expr_op_begin(); + } case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_tag_offset: case dwarf::DW_OP_constu: