@@ -167,10 +167,11 @@ Let's consider a simple call in LLVM IR:
167167
168168.. code-block :: llvm
169169
170- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
170+ declare void @foo()
171+ define ptr addrspace(1) @test1(ptr addrspace(1) %obj)
171172 gc "statepoint-example" {
172- call void ()* @foo()
173- ret i8 addrspace(1)* %obj
173+ call void @foo()
174+ ret ptr addrspace(1) %obj
174175 }
175176
176177 Depending on our language we may need to allow a safepoint during the execution
@@ -186,11 +187,11 @@ resulting relocation sequence is:
186187
187188.. code-block :: llvm
188189
189- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
190+ define ptr addrspace(1) @test(ptr addrspace(1) %obj)
190191 gc "statepoint-example" {
191- %0 = call token (i64, i32, void ()* , i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
192- %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8 (token %0 , i32 7 , i32 7 )
193- ret i8 addrspace(1)* %obj.relocated
192+ %safepoint = call token (i64, i32, ptr , i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, ptr elementtype( void ()) @foo, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %obj)]
193+ %obj.relocated = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1 (token %safepoint , i32 0 , i32 0 )
194+ ret ptr addrspace(1) %obj.relocated
194195 }
195196
196197 Ideally, this sequence would have been represented as a M argument, N
@@ -269,10 +270,13 @@ collector:
269270
270271.. code-block :: llvm
271272
272- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
273- gc "statepoint-example" {
274- call token (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
275- ret i8 addrspace(1)* %obj
273+ define void @manual_frame(ptr %a, ptr %b) gc "statepoint-example" {
274+ %alloca = alloca ptr
275+ %allocb = alloca ptr
276+ store ptr %a, ptr %alloca
277+ store ptr %b, ptr %allocb
278+ call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr %alloca, ptr %allocb)]
279+ ret void
276280 }
277281
278282 Recording On Stack Regions
@@ -332,25 +336,6 @@ lowering both the base and derived pointer operands are required to be live
332336over the associated call safepoint even if the base is otherwise unused
333337afterwards.
334338
335- If we extend our previous example to include a pointless derived pointer,
336- we get:
337-
338- .. code-block :: llvm
339-
340- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
341- gc "statepoint-example" {
342- %gep = getelementptr i8, i8 addrspace(1)* %obj, i64 20000
343- %token = call token (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %gep)
344- %obj.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token, i32 7, i32 7)
345- %gep.relocated = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token, i32 7, i32 8)
346- %p = getelementptr i8, i8 addrspace(1)* %gep, i64 -20000
347- ret i8 addrspace(1)* %p
348- }
349-
350- Note that in this example %p and %obj.relocate are the same address and we
351- could replace one with the other, potentially removing the derived pointer
352- from the live set at the safepoint entirely.
353-
354339.. _gc_transition_args :
355340
356341GC Transitions
@@ -564,21 +549,20 @@ As an example, given this code:
564549
565550.. code-block :: llvm
566551
567- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
552+ define ptr addrspace(1) @test1(ptr addrspace(1) %obj)
568553 gc "statepoint-example" {
569554 call void @foo()
570- ret i8 addrspace(1)* %obj
555+ ret ptr addrspace(1) %obj
571556 }
572557
573558 The pass would produce this IR:
574559
575560.. code-block :: llvm
576561
577- define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
578- gc "statepoint-example" {
579- %0 = call token (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
580- %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12)
581- ret i8 addrspace(1)* %obj.relocated
562+ define ptr addrspace(1) @test_rs4gc(ptr addrspace(1) %obj) gc "statepoint-example" {
563+ %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(ptr addrspace(1) %obj) ]
564+ %obj.relocated = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %statepoint_token, i32 0, i32 0) ; (%obj, %obj)
565+ ret ptr addrspace(1) %obj.relocated
582566 }
583567
584568 In the above examples, the addrspace(1) marker on the pointers is the mechanism
0 commit comments