cgen: support larger closure parameters (#13040)
parent
897bbb7da5
commit
de711da774
|
@ -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)
|
||||
|
||||
|
|
|
@ -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) + ')
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue