v / vlib / builtin / builtin.c.v
189 lines · 168 sloc · 5.54 KB · 81a5657604ec6da99c25e26546870c6888d6fdde
Raw
1@[has_globals]
2module builtin
3
4// NOTE: g_main_argc and g_main_argv are filled in right after C's main start.
5// They are used internally by V's builtin; for user code, it is much
6// more convenient to just use `os.args` or call `arguments()` instead.
7
8@[markused]
9__global g_main_argc = int(0)
10
11@[markused]
12__global g_main_argv = unsafe { nil }
13
14@[markused]
15__global g_live_reload_info voidptr
16
17pub type FnExitCb = fn ()
18
19fn C.atexit(f FnExitCb) i32
20fn C.strerror(i32) &char
21
22// These functions (_vinit, and _vcleanup), are generated by V.
23// `module no_main` programs that use custom manual entrypoints should ensure to call them when appropriate.
24// Exported V entrypoints are initialized automatically by the generated wrappers.
25fn C._vinit(argc i32, argv &&char)
26
27fn C._vcleanup()
28
29// exit terminates execution immediately and returns exit `code` to the shell.
30@[noreturn]
31pub fn exit(code int) {
32 C.exit(code)
33 for {}
34}
35
36// at_exit registers a fn callback, that will be called at normal process termination.
37// It returns an error, if the registration was not successful.
38// The registered callback functions, will be called either via exit/1,
39// or via return from the main program, in the reverse order of their registration.
40// The same fn may be registered multiple times.
41// Each callback fn will called once for each registration.
42pub fn at_exit(cb FnExitCb) ! {
43 $if freestanding {
44 return error('at_exit not implemented with -freestanding')
45 } $else {
46 res := C.atexit(cb)
47 if res != 0 {
48 return error_with_code('at_exit failed', res)
49 }
50 }
51}
52
53fn v_segmentation_fault_handler(signal_number i32) {
54 $if v2_native_windows_pe_minimal ? {
55 eprintln('signal 11: segmentation fault')
56 exit(128 + signal_number)
57 } $else {
58 $if freestanding {
59 eprintln('signal 11: segmentation fault')
60 } $else {
61 C.fprintf(C.stderr, c'signal %d: segmentation fault\n', signal_number)
62 }
63 $if use_libbacktrace ? {
64 $if openbsd {
65 print_backtrace()
66 } $else {
67 eprint_libbacktrace(1)
68 }
69 } $else {
70 print_backtrace()
71 }
72 exit(128 + signal_number)
73 }
74}
75
76@[inline]
77fn v_fixed_index(i int, len int) int {
78 $if !no_bounds_checking {
79 if i < 0 || i >= len {
80 panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' +
81 i64(len).str() + ')')
82 }
83 }
84 return i
85}
86
87@[inline; markused]
88fn v_fixed_index_i64(i i64, len int) int {
89 $if !no_bounds_checking {
90 if i < 0 || i >= i64(len) {
91 panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() +
92 ')')
93 }
94 }
95 return int(i)
96}
97
98@[inline; markused]
99fn v_fixed_index_u64(i u64, len int) int {
100 $if !no_bounds_checking {
101 if i >= u64(len) {
102 panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() +
103 ')')
104 }
105 }
106 return int(i)
107}
108
109@[inline; markused]
110fn v_fixed_index_ni(i int, len int) int {
111 return v_fixed_index(v_ni_index(i, len), len)
112}
113
114@[inline; markused]
115fn v_slice_index_i64(i i64) int {
116 if i < i64(min_int) || i > i64(max_int) {
117 panic('slice index out of range for int: ' + i.str())
118 }
119 return int(i)
120}
121
122@[inline; markused]
123fn v_slice_index_u64(i u64) int {
124 if i > u64(max_int) {
125 panic('slice index out of range for int: ' + i.str())
126 }
127 return int(i)
128}
129
130// arguments returns the command line arguments, used for starting the current program as a V array of strings.
131// The first string in the array (index 0), is the name of the program, used for invoking the program.
132// The second string in the array (index 1), if it exists, is the first argument to the program, etc.
133// For example, if you started your program as `myprogram -option`, then arguments() will return ['myprogram', '-option'].
134// Note: if you `v run file.v abc def`, then arguments() will return ['file', 'abc', 'def'], or ['file.exe', 'abc', 'def'] (on Windows).
135pub fn arguments() []string {
136 argv := &&u8(g_main_argv)
137 mut res := []string{cap: g_main_argc}
138 for i in 0 .. g_main_argc {
139 $if windows {
140 res << unsafe { string_from_wide(&u16(argv[i])) }
141 } $else {
142 res << unsafe { tos_clone(argv[i]) }
143 }
144 }
145 return res
146}
147
148// vcurrent_hash returns @VCURRENTHASH, which depends on the git version of
149// the V repository, from which the V executable had been compiled.
150pub fn vcurrent_hash() string {
151 return @VCURRENTHASH
152}
153
154// v_getpid returns a process identifier. It is a number that is guaranteed to
155// remain the same while the current process is running. It may or may not be
156// equal to the value of v_gettid(). Note: it is *NOT equal on Windows*.
157pub fn v_getpid() u64 {
158 $if no_getpid ? {
159 // support non posix/windows systems that lack process management
160 return 0
161 } $else $if windows {
162 return u64(C.GetCurrentProcessId())
163 } $else {
164 return u64(C.getpid())
165 }
166}
167
168// v_gettid retuns a thread identifier. It is a number that is guaranteed to not
169// change, while the current thread is running. Different threads, running at
170// the same time in the same process, have different thread ids. There is no
171// such guarantee for threads running in different processes.
172// Important: this will be the same number returned by v_getpid(), but only on
173// non windows systems, when the current thread is the main one. It is best to
174// *avoid relying on this equivalence*, and use v_gettid and v_getpid only for
175// tracing and debugging multithreaded issues, but *NOT for logic decisions*.
176pub fn v_gettid() u64 {
177 $if no_gettid ? {
178 // support non posix/windows systems that lack process management
179 return 0
180 } $else $if windows {
181 return u64(C.GetCurrentThreadId())
182 } $else $if linux && !musl ? {
183 return u64(C.gettid())
184 } $else $if threads {
185 return u64(C.pthread_self())
186 } $else {
187 return v_getpid()
188 }
189}
190