reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
; RUN: llc -o - %s -mtriple=aarch64-windows -verify-machineinstrs | FileCheck %s
; RUN: llc -o %t -filetype=obj %s -mtriple=aarch64-windows
; RUN: llvm-readobj --unwind %t | FileCheck %s -check-prefix=UNWIND

; We test the following
; 1) That the unwind help object is created and that its offset from the stack
;    pointer on entry is patched into the table fed to __CxxFrameHandler3
; 2) That the stack update for the catch funclet only includes the callee saved
;    registers
; 3) That the locals are accessed using the frame pointer in both the funclet
;    and the parent function.

; The following checks that the unwind help object has -2 stored into it at
; fp - 400 - 256 = fp - 656, which is on-entry sp - 48 + 32 - 656 =
; on-entry sp - 672.  We check this offset in the table later on.

; CHECK-LABEL: "?func@@YAHXZ":
; CHECK:       stp     x29, x30, [sp, #-48]!
; CHECK:       str     x28, [sp, #16]
; CHECK:       str     x21, [sp, #24]
; CHECK:       stp     x19, x20, [sp, #32]
; CHECK:       mov     x29, sp
; CHECK:       sub     sp, sp, #624
; CHECK:       mov     x19, sp
; CHECK:       mov     x0, #-2
; CHECK:       stur    x0, [x19]

; Now check that x is stored at fp - 20.  We check that this is the same
; location accessed from the funclet to retrieve x.
; CHECK:       mov     w8, #1
; CHECK:       stur    w8, [x29, [[X_OFFSET:#-[1-9][0-9]+]]

; Check the offset off the frame pointer at which B is located.
; Check the same offset is used to pass the address of B to init2 in the
; funclet.
; CHECK:       sub     x0, x29, [[B_OFFSET:#[1-9][0-9]+]]
; CHECK:       bl      "?init@@YAXPEAH@Z"

; This is the label for the throw that is encoded in the ip2state.
; We are inside the try block, where we make a call to func2
; CHECK-LABEL: .Ltmp0:
; CHECK:       bl      "?func2@@YAHXZ

; CHECK:        [[CATCHRETDEST:.LBB0_[0-9]+]]:      ; %catchret.dest

; Check the catch funclet.
; CHECK-LABEL: "?catch$2@?0??func@@YAHXZ@4HA":

; Check that the stack space is allocated only for the callee saved registers.
; CHECK:       stp     x29, x30, [sp, #-48]!
; CHECK:       str     x28, [sp, #16]
; CHECK:       str     x21, [sp, #24]
; CHECK:       stp     x19, x20, [sp, #32]
; CHECK:       add     x20, x19, #12

; Check that there are no further stack updates.
; CHECK-NOT:   sub     sp, sp

; Check that the stack address passed to init2 is off the frame pointer, and
; that it matches the address of B in the parent function.
; CHECK:       sub     x0, x29, [[B_OFFSET]]
; CHECK:       bl      "?init2@@YAXPEAH@Z"

; Check that are storing x back to the same location off the frame pointer as in
; the parent function.
; CHECK:       stur    w8, [x29, [[X_OFFSET]]]

; Check that the funclet branches back to the catchret destination
; CHECK:       adrp    x0, .LBB0_3
; CHECK-NEXT:  add     x0, x0, [[CATCHRETDEST]]


; Now check that the offset of the unwind help object from the stack pointer on
; entry to func is encoded in cppxdata that is passed to __CxxFrameHandler3.  As
; computed above, this comes to -672.
; CHECK-LABEL:        "$cppxdata$?func@@YAHXZ":
; CHECK-NEXT:         .word   429065506               ; MagicNumber
; CHECK-NEXT:         .word   2                       ; MaxState
; CHECK-NEXT:         .word   ("$stateUnwindMap$?func@@YAHXZ")@IMGREL ; UnwindMap
; CHECK-NEXT:         .word   1                       ; NumTryBlocks
; CHECK-NEXT:         .word   ("$tryMap$?func@@YAHXZ")@IMGREL ; TryBlockMap
; CHECK-NEXT:         .word   4                       ; IPMapEntries
; CHECK-NEXT:         .word   ("$ip2state$?func@@YAHXZ")@IMGREL ; IPToStateXData
; CHECK-NEXT:         .word   -672                    ; UnwindHelp

; UNWIND: Function: ?func@@YAHXZ (0x0)
; UNWIND: Prologue [
; UNWIND-NEXT: ; nop
; UNWIND-NEXT: ; sub sp, #624
; UNWIND-NEXT: ; mov fp, sp
; UNWIND-NEXT: ; stp x19, x20, [sp, #32]
; UNWIND-NEXT: ; str x21, [sp, #24]
; UNWIND-NEXT: ; str x28, [sp, #16]
; UNWIND-NEXT: ; stp x29, x30, [sp, #-48]!
; UNWIND-NEXT: ; end
; UNWIND: Function: ?catch$2@?0??func@@YAHXZ@4HA
; UNWIND: Prologue [
; UNWIND-NEXT: ; stp x19, x20, [sp, #32]
; UNWIND-NEXT: ; str x21, [sp, #24]
; UNWIND-NEXT: ; str x28, [sp, #16]
; UNWIND-NEXT: ; stp x29, x30, [sp, #-48]!
; UNWIND-NEXT: ; end

target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-windows-msvc19.11.0"

%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 }
%eh.CatchableTypeArray.1 = type { i32, [1 x i32] }
%eh.ThrowInfo = type { i32, i32, i32, i32 }

$"??_R0H@8" = comdat any

$"_CT??_R0H@84" = comdat any

$_CTA1H = comdat any

$_TI1H = comdat any

@"??_7type_info@@6B@" = external constant i8*
@"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
@__ImageBase = external dso_local constant i8
@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat
@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat

; Function Attrs: noinline optnone
define dso_local i32 @"?func@@YAHXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
  %B = alloca [50 x i32], align 4
  %x = alloca i32, align 4
  %tmp = alloca i32, align 4
  %i = alloca i32, align 4
  %C = alloca [100 x i32], align 4
  store i32 1, i32* %x, align 4
  %arraydecay = getelementptr inbounds [50 x i32], [50 x i32]* %B, i32 0, i32 0
  call void @"?init@@YAXPEAH@Z"(i32* %arraydecay)
  %call = invoke i32 @"?func2@@YAHXZ"()
          to label %invoke.cont unwind label %catch.dispatch

invoke.cont:                                      ; preds = %entry
  store i32 %call, i32* %tmp, align 4
  %0 = bitcast i32* %tmp to i8*
  invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #2
          to label %unreachable unwind label %catch.dispatch

catch.dispatch:                                   ; preds = %invoke.cont, %entry
  %1 = catchswitch within none [label %catch] unwind to caller

catch:                                            ; preds = %catch.dispatch
  %2 = catchpad within %1 [%rtti.TypeDescriptor2* @"??_R0H@8", i32 0, i32* %i]
  %arraydecay1 = getelementptr inbounds [100 x i32], [100 x i32]* %C, i32 0, i32 0
  call void @"?init@@YAXPEAH@Z"(i32* %arraydecay1) [ "funclet"(token %2) ]
  %arraydecay2 = getelementptr inbounds [50 x i32], [50 x i32]* %B, i32 0, i32 0
  call void @"?init2@@YAXPEAH@Z"(i32* %arraydecay2) [ "funclet"(token %2) ]
  %3 = load i32, i32* %i, align 4
  %idxprom = sext i32 %3 to i64
  %arrayidx = getelementptr inbounds [50 x i32], [50 x i32]* %B, i64 0, i64 %idxprom
  %4 = load i32, i32* %arrayidx, align 4
  %5 = load i32, i32* %i, align 4
  %idxprom3 = sext i32 %5 to i64
  %arrayidx4 = getelementptr inbounds [100 x i32], [100 x i32]* %C, i64 0, i64 %idxprom3
  %6 = load i32, i32* %arrayidx4, align 4
  %add = add nsw i32 %4, %6
  %7 = load i32, i32* %i, align 4
  %8 = load i32, i32* %i, align 4
  %mul = mul nsw i32 %7, %8
  %add5 = add nsw i32 %add, %mul
  store i32 %add5, i32* %x, align 4
  catchret from %2 to label %catchret.dest

catchret.dest:                                    ; preds = %catch
  br label %try.cont

try.cont:                                         ; preds = %catchret.dest
  %arrayidx6 = getelementptr inbounds [50 x i32], [50 x i32]* %B, i64 0, i64 2
  %9 = load i32, i32* %arrayidx6, align 4
  %10 = load i32, i32* %x, align 4
  %add7 = add nsw i32 %9, %10
  ret i32 %add7

unreachable:                                      ; preds = %invoke.cont
  unreachable
}

declare dso_local void @"?init@@YAXPEAH@Z"(i32*)

declare dso_local i32 @"?func2@@YAHXZ"()

declare dso_local i32 @__CxxFrameHandler3(...)

declare dllimport void @_CxxThrowException(i8*, %eh.ThrowInfo*)

declare dso_local void @"?init2@@YAXPEAH@Z"(i32*)

attributes #0 = { noinline optnone }
attributes #2 = { noreturn }