# REQUIRES: x86
# UNSUPPORTED: target=arm{{.*}}-unknown-linux-gnueabihf
# RUN: rm -rf %t; split-file %s %t && cd %t

## Compile rel_dylib.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o rel_dylib.o simple_class.s

## Test relative method lists
# RUN: %no-lsystem-lld rel_dylib.o -o rel_dylib.dylib -map rel_dylib.map -dylib -objc_relative_method_lists
# RUN: llvm-objdump --macho --objc-meta-data rel_dylib.dylib  | FileCheck %s --check-prefix=CHK_REL

## Test relative method lists + dead-strip
# RUN: %no-lsystem-lld rel_dylib.o -o rel_dylib.dylib -map rel_dylib.map -dylib -objc_relative_method_lists -dead_strip
# RUN: llvm-objdump --macho --objc-meta-data rel_dylib.dylib  | FileCheck %s --check-prefix=CHK_REL

## Test traditional method lists (no relative offsets)
# RUN: %no-lsystem-lld rel_dylib.o -o rel_dylib.dylib -map rel_dylib.map -dylib -no_objc_relative_method_lists
# RUN: llvm-objdump --macho --objc-meta-data rel_dylib.dylib  | FileCheck %s --check-prefix=CHK_NO_REL


CHK_REL:       Contents of (__DATA_CONST,__objc_classlist) section
CHK_REL-NEXT:  _OBJC_CLASS_$_MyClass
CHK_REL:       baseMethods
CHK_REL-NEXT:  entsize 12 (relative)
CHK_REL-NEXT:  count 3
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_00
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_00]
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_01
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_01]
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_02
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_02]

CHK_REL:       Meta Class
CHK_REL-NEXT:  isa 0x{{[0-9a-f]*}} _OBJC_METACLASS_$_MyClass
CHK_REL:       baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *)
CHK_REL-NEXT:  entsize 12 (relative)
CHK_REL-NEXT:  count 3
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  class_method_00
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  +[MyClass class_method_00]
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  class_method_01
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  +[MyClass class_method_01]
CHK_REL-NEXT:   name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  class_method_02
CHK_REL-NEXT:  types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  v16@0:8
CHK_REL-NEXT:    imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}})  +[MyClass class_method_02]


CHK_NO_REL-NOT: (relative)

CHK_NO_REL:           Contents of (__DATA_CONST,__objc_classlist) section
CHK_NO_REL-NEXT:      _OBJC_CLASS_$_MyClass

CHK_NO_REL:            baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *)
CHK_NO_REL-NEXT:		   entsize 24
CHK_NO_REL-NEXT:		     count 3
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} instance_method_00
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp -[MyClass instance_method_00]
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} instance_method_01
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp -[MyClass instance_method_01]
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} instance_method_02
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp -[MyClass instance_method_02]


CHK_NO_REL:             Meta Class
CHK_NO_REL-NEXT:        _OBJC_METACLASS_$_MyClass

CHK_NO_REL:             baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *)
CHK_NO_REL-NEXT:		   entsize 24
CHK_NO_REL-NEXT:		     count 3
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} class_method_00
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp +[MyClass class_method_00]
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} class_method_01
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp +[MyClass class_method_01]
CHK_NO_REL-NEXT:		      name 0x{{[0-9a-f]*}} class_method_02
CHK_NO_REL-NEXT:		     types 0x{{[0-9a-f]*}} v16@0:8
CHK_NO_REL-NEXT:		       imp +[MyClass class_method_02]


######################## Generate simple_class.s #########################
# clang -c simple_class.mm -s -o simple_class.s -target x86_64-apple-macos11 -Oz

########################       simple_class.mm       ########################
#  __attribute__((objc_root_class))
#  @interface MyClass
#  - (void)instance_method_00;
#  - (void)instance_method_01;
#  - (void)instance_method_02;
#  + (void)class_method_00;
#  + (void)class_method_01;
#  + (void)class_method_02;
#  @end
#
#  @implementation MyClass
#  - (void)instance_method_00 {}
#  - (void)instance_method_01 {}
#  - (void)instance_method_02 {}
#  + (void)class_method_00 {}
#  + (void)class_method_01 {}
#  + (void)class_method_02 {}
#  @end
#
#  void *_objc_empty_cache;
#

#--- objc-macros.s
.macro .objc_selector_def name
	.p2align	2
"\name":
	.cfi_startproc
	ret
	.cfi_endproc
.endm

#--- simple_class.s
.include "objc-macros.s"

