markused: cleanup the generated c code (#25210)

This commit is contained in:
Felipe Pena 2025-09-02 12:48:51 -03:00 committed by GitHub
parent 840e659d08
commit 2e8cc75e5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 62 additions and 28 deletions

View file

@ -596,6 +596,7 @@ fn (t Tree) fn_decl(node ast.FnDecl) &Node {
obj.add_terse('is_variadic', t.bool_node(node.is_variadic)) obj.add_terse('is_variadic', t.bool_node(node.is_variadic))
obj.add('is_anon', t.bool_node(node.is_anon)) obj.add('is_anon', t.bool_node(node.is_anon))
obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn)) obj.add_terse('is_noreturn', t.bool_node(node.is_noreturn))
obj.add_terse('is_weak', t.bool_node(node.is_weak))
obj.add_terse('is_manualfree', t.bool_node(node.is_manualfree)) obj.add_terse('is_manualfree', t.bool_node(node.is_manualfree))
obj.add('is_main', t.bool_node(node.is_main)) obj.add('is_main', t.bool_node(node.is_main))
obj.add('is_test', t.bool_node(node.is_test)) obj.add('is_test', t.bool_node(node.is_test))
@ -840,6 +841,8 @@ fn (t Tree) global_field(node ast.GlobalField) &Node {
obj.add_terse('typ', t.type_node(node.typ)) obj.add_terse('typ', t.type_node(node.typ))
obj.add_terse('has_expr', t.bool_node(node.has_expr)) obj.add_terse('has_expr', t.bool_node(node.has_expr))
obj.add_terse('is_markused', t.bool_node(node.is_markused)) obj.add_terse('is_markused', t.bool_node(node.is_markused))
obj.add_terse('is_weak', t.bool_node(node.is_weak))
obj.add_terse('is_hidden', t.bool_node(node.is_hidden))
obj.add('comments', t.array_node_comment(node.comments)) obj.add('comments', t.array_node_comment(node.comments))
obj.add('pos', t.pos(node.pos)) obj.add('pos', t.pos(node.pos))
obj.add('typ_pos', t.pos(node.typ_pos)) obj.add('typ_pos', t.pos(node.typ_pos))

View file

@ -446,6 +446,7 @@ pub:
module_pos int = -1 // module: module_pos int = -1 // module:
is_union bool is_union bool
is_option bool is_option bool
is_aligned bool
attrs []Attr attrs []Attr
pre_comments []Comment pre_comments []Comment
end_comments []Comment end_comments []Comment
@ -593,6 +594,7 @@ pub:
is_c_extern bool is_c_extern bool
is_variadic bool is_variadic bool
is_anon bool is_anon bool
is_weak bool
is_noreturn bool // true, when @[noreturn] is used on a fn is_noreturn bool // true, when @[noreturn] is used on a fn
is_manualfree bool // true, when @[manualfree] is used on a fn is_manualfree bool // true, when @[manualfree] is used on a fn
is_main bool // true for `fn main()` is_main bool // true for `fn main()`
@ -967,6 +969,8 @@ pub:
is_markused bool // an explicit `@[markused]` tag; the global will NOT be removed by `-skip-unused` is_markused bool // an explicit `@[markused]` tag; the global will NOT be removed by `-skip-unused`
is_volatile bool is_volatile bool
is_exported bool // an explicit `@[export]` tag; the global will NOT be removed by `-skip-unused` is_exported bool // an explicit `@[export]` tag; the global will NOT be removed by `-skip-unused`
is_weak bool
is_hidden bool
pub mut: pub mut:
expr Expr expr Expr
typ Type typ Type

View file

@ -38,6 +38,10 @@ pub mut:
// json bool // json is imported // json bool // json is imported
comptime_calls map[string]bool // resolved name to call on comptime comptime_calls map[string]bool // resolved name to call on comptime
comptime_syms map[Type]bool // resolved syms (generic) comptime_syms map[Type]bool // resolved syms (generic)
//
used_attr_noreturn bool // @[noreturn]
used_attr_hidden bool // @[hidden]
used_attr_weak bool // @[weak]
} }
@[unsafe] @[unsafe]

