# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass shadow-call-stack -verify-machineinstrs -o - %s | FileCheck %s --- | define void @no_return() #0 { ret void } define void @normal_return() #0 { ret void } define void @normal_return_leaf_func() #0 { ret void } define void @short_leaf_func() #0 { ret void } define void @normal_tail_call() #0 { ret void } define void @r11_tail_call() #0 { ret void } define void @conditional_tail_call() #0 { ret void } define void @r10_live_in() #0 { ret void } attributes #0 = { shadowcallstack } ... --- # CHECK-LABEL: name: no_return name: no_return tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: bb.0: ; CHECK-NEXT: $eax = MOV32ri 13 $eax = MOV32ri 13 ... --- # CHECK-LABEL: name: normal_return name: normal_return tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: bb.0: ; CHECK: $r10 = MOV64rm $rsp, 1, $noreg, 0, $noreg ; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags ; CHECK-NEXT: ADD64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: $r11 = MOV64rm $r11, 1, $noreg, 0, $gs ; CHECK-NEXT: MOV64mr $r11, 1, $noreg, 0, $gs, $r10 ; CHECK-NEXT: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags ; CHECK-NEXT: $r10 = MOV64rm $r11, 1, $noreg, 0, $gs ; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs ; CHECK-NEXT: SUB64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: CMP64mr $rsp, 1, $noreg, 0, $noreg, $r10, implicit-def $eflags ; CHECK-NEXT: JNE_1 %bb.1, implicit $eflags ; CHECK-NEXT: RETQ $eax RETQ $eax ; CHECK: bb.1: ; CHECK-NEXT; TRAP ... --- # CHECK-LABEL: name: normal_return_leaf_func name: normal_return_leaf_func tracksRegLiveness: true frameInfo: adjustsStack: false # leaf function body: | ; CHECK: bb.0: ; CHECK: liveins: $rcx bb.0: liveins: $rcx ; CHECK: $rdx = MOV64rm $rsp, 1, $noreg, 0, $noreg ; CHECK-NEXT: $eax = MOV32ri 0 $eax = MOV32ri 0 ; CHECK-NEXT: CMP64ri8 $rcx, 5, implicit-def $eflags CMP64ri8 $rcx, 5, implicit-def $eflags ; CHECK-NEXT: JA_1 %bb.1, implicit $eflags JA_1 %bb.1, implicit $eflags ; CHECK-NEXT: JMP_1 %bb.2 JMP_1 %bb.2 ; CHECK: bb.1 ; CHECK: liveins: $eax, $rdx bb.1: liveins: $eax ; CHECKT: $eax = MOV32ri 1 $eax = MOV32ri 1 ; CHECK: bb.2 ; CHECK: liveins: $eax, $rdx bb.2: liveins: $eax ; CHECK: CMP64mr $rsp, 1, $noreg, 0, $noreg, $rdx, implicit-def $eflags ; CHECK-NEXT: JNE_1 %bb.3, implicit $eflags ; CHECK-NEXT: RETQ $eax RETQ $eax ; CHECK: bb.3: ; CHECK-NEXT; TRAP ... --- # CHECK-LABEL: name: short_leaf_func name: short_leaf_func tracksRegLiveness: true frameInfo: adjustsStack: false # leaf function body: | ; CHECK: bb.0: bb.0: ; Ensure these are not counted as machine instructions CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 CFI_INSTRUCTION 0 DBG_VALUE 0 DBG_VALUE 0 DBG_VALUE 0 ; CHECK: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: RETQ $eax RETQ $eax ... --- # CHECK-LABEL: name: normal_tail_call name: normal_tail_call tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: bb.0: ; CHECK: $r10 = MOV64rm $rsp, 1, $noreg, 0, $noreg ; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags ; CHECK-NEXT: ADD64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: $r11 = MOV64rm $r11, 1, $noreg, 0, $gs ; CHECK-NEXT: MOV64mr $r11, 1, $noreg, 0, $gs, $r10 ; CHECK-NEXT: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags ; CHECK-NEXT: $r10 = MOV64rm $r11, 1, $noreg, 0, $gs ; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs ; CHECK-NEXT: SUB64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: CMP64mr $rsp, 1, $noreg, 0, $noreg, $r10, implicit-def $eflags ; CHECK-NEXT: JNE_1 %bb.1, implicit $eflags ; CHECK-NEXT: TAILJMPr64 $rax TAILJMPr64 $rax ; CHECK: bb.1: ; CHECK-NEXT; TRAP ... --- # CHECK-LABEL: name: r11_tail_call name: r11_tail_call tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: bb.0: ; CHECK: $r10 = MOV64rm $rsp, 1, $noreg, 0, $noreg ; CHECK-NEXT: $r11 = XOR64rr undef $r11, undef $r11, implicit-def $eflags ; CHECK-NEXT: ADD64mi8 $r11, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: $r11 = MOV64rm $r11, 1, $noreg, 0, $gs ; CHECK-NEXT: MOV64mr $r11, 1, $noreg, 0, $gs, $r10 ; CHECK-NEXT: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: $r10 = XOR64rr undef $r10, undef $r10, implicit-def $eflags ; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs ; CHECK-NEXT: $r10 = MOV64rm $r10, 1, $noreg, 0, $gs ; CHECK-NEXT: SUB64mi8 $noreg, 1, $noreg, 0, $gs, 8, implicit-def $eflags ; CHECK-NEXT: CMP64mr $rsp, 1, $noreg, 0, $noreg, $r10, implicit-def $eflags ; CHECK-NEXT: JNE_1 %bb.1, implicit $eflags ; CHECK-NEXT: TAILJMPr64 undef $r11 TAILJMPr64 undef $r11 ; CHECK: bb.1: ; CHECK-NEXT; TRAP ... --- # CHECK-LABEL: name: conditional_tail_call name: conditional_tail_call tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: bb.0: ; CHECK: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: TAILJMPd64_CC @conditional_tail_call, undef $eflags TAILJMPd64_CC @conditional_tail_call, undef $eflags ... --- # CHECK-LABEL: name: r10_live_in name: r10_live_in tracksRegLiveness: true frameInfo: adjustsStack: true # not a leaf function body: | ; CHECK: bb.0: ; CHECK: liveins: $r10 bb.0: liveins: $r10 ; CHECK: $eax = MOV32ri 13 $eax = MOV32ri 13 ; CHECK-NEXT: RETQ $eax RETQ $eax ...