| ; RUN: llc -mtriple=thumbv7m-none-macho %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NON-FAST | |
| ; RUN: llc -mtriple=thumbv7m-none-macho -O0 %s -o - -relocation-model=pic -disable-fp-elim | FileCheck %s | |
| ; RUN: llc -mtriple=thumbv7m-none-macho -filetype=obj %s -o /dev/null | |
| @var = external global i32 | |
| define i32 @test_litpool() minsize { | |
| ; CHECK-LABEL: test_litpool: | |
| %val = load i32, i32* @var | |
| ret i32 %val | |
| ; Lit-pool entries need to produce a "$non_lazy_ptr" version of the symbol. | |
| ; CHECK: LCPI0_0: | |
| ; CHECK-NEXT: .long L_var$non_lazy_ptr-(LPC0_0+4) | |
| } | |
| define i32 @test_movw_movt() { | |
| ; CHECK-LABEL: test_movw_movt: | |
| %val = load i32, i32* @var | |
| ret i32 %val | |
| ; movw/movt should also address their symbols MachO-style | |
| ; CHECK: movw [[RTMP:r[0-9]+]], :lower16:(L_var$non_lazy_ptr-(LPC1_0+4)) | |
| ; CHECK: movt [[RTMP]], :upper16:(L_var$non_lazy_ptr-(LPC1_0+4)) | |
| ; CHECK: LPC1_0: | |
| ; CHECK: add [[RTMP]], pc | |
| } | |
| declare void @llvm.trap() | |
| define void @test_trap() { | |
| ; CHECK-LABEL: test_trap: | |
| ; Bare-metal MachO gets compiled on top of normal MachO toolchain which | |
| ; understands trap natively. | |
| call void @llvm.trap() | |
| ; CHECK: trap | |
| ret void | |
| } | |
| define i32 @test_frame_ptr() { | |
| ; CHECK-LABEL: test_frame_ptr: | |
| call void @test_trap() | |
| ; Frame pointer is r7. | |
| ; CHECK: mov r7, sp | |
| ret i32 42 | |
| } | |
| %big_arr = type [8 x i32] | |
| define void @test_two_areas(%big_arr* %addr) { | |
| ; CHECK-LABEL: test_two_areas: | |
| %val = load %big_arr, %big_arr* %addr | |
| call void @test_trap() | |
| store %big_arr %val, %big_arr* %addr | |
| ; This goes with the choice of r7 as FP (largely). FP and LR have to be stored | |
| ; consecutively on the stack for the frame record to be valid, which means we | |
| ; need the 2 register-save areas employed by iOS. | |
| ; CHECK-NON-FAST: push {r4, r5, r6, r7, lr} | |
| ; CHECK-NON-FAST: push.w {r8, r9, r10, r11} | |
| ; ... | |
| ; CHECK-NON-FAST: pop.w {r8, r9, r10, r11} | |
| ; CHECK-NON-FAST: pop {r4, r5, r6, r7, pc} | |
| ret void | |
| } | |
| define void @test_tail_call() { | |
| ; CHECK-LABEL: test_tail_call: | |
| tail call void @test_trap() | |
| ; Tail calls should be available and use Thumb2 branch. | |
| ; CHECK: b.w _test_trap | |
| ret void | |
| } | |
| define float @test_softfloat_calls(float %in) { | |
| ; CHECK-LABEL: test_softfloat_calls: | |
| %sum = fadd float %in, %in | |
| ; Soft-float calls should be GNU-style rather than RTABI and should not be the | |
| ; *vfp variants used for ARMv6 iOS. | |
| ; CHECK: bl ___addsf3{{$}} | |
| ret float %sum | |
| } | |
| ; Even bare-metal PIC needs GOT-like behaviour, in principle. Depends a bit on | |
| ; the use-case of course, but LLVM doesn't know what that is. | |
| ; CHECK: non_lazy_symbol_pointers | |
| ; CHECK: L_var$non_lazy_ptr: | |
| ; CHECK-NEXT: .indirect_symbol _var | |
| ; All MachO objects should have this to give the linker leeway in removing | |
| ; dead code. | |
| ; CHECK: .subsections_via_symbols |