xref: /llvm-project/lld/test/MachO/objc-category-merging-minimal.s (revision dca43a1c82f1023127343daae487c3a6a8c7e3d4)
1# REQUIRES: aarch64
2# UNSUPPORTED: system-windows
3#   due to awk usage
4
5# RUN: rm -rf %t; split-file %s %t && cd %t
6
7############ Test merging multiple categories into a single category ############
8## Create a dylib with a fake base class to link against in when merging between categories
9# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_fakedylib.o a64_fakedylib.s
10# RUN: %lld -arch arm64 a64_fakedylib.o -o a64_fakedylib.dylib -dylib
11
12## Create our main testing dylib - linking against the fake dylib above
13# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_cat_minimal.o merge_cat_minimal.s
14# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_no_merge.dylib a64_fakedylib.dylib merge_cat_minimal.o
15# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_merge.dylib -objc_category_merging a64_fakedylib.dylib merge_cat_minimal.o
16
17## Now verify that the flag caused category merging to happen appropriatelly
18# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_CATS
19# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_merge.dylib | FileCheck %s --check-prefixes=MERGE_CATS
20
21############ Test merging multiple categories into the base class ############
22# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_base_class_minimal.o merge_base_class_minimal.s
23# RUN: %lld -arch arm64 -dylib -o merge_base_class_minimal_yes_merge.dylib -objc_category_merging merge_base_class_minimal.o merge_cat_minimal.o
24# RUN: %lld -arch arm64 -dylib -o merge_base_class_minimal_no_merge.dylib merge_base_class_minimal.o merge_cat_minimal.o
25
26# RUN: llvm-objdump --objc-meta-data --macho merge_base_class_minimal_no_merge.dylib  | FileCheck %s --check-prefixes=NO_MERGE_INTO_BASE
27# RUN: llvm-objdump --objc-meta-data --macho merge_base_class_minimal_yes_merge.dylib | FileCheck %s --check-prefixes=YES_MERGE_INTO_BASE
28
29############ Test merging swift category into the base class ############
30# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o MyBaseClassSwiftExtension.o MyBaseClassSwiftExtension.s
31# RUN: %lld -no_objc_relative_method_lists -arch arm64 -dylib -o merge_base_class_swift_minimal_yes_merge.dylib -objc_category_merging MyBaseClassSwiftExtension.o merge_base_class_minimal.o
32# RUN: llvm-objdump --objc-meta-data --macho merge_base_class_swift_minimal_yes_merge.dylib | FileCheck %s --check-prefixes=YES_MERGE_INTO_BASE_SWIFT
33
34############ Test merging skipped due to invalid category name ############
35# Modify __OBJC_$_CATEGORY_MyBaseClass_$_Category01's name to point to L_OBJC_IMAGE_INFO+3
36# RUN: awk '/^__OBJC_\$_CATEGORY_MyBaseClass_\$_Category01:/ { print; getline; sub(/^[ \t]*\.quad[ \t]+l_OBJC_CLASS_NAME_$/, "\t.quad\tL_OBJC_IMAGE_INFO+3"); print; next } { print }' merge_cat_minimal.s > merge_cat_minimal_bad_name.s
37
38# Assemble the modified source
39# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_cat_minimal_bad_name.o merge_cat_minimal_bad_name.s
40
41# Run lld and check for the specific warning
42# RUN: %no-fatal-warnings-lld -arch arm64 -dylib -objc_category_merging -o merge_cat_minimal_merge.dylib a64_fakedylib.dylib merge_cat_minimal_bad_name.o 2>&1 | FileCheck %s --check-prefix=MERGE_WARNING
43
44# Check that lld emitted the warning about skipping category merging
45MERGE_WARNING: warning: ObjC category merging skipped for class symbol' _OBJC_CLASS_$_MyBaseClass'
46
47#### Check merge categories enabled ###
48# Check that the original categories are not there
49MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
50MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
51
52# Check that the merged cateogry is there, in the correct format
53MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass(Category01|Category02)
54MERGE_CATS-NEXT:   name {{.*}} Category01|Category02
55MERGE_CATS:       instanceMethods
56MERGE_CATS-NEXT:  entsize 12 (relative)
57MERGE_CATS-NEXT:  count 2
58MERGE_CATS-NEXT:   name {{.*}} cat01_InstanceMethod
59MERGE_CATS-NEXT:  types {{.*}} v16@0:8
60MERGE_CATS-NEXT:    imp {{.*}} -[MyBaseClass(Category01) cat01_InstanceMethod]
61MERGE_CATS-NEXT:   name {{.*}} cat02_InstanceMethod
62MERGE_CATS-NEXT:  types {{.*}} v16@0:8
63MERGE_CATS-NEXT:    imp {{.*}} -[MyBaseClass(Category02) cat02_InstanceMethod]
64MERGE_CATS-NEXT:         classMethods 0x0
65MERGE_CATS-NEXT:            protocols 0x0
66MERGE_CATS-NEXT:   instanceProperties 0x0
67
68#### Check merge categories disabled ###
69# Check that the merged category is not there
70NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass(Category01|Category02)
71
72# Check that the original categories are there
73NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
74NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
75
76
77#### Check merge cateogires into base class is disabled ####
78NO_MERGE_INTO_BASE: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
79NO_MERGE_INTO_BASE: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
80
81#### Check merge cateogires into base class is enabled and categories are merged into base class ####
82YES_MERGE_INTO_BASE-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
83YES_MERGE_INTO_BASE-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
84
85YES_MERGE_INTO_BASE: _OBJC_CLASS_$_MyBaseClass
86YES_MERGE_INTO_BASE-NEXT: _OBJC_METACLASS_$_MyBaseClass
87YES_MERGE_INTO_BASE: baseMethods
88YES_MERGE_INTO_BASE-NEXT: entsize 12 (relative)
89YES_MERGE_INTO_BASE-NEXT: count 3
90YES_MERGE_INTO_BASE-NEXT: name {{.*}} cat01_InstanceMethod
91YES_MERGE_INTO_BASE-NEXT: types {{.*}} v16@0:8
92YES_MERGE_INTO_BASE-NEXT: imp {{.*}} -[MyBaseClass(Category01) cat01_InstanceMethod]
93YES_MERGE_INTO_BASE-NEXT: name {{.*}} cat02_InstanceMethod
94YES_MERGE_INTO_BASE-NEXT: types {{.*}} v16@0:8
95YES_MERGE_INTO_BASE-NEXT: imp {{.*}} -[MyBaseClass(Category02) cat02_InstanceMethod]
96YES_MERGE_INTO_BASE-NEXT: name {{.*}} baseInstanceMethod
97YES_MERGE_INTO_BASE-NEXT: types {{.*}} v16@0:8
98YES_MERGE_INTO_BASE-NEXT: imp {{.*}} -[MyBaseClass baseInstanceMethod]
99
100
101#### Check merge swift category into base class ###
102YES_MERGE_INTO_BASE_SWIFT: _OBJC_CLASS_$_MyBaseClass
103YES_MERGE_INTO_BASE_SWIFT-NEXT: _OBJC_METACLASS_$_MyBaseClass
104YES_MERGE_INTO_BASE_SWIFT: baseMethods
105YES_MERGE_INTO_BASE_SWIFT-NEXT: entsize 24
106YES_MERGE_INTO_BASE_SWIFT-NEXT: count 2
107YES_MERGE_INTO_BASE_SWIFT-NEXT: name {{.*}} swiftMethod
108YES_MERGE_INTO_BASE_SWIFT-NEXT: types {{.*}} v16@0:8
109YES_MERGE_INTO_BASE_SWIFT-NEXT: imp _$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyFTo
110YES_MERGE_INTO_BASE_SWIFT-NEXT: name {{.*}} baseInstanceMethod
111YES_MERGE_INTO_BASE_SWIFT-NEXT: types {{.*}} v16@0:8
112YES_MERGE_INTO_BASE_SWIFT-NEXT: imp -[MyBaseClass baseInstanceMethod]
113
114
115#--- a64_fakedylib.s
116
117    .section    __DATA,__objc_data
118    .globl    _OBJC_CLASS_$_MyBaseClass
119_OBJC_CLASS_$_MyBaseClass:
120    .quad    0
121
122#--- merge_cat_minimal.s
123
124;  ================== Generated from ObjC: ==================
125; __attribute__((objc_root_class))
126; @interface MyBaseClass
127; - (void)baseInstanceMethod;
128; @end
129;
130; @interface MyBaseClass(Category01)
131; - (void)cat01_InstanceMethod;
132; @end
133;
134; @implementation MyBaseClass(Category01)
135; - (void)cat01_InstanceMethod {}
136; @end
137;
138; @interface MyBaseClass(Category02)
139; - (void)cat02_InstanceMethod;
140; @end
141;
142; @implementation MyBaseClass(Category02)
143; - (void)cat02_InstanceMethod {}
144; @end
145;  ================== Generated from ObjC: ==================
146
147	.section	__TEXT,__text,regular,pure_instructions
148	.p2align	2                               ; -- Begin function -[MyBaseClass(Category01) cat01_InstanceMethod]
149"-[MyBaseClass(Category01) cat01_InstanceMethod]": ; @"\01-[MyBaseClass(Category01) cat01_InstanceMethod]"
150	.cfi_startproc
151	ret
152	.cfi_endproc
153                                        ; -- End function
154	.p2align	2                               ; -- Begin function -[MyBaseClass(Category02) cat02_InstanceMethod]
155"-[MyBaseClass(Category02) cat02_InstanceMethod]": ; @"\01-[MyBaseClass(Category02) cat02_InstanceMethod]"
156	.cfi_startproc
157	ret
158	.cfi_endproc
159                                        ; -- End function
160	.section	__TEXT,__objc_classname,cstring_literals
161l_OBJC_CLASS_NAME_:                     ; @OBJC_CLASS_NAME_
162	.asciz	"Category01"
163	.section	__TEXT,__objc_methname,cstring_literals
164l_OBJC_METH_VAR_NAME_:                  ; @OBJC_METH_VAR_NAME_
165	.asciz	"cat01_InstanceMethod"
166	.section	__TEXT,__objc_methtype,cstring_literals
167l_OBJC_METH_VAR_TYPE_:                  ; @OBJC_METH_VAR_TYPE_
168	.asciz	"v16@0:8"
169	.section	__DATA,__objc_const
170	.p2align	3, 0x0                          ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01"
171__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01:
172	.long	24                              ; 0x18
173	.long	1                               ; 0x1
174	.quad	l_OBJC_METH_VAR_NAME_
175	.quad	l_OBJC_METH_VAR_TYPE_
176	.quad	"-[MyBaseClass(Category01) cat01_InstanceMethod]"
177	.p2align	3, 0x0                          ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category01"
178__OBJC_$_CATEGORY_MyBaseClass_$_Category01:
179	.quad	l_OBJC_CLASS_NAME_
180	.quad	_OBJC_CLASS_$_MyBaseClass
181	.quad	__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01
182	.quad	0
183	.quad	0
184	.quad	0
185	.quad	0
186	.long	64                              ; 0x40
187	.space	4
188	.section	__DATA,__objc_const
189l_OBJC_CLASS_NAME_.1:                   ; @OBJC_CLASS_NAME_.1
190	.asciz	"Category02"
191	.section	__TEXT,__objc_methname,cstring_literals
192l_OBJC_METH_VAR_NAME_.2:                ; @OBJC_METH_VAR_NAME_.2
193	.asciz	"cat02_InstanceMethod"
194	.section	__DATA,__objc_const
195	.p2align	3, 0x0                          ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02"
196__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02:
197	.long	24                              ; 0x18
198	.long	1                               ; 0x1
199	.quad	l_OBJC_METH_VAR_NAME_.2
200	.quad	l_OBJC_METH_VAR_TYPE_
201	.quad	"-[MyBaseClass(Category02) cat02_InstanceMethod]"
202	.p2align	3, 0x0                          ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02"
203__OBJC_$_CATEGORY_MyBaseClass_$_Category02:
204	.quad	l_OBJC_CLASS_NAME_.1
205	.quad	_OBJC_CLASS_$_MyBaseClass
206	.quad	__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02
207	.quad	0
208	.quad	0
209	.quad	0
210	.quad	0
211	.long	64                              ; 0x40
212	.space	4
213	.section	__DATA,__objc_catlist,regular,no_dead_strip
214	.p2align	3, 0x0                          ; @"OBJC_LABEL_CATEGORY_$"
215l_OBJC_LABEL_CATEGORY_$:
216	.quad	__OBJC_$_CATEGORY_MyBaseClass_$_Category01
217	.quad	__OBJC_$_CATEGORY_MyBaseClass_$_Category02
218	.section	__DATA,__objc_imageinfo,regular,no_dead_strip
219L_OBJC_IMAGE_INFO:
220	.long	0
221	.long	96
222.subsections_via_symbols
223
224.addrsig
225.addrsig_sym __OBJC_$_CATEGORY_MyBaseClass_$_Category01
226
227#--- merge_base_class_minimal.s
228; clang -c merge_base_class_minimal.mm -O3 -target arm64-apple-macos -arch arm64 -S -o merge_base_class_minimal.s
229;  ================== Generated from ObjC: ==================
230; __attribute__((objc_root_class))
231; @interface MyBaseClass
232; - (void)baseInstanceMethod;
233; @end
234;
235; @implementation MyBaseClass
236; - (void)baseInstanceMethod {}
237; @end
238;  ================== Generated from ObjC  ==================
239	.section	__TEXT,__text,regular,pure_instructions
240	.build_version macos, 11, 0
241	.p2align	2
242"-[MyBaseClass baseInstanceMethod]":
243	.cfi_startproc
244; %bb.0:
245	ret
246	.cfi_endproc
247	.section	__DATA,__objc_data
248	.globl	_OBJC_CLASS_$_MyBaseClass
249	.p2align	3, 0x0
250_OBJC_CLASS_$_MyBaseClass:
251	.quad	_OBJC_METACLASS_$_MyBaseClass
252	.quad	0
253	.quad	0
254	.quad	0
255	.quad	__OBJC_CLASS_RO_$_MyBaseClass
256	.globl	_OBJC_METACLASS_$_MyBaseClass
257	.p2align	3, 0x0
258_OBJC_METACLASS_$_MyBaseClass:
259	.quad	_OBJC_METACLASS_$_MyBaseClass
260	.quad	_OBJC_CLASS_$_MyBaseClass
261	.quad	0
262	.quad	0
263	.quad	__OBJC_METACLASS_RO_$_MyBaseClass
264	.section	__TEXT,__objc_classname,cstring_literals
265l_OBJC_CLASS_NAME_:
266	.asciz	"MyBaseClass"
267	.section	__DATA,__objc_const
268	.p2align	3, 0x0
269__OBJC_METACLASS_RO_$_MyBaseClass:
270	.long	3
271	.long	40
272	.long	40
273	.space	4
274	.quad	0
275	.quad	l_OBJC_CLASS_NAME_
276	.quad	0
277	.quad	0
278	.quad	0
279	.quad	0
280	.quad	0
281	.section	__TEXT,__objc_methname,cstring_literals
282l_OBJC_METH_VAR_NAME_:
283	.asciz	"baseInstanceMethod"
284	.section	__TEXT,__objc_methtype,cstring_literals
285l_OBJC_METH_VAR_TYPE_:
286	.asciz	"v16@0:8"
287	.section	__DATA,__objc_const
288	.p2align	3, 0x0
289__OBJC_$_INSTANCE_METHODS_MyBaseClass:
290	.long	24
291	.long	1
292	.quad	l_OBJC_METH_VAR_NAME_
293	.quad	l_OBJC_METH_VAR_TYPE_
294	.quad	"-[MyBaseClass baseInstanceMethod]"
295	.p2align	3, 0x0
296__OBJC_CLASS_RO_$_MyBaseClass:
297	.long	2
298	.long	0
299	.long	0
300	.space	4
301	.quad	0
302	.quad	l_OBJC_CLASS_NAME_
303	.quad	__OBJC_$_INSTANCE_METHODS_MyBaseClass
304	.quad	0
305	.quad	0
306	.quad	0
307	.quad	0
308	.section	__DATA,__objc_classlist,regular,no_dead_strip
309	.p2align	3, 0x0
310l_OBJC_LABEL_CLASS_$:
311	.quad	_OBJC_CLASS_$_MyBaseClass
312	.section	__DATA,__objc_imageinfo,regular,no_dead_strip
313L_OBJC_IMAGE_INFO:
314	.long	0
315	.long	64
316.subsections_via_symbols
317
318
319#--- MyBaseClassSwiftExtension.s
320; xcrun -sdk macosx swiftc -emit-assembly MyBaseClassSwiftExtension.swift -import-objc-header YourProject-Bridging-Header.h -o MyBaseClassSwiftExtension.s
321;  ================== Generated from Swift: ==================
322; import Foundation
323; extension MyBaseClass {
324;     @objc func swiftMethod() {
325;     }
326; }
327;  ================== Generated from Swift ===================
328	.private_extern	_$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyF
329	.globl	_$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyF
330	.p2align	2
331_$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyF:
332	.cfi_startproc
333	mov	w0, #0
334	ret
335	.cfi_endproc
336
337	.p2align	2
338_$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyFTo:
339	.cfi_startproc
340	mov	w0, #0
341	ret
342	.cfi_endproc
343
344	.section	__TEXT,__cstring,cstring_literals
345	.p2align	4, 0x0
346l_.str.25.MyBaseClassSwiftExtension:
347	.asciz	"MyBaseClassSwiftExtension"
348
349	.section	__TEXT,__objc_methname,cstring_literals
350"L_selector_data(swiftMethod)":
351	.asciz	"swiftMethod"
352
353	.section	__TEXT,__cstring,cstring_literals
354"l_.str.7.v16@0:8":
355	.asciz	"v16@0:8"
356
357	.section	__DATA,__objc_data
358	.p2align	3, 0x0
359__CATEGORY_INSTANCE_METHODS_MyBaseClass_$_MyBaseClassSwiftExtension:
360	.long	24
361	.long	1
362	.quad	"L_selector_data(swiftMethod)"
363	.quad	"l_.str.7.v16@0:8"
364	.quad	_$sSo11MyBaseClassC0abC14SwiftExtensionE11swiftMethodyyFTo
365
366	.section	__DATA,__objc_const
367	.p2align	3, 0x0
368__CATEGORY_MyBaseClass_$_MyBaseClassSwiftExtension:
369	.quad	l_.str.25.MyBaseClassSwiftExtension
370	.quad	_OBJC_CLASS_$_MyBaseClass
371	.quad	__CATEGORY_INSTANCE_METHODS_MyBaseClass_$_MyBaseClassSwiftExtension
372	.quad	0
373	.quad	0
374	.quad	0
375	.quad	0
376	.long	60
377	.space	4
378
379	.section	__DATA,__objc_catlist,regular,no_dead_strip
380	.p2align	3, 0x0
381_objc_categories:
382	.quad	__CATEGORY_MyBaseClass_$_MyBaseClassSwiftExtension
383
384	.no_dead_strip	_main
385	.no_dead_strip	l_entry_point
386
387.subsections_via_symbols
388