brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 7c02d83 Raw
216 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 62; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s3 4; This test verifies that Thumb1 (ARMv6-M) generates correct code for backend KCFI.5; Thumb1 uses the backend KCFI implementation with Thumb1-specific instructions.6 7; Test function without KCFI annotation8; CHECK-LABEL: .globl nosan9; CHECK-NEXT:  .p2align 110; CHECK-NEXT:  .type nosan,%function11; CHECK-NEXT:  .code 1612; CHECK-NEXT:  .thumb_func13define dso_local void @nosan() nounwind {14; CHECK-LABEL: nosan:15; CHECK:       @ %bb.0:16; CHECK-NEXT:    bx lr17  ret void18}19 20; Test function with KCFI annotation - verifies type hash emission21;; The alignment is at least 4 to avoid unaligned type hash loads when this22;; instrumented function is indirectly called.23; CHECK-LABEL: .globl target_func24; CHECK-NEXT:  .p2align 225; CHECK-NEXT:  .type target_func,%function26; CHECK-NEXT:  .long 317046893227; CHECK-NEXT:  .code 1628; CHECK-NEXT:  .thumb_func29define void @target_func() !kcfi_type !1 {30; CHECK-LABEL: target_func:31; CHECK:       @ %bb.0:32; CHECK-NEXT:    bx lr33  ret void34}35 36; Test indirect call with KCFI check using operand bundles37; CHECK-LABEL: .globl f138; CHECK:       .p2align 239; CHECK-NEXT:  .type f1,%function40; CHECK-NEXT:  .long 317046893241; CHECK-NEXT:  .code 1642; CHECK-NEXT:  .thumb_func43define void @f1(ptr noundef %x) !kcfi_type !1 {44; CHECK-LABEL: f1:45; CHECK:       @ %bb.0:46; CHECK-NEXT:    .save {r7, lr}47; CHECK-NEXT:    push {r7, lr}48; CHECK-NEXT:    movs r3, #149; CHECK-NEXT:    mov r2, r050; CHECK-NEXT:    bics r2, r351; CHECK-NEXT:    subs r2, #452; CHECK-NEXT:    ldr r2, [r2]53; CHECK-NEXT:    movs r3, #18854; CHECK-NEXT:    lsls r3, r3, #855; CHECK-NEXT:    adds r3, #24956; CHECK-NEXT:    lsls r3, r3, #857; CHECK-NEXT:    adds r3, #13258; CHECK-NEXT:    lsls r3, r3, #859; CHECK-NEXT:    adds r3, #6860; CHECK-NEXT:    cmp r2, r361; CHECK-NEXT:    beq .Ltmp062; CHECK-NEXT:    bkpt #063; CHECK-NEXT:  .Ltmp0:64; CHECK-NEXT:    blx r065; CHECK-NEXT:    pop {r7, pc}66  call void %x() [ "kcfi"(i32 -1124498364) ]67  ret void68}69 70; Test with tail call - backend KCFI supports tail calls71define void @f2(ptr noundef %x) !kcfi_type !1 {72; CHECK-LABEL: f2:73; CHECK:       @ %bb.0:74; CHECK-NEXT:    .save {r7, lr}75; CHECK-NEXT:    push {r7, lr}76; CHECK-NEXT:    movs r3, #177; CHECK-NEXT:    mov r2, r078; CHECK-NEXT:    bics r2, r379; CHECK-NEXT:    subs r2, #480; CHECK-NEXT:    ldr r2, [r2]81; CHECK-NEXT:    movs r3, #18882; CHECK-NEXT:    lsls r3, r3, #883; CHECK-NEXT:    adds r3, #24984; CHECK-NEXT:    lsls r3, r3, #885; CHECK-NEXT:    adds r3, #13286; CHECK-NEXT:    lsls r3, r3, #887; CHECK-NEXT:    adds r3, #6888; CHECK-NEXT:    cmp r2, r389; CHECK-NEXT:    beq .Ltmp190; CHECK-NEXT:    bkpt #091; CHECK-NEXT:  .Ltmp1:92; CHECK-NEXT:    blx r093; CHECK-NEXT:    pop {r7, pc}94  tail call void %x() [ "kcfi"(i32 -1124498364) ]95  ret void96}97 98; Test with R2 live (3 arguments) - compiler shuffles args, no spilling needed99define void @f3_r2_live(ptr noundef %x, i32 %a, i32 %b, i32 %c) !kcfi_type !1 {100; CHECK-LABEL: f3_r2_live:101; CHECK:       @ %bb.0:102; CHECK-NEXT:    .save {r4, lr}103; CHECK-NEXT:    push {r4, lr}104; CHECK-NEXT:    mov r4, r0105; CHECK-NEXT:    mov r0, r1106; CHECK-NEXT:    mov r1, r2107; CHECK-NEXT:    mov r2, r3108; CHECK-NEXT:    push {r2}109; CHECK-NEXT:    movs r3, #1110; CHECK-NEXT:    mov r2, r4111; CHECK-NEXT:    bics r2, r3112; CHECK-NEXT:    subs r2, #4113; CHECK-NEXT:    ldr r2, [r2]114; CHECK-NEXT:    movs r3, #188115; CHECK-NEXT:    lsls r3, r3, #8116; CHECK-NEXT:    adds r3, #249117; CHECK-NEXT:    lsls r3, r3, #8118; CHECK-NEXT:    adds r3, #132119; CHECK-NEXT:    lsls r3, r3, #8120; CHECK-NEXT:    adds r3, #68121; CHECK-NEXT:    cmp r2, r3122; CHECK-NEXT:    pop {r2}123; CHECK-NEXT:    beq .Ltmp2124; CHECK-NEXT:    bkpt #0125; CHECK-NEXT:  .Ltmp2:126; CHECK-NEXT:    blx r4127; CHECK-NEXT:    pop {r4, pc}128; Compiler shuffles: target→r4, c→r2, a→r0, b→r1129; R2 is live (3rd arg), so we push it, then uses R3 as temp, R2 as scratch130  call void %x(i32 %a, i32 %b, i32 %c) [ "kcfi"(i32 -1124498364) ]131  ret void132}133 134; Test with both R2 and R3 live (4 arguments) - compiler moves to r5/r4, uses R3 temp and R12 scratch135define void @f4_r2_r3_live(ptr noundef %x, i32 %a, i32 %b, i32 %c, i32 %d) !kcfi_type !1 {136; CHECK-LABEL: f4_r2_r3_live:137; CHECK:       @ %bb.0:138; CHECK-NEXT:    .save {r4, r5, r7, lr}139; CHECK-NEXT:    push {r4, r5, r7, lr}140; CHECK-NEXT:    mov r5, r3141; CHECK-NEXT:    mov r4, r0142; CHECK-NEXT:    ldr r3, [sp, #16]143; CHECK-NEXT:    mov r0, r1144; CHECK-NEXT:    mov r1, r2145; CHECK-NEXT:    mov r2, r5146; CHECK-NEXT:    push {r3}147; CHECK-NEXT:    push {r2}148; CHECK-NEXT:    movs r3, #1149; CHECK-NEXT:    mov r2, r4150; CHECK-NEXT:    bics r2, r3151; CHECK-NEXT:    subs r2, #4152; CHECK-NEXT:    ldr r2, [r2]153; CHECK-NEXT:    movs r3, #188154; CHECK-NEXT:    lsls r3, r3, #8155; CHECK-NEXT:    adds r3, #249156; CHECK-NEXT:    lsls r3, r3, #8157; CHECK-NEXT:    adds r3, #132158; CHECK-NEXT:    lsls r3, r3, #8159; CHECK-NEXT:    adds r3, #68160; CHECK-NEXT:    cmp r2, r3161; CHECK-NEXT:    pop {r2}162; CHECK-NEXT:    pop {r3}163; CHECK-NEXT:    beq .Ltmp3164; CHECK-NEXT:    bkpt #0165; CHECK-NEXT:  .Ltmp3:166; CHECK-NEXT:    blx r4167; CHECK-NEXT:    pop {r4, r5, r7, pc}168; Compiler shuffles: r3→r5, target→r4, d→r3 (from stack), a→r0, b→r1, c→r2169; Then pushes r3 (d value), then r2, uses R3 as temp, R2 as scratch170  call void %x(i32 %a, i32 %b, i32 %c, i32 %d) [ "kcfi"(i32 -1124498364) ]171  ret void172}173 174; Test where target ends up in R12, forcing R2 as scratch, with both R2 and R3 live175; This uses inline asm to force target into R12, with 4 call arguments to make R2/R3 live176define void @f5_r12_target_r2_r3_live(i32 %a, i32 %b, i32 %c, i32 %d) !kcfi_type !1 {177; CHECK-LABEL: f5_r12_target_r2_r3_live:178; CHECK:       @ %bb.0:179; CHECK-NEXT:    .save {r7, lr}180; CHECK-NEXT:    push {r7, lr}181; CHECK-NEXT:    @APP182; CHECK-NEXT:    @NO_APP183; CHECK-NEXT:    push {r3}184; CHECK-NEXT:    push {r2}185; CHECK-NEXT:    movs r3, #1186; CHECK-NEXT:    mov r2, r12187; CHECK-NEXT:    bics r2, r3188; CHECK-NEXT:    subs r2, #4189; CHECK-NEXT:    ldr r2, [r2]190; CHECK-NEXT:    movs r3, #188191; CHECK-NEXT:    lsls r3, r3, #8192; CHECK-NEXT:    adds r3, #249193; CHECK-NEXT:    lsls r3, r3, #8194; CHECK-NEXT:    adds r3, #132195; CHECK-NEXT:    lsls r3, r3, #8196; CHECK-NEXT:    adds r3, #68197; CHECK-NEXT:    cmp r2, r3198; CHECK-NEXT:    pop {r2}199; CHECK-NEXT:    pop {r3}200; CHECK-NEXT:    beq .Ltmp4201; CHECK-NEXT:    bkpt #0202; CHECK-NEXT:  .Ltmp4:203; CHECK-NEXT:    blx r12204; CHECK-NEXT:    pop {r7, pc}205; Use inline asm to get function pointer into R12206; With 4 arguments (r0-r3), both R2 and R3 are live207; Target in R12 means R2 is scratch, R3 is temp, and both need spilling208  %target = call ptr asm "", "={r12}"()209  call void %target(i32 %a, i32 %b, i32 %c, i32 %d) [ "kcfi"(i32 -1124498364) ]210  ret void211}212 213!llvm.module.flags = !{!0}214!0 = !{i32 4, !"kcfi", i32 1}215!1 = !{i32 -1124498364}216