summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-20 00:37:38 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-20 00:37:38 -0700
commit0069c0b05d810c001c1ab9947b1f8f333caede14 (patch)
treecf9ff1eb72a5dc28e0738e50bd7d6ccf5b849639 /ffi.c
parent7aaa45187b87573080e92671336ed623f02428a8 (diff)
downloadtxr-0069c0b05d810c001c1ab9947b1f8f333caede14.tar.gz
txr-0069c0b05d810c001c1ab9947b1f8f333caede14.tar.bz2
txr-0069c0b05d810c001c1ab9947b1f8f333caede14.zip
ffi: new pack type operator; align increases only.
* ffi.c (pack_s): New symbol variable. (ffi_type_compile): Handle new pack type operator together with align. Allow a one-argument form of align and pack in which the value is defaulted. The behavior of align changes: align can only increase alignment now, never decrease, so for instance (align 1 ...) does nothing. pack must be used to decrease alignment. Furthermore, for certain argument types, pack performs transformations of the type syntax, rather than compiling the argument type and producing a variant of it with altered alignment. * txr.1: Documented. * stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/ffi.c b/ffi.c
index 5db3df87..4fbb6d28 100644
--- a/ffi.c
+++ b/ffi.c
@@ -148,7 +148,7 @@ val sbit_s, ubit_s; /* bit_s is in arith.c */
val enum_s, enumed_s, elemtype_s;
-val align_s;
+val align_s, pack_s;
val bool_s;
@@ -3919,6 +3919,28 @@ static val ffi_struct_init(val slot_init, val strct)
return nil;
}
+static val ffi_pack_members(val struct_syntax, val align)
+{
+ val op = pop(&struct_syntax);
+ val name = pop(&struct_syntax);
+ val iter;
+ list_collect_decl (packed, ptail);
+
+ for (iter = struct_syntax; iter; iter = cdr(iter)) {
+ val slot_spec = car(iter);
+ val slot = car(slot_spec);
+ val type = cadr(slot_spec);
+ val init = caddr(slot_spec);
+ val packed_type = list(pack_s, align, type, nao);
+
+ ptail = list_collect(ptail, if3(init,
+ list(slot, packed_type, init, nao),
+ list(slot, packed_type, nao)));
+ }
+
+ return cons(op, cons(name, packed));
+}
+
val ffi_type_compile(val syntax)
{
val self = lit("ffi-type-compile");
@@ -4292,26 +4314,37 @@ val ffi_type_compile(val syntax)
lit("~a: enum name ~s must be bindable symbol or nil"),
self, name, nao);
return make_ffi_type_enum(xsyntax, enums, base_type, self);
- } else if (sym == align_s && !consp(cddr(syntax))) {
- goto toofew;
- } else if (sym == align_s) {
- val align = ffi_eval_expr(cadr(syntax), nil, nil);
- ucnum al = c_num(align, self);
+ } else if (sym == align_s || sym == pack_s) {
+ int twoarg = !consp(cddr(syntax));
+ val align = if3(twoarg,
+ if3(sym == pack_s, one, num_fast(16)),
+ ffi_eval_expr(cadr(syntax), nil, nil));
+ cnum al = c_num(align, self);
if (cdddr(syntax))
goto excess;
if (al <= 0) {
uw_throwf(error_s, lit("~a: alignment must be positive"),
self, nao);
- } else if (al != 0 && (al & (al - 1)) != 0) {
+ } else if ((al & (al - 1)) != 0) {
uw_throwf(error_s, lit("~a: alignment must be a power of two"),
self, nao);
} else {
- val alsyntax = caddr(syntax);
- val altype = ffi_type_compile(alsyntax);
- val altype_copy = ffi_type_copy(altype);
- struct txr_ffi_type *atft = ffi_type_struct(altype_copy);
- atft->align = al;
- return altype_copy;
+ val alsyntax = if3(twoarg, cadr(syntax), caddr(syntax));
+ val xalsyntax = if3(sym == pack_s && consp(alsyntax) &&
+ (car(alsyntax) == struct_s ||
+ car(alsyntax) == union_s),
+ ffi_pack_members(alsyntax, align),
+ alsyntax);
+ val altype = ffi_type_compile(xalsyntax);
+ if (xalsyntax != alsyntax) {
+ return altype;
+ } else {
+ val altype_copy = ffi_type_copy(altype);
+ struct txr_ffi_type *atft = ffi_type_struct(altype_copy);
+ if (al > atft->align || sym == pack_s)
+ atft->align = al;
+ return altype_copy;
+ }
}
} else if (sym == bool_s) {
val type_syntax = cadr(syntax);
@@ -4405,7 +4438,8 @@ val ffi_type_operator_p(val sym)
sym == ptr_out_s_s || sym == buf_s || sym == buf_d_s ||
sym == cptr_s || sym == carray_s || sym == sbit_s ||
sym == ubit_s || sym == bit_s || sym == enum_s ||
- sym == enumed_s || sym == align_s || sym == bool_s);
+ sym == enumed_s || sym == align_s || sym == pack_s ||
+ sym == bool_s);
}
val ffi_type_p(val sym)
@@ -7002,6 +7036,7 @@ void ffi_init(void)
enumed_s = intern(lit("enumed"), user_package);
elemtype_s = intern(lit("elemtype"), user_package);
align_s = intern(lit("align"), user_package);
+ pack_s = intern(lit("pack"), user_package);
bool_s = intern(lit("bool"), user_package);
ffi_type_s = intern(lit("ffi-type"), user_package);
ffi_call_desc_s = intern(lit("ffi-call-desc"), user_package);