Skip to content

Commit 1000ada

Browse files
authored
cgen,parser,markused: add export const support (fix #25300) (#25303)
1 parent a2b4f08 commit 1000ada

File tree

7 files changed

+55
-79
lines changed

7 files changed

+55
-79
lines changed

vlib/v/ast/ast.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ pub:
403403
name string
404404
is_pub bool
405405
is_markused bool // an explicit `@[markused]` tag; the const will NOT be removed by `-skip-unused`, no matter what
406+
is_exported bool // an explicit `@[export]` tag; the const will NOT be removed by `-skip-unused`, no matter what
406407
pos token.Pos
407408
attrs []Attr // same value as `attrs` of the ConstDecl to which it belongs
408409
is_virtual_c bool // `const C.MY_CONST u8`

vlib/v/gen/c/assign.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn (mut g Gen) expr_with_opt_or_block(expr ast.Expr, expr_typ ast.Type, var_expr
1919
}
2020
g.writeln(';')
2121
expr_var := if expr is ast.Ident && expr.kind == .constant {
22-
g.get_const_name(expr)
22+
g.c_const_name(expr.name)
2323
} else if expr is ast.Ident && expr.is_auto_heap() {
2424
'(*${expr.name})'
2525
} else {

vlib/v/gen/c/cgen.v

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5260,19 +5260,6 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
52605260
}
52615261
}
52625262

5263-
fn (mut g Gen) get_const_name(node ast.Ident) string {
5264-
if g.pref.translated && !g.is_builtin_mod
5265-
&& !util.module_is_builtin(node.name.all_before_last('.')) {
5266-
mut x := util.no_dots(node.name)
5267-
if x.starts_with('main__') {
5268-
x = x['main__'.len..]
5269-
}
5270-
return x
5271-
} else {
5272-
return '_const_' + g.get_ternary_name(c_name(node.name))
5273-
}
5274-
}
5275-
52765263
fn (mut g Gen) ident(node ast.Ident) {
52775264
prevent_sum_type_unwrapping_once := g.prevent_sum_type_unwrapping_once
52785265
g.prevent_sum_type_unwrapping_once = false
@@ -5294,28 +5281,16 @@ fn (mut g Gen) ident(node ast.Ident) {
52945281
}
52955282
}
52965283
if node.kind == .constant {
5297-
if g.pref.translated && !g.is_builtin_mod
5298-
&& !util.module_is_builtin(node.name.all_before_last('.')) {
5299-
// Don't prepend "_const" to translated C consts,
5300-
// but only in user code, continue prepending "_const" to builtin consts.
5301-
mut x := util.no_dots(node.name)
5302-
if x.starts_with('main__') {
5303-
x = x['main__'.len..]
5304-
}
5305-
g.write(x)
5306-
return
5307-
} else {
5308-
if g.inside_opt_or_res && node.or_expr.kind != .absent && node.obj.typ.has_flag(.option) {
5309-
styp := g.base_type(node.obj.typ)
5310-
g.write('(*(${styp}*)')
5284+
if g.inside_opt_or_res && node.or_expr.kind != .absent && node.obj.typ.has_flag(.option) {
5285+
styp := g.base_type(node.obj.typ)
5286+
g.write('(*(${styp}*)')
53115287

5312-
defer {
5313-
g.write('.data)')
5314-
}
5288+
defer {
5289+
g.write('.data)')
53155290
}
5316-
// TODO: globals hack
5317-
g.write('_const_')
53185291
}
5292+
g.write(g.c_const_name(node.name))
5293+
return
53195294
}
53205295
mut is_auto_heap := node.is_auto_heap()
53215296
mut is_option := false

vlib/v/gen/c/consts_and_globals.v

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
3333
}
3434
}
3535
name := c_name(field.name)
36-
mut const_name := '_const_' + name
37-
if g.pref.translated && !g.is_builtin_mod
38-
&& !util.module_is_builtin(field.name.all_before_last('.')) {
39-
if name.starts_with('main__') {
40-
const_name = name.all_after_first('main__')
41-
}
42-
}
43-
if !g.is_builtin_mod {
44-
if cattr := node.attrs.find_first('export') {
45-
const_name = cattr.arg
46-
}
47-
}
36+
const_name := g.c_const_name(field.name)
4837
field_expr := field.expr
4938
match field.expr {
5039
ast.ArrayInit {
@@ -63,10 +52,11 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
6352
} else if field.expr.is_fixed && !field.expr.has_index
6453
&& ((g.is_cc_msvc && field.expr.elem_type == ast.string_type)
6554
|| !elems_are_const) {
66-
g.const_decl_init_later_msvc_string_fixed_array(field.mod, name, field.expr,
67-
field.typ)
55+
g.const_decl_init_later_msvc_string_fixed_array(field.mod, name, const_name,
56+
field.expr, field.typ)
6857
} else {
69-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
58+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
59+
false)
7060
}
7161
}
7262
ast.StringLiteral {
@@ -85,10 +75,12 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
8575
old_inside_const_opt_or_res := g.inside_const_opt_or_res
8676
g.inside_const_opt_or_res = true
8777
unwrap_opt_res := field.expr.or_block.kind != .absent
88-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, unwrap_opt_res)
78+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
79+
unwrap_opt_res)
8980
g.inside_const_opt_or_res = old_inside_const_opt_or_res
9081
} else {
91-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, false)
82+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
83+
false)
9284
}
9385
}
9486
else {
@@ -105,8 +97,8 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
10597
use_cache_mode := g.pref.build_mode == .build_module || g.pref.use_cache
10698
if !use_cache_mode {
10799
if ct_value := field.comptime_expr_value() {
108-
if g.const_decl_precomputed(field.mod, name, field.name, ct_value,
109-
field.typ)
100+
if g.const_decl_precomputed(field.mod, name, const_name, field.name,
101+
ct_value, field.typ)
110102
{
111103
continue
112104
}
@@ -115,7 +107,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
115107
if field.is_simple_define_const() {
116108
// "Simple" expressions are not going to need multiple statements,
117109
// only the ones which are inited later, so it's safe to use expr_string
118-
g.const_decl_simple_define(field.mod, field.name, g.expr_string(field_expr))
110+
g.const_decl_simple_define(field.mod, field.name, const_name, g.expr_string(field_expr))
119111
} else if field.expr is ast.CastExpr {
120112
if field.expr.expr is ast.ArrayInit {
121113
if field.expr.expr.is_fixed && g.pref.build_mode != .build_module {
@@ -131,27 +123,29 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
131123
}
132124
should_surround := field.expr.expr is ast.CallExpr
133125
&& field.expr.expr.or_block.kind != .absent
134-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, should_surround)
126+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
127+
should_surround)
135128
} else if field.expr is ast.InfixExpr {
136129
mut has_unwrap_opt_res := false
137130
if field.expr.left is ast.CallExpr {
138131
has_unwrap_opt_res = field.expr.left.or_block.kind != .absent
139132
} else if field.expr.right is ast.CallExpr {
140133
has_unwrap_opt_res = field.expr.right.or_block.kind != .absent
141134
}
142-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, has_unwrap_opt_res)
135+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
136+
has_unwrap_opt_res)
143137
} else {
144-
g.const_decl_init_later(field.mod, name, field.expr, field.typ, true)
138+
g.const_decl_init_later(field.mod, name, const_name, field.expr, field.typ,
139+
true)
145140
}
146141
}
147142
}
148143
}
149144
}
150145

