freestanding: add array support (stack only for now)
parent
3fea8f3de5
commit
854309a7d8
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
'
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue