Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -775,6 +775,28 @@ bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm(); int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0; + for (unsigned i = 0; i < Expr->getNumElements(); ++i) { + if (Deref) { + // We currently don't support extra Offsets or derefs after the first + // one. Bail out early instead of emitting an incorrect comment + OS << " [complex expression]"; + AP.OutStreamer->emitRawComment(OS.str()); + return true; + } + uint64_t Op = Expr->getElement(i); + if (Op == dwarf::DW_OP_deref) { + Deref = true; + continue; + } + uint64_t ExtraOffset = Expr->getElement(i++); + if (Op == dwarf::DW_OP_plus) + Offset += ExtraOffset; + else { + assert(Op == dwarf::DW_OP_minus); + Offset -= ExtraOffset; + } + } + // Register or immediate value. Register 0 means undef. if (MI->getOperand(0).isFPImm()) { APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -950,14 +950,12 @@ assert(Variable->isValidLocationForIntrinsic(dl) && "Expected inlined-at fields to agree"); uint64_t Offset = DI->getOffset(); - // A dbg.value for an alloca is always indirect. - bool IsIndirect = isa(V) || Offset != 0; SDDbgValue *SDV; if (Val.getNode()) { - if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, Offset, IsIndirect, + if (!EmitFuncArgumentDbgValue(V, Variable, Expr, dl, Offset, false, Val)) { SDV = DAG.getDbgValue(Variable, Expr, Val.getNode(), Val.getResNo(), - IsIndirect, Offset, dl, DbgSDNodeOrder); + false, Offset, dl, DbgSDNodeOrder); DAG.AddDbgValue(SDV, Val.getNode(), false); } } else @@ -4515,12 +4513,10 @@ // Check unused arguments map. N = UnusedArgNodeMap[V]; if (N.getNode()) { - // A dbg.value for an alloca is always indirect. - bool IsIndirect = isa(V) || Offset != 0; if (!EmitFuncArgumentDbgValue(V, Variable, Expression, dl, Offset, - IsIndirect, N)) { + false, N)) { SDV = DAG.getDbgValue(Variable, Expression, N.getNode(), N.getResNo(), - IsIndirect, Offset, dl, SDNodeOrder); + false, Offset, dl, SDNodeOrder); DAG.AddDbgValue(SDV, N.getNode(), false); } } else if (!V->use_empty() ) { Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1071,8 +1071,14 @@ if (LdStHasDebugValue(DIVar, LI)) return true; - Builder.insertDbgValueIntrinsic(LI->getOperand(0), 0, DIVar, DIExpr, - DDI->getDebugLoc(), LI); + // We are now tracking the loaded value instead of the address. In the + // future if multi-location support is added to the IR, it might be + // preferable to keep tracking both the loaded value and the original + // address in case the alloca can not be elided. + Instruction *DbgValue = + Builder.insertDbgValueIntrinsic(LI, 0, DIVar, DIExpr, + DDI->getDebugLoc(), (Instruction*) nullptr); + DbgValue->insertAfter(LI); return true; } @@ -1114,9 +1120,13 @@ // This is a call by-value or some other instruction that // takes a pointer to the variable. Insert a *value* // intrinsic that describes the alloca. + SmallVector NewDIExpr; + auto *DIExpr = DDI->getExpression(); + NewDIExpr.push_back(dwarf::DW_OP_deref); + NewDIExpr.append(DIExpr->elements_begin(), DIExpr->elements_end()); DIB.insertDbgValueIntrinsic(AI, 0, DDI->getVariable(), - DDI->getExpression(), DDI->getDebugLoc(), - CI); + DIB.createExpression(NewDIExpr), + DDI->getDebugLoc(), CI); } DDI->eraseFromParent(); } Index: test/CodeGen/ARM/debug-info-blocks.ll =================================================================== --- test/CodeGen/ARM/debug-info-blocks.ll +++ test/CodeGen/ARM/debug-info-blocks.ll @@ -1,5 +1,21 @@ -; RUN: llc -O0 < %s | FileCheck %s -; CHECK: @DEBUG_VALUE: foobar_func_block_invoke_0:mydata <- [%SP+{{[0-9]+}}] +; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump - | FileCheck %s + +; debug_info content +; CHECK: DW_AT_name {{.*}} "foobar_func_block_invoke_0" +; CHECK-NOT: DW_TAG_subprogram +; CHECK: DW_TAG_variable +; CHECK-NOT: DW_TAG +; CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ([[MYDATA_LOC:0x[0-9a-f]*]]) +; CHECK-NEXT: DW_AT_name {{.*}} "mydata" + +; debug_loc content +; CHECK: .debug_loc contents: +; CHECK: [[MYDATA_LOC]]: Beginning address offset: {{.*}} +; CHECK-NOT: {{0x[0-9a-f]*}}: Beginning address offset +; CHECK: Location description: {{.*}} 23 04 06 23 18 +; CHECK-NOT: {{0x[0-9a-f]*}}: Beginning address offset +; CHECK: Location description: {{.*}} 23 04 06 23 18 + ; Radar 9331779 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" target triple = "thumbv7-apple-ios" Index: test/DebugInfo/AArch64/coalescing.ll =================================================================== --- test/DebugInfo/AArch64/coalescing.ll +++ test/DebugInfo/AArch64/coalescing.ll @@ -60,6 +60,6 @@ !13 = !{i32 2, !"Debug Info Version", i32 3} !14 = !{!"clang version 3.6.0 (trunk 223149) (llvm/trunk 223115)"} !15 = !DILocation(line: 5, column: 3, scope: !4) -!16 = !DIExpression() +!16 = !DIExpression(DW_OP_deref) !17 = !DILocation(line: 4, column: 12, scope: !4) !18 = !DILocation(line: 8, column: 1, scope: !4) Index: test/DebugInfo/Mips/dsr-fixed-objects.ll =================================================================== --- test/DebugInfo/Mips/dsr-fixed-objects.ll +++ test/DebugInfo/Mips/dsr-fixed-objects.ll @@ -33,18 +33,18 @@ define i32 @f0(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e) !dbg !4 { entry: %x = alloca i32, align 4 - tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !9, metadata !26), !dbg !27 - tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !10, metadata !26), !dbg !28 - tail call void @llvm.dbg.value(metadata i32 %c, i64 0, metadata !11, metadata !26), !dbg !29 - tail call void @llvm.dbg.value(metadata i32 %d, i64 0, metadata !12, metadata !26), !dbg !30 - tail call void @llvm.dbg.value(metadata i32 %e, i64 0, metadata !13, metadata !26), !dbg !31 + tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !9, metadata !DIExpression()), !dbg !27 + tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !10, metadata !DIExpression()), !dbg !28 + tail call void @llvm.dbg.value(metadata i32 %c, i64 0, metadata !11, metadata !DIExpression()), !dbg !29 + tail call void @llvm.dbg.value(metadata i32 %d, i64 0, metadata !12, metadata !DIExpression()), !dbg !30 + tail call void @llvm.dbg.value(metadata i32 %e, i64 0, metadata !13, metadata !DIExpression()), !dbg !31 %0 = bitcast i32* %x to i8*, !dbg !32 call void @llvm.lifetime.start(i64 4, i8* %0) #4, !dbg !32 %add = add nsw i32 %b, %a, !dbg !33 %add1 = add nsw i32 %add, %c, !dbg !34 %add2 = add nsw i32 %add1, %d, !dbg !35 %add3 = add nsw i32 %add2, %e, !dbg !36 - tail call void @llvm.dbg.value(metadata i32 %add3, i64 0, metadata !14, metadata !26), !dbg !37 + tail call void @llvm.dbg.value(metadata i32 %add3, i64 0, metadata !14, metadata !DIExpression()), !dbg !37 store i32 %add3, i32* %x, align 4, !dbg !37, !tbaa !38 tail call void @llvm.dbg.value(metadata i32* %x, i64 0, metadata !14, metadata !26), !dbg !37 call void @foo(i32* nonnull %x) #4, !dbg !42 @@ -66,18 +66,18 @@ define i32 @f1(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e) !dbg !15 { entry: %x = alloca i32, align 16 - tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !17, metadata !26), !dbg !46 - tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !18, metadata !26), !dbg !47 - tail call void @llvm.dbg.value(metadata i32 %c, i64 0, metadata !19, metadata !26), !dbg !48 - tail call void @llvm.dbg.value(metadata i32 %d, i64 0, metadata !20, metadata !26), !dbg !49 - tail call void @llvm.dbg.value(metadata i32 %e, i64 0, metadata !21, metadata !26), !dbg !50 + tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !17, metadata !DIExpression()), !dbg !46 + tail call void @llvm.dbg.value(metadata i32 %b, i64 0, metadata !18, metadata !DIExpression()), !dbg !47 + tail call void @llvm.dbg.value(metadata i32 %c, i64 0, metadata !19, metadata !DIExpression()), !dbg !48 + tail call void @llvm.dbg.value(metadata i32 %d, i64 0, metadata !20, metadata !DIExpression()), !dbg !49 + tail call void @llvm.dbg.value(metadata i32 %e, i64 0, metadata !21, metadata !DIExpression()), !dbg !50 %0 = bitcast i32* %x to i8*, !dbg !51 call void @llvm.lifetime.start(i64 4, i8* %0) #4, !dbg !51 %add = add nsw i32 %b, %a, !dbg !52 %add1 = add nsw i32 %add, %c, !dbg !53 %add2 = add nsw i32 %add1, %d, !dbg !54 %add3 = add nsw i32 %add2, %e, !dbg !55 - tail call void @llvm.dbg.value(metadata i32 %add3, i64 0, metadata !22, metadata !26), !dbg !56 + tail call void @llvm.dbg.value(metadata i32 %add3, i64 0, metadata !22, metadata !DIExpression()), !dbg !56 store i32 %add3, i32* %x, align 16, !dbg !56, !tbaa !38 tail call void @llvm.dbg.value(metadata i32* %x, i64 0, metadata !22, metadata !26), !dbg !56 call void @foo(i32* nonnull %x) #4, !dbg !57 @@ -119,7 +119,7 @@ !23 = !{i32 2, !"Dwarf Version", i32 4} !24 = !{i32 2, !"Debug Info Version", i32 3} !25 = !{!"clang version 3.8.0 (trunk 251783) (llvm/trunk 251781)"} -!26 = !DIExpression() +!26 = !DIExpression(DW_OP_deref) !27 = !DILocation(line: 4, column: 12, scope: !4) !28 = !DILocation(line: 4, column: 19, scope: !4) !29 = !DILocation(line: 4, column: 26, scope: !4) Index: test/DebugInfo/X86/array.ll =================================================================== --- test/DebugInfo/X86/array.ll +++ test/DebugInfo/X86/array.ll @@ -37,13 +37,13 @@ %array = alloca [4 x i32], align 16 tail call void @llvm.dbg.value(metadata i32 %argc, i64 0, metadata !19, metadata !DIExpression()), !dbg !35 tail call void @llvm.dbg.value(metadata i8** %argv, i64 0, metadata !20, metadata !DIExpression()), !dbg !35 - tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression()), !dbg !36 + tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression(DW_OP_deref)), !dbg !36 %1 = bitcast [4 x i32]* %array to i8*, !dbg !36 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* bitcast ([4 x i32]* @main.array to i8*), i64 16, i32 16, i1 false), !dbg !36 - tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression()), !dbg !36 + tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression(DW_OP_deref)), !dbg !36 %2 = getelementptr inbounds [4 x i32], [4 x i32]* %array, i64 0, i64 0, !dbg !37 call void @f(i32* %2), !dbg !37 - tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression()), !dbg !36 + tail call void @llvm.dbg.value(metadata [4 x i32]* %array, i64 0, metadata !21, metadata !DIExpression(DW_OP_deref)), !dbg !36 %3 = load i32, i32* %2, align 16, !dbg !38, !tbaa !30 ret i32 %3, !dbg !38 } Index: test/DebugInfo/X86/dbg-value-const-byref.ll =================================================================== --- test/DebugInfo/X86/dbg-value-const-byref.ll +++ test/DebugInfo/X86/dbg-value-const-byref.ll @@ -56,7 +56,7 @@ %call1 = call i32 (...) @f1() #3, !dbg !19 call void @llvm.dbg.value(metadata i32 %call1, i64 0, metadata !10, metadata !DIExpression()), !dbg !19 store i32 %call1, i32* %i, align 4, !dbg !19, !tbaa !20 - call void @llvm.dbg.value(metadata i32* %i, i64 0, metadata !10, metadata !DIExpression()), !dbg !24 + call void @llvm.dbg.value(metadata i32* %i, i64 0, metadata !10, metadata !DIExpression(DW_OP_deref)), !dbg !24 call void @f2(i32* %i) #3, !dbg !24 ret i32 0, !dbg !25 } Index: test/DebugInfo/X86/debug-loc-asan.ll =================================================================== --- test/DebugInfo/X86/debug-loc-asan.ll +++ /dev/null @@ -1,182 +0,0 @@ -; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s - -; Verify that we have correct debug info for local variables in code -; instrumented with AddressSanitizer. - -; Generated from the source file test.cc: -; int bar(int y) { -; return y + 2; -; } -; with "clang++ -S -emit-llvm -fsanitize=address -O0 -g test.cc" - -; First, argument variable "y" resides in %rdi: -; CHECK: DEBUG_VALUE: bar:y <- %RDI - -; Then its address is stored in a location on a stack: -; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp) -; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]] -; CHECK-NEXT: DEBUG_VALUE: bar:y <- [%RSP+[[OFFSET]]] -; This location should be valid until the end of the function. - -; CHECK: .Ldebug_loc{{[0-9]+}}: -; We expect two location ranges for the variable. - -; First, its address is stored in %rdi: -; CHECK: .quad .Lfunc_begin0-.Lfunc_begin0 -; CHECK-NEXT: .quad [[START_LABEL]]-.Lfunc_begin0 -; CHECK: DW_OP_breg5 - -; Then it's addressed via %rsp: -; CHECK: .quad [[START_LABEL]]-.Lfunc_begin0 -; CHECK-NEXT: .Lfunc_end0-.Lfunc_begin0 -; CHECK: DW_OP_breg7 -; CHECK-NEXT: [[OFFSET]] -; CHECK: DW_OP_deref - -; ModuleID = 'test.cc' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 1, void ()* @asan.module_ctor }] -@__asan_option_detect_stack_use_after_return = external global i32 -@__asan_gen_ = private unnamed_addr constant [16 x i8] c"1 32 4 6 y.addr\00", align 1 - -; Function Attrs: nounwind sanitize_address uwtable -define i32 @_Z3bari(i32 %y) #0 !dbg !4 { -entry: - %MyAlloca = alloca [64 x i8], align 32 - %0 = ptrtoint [64 x i8]* %MyAlloca to i64 - %1 = load i32, i32* @__asan_option_detect_stack_use_after_return - %2 = icmp ne i32 %1, 0 - br i1 %2, label %3, label %5 - -;