151-
fn (mut g Gen) const_decl_precomputed(mod string, name string, field_name string, ct_value ast.ComptTimeConstValue,
146+
fn (mut g Gen) const_decl_precomputed(mod string, name string, cname string, field_name string, ct_value ast.ComptTimeConstValue,
152147
typ ast.Type) bool {
153148
mut styp := g.styp(typ)
154-
cname := if g.pref.translated && !g.is_builtin_mod { name } else { '_const_${name}' }
155149
$if trace_const_precomputed ? {
156150
eprintln('> styp: ${styp} | cname: ${cname} | ct_value: ${ct_value} | ${ct_value.type_name()}')
157151
}
@@ -179,7 +173,7 @@ fn (mut g Gen) const_decl_precomputed(mod string, name string, field_name string
179173
// with -cstrict. Add checker errors for overflows instead,
180174
// so V can catch them earlier, instead of relying on the
181175
// C compiler for that.
182-
g.const_decl_simple_define(mod, name, ct_value.str())
176+
g.const_decl_simple_define(mod, name, cname, ct_value.str())
183177
return true
184178
}
185179
if typ == ast.u64_type {
@@ -274,48 +268,52 @@ fn (mut g Gen) const_decl_write_precomputed(mod string, styp string, cname strin
274268
}
275269
}
276270

277-
fn (mut g Gen) const_decl_simple_define(mod string, name string, val string) {
271+
fn (mut g Gen) const_decl_simple_define(mod string, name string, cname string, val string) {
278272
// Simple expressions should use a #define
279273
// so that we don't pollute the binary with unnecessary global vars
280274
// Do not do this when building a module, otherwise the consts
281275
// will not be accessible.
282-
mut x := util.no_dots(name)
283-
if g.pref.translated && !g.is_builtin_mod && !util.module_is_builtin(name.all_before_last('.')) {
284-
// Don't prepend "_const" to translated C consts,
285-
// but only in user code, continue prepending "_const" to builtin consts.
286-
if x.starts_with('main__') {
287-
x = x['main__'.len..]
288-
}
289-
} else {
290-
x = '_const_${x}'
291-
}
292276
if g.pref.translated {
293277
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{
294278
mod: mod
295-
def: 'const ${ast.int_type_name} ${x} = ${val};'
279+
def: 'const ${ast.int_type_name} ${cname} = ${val};'
296280
order: -1
297281
}
298282
} else {
299283
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{
300284
mod: mod
301-
def: '#define ${x} ${val}'
285+
def: '#define ${cname} ${val}'
302286
order: -1
303287
}
304288
}
305289
}
306290

307291
fn (mut g Gen) c_const_name(name string) string {
308-
return if g.pref.translated && !g.is_builtin_mod { name } else { '_const_${name}' }
292+
if name in g.table.export_names {
293+
// `@[export] name
294+
return g.table.export_names[name]
295+
}
296+
mut const_name := util.no_dots(name)
297+
if g.pref.translated && !g.is_builtin_mod && !util.module_is_builtin(name.all_before_last('.')) {
298+
if name.starts_with('main.') {
299+
const_name = util.no_dots(name.all_after_first('main.'))
300+
}
301+
}
302+
303+
return if g.pref.translated && !g.is_builtin_mod {
304+
const_name
305+
} else {
306+
'_const_' + g.get_ternary_name(c_name(name))
307+
}
309308
}
310309

311-
fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ ast.Type, surround_cbr bool) {
310+
fn (mut g Gen) const_decl_init_later(mod string, name string, cname string, expr ast.Expr, typ ast.Type, surround_cbr bool) {
312311
if name.starts_with('C__') {
313312
return
314313
}
315314
// Initialize more complex consts in `void _vinit/2{}`
316315
// (C doesn't allow init expressions that can't be resolved at compile time).
317316
mut styp := g.styp(typ)
318-
cname := g.c_const_name(name)
319317
mut init := strings.new_builder(100)
320318

321319
if surround_cbr {
@@ -372,10 +370,9 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ
372370
}
373371
}
374372

375-
fn (mut g Gen) const_decl_init_later_msvc_string_fixed_array(mod string, name string, expr ast.ArrayInit,
373+
fn (mut g Gen) const_decl_init_later_msvc_string_fixed_array(mod string, name string, cname string, expr ast.ArrayInit,
376374
typ ast.Type) {
377375
mut styp := g.styp(typ)
378-
cname := g.c_const_name(name)
379376
mut init := strings.new_builder(100)
380377
for i, elem_expr in expr.exprs {
381378
if elem_expr is ast.ArrayInit && elem_expr.is_fixed {

vlib/v/gen/c/fn.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2056,7 +2056,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
20562056
}
20572057
}
20582058
if node.is_fn_a_const {
2059-
name = g.c_const_name(node.const_name.replace('.', '__'))
2059+
name = g.c_const_name(node.const_name)
20602060
}
20612061
// TODO2
20622062
// cgen shouldn't modify ast nodes, this should be moved

vlib/v/markused/walker.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
203203

204204
pub fn (mut w Walker) mark_markused_consts() {
205205
for ckey, mut constfield in w.all_consts {
206-
if constfield.is_markused {
206+
if constfield.is_markused || constfield.is_exported {
207207
$if trace_skip_unused_markused_consts ? {
208208
println('>>>> walking markused const: ${ckey}')
209209
}

vlib/v/parser/parser.v

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,9 +2446,11 @@ fn (mut p Parser) const_decl() ast.ConstDecl {
24462446
p.attrs = []
24472447
}
24482448
mut is_markused := false
2449+
mut is_exported := false
24492450
for ga in attrs {
24502451
match ga.name {
24512452
'markused' { is_markused = true }
2453+
'export' { is_exported = true }
24522454
else {}
24532455
}
24542456
}
@@ -2538,6 +2540,7 @@ fn (mut p Parser) const_decl() ast.ConstDecl {
25382540
comments: comments
25392541
end_comments: end_comments
25402542
is_markused: is_markused
2543+
is_exported: is_exported
25412544
is_virtual_c: is_virtual_c_const
25422545
}
25432546
if is_virtual_c_const {

0 commit comments

Comments
 (0)