freestanding: add array support (stack only for now)

pull/2944/head
bogen85 2019-12-01 02:27:36 -06:00 committed by Alexander Medvednikov
parent 3fea8f3de5
commit 854309a7d8
9 changed files with 235 additions and 49 deletions

View File

@ -12,12 +12,13 @@ fn passed (msg string) {
fn vcheck(vfile string) {
run_check := "v -freestanding --enable-globals run "
run_check := "v -show_c_cmd -freestanding --enable-globals run "
if 0 == os.system("$run_check $vfile/${vfile}.v") {
passed(run_check)
} else {
failed(run_check)
}
os.system("ls -lh $vfile/$vfile")
os.system("rm -f $vfile/$vfile")
}

View File

@ -165,7 +165,7 @@ fn check_mm_pages() {
//pub fn mm_alloc(size u64) (voidptr, errno)
fn check_mm_alloc() {
println ("checking check_mm_alloc")
println ("checking mm_alloc")
for i in 1 .. 2000 {
size := u64(i*1000)
@ -201,6 +201,107 @@ fn check_mm_alloc() {
println ("mm_alloc passed")
}
fn check_int_array_ro() {
println ("trying check_int_array_ro")
a := [100,110,120,130]
assert a.len == 4
assert a[0] == 100
assert a[1] == 110
assert a[2] == 120
assert a[3] == 130
println ("check_int_array_ro passed")
}
fn check_int_array_rw() {
println ("trying check_int_array_rw")
mut a := [-10,-11,-12,-13]
assert a.len == 4
assert a[0] == -10
assert a[1] == -11
assert a[2] == -12
assert a[3] == -13
for i in 0..a.len {
b := -a[i] * 10
a[i] = b
assert a[i] == b
}
assert a[3] == 130
println ("check_int_array_rw passed")
}
fn check_int64_array_ro() {
println ("trying check_int64_array_ro")
a := [i64(1000),1100,1200,1300,1400]
assert a.len == 5
assert a[0] == 1000
assert a[1] == 1100
assert a[2] == 1200
assert a[3] == 1300
assert a[4] == 1400
println ("check_int64_array_ro passed")
}
fn check_voidptr_array_ro() {
println ("trying check_voidptr_array_ro")
a := [
voidptr(10000),
voidptr(11000),
voidptr(12000),
voidptr(13000),
voidptr(14000),
voidptr(15000)
]
assert a.len == 6
assert a[0] == voidptr(10000)
assert a[1] == voidptr(11000)
assert a[2] == voidptr(12000)
assert a[3] == voidptr(13000)
assert a[4] == voidptr(14000)
assert a[5] == voidptr(15000)
println ("check_voidptr_array_ro passed")
}
fn check_voidptr_array_rw() {
println ("trying check_voidptr_array_rw")
mut a := [
voidptr(-1),
voidptr(-1),
voidptr(-1),
voidptr(-1),
voidptr(-1),
voidptr(-1)
]
assert a.len == 6
assert a[0] == voidptr(-1)
assert a[1] == voidptr(-1)
assert a[2] == voidptr(-1)
assert a[3] == voidptr(-1)
assert a[4] == voidptr(-1)
assert a[5] == voidptr(-1)
a[0] = voidptr(100000)
assert a[0] == voidptr(100000)
a[1] = voidptr(110000)
assert a[1] == voidptr(110000)
a[2] = voidptr(120000)
assert a[2] == voidptr(120000)
a[3] = voidptr(130000)
assert a[3] == voidptr(130000)
a[4] = voidptr(140000)
assert a[4] == voidptr(140000)
a[5] = voidptr(150000)
assert a[5] == voidptr(150000)
println ("check_voidptr_array_rw passed")
}
fn main() {
check_read_write_pipe()
check_read_file()
@ -210,5 +311,10 @@ fn main() {
check_mmap_one_page()
check_mm_pages()
check_mm_alloc()
check_int_array_ro()
check_int_array_rw()
check_int64_array_ro()
check_voidptr_array_ro()
check_voidptr_array_rw()
sys_exit(0)
}

View File

@ -0,0 +1,36 @@
module builtin
pub struct array {
pub:
data voidptr
len int
cap int
element_size int
}
// for now off the stack
fn new_array_from_c_array(len, cap, elm_size int, c_array voidptr) array {
arr := array {
len: len
cap: cap
element_size: elm_size
data: c_array
}
return arr
}
// Private function. Used to implement array[] operator
fn (a array) get(i int) voidptr {
if i < 0 || i >= a.len {
panic('array.get: index out of range') // FIXME: (i == $i, a.len == $a.len)')
}
return a.data + i * a.element_size
}
// Private function. Used to implement assigment to the array element.
fn (a mut array) set(i int, val voidptr) {
if i < 0 || i >= a.len {
panic('array.set: index out of range') //FIXME: (i == $i, a.len == $a.len)')
}
mem_copy(a.data + a.element_size * i, val, a.element_size)
}

View File

@ -17,12 +17,53 @@ pub enum wp_sys {
}
// First argument to waitid:
pub enum wi_sys {
pub enum wi_which {
p_all = 0
p_pid = 1
p_pgid = 2
}
pub enum wi_si_code {
cld_exited = 1 // child has exited
cld_killed = 2 // child was killed
cld_dumped = 3 // child terminated abnormally
cld_trapped = 4 // traced child has trapped
cld_stopped = 5 // child has stopped
cld_continued = 6 // stopped child has continued
}
/* Paraphrased from "man 2 waitid" on Linux
Upon successful return, waitid() fills in the
following fields of the siginfo_t structure
pointed to by infop:
si_pid, offset 0x10, int index 0x04:
The process ID of the child.
si_uid: offset 0x14, int index 0x05
The real user ID of the child.
si_signo: offset 0x00, int index 0x00
Always set to SIGCHLD.
si_status: ofset 0x18, int index 0x06
1 the exit status of the child, as given to _exit(2)
(or exit(3)) (sc_sys.cld_exited)
2 the signal that caused the child to terminate, stop,
or continue.
3 The si_code field can be used to determine how to
interpret this field.
si_code, set to one of (enum wi_si_code), offset 0x08, int index 0x02:
CLD_EXITED (child called _exit(2));
CLD_KILLED (child killed by signal);
CLD_DUMPED (child killed by signal, and dumped core);
CLD_STOPPED (child stopped by signal);
CLD_TRAPPED (traced child has trapped);
CLD_CONTINUED (child continued by SIGCONT).
*/
pub enum fcntl {
fd_cloexec = 0x00000001
f_dupfd = 0x00000000

View File

@ -1,7 +1,5 @@
module builtin
//__global buffer [128]byte
pub fn mm_pages(size u64) u32 {
pages := (u64(size+u64(4))+u64(linux_mem.page_size))/u64(linux_mem.page_size)
return u32(pages)
@ -14,16 +12,6 @@ pub fn mm_alloc(size u64) (byteptr, errno) {
mem_prot := mm_prot(int(mm_prot.prot_read) | int(mm_prot.prot_write))
mem_flags := map_flags(int(map_flags.map_private) | int(map_flags.map_anonymous))
//mps := i64_tos(buffer,80,i64(mem_prot),16)
//println(mps)
//mfs := i64_tos(buffer,80,i64(mem_flags),16)
//println(mfs)
//print("pages in: ")
//ps := i64_tos(buffer,80,i64(pages),16)
//println(ps)
a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0)
if e == .enoerror {
mut ap := intptr(a)
@ -37,20 +25,14 @@ pub fn mm_free(addr byteptr) errno {
ap := intptr(addr-4)
size := u64(*ap) * u64(linux_mem.page_size)
//aps := i64_tos(buffer,80,i64(addr),16)
//println(aps)
//ss := i64_tos(buffer,80,i64(size),16)
//print("size out: ")
//println(ss)
//pas := i64_tos(buffer,80,i64(ap),16)
//println(pas)
e := sys_munmap(ap, size)
//es := i64_tos(buffer,80,i64(e),16)
//println(es)
return e
return sys_munmap(ap, size)
}
pub fn mem_copy(dest0 voidptr, src0 voidptr, n int) voidptr {
mut dest := byteptr(dest0)
src := byteptr(src0)
for i in 0..n {
dest[i] = src[i]
}
return dest0
}

View File

@ -1,20 +1,25 @@
import os
fn test_syscallwrappers() {
if true {return}
vexe := os.getenv("VEXE")
vn := vexe.len - 1
if vn > 1 {
dot_checks := vexe.substr(0,vn) + "vlib/builtin/bare/.checks"
assert os.dir_exists(dot_checks)
os.chdir(dot_checks)
checks_v := "checks.v"
assert os.file_exists(checks_v)
rc := os.exec("v run $checks_v") or { panic(err) }
assert !rc.output.contains("V panic: An assertion failed.")
assert !rc.output.contains("failed")
assert rc.exit_code == 0
} else {
panic("Can't find v")
if true { return }
$if linux {
$if x64 {
exe := os.executable()
vdir := os.dir(exe)
if vdir.len > 1 {
dot_checks := vdir + "/.checks"
assert os.dir_exists(dot_checks)
os.chdir(dot_checks)
checks_v := "checks.v"
assert os.file_exists(checks_v)
rc := os.exec("v run $checks_v") or { panic(err) }
assert !rc.output.contains("V panic: An assertion failed.")
assert !rc.output.contains("failed")
assert rc.exit_code == 0
} else {
panic("Can't find test directory")
}
}
}
}

View File

@ -126,7 +126,7 @@ fn (v mut V) cc() {
v.out_name = v.out_name + '.so'
}
if v.pref.is_bare {
a << '-static -ffreestanding -nostdlib $vdir/vlib/os/bare/bare.S'
a << '-fno-stack-protector -static -ffreestanding -nostdlib $vdir/vlib/os/bare/bare.S'
}
if v.pref.build_mode == .build_module {
// Create the modules & out directory if it's not there.
@ -263,7 +263,7 @@ fn (v mut V) cc() {
a << libs
// Without these libs compilation will fail on Linux
// || os.user_os() == 'linux'
if v.pref.build_mode != .build_module && (v.os == .linux || v.os == .freebsd || v.os == .openbsd ||
if !v.pref.is_bare && v.pref.build_mode != .build_module && (v.os == .linux || v.os == .freebsd || v.os == .openbsd ||
v.os == .netbsd || v.os == .dragonfly || v.os == .solaris) {
a << '-lm -lpthread '
// -ldl is a Linux only thing. BSDs have it in libc.
@ -272,7 +272,7 @@ fn (v mut V) cc() {
}
}
if v.os == .js && os.user_os() == 'linux' {
if !v.pref.is_bare && v.os == .js && os.user_os() == 'linux' {
a << '-lm'
}

View File

@ -206,4 +206,17 @@ typedef map map_string;
#define false 0
#endif
'
bare_c_headers = '
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[])
#define TCCSKIP(x) x
#ifdef __TINYC__
#undef EMPTY_ARRAY_OF_ELEMS
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n])
#undef TCCSKIP
#define TCCSKIP(x)
#endif
'
)

View File

@ -254,6 +254,8 @@ pub fn (v mut V) compile() {
if !v.pref.is_bare {
cgen.genln(c_headers)
} else {
cgen.genln(bare_c_headers)
}
}
v.generate_hotcode_reloading_declarations()