summaryrefslogtreecommitdiff
path: root/lib9p/protogen
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/protogen')
-rw-r--r--lib9p/protogen/c9util.py2
-rw-r--r--lib9p/protogen/c_marshal.py9
-rw-r--r--lib9p/protogen/c_unmarshal.py14
-rw-r--r--lib9p/protogen/h.py14
4 files changed, 36 insertions, 3 deletions
diff --git a/lib9p/protogen/c9util.py b/lib9p/protogen/c9util.py
index e7ad999..10d1c8c 100644
--- a/lib9p/protogen/c9util.py
+++ b/lib9p/protogen/c9util.py
@@ -76,6 +76,8 @@ def typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str:
match typ:
case idl.Primitive():
if typ.value == 1 and parent and parent.cnt: # SPECIAL (string)
+ if parent.membname == "data": # SPECIAL (zerocopy)
+ return f"struct {ident('_iovec')}"
return "[[gnu::nonstring]] char"
return f"uint{typ.value*8}_t"
case idl.Number():
diff --git a/lib9p/protogen/c_marshal.py b/lib9p/protogen/c_marshal.py
index 74b64f5..87ba50b 100644
--- a/lib9p/protogen/c_marshal.py
+++ b/lib9p/protogen/c_marshal.py
@@ -318,7 +318,14 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str:
if path.root.typname == "stat": # SPECIAL (stat)
ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES(ctx, {path.c_str('val->')[:-3]}, {cnt_path.c_str('val->')});\n"
else:
- ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}, {cnt_path.c_str('val->')});\n"
+ if (
+ c9util.typename(child.typ, child)
+ == f"struct {c9util.ident("_iovec")}"
+ ):
+ ret += f"{'\t'*indent_lvl()}for (int iov_i = 0; iov_i < {path.c_str('val->')[:-3]}->iovcnt; iov_i++)\n"
+ ret += f"{'\t'*(indent_lvl()+1)}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}->iov[iov_i].iov_base, {path.c_str('val->')[:-3]}->iov[iov_i].iov_len);\n"
+ else:
+ ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}, {cnt_path.c_str('val->')});\n"
return idlutil.WalkCmd.KEEP_GOING, pop
loopvar = chr(ord("i") + loopdepth - 1)
ret += f"{'\t'*indent_lvl()}for ({c9util.typename(child.cnt.typ)} {loopvar} = 0; {loopvar} < {cnt_path.c_str('val->')}; {loopvar}++) {{\n"
diff --git a/lib9p/protogen/c_unmarshal.py b/lib9p/protogen/c_unmarshal.py
index 018d750..f14fb55 100644
--- a/lib9p/protogen/c_unmarshal.py
+++ b/lib9p/protogen/c_unmarshal.py
@@ -95,7 +95,19 @@ def gen_c_unmarshal(versions: set[str], typs: list[idl.UserType]) -> str:
if child.cnt:
cnt_path = path.parent().add(child.cnt)
if child.typ.static_size == 1: # SPECIAL (zerocopy)
- ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_path.c_str('out->')});\n"
+ if (
+ c9util.typename(child.typ, child)
+ == f"struct {c9util.ident('_iovec')}"
+ ): # SPECIAL(zerocopy)
+ ret += (
+ f"{'\t'*indent_lvl()}out->{child.membname}.iov = ctx->extra;\n"
+ )
+ ret += f"{'\t'*indent_lvl()}ctx->extra += sizeof(out->{child.membname}.iov[0]);\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_base = &ctx->net_bytes[ctx->net_offset];\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_len = out->{child.cnt.membname};\n"
+ ret += f"{'\t'*indent_lvl()}out->{child.membname}.iovcnt = 1;\n"
+ else:
+ ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_path.c_str('out->')});\n"
return idlutil.WalkCmd.KEEP_GOING, pop
ret += f"{'\t'*indent_lvl()}{path.c_str('out->')[:-3]} = extra;\n"
ret += f"{'\t'*indent_lvl()}extra += sizeof({path.c_str('out->')[:-3]}[0]) * {cnt_path.c_str('out->')};\n"
diff --git a/lib9p/protogen/h.py b/lib9p/protogen/h.py
index 7785ca1..3e743e9 100644
--- a/lib9p/protogen/h.py
+++ b/lib9p/protogen/h.py
@@ -166,6 +166,11 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str:
#include <stdint.h> /* for uint{{n}}_t types */
#include <libhw/generic/net.h> /* for struct iovec */
+
+struct {c9util.ident('_iovec_list')} {{
+\tstruct iovec *iov;
+\tint iovcnt;
+}};
"""
id2typ: dict[int, idl.Message] = {}
@@ -224,6 +229,7 @@ enum {c9util.ident('version')} {{
ret += """
/* payload types **************************************************************/
+
"""
def per_version_comment(
@@ -357,7 +363,13 @@ enum {c9util.ident('version')} {{
if member.val:
continue
ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions))
- ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n"
+ ptr = bool(member.cnt)
+ if (
+ c9util.typename(member.typ, member)
+ == f"struct {c9util.ident('_iovec')}"
+ ): # SPECIAL (zerocopy)
+ ptr = False
+ ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if ptr else ' '}{member.membname};\n"
ret += cutil.ifdef_pop(1)
ret += "};\n"
del typ