From a284ce24c9d86a4f39bf2aaf69cea13b3950e37f Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 22 Mar 2017 01:16:01 +0000 Subject: [PATCH] Don't compose DWARF expressions with multiple subregisters. If a register location can only be described by a complex expression (i.e., multiple subregisters) it doesn't safely compose with another complex expression. For example, it is not possible to apply a DW_OP_deref operation to multiple DW_OP_pieces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298472 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 9 ++ .../MIR/ARM/split-superreg-complex.mir | 122 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 test/DebugInfo/MIR/ARM/split-superreg-complex.mir diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index cf199810a0f..88ea4741937 100644 --- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -196,6 +196,15 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, if (Op && Op->getOp() != dwarf::DW_OP_LLVM_fragment) HasComplexExpression = true; + // If the register can only be described by a complex expression (i.e., + // multiple subregisters) it doesn't safely compose with another complex + // expression. For example, it is not possible to apply a DW_OP_deref + // operation to multiple DW_OP_pieces. + if (HasComplexExpression && DwarfRegs.size() > 1) { + DwarfRegs.clear(); + return false; + } + // Handle simple register locations. if (!HasComplexExpression) { for (auto &Reg : DwarfRegs) { diff --git a/test/DebugInfo/MIR/ARM/split-superreg-complex.mir b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir new file mode 100644 index 00000000000..2e8d9977a64 --- /dev/null +++ b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir @@ -0,0 +1,122 @@ +# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s +# +# This is an artificial example of a debug value residing in a composite +# location with a complex expression. Because the semantics of applying a DWARF +# expression to a composite location are ill-defined, the compiler should bail +# out of emitting a location. +# +# CHECK: .debug_info contents: +# CHECK: DW_TAG_variable +# CHECK-NOT: DW_AT_location +# CHECK: DW_TAG +--- | + ; Generated from: + ; typedef float vec2 __attribute__((vector_size(16))); + ; vec2 v(); + ; float f() { + ; vec2 vec = v(); + ; return vec[0] + vec[1]; + ; } + + target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + target triple = "thumbv7s-apple-ios5.0.0" + + define float @f() local_unnamed_addr #0 !dbg !9 { + entry: + %call = tail call <4 x float> bitcast (<4 x float> (...)* @v to <4 x float> ()*)() #0, !dbg !19 + tail call void @llvm.dbg.value(metadata <4 x float> %call, i64 0, metadata !14, metadata !20), !dbg !21 + %vecext = extractelement <4 x float> %call, i32 0, !dbg !22 + %vecext1 = extractelement <4 x float> %call, i32 1, !dbg !23 + %add = fadd float %vecext, %vecext1, !dbg !24 + ret float %add, !dbg !25 + } + + declare arm_aapcs_vfpcc <4 x float> @v(...) local_unnamed_addr #0 + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0 + + attributes #0 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4} + !llvm.ident = !{!8} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "v.c", directory: "/") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 2} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !8 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"} + !9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !13) + !10 = !DISubroutineType(types: !11) + !11 = !{!12} + !12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) + !13 = !{!14} + !14 = !DILocalVariable(name: "vec", scope: !9, file: !1, line: 4, type: !15) + !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec2", file: !1, line: 1, baseType: !16) + !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, flags: DIFlagVector, elements: !17) + !17 = !{!18} + !18 = !DISubrange(count: 4) + !19 = !DILocation(line: 4, column: 13, scope: !9) + !20 = !DIExpression(DW_OP_plus, 1, DW_OP_minus, 1) + !21 = !DILocation(line: 4, column: 7, scope: !9) + !22 = !DILocation(line: 5, column: 9, scope: !9) + !23 = !DILocation(line: 5, column: 18, scope: !9) + !24 = !DILocation(line: 5, column: 16, scope: !9) + !25 = !DILocation(line: 5, column: 2, scope: !9) + +... +--- +name: f +alignment: 1 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13', + '%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4', + '%r5', '%r6', '%r7', '%r8', '%r10', '%r11', '%s16', + '%s17', '%s18', '%s19', '%s20', '%s21', '%s22', + '%s23', '%s24', '%s25', '%s26', '%s27', '%s28', + '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11', '%d10_d12', + '%d11_d13', '%d12_d14', '%d13_d15', '%q4_q5', '%q5_q6', + '%q6_q7', '%q4_q5_q6_q7', '%r4_r5', '%r6_r7', '%r10_r11', + '%d8_d9_d10', '%d9_d10_d11', '%d10_d11_d12', '%d11_d12_d13', + '%d12_d13_d14', '%d13_d14_d15', '%d8_d10_d12', + '%d9_d11_d13', '%d10_d12_d14', '%d11_d13_d15', + '%d8_d10_d12_d14', '%d9_d11_d13_d15', '%d9_d10', + '%d11_d12', '%d13_d14', '%d9_d10_d11_d12', '%d11_d12_d13_d14' ] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 4 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +stack: + - { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' } +body: | + bb.0.entry: + liveins: %lr + + early-clobber %sp = frame-setup t2STR_PRE killed undef %lr, %sp, -4, 14, _ + frame-setup CFI_INSTRUCTION def_cfa_offset 4 + frame-setup CFI_INSTRUCTION offset %lr, -4 + tBL 14, _, @v, csr_ios, implicit-def dead %lr, implicit %sp, implicit-def %sp, implicit-def %r0, implicit-def %r1, implicit-def %r2, implicit-def %r3, debug-location !19 + %d1 = VMOVDRR killed %r2, killed %r3, 14, _, implicit-def %q0, debug-location !19 + %d0 = VMOVDRR killed %r0, killed %r1, 14, _, implicit killed %q0, implicit-def %q0, debug-location !19 + DBG_VALUE debug-use %q0, debug-use _, !14, !20, debug-location !21 + %s4 = VMOVS %s1, 14, _, implicit-def %d2, debug-location !24 + %d0 = VADDfd %d0, killed %d2, 14, _, implicit killed %q0, debug-location !24 + %r0 = VMOVRS %s0, 14, _, implicit killed %d0, debug-location !25 + %lr, %sp = t2LDR_POST %sp, 4, 14, _, debug-location !25 + tBX_RET 14, _, implicit %r0, debug-location !25 + +... -- 2.40.0