.section	__TEXT,__text,regular,pure_instructions
.build_version macos, 11, 0

.objc_selector_def "-[MyClass instance_method_00]"
.objc_selector_def "-[MyClass instance_method_01]"
.objc_selector_def "-[MyClass instance_method_02]"

.objc_selector_def "+[MyClass class_method_00]"
.objc_selector_def "+[MyClass class_method_01]"
.objc_selector_def "+[MyClass class_method_02]"

.section	__DATA,__objc_data
.globl	_OBJC_CLASS_$_MyClass
.p2align	3, 0x0
_OBJC_CLASS_$_MyClass:
	.quad	_OBJC_METACLASS_$_MyClass
	.quad	0
	.quad	__objc_empty_cache
	.quad	0
	.quad	__OBJC_CLASS_RO_$_MyClass

	.globl	_OBJC_METACLASS_$_MyClass
	.p2align	3, 0x0
_OBJC_METACLASS_$_MyClass:
	.quad	_OBJC_METACLASS_$_MyClass
	.quad	_OBJC_CLASS_$_MyClass
	.quad	__objc_empty_cache
	.quad	0
	.quad	__OBJC_METACLASS_RO_$_MyClass

	.section	__TEXT,__objc_classname,cstring_literals
L_OBJC_CLASS_NAME_:
	.asciz	"MyClass"

	.section	__TEXT,__objc_methname,cstring_literals
L_OBJC_METH_VAR_NAME_:
	.asciz	"class_method_00"

	.section	__TEXT,__objc_methtype,cstring_literals
L_OBJC_METH_VAR_TYPE_:
	.asciz	"v16@0:8"

	.section	__TEXT,__objc_methname,cstring_literals
L_OBJC_METH_VAR_NAME_.1:
	.asciz	"class_method_01"

L_OBJC_METH_VAR_NAME_.2:
	.asciz	"class_method_02"

	.section	__DATA,__objc_const
	.p2align	3, 0x0
__OBJC_$_CLASS_METHODS_MyClass:
	.long	24
	.long	3
	.quad	L_OBJC_METH_VAR_NAME_
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"+[MyClass class_method_00]"
	.quad	L_OBJC_METH_VAR_NAME_.1
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"+[MyClass class_method_01]"
	.quad	L_OBJC_METH_VAR_NAME_.2
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"+[MyClass class_method_02]"

	.p2align	3, 0x0
__OBJC_METACLASS_RO_$_MyClass:
	.long	3
	.long	40
	.long	40
	.space	4
	.quad	0
	.quad	L_OBJC_CLASS_NAME_
	.quad	__OBJC_$_CLASS_METHODS_MyClass
	.quad	0
	.quad	0
	.quad	0
	.quad	0

	.section	__TEXT,__objc_methname,cstring_literals
L_OBJC_METH_VAR_NAME_.3:
	.asciz	"instance_method_00"

L_OBJC_METH_VAR_NAME_.4:
	.asciz	"instance_method_01"

L_OBJC_METH_VAR_NAME_.5:
	.asciz	"instance_method_02"

	.section	__DATA,__objc_const
	.p2align	3, 0x0
__OBJC_$_INSTANCE_METHODS_MyClass:
	.long	24
	.long	3
	.quad	L_OBJC_METH_VAR_NAME_.3
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"-[MyClass instance_method_00]"
	.quad	L_OBJC_METH_VAR_NAME_.4
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"-[MyClass instance_method_01]"
	.quad	L_OBJC_METH_VAR_NAME_.5
	.quad	L_OBJC_METH_VAR_TYPE_
	.quad	"-[MyClass instance_method_02]"

	.p2align	3, 0x0
__OBJC_CLASS_RO_$_MyClass:
	.long	2
	.long	0
	.long	0
	.space	4
	.quad	0
	.quad	L_OBJC_CLASS_NAME_
	.quad	__OBJC_$_INSTANCE_METHODS_MyClass
	.quad	0
	.quad	0
	.quad	0
	.quad	0

	.globl	__objc_empty_cache
.zerofill __DATA,__common,__objc_empty_cache,8,3
	.section	__DATA,__objc_classlist,regular,no_dead_strip
	.p2align	3, 0x0
l_OBJC_LABEL_CLASS_$:
	.quad	_OBJC_CLASS_$_MyClass

	.section	__DATA,__objc_imageinfo,regular,no_dead_strip
L_OBJC_IMAGE_INFO:
	.long	0
	.long	64

.subsections_via_symbols
