From de711da7741d292b7b76890a0f22945dd5aae1f3 Mon Sep 17 00:00:00 2001 From: spaceface Date: Wed, 5 Jan 2022 15:22:20 +0100 Subject: [PATCH] cgen: support larger closure parameters (#13040) --- vlib/v/gen/c/cheaders.v | 2 ++ vlib/v/gen/c/fn.v | 2 +- vlib/v/tests/closure_test.v | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index 71ede72787c704..25a5a9d306b2aa 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -330,6 +330,8 @@ const c_common_macros = ' // returns the number of CPU registers that TYPE takes up #define _REG_WIDTH(T) (((sizeof(T) + sizeof(void*) - 1) & ~(sizeof(void*) - 1)) / sizeof(void*)) +// parameters of size <= 2 registers are spilled across those two registers; larger types are passed as one pointer to some stack location +#define _REG_WIDTH_BOUNDED(T) (_REG_WIDTH(T) <= 2 ? _REG_WIDTH(T) : 1) #define OPTION_CAST(x) (x) diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index f24889bc0fb199..1432e966a8fc7e 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -467,7 +467,7 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) { mut size_sb := strings.new_builder(node.decl.params.len * 50) for param in node.decl.params { - size_sb.write_string('_REG_WIDTH(${g.typ(param.typ)}) + ') + size_sb.write_string('_REG_WIDTH_BOUNDED(${g.typ(param.typ)}) + ') } if g.pref.arch == .amd64 && node.decl.return_type != ast.void_type { size_sb.write_string('(_REG_WIDTH(${g.typ(node.decl.return_type)}) > 2) + ') diff --git a/vlib/v/tests/closure_test.v b/vlib/v/tests/closure_test.v index f58e94e85d9c0a..299fca39dcf558 100644 --- a/vlib/v/tests/closure_test.v +++ b/vlib/v/tests/closure_test.v @@ -168,3 +168,33 @@ fn test_closures_with_ifstmt() { assert f(0) == 1 assert g() == 1 } + +struct Command { + a int = 1234 + b int = 2345 + c int = 3456 + d int = 4567 + e int = 5678 +} + +struct App {} + +fn main() { + mut app := &App{} + eprintln('app ptr: ${u64(app)}') + f := fn [mut app] (cmd Command) u64 { + p := u64(app) + println('>> p: $p') + println('>> cmd: $cmd') + assert cmd.a == 1234 + assert cmd.b == 2345 + assert cmd.c == 3456 + assert cmd.d == 4567 + assert cmd.e == 5678 + return p + } + cmd := Command{} + res := f(cmd) + println('> res: $res | sizeof Command: ${sizeof(Command)}') + assert res == u64(app) +}