1f554e272SFangrui Song; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s
2f554e272SFangrui Song; RUN: llc -mtriple=aarch64 -function-sections %s -o - | FileCheck %s
3*853a2649SFangrui Song; RUN: llc -mtriple=aarch64 -function-sections %s -o - | FileCheck %s
4*853a2649SFangrui Song; RUN: llc -mtriple=aarch64 -no-integrated-as -binutils-version=2.35 %s -o - | FileCheck --check-prefix=NOLINK %s
5*853a2649SFangrui Song; RUN: llc -mtriple=aarch64 -no-integrated-as -binutils-version=2.36 %s -o - | FileCheck %s
64d1e23e3SFangrui Song
7*853a2649SFangrui Song;; GNU ld < 2.36 did not support mixed SHF_LINK_ORDER and non-SHF_LINK_ORDER sections.
84d1e23e3SFangrui Song; NOLINK-NOT: "awo"
94d1e23e3SFangrui Song
104d1e23e3SFangrui Songdefine i32 @f0() "patchable-function-entry"="0" {
114d1e23e3SFangrui Song; CHECK-LABEL: f0:
124d1e23e3SFangrui Song; CHECK-NEXT: .Lfunc_begin0:
134d1e23e3SFangrui Song; CHECK-NOT:   nop
144d1e23e3SFangrui Song; CHECK:       mov w0, wzr
15d232c215SFangrui Song; CHECK-NOT:   .section __patchable_function_entries
164d1e23e3SFangrui Song  ret i32 0
174d1e23e3SFangrui Song}
184d1e23e3SFangrui Song
194d1e23e3SFangrui Songdefine i32 @f1() "patchable-function-entry"="1" {
204d1e23e3SFangrui Song; CHECK-LABEL: f1:
214d1e23e3SFangrui Song; CHECK-NEXT: .Lfunc_begin1:
224d1e23e3SFangrui Song; CHECK:       nop
234d1e23e3SFangrui Song; CHECK-NEXT:  mov w0, wzr
24f554e272SFangrui Song; CHECK:       .section __patchable_function_entries,"awo",@progbits,f1{{$}}
254d1e23e3SFangrui Song; CHECK-NEXT:  .p2align 3
264d1e23e3SFangrui Song; CHECK-NEXT:  .xword .Lfunc_begin1
274d1e23e3SFangrui Song  ret i32 0
284d1e23e3SFangrui Song}
294d1e23e3SFangrui Song
3022467e25SFangrui Song;; Without -function-sections, f2 is in the same text section as f1.
3122467e25SFangrui Song;; They share the __patchable_function_entries section.
3222467e25SFangrui Song;; With -function-sections, f1 and f2 are in different text sections.
3322467e25SFangrui Song;; Use separate __patchable_function_entries.
34d232c215SFangrui Songdefine void @f2() "patchable-function-entry"="2" {
35d232c215SFangrui Song; CHECK-LABEL: f2:
36d232c215SFangrui Song; CHECK-NEXT: .Lfunc_begin2:
37d232c215SFangrui Song; CHECK-COUNT-2: nop
38d232c215SFangrui Song; CHECK-NEXT:  ret
39f554e272SFangrui Song; CHECK:       .section __patchable_function_entries,"awo",@progbits,f2{{$}}
40d232c215SFangrui Song; CHECK-NEXT:  .p2align 3
41d232c215SFangrui Song; CHECK-NEXT:  .xword .Lfunc_begin2
42d232c215SFangrui Song  ret void
43d232c215SFangrui Song}
44d232c215SFangrui Song
454d1e23e3SFangrui Song$f3 = comdat any
464d1e23e3SFangrui Songdefine void @f3() "patchable-function-entry"="3" comdat {
474d1e23e3SFangrui Song; CHECK-LABEL: f3:
48d232c215SFangrui Song; CHECK-NEXT: .Lfunc_begin3:
494d1e23e3SFangrui Song; CHECK-COUNT-3: nop
504d1e23e3SFangrui Song; CHECK-NEXT:  ret
51f554e272SFangrui Song; CHECK:       .section __patchable_function_entries,"aGwo",@progbits,f3,comdat,f3{{$}}
524d1e23e3SFangrui Song; CHECK-NEXT:  .p2align 3
53d232c215SFangrui Song; CHECK-NEXT:  .xword .Lfunc_begin3
544d1e23e3SFangrui Song  ret void
554d1e23e3SFangrui Song}
564d1e23e3SFangrui Song
574d1e23e3SFangrui Song$f5 = comdat any
584d1e23e3SFangrui Songdefine void @f5() "patchable-function-entry"="5" comdat {
594d1e23e3SFangrui Song; CHECK-LABEL: f5:
60d232c215SFangrui Song; CHECK-NEXT: .Lfunc_begin4:
614d1e23e3SFangrui Song; CHECK-COUNT-5: nop
624d1e23e3SFangrui Song; CHECK-NEXT:  sub sp, sp, #16
63f554e272SFangrui Song; CHECK:       .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
644d1e23e3SFangrui Song; CHECK:       .p2align 3
65d232c215SFangrui Song; CHECK-NEXT:  .xword .Lfunc_begin4
664d1e23e3SFangrui Song  %frame = alloca i8, i32 16
674d1e23e3SFangrui Song  ret void
684d1e23e3SFangrui Song}
6922467e25SFangrui Song
7022467e25SFangrui Song;; -fpatchable-function-entry=3,2
7122467e25SFangrui Song;; "patchable-function-prefix" emits data before the function entry label.
7222467e25SFangrui Songdefine void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
7322467e25SFangrui Song; CHECK-LABEL: .type f3_2,@function
7422467e25SFangrui Song; CHECK-NEXT: .Ltmp1: // @f3_2
7522467e25SFangrui Song; CHECK-NEXT:  nop
7622467e25SFangrui Song; CHECK-NEXT:  nop
7722467e25SFangrui Song; CHECK-NEXT: f3_2:
7822467e25SFangrui Song; CHECK:      // %bb.0:
7922467e25SFangrui Song; CHECK-NEXT:  nop
8022467e25SFangrui Song; CHECK-NEXT:  ret
8122467e25SFangrui Song;; .size does not include the prefix.
8222467e25SFangrui Song; CHECK:      .Lfunc_end5:
8322467e25SFangrui Song; CHECK-NEXT: .size f3_2, .Lfunc_end5-f3_2
84f554e272SFangrui Song; CHECK:      .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
8522467e25SFangrui Song; CHECK:      .p2align 3
8622467e25SFangrui Song; CHECK-NEXT: .xword .Ltmp1
8722467e25SFangrui Song  ret void
8822467e25SFangrui Song}
8922467e25SFangrui Song
9022467e25SFangrui Song;; When prefix data is used, arbitrarily place NOPs after prefix data.
9122467e25SFangrui Songdefine void @prefix() "patchable-function-entry"="0" "patchable-function-prefix"="1" prefix i32 1 {
9222467e25SFangrui Song; CHECK-LABEL: .type prefix,@function
9322467e25SFangrui Song; CHECK-NEXT: .word 1 // @prefix
9422467e25SFangrui Song; CHECK:      .Ltmp2:
9522467e25SFangrui Song; CHECK:       nop
9622467e25SFangrui Song; CHECK-NEXT: prefix:
9722467e25SFangrui Song;; Emit a __patchable_function_entries entry even if "patchable-function-entry" is 0.
98f554e272SFangrui Song; CHECK:      .section __patchable_function_entries,"awo",@progbits,prefix{{$}}
9922467e25SFangrui Song; CHECK:      .p2align 3
10022467e25SFangrui Song; CHECK-NEXT: .xword .Ltmp2
10122467e25SFangrui Song  ret void
10222467e25SFangrui Song}
103