cgen: sort globals and consts definitions (#14739)
parent
c7a619d16e
commit
cdf4ffc513
|
@ -9,14 +9,16 @@ import v.dotgraph
|
||||||
|
|
||||||
struct DepGraphNode {
|
struct DepGraphNode {
|
||||||
pub mut:
|
pub mut:
|
||||||
name string
|
name string
|
||||||
deps []string
|
value i64
|
||||||
|
deps []string
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DepGraph {
|
struct DepGraph {
|
||||||
pub mut:
|
pub mut:
|
||||||
acyclic bool
|
acyclic bool
|
||||||
nodes []DepGraphNode
|
nodes []DepGraphNode
|
||||||
|
values map[string]i64
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OrderedDepMap {
|
struct OrderedDepMap {
|
||||||
|
@ -43,7 +45,6 @@ pub fn (mut o OrderedDepMap) add(name string, deps []string) {
|
||||||
for dep in deps {
|
for dep in deps {
|
||||||
if dep !in d {
|
if dep !in d {
|
||||||
d << dep
|
d << dep
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.set(name, d)
|
o.set(name, d)
|
||||||
|
@ -95,6 +96,17 @@ pub fn (mut graph DepGraph) add(mod string, deps []string) {
|
||||||
deps: deps.clone()
|
deps: deps.clone()
|
||||||
}
|
}
|
||||||
graph.nodes << new_node
|
graph.nodes << new_node
|
||||||
|
graph.values[mod] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut graph DepGraph) add_with_value(mod string, deps []string, value i64) {
|
||||||
|
new_node := DepGraphNode{
|
||||||
|
name: mod
|
||||||
|
value: value
|
||||||
|
deps: deps.clone()
|
||||||
|
}
|
||||||
|
graph.nodes << new_node
|
||||||
|
graph.values[mod] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (graph &DepGraph) resolve() &DepGraph {
|
pub fn (graph &DepGraph) resolve() &DepGraph {
|
||||||
|
@ -119,14 +131,14 @@ pub fn (graph &DepGraph) resolve() &DepGraph {
|
||||||
mut g := new_dep_graph()
|
mut g := new_dep_graph()
|
||||||
g.acyclic = false
|
g.acyclic = false
|
||||||
for name in node_deps.keys {
|
for name in node_deps.keys {
|
||||||
g.add(name, node_names.get(name))
|
g.add_with_value(name, node_names.get(name), graph.values[name])
|
||||||
}
|
}
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
for name in ready_set {
|
for name in ready_set {
|
||||||
node_deps.delete(name)
|
node_deps.delete(name)
|
||||||
resolved_deps := node_names.get(name)
|
resolved_deps := node_names.get(name)
|
||||||
resolved.add(name, resolved_deps)
|
resolved.add_with_value(name, resolved_deps, graph.values[name])
|
||||||
}
|
}
|
||||||
for name in node_deps.keys {
|
for name in node_deps.keys {
|
||||||
node_deps.apply_diff(name, ready_set)
|
node_deps.apply_diff(name, ready_set)
|
||||||
|
|
|
@ -61,10 +61,6 @@ mut:
|
||||||
hotcode_definitions strings.Builder // -live declarations & functions
|
hotcode_definitions strings.Builder // -live declarations & functions
|
||||||
channel_definitions strings.Builder // channel related code
|
channel_definitions strings.Builder // channel related code
|
||||||
comptime_definitions strings.Builder // custom defines, given by -d/-define flags on the CLI
|
comptime_definitions strings.Builder // custom defines, given by -d/-define flags on the CLI
|
||||||
global_inits map[string]strings.Builder // default initializers for globals (goes in _vinit())
|
|
||||||
global_init strings.Builder // thread local of the above
|
|
||||||
inits map[string]strings.Builder // contents of `void _vinit/2{}`
|
|
||||||
init strings.Builder
|
|
||||||
cleanup strings.Builder
|
cleanup strings.Builder
|
||||||
cleanups map[string]strings.Builder // contents of `void _vcleanup(){}`
|
cleanups map[string]strings.Builder // contents of `void _vcleanup(){}`
|
||||||
gowrappers strings.Builder // all go callsite wrappers
|
gowrappers strings.Builder // all go callsite wrappers
|
||||||
|
@ -79,6 +75,8 @@ mut:
|
||||||
out_results strings.Builder // `result_xxxx` types
|
out_results strings.Builder // `result_xxxx` types
|
||||||
json_forward_decls strings.Builder // json type forward decls
|
json_forward_decls strings.Builder // json type forward decls
|
||||||
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
sql_buf strings.Builder // for writing exprs to args via `sqlite3_bind_int()` etc
|
||||||
|
global_const_defs map[string]GlobalConstDef
|
||||||
|
sorted_global_const_names []string
|
||||||
file &ast.File
|
file &ast.File
|
||||||
unique_file_path_hash u64 // a hash of file.path, used for making auxilary fn generation unique (like `compare_xyz`)
|
unique_file_path_hash u64 // a hash of file.path, used for making auxilary fn generation unique (like `compare_xyz`)
|
||||||
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
fn_decl &ast.FnDecl // pointer to the FnDecl we are currently inside otherwise 0
|
||||||
|
@ -215,6 +213,15 @@ mut:
|
||||||
use_segfault_handler bool = true
|
use_segfault_handler bool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// global or const variable definition string
|
||||||
|
struct GlobalConstDef {
|
||||||
|
mod string // module name
|
||||||
|
def string // definition
|
||||||
|
init string // init later (in _vinit)
|
||||||
|
dep_names []string // the names of all the consts, that this const depends on
|
||||||
|
order int // -1 for simple defines, string literals, anonymous function names, extern declarations etc
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
// println('start cgen2')
|
// println('start cgen2')
|
||||||
mut module_built := ''
|
mut module_built := ''
|
||||||
|
@ -245,7 +252,6 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
comptime_definitions: strings.new_builder(100)
|
comptime_definitions: strings.new_builder(100)
|
||||||
definitions: strings.new_builder(100)
|
definitions: strings.new_builder(100)
|
||||||
gowrappers: strings.new_builder(100)
|
gowrappers: strings.new_builder(100)
|
||||||
stringliterals: strings.new_builder(100)
|
|
||||||
auto_str_funcs: strings.new_builder(100)
|
auto_str_funcs: strings.new_builder(100)
|
||||||
dump_funcs: strings.new_builder(100)
|
dump_funcs: strings.new_builder(100)
|
||||||
pcs_declarations: strings.new_builder(100)
|
pcs_declarations: strings.new_builder(100)
|
||||||
|
@ -266,7 +272,6 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
timers: util.new_timers(should_print: timers_should_print, label: 'global_cgen')
|
timers: util.new_timers(should_print: timers_should_print, label: 'global_cgen')
|
||||||
inner_loop: &ast.EmptyStmt{}
|
inner_loop: &ast.EmptyStmt{}
|
||||||
field_data_type: ast.Type(table.find_type_idx('FieldData'))
|
field_data_type: ast.Type(table.find_type_idx('FieldData'))
|
||||||
init: strings.new_builder(100)
|
|
||||||
is_cc_msvc: pref.ccompiler == 'msvc'
|
is_cc_msvc: pref.ccompiler == 'msvc'
|
||||||
use_segfault_handler: !('no_segfault_handler' in pref.compile_defines || pref.os == .wasm32)
|
use_segfault_handler: !('no_segfault_handler' in pref.compile_defines || pref.os == .wasm32)
|
||||||
}
|
}
|
||||||
|
@ -278,8 +283,6 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
|
|
||||||
global_g.timers.start('cgen init')
|
global_g.timers.start('cgen init')
|
||||||
for mod in global_g.table.modules {
|
for mod in global_g.table.modules {
|
||||||
global_g.inits[mod] = strings.new_builder(200)
|
|
||||||
global_g.global_inits[mod] = strings.new_builder(100)
|
|
||||||
global_g.cleanups[mod] = strings.new_builder(100)
|
global_g.cleanups[mod] = strings.new_builder(100)
|
||||||
}
|
}
|
||||||
global_g.init()
|
global_g.init()
|
||||||
|
@ -315,6 +318,9 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
global_g.force_main_console = global_g.force_main_console || g.force_main_console
|
global_g.force_main_console = global_g.force_main_console || g.force_main_console
|
||||||
|
|
||||||
// merge maps
|
// merge maps
|
||||||
|
for k, v in g.global_const_defs {
|
||||||
|
global_g.global_const_defs[k] = v
|
||||||
|
}
|
||||||
for k, v in g.shareds {
|
for k, v in g.shareds {
|
||||||
global_g.shareds[k] = v
|
global_g.shareds[k] = v
|
||||||
}
|
}
|
||||||
|
@ -342,8 +348,6 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
global_g.sql_buf.write(g.sql_buf) or { panic(err) }
|
global_g.sql_buf.write(g.sql_buf) or { panic(err) }
|
||||||
|
|
||||||
global_g.cleanups[g.file.mod.name].write(g.cleanup) or { panic(err) } // strings.Builder.write never fails; it is like that in the source
|
global_g.cleanups[g.file.mod.name].write(g.cleanup) or { panic(err) } // strings.Builder.write never fails; it is like that in the source
|
||||||
global_g.inits[g.file.mod.name].write(g.init) or { panic(err) }
|
|
||||||
global_g.global_inits[g.file.mod.name].write(g.global_init) or { panic(err) }
|
|
||||||
|
|
||||||
for str_type in g.str_types {
|
for str_type in g.str_types {
|
||||||
global_g.str_types << str_type
|
global_g.str_types << str_type
|
||||||
|
@ -374,10 +378,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
for file in files {
|
for file in files {
|
||||||
global_g.file = file
|
global_g.file = file
|
||||||
global_g.gen_file()
|
global_g.gen_file()
|
||||||
global_g.inits[file.mod.name].drain_builder(mut global_g.init, 100)
|
|
||||||
global_g.cleanups[file.mod.name].drain_builder(mut global_g.cleanup, 100)
|
global_g.cleanups[file.mod.name].drain_builder(mut global_g.cleanup, 100)
|
||||||
global_g.global_inits[file.mod.name].drain_builder(mut global_g.global_init,
|
|
||||||
100)
|
|
||||||
}
|
}
|
||||||
global_g.timers.start('cgen unification')
|
global_g.timers.start('cgen unification')
|
||||||
}
|
}
|
||||||
|
@ -399,6 +400,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
global_g.gen_array_index_methods()
|
global_g.gen_array_index_methods()
|
||||||
global_g.gen_equality_fns()
|
global_g.gen_equality_fns()
|
||||||
global_g.gen_free_methods()
|
global_g.gen_free_methods()
|
||||||
|
global_g.sort_globals_consts()
|
||||||
global_g.timers.show('cgen unification')
|
global_g.timers.show('cgen unification')
|
||||||
|
|
||||||
mut g := global_g
|
mut g := global_g
|
||||||
|
@ -462,6 +464,12 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
b.write_string(g.json_forward_decls.str())
|
b.write_string(g.json_forward_decls.str())
|
||||||
b.writeln('\n// V definitions:')
|
b.writeln('\n// V definitions:')
|
||||||
b.write_string(g.definitions.str())
|
b.write_string(g.definitions.str())
|
||||||
|
b.writeln('\n// V global/const definitions:')
|
||||||
|
for var_name in g.sorted_global_const_names {
|
||||||
|
if var := g.global_const_defs[var_name] {
|
||||||
|
b.writeln(var.def)
|
||||||
|
}
|
||||||
|
}
|
||||||
interface_table := g.interface_table()
|
interface_table := g.interface_table()
|
||||||
if interface_table.len > 0 {
|
if interface_table.len > 0 {
|
||||||
b.writeln('\n// V interface table:')
|
b.writeln('\n// V interface table:')
|
||||||
|
@ -545,7 +553,6 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen {
|
||||||
alias_definitions: strings.new_builder(100)
|
alias_definitions: strings.new_builder(100)
|
||||||
definitions: strings.new_builder(100)
|
definitions: strings.new_builder(100)
|
||||||
gowrappers: strings.new_builder(100)
|
gowrappers: strings.new_builder(100)
|
||||||
stringliterals: strings.new_builder(100)
|
|
||||||
auto_str_funcs: strings.new_builder(100)
|
auto_str_funcs: strings.new_builder(100)
|
||||||
comptime_definitions: strings.new_builder(100)
|
comptime_definitions: strings.new_builder(100)
|
||||||
pcs_declarations: strings.new_builder(100)
|
pcs_declarations: strings.new_builder(100)
|
||||||
|
@ -559,8 +566,6 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen {
|
||||||
json_forward_decls: strings.new_builder(100)
|
json_forward_decls: strings.new_builder(100)
|
||||||
enum_typedefs: strings.new_builder(100)
|
enum_typedefs: strings.new_builder(100)
|
||||||
sql_buf: strings.new_builder(100)
|
sql_buf: strings.new_builder(100)
|
||||||
init: strings.new_builder(100)
|
|
||||||
global_init: strings.new_builder(0)
|
|
||||||
cleanup: strings.new_builder(100)
|
cleanup: strings.new_builder(100)
|
||||||
table: global_g.table
|
table: global_g.table
|
||||||
pref: global_g.pref
|
pref: global_g.pref
|
||||||
|
@ -599,8 +604,6 @@ pub fn (mut g Gen) free_builders() {
|
||||||
g.type_definitions.free()
|
g.type_definitions.free()
|
||||||
g.alias_definitions.free()
|
g.alias_definitions.free()
|
||||||
g.definitions.free()
|
g.definitions.free()
|
||||||
g.global_init.free()
|
|
||||||
g.init.free()
|
|
||||||
g.cleanup.free()
|
g.cleanup.free()
|
||||||
g.gowrappers.free()
|
g.gowrappers.free()
|
||||||
g.stringliterals.free()
|
g.stringliterals.free()
|
||||||
|
@ -618,12 +621,6 @@ pub fn (mut g Gen) free_builders() {
|
||||||
g.json_forward_decls.free()
|
g.json_forward_decls.free()
|
||||||
g.enum_typedefs.free()
|
g.enum_typedefs.free()
|
||||||
g.sql_buf.free()
|
g.sql_buf.free()
|
||||||
for _, mut v in g.global_inits {
|
|
||||||
v.free()
|
|
||||||
}
|
|
||||||
for _, mut v in g.inits {
|
|
||||||
v.free()
|
|
||||||
}
|
|
||||||
for _, mut v in g.cleanups {
|
for _, mut v in g.cleanups {
|
||||||
v.free()
|
v.free()
|
||||||
}
|
}
|
||||||
|
@ -707,14 +704,6 @@ pub fn (mut g Gen) init() {
|
||||||
g.write_sorted_types()
|
g.write_sorted_types()
|
||||||
g.write_multi_return_types()
|
g.write_multi_return_types()
|
||||||
g.definitions.writeln('// end of definitions #endif')
|
g.definitions.writeln('// end of definitions #endif')
|
||||||
//
|
|
||||||
if !g.pref.no_builtin {
|
|
||||||
g.stringliterals.writeln('')
|
|
||||||
g.stringliterals.writeln('// >> string literal consts')
|
|
||||||
if g.pref.build_mode != .build_module {
|
|
||||||
g.stringliterals.writeln('void vinit_string_literals(void){')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if g.pref.compile_defines_all.len > 0 {
|
if g.pref.compile_defines_all.len > 0 {
|
||||||
g.comptime_definitions.writeln('// V compile time defines by -d or -define flags:')
|
g.comptime_definitions.writeln('// V compile time defines by -d or -define flags:')
|
||||||
g.comptime_definitions.writeln('// All custom defines : ' +
|
g.comptime_definitions.writeln('// All custom defines : ' +
|
||||||
|
@ -796,13 +785,6 @@ pub fn (mut g Gen) init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) finish() {
|
pub fn (mut g Gen) finish() {
|
||||||
if !g.pref.no_builtin {
|
|
||||||
if g.pref.build_mode != .build_module {
|
|
||||||
g.stringliterals.writeln('}')
|
|
||||||
}
|
|
||||||
g.stringliterals.writeln('// << string literal consts')
|
|
||||||
g.stringliterals.writeln('')
|
|
||||||
}
|
|
||||||
if g.pref.is_prof && g.pref.build_mode != .build_module {
|
if g.pref.is_prof && g.pref.build_mode != .build_module {
|
||||||
g.gen_vprint_profile_stats()
|
g.gen_vprint_profile_stats()
|
||||||
}
|
}
|
||||||
|
@ -4383,6 +4365,44 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) dependent_var_names(expr ast.Expr) []string {
|
||||||
|
mut vars := []string{}
|
||||||
|
match expr {
|
||||||
|
ast.Ident {
|
||||||
|
if expr.kind in [.global, .constant] {
|
||||||
|
vars << util.no_dots(expr.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.ArrayInit {
|
||||||
|
for elem_expr in expr.exprs {
|
||||||
|
vars << g.dependent_var_names(elem_expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
for field in expr.fields {
|
||||||
|
vars << g.dependent_var_names(field.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.InfixExpr {
|
||||||
|
vars << g.dependent_var_names(expr.left)
|
||||||
|
vars << g.dependent_var_names(expr.right)
|
||||||
|
}
|
||||||
|
ast.PostfixExpr {
|
||||||
|
vars << g.dependent_var_names(expr.expr)
|
||||||
|
}
|
||||||
|
ast.PrefixExpr {
|
||||||
|
vars << g.dependent_var_names(expr.right)
|
||||||
|
}
|
||||||
|
ast.CallExpr {
|
||||||
|
for arg in expr.args {
|
||||||
|
vars << g.dependent_var_names(arg.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
g.inside_const = true
|
g.inside_const = true
|
||||||
defer {
|
defer {
|
||||||
|
@ -4409,21 +4429,23 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
if field.expr.is_fixed {
|
if field.expr.is_fixed {
|
||||||
styp := g.typ(field.expr.typ)
|
styp := g.typ(field.expr.typ)
|
||||||
if g.pref.build_mode != .build_module {
|
val := g.expr_string(field.expr)
|
||||||
val := g.expr_string(field.expr)
|
g.global_const_defs[util.no_dots(field.name)] = GlobalConstDef{
|
||||||
g.definitions.writeln('$styp $const_name = $val; // fixed array const')
|
mod: field.mod
|
||||||
} else {
|
def: '$styp $const_name = $val; // fixed array const'
|
||||||
g.definitions.writeln('$styp $const_name; // fixed array const')
|
dep_names: g.dependent_var_names(field_expr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
|
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
g.definitions.writeln('string $const_name; // a string literal, inited later')
|
val := g.expr_string(field.expr)
|
||||||
if g.pref.build_mode != .build_module {
|
g.global_const_defs[util.no_dots(field.name)] = GlobalConstDef{
|
||||||
val := g.expr_string(field.expr)
|
mod: field.mod
|
||||||
g.stringliterals.writeln('\t$const_name = $val;')
|
def: 'string $const_name; // a string literal, inited later'
|
||||||
|
init: '\t$const_name = $val;'
|
||||||
|
order: -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
|
@ -4450,7 +4472,9 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
use_cache_mode := g.pref.build_mode == .build_module || g.pref.use_cache
|
use_cache_mode := g.pref.build_mode == .build_module || g.pref.use_cache
|
||||||
if !use_cache_mode {
|
if !use_cache_mode {
|
||||||
if ct_value := field.comptime_expr_value() {
|
if ct_value := field.comptime_expr_value() {
|
||||||
if g.const_decl_precomputed(field.mod, name, ct_value, field.typ) {
|
if g.const_decl_precomputed(field.mod, name, field.name, ct_value,
|
||||||
|
field.typ)
|
||||||
|
{
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4458,7 +4482,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
if field.is_simple_define_const() {
|
if field.is_simple_define_const() {
|
||||||
// "Simple" expressions are not going to need multiple statements,
|
// "Simple" expressions are not going to need multiple statements,
|
||||||
// only the ones which are inited later, so it's safe to use expr_string
|
// only the ones which are inited later, so it's safe to use expr_string
|
||||||
g.const_decl_simple_define(field.name, g.expr_string(field_expr))
|
g.const_decl_simple_define(field.mod, field.name, g.expr_string(field_expr))
|
||||||
} else {
|
} else {
|
||||||
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
|
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
|
||||||
}
|
}
|
||||||
|
@ -4467,7 +4491,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.ComptTimeConstValue, typ ast.Type) bool {
|
fn (mut g Gen) const_decl_precomputed(mod string, name string, field_name string, ct_value ast.ComptTimeConstValue, typ ast.Type) bool {
|
||||||
mut styp := g.typ(typ)
|
mut styp := g.typ(typ)
|
||||||
cname := if g.pref.translated && !g.is_builtin_mod { name } else { '_const_$name' }
|
cname := if g.pref.translated && !g.is_builtin_mod { name } else { '_const_$name' }
|
||||||
$if trace_const_precomputed ? {
|
$if trace_const_precomputed ? {
|
||||||
|
@ -4475,13 +4499,13 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.Comp
|
||||||
}
|
}
|
||||||
match ct_value {
|
match ct_value {
|
||||||
i8 {
|
i8 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
i16 {
|
i16 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
int {
|
int {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
i64 {
|
i64 {
|
||||||
if typ == ast.i64_type {
|
if typ == ast.i64_type {
|
||||||
|
@ -4493,32 +4517,32 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.Comp
|
||||||
// with -cstrict. Add checker errors for overflows instead,
|
// with -cstrict. Add checker errors for overflows instead,
|
||||||
// so V can catch them earlier, instead of relying on the
|
// so V can catch them earlier, instead of relying on the
|
||||||
// C compiler for that.
|
// C compiler for that.
|
||||||
g.const_decl_simple_define(name, ct_value.str())
|
g.const_decl_simple_define(mod, name, ct_value.str())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if typ == ast.u64_type {
|
if typ == ast.u64_type {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str() + 'U')
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str() + 'U')
|
||||||
} else {
|
} else {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u8 {
|
u8 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
u16 {
|
u16 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
u32 {
|
u32 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
u64 {
|
u64 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str() + 'U')
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str() + 'U')
|
||||||
}
|
}
|
||||||
f32 {
|
f32 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
f64 {
|
f64 {
|
||||||
g.const_decl_write_precomputed(styp, cname, ct_value.str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, ct_value.str())
|
||||||
}
|
}
|
||||||
rune {
|
rune {
|
||||||
rune_code := u32(ct_value)
|
rune_code := u32(ct_value)
|
||||||
|
@ -4527,9 +4551,9 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.Comp
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
escval := util.smart_quote(u8(rune_code).ascii_str(), false)
|
escval := util.smart_quote(u8(rune_code).ascii_str(), false)
|
||||||
g.const_decl_write_precomputed(styp, cname, "'$escval'")
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, "'$escval'")
|
||||||
} else {
|
} else {
|
||||||
g.const_decl_write_precomputed(styp, cname, u32(ct_value).str())
|
g.const_decl_write_precomputed(mod, styp, cname, field_name, u32(ct_value).str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string {
|
string {
|
||||||
|
@ -4538,8 +4562,12 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.Comp
|
||||||
// TODO: ^ the above for strings, cause:
|
// TODO: ^ the above for strings, cause:
|
||||||
// `error C2099: initializer is not a constant` errors in MSVC,
|
// `error C2099: initializer is not a constant` errors in MSVC,
|
||||||
// so fall back to the delayed initialisation scheme:
|
// so fall back to the delayed initialisation scheme:
|
||||||
g.definitions.writeln('$styp $cname; // str inited later')
|
g.global_const_defs[util.no_dots(field_name)] = GlobalConstDef{
|
||||||
g.init.writeln('\t$cname = _SLIT("$escaped_val");')
|
mod: mod
|
||||||
|
def: '$styp $cname; // str inited later'
|
||||||
|
init: '\t$cname = _SLIT("$escaped_val");'
|
||||||
|
order: -1
|
||||||
|
}
|
||||||
if g.is_autofree {
|
if g.is_autofree {
|
||||||
g.cleanups[mod].writeln('\tstring_free(&$cname);')
|
g.cleanups[mod].writeln('\tstring_free(&$cname);')
|
||||||
}
|
}
|
||||||
|
@ -4551,11 +4579,14 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, ct_value ast.Comp
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) const_decl_write_precomputed(styp string, cname string, ct_value string) {
|
fn (mut g Gen) const_decl_write_precomputed(mod string, styp string, cname string, field_name string, ct_value string) {
|
||||||
g.definitions.writeln('$styp $cname = $ct_value; // precomputed')
|
g.global_const_defs[util.no_dots(field_name)] = GlobalConstDef{
|
||||||
|
mod: mod
|
||||||
|
def: '$styp $cname = $ct_value; // precomputed'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) const_decl_simple_define(name string, val string) {
|
fn (mut g Gen) const_decl_simple_define(mod string, name string, val string) {
|
||||||
// Simple expressions should use a #define
|
// Simple expressions should use a #define
|
||||||
// so that we don't pollute the binary with unnecessary global vars
|
// so that we don't pollute the binary with unnecessary global vars
|
||||||
// Do not do this when building a module, otherwise the consts
|
// Do not do this when building a module, otherwise the consts
|
||||||
|
@ -4571,13 +4602,17 @@ fn (mut g Gen) const_decl_simple_define(name string, val string) {
|
||||||
x = '_const_$x'
|
x = '_const_$x'
|
||||||
}
|
}
|
||||||
if g.pref.translated {
|
if g.pref.translated {
|
||||||
g.definitions.write_string('const int $x = ')
|
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{
|
||||||
|
mod: mod
|
||||||
|
def: 'const int $x = $val;'
|
||||||
|
order: -1
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.definitions.write_string('#define $x ')
|
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{
|
||||||
}
|
mod: mod
|
||||||
g.definitions.writeln(val)
|
def: '#define $x $val'
|
||||||
if g.pref.translated {
|
order: -1
|
||||||
g.definitions.write_string(';')
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4586,22 +4621,27 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ
|
||||||
// (C doesn't allow init expressions that can't be resolved at compile time).
|
// (C doesn't allow init expressions that can't be resolved at compile time).
|
||||||
mut styp := g.typ(typ)
|
mut styp := g.typ(typ)
|
||||||
cname := if g.pref.translated && !g.is_builtin_mod { name } else { '_const_$name' }
|
cname := if g.pref.translated && !g.is_builtin_mod { name } else { '_const_$name' }
|
||||||
g.definitions.writeln('$styp $cname; // inited later')
|
mut init := strings.new_builder(100)
|
||||||
if cname == '_const_os__args' {
|
if cname == '_const_os__args' {
|
||||||
if g.pref.os == .windows {
|
if g.pref.os == .windows {
|
||||||
g.init.writeln('\t_const_os__args = os__init_os_args_wide(___argc, (byteptr*)___argv);')
|
init.writeln('\t_const_os__args = os__init_os_args_wide(___argc, (byteptr*)___argv);')
|
||||||
} else {
|
} else {
|
||||||
g.init.writeln('\t_const_os__args = os__init_os_args(___argc, (byte**)___argv);')
|
init.writeln('\t_const_os__args = os__init_os_args(___argc, (byte**)___argv);')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if unwrap_option {
|
if unwrap_option {
|
||||||
g.init.writeln('{')
|
init.writeln('{')
|
||||||
g.init.writeln(g.expr_string_surround('\t$cname = *($styp*)', expr, '.data;'))
|
init.writeln(g.expr_string_surround('\t$cname = *($styp*)', expr, '.data;'))
|
||||||
g.init.writeln('}')
|
init.writeln('}')
|
||||||
} else {
|
} else {
|
||||||
g.init.writeln(g.expr_string_surround('\t$cname = ', expr, ';'))
|
init.writeln(g.expr_string_surround('\t$cname = ', expr, ';'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{
|
||||||
|
mod: mod
|
||||||
|
def: '$styp $cname; // inited later'
|
||||||
|
init: init.str()
|
||||||
|
}
|
||||||
if g.is_autofree {
|
if g.is_autofree {
|
||||||
sym := g.table.sym(typ)
|
sym := g.table.sym(typ)
|
||||||
if styp.starts_with('Array_') {
|
if styp.starts_with('Array_') {
|
||||||
|
@ -4654,40 +4694,57 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) {
|
||||||
if field.has_expr && mut anon_fn_expr is ast.AnonFn {
|
if field.has_expr && mut anon_fn_expr is ast.AnonFn {
|
||||||
g.gen_anon_fn_decl(mut anon_fn_expr)
|
g.gen_anon_fn_decl(mut anon_fn_expr)
|
||||||
fn_type_name := g.get_anon_fn_type_name(mut anon_fn_expr, field.name)
|
fn_type_name := g.get_anon_fn_type_name(mut anon_fn_expr, field.name)
|
||||||
g.definitions.writeln('$fn_type_name = ${g.table.sym(field.typ).name}; // global2')
|
g.global_const_defs[util.no_dots(fn_type_name)] = GlobalConstDef{
|
||||||
|
mod: node.mod
|
||||||
|
def: '$fn_type_name = ${g.table.sym(field.typ).name}; // global2'
|
||||||
|
order: -1
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
mut def_builder := strings.new_builder(100)
|
||||||
|
mut init := ''
|
||||||
extern := if cextern { 'extern ' } else { '' }
|
extern := if cextern { 'extern ' } else { '' }
|
||||||
modifier := if field.is_volatile { ' volatile ' } else { '' }
|
modifier := if field.is_volatile { ' volatile ' } else { '' }
|
||||||
g.definitions.write_string('$extern$visibility_kw$modifier$styp $attributes $field.name')
|
def_builder.write_string('$extern$visibility_kw$modifier$styp $attributes $field.name')
|
||||||
if cextern {
|
if cextern {
|
||||||
g.definitions.writeln('; // global5')
|
def_builder.writeln('; // global5')
|
||||||
|
g.global_const_defs[util.no_dots(field.name)] = GlobalConstDef{
|
||||||
|
mod: node.mod
|
||||||
|
def: def_builder.str()
|
||||||
|
order: -1
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if field.has_expr || cinit {
|
if field.has_expr || cinit {
|
||||||
if g.pref.translated {
|
if g.pref.translated {
|
||||||
g.definitions.write_string(' = ${g.expr_string(field.expr)}')
|
def_builder.write_string(' = ${g.expr_string(field.expr)}')
|
||||||
} else if (field.expr.is_literal() && should_init) || cinit
|
} else if (field.expr.is_literal() && should_init) || cinit
|
||||||
|| (field.expr is ast.ArrayInit && (field.expr as ast.ArrayInit).is_fixed) {
|
|| (field.expr is ast.ArrayInit && (field.expr as ast.ArrayInit).is_fixed) {
|
||||||
// Simple literals can be initialized right away in global scope in C.
|
// Simple literals can be initialized right away in global scope in C.
|
||||||
// e.g. `int myglobal = 10;`
|
// e.g. `int myglobal = 10;`
|
||||||
g.definitions.write_string(' = ${g.expr_string(field.expr)}')
|
def_builder.write_string(' = ${g.expr_string(field.expr)}')
|
||||||
} else {
|
} else {
|
||||||
// More complex expressions need to be moved to `_vinit()`
|
// More complex expressions need to be moved to `_vinit()`
|
||||||
// e.g. `__global ( mygblobal = 'hello ' + world' )`
|
// e.g. `__global ( mygblobal = 'hello ' + world' )`
|
||||||
g.global_init.writeln('\t$field.name = ${g.expr_string(field.expr)}; // 3global')
|
init = '\t$field.name = ${g.expr_string(field.expr)}; // 3global'
|
||||||
}
|
}
|
||||||
} else if !g.pref.translated { // don't zero globals from C code
|
} else if !g.pref.translated { // don't zero globals from C code
|
||||||
default_initializer := g.type_default(field.typ)
|
default_initializer := g.type_default(field.typ)
|
||||||
if default_initializer == '{0}' && should_init {
|
if default_initializer == '{0}' && should_init {
|
||||||
g.definitions.write_string(' = {0}')
|
def_builder.write_string(' = {0}')
|
||||||
} else {
|
} else {
|
||||||
if field.name !in ['as_cast_type_indexes', 'g_memory_block', 'global_allocator'] {
|
if field.name !in ['as_cast_type_indexes', 'g_memory_block', 'global_allocator'] {
|
||||||
g.global_init.writeln('\t$field.name = *($styp*)&(($styp[]){${g.type_default(field.typ)}}[0]); // global')
|
init = '\t$field.name = *($styp*)&(($styp[]){${g.type_default(field.typ)}}[0]); // global'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.definitions.writeln('; // global4')
|
def_builder.writeln('; // global4')
|
||||||
|
g.global_const_defs[util.no_dots(field.name)] = GlobalConstDef{
|
||||||
|
mod: node.mod
|
||||||
|
def: def_builder.str()
|
||||||
|
init: init
|
||||||
|
dep_names: g.dependent_var_names(field.expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4769,17 +4826,21 @@ fn (mut g Gen) write_init_function() {
|
||||||
// calling module init functions too, just in case they do fail...
|
// calling module init functions too, just in case they do fail...
|
||||||
g.write('\tas_cast_type_indexes = ')
|
g.write('\tas_cast_type_indexes = ')
|
||||||
g.writeln(g.as_cast_name_table())
|
g.writeln(g.as_cast_name_table())
|
||||||
//
|
|
||||||
g.writeln('\tbuiltin_init();')
|
g.writeln('\tbuiltin_init();')
|
||||||
g.writeln('\tvinit_string_literals();')
|
|
||||||
//
|
|
||||||
if g.nr_closures > 0 {
|
if g.nr_closures > 0 {
|
||||||
g.writeln('\t_closure_mtx_init();')
|
g.writeln('\t_closure_mtx_init();')
|
||||||
}
|
}
|
||||||
for mod_name in g.table.modules {
|
for mod_name in g.table.modules {
|
||||||
g.writeln('\t{ // Initializations for module $mod_name :')
|
g.writeln('\t{ // Initializations for module $mod_name :')
|
||||||
g.write(g.inits[mod_name].str())
|
// write globals and consts init later
|
||||||
g.write(g.global_inits[mod_name].str())
|
for var_name in g.sorted_global_const_names {
|
||||||
|
if var := g.global_const_defs[var_name] {
|
||||||
|
if var.mod == mod_name && var.init.len > 0 {
|
||||||
|
g.writeln(var.init)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
init_fn_name := '${mod_name}.init'
|
init_fn_name := '${mod_name}.init'
|
||||||
if initfn := g.table.find_fn(init_fn_name) {
|
if initfn := g.table.find_fn(init_fn_name) {
|
||||||
if initfn.return_type == ast.void_type && initfn.params.len == 0 {
|
if initfn.return_type == ast.void_type && initfn.params.len == 0 {
|
||||||
|
@ -5059,6 +5120,22 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) sort_globals_consts() {
|
||||||
|
g.sorted_global_const_names.clear()
|
||||||
|
mut dep_graph := depgraph.new_dep_graph()
|
||||||
|
for var_name, var_info in g.global_const_defs {
|
||||||
|
dep_graph.add_with_value(var_name, var_info.dep_names, var_info.order)
|
||||||
|
}
|
||||||
|
dep_graph_sorted := dep_graph.resolve()
|
||||||
|
for order in [-1, 0] {
|
||||||
|
for node in dep_graph_sorted.nodes {
|
||||||
|
if node.value == order {
|
||||||
|
g.sorted_global_const_names << node.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// sort structs by dependant fields
|
// sort structs by dependant fields
|
||||||
fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
|
fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
|
|
|
@ -152,7 +152,7 @@ $enc_fn_dec {
|
||||||
dec.writeln('\topt_ok2(&res, ($option_name*)&ret, sizeof(res));')
|
dec.writeln('\topt_ok2(&res, ($option_name*)&ret, sizeof(res));')
|
||||||
dec.writeln('\treturn ret;\n}')
|
dec.writeln('\treturn ret;\n}')
|
||||||
enc.writeln('\treturn o;\n}')
|
enc.writeln('\treturn o;\n}')
|
||||||
g.definitions.writeln(dec.str())
|
g.gowrappers.writeln(dec.str())
|
||||||
g.gowrappers.writeln(enc.str())
|
g.gowrappers.writeln(enc.str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue