| 1 | module builtin |
| 2 | |
| 3 | import dlmalloc |
| 4 | |
| 5 | __global global_allocator dlmalloc.Dlmalloc |
| 6 | |
| 7 | @[export: 'memcpy'] |
| 8 | @[unsafe] |
| 9 | pub fn memcpy(dest voidptr, const_src voidptr, n usize) voidptr { |
| 10 | dest_ := unsafe { &u8(dest) } |
| 11 | src_ := unsafe { &u8(const_src) } |
| 12 | unsafe { |
| 13 | for i in 0 .. int(n) { |
| 14 | dest_[i] = src_[i] |
| 15 | } |
| 16 | } |
| 17 | return unsafe { dest } |
| 18 | } |
| 19 | |
| 20 | @[export: 'malloc'] |
| 21 | @[unsafe] |
| 22 | fn __malloc(n usize) voidptr { |
| 23 | return unsafe { global_allocator.malloc(n) } |
| 24 | } |
| 25 | |
| 26 | @[export: 'strlen'] |
| 27 | @[unsafe] |
| 28 | fn strlen(const_s voidptr) usize { |
| 29 | s := unsafe { &u8(const_s) } |
| 30 | mut i := 0 |
| 31 | for ; unsafe { s[i] } != 0; i++ {} |
| 32 | return usize(i) |
| 33 | } |
| 34 | |
| 35 | @[export: 'realloc'] |
| 36 | @[unsafe] |
| 37 | fn realloc(old_area voidptr, new_size usize) voidptr { |
| 38 | if old_area == 0 { |
| 39 | return unsafe { malloc(int(new_size)) } |
| 40 | } |
| 41 | if new_size == usize(0) { |
| 42 | unsafe { free(old_area) } |
| 43 | return 0 |
| 44 | } |
| 45 | old_size := unsafe { *(&u64(&u64(old_area) - sizeof(u64))) } |
| 46 | if u64(new_size) <= old_size { |
| 47 | return unsafe { old_area } |
| 48 | } else { |
| 49 | new_area := unsafe { malloc(int(new_size)) } |
| 50 | unsafe { memmove(new_area, old_area, usize(old_size)) } |
| 51 | unsafe { free(old_area) } |
| 52 | return new_area |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | @[export: 'memset'] |
| 57 | @[unsafe] |
| 58 | fn memset(s voidptr, c int, n usize) voidptr { |
| 59 | mut s_ := unsafe { &char(s) } |
| 60 | for i in 0 .. int(n) { |
| 61 | unsafe { |
| 62 | s_[i] = char(c) |
| 63 | } |
| 64 | } |
| 65 | return unsafe { s } |
| 66 | } |
| 67 | |
| 68 | @[export: 'memmove'] |
| 69 | @[unsafe] |
| 70 | fn memmove(dest voidptr, const_src voidptr, n usize) voidptr { |
| 71 | dest_ := unsafe { &u8(dest) } |
| 72 | src_ := unsafe { &u8(const_src) } |
| 73 | mut temp_buf := unsafe { malloc(int(n)) } |
| 74 | for i in 0 .. int(n) { |
| 75 | unsafe { |
| 76 | temp_buf[i] = src_[i] |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | for i in 0 .. int(n) { |
| 81 | unsafe { |
| 82 | dest_[i] = temp_buf[i] |
| 83 | } |
| 84 | } |
| 85 | unsafe { free(temp_buf) } |
| 86 | return unsafe { dest } |
| 87 | } |
| 88 | |
| 89 | @[export: 'calloc'] |
| 90 | @[unsafe] |
| 91 | fn __calloc(nmemb usize, size usize) voidptr { |
| 92 | new_area := unsafe { malloc(int(nmemb) * int(size)) } |
| 93 | unsafe { memset(new_area, 0, nmemb * size) } |
| 94 | return new_area |
| 95 | } |
| 96 | |
| 97 | fn getchar() int { |
| 98 | x := u8(0) |
| 99 | sys_read(0, &x, 1) |
| 100 | return int(x) |
| 101 | } |
| 102 | |
| 103 | @[export: 'memcmp'] |
| 104 | fn memcmp(const_a voidptr, const_b voidptr, n usize) int { |
| 105 | a_ := unsafe { &u8(const_a) } |
| 106 | b_ := unsafe { &u8(const_b) } |
| 107 | for i in 0 .. int(n) { |
| 108 | if unsafe { a_[i] != b_[i] } { |
| 109 | unsafe { |
| 110 | return a_[i] - b_[i] |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | return 0 |
| 115 | } |
| 116 | |
| 117 | @[export: 'free'] |
| 118 | @[unsafe] |
| 119 | fn __free(ptr voidptr) { |
| 120 | unsafe { |
| 121 | global_allocator.free_(ptr) |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | fn vsprintf(str &char, format &char, ap &u8) int { |
| 126 | panic('vsprintf(): string interpolation is not supported in `-freestanding`') |
| 127 | } |
| 128 | |
| 129 | fn vsnprintf(str &char, size usize, format &char, ap &u8) int { |
| 130 | panic('vsnprintf(): string interpolation is not supported in `-freestanding`') |
| 131 | } |
| 132 | |
| 133 | // not really needed |
| 134 | fn bare_read(buf &u8, count u64) (i64, Errno) { |
| 135 | return sys_read(0, buf, count) |
| 136 | } |
| 137 | |
| 138 | pub fn bare_print(buf &u8, len u64) { |
| 139 | sys_write(1, buf, len) |
| 140 | } |
| 141 | |
| 142 | fn bare_eprint(buf &u8, len u64) { |
| 143 | sys_write(2, buf, len) |
| 144 | } |
| 145 | |
| 146 | pub fn write(fd i64, buf &u8, count u64) i64 { |
| 147 | x, _ := sys_write(fd, buf, count) |
| 148 | return x |
| 149 | } |
| 150 | |
| 151 | @[noreturn] |
| 152 | fn bare_panic(msg string) { |
| 153 | println('V panic' + msg) |
| 154 | exit(1) |
| 155 | } |
| 156 | |
| 157 | fn bare_backtrace() string { |
| 158 | return 'backtraces are not available with `-freestanding`' |
| 159 | } |
| 160 | |
| 161 | @[export: 'exit'] |
| 162 | @[noreturn] |
| 163 | fn __exit(code int) { |
| 164 | sys_exit(code) |
| 165 | } |
| 166 | |
| 167 | @[export: 'qsort'] |
| 168 | fn __qsort(base voidptr, nmemb usize, size usize, sort_cb FnSortCB) { |
| 169 | panic('qsort() is not yet implemented in `-freestanding`') |
| 170 | } |
| 171 | |
| 172 | fn init_global_allocator() { |
| 173 | global_allocator = dlmalloc.new(get_linux_allocator()) |
| 174 | } |
| 175 | |