ffi M1.2 A.4: emitObjcDefinedClassInit class-pair registration
For every sx-defined '#objc_class', emit a module-init constructor
that registers the class with the Obj-C runtime at module load.
Pattern mirrors the Phase 3.1 emitObjcClassInit companion:
'@llvm.global_ctors' + ORC-JIT main injection.
Constructor body, per cache entry:
super = objc_getClass("<ParentName>") // default NSObject
cls = objc_allocateClassPair(super, "<ClassName>", 0)
objc_registerClassPair(cls)
Parent is read from the foreign_class_decl's '.extends' member;
absent ⇒ NSObject (matches M1.2 A.0 spec). Class-name strings
go through new emitPrivateCString helper that mirrors the
selector-init / class-init shape.
Two new small helpers extracted while we were here:
- lazyDeclareCRuntime — declare-once extern wrapper for Obj-C
runtime APIs.
- appendModuleCtor — append-or-create global_ctors + ORC-JIT
injection, factored out of emitObjcClassInit.
143-objc-class-registration.sx exercises the round-trip on
macOS: after main starts, objc_getClass("SxFoo".ptr) returns
non-null. Runs against the real Obj-C runtime.
142's IR snapshot updated — the constructor + ctors metadata
are now part of the expected shape.
DEFERRED (A.4b): method-IMP registration (class_addMethod with
a C-ABI trampoline that reads __sx_state ivar and calls the sx
body). DEFERRED (A.5+): synthesized +alloc / -dealloc IMPs and
the '__sx_state' ivar setup.
172 example tests pass (+1 from 143). zig build test green.
This commit is contained in:
@@ -22,6 +22,9 @@
|
||||
@str.16 = private unnamed_addr constant [10 x i8] c"compiled\0A\00", align 1
|
||||
@str.17 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||
@str.18 = private unnamed_addr constant [10 x i8] c"compiled\0A\00", align 1
|
||||
@OBJC_CLASS_NAME_ = private unnamed_addr constant [9 x i8] c"NSObject\00"
|
||||
@OBJC_CLASS_NAME_.19 = private unnamed_addr constant [6 x i8] c"SxFoo\00"
|
||||
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__sx_objc_defined_class_init, ptr null }]
|
||||
|
||||
; Function Attrs: nounwind
|
||||
declare void @out(ptr) #0
|
||||
@@ -735,6 +738,7 @@ entry:
|
||||
; Function Attrs: nounwind
|
||||
define i32 @main() #0 {
|
||||
entry:
|
||||
call void @__sx_objc_defined_class_init()
|
||||
%alloca = alloca { ptr, i64 }, align 8
|
||||
%gep = getelementptr inbounds { ptr, i64 }, ptr %alloca, i32 0, i32 0
|
||||
store ptr null, ptr %gep, align 8
|
||||
@@ -778,3 +782,17 @@ entry:
|
||||
}
|
||||
|
||||
declare i64 @write(i32, ptr, i64)
|
||||
|
||||
declare ptr @objc_getClass(ptr)
|
||||
|
||||
declare ptr @objc_allocateClassPair(ptr, ptr, i64)
|
||||
|
||||
declare void @objc_registerClassPair(ptr)
|
||||
|
||||
define internal void @__sx_objc_defined_class_init() {
|
||||
entry:
|
||||
%super_cls = call ptr @objc_getClass(ptr @OBJC_CLASS_NAME_)
|
||||
%cls = call ptr @objc_allocateClassPair(ptr %super_cls, ptr @OBJC_CLASS_NAME_.19, i64 0)
|
||||
call void @objc_registerClassPair(ptr %cls)
|
||||
ret void
|
||||
}
|
||||
|
||||
1
tests/expected/143-objc-class-registration.exit
Normal file
1
tests/expected/143-objc-class-registration.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
tests/expected/143-objc-class-registration.txt
Normal file
1
tests/expected/143-objc-class-registration.txt
Normal file
@@ -0,0 +1 @@
|
||||
registered: SxFoo
|
||||
Reference in New Issue
Block a user