View file

@ -1001,6 +1001,16 @@ pub fn (mut g Gen) init() {
} else { } else {
g.cheaders.writeln(c_headers) g.cheaders.writeln(c_headers)
} }
if !g.pref.skip_unused || g.table.used_features.used_attr_weak {
g.cheaders.writeln(c_common_weak_attr)
}
if !g.pref.skip_unused || g.table.used_features.used_attr_hidden {
g.cheaders.writeln(c_common_hidden_attr)
}
if !g.pref.skip_unused || g.table.used_features.used_attr_noreturn {
g.cheaders.writeln(c_common_noreturn_attr)
g.cheaders.writeln(c_common_unreachable_attr)
}
if !g.pref.skip_unused || g.table.used_features.used_maps > 0 { if !g.pref.skip_unused || g.table.used_features.used_maps > 0 {
g.cheaders.writeln(c_wyhash_headers) g.cheaders.writeln(c_wyhash_headers)
} }

View file

@ -180,8 +180,6 @@ const c_common_macros = '
#endif #endif
#endif #endif
#define OPTION_CAST(x) (x)
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
#define VV_EXP extern __declspec(dllexport) #define VV_EXP extern __declspec(dllexport)
#define VV_LOC static #define VV_LOC static
@ -220,7 +218,17 @@ const c_common_macros = '
#undef __has_include #undef __has_include
#endif #endif
//likely and unlikely macros
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
#define _likely_(x) __builtin_expect(x,1)
#define _unlikely_(x) __builtin_expect(x,0)
#else
#define _likely_(x) (x)
#define _unlikely_(x) (x)
#endif
'
const c_common_weak_attr = '
#if !defined(VWEAK) #if !defined(VWEAK)
#define VWEAK __attribute__((weak)) #define VWEAK __attribute__((weak))
#ifdef _MSC_VER #ifdef _MSC_VER
@ -232,7 +240,9 @@ const c_common_macros = '
#define VWEAK #define VWEAK
#endif #endif
#endif #endif
'
const c_common_hidden_attr = '
#if !defined(VHIDDEN) #if !defined(VHIDDEN)
#define VHIDDEN __attribute__((visibility("hidden"))) #define VHIDDEN __attribute__((visibility("hidden")))
#ifdef _MSC_VER #ifdef _MSC_VER
@ -244,7 +254,9 @@ const c_common_macros = '
#define VHIDDEN #define VHIDDEN
#endif #endif
#endif #endif
'
const c_common_noreturn_attr = '
#if !defined(VNORETURN) #if !defined(VNORETURN)
#if defined(__TINYC__) #if defined(__TINYC__)
#include <stdnoreturn.h> #include <stdnoreturn.h>
@ -259,7 +271,9 @@ const c_common_macros = '
#define VNORETURN #define VNORETURN
#endif #endif
#endif #endif
'
const c_common_unreachable_attr = '
#if !defined(VUNREACHABLE) #if !defined(VUNREACHABLE)
#if defined(__GNUC__) && !defined(__clang__) #if defined(__GNUC__) && !defined(__clang__)
#define V_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__) #define V_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
@ -276,16 +290,6 @@ const c_common_macros = '
#define VUNREACHABLE() do { } while (0) #define VUNREACHABLE() do { } while (0)
#endif #endif
#endif #endif
//likely and unlikely macros
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
#define _likely_(x) __builtin_expect(x,1)
#define _unlikely_(x) __builtin_expect(x,0)
#else
#define _likely_(x) (x)
#define _unlikely_(x) (x)
#endif
' '
const c_unsigned_comparison_functions = ' const c_unsigned_comparison_functions = '
@ -433,8 +437,6 @@ void v_free(voidptr ptr);
#define _Atomic volatile #define _Atomic volatile
// MSVC cannot parse some things properly // MSVC cannot parse some things properly
#undef OPTION_CAST
#define OPTION_CAST(x)
#undef __NOINLINE #undef __NOINLINE
#undef __IRQHANDLER #undef __IRQHANDLER
#define __NOINLINE __declspec(noinline) #define __NOINLINE __declspec(noinline)
@ -451,9 +453,6 @@ void v_free(voidptr ptr);
#endif #endif
#endif #endif
// g_live_info is used by live.info()
static void* g_live_info = NULL;
#if defined(__MINGW32__) || defined(__MINGW64__) || (defined(_WIN32) && defined(__TINYC__)) #if defined(__MINGW32__) || defined(__MINGW64__) || (defined(_WIN32) && defined(__TINYC__))
#undef PRId64 #undef PRId64
#undef PRIi64 #undef PRIi64
@ -711,5 +710,4 @@ static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k;
#endif #endif
#define _IN_MAP(val, m) map_exists(m, val) #define _IN_MAP(val, m) map_exists(m, val)
' '

