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
parent
6ec626c5e9
commit
8178e1f7da
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue