Index: llvm/lib/CodeGen/LiveDebugValues.cpp =================================================================== --- llvm/lib/CodeGen/LiveDebugValues.cpp +++ llvm/lib/CodeGen/LiveDebugValues.cpp @@ -1242,7 +1242,8 @@ // function parameters in order to generate debug entry values for them. // Currently, we generate debug entry values only for parameters that are // unmodified throughout the function and located in a register. - // TODO: Add support for parameters that are described as fragments. + // TODO: Add support for parameters with non-empty debug expressions (for + // example fragments). // TODO: Add support for modified arguments that can be expressed // by using its entry value. // TODO: Add support for local variables that are expressed in terms of @@ -1251,7 +1252,7 @@ if (MI.isDebugValue() && IsUnmodifiedFuncParam(MI) && !MI.isIndirectDebugValue() && IsRegOtherThanSPAndFP(MI.getOperand(0)) && !DebugEntryVals.count(MI.getDebugVariable()) && - !MI.getDebugExpression()->isFragment()) + MI.getDebugExpression()->getNumElements() == 0) DebugEntryVals[MI.getDebugVariable()] = &MI; // Initialize every mbb with OutLocs. Index: llvm/test/DebugInfo/Mips/entry-value-non-empty-expr.ll =================================================================== --- /dev/null +++ llvm/test/DebugInfo/Mips/entry-value-non-empty-expr.ll @@ -0,0 +1,80 @@ +; RUN: llc -O0 -debug-entry-values -stop-after=livedebugvalues < %s | FileCheck %s + +target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64" +target triple = "mips" + +; Based on the following C reproducer: +; +; int arr[9]; +; extern void ext(int); +; static void bar(int *p) { ext(*p); } +; void foo() { bar(&arr[8]); } + +; Verify that there is no entry value created for the parameter. Entry values +; are currently only supported for register DBG_VALUEs with empty debug +; expressions, since the DW_OP_entry_value can currently only wrap one byte. +; Creating an entry value for a DBG_VALUE with a non-empty debug expression +; would result in an invalid expression, triggering an assertion later on. +; +; In this case the entry value for the parameter would not have any purpose +; since the caller's parameter value has been propagated to the static callee, +; so there is no call site entry for the parameter. + +; CHECK-NOT: DBG_VALUE +; CHECK: DBG_VALUE {{.*}}, $noreg, {{.*}}, !DIExpression(DW_OP_plus_uconst, 32, DW_OP_stack_value) +; CHECK-NOT: DBG_VALUE + +@arr = common global [9 x i32] zeroinitializer, align 4 + +; Function Attrs: nounwind +define void @foo() #0 !dbg !11 { +entry: + tail call fastcc void @bar() #2, !dbg !14 + ret void, !dbg !14 +} + +; Function Attrs: nounwind +define internal fastcc void @bar() #0 !dbg !15 { +entry: + call void @llvm.dbg.value(metadata i32* getelementptr inbounds ([9 x i32], [9 x i32]* @arr, i32 0, i32 8), metadata !20, metadata !DIExpression()), !dbg !21 + %0 = load i32, i32* getelementptr inbounds ([9 x i32], [9 x i32]* @arr, i32 0, i32 8), align 4, !dbg !22 + tail call void @ext(i32 signext %0), !dbg !22 + ret void, !dbg !22 +} + +declare !dbg !4 void @ext(i32 signext) + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone speculatable willreturn } +attributes #2 = { nobuiltin } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!8, !9} +!llvm.ident = !{!10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, globals: !2, nameTableKind: None) +!1 = !DIFile(filename: "mips.c", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DISubprogram(name: "ext", scope: !1, file: !1, line: 3, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null, !7} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{!"clang version 10.0.0"} +!11 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 7, type: !12, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!12 = !DISubroutineType(types: !13) +!13 = !{null} +!14 = !DILocation(line: 7, scope: !11) +!15 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19) +!16 = !DISubroutineType(types: !17) +!17 = !{null, !18} +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32) +!19 = !{!20} +!20 = !DILocalVariable(name: "p", arg: 1, scope: !15, file: !1, line: 5, type: !18, flags: DIFlagArgumentNotModified) +!21 = !DILocation(line: 0, scope: !15) +!22 = !DILocation(line: 5, scope: !15)