Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4cb776b

Browse files
RISC-V go closures
This implements go closures for RISC-V. It has been tested on riscv64-suse-linux and against the libgo testsuite.
1 parent 65da63a commit 4cb776b

File tree

3 files changed

+129
-13
lines changed

3 files changed

+129
-13
lines changed

src/riscv/ffi.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,12 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsig
324324
}
325325

326326
/* Low level routine for calling functions */
327-
extern void ffi_call_asm(void *stack, struct call_context *regs, void (*fn)(void)) FFI_HIDDEN;
327+
extern void ffi_call_asm (void *stack, struct call_context *regs,
328+
void (*fn) (void), void *closure) FFI_HIDDEN;
328329

329-
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
330+
static void
331+
ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
332+
void *closure)
330333
{
331334
/* this is a conservative estimate, assuming a complex return value and
332335
that all remaining arguments are long long / __int128 */
@@ -366,13 +369,26 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
366369
for (i = 0; i < cif->nargs; i++)
367370
marshal(&cb, cif->arg_types[i], i >= cif->riscv_nfixedargs, avalue[i]);
368371

369-
ffi_call_asm((void*)alloc_base, cb.aregs, fn);
372+
ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure);
370373

371374
cb.used_float = cb.used_integer = 0;
372375
if (!return_by_ref && rvalue)
373376
unmarshal(&cb, cif->rtype, 0, rvalue);
374377
}
375378

379+
void
380+
ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
381+
{
382+
ffi_call_int(cif, fn, rvalue, avalue, NULL);
383+
}
384+
385+
void
386+
ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
387+
void **avalue, void *closure)
388+
{
389+
ffi_call_int(cif, fn, rvalue, avalue, closure);
390+
}
391+
376392
extern void ffi_closure_asm(void) FFI_HIDDEN;
377393

378394
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
@@ -406,11 +422,31 @@ ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(
406422
return FFI_OK;
407423
}
408424