View file

@ -437,13 +437,14 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) {
should_init := (!g.pref.use_cache && g.pref.build_mode != .build_module) should_init := (!g.pref.use_cache && g.pref.build_mode != .build_module)
|| (g.pref.build_mode == .build_module && g.module_built == node.mod) || (g.pref.build_mode == .build_module && g.module_built == node.mod)
mut attributes := '' mut attributes := ''
if node.attrs.contains('weak') { first_field := node.fields[0]
if first_field.is_weak {
attributes += 'VWEAK ' attributes += 'VWEAK '
} }
if node.attrs.contains('hidden') { if first_field.is_hidden {
attributes += 'VHIDDEN ' attributes += 'VHIDDEN '
} }
if node.attrs.contains('export') { if first_field.is_exported {
attributes += 'VV_EXP ' attributes += 'VV_EXP '
} }
if attr := node.attrs.find_first('_linker_section') { if attr := node.attrs.find_first('_linker_section') {

View file

@ -532,9 +532,9 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
if g.pref.printfn_list.len > 0 && g.last_fn_c_name in g.pref.printfn_list { if g.pref.printfn_list.len > 0 && g.last_fn_c_name in g.pref.printfn_list {
println(g.out.after(fn_start_pos)) println(g.out.after(fn_start_pos))
} }
weak := if node.is_weak { 'VWEAK ' } else { '' }
for attr in node.attrs { for attr in node.attrs {
if attr.name == 'export' { if attr.name == 'export' {
weak := if node.attrs.any(it.name == 'weak') { 'VWEAK ' } else { '' }
g.writeln('// export alias: ${attr.arg} -> ${name}') g.writeln('// export alias: ${attr.arg} -> ${name}')
g.export_funcs << attr.arg g.export_funcs << attr.arg
export_alias := '${weak}${type_name} ${fn_attrs}${attr.arg}(${arg_str})' export_alias := '${weak}${type_name} ${fn_attrs}${attr.arg}(${arg_str})'

View file

@ -142,6 +142,9 @@ pub fn (mut w Walker) mark_global_as_used(ckey string) {
} }
w.used_globals[ckey] = true w.used_globals[ckey] = true
gfield := w.all_globals[ckey] or { return } gfield := w.all_globals[ckey] or { return }
w.table.used_features.used_attr_weak = w.table.used_features.used_attr_weak || gfield.is_weak
w.table.used_features.used_attr_hidden = w.table.used_features.used_attr_hidden
|| gfield.is_hidden || gfield.is_hidden
w.expr(gfield.expr) w.expr(gfield.expr)
if !gfield.has_expr { if !gfield.has_expr {
w.mark_by_type(gfield.typ) w.mark_by_type(gfield.typ)
@ -355,9 +358,7 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
w.mark_by_type(typ.typ) w.mark_by_type(typ.typ)
} }
w.struct_fields(node.fields) w.struct_fields(node.fields)
if !w.uses_mem_align { w.uses_mem_align = w.uses_mem_align || node.is_aligned
w.uses_mem_align = node.attrs.contains('aligned')
}
} }
ast.DeferStmt { ast.DeferStmt {
w.stmts(node.stmts) w.stmts(node.stmts)
@ -894,6 +895,9 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
w.is_builtin_mod = last_is_builtin_mod w.is_builtin_mod = last_is_builtin_mod
} }
} }
w.table.used_features.used_attr_weak = w.table.used_features.used_attr_weak || node.is_weak
w.table.used_features.used_attr_noreturn = w.table.used_features.used_attr_noreturn
|| node.is_noreturn
if node.language == .c { if node.language == .c {
w.mark_fn_as_used(node.fkey()) w.mark_fn_as_used(node.fkey())
w.mark_fn_ret_and_params(node.return_type, node.params) w.mark_fn_ret_and_params(node.return_type, node.params)
@ -1153,9 +1157,7 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
} }
if decl := w.all_structs[isym.name] { if decl := w.all_structs[isym.name] {
w.struct_fields(decl.fields) w.struct_fields(decl.fields)
if !w.uses_mem_align { w.uses_mem_align = w.uses_mem_align || decl.is_aligned
w.uses_mem_align = decl.attrs.contains('aligned')
}
for iface_typ in decl.implements_types { for iface_typ in decl.implements_types {
w.mark_by_type(iface_typ.typ) w.mark_by_type(iface_typ.typ)
} }

View file

@ -213,6 +213,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
mut is_c2v_variadic := false mut is_c2v_variadic := false
mut is_c_extern := false mut is_c_extern := false
mut is_markused := false mut is_markused := false
mut is_weak := false
mut is_expand_simple_interpolation := false mut is_expand_simple_interpolation := false
mut comments := []ast.Comment{} mut comments := []ast.Comment{}
fn_attrs := p.attrs fn_attrs := p.attrs
@ -254,6 +255,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
'c2v_variadic' { 'c2v_variadic' {
is_c2v_variadic = true is_c2v_variadic = true
} }
'weak' {
is_weak = true
}
'use_new' { 'use_new' {
is_ctor_new = true is_ctor_new = true
} }
@ -706,6 +710,7 @@ run them via `v file.v` instead',
is_unsafe: is_unsafe is_unsafe: is_unsafe
is_must_use: is_must_use is_must_use: is_must_use
is_markused: is_markused is_markused: is_markused
is_weak: is_weak
is_file_translated: p.is_translated is_file_translated: p.is_translated
// //
attrs: fn_attrs attrs: fn_attrs

View file

@ -2599,10 +2599,14 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
mut is_markused := false mut is_markused := false
mut is_exported := false mut is_exported := false
mut is_weak := false
mut is_hidden := false
for ga in attrs { for ga in attrs {
match ga.name { match ga.name {
'export' { is_exported = true } 'export' { is_exported = true }
'markused' { is_markused = true } 'markused' { is_markused = true }
'weak' { is_weak = true }
'hidden' { is_hidden = true }
else {} else {}
} }
} }
@ -2687,6 +2691,8 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
is_markused: is_markused is_markused: is_markused
is_volatile: is_volatile is_volatile: is_volatile
is_exported: is_exported is_exported: is_exported
is_weak: is_weak
is_hidden: is_hidden
} }
fields << field fields << field
if name !in ast.global_reserved_type_names { if name !in ast.global_reserved_type_names {

View file

@ -480,6 +480,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
language: language language: language
is_union: is_union is_union: is_union
is_option: is_option is_option: is_option
is_aligned: attrs.contains('aligned')
attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes attrs: if is_anon { []ast.Attr{} } else { attrs } // anon structs can't have attributes
pre_comments: pre_comments pre_comments: pre_comments
end_comments: end_comments end_comments: end_comments