freestanding: malloc/free with mm_alloc an mm_free

Added more array support that depends on malloc. Added string clone (that uses malloc). Added test for it. Eliminated stack allocated buffers from most of the unit checks.
pull/3011/head
bogen85 2019-12-08 04:44:52 -06:00 committed by Alexander Medvednikov
parent 6ec626c5e9
commit 8178e1f7da
10 changed files with 96 additions and 56 deletions

View File

@ -12,8 +12,7 @@ fn passed (msg string) {
fn vcheck(vfile string) { fn vcheck(vfile string) {
//os.system("ln -s ../forkedtest $vfile/forkedtest") run_check := "v -user_mod_path . -freestanding run "
run_check := "v -user_mod_path . -freestanding --enable-globals run "
if 0 == os.system("$run_check $vfile/${vfile}.v") { if 0 == os.system("$run_check $vfile/${vfile}.v") {
passed(run_check) passed(run_check)
} else { } else {
@ -21,7 +20,6 @@ fn vcheck(vfile string) {
} }
os.system("ls -lh $vfile/$vfile") os.system("ls -lh $vfile/$vfile")
os.system("rm -f $vfile/$vfile") os.system("rm -f $vfile/$vfile")
//os.system("rm -f $vfile/forkedtest")
} }
fn main() { fn main() {

View File

@ -1,33 +1,25 @@
module forkedtest module forkedtest
__global buffer [128]byte
pub fn run (op fn(), label string, code wi_si_code, status int) int { pub fn run (op fn(), label string, code wi_si_code, status int) int {
child := sys_fork() child := sys_fork()
if child == 0 { if child == 0 {
op() op()
sys_exit(0) sys_exit(0)
} }
siginfo := [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0]
e := sys_waitid(.p_pid, child, intptr(siginfo.data) , .wexited, 0) siginfo := [0].repeat(int(sig_index.si_size))
e := sys_waitid(.p_pid, child, intptr(&siginfo[0]), .wexited, 0)
assert e == .enoerror assert e == .enoerror
assert siginfo[sig_index.si_pid] == child assert siginfo[int(sig_index.si_pid)] == child
assert siginfo[sig_index.si_signo] == int(signo.sigchld) assert siginfo[int(sig_index.si_signo)] == int(signo.sigchld)
assert siginfo[sig_index.si_uid] == sys_getuid() assert siginfo[int(sig_index.si_uid)] == sys_getuid()
r_code := siginfo[sig_index.si_code] r_code := siginfo[sig_index.si_code]
r_status := siginfo[sig_index.si_status] r_status := siginfo[sig_index.si_status]
print("+++ ")
print(label) print(label)
if (int(code) == r_code) && (status == r_status) { if (int(code) == r_code) && (status == r_status) {
println(" PASSED") println(" PASSED")
@ -37,16 +29,16 @@ pub fn run (op fn(), label string, code wi_si_code, status int) int {
if int(code) != r_code { if int(code) != r_code {
print(">> Expecting si_code 0x") print(">> Expecting si_code 0x")
println(i64_tos(buffer,80,int(code),16)) println(i64_str(int(code),16))
print(">> Got 0x") print(">> Got 0x")
println(i64_tos(buffer,80,r_code,16)) println(i64_str(r_code,16))
} }
if status != r_status { if status != r_status {
print(">> Expecting status 0x") print(">> Expecting status 0x")
println(i64_tos(buffer,80,status,16)) println(i64_str(status,16))
print(">> Got 0x") print(">> Got 0x")
println(i64_tos(buffer,80,r_status,16)) println(i64_str(r_status,16))
} }
return 1 return 1

View File

@ -40,15 +40,15 @@ fn check_read_write_pipe() {
// sys_read // sys_read
// sys_close // sys_close
// //
buffer, e := mm_alloc(128) buffer0 := [byte(0)].repeat(128)
assert e == .enoerror buffer := byteptr(buffer0.data)
fd := [-1, -1] fd := [-1, -1]
assert fd[0] == -1 assert fd[0] == -1
assert fd[1] == -1 assert fd[1] == -1
a := sys_pipe(intptr(fd.data)) a := sys_pipe(intptr(&fd[0]))
assert a == .enoerror assert a == .enoerror
@ -62,7 +62,7 @@ fn check_read_write_pipe() {
assert e1 == .enoerror assert e1 == .enoerror
assert c1 == b assert c1 == b
c2, e2 := sys_read(fd[0], byteptr(buffer), u64(b)) c2, e2 := sys_read(fd[0], buffer, u64(b))
assert e2 == .enoerror assert e2 == .enoerror
assert c2 == b assert c2 == b
@ -77,8 +77,6 @@ fn check_read_write_pipe() {
assert sys_close(fd[1]) == .enoerror assert sys_close(fd[1]) == .enoerror
assert sys_close(-1) == .ebadf assert sys_close(-1) == .ebadf
assert mm_free(buffer) == .enoerror
} }
fn check_read_file() { fn check_read_file() {
@ -89,8 +87,8 @@ fn check_read_file() {
sys_close sys_close
sys_open sys_open
*/ */
buffer, mae := mm_alloc(128) buffer0 := [byte(0)].repeat(128)
assert mae == .enoerror buffer := byteptr(buffer0.data)
test_file := "sample_text1.txt" test_file := "sample_text1.txt"
sample_text := "Do not change this text.\n" sample_text := "Do not change this text.\n"
@ -105,7 +103,6 @@ fn check_read_file() {
assert sample_text[i] == buffer[i] assert sample_text[i] == buffer[i]
} }
assert sys_close(fd) == .enoerror assert sys_close(fd) == .enoerror
assert mm_free(buffer) == .enoerror
} }
fn check_open_file_fail() { fn check_open_file_fail() {

View File

@ -8,9 +8,8 @@ fn check_string_eq () {
} }
fn check_i64_tos() { fn check_i64_tos() {
buffer, e := mm_alloc(128) buffer0 := [byte(0)].repeat(128)
assert e == .enoerror buffer := byteptr(buffer0.data)
assert !isnil(buffer)
s0 := i64_tos(buffer, 70, 140, 10) s0 := i64_tos(buffer, 70, 140, 10)
assert s0 == "140" assert s0 == "140"
@ -23,14 +22,29 @@ fn check_i64_tos() {
s3 := i64_tos(buffer, 70, -160000, 10) s3 := i64_tos(buffer, 70, -160000, 10)
assert s3 == "-160000" assert s3 == "-160000"
}
assert mm_free(buffer) == .enoerror fn check_i64_str() {
assert "141" == i64_str(141, 10)
assert "-161" == i64_str(-161, 10)
assert "10002" == i64_str(65538, 16)
assert "-160001" == i64_str(-160001, 10)
}
fn check_str_clone() {
a := i64_str(1234,10)
b := a.clone()
assert a == b
c := i64_str(-6789,10).clone()
assert c == "-6789"
} }
fn main () { fn main () {
mut fails := 0 mut fails := 0
fails += forkedtest.normal_run(check_string_eq, "check_string_eq") fails += forkedtest.normal_run(check_string_eq, "check_string_eq")
fails += forkedtest.normal_run(check_i64_tos, "check_i64_tos") fails += forkedtest.normal_run(check_i64_tos, "check_i64_tos")
fails += forkedtest.normal_run(check_i64_str, "check_i64_str")
fails += forkedtest.normal_run(check_str_clone, "check_str_clone")
assert fails == 0 assert fails == 0
sys_exit(0) sys_exit(0)
} }

View File

@ -34,3 +34,21 @@ fn (a mut array) set(i int, val voidptr) {
} }
mem_copy(a.data + a.element_size * i, val, a.element_size) mem_copy(a.data + a.element_size * i, val, a.element_size)
} }
// array.repeat returns new array with the given array elements
// repeated `nr_repeat` times
pub fn (a array) repeat(nr_repeats int) array {
assert nr_repeats >= 0
arr := array {
len: nr_repeats * a.len
cap: nr_repeats * a.len
element_size: a.element_size
data: malloc(nr_repeats * a.len * a.element_size)
}
for i := 0; i < nr_repeats; i++ {
mem_copy(arr.data + i * a.len * a.element_size, a.data, a.len * a.element_size)
}
return arr
}

View File

@ -18,25 +18,25 @@ pub fn println(s string) {
} }
pub fn panic(s string) { pub fn panic(s string) {
print('V panic: ') eprint('V panic: ')
println(s) eprintln(s)
sys_exit(1) sys_exit(1)
} }
// replaces panic when -debug arg is passed // replaces panic when -debug arg is passed
fn panic_debug(line_no int, file, mod, fn_name, s string) { fn panic_debug(line_no int, file, mod, fn_name, s string) {
println('================ V panic ================') eprintln('================ V panic ================')
print(' module: ') eprint(' module: ')
println('mod') eprintln('mod')
print(' function: ') eprint(' function: ')
print(fn_name) eprint(fn_name)
println('()') eprintln('()')
println(' file: ') eprintln(' file: ')
println(file) eprintln(file)
//println(' line: ${line_no}') //println(' line: ${line_no}')
print(' message: ') eprint(' message: ')
println(s) eprintln(s)
println('=========================================') eprintln('=========================================')
sys_exit(1) sys_exit(1)
} }
pub fn eprint(s string) { pub fn eprint(s string) {

View File

@ -70,6 +70,7 @@ pub enum sig_index {
si_pid = 0x04 si_pid = 0x04
si_uid = 0x05 si_uid = 0x05
si_status = 0x06 si_status = 0x06
si_size = 0x80
} }
pub enum signo { pub enum signo {

View File

@ -39,3 +39,20 @@ pub fn mem_copy(dest0 voidptr, src0 voidptr, n int) voidptr {
} }
return dest0 return dest0
} }
[unsafe_fn]
pub fn malloc(n int) byteptr {
if n < 0 {
panic('malloc(<0)')
}
ptr, e := mm_alloc(u64(n))
assert e == .enoerror
assert !isnil(ptr)
return ptr
}
[unsafe_fn]
pub fn free(ptr voidptr) {
assert mm_free(ptr) == .enoerror
}

View File

@ -95,18 +95,17 @@ pub fn i64_tos(buf byteptr, len int, n0 i64, base int) string {
return b return b
} }
pub fn i64_str(n0 i64, base int) string {
buf := malloc(80)
return i64_tos(buf, 79, n0, base)
}
/*
pub fn (a string) clone() string { pub fn (a string) clone() string {
mut b := string { mut b := string {
len: a.len len: a.len
str: malloc(a.len + 1) str: malloc(a.len + 1)
} }
for i := 0; i < a.len; i++ { mem_copy(b.str, a.str, a.len)
b[i] = a[i]
}
b[a.len] = `\0` b[a.len] = `\0`
return b return b
} }
*/

View File

@ -219,6 +219,10 @@ bare_c_headers = '
#define TCCSKIP(x) #define TCCSKIP(x)
#endif #endif
#ifndef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_INITIALIZATION 0
#endif
#ifndef exit #ifndef exit
#define exit(rc) sys_exit(rc) #define exit(rc) sys_exit(rc)
void sys_exit (int); void sys_exit (int);