1// This test checks various cases around sharing opcodes between epilogue and prologue with more than one epilogue. 2 3// RUN: llvm-mc -triple thumbv7-pc-win32 -filetype=obj %s | llvm-readobj -u - | FileCheck %s 4 5// CHECK: RuntimeFunction { 6// CHECK-NEXT: Function: func1 7// CHECK-NEXT: ExceptionRecord: 8// CHECK-NEXT: ExceptionData { 9// CHECK-NEXT: FunctionLength: 10// CHECK-NEXT: Version: 11// CHECK-NEXT: ExceptionData: 12// CHECK-NEXT: EpiloguePacked: No 13// CHECK-NEXT: Fragment: 14// CHECK-NEXT: EpilogueScopes: 3 15// CHECK-NEXT: ByteCodeLength: 12 16// CHECK-NEXT: Prologue [ 17// CHECK-NEXT: 0xf5 0x15 ; vpush {d1-d5} 18// CHECK-NEXT: 0x05 ; sub sp, #(5 * 4) 19// CHECK-NEXT: 0xa0 0xf0 ; push.w {r4-r7, lr} 20// CHECK-NEXT: ] 21// CHECK-NEXT: EpilogueScopes [ 22// CHECK-NEXT: EpilogueScope { 23// CHECK-NEXT: StartOffset: 6 24// CHECK-NEXT: Condition: 14 25// CHECK-NEXT: EpilogueStartIndex: 6 26// CHECK-NEXT: Opcodes [ 27// CHECK-NEXT: 0x08 ; add sp, #(8 * 4) 28// CHECK-NEXT: 0xfd ; bx <reg> 29// CHECK-NEXT: ] 30// CHECK-NEXT: } 31// CHECK-NEXT: EpilogueScope { 32// CHECK-NEXT: StartOffset: 9 33// CHECK-NEXT: Condition: 14 34// CHECK-NEXT: EpilogueStartIndex: 8 35// CHECK-NEXT: Opcodes [ 36// CHECK-NEXT: 0x10 ; add sp, #(16 * 4) 37// CHECK-NEXT: 0xfd ; bx <reg> 38// CHECK-NEXT: ] 39// CHECK-NEXT: } 40// CHECK-NEXT: EpilogueScope { 41// CHECK-NEXT: StartOffset: 13 42// CHECK-NEXT: Condition: 10 43// CHECK-NEXT: EpilogueStartIndex: 6 44// CHECK-NEXT: Opcodes [ 45// CHECK-NEXT: 0x08 ; add sp, #(8 * 4) 46// CHECK-NEXT: 0xfd ; bx <reg> 47// CHECK-NEXT: ] 48// CHECK-NEXT: } 49// CHECK-NEXT: ] 50// CHECK-NEXT: } 51// CHECK-NEXT: } 52// CHECK-NEXT: RuntimeFunction { 53// CHECK-NEXT: Function: func2 54// CHECK-NEXT: ExceptionRecord: 55// CHECK-NEXT: ExceptionData { 56// CHECK-NEXT: FunctionLength: 57// CHECK-NEXT: Version: 58// CHECK-NEXT: ExceptionData: 59// CHECK-NEXT: EpiloguePacked: No 60// CHECK-NEXT: Fragment: 61// CHECK-NEXT: EpilogueScopes: 3 62// CHECK-NEXT: ByteCodeLength: 12 63// CHECK-NEXT: Prologue [ 64// CHECK-NEXT: 0xf5 0x15 ; vpush {d1-d5} 65// CHECK-NEXT: 0x05 ; sub sp, #(5 * 4) 66// CHECK-NEXT: 0xa0 0xf0 ; push.w {r4-r7, lr} 67// CHECK-NEXT: 0xfe ; b.w <target> 68// CHECK-NEXT: ] 69// CHECK-NEXT: EpilogueScopes [ 70// CHECK-NEXT: EpilogueScope { 71// CHECK-NEXT: StartOffset: 6 72// CHECK-NEXT: Condition: 14 73// CHECK-NEXT: EpilogueStartIndex: 2 74// CHECK-NEXT: Opcodes [ 75// CHECK-NEXT: 0x05 ; add sp, #(5 * 4) 76// CHECK-NEXT: 0xa0 0xf0 ; pop.w {r4-r7, pc} 77// CHECK-NEXT: 0xfe ; b.w <target> 78// CHECK-NEXT: ] 79// CHECK-NEXT: } 80// CHECK-NEXT: EpilogueScope { 81// CHECK-NEXT: StartOffset: 11 82// CHECK-NEXT: Condition: 14 83// CHECK-NEXT: EpilogueStartIndex: 3 84// CHECK-NEXT: Opcodes [ 85// CHECK-NEXT: 0xa0 0xf0 ; pop.w {r4-r7, pc} 86// CHECK-NEXT: 0xfe ; b.w <target> 87// CHECK-NEXT: ] 88// CHECK-NEXT: } 89// CHECK-NEXT: EpilogueScope { 90// CHECK-NEXT: StartOffset: 15 91// CHECK-NEXT: Condition: 14 92// CHECK-NEXT: EpilogueStartIndex: 6 93// CHECK-NEXT: Opcodes [ 94// CHECK-NEXT: 0xa0 0xf0 ; pop.w {r4-r7, pc} 95// CHECK-NEXT: 0xfd ; bx <reg> 96// CHECK-NEXT: ] 97// CHECK-NEXT: } 98// CHECK-NEXT: ] 99// CHECK-NEXT: } 100// CHECK-NEXT: } 101 102 .text 103 .syntax unified 104 105 .seh_proc func1 106func1: 107 push.w {r4-r7,lr} 108 .seh_save_regs_w {r4-r7,lr} 109 sub sp, sp, #20 110 .seh_stackalloc 20 111 vpush {d1-d5} 112 .seh_save_fregs {d1-d5} 113 .seh_endprologue 114 nop 115 116 // Entirely different epilogue; can't be shared with the prologue. 117 .seh_startepilogue 118 add sp, sp, #32 119 .seh_stackalloc 32 120 bx lr 121 .seh_nop 122 .seh_endepilogue 123 124 nop 125 126 // Also a differing epilogue. 127 .seh_startepilogue 128 add sp, sp, #64 129 .seh_stackalloc 64 130 bx lr 131 .seh_nop 132 .seh_endepilogue 133 134 nop 135 136 // Epilogue matches the first one; will reuse that epilogue's opcodes, 137 // even if they differ in conditionality. 138 itt ge 139 .seh_startepilogue_cond ge 140 addge sp, sp, #32 141 .seh_stackalloc 32 142 bxge lr 143 .seh_nop 144 .seh_endepilogue 145 .seh_endproc 146 147 .seh_proc func2 148func2: 149 push.w {r4-r7,lr} 150 .seh_save_regs_w {r4-r7,lr} 151 sub sp, sp, #20 152 .seh_stackalloc 20 153 vpush {d1-d5} 154 .seh_save_fregs {d1-d5} 155 .seh_endprologue 156 157 nop 158 159 .seh_startepilogue 160 add sp, sp, #20 161 .seh_stackalloc 20 162 // As we're popping into lr instead of directly into pc, this pop 163 // becomes a wide instruction. To match prologue vs epilogue, the 164 // push in the prologue has been made wide too. 165 pop.w {r4-r7,lr} 166 .seh_save_regs_w {r4-r7,lr} 167 b.w tailcall 168 // Ending with a different end opcode, but can still be shared with 169 // the prolog. 170 .seh_nop_w 171 .seh_endepilogue 172 173 // Another epilogue, matching the end of the previous epilogue. 174 .seh_startepilogue 175 pop.w {r4-r7,lr} 176 .seh_save_regs_w {r4-r7,lr} 177 b.w tailcall 178 .seh_nop_w 179 .seh_endepilogue 180 181 // This epilogue differs in the end opcode, and can't be shared with 182 // the prologue. 183 .seh_startepilogue 184 pop.w {r4-r7,lr} 185 .seh_save_regs_w {r4-r7,lr} 186 bx lr 187 .seh_nop 188 .seh_endepilogue 189 .seh_endproc 190