241 lines
7.6 KiB
LLVM
241 lines
7.6 KiB
LLVM
|
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||
|
; RUN: llc -mtriple x86_64-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86_64
|
||
|
; RUN: llc -mtriple i386-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86
|
||
|
|
||
|
; The MacOS tripples are used to get trapping behavior on the "unreachable" IR
|
||
|
; instruction, so that the placement of the ud2 instruction could be verified.
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;; The IR was created using the following C code:
|
||
|
;; typedef void *jmp_buf;
|
||
|
;; jmp_buf buf;
|
||
|
;;
|
||
|
;; __attribute__((noinline)) int bar(int i) {
|
||
|
;; int j = i - 111;
|
||
|
;; __builtin_longjmp(&buf, 1);
|
||
|
;; return j;
|
||
|
;; }
|
||
|
;;
|
||
|
;; int foo(int i) {
|
||
|
;; int j = i * 11;
|
||
|
;; if (!__builtin_setjmp(&buf)) {
|
||
|
;; j += 33 + bar(j);
|
||
|
;; }
|
||
|
;; return j + i;
|
||
|
;; }
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
@buf = common local_unnamed_addr global i8* null, align 8
|
||
|
|
||
|
; Functions that use LongJmp should fix the Shadow Stack using previosuly saved
|
||
|
; ShadowStackPointer in the input buffer.
|
||
|
; The fix requires unwinding the shadow stack to the last SSP.
|
||
|
define i32 @bar(i32 %i) local_unnamed_addr {
|
||
|
; X86_64-LABEL: bar:
|
||
|
; X86_64: ## %bb.0: ## %entry
|
||
|
; X86_64-NEXT: pushq %rbp
|
||
|
; X86_64-NEXT: .cfi_def_cfa_offset 16
|
||
|
; X86_64-NEXT: .cfi_offset %rbp, -16
|
||
|
; X86_64-NEXT: movq _buf@{{.*}}(%rip), %rax
|
||
|
; X86_64-NEXT: movq (%rax), %rax
|
||
|
; X86_64-NEXT: xorl %edx, %edx
|
||
|
; X86_64-NEXT: rdsspq %rdx
|
||
|
; X86_64-NEXT: testq %rdx, %rdx
|
||
|
; X86_64-NEXT: je LBB0_5
|
||
|
; X86_64-NEXT: ## %bb.1: ## %entry
|
||
|
; X86_64-NEXT: movq 24(%rax), %rcx
|
||
|
; X86_64-NEXT: subq %rdx, %rcx
|
||
|
; X86_64-NEXT: jbe LBB0_5
|
||
|
; X86_64-NEXT: ## %bb.2: ## %entry
|
||
|
; X86_64-NEXT: shrq $3, %rcx
|
||
|
; X86_64-NEXT: incsspq %rcx
|
||
|
; X86_64-NEXT: shrq $8, %rcx
|
||
|
; X86_64-NEXT: je LBB0_5
|
||
|
; X86_64-NEXT: ## %bb.3: ## %entry
|
||
|
; X86_64-NEXT: shlq %rcx
|
||
|
; X86_64-NEXT: movq $128, %rdx
|
||
|
; X86_64-NEXT: LBB0_4: ## %entry
|
||
|
; X86_64-NEXT: ## =>This Inner Loop Header: Depth=1
|
||
|
; X86_64-NEXT: incsspq %rdx
|
||
|
; X86_64-NEXT: decq %rcx
|
||
|
; X86_64-NEXT: jne LBB0_4
|
||
|
; X86_64-NEXT: LBB0_5: ## %entry
|
||
|
; X86_64-NEXT: movq (%rax), %rbp
|
||
|
; X86_64-NEXT: movq 8(%rax), %rcx
|
||
|
; X86_64-NEXT: movq 16(%rax), %rsp
|
||
|
; X86_64-NEXT: jmpq *%rcx
|
||
|
;
|
||
|
; X86-LABEL: bar:
|
||
|
; X86: ## %bb.0: ## %entry
|
||
|
; X86-NEXT: pushl %ebp
|
||
|
; X86-NEXT: .cfi_def_cfa_offset 8
|
||
|
; X86-NEXT: .cfi_offset %ebp, -8
|
||
|
; X86-NEXT: movl L_buf$non_lazy_ptr, %eax
|
||
|
; X86-NEXT: movl (%eax), %eax
|
||
|
; X86-NEXT: xorl %edx, %edx
|
||
|
; X86-NEXT: rdsspd %edx
|
||
|
; X86-NEXT: testl %edx, %edx
|
||
|
; X86-NEXT: je LBB0_5
|
||
|
; X86-NEXT: ## %bb.1: ## %entry
|
||
|
; X86-NEXT: movl 12(%eax), %ecx
|
||
|
; X86-NEXT: subl %edx, %ecx
|
||
|
; X86-NEXT: jbe LBB0_5
|
||
|
; X86-NEXT: ## %bb.2: ## %entry
|
||
|
; X86-NEXT: shrl $2, %ecx
|
||
|
; X86-NEXT: incsspd %ecx
|
||
|
; X86-NEXT: shrl $8, %ecx
|
||
|
; X86-NEXT: je LBB0_5
|
||
|
; X86-NEXT: ## %bb.3: ## %entry
|
||
|
; X86-NEXT: shll %ecx
|
||
|
; X86-NEXT: movl $128, %edx
|
||
|
; X86-NEXT: LBB0_4: ## %entry
|
||
|
; X86-NEXT: ## =>This Inner Loop Header: Depth=1
|
||
|
; X86-NEXT: incsspd %edx
|
||
|
; X86-NEXT: decl %ecx
|
||
|
; X86-NEXT: jne LBB0_4
|
||
|
; X86-NEXT: LBB0_5: ## %entry
|
||
|
; X86-NEXT: movl (%eax), %ebp
|
||
|
; X86-NEXT: movl 4(%eax), %ecx
|
||
|
; X86-NEXT: movl 8(%eax), %esp
|
||
|
; X86-NEXT: jmpl *%ecx
|
||
|
entry:
|
||
|
%0 = load i8*, i8** @buf, align 8
|
||
|
tail call void @llvm.eh.sjlj.longjmp(i8* %0)
|
||
|
unreachable
|
||
|
}
|
||
|
|
||
|
declare void @llvm.eh.sjlj.longjmp(i8*)
|
||
|
|
||
|
; Functions that call SetJmp should save the current ShadowStackPointer for
|
||
|
; future fixing of the Shadow Stack.
|
||
|
define i32 @foo(i32 %i) local_unnamed_addr {
|
||
|
; X86_64-LABEL: foo:
|
||
|
; X86_64: ## %bb.0: ## %entry
|
||
|
; X86_64-NEXT: pushq %rbp
|
||
|
; X86_64-NEXT: .cfi_def_cfa_offset 16
|
||
|
; X86_64-NEXT: .cfi_offset %rbp, -16
|
||
|
; X86_64-NEXT: movq %rsp, %rbp
|
||
|
; X86_64-NEXT: .cfi_def_cfa_register %rbp
|
||
|
; X86_64-NEXT: pushq %r15
|
||
|
; X86_64-NEXT: pushq %r14
|
||
|
; X86_64-NEXT: pushq %r13
|
||
|
; X86_64-NEXT: pushq %r12
|
||
|
; X86_64-NEXT: pushq %rbx
|
||
|
; X86_64-NEXT: pushq %rax
|
||
|
; X86_64-NEXT: .cfi_offset %rbx, -56
|
||
|
; X86_64-NEXT: .cfi_offset %r12, -48
|
||
|
; X86_64-NEXT: .cfi_offset %r13, -40
|
||
|
; X86_64-NEXT: .cfi_offset %r14, -32
|
||
|
; X86_64-NEXT: .cfi_offset %r15, -24
|
||
|
; X86_64-NEXT: ## kill: def $edi killed $edi def $rdi
|
||
|
; X86_64-NEXT: movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill
|
||
|
; X86_64-NEXT: movq _buf@{{.*}}(%rip), %rax
|
||
|
; X86_64-NEXT: movq (%rax), %rax
|
||
|
; X86_64-NEXT: movq %rbp, (%rax)
|
||
|
; X86_64-NEXT: movq %rsp, 16(%rax)
|
||
|
; X86_64-NEXT: leaq {{.*}}(%rip), %rcx
|
||
|
; X86_64-NEXT: movq %rcx, 8(%rax)
|
||
|
; X86_64-NEXT: xorq %rcx, %rcx
|
||
|
; X86_64-NEXT: rdsspq %rcx
|
||
|
; X86_64-NEXT: movq %rcx, 24(%rax)
|
||
|
; X86_64-NEXT: #EH_SjLj_Setup LBB1_4
|
||
|
; X86_64-NEXT: ## %bb.1: ## %entry
|
||
|
; X86_64-NEXT: xorl %eax, %eax
|
||
|
; X86_64-NEXT: jmp LBB1_2
|
||
|
; X86_64-NEXT: LBB1_4: ## Block address taken
|
||
|
; X86_64-NEXT: ## %entry
|
||
|
; X86_64-NEXT: movl $1, %eax
|
||
|
; X86_64-NEXT: LBB1_2: ## %entry
|
||
|
; X86_64-NEXT: testl %eax, %eax
|
||
|
; X86_64-NEXT: je LBB1_5
|
||
|
; X86_64-NEXT: ## %bb.3: ## %if.end
|
||
|
; X86_64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload
|
||
|
; X86_64-NEXT: shll $2, %eax
|
||
|
; X86_64-NEXT: leal (%rax,%rax,2), %eax
|
||
|
; X86_64-NEXT: addq $8, %rsp
|
||
|
; X86_64-NEXT: popq %rbx
|
||
|
; X86_64-NEXT: popq %r12
|
||
|
; X86_64-NEXT: popq %r13
|
||
|
; X86_64-NEXT: popq %r14
|
||
|
; X86_64-NEXT: popq %r15
|
||
|
; X86_64-NEXT: popq %rbp
|
||
|
; X86_64-NEXT: retq
|
||
|
; X86_64-NEXT: LBB1_5: ## %if.then
|
||
|
; X86_64-NEXT: callq _bar
|
||
|
; X86_64-NEXT: ud2
|
||
|
;
|
||
|
; X86-LABEL: foo:
|
||
|
; X86: ## %bb.0: ## %entry
|
||
|
; X86-NEXT: pushl %ebp
|
||
|
; X86-NEXT: .cfi_def_cfa_offset 8
|
||
|
; X86-NEXT: .cfi_offset %ebp, -8
|
||
|
; X86-NEXT: movl %esp, %ebp
|
||
|
; X86-NEXT: .cfi_def_cfa_register %ebp
|
||
|
; X86-NEXT: pushl %ebx
|
||
|
; X86-NEXT: pushl %edi
|
||
|
; X86-NEXT: pushl %esi
|
||
|
; X86-NEXT: subl $12, %esp
|
||
|
; X86-NEXT: .cfi_offset %esi, -20
|
||
|
; X86-NEXT: .cfi_offset %edi, -16
|
||
|
; X86-NEXT: .cfi_offset %ebx, -12
|
||
|
; X86-NEXT: movl L_buf$non_lazy_ptr, %eax
|
||
|
; X86-NEXT: movl (%eax), %eax
|
||
|
; X86-NEXT: movl %ebp, (%eax)
|
||
|
; X86-NEXT: movl %esp, 16(%eax)
|
||
|
; X86-NEXT: movl $LBB1_4, 4(%eax)
|
||
|
; X86-NEXT: xorl %ecx, %ecx
|
||
|
; X86-NEXT: rdsspd %ecx
|
||
|
; X86-NEXT: movl %ecx, 12(%eax)
|
||
|
; X86-NEXT: #EH_SjLj_Setup LBB1_4
|
||
|
; X86-NEXT: ## %bb.1: ## %entry
|
||
|
; X86-NEXT: xorl %eax, %eax
|
||
|
; X86-NEXT: jmp LBB1_2
|
||
|
; X86-NEXT: LBB1_4: ## Block address taken
|
||
|
; X86-NEXT: ## %entry
|
||
|
; X86-NEXT: movl $1, %eax
|
||
|
; X86-NEXT: LBB1_2: ## %entry
|
||
|
; X86-NEXT: testl %eax, %eax
|
||
|
; X86-NEXT: je LBB1_5
|
||
|
; X86-NEXT: ## %bb.3: ## %if.end
|
||
|
; X86-NEXT: movl 8(%ebp), %eax
|
||
|
; X86-NEXT: shll $2, %eax
|
||
|
; X86-NEXT: leal (%eax,%eax,2), %eax
|
||
|
; X86-NEXT: addl $12, %esp
|
||
|
; X86-NEXT: popl %esi
|
||
|
; X86-NEXT: popl %edi
|
||
|
; X86-NEXT: popl %ebx
|
||
|
; X86-NEXT: popl %ebp
|
||
|
; X86-NEXT: retl
|
||
|
; X86-NEXT: LBB1_5: ## %if.then
|
||
|
; X86-NEXT: calll _bar
|
||
|
; X86-NEXT: ud2
|
||
|
entry:
|
||
|
%0 = load i8*, i8** @buf, align 8
|
||
|
%1 = bitcast i8* %0 to i8**
|
||
|
%2 = tail call i8* @llvm.frameaddress(i32 0)
|
||
|
store i8* %2, i8** %1, align 8
|
||
|
%3 = tail call i8* @llvm.stacksave()
|
||
|
%4 = getelementptr inbounds i8, i8* %0, i64 16
|
||
|
%5 = bitcast i8* %4 to i8**
|
||
|
store i8* %3, i8** %5, align 8
|
||
|
%6 = tail call i32 @llvm.eh.sjlj.setjmp(i8* %0)
|
||
|
%tobool = icmp eq i32 %6, 0
|
||
|
br i1 %tobool, label %if.then, label %if.end
|
||
|
|
||
|
if.then: ; preds = %entry
|
||
|
%call = tail call i32 @bar(i32 undef)
|
||
|
unreachable
|
||
|
|
||
|
if.end: ; preds = %entry
|
||
|
%add2 = mul nsw i32 %i, 12
|
||
|
ret i32 %add2
|
||
|
}
|
||
|
|
||
|
declare i8* @llvm.frameaddress(i32)
|
||
|
declare i8* @llvm.stacksave()
|
||
|
declare i32 @llvm.eh.sjlj.setjmp(i8*)
|
||
|
|
||
|
!llvm.module.flags = !{!0}
|
||
|
|
||
|
!0 = !{i32 4, !"cf-protection-return", i32 1}
|