cgen: support larger closure parameters (#13040)

pull/13042/head
spaceface 2022-01-05 15:22:20 +01:00 committed by GitHub
parent 897bbb7da5
commit de711da774
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 1 deletions

View File

@ -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)

View File

@ -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) + ')

View File

@ -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)
}