summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-25 06:19:09 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-25 06:19:09 -0700
commit02c9c3c46a4e77939f0b2f58b9dcfab950980a82 (patch)
tree35da71725ab7381105be957037fae2a2c6249078
parent2948a2b1e01b91e17d90d2e7954f0d3a499a3a4d (diff)
downloadtxr-02c9c3c46a4e77939f0b2f58b9dcfab950980a82.tar.gz
txr-02c9c3c46a4e77939f0b2f58b9dcfab950980a82.tar.bz2
txr-02c9c3c46a4e77939f0b2f58b9dcfab950980a82.zip
ffi: precompute member offsets in struct type.
This change will make bitfield support easier. * ffi.c (struct smemb): New member, offs. (ffi_struct_in, ffi_struct_put, ffi_struct_out, ffi_struct_get, ffi_struct_release): For each member, refer to the offset in the memb array, rather than calculating it on-the-fly. (make_ffi_type_struct): Calculate the offset for each member. This is exactly the same as the total_size calculation before; just the name is changed to offs, and bit operations are used for the alignment calculations.
-rw-r--r--ffi.c40
1 files changed, 14 insertions, 26 deletions
diff --git a/ffi.c b/ffi.c
index 0e271618..4c46a8f0 100644
--- a/ffi.c
+++ b/ffi.c
@@ -99,6 +99,7 @@ struct smemb {
val mname;
val mtype;
struct txr_ffi_type *mtft;
+ cnum offs;
};
struct txr_ffi_type {
@@ -965,7 +966,6 @@ static val ffi_struct_in(struct txr_ffi_type *tft, int copy, mem_t *src,
{
cnum i, nmemb = tft->nelem;
struct smemb *memb = tft->memb;
- ucnum offs = 0;
if (strct == nil) {
args_decl(args, 0);
@@ -975,8 +975,7 @@ static val ffi_struct_in(struct txr_ffi_type *tft, int copy, mem_t *src,
for (i = 0; i < nmemb; i++) {
val slsym = memb[i].mname;
struct txr_ffi_type *mtft = memb[i].mtft;
- ucnum almask = mtft->align - 1;
- offs = (offs + almask) & ~almask;
+ ucnum offs = memb[i].offs;
if (slsym) {
if (mtft->in != 0) {
val slval = slot(strct, slsym);
@@ -986,7 +985,6 @@ static val ffi_struct_in(struct txr_ffi_type *tft, int copy, mem_t *src,
slotset(strct, slsym, slval);
}
}
- offs += mtft->size;
}
return strct;
@@ -997,18 +995,15 @@ static void ffi_struct_put(struct txr_ffi_type *tft, val strct, mem_t *dst,
{
cnum i, nmemb = tft->nelem;
struct smemb *memb = tft->memb;
- ucnum offs = 0;
for (i = 0; i < nmemb; i++) {
val slsym = memb[i].mname;
struct txr_ffi_type *mtft = memb[i].mtft;
- ucnum almask = mtft->align - 1;
- offs = (offs + almask) & ~almask;
+ ucnum offs = memb[i].offs;
if (slsym) {
val slval = slot(strct, slsym);
mtft->put(mtft, slval, dst + offs, self);
}
- offs += mtft->size;
}
}
@@ -1017,13 +1012,11 @@ static void ffi_struct_out(struct txr_ffi_type *tft, int copy, val strct,
{
cnum i, nmemb = tft->nelem;
struct smemb *memb = tft->memb;
- ucnum offs = 0;
for (i = 0; i < nmemb; i++) {
val slsym = memb[i].mname;
struct txr_ffi_type *mtft = memb[i].mtft;
- ucnum almask = mtft->align - 1;
- offs = (offs + almask) & ~almask;
+ ucnum offs = memb[i].offs;
if (slsym) {
if (mtft->out != 0) {
val slval = slot(strct, slsym);
@@ -1033,7 +1026,6 @@ static void ffi_struct_out(struct txr_ffi_type *tft, int copy, val strct,
mtft->put(mtft, slval, dst + offs, self);
}
}
- offs += mtft->size;
}
}
@@ -1041,20 +1033,17 @@ static val ffi_struct_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
cnum i, nmemb = tft->nelem;
struct smemb *memb = tft->memb;
- ucnum offs = 0;
args_decl(args, 0);
val strct = make_struct(tft->lt, nil, args);
for (i = 0; i < nmemb; i++) {
val slsym = memb[i].mname;
struct txr_ffi_type *mtft = memb[i].mtft;
- ucnum almask = mtft->align - 1;
- offs = (offs + almask) & ~almask;
+ ucnum offs = memb[i].offs;
if (slsym) {
val slval = mtft->get(mtft, src + offs, self);
slotset(strct, slsym, slval);
}
- offs += mtft->size;
}
return strct;
@@ -1064,7 +1053,6 @@ static void ffi_struct_release(struct txr_ffi_type *tft, val strct, mem_t *dst)
{
cnum i, nmemb = tft->nelem;
struct smemb *memb = tft->memb;
- ucnum offs = 0;
if (strct == nil)
return;
@@ -1072,15 +1060,13 @@ static void ffi_struct_release(struct txr_ffi_type *tft, val strct, mem_t *dst)
for (i = 0; i < nmemb; i++) {
val slsym = memb[i].mname;
struct txr_ffi_type *mtft = memb[i].mtft;
- ucnum almask = mtft->align - 1;
- offs = (offs + almask) & ~almask;
+ ucnum offs = memb[i].offs;
if (slsym) {
if (mtft->release != 0) {
val slval = slot(strct, slsym);
mtft->release(mtft, slval, dst + offs);
}
}
- offs += mtft->size;
}
}
@@ -1530,8 +1516,8 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
struct smemb *memb = coerce(struct smemb *,
chk_malloc(sizeof *memb * nmemb));
val obj = cobj(coerce(mem_t *, tft), ffi_type_s, &ffi_type_struct_ops);
- cnum total_size = 0;
- cnum most_align = 0;
+ ucnum offs = 0;
+ ucnum most_align = 0;
int need_out_handler = 0;
ft->type = FFI_TYPE_STRUCT;
@@ -1554,18 +1540,22 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
struct txr_ffi_type *mtft = ffi_type_struct(type);
cnum align = mtft->align;
cnum size = mtft->size;
+ ucnum almask = align - 1;
elements[i] = mtft->ft;
memb[i].mtype = type;
memb[i].mname = slot;
memb[i].mtft = mtft;
+ memb[i].offs = offs;
if (align > most_align)
most_align = align;
- total_size = (total_size + align - 1) / align * align + size;
need_out_handler = need_out_handler || mtft->out != 0;
+
+ offs += size;
+ offs = (offs + almask) & ~almask;
}
elements[i] = 0;
@@ -1575,9 +1565,7 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
ft->elements = elements;
- total_size = (total_size + most_align - 1) / most_align * most_align;
-
- tft->size = total_size;
+ tft->size = (offs + most_align - 1) & ~(most_align - 1);
tft->align = most_align;
tft->memb = memb;