239 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple x86_64-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X86_643; RUN: llc -mtriple i386-apple-macosx10.13.0 < %s | FileCheck %s --check-prefix=X864 5; The MacOS tripples are used to get trapping behavior on the "unreachable" IR6; instruction, so that the placement of the ud2 instruction could be verified.7 8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9;; The IR was created using the following C code:10;; typedef ptr jmp_buf;11;; jmp_buf buf;12;;13;; __attribute__((noinline)) int bar(int i) {14;; int j = i - 111;15;; __builtin_longjmp(&buf, 1);16;; return j;17;; }18;;19;; int foo(int i) {20;; int j = i * 11;21;; if (!__builtin_setjmp(&buf)) {22;; j += 33 + bar(j);23;; }24;; return j + i;25;; }26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27 28@buf = common local_unnamed_addr global ptr null, align 829 30; Functions that use LongJmp should fix the Shadow Stack using previosuly saved31; ShadowStackPointer in the input buffer.32; The fix requires unwinding the shadow stack to the last SSP.33define i32 @bar(i32 %i) local_unnamed_addr {34; X86_64-LABEL: bar:35; X86_64: ## %bb.0: ## %entry36; X86_64-NEXT: pushq %rbp37; X86_64-NEXT: .cfi_def_cfa_offset 1638; X86_64-NEXT: .cfi_offset %rbp, -1639; X86_64-NEXT: movq _buf@GOTPCREL(%rip), %rax40; X86_64-NEXT: movq (%rax), %rax41; X86_64-NEXT: xorl %edx, %edx42; X86_64-NEXT: rdsspq %rdx43; X86_64-NEXT: testq %rdx, %rdx44; X86_64-NEXT: je LBB0_545; X86_64-NEXT: ## %bb.1: ## %entry46; X86_64-NEXT: movq 24(%rax), %rcx47; X86_64-NEXT: subq %rdx, %rcx48; X86_64-NEXT: jbe LBB0_549; X86_64-NEXT: ## %bb.2: ## %entry50; X86_64-NEXT: shrq $3, %rcx51; X86_64-NEXT: incsspq %rcx52; X86_64-NEXT: shrq $8, %rcx53; X86_64-NEXT: je LBB0_554; X86_64-NEXT: ## %bb.3: ## %entry55; X86_64-NEXT: shlq %rcx56; X86_64-NEXT: movq $128, %rdx57; X86_64-NEXT: LBB0_4: ## %entry58; X86_64-NEXT: ## =>This Inner Loop Header: Depth=159; X86_64-NEXT: incsspq %rdx60; X86_64-NEXT: decq %rcx61; X86_64-NEXT: jne LBB0_462; X86_64-NEXT: LBB0_5: ## %entry63; X86_64-NEXT: movq (%rax), %rbp64; X86_64-NEXT: movq 8(%rax), %rcx65; X86_64-NEXT: movq 16(%rax), %rsp66; X86_64-NEXT: jmpq *%rcx67;68; X86-LABEL: bar:69; X86: ## %bb.0: ## %entry70; X86-NEXT: pushl %ebp71; X86-NEXT: .cfi_def_cfa_offset 872; X86-NEXT: .cfi_offset %ebp, -873; X86-NEXT: movl L_buf$non_lazy_ptr, %eax74; X86-NEXT: movl (%eax), %eax75; X86-NEXT: xorl %edx, %edx76; X86-NEXT: rdsspd %edx77; X86-NEXT: testl %edx, %edx78; X86-NEXT: je LBB0_579; X86-NEXT: ## %bb.1: ## %entry80; X86-NEXT: movl 12(%eax), %ecx81; X86-NEXT: subl %edx, %ecx82; X86-NEXT: jbe LBB0_583; X86-NEXT: ## %bb.2: ## %entry84; X86-NEXT: shrl $2, %ecx85; X86-NEXT: incsspd %ecx86; X86-NEXT: shrl $8, %ecx87; X86-NEXT: je LBB0_588; X86-NEXT: ## %bb.3: ## %entry89; X86-NEXT: shll %ecx90; X86-NEXT: movl $128, %edx91; X86-NEXT: LBB0_4: ## %entry92; X86-NEXT: ## =>This Inner Loop Header: Depth=193; X86-NEXT: incsspd %edx94; X86-NEXT: decl %ecx95; X86-NEXT: jne LBB0_496; X86-NEXT: LBB0_5: ## %entry97; X86-NEXT: movl (%eax), %ebp98; X86-NEXT: movl 4(%eax), %ecx99; X86-NEXT: movl 8(%eax), %esp100; X86-NEXT: jmpl *%ecx101entry:102 %0 = load ptr, ptr @buf, align 8103 tail call void @llvm.eh.sjlj.longjmp(ptr %0)104 unreachable105}106 107declare void @llvm.eh.sjlj.longjmp(ptr)108 109; Functions that call SetJmp should save the current ShadowStackPointer for110; future fixing of the Shadow Stack.111define i32 @foo(i32 %i) local_unnamed_addr {112; X86_64-LABEL: foo:113; X86_64: ## %bb.0: ## %entry114; X86_64-NEXT: pushq %rbp115; X86_64-NEXT: .cfi_def_cfa_offset 16116; X86_64-NEXT: .cfi_offset %rbp, -16117; X86_64-NEXT: movq %rsp, %rbp118; X86_64-NEXT: .cfi_def_cfa_register %rbp119; X86_64-NEXT: pushq %r15120; X86_64-NEXT: pushq %r14121; X86_64-NEXT: pushq %r13122; X86_64-NEXT: pushq %r12123; X86_64-NEXT: pushq %rbx124; X86_64-NEXT: pushq %rax125; X86_64-NEXT: .cfi_offset %rbx, -56126; X86_64-NEXT: .cfi_offset %r12, -48127; X86_64-NEXT: .cfi_offset %r13, -40128; X86_64-NEXT: .cfi_offset %r14, -32129; X86_64-NEXT: .cfi_offset %r15, -24130; X86_64-NEXT: ## kill: def $edi killed $edi def $rdi131; X86_64-NEXT: movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill132; X86_64-NEXT: movq _buf@GOTPCREL(%rip), %rax133; X86_64-NEXT: movq (%rax), %rax134; X86_64-NEXT: movq %rbp, (%rax)135; X86_64-NEXT: movq %rsp, 16(%rax)136; X86_64-NEXT: leaq LBB1_4(%rip), %rcx137; X86_64-NEXT: movq %rcx, 8(%rax)138; X86_64-NEXT: xorq %rcx, %rcx139; X86_64-NEXT: rdsspq %rcx140; X86_64-NEXT: movq %rcx, 24(%rax)141; X86_64-NEXT: #EH_SjLj_Setup LBB1_4142; X86_64-NEXT: ## %bb.1: ## %entry143; X86_64-NEXT: xorl %eax, %eax144; X86_64-NEXT: jmp LBB1_2145; X86_64-NEXT: LBB1_4: ## Block address taken146; X86_64-NEXT: ## %entry147; X86_64-NEXT: movl $1, %eax148; X86_64-NEXT: LBB1_2: ## %entry149; X86_64-NEXT: testl %eax, %eax150; X86_64-NEXT: je LBB1_5151; X86_64-NEXT: ## %bb.3: ## %if.end152; X86_64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload153; X86_64-NEXT: shll $2, %eax154; X86_64-NEXT: leal (%rax,%rax,2), %eax155; X86_64-NEXT: addq $8, %rsp156; X86_64-NEXT: popq %rbx157; X86_64-NEXT: popq %r12158; X86_64-NEXT: popq %r13159; X86_64-NEXT: popq %r14160; X86_64-NEXT: popq %r15161; X86_64-NEXT: popq %rbp162; X86_64-NEXT: retq163; X86_64-NEXT: LBB1_5: ## %if.then164; X86_64-NEXT: callq _bar165; X86_64-NEXT: ud2166;167; X86-LABEL: foo:168; X86: ## %bb.0: ## %entry169; X86-NEXT: pushl %ebp170; X86-NEXT: .cfi_def_cfa_offset 8171; X86-NEXT: .cfi_offset %ebp, -8172; X86-NEXT: movl %esp, %ebp173; X86-NEXT: .cfi_def_cfa_register %ebp174; X86-NEXT: pushl %ebx175; X86-NEXT: pushl %edi176; X86-NEXT: pushl %esi177; X86-NEXT: subl $12, %esp178; X86-NEXT: .cfi_offset %esi, -20179; X86-NEXT: .cfi_offset %edi, -16180; X86-NEXT: .cfi_offset %ebx, -12181; X86-NEXT: movl L_buf$non_lazy_ptr, %eax182; X86-NEXT: movl (%eax), %eax183; X86-NEXT: movl %ebp, (%eax)184; X86-NEXT: movl %esp, 16(%eax)185; X86-NEXT: movl $LBB1_4, 4(%eax)186; X86-NEXT: xorl %ecx, %ecx187; X86-NEXT: rdsspd %ecx188; X86-NEXT: movl %ecx, 12(%eax)189; X86-NEXT: #EH_SjLj_Setup LBB1_4190; X86-NEXT: ## %bb.1: ## %entry191; X86-NEXT: xorl %eax, %eax192; X86-NEXT: jmp LBB1_2193; X86-NEXT: LBB1_4: ## Block address taken194; X86-NEXT: ## %entry195; X86-NEXT: movl $1, %eax196; X86-NEXT: LBB1_2: ## %entry197; X86-NEXT: testl %eax, %eax198; X86-NEXT: je LBB1_5199; X86-NEXT: ## %bb.3: ## %if.end200; X86-NEXT: movl 8(%ebp), %eax201; X86-NEXT: shll $2, %eax202; X86-NEXT: leal (%eax,%eax,2), %eax203; X86-NEXT: addl $12, %esp204; X86-NEXT: popl %esi205; X86-NEXT: popl %edi206; X86-NEXT: popl %ebx207; X86-NEXT: popl %ebp208; X86-NEXT: retl209; X86-NEXT: LBB1_5: ## %if.then210; X86-NEXT: calll _bar211; X86-NEXT: ud2212entry:213 %0 = load ptr, ptr @buf, align 8214 %1 = tail call ptr @llvm.frameaddress(i32 0)215 store ptr %1, ptr %0, align 8216 %2 = tail call ptr @llvm.stacksave()217 %3 = getelementptr inbounds i8, ptr %0, i64 16218 store ptr %2, ptr %3, align 8219 %4 = tail call i32 @llvm.eh.sjlj.setjmp(ptr %0)220 %tobool = icmp eq i32 %4, 0221 br i1 %tobool, label %if.then, label %if.end222 223if.then: ; preds = %entry224 %call = tail call i32 @bar(i32 undef)225 unreachable226 227if.end: ; preds = %entry228 %add2 = mul nsw i32 %i, 12229 ret i32 %add2230}231 232declare ptr @llvm.frameaddress(i32)233declare ptr @llvm.stacksave()234declare i32 @llvm.eh.sjlj.setjmp(ptr)235 236!llvm.module.flags = !{!0}237 238!0 = !{i32 8, !"cf-protection-return", i32 1}239