summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi.c107
1 files changed, 40 insertions, 67 deletions
diff --git a/ffi.c b/ffi.c
index 16bedd40..43ae753c 100644
--- a/ffi.c
+++ b/ffi.c
@@ -95,11 +95,10 @@ struct txr_ffi_type {
void (*put)(struct txr_ffi_type *, val obj, mem_t *dst,
mem_t *rtvec[], val self);
val (*get)(struct txr_ffi_type *, mem_t *src, val self);
- void (*in)(struct txr_ffi_type *, val obj,
+ void (*in)(struct txr_ffi_type *, mem_t *src, val obj,
mem_t *rtvec[], val self);
mem_t *(*alloc)(struct txr_ffi_type *, val obj, val self);
void (*free)(void *);
- void (*fill)(struct txr_ffi_type *, mem_t *src, val obj, val self);
};
static struct txr_ffi_type *ffi_type_struct(val obj)
@@ -653,10 +652,11 @@ static mem_t *ffi_cptr_alloc(struct txr_ffi_type *tft, val ptr, val self)
return coerce(mem_t *, cptr_addr_of(ptr));
}
-static void ffi_freeing_in(struct txr_ffi_type *tft, val obj,
+static void ffi_freeing_in(struct txr_ffi_type *tft, mem_t *src, val obj,
mem_t *rtvec[], val self)
{
mem_t **loc = &rtvec[tft->rtidx];
+ (void) src;
(void) obj;
(void) self;
free(*loc);
@@ -827,7 +827,7 @@ static void ffi_ptr_walk(struct txr_ffi_type *tft, mem_t *ctx,
visit(tgtft, ctx);
}
-static void ffi_ptr_in_in(struct txr_ffi_type *tft, val obj,
+static void ffi_ptr_in_in(struct txr_ffi_type *tft, mem_t *src, val obj,
mem_t *rtvec[], val self)
{
val tgttype = tft->mtypes;
@@ -868,14 +868,14 @@ static void ffi_ptr_in_d_put(struct txr_ffi_type *tft, val s, mem_t *dst,
}
}
-static void ffi_ptr_out_in(struct txr_ffi_type *tft, val obj,
+static void ffi_ptr_out_in(struct txr_ffi_type *tft, mem_t *src, val obj,
mem_t *rtvec[], val self)
{
val tgttype = tft->mtypes;
struct txr_ffi_type *tgtft = ffi_type_struct(tgttype);
mem_t **loc = &rtvec[tft->rtidx];
- if (tgtft->fill != 0)
- tgtft->fill(tgtft, *loc, obj, self);
+ if (tgtft->in != 0)
+ tgtft->in(tgtft, *loc, obj, rtvec, self);
tgtft->free(*loc);
*loc = 0;
}
@@ -941,16 +941,29 @@ static void ffi_struct_walk(struct txr_ffi_type *tft, mem_t *ctx,
}
}
-static void ffi_struct_in(struct txr_ffi_type *tft, val obj,
+static void ffi_struct_in(struct txr_ffi_type *tft, mem_t *src, val strct,
mem_t *rtvec[], val self)
{
+ val slots = tft->mnames;
val types = tft->mtypes;
+ ucnum offs = 0;
- while (types) {
+ while (slots) {
+ val slsym = pop(&slots);
val type = pop(&types);
struct txr_ffi_type *mtft = ffi_type_struct(type);
- if (mtft->in != 0)
- mtft->in(mtft, obj, rtvec, self);
+ ucnum almask = mtft->align - 1;
+ offs = (offs + almask) & ~almask;
+ if (slsym) {
+ if (mtft->in != 0) {
+ val slval = slot(strct, slsym);
+ mtft->in(mtft, src + offs, slval, rtvec, self);
+ } else {
+ val slval = mtft->get(mtft, src + offs, self);
+ slotset(strct, slsym, slval);
+ }
+ }
+ offs += mtft->size;
}
}
@@ -1001,41 +1014,25 @@ static val ffi_struct_get(struct txr_ffi_type *tft, mem_t *src, val self)
return strct;
}
-static void ffi_struct_fill(struct txr_ffi_type *tft, mem_t *src,
- val strct, val self)
-{
- val slots = tft->mnames;
- val types = tft->mtypes;
- ucnum offs = 0;
-
- while (slots) {
- val slsym = pop(&slots);
- val type = pop(&types);
- struct txr_ffi_type *mtft = ffi_type_struct(type);
- ucnum almask = mtft->align - 1;
- val slval;
- offs = (offs + almask) & ~almask;
- if (slsym) {
- slval = mtft->get(mtft, src + offs, self);
- slotset(strct, slsym, slval);
- }
- offs += mtft->size;
- }
-}
-
-static void ffi_array_in(struct txr_ffi_type *tft, val obj,
+static void ffi_array_in(struct txr_ffi_type *tft, mem_t *src, val vec,
mem_t *rtvec[], val self)
{
val eltypes = tft->mtypes;
cnum nelem = tft->nelem, i;
+ ucnum offs = 0;
for (i = 0; i < nelem; i++) {
val eltype = pop(&eltypes);
struct txr_ffi_type *etft = ffi_type_struct(eltype);
- if (i == nelem - 1 && tft->null_term)
- break;
- if (etft->in != 0)
- etft->in(etft, obj, rtvec, self);
+ cnum elsize = etft->size;
+ if (etft->in != 0) {
+ val elval = ref(vec, num_fast(i));
+ etft->in(etft, src + offs, elval, rtvec, self);
+ } else {
+ val elval = etft->get(etft, src + offs, self);
+ refset(vec, num_fast(i), elval);
+ }
+ offs += elsize;
}
}
@@ -1109,23 +1106,6 @@ static val ffi_array_get(struct txr_ffi_type *tft, mem_t *src, val self)
}
}
-static void ffi_array_fill(struct txr_ffi_type *tft, mem_t *src,
- val vec, val self)
-{
- val eltypes = tft->mtypes;
- cnum nelem = tft->nelem, i;
- ucnum offs = 0;
-
- for (i = 0; i < nelem; i++) {
- val eltype = pop(&eltypes);
- struct txr_ffi_type *etft = ffi_type_struct(eltype);
- cnum elsize = etft->size;
- val elval = etft->get(etft, src + offs, self);
- refset(vec, num_fast(i), elval);
- offs += elsize;
- }
-}
-
static val make_ffi_type_builtin(val syntax, val lisp_type,
cnum size, ffi_type *ft,
void (*put)(struct txr_ffi_type *,
@@ -1159,8 +1139,8 @@ static val make_ffi_type_pointer(val syntax, val lisp_type,
val self),
val (*get)(struct txr_ffi_type *,
mem_t *src, val self),
- void (*in)(struct txr_ffi_type *, val obj,
- mem_t *rtvec[], val self),
+ void (*in)(struct txr_ffi_type *, mem_t *src,
+ val obj, mem_t *rtvec[], val self),
val tgtype)
{
struct txr_ffi_type *tft = coerce(struct txr_ffi_type *,
@@ -1198,7 +1178,6 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
val obj = cobj(coerce(mem_t *, tft), ffi_type_s, &ffi_type_struct_ops);
cnum total_size = 0;
cnum most_align = 0;
- int need_in_handler = 0;
ft->type = FFI_TYPE_STRUCT;
ft->size = 0;
@@ -1211,9 +1190,9 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
tft->walk = ffi_struct_walk;
tft->put = ffi_struct_put;
tft->get = ffi_struct_get;
+ tft->in = ffi_struct_in;
tft->alloc = ffi_fixed_alloc;
tft->free = free;
- tft->fill = ffi_struct_fill;
for (i = 0; i < nmemb; i++) {
val type = pop(&types);
@@ -1227,14 +1206,10 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
most_align = align;
total_size = (total_size + align - 1) / align * align + size;
- need_in_handler = need_in_handler || mtft->rtsize != 0 || mtft->in != 0;
}
elements[i] = 0;
- if (need_in_handler)
- tft->in = ffi_struct_in;
-
ft->elements = elements;
total_size = (total_size + most_align - 1) / most_align * most_align;
@@ -1268,9 +1243,9 @@ static val make_ffi_type_array(val syntax, val lisp_type,
tft->walk = ffi_struct_walk;
tft->put = ffi_array_put;
tft->get = ffi_array_get;
+ tft->in = ffi_array_in;
tft->alloc = ffi_fixed_alloc;
tft->free = free;
- tft->fill = ffi_array_fill;
for (i = 0; i < nelem; i++) {
val eltype = pop(&eltypes);
@@ -1279,8 +1254,6 @@ static val make_ffi_type_array(val syntax, val lisp_type,
if (i == 0) {
tft->size = etft->size * nelem;
tft->align = etft->align;
- if (etft->rtsize != 0 || etft->in != 0)
- tft->in = ffi_array_in;
}
}
@@ -1692,7 +1665,7 @@ val ffi_call_wrap(val ffi_call_desc, val fptr, val args_in)
val arg = pop(&args);
struct txr_ffi_type *mtft = ffi_type_struct(type);
if (mtft->in != 0)
- mtft->in(mtft, arg, rtvec[i], self);
+ mtft->in(mtft, 0, arg, rtvec[i], self);
}
}