213 lines · plain
1; RUN: llc -verify-machineinstrs -filetype=obj -o - -mtriple=x86_64-apple-macosx < %s | llvm-objdump --no-print-imm-hex --triple=x86_64-apple-macosx -d - | FileCheck %s2; RUN: llc -verify-machineinstrs -mtriple=x86_64-apple-macosx < %s | FileCheck %s --check-prefix=CHECK-ALIGN3; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386 < %s | FileCheck %s --check-prefixes=X86,X86CFI,XCHG4; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc < %s | FileCheck %s --check-prefixes=X86,MOV5; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium3 < %s | FileCheck %s --check-prefixes=X86,MOV6; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=i386-windows-msvc -mcpu=pentium4 < %s | FileCheck %s --check-prefixes=X86,XCHG7; RUN: llc -verify-machineinstrs -show-mc-encoding -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=X648 9declare void @callee(ptr)10 11define void @f0() "patchable-function"="prologue-short-redirect" {12; CHECK-LABEL: _f0{{>?}}:13; CHECK-NEXT: 66 90 nop14 15; CHECK-ALIGN: .p2align 416; CHECK-ALIGN: _f0:17 18; X86: f0:19; X86CFI-NEXT: .cfi_startproc20; X86-NEXT: # %bb.0:21; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90]22; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff]23; X86-NEXT: retl24 25; X64: f0:26; X64-NEXT: # %bb.0:27; X64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90]28; X64-NEXT: retq29 30 ret void31}32 33define void @f1() "patchable-function"="prologue-short-redirect" "frame-pointer"="all" {34; CHECK-LABEL: _f135; CHECK-NEXT: 66 90 nop36; CHECK-NEXT: 55 pushq %rbp37 38; CHECK-ALIGN: .p2align 439; CHECK-ALIGN: _f1:40 41; X86: f1:42; X86CFI-NEXT: .cfi_startproc43; X86-NEXT: # %bb.0:44; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90]45; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff]46; X86-NEXT: pushl %ebp47 48; X64: f1:49; X64-NEXT: .seh_proc f150; X64-NEXT: # %bb.0:51; X64-NEXT: xchgw %ax, %ax52; X64-NEXT: pushq %rbp53 54 ret void55}56 57define void @f2() "patchable-function"="prologue-short-redirect" {58; CHECK-LABEL: _f259; CHECK-NEXT: 48 81 ec a8 00 00 00 subq $168, %rsp60 61; CHECK-ALIGN: .p2align 462; CHECK-ALIGN: _f2:63 64; X86: f2:65; X86CFI-NEXT: .cfi_startproc66; X86-NEXT: # %bb.0:67; XCHG-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90]68; MOV-NEXT: movl %edi, %edi # encoding: [0x8b,0xff]69; X86-NEXT: pushl %ebp70 71; X64: f2:72; X64-NEXT: .seh_proc f273; X64-NEXT: # %bb.0:74; X64-NEXT: subq $200, %rsp75 76 %ptr = alloca i64, i32 2077 call void @callee(ptr %ptr)78 ret void79}80 81define void @f3() "patchable-function"="prologue-short-redirect" optsize {82; CHECK-LABEL: _f383; CHECK-NEXT: 66 90 nop84 85; CHECK-ALIGN: .p2align 486; CHECK-ALIGN: _f3:87 88; X86: f3:89; X86CFI-NEXT: .cfi_startproc90; X86-NEXT: # %bb.0:91; XCHG-NEXT: xchgw %ax, %ax92; MOV-NEXT: movl %edi, %edi93; X86-NEXT: retl94 95; X64: f3:96; X64-NEXT: # %bb.0:97; X64-NEXT: xchgw %ax, %ax98; X64-NEXT: retq99 100 ret void101}102 103; This testcase happens to produce a KILL instruction at the beginning of the104; first basic block. In this case the 2nd instruction should be turned into a105; patchable one.106; CHECK-LABEL: f4{{>?}}:107; CHECK-NEXT: 8b 0c 37 movl (%rdi,%rsi), %ecx108; X86: f4:109; X86CFI-NEXT: .cfi_startproc110; X86-NEXT: # %bb.0:111; XCHG-NEXT: xchgw %ax, %ax112; MOV-NEXT: movl %edi, %edi113; X86-NEXT: pushl %ebx114 115; X64: f4:116; X64-NEXT: # %bb.0:117; X64-NOT: xchgw %ax, %ax118 119define i32 @f4(ptr %arg1, i64 %arg2, i32 %arg3) "patchable-function"="prologue-short-redirect" {120bb:121 %tmp10 = getelementptr i8, ptr %arg1, i64 %arg2122 %tmp12 = load i32, ptr %tmp10, align 4123 fence acquire124 %tmp13 = add i32 %tmp12, %arg3125 %tmp14 = cmpxchg ptr %tmp10, i32 %tmp12, i32 %tmp13 seq_cst monotonic126 %tmp15 = extractvalue { i32, i1 } %tmp14, 1127 br i1 %tmp15, label %bb21, label %bb16128 129bb16:130 br label %bb21131 132bb21:133 %tmp22 = phi i32 [ %tmp12, %bb ], [ %arg3, %bb16 ]134 ret i32 %tmp22135}136 137; This testcase produces an empty function (not even a ret on some targets).138; This scenario can happen with undefined behavior.139; Ensure that the "patchable-function" pass supports this case.140; CHECK-LABEL: _emptyfunc141; CHECK-NEXT: 0f 0b ud2142 143; CHECK-ALIGN: .p2align 4144; CHECK-ALIGN: _emptyfunc:145 146; X86: emptyfunc:147; X86CFI-NEXT: .cfi_startproc148; X86-NEXT: # %bb.0:149; XCHG-NEXT: xchgw %ax, %ax150; MOV-NEXT: movl %edi, %edi151 152; X64: emptyfunc:153; X64-NEXT: # %bb.0:154; X64-NEXT: xchgw %ax, %ax155 156; From code: int emptyfunc() {}157define i32 @emptyfunc() "patchable-function"="prologue-short-redirect" {158 unreachable159}160 161 162; Hotpatch feature must ensure no jump within the function goes to the first instruction.163; From code:164; void jmp_to_start(char *b) {165; do {166; } while ((++(*b++)));167; }168 169; CHECK-ALIGN: .p2align 4170; CHECK-ALIGN: _jmp_to_start:171 172; X86: jmp_to_start:173; X86CFI-NEXT: .cfi_startproc174; X86-NEXT: # %bb.0:175; XCHG-NEXT: xchgw %ax, %ax176; MOV-NEXT: movl %edi, %edi177 178; X64: jmp_to_start:179; X64-NEXT: # %bb.0:180; X64-NEXT: xchgw %ax, %ax181 182define dso_local void @jmp_to_start(ptr inreg nocapture noundef %b) "patchable-function"="prologue-short-redirect" {183entry:184 br label %do.body185do.body: ; preds = %do.body, %entry186 %b.addr.0 = phi ptr [ %b, %entry ], [ %incdec.ptr, %do.body ]187 %incdec.ptr = getelementptr inbounds i8, ptr %b.addr.0, i64 1188 %0 = load i8, ptr %b.addr.0, align 1189 %inc = add i8 %0, 1190 store i8 %inc, ptr %b.addr.0, align 1191 %tobool.not = icmp eq i8 %inc, 0192 br i1 %tobool.not, label %do.end, label %do.body193do.end: ; preds = %do.body194 ret void195}196 197 198; Test that inline asm is properly hotpatched. We currently don't examine the199; asm instruction when printing it, thus we always emit patching NOPs.200 201; X64: inline_asm:202; X64-NEXT: # %bb.0:203; X64-NEXT: xchgw %ax, %ax # encoding: [0x66,0x90]204; X64-NEXT: #APP205; X64-NEXT: int3 # encoding: [0xcc]206; X64-NEXT: #NO_APP207 208define dso_local void @inline_asm() "patchable-function"="prologue-short-redirect" {209entry:210 call void asm sideeffect "int3", "~{dirflag},~{fpsr},~{flags}"()211 ret void212}213