v.gen.c: support inter-dependent function types (#20638)

This commit is contained in:
Pierre Curto 2024-01-24 17:41:46 +01:00 committed by GitHub
parent d750d1f5a0
commit a09bd7cff3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 70 additions and 5 deletions

View File

@ -1515,11 +1515,7 @@ static inline void __${sym.cname}_pushval(${sym.cname} ch, ${push_arg} val) {
g.write_alias_typesymbol_declaration(sym)
}
}
for sym in g.table.type_symbols {
if sym.kind == .function && sym.name !in c.builtins {
g.write_fn_typesymbol_declaration(sym)
}
}
g.write_sorted_fn_typesymbol_declaration()
// Generating interfaces after all the common types have been defined
// to prevent generating interface struct before definition of field types
for sym in g.table.type_symbols {
@ -6382,6 +6378,63 @@ fn (mut g Gen) sort_globals_consts() {
}
}
// sort functions by dependent arguments and return value
// As functions may depend on one another, make sure they are
// defined in the correct order: add non dependent ones first.
fn (mut g Gen) write_sorted_fn_typesymbol_declaration() {
util.timing_start(@METHOD)
defer {
util.timing_measure(@METHOD)
}
mut syms := []&ast.TypeSymbol{} // functions to be defined
for sym in g.table.type_symbols {
if sym.kind == .function && sym.name !in c.builtins {
syms << sym
}
}
mut pending := []&ast.TypeSymbol{} // functions with a dependency
for {
// Add non dependent functions or functions which
// dependency has been added.
next: for sym in syms {
info := sym.info as ast.FnType
func := info.func
return_sym := g.table.sym(func.return_type)
if return_sym in syms {
pending << sym
continue
}
for param in func.params {
param_sym := g.table.sym(param.typ)
if param_sym in syms {
pending << sym
continue next
}
}
g.write_fn_typesymbol_declaration(sym)
}
if pending.len == 0 {
// All functions were added.
break
}
if syms.len == pending.len {
// Could not add any function: there is a circular
// dependency.
mut deps := []string{}
for sym in pending {
deps << sym.name
}
verror(
'cgen.write_sorted_fn_typesymbol_declaration(): the following functions form a dependency cycle:\n' +
deps.join(','))
}
unsafe {
// Swap the to-be-processed and the dependent functions.
syms, pending = pending, syms[..0]
}
}
}
// sort structs by dependent fields
fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
util.timing_start(@METHOD)

View File

@ -0,0 +1,4 @@
typedef void (*gdi__Function_ptr)();
typedef void (*gdi__Function_ptr2)();
typedef gdi__Function_ptr* (*gdi__Get_proc_address)(i8*);
typedef void (*gdi__Set_proc_address)(gdi__Function_ptr2*);

View File

@ -0,0 +1,8 @@
// vtest vflags: -shared
module gdi
pub type Get_proc_address = fn(&i8) &Function_ptr
pub type Set_proc_address = fn(&Function_ptr2)
pub type Function_ptr = fn ()
pub type Function_ptr2 = fn ()