
By chance, two things have prevented the autoupgrade path being exercised much so far: * LLParser setting the debug-info mode to "old" on seeing intrinsics, * The test in AutoUpgrade.cpp wanting to upgrade into a "new" debug-info block. In practice, this appears to mean this code path hasn't seen the various invalid inputs that can come its way. This commit does a number of things: * Tolerates the various illegal inputs that can be written with debug-intrinsics, and that must be tolerated until the Verifier runs, * Printing illegal/null DbgRecord fields must succeed, * Verifier errors need to localise the function/block where the error is, * Tests that now see debug records will print debug-record errors, Plus a few new tests for other intrinsic-to-debug-record failures modes I found. There are also two edge cases: * Some of the unit tests switch back and forth between intrinsic and record modes at will; I've deleted coverage and some assertions to tolerate this as intrinsic support is now Gone (TM), * In sroa-extract-bits.ll, the order of debug records flips. This is because the autoupgrader upgrades in the opposite order to the basic block conversion routines... which doesn't change the record order, but _does_ change the use list order in Metadata! This should (TM) have no consequence to the correctness of LLVM, but will change the order of various records and the order of DWARF record output too. I tried to reduce this patch to a smaller collection of changes, but they're all intertwined, sorry.
206 lines
12 KiB
LLVM
206 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
|
|
; RUN: opt -passes='sroa<preserve-cfg>' %s -S | FileCheck %s
|
|
; RUN: opt -passes='sroa<modify-cfg>' %s -S | FileCheck %s
|
|
|
|
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
|
|
|
|
; The alloca is split into two fragments: variable x is in the first, variables y and z are in the second
|
|
define i8 @test1(i32 %arg) {
|
|
; CHECK-LABEL: define i8 @test1(
|
|
; CHECK-SAME: i32 [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]], [[META2:![0-9]+]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8), [[META7:![0-9]+]])
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i24
|
|
; CHECK-NEXT: #dbg_value(i24 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META8:![0-9]+]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: #dbg_value(i24 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META10:![0-9]+]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 8, 16), [[META7]])
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !9, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 8, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !8, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 16, 16)), !dbg !7
|
|
store i32 %arg, ptr %ptr, align 4
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
; The alloca is split into three fragments corresponding to the variables x, y, z
|
|
define i8 @test2(i32 %arg1, i8 %arg2) {
|
|
; CHECK-LABEL: define i8 @test2(
|
|
; CHECK-SAME: i32 [[ARG1:%.*]], i8 [[ARG2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG1]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]], [[META2]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i16
|
|
; CHECK-NEXT: #dbg_value(i16 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META8]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 16), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 24
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_21_0_EXTRACT_SHIFT]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 [[PTR_SROA_21_0_EXTRACT_TRUNC]], [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: #dbg_value(i8 [[ARG2]], [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !9, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 8, 16)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !8, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 24, 8)), !dbg !7
|
|
store i32 %arg1, ptr %ptr, align 4
|
|
%gep = getelementptr i8, ptr %ptr, i32 3
|
|
store i8 %arg2, ptr %gep, align 1
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
; The alloca is split into two fragments, with variable x being half in one and half in the other
|
|
; FIXME: We currently generate no debug info for x in this case
|
|
define i8 @test3(i32 %arg) {
|
|
; CHECK-LABEL: define i8 @test3(
|
|
; CHECK-SAME: i32 [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG]] to i8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i24
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 16)), !dbg !7
|
|
store i32 %arg, ptr %ptr, align 4
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
; The alloca is split into two fragments, with variable y being half in one and half in the other
|
|
; FIXME: We currently generate no debug info for y in this case
|
|
define i16 @test4(i32 %arg) {
|
|
; CHECK-LABEL: define i16 @test4(
|
|
; CHECK-SAME: i32 [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG]] to i16
|
|
; CHECK-NEXT: #dbg_value(i16 [[PTR_SROA_0_0_EXTRACT_TRUNC]], [[META2]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG]], 16
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i16
|
|
; CHECK-NEXT: #dbg_value(i16 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 8, 8), [[META7]])
|
|
; CHECK-NEXT: ret i16 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !9, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 8, 16)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !8, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 24, 8)), !dbg !7
|
|
store i32 %arg, ptr %ptr, align 4
|
|
%ret = load i16, ptr %ptr, align 4
|
|
ret i16 %ret
|
|
}
|
|
|
|
; Struct where the first element is an ordinary char, the second is a bitfield of two elements, and the third is padding
|
|
%struct.struct_t = type <{ i8, i16, i8 }>
|
|
define i8 @test5(i32 %arg) {
|
|
; CHECK-LABEL: define i8 @test5(
|
|
; CHECK-SAME: i32 [[ARG:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]], [[META11:![0-9]+]], !DIExpression(), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i24
|
|
; CHECK-NEXT: #dbg_value(i24 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META8]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: #dbg_value(i24 [[PTR_SROA_2_0_EXTRACT_TRUNC]], [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 8, 8), [[META7]])
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca %struct.struct_t, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !11, metadata !DIExpression()), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !9, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 8, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !8, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 16, 8)), !dbg !7
|
|
store i32 %arg, ptr %ptr, align 4
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
; Sign mismatch between extract expression and debug variable type.
|
|
define i8 @test6(i32 %arg1, i8 %arg2) {
|
|
; CHECK-LABEL: define i8 @test6(
|
|
; CHECK-SAME: i32 [[ARG1:%.*]], i8 [[ARG2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG1]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 poison, [[META2]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i16
|
|
; CHECK-NEXT: #dbg_value(i16 poison, [[META8]], !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 16), [[META7]])
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 24
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_21_0_EXTRACT_SHIFT]] to i8
|
|
; CHECK-NEXT: #dbg_value(i8 poison, [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: #dbg_value(i8 poison, [[META10]], !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8), [[META7]])
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 0, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !9, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 8, 16)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !8, metadata !DIExpression(DW_OP_LLVM_extract_bits_sext, 24, 8)), !dbg !7
|
|
store i32 %arg1, ptr %ptr, align 4
|
|
%gep = getelementptr i8, ptr %ptr, i32 3
|
|
store i8 %arg2, ptr %gep, align 1
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
; Combine extract_bits and fragment in a way such that the bottom 8 bits of
|
|
; the alloca are the top 8 bits of variable x and vice versa.
|
|
; FIXME: We currently don't handle this and generate no debug info
|
|
define i8 @test7(i32 %arg1, i8 %arg2) {
|
|
; CHECK-LABEL: define i8 @test7(
|
|
; CHECK-SAME: i32 [[ARG1:%.*]], i8 [[ARG2:%.*]]) {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[PTR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARG1]] to i8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 8
|
|
; CHECK-NEXT: [[PTR_SROA_2_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_2_0_EXTRACT_SHIFT]] to i16
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[ARG1]], 24
|
|
; CHECK-NEXT: [[PTR_SROA_21_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[PTR_SROA_21_0_EXTRACT_SHIFT]] to i8
|
|
; CHECK-NEXT: ret i8 [[PTR_SROA_0_0_EXTRACT_TRUNC]]
|
|
;
|
|
entry:
|
|
%ptr = alloca i32, align 4
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 0, 8, DW_OP_LLVM_fragment, 24, 8)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 8, 16, DW_OP_LLVM_fragment, 8, 16)), !dbg !7
|
|
call void @llvm.dbg.declare(metadata ptr %ptr, metadata !2, metadata !DIExpression(DW_OP_LLVM_extract_bits_zext, 24, 8, DW_OP_LLVM_fragment, 0, 8)), !dbg !7
|
|
store i32 %arg1, ptr %ptr, align 4
|
|
%gep = getelementptr i8, ptr %ptr, i32 3
|
|
store i8 %arg2, ptr %gep, align 1
|
|
%ret = load i8, ptr %ptr, align 4
|
|
ret i8 %ret
|
|
}
|
|
|
|
!llvm.module.flags = !{!0, !1}
|
|
!0 = !{i32 7, !"Dwarf Version", i32 5}
|
|
!1 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!2 = !DILocalVariable(name: "x", scope: !3, type: !6)
|
|
!3 = distinct !DISubprogram(name: "test", unit: !4)
|
|
!4 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !5, emissionKind: FullDebug)
|
|
!5 = !DIFile(filename: "dbg-bit-piece.cpp", directory: "")
|
|
!6 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
|
|
!7 = !DILocation(line: 0, column: 0, scope: !3)
|
|
!8 = !DILocalVariable(name: "z", scope: !3, type: !6)
|
|
!9 = !DILocalVariable(name: "y", scope: !3, type: !10)
|
|
!10 = !DIBasicType(name: "signed int", size: 32, encoding: DW_ATE_signed)
|
|
!11 = !DILocalVariable(name: "x", scope: !3, type: !12)
|
|
!12 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
|
|
;.
|
|
; CHECK: [[META2]] = !DILocalVariable(name: "x", scope: [[META3:![0-9]+]], type: [[META6:![0-9]+]])
|
|
; CHECK: [[META3]] = distinct !DISubprogram(name: "test", scope: null, spFlags: DISPFlagDefinition, unit: [[META4:![0-9]+]])
|
|
; CHECK: [[META4]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META5:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
|
; CHECK: [[META5]] = !DIFile(filename: "dbg-bit-piece.cpp", directory: "")
|
|
; CHECK: [[META6]] = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
|
|
; CHECK: [[META7]] = !DILocation(line: 0, scope: [[META3]])
|
|
; CHECK: [[META8]] = !DILocalVariable(name: "y", scope: [[META3]], type: [[META9:![0-9]+]])
|
|
; CHECK: [[META9]] = !DIBasicType(name: "signed int", size: 32, encoding: DW_ATE_signed)
|
|
; CHECK: [[META10]] = !DILocalVariable(name: "z", scope: [[META3]], type: [[META6]])
|
|
; CHECK: [[META11]] = !DILocalVariable(name: "x", scope: [[META3]], type: [[META12:![0-9]+]])
|
|
; CHECK: [[META12]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
;.
|