425+
extern void ffi_go_closure_asm (void) FFI_HIDDEN;
426+
427+
ffi_status
428+
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
429+
void (*fun) (ffi_cif *, void *, void **, void *))
430+
{
431+
if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
432+
return FFI_BAD_ABI;
433+
434+
closure->tramp = (void *) ffi_go_closure_asm;
435+
closure->cif = cif;
436+
closure->fun = fun;
437+
438+
return FFI_OK;
439+
}
440+
409441
/* Called by the assembly code with aregs pointing to saved argument registers
410442
and stack pointing to the stacked arguments. Return values passed in
411443
registers will be reloaded from aregs. */
412-
void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closure *closure) {
413-
ffi_cif *cif = closure->cif;
444+
void FFI_HIDDEN
445+
ffi_closure_inner (ffi_cif *cif,
446+
void (*fun) (ffi_cif *, void *, void **, void *),
447+
void *user_data,
448+
size_t *stack, call_context *aregs)
449+
{
414450
void **avalue = alloca(cif->nargs * sizeof(void*));
415451
/* storage for arguments which will be copied by unmarshal(). We could
416452
theoretically avoid the copies in many cases and use at most 128 bytes
@@ -436,7 +472,7 @@ void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closur
436472
avalue[i] = unmarshal(&cb, cif->arg_types[i],
437473
i >= cif->riscv_nfixedargs, astorage + i*MAXCOPYARG);
438474

439-
(closure->fun)(cif, rvalue, avalue, closure->user_data);
475+
fun (cif, rvalue, avalue, user_data);
440476

441477
if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) {
442478
cb.used_integer = cb.used_float = 0;

src/riscv/ffitarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef enum ffi_abi {
5959
/* ---- Definitions for closures ----------------------------------------- */
6060

6161
#define FFI_CLOSURES 1
62+
#define FFI_GO_CLOSURES 1
6263
#define FFI_TRAMPOLINE_SIZE 24
6364
#define FFI_NATIVE_RAW_API 0
6465
#define FFI_EXTRA_CIF_FIELDS unsigned riscv_nfixedargs; unsigned riscv_unused;

src/riscv/sysv.S

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@
6767
intreg pad[rv32 ? 2 : 0];
6868
intreg save_fp, save_ra;
6969
}
70-
void ffi_call_asm(size_t *stackargs, struct call_context *regargs,
71-
void (*fn)(void));
70+
void ffi_call_asm (size_t *stackargs, struct call_context *regargs,
71+
void (*fn) (void), void *closure);
7272
*/
7373

7474
#define FRAME_LEN (8 * FLTS + 8 * PTRS + 16)
@@ -98,6 +98,7 @@ ffi_call_asm:
9898

9999
# Load arguments
100100
mv t1, a2
101+
mv t2, a3
101102

102103
#if FLTS
103104
FLARG fa0, -FRAME_LEN+0*FLTS(fp)
@@ -145,8 +146,10 @@ ffi_call_asm:
145146

146147
/*
147148
ffi_closure_asm. Expects address of the passed-in ffi_closure in t1.
148-
void ffi_closure_inner(size_t *stackargs, struct call_context *regargs,
149-
ffi_closure *closure);
149+
void ffi_closure_inner (ffi_cif *cif,
150+
void (*fun) (ffi_cif *, void *, void **, void *),
151+
void *user_data,
152+
size_t *stackargs, struct call_context *regargs)
150153
*/
151154

152155
.globl ffi_closure_asm
@@ -187,9 +190,11 @@ ffi_closure_asm:
187190
SARG a7, 8*FLTS+7*PTRS(sp)
188191

189192
/* enter C */
190-
addi a0, sp, FRAME_LEN
191-
mv a1, sp
192-
mv a2, t1
193+
LARG a0, FFI_TRAMPOLINE_SIZE+0*PTRS(t1)
194+
LARG a1, FFI_TRAMPOLINE_SIZE+1*PTRS(t1)
195+
LARG a2, FFI_TRAMPOLINE_SIZE+2*PTRS(t1)
196+
addi a3, sp, FRAME_LEN
197+
mv a4, sp
193198

194199
call ffi_closure_inner
195200

@@ -212,3 +217,77 @@ ffi_closure_asm:
212217
ret
213218
.cfi_endproc
214219
.size ffi_closure_asm, .-ffi_closure_asm
220+
221+
/*
222+
ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2.
223+
void ffi_closure_inner (ffi_cif *cif,
224+
void (*fun) (ffi_cif *, void *, void **, void *),
225+
void *user_data,
226+
size_t *stackargs, struct call_context *regargs)
227+
*/
228+
229+
.globl ffi_go_closure_asm
230+
.hidden ffi_go_closure_asm
231+
.type ffi_go_closure_asm, @function
232+
ffi_go_closure_asm:
233+
.cfi_startproc
234+
235+
addi sp, sp, -FRAME_LEN
236+
.cfi_def_cfa_offset FRAME_LEN
237+
238+
/* make a frame */
239+
SARG fp, FRAME_LEN - 2*PTRS(sp)
240+
.cfi_offset 8, -2*PTRS
241+
SARG ra, FRAME_LEN - 1*PTRS(sp)
242+
.cfi_offset 1, -1*PTRS
243+
addi fp, sp, FRAME_LEN
244+
245+
/* save arguments */
246+
#if FLTS
247+
FSARG fa0, 0*FLTS(sp)
248+
FSARG fa1, 1*FLTS(sp)
249+
FSARG fa2, 2*FLTS(sp)
250+
FSARG fa3, 3*FLTS(sp)
251+
FSARG fa4, 4*FLTS(sp)
252+
FSARG fa5, 5*FLTS(sp)
253+
FSARG fa6, 6*FLTS(sp)
254+
FSARG fa7, 7*FLTS(sp)
255+
#endif
256+
257+
SARG a0, 8*FLTS+0*PTRS(sp)
258+
SARG a1, 8*FLTS+1*PTRS(sp)
259+
SARG a2, 8*FLTS+2*PTRS(sp)
260+
SARG a3, 8*FLTS+3*PTRS(sp)
261+
SARG a4, 8*FLTS+4*PTRS(sp)
262+
SARG a5, 8*FLTS+5*PTRS(sp)
263+
SARG a6, 8*FLTS+6*PTRS(sp)
264+
SARG a7, 8*FLTS+7*PTRS(sp)
265+
266+
/* enter C */
267+
LARG a0, 1*PTRS(t2)
268+
LARG a1, 2*PTRS(t2)
269+
mv a2, t2
270+
addi a3, sp, FRAME_LEN
271+
mv a4, sp
272+
273+
call ffi_closure_inner
274+
275+
/* return values */
276+
#if FLTS
277+
FLARG fa0, 0*FLTS(sp)
278+
FLARG fa1, 1*FLTS(sp)
279+
#endif
280+
281+
LARG a0, 8*FLTS+0*PTRS(sp)
282+
LARG a1, 8*FLTS+1*PTRS(sp)
283+
284+
/* restore and return */
285+
LARG ra, FRAME_LEN-1*PTRS(sp)
286+
.cfi_restore 1
287+
LARG fp, FRAME_LEN-2*PTRS(sp)
288+
.cfi_restore 8
289+
addi sp, sp, FRAME_LEN
290+
.cfi_def_cfa_offset 0
291+
ret
292+
.cfi_endproc
293+
.size ffi_go_closure_asm, .-ffi_go_closure_asm

0 commit comments

Comments
 (0)