Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -4377,6 +4377,10 @@ - ``DW_OP_plus, 93`` adds ``93`` to the working expression. - ``DW_OP_bit_piece, 16, 8`` specifies the offset and size (``16`` and ``8`` here, respectively) of the variable piece from the working expression. +- ``DW_OP_swap`` swaps top two stack entries. +- ``DW_OP_xderef`` provides extended dereference mechanism. The entry at the top + of the stack is treated as an address. The second stack entry is treated as an + address space identifier. .. code-block:: text @@ -4384,6 +4388,7 @@ !1 = !DIExpression(DW_OP_plus, 3) !2 = !DIExpression(DW_OP_bit_piece, 3, 7) !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7) + !4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) DIObjCProperty """""""""""""" Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -273,6 +273,12 @@ case dwarf::DW_OP_stack_value: AddStackValue(); break; + case dwarf::DW_OP_swap: + EmitOp(dwarf::DW_OP_swap); + break; + case dwarf::DW_OP_xderef: + EmitOp(dwarf::DW_OP_xderef); + break; default: llvm_unreachable("unhandled opcode found in expression"); } Index: llvm/trunk/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/trunk/lib/IR/DebugInfoMetadata.cpp +++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp @@ -612,10 +612,23 @@ return false; break; } + case dwarf::DW_OP_swap: { + // Must be more than one implicit element on the stack. + + // FIXME: A better way to implement this would be to add a local variable + // that keeps track of the stack depth and introduce something like a + // DW_LLVM_OP_implicit_location as a placeholder for the location this + // DIExpression is attached to, or else pass the number of implicit stack + // elements into isValid. + if (getNumElements() == 1) + return false; + break; + } case dwarf::DW_OP_constu: case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: case dwarf::DW_OP_deref: + case dwarf::DW_OP_xderef: break; } } Index: llvm/trunk/test/Assembler/diexpression.ll =================================================================== --- llvm/trunk/test/Assembler/diexpression.ll +++ llvm/trunk/test/Assembler/diexpression.ll @@ -1,16 +1,18 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !1, !2, !3, !4} -!named = !{!0, !1, !2, !3, !4} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5} +!named = !{!0, !1, !2, !3, !4, !5} ; CHECK: !0 = !DIExpression() ; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref) ; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3) ; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) ; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) +; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) !0 = !DIExpression() !1 = !DIExpression(DW_OP_deref) !2 = !DIExpression(DW_OP_plus, 3) !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) +!5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) Index: llvm/trunk/test/Verifier/diexpression-swap.ll =================================================================== --- llvm/trunk/test/Verifier/diexpression-swap.ll +++ llvm/trunk/test/Verifier/diexpression-swap.ll @@ -0,0 +1,5 @@ +; RUN: not opt -S < %s 2>&1 | FileCheck %s + +!named = !{!0} +; CHECK: invalid expression +!0 = !DIExpression(DW_OP_swap)