Index: llvm/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAG.h +++ llvm/include/llvm/CodeGen/SelectionDAG.h @@ -1171,8 +1171,7 @@ /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, - unsigned R, bool IsIndirect, const DebugLoc &DL, - unsigned O); + unsigned R, const DebugLoc &DL, unsigned O); /// Constant SDDbgValue *getConstantDbgValue(DIVariable *Var, DIExpression *Expr, Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2286,6 +2286,10 @@ /// return true with an offset of zero. bool extractIfOffset(int64_t &Offset) const; + /// Append DW_OP_deref to an existing expression. Useful when converting a + /// dbg.declare that uses this expression to dbg.value. + DIExpression *appendDeref() const; + /// Constants for DIExpression::prepend. enum { NoDeref = false, WithDeref = true, WithStackValue = true }; Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1183,11 +1183,12 @@ "Expected inlined-at fields to agree"); if (Op->isReg()) { Op->setIsDebug(true); - // A dbg.declare describes the address of a source variable, so lower it - // into an indirect DBG_VALUE. + // A dbg.declare describes the address of a source variable, so add + // DW_OP_deref. BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, - TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ true, - Op->getReg(), DI->getVariable(), DI->getExpression()); + TII.get(TargetOpcode::DBG_VALUE), /*IsIndirect*/ false, + Op->getReg(), DI->getVariable(), + DI->getExpression()->appendDeref()); } else BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::DBG_VALUE)) Index: llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -724,12 +724,7 @@ MIB.addReg(0U); } - // Indirect addressing is indicated by an Imm as the second parameter. - if (SD->isIndirect()) - MIB.addImm(0U); - else - MIB.addReg(0U, RegState::Debug); - + MIB.addReg(0U, RegState::Debug); MIB.addMetadata(Var); MIB.addMetadata(Expr); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -842,9 +842,8 @@ DIVariable *Var = Dbg->getVariable(); auto *Fragment = DIExpression::createFragmentExpression( Dbg->getExpression(), OffsetInBits, To.getValueSizeInBits()); - SDDbgValue *Clone = - DAG.getDbgValue(Var, Fragment, ToNode, To.getResNo(), Dbg->isIndirect(), - Dbg->getDebugLoc(), Dbg->getOrder()); + SDDbgValue *Clone = DAG.getDbgValue(Var, Fragment, ToNode, To.getResNo(), + Dbg->getDebugLoc(), Dbg->getOrder()); Dbg->setIsInvalidated(); ClonedDVs.push_back(Clone); } Index: llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h +++ llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h @@ -49,14 +49,13 @@ DebugLoc DL; unsigned Order; enum DbgValueKind kind; - bool IsIndirect; bool Invalid = false; public: // Constructor for non-constants. SDDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, unsigned R, - bool indir, DebugLoc dl, unsigned O) - : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(indir) { + DebugLoc dl, unsigned O) + : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O) { kind = SDNODE; u.s.Node = N; u.s.ResNo = R; @@ -65,7 +64,7 @@ // Constructor for constants. SDDbgValue(DIVariable *Var, DIExpression *Expr, const Value *C, DebugLoc dl, unsigned O) - : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(false) { + : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O) { kind = CONST; u.Const = C; } @@ -73,7 +72,7 @@ // Constructor for frame indices. SDDbgValue(DIVariable *Var, DIExpression *Expr, unsigned FI, DebugLoc dl, unsigned O) - : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(false) { + : Var(Var), Expr(Expr), DL(std::move(dl)), Order(O) { kind = FRAMEIX; u.FrameIx = FI; } @@ -99,9 +98,6 @@ // Returns the FrameIx for a stack object unsigned getFrameIx() const { assert (kind==FRAMEIX); return u.FrameIx; } - // Returns whether this is an indirect value. - bool isIndirect() const { return IsIndirect; } - // Returns the DebugLoc. DebugLoc getDebugLoc() const { return DL; } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6916,12 +6916,11 @@ /// /// SDNode SDDbgValue *SelectionDAG::getDbgValue(DIVariable *Var, DIExpression *Expr, - SDNode *N, unsigned R, bool IsIndirect, - const DebugLoc &DL, unsigned O) { + SDNode *N, unsigned R, const DebugLoc &DL, + unsigned O) { assert(cast(Var)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); - return new (DbgInfo->getAlloc()) - SDDbgValue(Var, Expr, N, R, IsIndirect, DL, O); + return new (DbgInfo->getAlloc()) SDDbgValue(Var, Expr, N, R, DL, O); } /// Constant @@ -7375,9 +7374,9 @@ Dbg->getResNo() == From.getResNo() && !Dbg->isInvalidated()) { assert(FromNode != ToNode && "Should not transfer Debug Values intranode"); - SDDbgValue *Clone = getDbgValue(Dbg->getVariable(), Dbg->getExpression(), - ToNode, To.getResNo(), Dbg->isIndirect(), - Dbg->getDebugLoc(), Dbg->getOrder()); + SDDbgValue *Clone = + getDbgValue(Dbg->getVariable(), Dbg->getExpression(), ToNode, + To.getResNo(), Dbg->getDebugLoc(), Dbg->getOrder()); ClonedDVs.push_back(Clone); Dbg->setIsInvalidated(); } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -4783,7 +4783,6 @@ if (!Variable->getScope()->getSubprogram()->describes(MF.getFunction())) return false; - bool IsIndirect = false; Optional Op; // Some arguments' frame index is recorded during argument lowering. int FI = FuncInfo.getArgumentFrameIndex(Arg); @@ -4798,19 +4797,15 @@ if (PR) Reg = PR; } - if (Reg) { + if (Reg) Op = MachineOperand::CreateReg(Reg, false); - IsIndirect = IsDbgDeclare; - } } if (!Op) { // Check if ValueMap has reg number. DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); - if (VMI != FuncInfo.ValueMap.end()) { + if (VMI != FuncInfo.ValueMap.end()) Op = MachineOperand::CreateReg(VMI->second, false); - IsIndirect = IsDbgDeclare; - } } if (!Op && N.getNode()) @@ -4825,11 +4820,14 @@ assert(Variable->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); - if (Op->isReg()) + if (Op->isReg()) { + // Make this an indirect register location if this was dbg.declare. + if (IsDbgDeclare) + Expr = Expr->appendDeref(); FuncInfo.ArgDbgValues.push_back( - BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsIndirect, + BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE), /*IsIndirect=*/false, Op->getReg(), Variable, Expr)); - else + } else FuncInfo.ArgDbgValues.push_back( BuildMI(MF, DL, TII->get(TargetOpcode::DBG_VALUE)) .add(*Op) @@ -4853,7 +4851,7 @@ return DAG.getFrameIndexDbgValue(Variable, Expr, FISDN->getIndex(), dl, DbgSDNodeOrder); } - return DAG.getDbgValue(Variable, Expr, N.getNode(), N.getResNo(), false, dl, + return DAG.getDbgValue(Variable, Expr, N.getNode(), N.getResNo(), dl, DbgSDNodeOrder); } @@ -5137,8 +5135,8 @@ EmitFuncArgumentDbgValue(Address, Variable, Expression, dl, true, N); return nullptr; } else { - SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(), - true, dl, SDNodeOrder); + SDV = DAG.getDbgValue(Variable, Expression->appendDeref(), N.getNode(), + N.getResNo(), dl, SDNodeOrder); } DAG.AddDbgValue(SDV, N.getNode(), isParameter); } else { Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -529,9 +529,7 @@ const MDNode *Expr = MI->getDebugExpression(); DebugLoc DL = MI->getDebugLoc(); bool IsIndirect = MI->isIndirectDebugValue(); - if (IsIndirect) - assert(MI->getOperand(1).getImm() == 0 && - "DBG_VALUE with nonzero offset"); + assert(!IsIndirect && "no indirect DBG_VALUES before regalloc"); assert(cast(Variable)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); // Def is never a terminator here, so it is ok to increment InsertPos. Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -698,6 +698,18 @@ return false; } +DIExpression *DIExpression::appendDeref() const { + // Place DW_OP_deref after all opcodes that compute the pointer, and place any + // fragment ops at the end. + SmallVector Ops(elements_begin(), elements_end()); + auto I = expr_op_iterator(Ops.begin()), E = expr_op_iterator(Ops.end()); + for (; I != E; ++I) + if (I->getOp() == dwarf::DW_OP_LLVM_fragment) + break; + Ops.insert(const_cast(I.getBase()), dwarf::DW_OP_deref); + return DIExpression::get(getContext(), Ops); +} + DIExpression *DIExpression::prepend(const DIExpression *Expr, bool Deref, int64_t Offset, bool StackValue) { SmallVector Ops; Index: llvm/test/DebugInfo/COFF/pieces.ll =================================================================== --- llvm/test/DebugInfo/COFF/pieces.ll +++ llvm/test/DebugInfo/COFF/pieces.ll @@ -77,7 +77,7 @@ ; ASM-LABEL: nested: # @nested -; ASM: #DEBUG_VALUE: nested:o <- [DW_OP_deref] [%RCX+0] +; ASM: #DEBUG_VALUE: nested:o <- [DW_OP_deref] %RCX ; ASM: movl 12(%rcx), %eax ; ASM: [[p_start:\.Ltmp[0-9]+]]: ; ASM: #DEBUG_VALUE: nested:p <- [DW_OP_LLVM_fragment 32 32] %EAX @@ -179,7 +179,7 @@ ; ASM: .asciz "nested" # Function name ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "o" -; ASM: .cv_def_range .Lfunc_begin3 .Lfunc_end3, "E\021J\001\000\000\000\000\000\000" +; ASM: .cv_def_range .Lfunc_begin3 .Lfunc_end3, "E\021J\001\000\000\000\000\000\000" ; ASM: .short 4414 # Record kind: S_LOCAL ; ASM: .asciz "p" ; ASM: .cv_def_range [[p_start]] .Lfunc_end3, "C\021\021\000\000\000\004\000\000\000" @@ -189,7 +189,7 @@ ; OBJ: DisplayName: nested ; OBJ: } ; OBJ: LocalSym { -; OBJ: Type: Nested& +; OBJ: Type: Nested ({{.*}}) ; OBJ: VarName: o ; OBJ: } ; OBJ: DefRangeRegisterRelSym { @@ -422,7 +422,7 @@ !70 = !{!71, !72} !71 = !DILocalVariable(name: "o", arg: 1, scope: !61, file: !1, line: 27, type: !64) !72 = !DILocalVariable(name: "p", scope: !61, file: !1, line: 28, type: !53) -!73 = !DIExpression(DW_OP_deref) +!73 = !DIExpression() !74 = !DILocation(line: 27, column: 26, scope: !61) !75 = !DILocation(line: 28, column: 18, scope: !61) !76 = !DILocation(line: 28, column: 22, scope: !61) Index: llvm/test/DebugInfo/COFF/types-array-advanced.ll =================================================================== --- llvm/test/DebugInfo/COFF/types-array-advanced.ll +++ llvm/test/DebugInfo/COFF/types-array-advanced.ll @@ -50,40 +50,28 @@ ; CHECK: SizeOf: 4 ; CHECK: Name: ; CHECK: } -; CHECK: Pointer (0x1004) { -; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: 0x1003 -; CHECK: PointerAttributes: 0x2A -; CHECK: PtrType: Near32 (0xA) -; CHECK: PtrMode: LValueReference (0x1) -; CHECK: IsFlat: 0 -; CHECK: IsConst: 0 -; CHECK: IsVolatile: 0 -; CHECK: IsUnaligned: 0 -; CHECK: SizeOf: 0 -; CHECK: } -; CHECK: Array (0x1005) { +; CHECK: Array (0x1004) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) ; CHECK: ElementType: char (0x70) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 7 ; CHECK: Name: ; CHECK: } -; CHECK: Array (0x1006) { +; CHECK: Array (0x1005) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: 0x1005 +; CHECK: ElementType: 0x1004 ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 35 ; CHECK: Name: ; CHECK: } -; CHECK: Array (0x1007) { +; CHECK: Array (0x1006) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: 0x1006 +; CHECK: ElementType: 0x1005 ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 70 ; CHECK: Name: ; CHECK: } -; CHECK: Struct (0x1008) { +; CHECK: Struct (0x1007) { ; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) ; CHECK: MemberCount: 0 ; CHECK: Properties [ (0x280) @@ -97,16 +85,16 @@ ; CHECK: Name: incomplete_struct ; CHECK: LinkageName: .?AUincomplete_struct@@ ; CHECK: } -; CHECK: Array (0x1009) { +; CHECK: Array (0x1008) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: incomplete_struct (0x1008) +; CHECK: ElementType: incomplete_struct (0x1007) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 12 ; CHECK: Name: ; CHECK: } -; CHECK: Pointer (0x100A) { +; CHECK: Pointer (0x1009) { ; CHECK: TypeLeafKind: LF_POINTER (0x1002) -; CHECK: PointeeType: 0x1009 +; CHECK: PointeeType: 0x1008 ; CHECK: PointerAttributes: 0x800A ; CHECK: PtrType: Near32 (0xA) ; CHECK: PtrMode: Pointer (0x0) @@ -116,41 +104,8 @@ ; CHECK: IsUnaligned: 0 ; CHECK: SizeOf: 4 ; CHECK: } -; CHECK: FieldList (0x100B) { -; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) -; CHECK: DataMember { -; CHECK: TypeLeafKind: LF_MEMBER (0x150D) -; CHECK: AccessSpecifier: Public (0x3) -; CHECK: Type: int (0x74) -; CHECK: FieldOffset: 0x0 -; CHECK: Name: s1 -; CHECK: } -; CHECK: } -; CHECK: Struct (0x100C) { -; CHECK: TypeLeafKind: LF_STRUCTURE (0x1505) -; CHECK: MemberCount: 1 -; CHECK: Properties [ (0x200) -; CHECK: HasUniqueName (0x200) -; CHECK: ] -; CHECK: FieldList: (0x100B) -; CHECK: DerivedFrom: 0x0 -; CHECK: VShape: 0x0 -; CHECK: SizeOf: 4 -; CHECK: Name: incomplete_struct -; CHECK: LinkageName: .?AUincomplete_struct@@ -; CHECK: } -; CHECK: StringId (0x100D) { -; CHECK: TypeLeafKind: LF_STRING_ID (0x1605) -; CHECK: Id: 0x0 -; CHECK: StringData: \t.cpp -; CHECK: } -; CHECK: UdtSourceLine (0x100E) { -; CHECK: TypeLeafKind: LF_UDT_SRC_LINE (0x1606) -; CHECK: UDT: incomplete_struct (0x100C) -; CHECK: SourceFile: \t.cpp (0x100D) -; CHECK: LineNumber: 4 -; CHECK: } -; CHECK: Modifier (0x100F) { +; +; CHECK: Modifier (0x100E) { ; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) ; CHECK: ModifiedType: int (0x74) ; CHECK: Modifiers [ (0x3) @@ -158,12 +113,12 @@ ; CHECK: Volatile (0x2) ; CHECK: ] ; CHECK: } -; CHECK: Array (0x1010) { +; CHECK: Array (0x100F) { ; CHECK: TypeLeafKind: LF_ARRAY (0x1503) -; CHECK: ElementType: const volatile int (0x100F) +; CHECK: ElementType: const volatile int (0x100E) ; CHECK: IndexType: unsigned long (0x22) ; CHECK: SizeOf: 16 -; CHECK: Name: +; CHECK: Name: ; CHECK: } ; CHECK: ] @@ -189,7 +144,7 @@ %1 = call i8* @llvm.stacksave(), !dbg !42 store i8* %1, i8** %saved_stack, align 4, !dbg !42 %vla = alloca i32, i32 %0, align 4, !dbg !42 - call void @llvm.dbg.declare(metadata i32* %vla, metadata !43, metadata !47), !dbg !48 + call void @llvm.dbg.declare(metadata i32* %vla, metadata !43, metadata !DIExpression()), !dbg !48 %arrayidx = getelementptr inbounds i32, i32* %vla, i32 0, !dbg !49 store i32 0, i32* %arrayidx, align 4, !dbg !50 %2 = load i8*, i8** %saved_stack, align 4, !dbg !51 @@ -260,7 +215,6 @@ !44 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, align: 32, elements: !45) !45 = !{!46} !46 = !DISubrange(count: -1) -!47 = !DIExpression(DW_OP_deref) !48 = !DILocation(line: 9, column: 8, scope: !35) !49 = !DILocation(line: 10, column: 4, scope: !35) !50 = !DILocation(line: 10, column: 20, scope: !35) Index: llvm/test/DebugInfo/X86/dbg-declare-arg.ll =================================================================== --- llvm/test/DebugInfo/X86/dbg-declare-arg.ll +++ llvm/test/DebugInfo/X86/dbg-declare-arg.ll @@ -2,11 +2,14 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-macosx10.6.7" ; rdar://problem/9321650 + +; %agg.result is spilled to [RSP+8] early on. It is a pointer to the "my_a" +; value, so we need DW_OP_deref. ; ; CHECK: DW_AT_name {{.*}}"j" ; CHECK: DW_TAG_variable ; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ( -; CHECK-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+8) +; CHECK-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+8, DW_OP_deref) ; CHECK-NEXT: DW_AT_name {{.*}}"my_a" %class.A = type { i32, i32, i32, i32 } Index: llvm/test/DebugInfo/X86/debug-loc-asan.ll =================================================================== --- llvm/test/DebugInfo/X86/debug-loc-asan.ll +++ llvm/test/DebugInfo/X86/debug-loc-asan.ll @@ -14,7 +14,7 @@ ; The address of the (potentially now malloc'ed) alloca ends up ; in RDI, after which it is spilled to the stack. We record the ; spill OFFSET on the stack for checking the debug info below. -; CHECK: #DEBUG_VALUE: bar:y <- [DW_OP_deref] [%RDI+0] +; CHECK: #DEBUG_VALUE: bar:y <- [DW_OP_deref, DW_OP_deref] %RDI ; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp) ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]] ; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [DW_OP_plus_uconst [[OFFSET]], DW_OP_deref, DW_OP_deref] Index: llvm/test/DebugInfo/X86/dw_op_minus.ll =================================================================== --- llvm/test/DebugInfo/X86/dw_op_minus.ll +++ llvm/test/DebugInfo/X86/dw_op_minus.ll @@ -1,5 +1,7 @@ ; Test dwarf codegen of DW_OP_minus. ; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s +; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu %s -filetype=obj -o %t.o +; RUN: llvm-dwarfdump %t.o -debug-dump=info | FileCheck %s --check-prefix=DWARF ; This was built by compiling the following source with SafeStack and ; simplifying the result a little. @@ -73,8 +75,14 @@ ; CHECK: .short 7 # Loc expr size ; CHECK-NEXT: .byte 119 # DW_OP_breg7 ; CHECK-NEXT: .byte 8 # 8 -; CHECK-NEXT: .byte 6 # DW_OP_deref ; CHECK-NEXT: .byte 16 # DW_OP_constu ; CHECK-NEXT: .byte 144 # 400 ; CHECK-NEXT: .byte 3 # DW_OP_minus -; CHECK-NEXT: .byte 28 +; CHECK-NEXT: .byte 28 # DW_OP_deref +; CHECK-NEXT: .byte 6 + +; DWARF: DW_TAG_variable +; DWARF-NEXT: DW_AT_location [DW_FORM_sec_offset] (0x00000000 +; DWARF-NEXT: {{.*}} - {{.*}}: DW_OP_breg2 RCX-400 +; DWARF-NEXT: {{.*}} - {{.*}}: DW_OP_breg7 RSP+8, DW_OP_constu 0x190, DW_OP_minus, DW_OP_deref) +; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "buf") Index: llvm/test/DebugInfo/X86/safestack-byval.ll =================================================================== --- llvm/test/DebugInfo/X86/safestack-byval.ll +++ llvm/test/DebugInfo/X86/safestack-byval.ll @@ -2,6 +2,7 @@ ; points to neither an argument nor an alloca. This kind of IR is generated by ; SafeStack for unsafe byval arguments. ; RUN: llc -mtriple=x86_64-unknown-unknown -stop-after expand-isel-pseudos %s -o - | FileCheck %s +; RUN: llc -mtriple=x86_64-unknown-unknown -filetype=obj %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s --check-prefix=DWARF ; This was built by compiling the following source with SafeStack and ; simplifying the result a little. @@ -14,7 +15,13 @@ ; } ; CHECK: ![[ZZZ:.*]] = !DILocalVariable(name: "zzz", -; CHECK: DBG_VALUE {{.*}} ![[ZZZ]], !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus) +; CHECK: DBG_VALUE {{.*}} ![[ZZZ]], !DIExpression(DW_OP_constu, 400, DW_OP_minus, DW_OP_deref) + +; DWARF: DW_TAG_formal_parameter +; DWARF-NOT: DW_TAG_ +; DWARF: DW_AT_location {{.*}} ({{.*}} +; DWARF-NEXT: {{.*}} - {{.*}}: DW_OP_breg3 RBX-400) +; DWARF-NEXT: DW_AT_name {{.*}} "zzz" %struct.S = type { [100 x i32] } @@ -78,7 +85,7 @@ !20 = !{i32 2, !"Debug Info Version", i32 3} !21 = !{!"clang version 3.8.0 (trunk 254107) (llvm/trunk 254109)"} !22 = !DILocation(line: 8, column: 9, scope: !12) -!23 = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus) +!23 = !DIExpression(DW_OP_constu, 400, DW_OP_minus) !24 = !DILocation(line: 8, column: 28, scope: !12) !25 = !DIExpression() !26 = !DILocation(line: 9, column: 10, scope: !12) Index: llvm/test/DebugInfo/X86/vla.ll =================================================================== --- llvm/test/DebugInfo/X86/vla.ll +++ llvm/test/DebugInfo/X86/vla.ll @@ -1,6 +1,6 @@ ; RUN: llc -O0 -mtriple=x86_64-apple-darwin -filetype=asm %s -o - | FileCheck %s ; Ensure that we generate an indirect location for the variable length array a. -; CHECK: ##DEBUG_VALUE: vla:a <- [DW_OP_deref] [%RCX+0] +; CHECK: ##DEBUG_VALUE: vla:a <- [DW_OP_deref] %RCX ; CHECK: DW_OP_breg2 ; rdar://problem/13658587 ; @@ -33,7 +33,7 @@ %2 = call i8* @llvm.stacksave(), !dbg !17 store i8* %2, i8** %saved_stack, !dbg !17 %vla = alloca i32, i64 %1, align 16, !dbg !17 - call void @llvm.dbg.declare(metadata i32* %vla, metadata !18, metadata !DIExpression(DW_OP_deref)), !dbg !17 + call void @llvm.dbg.declare(metadata i32* %vla, metadata !18, metadata !DIExpression()), !dbg !17 %arrayidx = getelementptr inbounds i32, i32* %vla, i64 0, !dbg !22 store i32 42, i32* %arrayidx, align 4, !dbg !22 %3 = load i32, i32* %n.addr, align 4, !dbg !23 Index: llvm/test/DebugInfo/X86/vla2.ll =================================================================== --- llvm/test/DebugInfo/X86/vla2.ll +++ llvm/test/DebugInfo/X86/vla2.ll @@ -1,3 +1,5 @@ +; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm \ +; RUN: | FileCheck %s -check-prefix=ASM-CHECK ; RUN: llc -O0 -mtriple=x86_64-apple-darwin < %s -filetype=obj \ ; RUN: | llvm-dwarfdump -debug-dump=info - \ ; RUN: | FileCheck %s -check-prefix=CHECK -check-prefix=DWARF4 @@ -5,24 +7,24 @@ ; RUN: | llvm-dwarfdump -debug-dump=info - \ ; RUN: | FileCheck %s -check-prefix=CHECK -check-prefix=DWARF3 +; ASM-CHECK-LABEL: _testVLAwithSize: +; ASM-CHECK-LABEL: Lfunc_begin0: +; Copy from RSP to RCX. +; ASM-CHECK: movq %rsp, %rcx +; ASM-CHECK: DEBUG_VALUE: vla <- [DW_OP_deref] %RCX +; ASM-CHECK-LABEL: Lfunc_end0: + +; ASM-CHECK: DW_OP_breg2 + ; DWARF4: DW_AT_location [DW_FORM_sec_offset] (0x00000000 -; DWARF4-NEXT: {{.*}}: DW_OP_breg2 RCX+0, DW_OP_deref +; DWARF4-NEXT: {{.*}}: DW_OP_breg2 RCX+0{{$}} ; DWARF3: DW_AT_location [DW_FORM_data4] (0x00000000 -; DWARF3-NEXT: {{.*}}: DW_OP_breg2 RCX+0, DW_OP_deref +; DWARF3-NEXT: {{.*}}: DW_OP_breg2 RCX+0{{$}} ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla") -; Check the DEBUG_VALUE comments for good measure. -; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK -; vla should have a register-indirect address at one point. -; ASM-CHECK: DEBUG_VALUE: vla <- [DW_OP_deref] [%RCX+0] -; ASM-CHECK: DW_OP_breg2 - -; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s --check-prefix=PRETTY-PRINT -; PRETTY-PRINT: DIExpression(DW_OP_deref) - define void @testVLAwithSize(i32 %s) nounwind uwtable ssp !dbg !5 { entry: %s.addr = alloca i32, align 4 @@ -35,7 +37,7 @@ %2 = call i8* @llvm.stacksave(), !dbg !12 store i8* %2, i8** %saved_stack, !dbg !12 %vla = alloca i32, i64 %1, align 16, !dbg !12 - call void @llvm.dbg.declare(metadata i32* %vla, metadata !14, metadata !30), !dbg !18 + call void @llvm.dbg.declare(metadata i32* %vla, metadata !14, metadata !DIExpression()), !dbg !18 call void @llvm.dbg.declare(metadata i32* %i, metadata !19, metadata !DIExpression()), !dbg !20 store i32 0, i32* %i, align 4, !dbg !21 br label %for.cond, !dbg !21 @@ -104,4 +106,3 @@ !27 = !DILocation(line: 8, column: 1, scope: !13) !28 = !DIFile(filename: "bar.c", directory: "/Users/echristo/tmp") !29 = !{i32 1, !"Debug Info Version", i32 3} -!30 = !DIExpression(DW_OP_deref)