Refactor unwind generation in Cranelift.

This commit makes the following changes to unwind information generation in
Cranelift:

* Remove frame layout change implementation in favor of processing the prologue
  and epilogue instructions when unwind information is requested.  This also
  means this work is no longer performed for Windows, which didn't utilize it.
  It also helps simplify the prologue and epilogue generation code.

* Remove the unwind sink implementation that required each unwind information
  to be represented in final form. For FDEs, this meant writing a
  complete frame table per function, which wastes 20 bytes or so for each
  function with duplicate CIEs.  This also enables Cranelift users to collect the
  unwind information and write it as a single frame table.

* For System V calling convention, the unwind information is no longer stored
  in code memory (it's only a requirement for Windows ABI to do so).  This allows
  for more compact code memory for modules with a lot of functions.

* Deletes some duplicate code relating to frame table generation.  Users can
  now simply use gimli to create a frame table from each function's unwind
  information.

Fixes #1181.
This commit is contained in:
Peter Huene
2020-03-30 19:48:02 -07:00
parent 7da6101732
commit f7e9f86ba9
42 changed files with 2678 additions and 3161 deletions

View File

@@ -0,0 +1,197 @@
test unwind
set opt_level=speed_and_size
set is_pic
target x86_64 haswell
; check the unwind information with a function with no args
function %no_args() system_v {
block0:
return
}
; sameln: 0x00000000: CIE
; nextln: length: 0x00000014
; nextln: version: 0x01
; nextln: code_align: 1
; nextln: data_align: -8
; nextln: ra_register: 0x10
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_offset (r16, 1)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: Instructions: Init State:
; nextln:
; nextln:
; nextln: 0x00000018: FDE
; nextln: length: 0x00000024
; nextln: CIE_pointer: 0x00000000
; nextln: start_addr: 0x0000000000000000
; nextln: range_size: 0x0000000000000006 (end_addr = 0x0000000000000006)
; nextln: Instructions:
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa_offset (16)
; nextln: DW_CFA_offset (r6, 2)
; nextln: DW_CFA_advance_loc (3)
; nextln: DW_CFA_def_cfa_register (r6)
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; check a function with medium-sized stack alloc
function %medium_stack() system_v {
ss0 = explicit_slot 100000
block0:
return
}
; sameln: 0x00000000: CIE
; nextln: length: 0x00000014
; nextln: version: 0x01
; nextln: code_align: 1
; nextln: data_align: -8
; nextln: ra_register: 0x10
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_offset (r16, 1)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: Instructions: Init State:
; nextln:
; nextln:
; nextln: 0x00000018: FDE
; nextln: length: 0x00000024
; nextln: CIE_pointer: 0x00000000
; nextln: start_addr: 0x0000000000000000
; nextln: range_size: 0x000000000000001a (end_addr = 0x000000000000001a)
; nextln: Instructions:
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa_offset (16)
; nextln: DW_CFA_offset (r6, 2)
; nextln: DW_CFA_advance_loc (3)
; nextln: DW_CFA_def_cfa_register (r6)
; nextln: DW_CFA_advance_loc (21)
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; check a function with large-sized stack alloc
function %large_stack() system_v {
ss0 = explicit_slot 524288
block0:
return
}
; sameln: 0x00000000: CIE
; nextln: length: 0x00000014
; nextln: version: 0x01
; nextln: code_align: 1
; nextln: data_align: -8
; nextln: ra_register: 0x10
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_offset (r16, 1)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: Instructions: Init State:
; nextln:
; nextln:
; nextln: 0x00000018: FDE
; nextln: length: 0x00000024
; nextln: CIE_pointer: 0x00000000
; nextln: start_addr: 0x0000000000000000
; nextln: range_size: 0x000000000000001a (end_addr = 0x000000000000001a)
; nextln: Instructions:
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa_offset (16)
; nextln: DW_CFA_offset (r6, 2)
; nextln: DW_CFA_advance_loc (3)
; nextln: DW_CFA_def_cfa_register (r6)
; nextln: DW_CFA_advance_loc (21)
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln:
; check a function that has CSRs
function %lots_of_registers(i64, i64) system_v {
block0(v0: i64, v1: i64):
v2 = load.i32 v0+0
v3 = load.i32 v0+8
v4 = load.i32 v0+16
v5 = load.i32 v0+24
v6 = load.i32 v0+32
v7 = load.i32 v0+40
v8 = load.i32 v0+48
v9 = load.i32 v0+56
v10 = load.i32 v0+64
v11 = load.i32 v0+72
v12 = load.i32 v0+80
v13 = load.i32 v0+88
v14 = load.i32 v0+96
store.i32 v2, v1+0
store.i32 v3, v1+8
store.i32 v4, v1+16
store.i32 v5, v1+24
store.i32 v6, v1+32
store.i32 v7, v1+40
store.i32 v8, v1+48
store.i32 v9, v1+56
store.i32 v10, v1+64
store.i32 v11, v1+72
store.i32 v12, v1+80
store.i32 v13, v1+88
store.i32 v14, v1+96
return
}
; sameln: 0x00000000: CIE
; nextln: length: 0x00000014
; nextln: version: 0x01
; nextln: code_align: 1
; nextln: data_align: -8
; nextln: ra_register: 0x10
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_offset (r16, 1)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: Instructions: Init State:
; nextln:
; nextln:
; nextln: 0x00000018: FDE
; nextln: length: 0x00000034
; nextln: CIE_pointer: 0x00000000
; nextln: start_addr: 0x0000000000000000
; nextln: range_size: 0x0000000000000074 (end_addr = 0x0000000000000074)
; nextln: Instructions:
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa_offset (16)
; nextln: DW_CFA_offset (r6, 2)
; nextln: DW_CFA_advance_loc (3)
; nextln: DW_CFA_def_cfa_register (r6)
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_offset (r3, 3)
; nextln: DW_CFA_advance_loc (2)
; nextln: DW_CFA_offset (r12, 4)
; nextln: DW_CFA_advance_loc (2)
; nextln: DW_CFA_offset (r13, 5)
; nextln: DW_CFA_advance_loc (2)
; nextln: DW_CFA_offset (r14, 6)
; nextln: DW_CFA_advance_loc (2)
; nextln: DW_CFA_offset (r15, 7)
; nextln: DW_CFA_advance_loc (102)
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop

View File

@@ -3,46 +3,29 @@ set opt_level=speed_and_size
set is_pic
target x86_64 haswell
; check that there is no unwind information for a system_v function
function %not_fastcall() system_v {
block0:
return
}
; sameln: No unwind information.
; check the unwind information with a function with no args
function %no_args() windows_fastcall {
block0:
return
}
; sameln: UnwindInfo {
; nextln: version: 1,
; nextln: flags: 0,
; nextln: prologue_size: 8,
; nextln: unwind_code_count_raw: 3,
; nextln: frame_register: 5,
; nextln: frame_register_offset: 0,
; nextln: unwind_codes: [
; nextln: UnwindCode {
; nextln: offset: 8,
; nextln: op: SmallStackAlloc,
; nextln: info: 3,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 4,
; nextln: op: SetFramePointer,
; nextln: info: 0,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 1,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 5,
; nextln: value: None,
; nextln: },
; nextln: ],
; nextln: }
; sameln: version: 1
; nextln: flags: 0
; nextln: prologue size: 8
; nextln: frame register: 5
; nextln: frame register offset: 0
; nextln: unwind codes: 3
; nextln:
; nextln: offset: 1
; nextln: op: PushNonvolatileRegister
; nextln: info: 5
; nextln:
; nextln: offset: 4
; nextln: op: SetFramePointer
; nextln: info: 0
; nextln:
; nextln: offset: 8
; nextln: op: SmallStackAlloc
; nextln: info: 3
; check a function with medium-sized stack alloc
function %medium_stack() windows_fastcall {
@@ -50,36 +33,25 @@ function %medium_stack() windows_fastcall {
block0:
return
}
; sameln: UnwindInfo {
; nextln: version: 1,
; nextln: flags: 0,
; nextln: prologue_size: 17,
; nextln: unwind_code_count_raw: 4,
; nextln: frame_register: 5,
; nextln: frame_register_offset: 0,
; nextln: unwind_codes: [
; nextln: UnwindCode {
; nextln: offset: 17,
; nextln: op: LargeStackAlloc,
; nextln: info: 0,
; nextln: value: U16(
; nextln: 12504,
; nextln: ),
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 4,
; nextln: op: SetFramePointer,
; nextln: info: 0,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 1,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 5,
; nextln: value: None,
; nextln: },
; nextln: ],
; nextln: }
; sameln: version: 1
; nextln: flags: 0
; nextln: prologue size: 17
; nextln: frame register: 5
; nextln: frame register offset: 0
; nextln: unwind codes: 3
; nextln:
; nextln: offset: 1
; nextln: op: PushNonvolatileRegister
; nextln: info: 5
; nextln:
; nextln: offset: 4
; nextln: op: SetFramePointer
; nextln: info: 0
; nextln:
; nextln: offset: 17
; nextln: op: LargeStackAlloc
; nextln: info: 0
; nextln: value: 12504 (u16)
; check a function with large-sized stack alloc
function %large_stack() windows_fastcall {
@@ -87,36 +59,25 @@ function %large_stack() windows_fastcall {
block0:
return
}
; sameln: UnwindInfo {
; nextln: version: 1,
; nextln: flags: 0,
; nextln: prologue_size: 17,
; nextln: unwind_code_count_raw: 5,
; nextln: frame_register: 5,
; nextln: frame_register_offset: 0,
; nextln: unwind_codes: [
; nextln: UnwindCode {
; nextln: offset: 17,
; nextln: op: LargeStackAlloc,
; nextln: info: 1,
; nextln: value: U32(
; nextln: 524320,
; nextln: ),
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 4,
; nextln: op: SetFramePointer,
; nextln: info: 0,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 1,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 5,
; nextln: value: None,
; nextln: },
; nextln: ],
; nextln: }
; sameln: version: 1
; nextln: flags: 0
; nextln: prologue size: 17
; nextln: frame register: 5
; nextln: frame register offset: 0
; nextln: unwind codes: 3
; nextln:
; nextln: offset: 1
; nextln: op: PushNonvolatileRegister
; nextln: info: 5
; nextln:
; nextln: offset: 4
; nextln: op: SetFramePointer
; nextln: info: 0
; nextln:
; nextln: offset: 17
; nextln: op: LargeStackAlloc
; nextln: info: 1
; nextln: value: 524320 (u32)
function %fpr_with_function_call(i64, i64) windows_fastcall {
fn0 = %foo(f64, f64, i64, i64, i64) windows_fastcall;
@@ -150,20 +111,34 @@ block0(v0: i64, v1: i64):
; area that does not overlap either the callee's shadow space or stack argument
; space.
;
; sameln: UnwindInfo {
; nextln: version: 1,
; nextln: flags: 0,
; nextln: prologue_size: 25,
; nextln: unwind_code_count_raw: 7,
; nextln: frame_register: 5,
; nextln: frame_register_offset: 12,
; nextln: unwind_codes: [
; nextln: UnwindCode {
; nextln: offset: 25,
; nextln: op: SaveXmm128,
; nextln: info: 15,
; nextln: value: U16(
; nextln: 3,
; sameln: version: 1
; nextln: flags: 0
; nextln: prologue size: 25
; nextln: frame register: 5
; nextln: frame register offset: 12
; nextln: unwind codes: 5
; nextln:
; nextln: offset: 1
; nextln: op: PushNonvolatileRegister
; nextln: info: 5
; nextln:
; nextln: offset: 4
; nextln: op: SetFramePointer
; nextln: info: 0
; nextln:
; nextln: offset: 6
; nextln: op: PushNonvolatileRegister
; nextln: info: 15
; nextln:
; nextln: offset: 13
; nextln: op: LargeStackAlloc
; nextln: info: 0
; nextln: value: 23 (u16)
; nextln:
; nextln: offset: 25
; nextln: op: SaveXmm128
; nextln: info: 15
; nextln: value: 3 (u16)
; check a function that has CSRs
function %lots_of_registers(i64, i64) windows_fastcall {
@@ -214,97 +189,64 @@ block0(v0: i64, v1: i64):
store.f64 v23, v1+168
return
}
; sameln: UnwindInfo {
; nextln: version: 1,
; nextln: flags: 0,
; nextln: prologue_size: 41,
; nextln: unwind_code_count_raw: 16,
; nextln: frame_register: 5,
; nextln: frame_register_offset: 10,
; nextln: unwind_codes: [
; nextln: UnwindCode {
; nextln: offset: 41,
; nextln: op: SaveXmm128,
; nextln: info: 8,
; nextln: value: U16(
; nextln: 2,
; nextln: ),
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 36,
; nextln: op: SaveXmm128,
; nextln: info: 7,
; nextln: value: U16(
; nextln: 1,
; nextln: ),
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 31,
; nextln: op: SaveXmm128,
; nextln: info: 6,
; nextln: value: U16(
; nextln: 0,
; nextln: ),
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 19,
; nextln: op: SmallStackAlloc,
; nextln: info: 12,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 15,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 15,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 13,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 14,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 11,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 13,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 9,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 12,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 7,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 7,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 6,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 6,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 5,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 3,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 4,
; nextln: op: SetFramePointer,
; nextln: info: 0,
; nextln: value: None,
; nextln: },
; nextln: UnwindCode {
; nextln: offset: 1,
; nextln: op: PushNonvolatileRegister,
; nextln: info: 5,
; nextln: value: None,
; nextln: },
; nextln: ],
; nextln: }
; sameln: version: 1
; nextln: flags: 0
; nextln: prologue size: 41
; nextln: frame register: 5
; nextln: frame register offset: 10
; nextln: unwind codes: 13
; nextln:
; nextln: offset: 1
; nextln: op: PushNonvolatileRegister
; nextln: info: 5
; nextln:
; nextln: offset: 4
; nextln: op: SetFramePointer
; nextln: info: 0
; nextln:
; nextln: offset: 5
; nextln: op: PushNonvolatileRegister
; nextln: info: 3
; nextln:
; nextln: offset: 6
; nextln: op: PushNonvolatileRegister
; nextln: info: 6
; nextln:
; nextln: offset: 7
; nextln: op: PushNonvolatileRegister
; nextln: info: 7
; nextln:
; nextln: offset: 9
; nextln: op: PushNonvolatileRegister
; nextln: info: 12
; nextln:
; nextln: offset: 11
; nextln: op: PushNonvolatileRegister
; nextln: info: 13
; nextln:
; nextln: offset: 13
; nextln: op: PushNonvolatileRegister
; nextln: info: 14
; nextln:
; nextln: offset: 15
; nextln: op: PushNonvolatileRegister
; nextln: info: 15
; nextln:
; nextln: offset: 19
; nextln: op: SmallStackAlloc
; nextln: info: 12
; nextln:
; nextln: offset: 31
; nextln: op: SaveXmm128
; nextln: info: 6
; nextln: value: 0 (u16)
; nextln:
; nextln: offset: 36
; nextln: op: SaveXmm128
; nextln: info: 7
; nextln: value: 1 (u16)
; nextln:
; nextln: offset: 41
; nextln: op: SaveXmm128
; nextln: info: 8
; nextln: value: 2 (u16)

View File

@@ -1,54 +0,0 @@
test fde
set opt_level=speed_and_size
set is_pic
target x86_64 haswell
; check that there is no libunwind information for a windows_fastcall function
function %not_fastcall() windows_fastcall {
block0:
return
}
; sameln: No unwind information.
; check the libunwind information with a function with no args
function %no_args() system_v {
block0:
return
}
; sameln: 0x00000000: CIE
; nextln: length: 0x00000014
; nextln: version: 0x01
; nextln: code_align: 1
; nextln: data_align: -8
; nextln: ra_register: 0x10
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_offset (r16, 1)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: Instructions: Init State:
; nextln:
; nextln:
; nextln: 0x00000018: FDE
; nextln: length: 0x00000024
; nextln: CIE_pointer: 0x00000000
; nextln: start_addr: 0x0000000000000000
; nextln: range_size: 0x0000000000000006 (end_addr = 0x0000000000000006)
; nextln: Instructions:
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa_offset (16)
; nextln: DW_CFA_offset (r6, 2)
; nextln: DW_CFA_advance_loc (3)
; nextln: DW_CFA_def_cfa_register (r6)
; nextln: DW_CFA_advance_loc (1)
; nextln: DW_CFA_def_cfa (r7, 8)
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln: DW_CFA_nop
; nextln:
; nextln: Entry: 24
; nextln: Relocs: [(Abs8, 32)]