freestanding: add array support (stack only for now)
parent
3fea8f3de5
commit
854309a7d8
|
@ -12,12 +12,13 @@ fn passed (msg string) {
|
||||||
|
|
||||||
|
|
||||||
fn vcheck(vfile 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") {
|
if 0 == os.system("$run_check $vfile/${vfile}.v") {
|
||||||
passed(run_check)
|
passed(run_check)
|
||||||
} else {
|
} else {
|
||||||
failed(run_check)
|
failed(run_check)
|
||||||
}
|
}
|
||||||
|
os.system("ls -lh $vfile/$vfile")
|
||||||
os.system("rm -f $vfile/$vfile")
|
os.system("rm -f $vfile/$vfile")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ fn check_mm_pages() {
|
||||||
//pub fn mm_alloc(size u64) (voidptr, errno)
|
//pub fn mm_alloc(size u64) (voidptr, errno)
|
||||||
|
|
||||||
fn check_mm_alloc() {
|
fn check_mm_alloc() {
|
||||||
println ("checking check_mm_alloc")
|
println ("checking mm_alloc")
|
||||||
|
|
||||||
for i in 1 .. 2000 {
|
for i in 1 .. 2000 {
|
||||||
size := u64(i*1000)
|
size := u64(i*1000)
|
||||||
|
@ -201,6 +201,107 @@ fn check_mm_alloc() {
|
||||||
println ("mm_alloc passed")
|
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() {
|
fn main() {
|
||||||
check_read_write_pipe()
|
check_read_write_pipe()
|
||||||
check_read_file()
|
check_read_file()
|
||||||
|
@ -210,5 +311,10 @@ fn main() {
|
||||||
check_mmap_one_page()
|
check_mmap_one_page()
|
||||||
check_mm_pages()
|
check_mm_pages()
|
||||||
check_mm_alloc()
|
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)
|
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:
|
// First argument to waitid:
|
||||||
pub enum wi_sys {
|
pub enum wi_which {
|
||||||
p_all = 0
|
p_all = 0
|
||||||
p_pid = 1
|
p_pid = 1
|
||||||
p_pgid = 2
|
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 {
|
pub enum fcntl {
|
||||||
fd_cloexec = 0x00000001
|
fd_cloexec = 0x00000001
|
||||||
f_dupfd = 0x00000000
|
f_dupfd = 0x00000000
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
//__global buffer [128]byte
|
|
||||||
|
|
||||||
pub fn mm_pages(size u64) u32 {
|
pub fn mm_pages(size u64) u32 {
|
||||||
pages := (u64(size+u64(4))+u64(linux_mem.page_size))/u64(linux_mem.page_size)
|
pages := (u64(size+u64(4))+u64(linux_mem.page_size))/u64(linux_mem.page_size)
|
||||||
return u32(pages)
|
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_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))
|
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)
|
a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0)
|
||||||
if e == .enoerror {
|
if e == .enoerror {
|
||||||
mut ap := intptr(a)
|
mut ap := intptr(a)
|
||||||
|
@ -37,20 +25,14 @@ pub fn mm_free(addr byteptr) errno {
|
||||||
ap := intptr(addr-4)
|
ap := intptr(addr-4)
|
||||||
size := u64(*ap) * u64(linux_mem.page_size)
|
size := u64(*ap) * u64(linux_mem.page_size)
|
||||||
|
|
||||||
//aps := i64_tos(buffer,80,i64(addr),16)
|
return sys_munmap(ap, size)
|
||||||
//println(aps)
|
}
|
||||||
|
|
||||||
//ss := i64_tos(buffer,80,i64(size),16)
|
pub fn mem_copy(dest0 voidptr, src0 voidptr, n int) voidptr {
|
||||||
//print("size out: ")
|
mut dest := byteptr(dest0)
|
||||||
//println(ss)
|
src := byteptr(src0)
|
||||||
|
for i in 0..n {
|
||||||
//pas := i64_tos(buffer,80,i64(ap),16)
|
dest[i] = src[i]
|
||||||
//println(pas)
|
}
|
||||||
|
return dest0
|
||||||
e := sys_munmap(ap, size)
|
|
||||||
|
|
||||||
//es := i64_tos(buffer,80,i64(e),16)
|
|
||||||
//println(es)
|
|
||||||
|
|
||||||
return e
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
fn test_syscallwrappers() {
|
fn test_syscallwrappers() {
|
||||||
if true {return}
|
if true { return }
|
||||||
vexe := os.getenv("VEXE")
|
$if linux {
|
||||||
vn := vexe.len - 1
|
$if x64 {
|
||||||
if vn > 1 {
|
exe := os.executable()
|
||||||
dot_checks := vexe.substr(0,vn) + "vlib/builtin/bare/.checks"
|
vdir := os.dir(exe)
|
||||||
assert os.dir_exists(dot_checks)
|
if vdir.len > 1 {
|
||||||
os.chdir(dot_checks)
|
dot_checks := vdir + "/.checks"
|
||||||
checks_v := "checks.v"
|
assert os.dir_exists(dot_checks)
|
||||||
assert os.file_exists(checks_v)
|
|
||||||
rc := os.exec("v run $checks_v") or { panic(err) }
|
os.chdir(dot_checks)
|
||||||
assert !rc.output.contains("V panic: An assertion failed.")
|
checks_v := "checks.v"
|
||||||
assert !rc.output.contains("failed")
|
assert os.file_exists(checks_v)
|
||||||
assert rc.exit_code == 0
|
rc := os.exec("v run $checks_v") or { panic(err) }
|
||||||
} else {
|
assert !rc.output.contains("V panic: An assertion failed.")
|
||||||
panic("Can't find v")
|
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'
|
v.out_name = v.out_name + '.so'
|
||||||
}
|
}
|
||||||
if v.pref.is_bare {
|
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 {
|
if v.pref.build_mode == .build_module {
|
||||||
// Create the modules & out directory if it's not there.
|
// Create the modules & out directory if it's not there.
|
||||||
|
@ -263,7 +263,7 @@ fn (v mut V) cc() {
|
||||||
a << libs
|
a << libs
|
||||||
// Without these libs compilation will fail on Linux
|
// Without these libs compilation will fail on Linux
|
||||||
// || os.user_os() == '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) {
|
v.os == .netbsd || v.os == .dragonfly || v.os == .solaris) {
|
||||||
a << '-lm -lpthread '
|
a << '-lm -lpthread '
|
||||||
// -ldl is a Linux only thing. BSDs have it in libc.
|
// -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'
|
a << '-lm'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,4 +206,17 @@ typedef map map_string;
|
||||||
#define false 0
|
#define false 0
|
||||||
#endif
|
#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 {
|
if !v.pref.is_bare {
|
||||||
cgen.genln(c_headers)
|
cgen.genln(c_headers)
|
||||||
|
} else {
|
||||||
|
cgen.genln(bare_c_headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.generate_hotcode_reloading_declarations()
|
v.generate_hotcode_reloading_declarations()
|
||||||
|
|
Loading…
Reference in New Issue