diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-07-11 06:44:36 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-07-11 06:44:36 -0700 |
commit | 81c97fcb7736ee17d581d6c78af567e2f7d25ca0 (patch) | |
tree | 28dbfe5937cad52ed9f2b2f5cf97d1c5da3f01a3 | |
parent | 46ae35f5b87efa3582aa8564839b30acbeeffe57 (diff) | |
download | txr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.tar.gz txr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.tar.bz2 txr-81c97fcb7736ee17d581d6c78af567e2f7d25ca0.zip |
ffi: two-argument form of sizeof.
If sizeof is given an extra argument (an expression which
evaluates to an object), it can calculate the dynamic size of
the FFI type in relation to representing that object.
* ffi.c (dyn_size): New static function.
(ffi_init): Register sys:dyn-size intrinsic.
* share/txr/stdlib/ffi.tl (sizeof): Support additional
argument, avoiding run-time compilation of the type expression
with the help of load-time.
* txr.1: Update documentation for sizeof macro.
-rw-r--r-- | ffi.c | 8 | ||||
-rw-r--r-- | share/txr/stdlib/ffi.tl | 8 | ||||
-rw-r--r-- | txr.1 | 33 |
3 files changed, 42 insertions, 7 deletions
@@ -5494,6 +5494,13 @@ val fill_obj(val obj, val type, val stream) return tft->in(tft, 1, data, obj, self); } +static val dyn_size(val type, val obj) +{ + val self = lit("sizeof"); + struct txr_ffi_type *tft = ffi_type_struct_checked(self, type); + return num(tft->dynsize(tft, obj, self)); +} + void ffi_init(void) { prot1(&ffi_typedef_hash); @@ -5625,6 +5632,7 @@ void ffi_init(void) reg_fun(intern(lit("put-obj"), user_package), func_n3o(put_obj, 2)); reg_fun(intern(lit("get-obj"), user_package), func_n2o(get_obj, 1)); reg_fun(intern(lit("fill-obj"), user_package), func_n3o(fill_obj, 2)); + reg_fun(intern(lit("dyn-size"), system_package), func_n2(dyn_size)); ffi_typedef_hash = make_hash(nil, nil, nil); ffi_init_types(); ffi_init_extra_types(); diff --git a/share/txr/stdlib/ffi.tl b/share/txr/stdlib/ffi.tl index cf5bd8a1..99c0da72 100644 --- a/share/txr/stdlib/ffi.tl +++ b/share/txr/stdlib/ffi.tl @@ -122,8 +122,12 @@ (defvarl ,var-sym (carray-cptr ,var-ref ,type-sym 1)) (defsymacro ,name (carray-ref ,var-sym 0))))) -(defmacro sizeof (type) - (ffi-size (ffi-type-compile type))) +(defmacro sizeof (type : (obj nil obj-p) :env menv) + (if obj-p + (if (constantp obj menv) + (sys:dyn-size (ffi-type-compile type) obj) + ^(sys:dyn-size (load-time (ffi-type-compile ',type)) ,obj)) + (ffi-size (ffi-type-compile type)))) (defmacro alignof (type) (ffi-alignof (ffi-type-compile type))) @@ -64059,17 +64059,40 @@ as its value. .coNP Macro @ sizeof .synb -.mets (sizeof << type-syntax ) +.mets (sizeof < type-syntax <> [ object-expr ]) .syne .desc The macro .code sizeof calculates the size of the FFI type denoted by +.codn type-syntax . + +The +.meta type-syntax +expression is compiled to a type using +.codn ffi-type-compile . +The +.meta object-expr +expression is evaluated to an object value. + +If .code type-syntax -at macro-expansion time, and produces that -integer value as its expansion, such that there is no -run-time computation. It uses the -.code ffi-sizeof +denotes a variable length type, and the +.meta object-expr +argument is present, then a +.I "dynamic size" is computed: the actual number of bytes required to store +that object value as a foreign representation of the specified variable length +type. + +The +.code sizeof +macro arranges for the size calculation to be carried out at macro-expansion +time, if possible, so that the +.code sizeof +form is replaced by an integer constant. This is possible when the +.meta object-expr +is omitted, or if it is a constant expression according to the +.code constantp function. .coNP Macro @ alignof |