1# REQUIRES: x86 2# RUN: rm -rf %t; split-file %s %t 3# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o 4# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o 5# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o 6# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -g -o %t/cat1_w_sym.o 7# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -g -o %t/cat2_w_sym.o 8# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -g -o %t/klass_w_sym.o 9# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat1-with-load.o 10# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat2-with-load.o 11# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s --defsym MAKE_LOAD_METHOD=1 -o %t/klass-with-load.o 12# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass-with-no-rodata.s -o %t/klass-with-no-rodata.o 13# RUN: %lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o -o %t/libklass.dylib 14 15# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ 16# RUN: /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT 17# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1.o \ 18# RUN: %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT 19 20# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass_w_sym.o %t/cat1_w_sym.o %t/cat2_w_sym.o -o \ 21# RUN: /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS_W_SYM,CATCAT_W_SYM 22# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1_w_sym.o \ 23# RUN: %t/cat2_w_sym.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT_W_SYM 24 25## Check that we don't emit spurious warnings around the +load method while 26## still emitting the other warnings. Note that we have made separate 27## `*-with-load.s` files for ease of comparison with ld64; ld64 will not warn 28## at all if multiple +load methods are present. 29# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-load.o \ 30# RUN: %t/cat1-with-load.o %t/cat2-with-load.o -o /dev/null 2>&1 | \ 31# RUN: FileCheck %s --check-prefixes=CATCLS,CATCAT --implicit-check-not '+load' 32 33## Regression test: Check that we don't crash. 34# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null 35 36## Check that we don't emit any warnings without --check-category-conflicts. 37# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ 38# RUN: /dev/null 2>&1 | FileCheck %s --implicit-check-not 'warning' --allow-empty 39 40# CATCLS: warning: method '+s1' has conflicting definitions: 41# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o 42# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o 43 44# CATCLS: warning: method '-m1' has conflicting definitions: 45# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o 46# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o 47 48# CATCAT: warning: method '+s2' has conflicting definitions: 49# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o 50# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o 51 52# CATCAT: warning: method '-m2' has conflicting definitions: 53# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o 54# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o 55 56 57# CATCLS_W_SYM: warning: method '+s1' has conflicting definitions: 58# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}}) 59# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}}) 60 61# CATCLS_W_SYM: warning: method '-m1' has conflicting definitions: 62# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}}) 63# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}}) 64 65# CATCAT_W_SYM: warning: method '+s2' has conflicting definitions: 66# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}}) 67# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}}) 68 69# CATCAT_W_SYM: warning: method '-m2' has conflicting definitions: 70# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}}) 71# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}}) 72 73 74#--- cat1.s 75 76.include "objc-macros.s" 77 78## @interface Foo(Cat1) 79## -(void) m1; 80## -(void) m2; 81## +(void) s1; 82## +(void) s2; 83## @end 84## 85## @implementation Foo(Cat1) 86## -(void) m1 {} 87## -(void) m2 {} 88## +(void) s1 {} 89## +(void) s2 {} 90## @end 91 92.section __DATA,__objc_catlist,regular,no_dead_strip 93 .quad __OBJC_$_CATEGORY_Foo_$_Cat1 94 95.ifdef MAKE_LOAD_METHOD 96.section __DATA,__objc_nlcatlist,regular,no_dead_strip 97 .quad __OBJC_$_CATEGORY_Foo_$_Cat1 98.endif 99 100.section __DATA,__objc_const 101__OBJC_$_CATEGORY_Foo_$_Cat1: 102 .objc_classname "Cat1" 103 .quad _OBJC_CLASS_$_Foo 104 .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1 105 .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1 106 .quad 0 107 .quad 0 108 .quad 0 109 .long 64 110 .space 4 111 112__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1: 113 .long 24 # size of method entry 114 .long 2 # number of methods 115 .empty_objc_method "m1", "v16@0:8", "-[Foo(Cat1) m1]" 116 .empty_objc_method "m2", "v16@0:8", "-[Foo(Cat2) m2]" 117 118__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1: 119 .long 24 120.ifdef MAKE_LOAD_METHOD 121 .long 3 122 .empty_objc_method "load", "v16@0:8", "+[Foo(Cat1) load]" 123.else 124 .long 2 125.endif 126 .empty_objc_method "s1", "v16@0:8", "+[Foo(Cat1) s1]" 127 .empty_objc_method "s2", "v16@0:8", "+[Foo(Cat1) s2]" 128 129.section __DATA,__objc_imageinfo,regular,no_dead_strip 130 .long 0 131 .long 64 132 133.subsections_via_symbols 134 135#--- cat2.s 136 137.include "objc-macros.s" 138 139## @interface Foo(Cat2) 140## -(void) m2; 141## +(void) s2; 142## @end 143## 144## @implementation Foo(Cat2) 145## -(void) m2 {} 146## +(void) s2 {} 147## @end 148 149.section __DATA,__objc_catlist,regular,no_dead_strip 150 .quad __OBJC_$_CATEGORY_Foo_$_Cat2 151 152.ifdef MAKE_LOAD_METHOD 153.section __DATA,__objc_nlcatlist,regular,no_dead_strip 154 .quad __OBJC_$_CATEGORY_Foo_$_Cat2 155.endif 156 157.section __DATA,__objc_const 158__OBJC_$_CATEGORY_Foo_$_Cat2: 159 .objc_classname "Cat2" 160 .quad _OBJC_CLASS_$_Foo 161 .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2 162 .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2 163 .quad 0 164 .quad 0 165 .quad 0 166 .long 64 167 .space 4 168 169__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2: 170 .long 24 171 .long 1 172 .empty_objc_method "m2", "v16@0:8", "-[Foo(Cat2) m2]" 173 174__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2: 175 .long 24 176.ifdef MAKE_LOAD_METHOD 177 .long 2 178 .empty_objc_method "load", "v16@0:8", "+[Foo(Cat2) load]" 179.else 180 .long 1 181.endif 182 .empty_objc_method "s2", "v16@0:8", "+[Foo(Cat2) m2]" 183 184.section __DATA,__objc_imageinfo,regular,no_dead_strip 185 .long 0 186 .long 64 187 188.subsections_via_symbols 189 190#--- klass.s 191 192.include "objc-macros.s" 193 194## @interface Foo 195## -(void) m1; 196## +(void) s1; 197## @end 198## 199## @implementation Foo 200## -(void) m1 {} 201## +(void) s1 {} 202## @end 203 204.globl _OBJC_CLASS_$_Foo, _OBJC_METACLASS_$_Foo 205 206.section __DATA,__objc_data 207_OBJC_CLASS_$_Foo: 208 .quad _OBJC_METACLASS_$_Foo 209 .quad 0 210 .quad __objc_empty_cache 211 .quad 0 212 .quad __OBJC_CLASS_RO_$_Foo 213 214_OBJC_METACLASS_$_Foo: 215 .quad _OBJC_METACLASS_$_Foo 216 .quad _OBJC_CLASS_$_Foo 217 .quad __objc_empty_cache 218 .quad 0 219 .quad __OBJC_METACLASS_RO_$_Foo 220 221.section __DATA,__objc_const 222__OBJC_METACLASS_RO_$_Foo: 223 .long 3 224 .long 40 225 .long 40 226 .space 4 227 .quad 0 228 .objc_classname "Foo" 229 .quad __OBJC_$_CLASS_METHODS_Foo 230 .quad 0 231 .quad 0 232 .quad 0 233 .quad 0 234 235__OBJC_CLASS_RO_$_Foo: 236 .long 2 237 .long 0 238 .long 0 239 .space 4 240 .quad 0 241 .objc_classname "Foo" 242 .quad __OBJC_$_INSTANCE_METHODS_Foo 243 .quad 0 244 .quad 0 245 .quad 0 246 .quad 0 247 248__OBJC_$_CLASS_METHODS_Foo: 249 .long 24 250.ifdef MAKE_LOAD_METHOD 251 .long 2 252 .empty_objc_method "load", "v16@0:8", "+[Foo load]" 253.else 254 .long 1 255.endif 256 .empty_objc_method "s1", "v16@0:8", "+[Foo s1]" 257 258__OBJC_$_INSTANCE_METHODS_Foo: 259 .long 24 260 .long 1 261 .empty_objc_method "m1", "v16@0:8", "-[Foo m1]" 262 263.section __DATA,__objc_classlist,regular,no_dead_strip 264 .quad _OBJC_CLASS_$_Foo 265 266.ifdef MAKE_LOAD_METHOD 267.section __DATA,__objc_nlclslist,regular,no_dead_strip 268 .quad _OBJC_CLASS_$_Foo 269.endif 270 271.section __DATA,__objc_imageinfo,regular,no_dead_strip 272 .long 0 273 .long 64 274 275.subsections_via_symbols 276 277#--- klass-with-no-rodata.s 278 279.include "objc-macros.s" 280 281## swiftc generates some classes without a statically-linked rodata. Not 282## entirely sure what the corresponding Swift inputs are required for this to 283## happen; this test merely checks that we can gracefully handle this case 284## without crashing. 285## FIXME: It would be better if this test used the output of some real Swift 286## code. 287 288.globl _$s11FooAACfD 289 290.section __DATA,__objc_data 291_$s11FooAACfD: 292 .quad _$s11FooAACfD 293 .quad 0 294 .quad __objc_empty_cache 295 .quad 0 296 .quad __objc_empty_cache 297 298.section __DATA,__objc_catlist,regular,no_dead_strip 299 .quad __CATEGORY_METAFoo_$_Foo20 300 301.section __DATA,__objc_const 302__CATEGORY_METAFoo_$_Foo20: 303 .objc_classname "Foo20" 304 .quad _$s11FooAACfD 305 .quad 0 306 .quad 0 307 .quad 0 308 .quad 0 309 .quad 0 310 .long 64 311 .space 4 312 313#--- objc-macros.s 314 315# Macros for taking some of the boilerplate out of defining objc structs. 316 317# NOTE: \@ below is a variable that gets auto-incremented by the assembler on 318# each macro invocation. It serves as a mechanism for generating unique symbol 319# names for each macro call. 320 321.macro .objc_classname name 322 323 .section __TEXT,__objc_classname,cstring_literals 324 L_OBJC_CLASS_NAME_.\@: 325 .asciz "\name" 326 327 .section __DATA,__objc_const 328 .quad L_OBJC_CLASS_NAME_.\@ 329 330.endm 331 332# struct method_t { 333# const char *name; 334# const char *type; 335# void *impl; 336# } 337.macro .objc_method name, type, impl 338 339 .section __TEXT,__objc_methname,cstring_literals 340 L_OBJC_METH_VAR_NAME_.\@: 341 .asciz "\name" 342 343 .section __TEXT,__objc_methtype,cstring_literals 344 L_OBJC_METH_VAR_TYPE_.\@: 345 .asciz "\type" 346 347 .section __DATA,__objc_const 348 .quad L_OBJC_METH_VAR_NAME_.\@ 349 .quad L_OBJC_METH_VAR_TYPE_.\@ 350 .quad "\impl" 351 352.endm 353 354# Generate a method_t with a basic impl that just contains `ret`. 355.macro .empty_objc_method name, type, impl 356 357 .text 358 "\impl": 359 ret 360 361 .objc_method "\name", "\type", "\impl" 362 363.endm 364