vxx2 / vlib / builtin / builtin.c.v
191 lines · 170 sloc · 5.62 KB · 099040eb391e8186e1bafd1906cb9dc01e20f07c
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 ? && !tinyc {
64 $if openbsd {
65 print_backtrace()
66 } $else {
67 eprint_libbacktrace(1)
68 }
69 } $else $if tinyc && glibc {
70 print_backtrace_skipping_top_frames(1)
71 } $else {
72 print_backtrace()
73 }
74 exit(128 + signal_number)
75 }
76}
77
78@[inline]
79fn v_fixed_index(i int, len int) int {
80 $if !no_bounds_checking {
81 if i < 0 || i >= len {
82 panic('fixed array index out of range (index: ' + i64(i).str() + ', len: ' +
83 i64(len).str() + ')')
84 }
85 }
86 return i
87}
88
89@[inline; markused]
90fn v_fixed_index_i64(i i64, len int) int {
91 $if !no_bounds_checking {
92 if i < 0 || i >= i64(len) {
93 panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() +
94 ')')
95 }
96 }
97 return int(i)
98}
99
100@[inline; markused]
101fn v_fixed_index_u64(i u64, len int) int {
102 $if !no_bounds_checking {
103 if i >= u64(len) {
104 panic('fixed array index out of range (index: ' + i.str() + ', len: ' + i64(len).str() +
105 ')')
106 }
107 }
108 return int(i)
109}
110
111@[inline; markused]
112fn v_fixed_index_ni(i int, len int) int {
113 return v_fixed_index(v_ni_index(i, len), len)
114}
115
116@[inline; markused]
117fn v_slice_index_i64(i i64) int {
118 if i < i64(min_int) || i > i64(max_int) {
119 panic('slice index out of range for int: ' + i.str())
120 }
121 return int(i)
122}
123
124@[inline; markused]
125fn v_slice_index_u64(i u64) int {
126 if i > u64(max_int) {
127 panic('slice index out of range for int: ' + i.str())
128 }
129 return int(i)
130}
131
132// arguments returns the command line arguments, used for starting the current program as a V array of strings.
133// The first string in the array (index 0), is the name of the program, used for invoking the program.
134// The second string in the array (index 1), if it exists, is the first argument to the program, etc.
135// For example, if you started your program as `myprogram -option`, then arguments() will return ['myprogram', '-option'].
136// Note: if you `v run file.v abc def`, then arguments() will return ['file', 'abc', 'def'], or ['file.exe', 'abc', 'def'] (on Windows).
137pub fn arguments() []string {
138 argv := &&u8(g_main_argv)
139 mut res := []string{cap: g_main_argc}
140 for i in 0 .. g_main_argc {
141 $if windows {
142 res << unsafe { string_from_wide(&u16(argv[i])) }
143 } $else {
144 res << unsafe { tos_clone(argv[i]) }
145 }
146 }
147 return res
148}
149
150// vcurrent_hash returns @VCURRENTHASH, which depends on the git version of
151// the V repository, from which the V executable had been compiled.
152pub fn vcurrent_hash() string {
153 return @VCURRENTHASH
154}
155
156// v_getpid returns a process identifier. It is a number that is guaranteed to
157// remain the same while the current process is running. It may or may not be
158// equal to the value of v_gettid(). Note: it is *NOT equal on Windows*.
159pub fn v_getpid() u64 {
160 $if no_getpid ? {
161 // support non posix/windows systems that lack process management
162 return 0
163 } $else $if windows {
164 return u64(C.GetCurrentProcessId())
165 } $else {
166 return u64(C.getpid())
167 }
168}
169
170// v_gettid retuns a thread identifier. It is a number that is guaranteed to not
171// change, while the current thread is running. Different threads, running at
172// the same time in the same process, have different thread ids. There is no
173// such guarantee for threads running in different processes.
174// Important: this will be the same number returned by v_getpid(), but only on
175// non windows systems, when the current thread is the main one. It is best to
176// *avoid relying on this equivalence*, and use v_gettid and v_getpid only for
177// tracing and debugging multithreaded issues, but *NOT for logic decisions*.
178pub fn v_gettid() u64 {
179 $if no_gettid ? {
180 // support non posix/windows systems that lack process management
181 return 0
182 } $else $if windows {
183 return u64(C.GetCurrentThreadId())
184 } $else $if linux && !musl ? {
185 return u64(C.gettid())
186 } $else $if threads {
187 return u64(C.pthread_self())
188 } $else {
189 return v_getpid()
190 }
191}
192