Skip to content

Commit e983d75

Browse files
authored
markused,builtin,strconv,vlib: reduce generated C sizes for compilers != tcc, for short programs, by simplifying the generation of backtraces, and reducing string interpolations in panics (#23380)
1 parent 738f847 commit e983d75

31 files changed

+278
-191
lines changed

vlib/builtin/array.v

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ fn (mut a array) ensure_cap(required int) {
194194
return
195195
}
196196
if a.flags.has(.nogrow) {
197-
panic('array.ensure_cap: array with the flag `.nogrow` cannot grow in size, array required new size: ${required}')
197+
panic_n('array.ensure_cap: array with the flag `.nogrow` cannot grow in size, array required new size:',
198+
required)
198199
}
199200
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
200201
for required > cap {
@@ -205,7 +206,8 @@ fn (mut a array) ensure_cap(required int) {
205206
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
206207
cap = max_int
207208
} else {
208-
panic('array.ensure_cap: array needs to grow to cap = ${cap}, which is > 2^31')
209+
panic_n('array.ensure_cap: array needs to grow to cap (which is > 2^31):',
210+
cap)
209211
}
210212
}
211213
new_size := u64(cap) * u64(a.element_size)
@@ -240,7 +242,7 @@ pub fn (a array) repeat(count int) array {
240242
@[direct_array_access; unsafe]
241243
pub fn (a array) repeat_to_depth(count int, depth int) array {
242244
if count < 0 {
243-
panic('array.repeat: count is negative: ${count}')
245+
panic_n('array.repeat: count is negative:', count)
244246
}
245247
mut size := u64(count) * u64(a.len) * u64(a.element_size)
246248
if size == 0 {
@@ -293,7 +295,7 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
293295
// ```
294296
pub fn (mut a array) insert(i int, val voidptr) {
295297
if i < 0 || i > a.len {
296-
panic('array.insert: index out of range (i == ${i}, a.len == ${a.len})')
298+
panic_n2('array.insert: index out of range (i,a.len):', i, a.len)
297299
}
298300
if a.len == max_int {
299301
panic('array.insert: a.len reached max_int')
@@ -313,11 +315,11 @@ pub fn (mut a array) insert(i int, val voidptr) {
313315
@[unsafe]
314316
fn (mut a array) insert_many(i int, val voidptr, size int) {
315317
if i < 0 || i > a.len {
316-
panic('array.insert_many: index out of range (i == ${i}, a.len == ${a.len})')
318+
panic_n2('array.insert_many: index out of range (i,a.len):', i, a.len)
317319
}
318320
new_len := i64(a.len) + i64(size)
319321
if new_len > max_int {
320-
panic('array.insert_many: a.len = ${new_len} will exceed max_int')
322+
panic_n('array.insert_many: max_int will be exceeded by a.len:', new_len)
321323
}
322324
a.ensure_cap(int(new_len))
323325
elem_size := a.element_size
@@ -374,8 +376,12 @@ pub fn (mut a array) delete(i int) {
374376
// ```
375377
pub fn (mut a array) delete_many(i int, size int) {
376378
if i < 0 || i64(i) + i64(size) > i64(a.len) {
377-
endidx := if size > 1 { '..${i + size}' } else { '' }
378-
panic('array.delete: index out of range (i == ${i}${endidx}, a.len == ${a.len})')
379+
if size > 1 {
380+
panic_n3('array.delete: index out of range (i,i+size,a.len):', i, i + size,
381+
a.len)
382+
} else {
383+
panic_n2('array.delete: index out of range (i,a.len):', i, a.len)
384+
}
379385
}
380386
if a.flags.all(.noshrink | .noslices) {
381387
unsafe {
@@ -465,7 +471,7 @@ fn (a array) get_unsafe(i int) voidptr {
465471
fn (a array) get(i int) voidptr {
466472
$if !no_bounds_checking {
467473
if i < 0 || i >= a.len {
468-
panic('array.get: index out of range (i == ${i}, a.len == ${a.len})')
474+
panic_n2('array.get: index out of range (i,a.len):', i, a.len)
469475
}
470476
}
471477
unsafe {
@@ -557,13 +563,15 @@ fn (a array) slice(start int, _end int) array {
557563
end := if _end == max_int { a.len } else { _end } // max_int
558564
$if !no_bounds_checking {
559565
if start > end {
560-
panic('array.slice: invalid slice index (${start} > ${end})')
566+
panic('array.slice: invalid slice index (start>end):' + i64(start).str() + ', ' +
567+
i64(end).str())
561568
}
562569
if end > a.len {
563-
panic('array.slice: slice bounds out of range (${end} >= ${a.len})')
570+
panic('array.slice: slice bounds out of range (' + i64(end).str() + ' >= ' +
571+
i64(a.len).str() + ')')
564572
}
565573
if start < 0 {
566-
panic('array.slice: slice bounds out of range (${start} < 0)')
574+
panic('array.slice: slice bounds out of range (start<0):' + start.str())
567575
}
568576
}
569577
// TODO: integrate reference counting
@@ -683,7 +691,7 @@ fn (mut a array) set_unsafe(i int, val voidptr) {
683691
fn (mut a array) set(i int, val voidptr) {
684692
$if !no_bounds_checking {
685693
if i < 0 || i >= a.len {
686-
panic('array.set: index out of range (i == ${i}, a.len == ${a.len})')
694+
panic_n2('array.set: index out of range (i,a.len):', i, a.len)
687695
}
688696
}
689697
unsafe { vmemcpy(&u8(a.data) + u64(a.element_size) * u64(i), val, a.element_size) }
@@ -1000,7 +1008,7 @@ pub fn copy(mut dst []u8, src []u8) int {
10001008
pub fn (mut a array) grow_cap(amount int) {
10011009
new_cap := i64(amount) + i64(a.cap)
10021010
if new_cap > max_int {
1003-
panic('array.grow_cap: new capacity ${new_cap} will exceed max_int')
1011+
panic_n('array.grow_cap: max_int will be exceeded by new cap:', new_cap)
10041012
}
10051013
a.ensure_cap(int(new_cap))
10061014
}
@@ -1013,7 +1021,7 @@ pub fn (mut a array) grow_cap(amount int) {
10131021
pub fn (mut a array) grow_len(amount int) {
10141022
new_len := i64(amount) + i64(a.len)
10151023
if new_len > max_int {
1016-
panic('array.grow_len: new len ${new_len} will exceed max_int')
1024+
panic_n('array.grow_len: max_int will be exceeded by new len:', new_len)
10171025
}
10181026
a.ensure_cap(int(new_len))
10191027
a.len = int(new_len)
@@ -1053,13 +1061,13 @@ pub fn (data &u8) vbytes(len int) []u8 {
10531061
@[if !no_bounds_checking ?; inline]
10541062
fn panic_on_negative_len(len int) {
10551063
if len < 0 {
1056-
panic('negative .len')
1064+
panic_n('negative .len:', len)
10571065
}
10581066
}
10591067

10601068
@[if !no_bounds_checking ?; inline]
10611069
fn panic_on_negative_cap(cap int) {
10621070
if cap < 0 {
1063-
panic('negative .cap')
1071+
panic_n('negative .cap:', cap)
10641072
}
10651073
}

vlib/builtin/array_d_gcboehm_opt.v

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ fn (mut a array) ensure_cap_noscan(required int) {
103103
return
104104
}
105105
if a.flags.has(.nogrow) {
106-
panic('array.ensure_cap_noscan: array with the flag `.nogrow` cannot grow in size, array required new size: ${required}')
106+
panic_n('array.ensure_cap_noscan: array with the flag `.nogrow` cannot grow in size, array required new size:',
107+
required)
107108
}
108109
mut cap := if a.cap > 0 { i64(a.cap) } else { i64(2) }
109110
for required > cap {
@@ -114,7 +115,8 @@ fn (mut a array) ensure_cap_noscan(required int) {
114115
// limit the capacity, since bigger values, will overflow the 32bit integer used to store it
115116
cap = max_int
116117
} else {
117-
panic('array.ensure_cap_noscan: array needs to grow to cap = ${cap}, which is > 2^31')
118+
panic_n('array.ensure_cap_noscan: array needs to grow to cap (which is > 2^31):',
119+
cap)
118120
}
119121
}
120122
new_size := u64(cap) * u64(a.element_size)
@@ -136,7 +138,7 @@ fn (mut a array) ensure_cap_noscan(required int) {
136138
@[unsafe]
137139
fn (a array) repeat_to_depth_noscan(count int, depth int) array {
138140
if count < 0 {
139-
panic('array.repeat: count is negative: ${count}')
141+
panic_n('array.repeat: count is negative:', count)
140142
}
141143
mut size := u64(count) * u64(a.len) * u64(a.element_size)
142144
if size == 0 {
@@ -170,7 +172,7 @@ fn (a array) repeat_to_depth_noscan(count int, depth int) array {
170172
// insert inserts a value in the array at index `i`
171173
fn (mut a array) insert_noscan(i int, val voidptr) {
172174
if i < 0 || i > a.len {
173-
panic('array.insert_noscan: index out of range (i == ${i}, a.len == ${a.len})')
175+
panic_n2('array.insert_noscan: index out of range (i,a.len):', i, a.len)
174176
}
175177
if a.len == max_int {
176178
panic('array.insert_noscan: a.len reached max_int')
@@ -187,11 +189,11 @@ fn (mut a array) insert_noscan(i int, val voidptr) {
187189
@[unsafe]
188190
fn (mut a array) insert_many_noscan(i int, val voidptr, size int) {
189191
if i < 0 || i > a.len {
190-
panic('array.insert_many: index out of range (i == ${i}, a.len == ${a.len})')
192+
panic_n2('array.insert_many: index out of range (i, a.len):', i, a.len)
191193
}
192194
new_len := i64(a.len) + i64(size)
193195
if new_len > max_int {
194-
panic('array.insert_many_noscan: a.len = ${new_len} will exceed max_int')
196+
panic_n('array.insert_many_noscan: max_int will be exceeded by a.len:', new_len)
195197
}
196198
a.ensure_cap_noscan(a.len + size)
197199
elem_size := a.element_size
@@ -328,7 +330,7 @@ fn (a array) reverse_noscan() array {
328330
fn (mut a array) grow_cap_noscan(amount int) {
329331
new_cap := i64(amount) + i64(a.cap)
330332
if new_cap > max_int {
331-
panic('array.grow_cap: new capacity ${new_cap} will exceed max_int')
333+
panic_n('array.grow_cap: max_int will be exceeded by new cap:', new_cap)
332334
}
333335
a.ensure_cap_noscan(int(new_cap))
334336
}
@@ -338,7 +340,7 @@ fn (mut a array) grow_cap_noscan(amount int) {
338340
fn (mut a array) grow_len_noscan(amount int) {
339341
new_len := i64(amount) + i64(a.len)
340342
if new_len > max_int {
341-
panic('array.grow_len: new len ${new_len} will exceed max_int')
343+
panic_n('array.grow_len: max_int will be exceeded by new len:', new_len)
342344
}
343345
a.ensure_cap_noscan(int(new_len))
344346
a.len = int(new_len)

vlib/builtin/backtraces.c.v

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ pub fn print_backtrace() {
1010
$if !no_backtrace ? {
1111
$if freestanding {
1212
println(bare_backtrace())
13+
} $else $if native {
14+
// TODO: native backtrace solution
15+
} $else $if tinyc {
16+
C.tcc_backtrace(c'Backtrace')
17+
} $else $if use_libbacktrace ? {
18+
// NOTE: TCC doesn't have the unwind library
19+
print_libbacktrace(1)
1320
} $else {
14-
$if native {
15-
// TODO: native backtrace solution
16-
} $else $if tinyc {
17-
C.tcc_backtrace(c'Backtrace')
18-
} $else {
19-
// NOTE: TCC doesn't have the unwind library
20-
$if use_libbacktrace ? {
21-
print_libbacktrace(1)
22-
} $else {
23-
print_backtrace_skipping_top_frames(2)
24-
}
25-
}
21+
print_backtrace_skipping_top_frames(2)
22+
}
23+
}
24+
}
25+
26+
fn eprint_space_padding(output string, max_len int) {
27+
padding_len := max_len - output.len
28+
if padding_len > 0 {
29+
for _ in 0 .. padding_len {
30+
eprint(' ')
2631
}
2732
}
2833
}

vlib/builtin/backtraces_nix.c.v

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,14 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
6767
return false
6868
}
6969
nr_actual_frames := nr_ptrs - skipframes
70-
mut sframes := []string{}
7170
//////csymbols := backtrace_symbols(*voidptr(&buffer[skipframes]), nr_actual_frames)
7271
csymbols := C.backtrace_symbols(voidptr(&buffer[skipframes]), nr_actual_frames)
7372
for i in 0 .. nr_actual_frames {
74-
sframes << unsafe { tos2(&u8(csymbols[i])) }
75-
}
76-
for sframe in sframes {
73+
sframe := unsafe { tos2(&u8(csymbols[i])) }
7774
executable := sframe.all_before('(')
7875
addr := sframe.all_after('[').all_before(']')
7976
beforeaddr := sframe.all_before('[')
80-
cmd := 'addr2line -e ${executable} ${addr}'
77+
cmd := 'addr2line -e ' + executable + ' ' + addr
8178
// taken from os, to avoid depending on the os module inside builtin.v
8279
f := C.popen(&char(cmd.str), c'r')
8380
if f == unsafe { nil } {
@@ -92,7 +89,7 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
9289
output += tos(bp, vstrlen(bp))
9390
}
9491
}
95-
output = output.trim_space() + ':'
92+
output = output.trim_chars(' \t\n', .trim_both) + ':'
9693
if C.pclose(f) != 0 {
9794
eprintln(sframe)
9895
continue
@@ -104,9 +101,14 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
104101
// Note: it is shortened here to just d. , just so that it fits, and so
105102
// that the common error file:lineno: line format is enforced.
106103
output = output.replace(' (discriminator', ': (d.')
107-
eprintln('${output:-55s} | ${addr:14s} | ${beforeaddr}')
104+
eprint(output)
105+
eprint_space_padding(output, 55)
106+
eprint(' | ')
107+
eprint(addr)
108+
eprint(' | ')
109+
eprintln(beforeaddr)
108110
}
109-
if sframes.len > 0 {
111+
if nr_actual_frames > 0 {
110112
unsafe { C.free(csymbols) }
111113
}
112114
}

vlib/builtin/backtraces_windows.c.v

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ pub fn print_backtrace_skipping_top_frames(skipframes int) bool {
7676
return false
7777
}
7878

79+
@[direct_array_access]
7980
fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
8081
$if msvc {
8182
mut offset := u64(0)
@@ -116,23 +117,31 @@ fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
116117
if C.SymGetLineFromAddr64(handle, frame_addr, &offset, &sline64) == 1 {
117118
file_name := unsafe { tos3(sline64.f_file_name) }
118119
lnumber := sline64.f_line_number
119-
lineinfo = '${file_name}:${lnumber}'
120+
lineinfo = file_name + i64(lnumber).str()
120121
} else {
121122
// addr:
122-
lineinfo = '?? : address = 0x${(&frame_addr):x}'
123+
lineinfo = '?? : address = 0x' + ptr_str(frame_addr)
123124
}
124125
sfunc := unsafe { tos3(fname) }
125-
eprintln('${nframe:-2d}: ${sfunc:-25s} ${lineinfo}')
126+
snframe := i64(nframe).str()
127+
eprint_space_padding(snframe, 2)
128+
eprint(': ')
129+
eprint(sfunc)
130+
eprint_space_padding(sfunc, 25)
131+
eprint(' ')
132+
eprint(lineinfo)
126133
} else {
127134
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
128135
cerr := int(C.GetLastError())
136+
eprint('SymFromAddr failure: ')
137+
eprint(i64(cerr).str())
129138
if cerr == 87 {
130-
eprintln('SymFromAddr failure: ${cerr} = The parameter is incorrect)')
139+
eprintln(' = The parameter is incorrect)')
131140
} else if cerr == 487 {
132141
// probably caused because the .pdb isn't in the executable folder
133-
eprintln('SymFromAddr failure: ${cerr} = Attempt to access invalid address (Verify that you have the .pdb file in the right folder.)')
142+
eprintln(' = Attempt to access invalid address (Verify that you have the .pdb file in the right folder.)')
134143
} else {
135-
eprintln('SymFromAddr failure: ${cerr} (see https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)')
144+
eprintln(' (see https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes)')
136145
}
137146
}
138147
}

vlib/builtin/builtin.c.v

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ fn panic_debug(line_no int, file string, mod string, fn_name string, s string) {
106106
// It ends the program with a panic.
107107
@[noreturn]
108108
pub fn panic_option_not_set(s string) {
109-
panic('option not set (${s})')
109+
panic('option not set (' + s + ')')
110110
}
111111

112112
// panic_result_not_set is called by V, when you use result error propagation in your main function
113113
// It ends the program with a panic.
114114
@[noreturn]
115115
pub fn panic_result_not_set(s string) {
116-
panic('result not set (${s})')
116+
panic('result not set (' + s + ')')
117117
}
118118

119119
// panic prints a nice error message, then exits the process with exit code of 1.
@@ -175,6 +175,24 @@ pub fn c_error_number_str(errnum int) string {
175175
return err_msg
176176
}
177177

178+
// panic_n prints an error message, followed by the given number, then exits the process with exit code of 1.
179+
@[noreturn]
180+
pub fn panic_n(s string, number1 i64) {
181+
panic(s + number1.str())
182+
}
183+
184+
// panic_n2 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
185+
@[noreturn]
186+
pub fn panic_n2(s string, number1 i64, number2 i64) {
187+
panic(s + number1.str() + ', ' + number2.str())
188+
}
189+
190+
// panic_n3 prints an error message, followed by the given numbers, then exits the process with exit code of 1.
191+
@[noreturn]
192+
fn panic_n3(s string, number1 i64, number2 i64, number3 i64) {
193+
panic(s + number1.str() + ', ' + number2.str() + ', ' + number2.str())
194+
}
195+
178196
// panic with a C-API error message matching `errnum`
179197
@[noreturn]
180198
pub fn panic_error_number(basestr string, errnum int) {
@@ -751,8 +769,8 @@ pub fn gc_memory_use() usize {
751769
fn v_fixed_index(i int, len int) int {
752770
$if !no_bounds_checking {
753771
if i < 0 || i >= len {
754-
s := 'fixed array index out of range (index: ${i}, len: ${len})'
755-
panic(s)
772+
panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' +
773+
i64(len).str() + ')')
756774
}
757775
}
758776
return i

0 commit comments

Comments
 (0)