| 1 | module builtin |
| 2 | |
| 3 | //__global global_allocator dlmalloc.Dlmalloc |
| 4 | |
| 5 | @[unsafe] |
| 6 | pub fn __malloc(size usize) voidptr { |
| 7 | unsafe { |
| 8 | $if windows { |
| 9 | // Warning! On windows, we always use _aligned_malloc to allocate memory. |
| 10 | // This ensures that we can later free the memory with _aligned_free |
| 11 | // without needing to track whether the memory was originally allocated |
| 12 | // by malloc or _aligned_malloc. |
| 13 | return C._aligned_malloc(size, 1) |
| 14 | } $else { |
| 15 | return C.malloc(int(size)) |
| 16 | } |
| 17 | } |
| 18 | return unsafe { nil } |
| 19 | } |
| 20 | |
| 21 | @[unsafe] |
| 22 | pub fn memcpy(dest &C.void, const_src &C.void, n usize) &C.void { |
| 23 | dest_ := unsafe { &u8(dest) } |
| 24 | src_ := unsafe { &u8(const_src) } |
| 25 | unsafe { |
| 26 | for i in 0 .. int(n) { |
| 27 | dest_[i] = src_[i] |
| 28 | } |
| 29 | } |
| 30 | return unsafe { dest } |
| 31 | } |
| 32 | |
| 33 | @[unsafe] |
| 34 | fn strlen(const_s &char) usize { |
| 35 | s := unsafe { &u8(const_s) } |
| 36 | mut i := 0 |
| 37 | for ; unsafe { s[i] } != 0; i++ {} |
| 38 | return usize(i) |
| 39 | } |
| 40 | |
| 41 | @[unsafe] |
| 42 | fn realloc(old_area &C.void, new_size usize) &C.void { |
| 43 | if old_area == 0 { |
| 44 | return unsafe { malloc(int(new_size)) } |
| 45 | } |
| 46 | if new_size == usize(0) { |
| 47 | unsafe { free(old_area) } |
| 48 | return 0 |
| 49 | } |
| 50 | old_size := unsafe { *(&u64(old_area - sizeof(u64))) } |
| 51 | if u64(new_size) <= old_size { |
| 52 | return unsafe { old_area } |
| 53 | } else { |
| 54 | new_area := unsafe { malloc(int(new_size)) } |
| 55 | unsafe { memmove(new_area, old_area, usize(old_size)) } |
| 56 | unsafe { free(old_area) } |
| 57 | return new_area |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | @[unsafe] |
| 62 | fn memset(s &C.void, c int, n usize) &C.void { |
| 63 | mut s_ := unsafe { &char(s) } |
| 64 | for i in 0 .. int(n) { |
| 65 | unsafe { |
| 66 | s_[i] = char(c) |
| 67 | } |
| 68 | } |
| 69 | return unsafe { s } |
| 70 | } |
| 71 | |
| 72 | @[unsafe] |
| 73 | fn memmove(dest &C.void, const_src &C.void, n usize) &C.void { |
| 74 | dest_ := unsafe { &u8(dest) } |
| 75 | src_ := unsafe { &u8(const_src) } |
| 76 | mut temp_buf := unsafe { malloc(int(n)) } |
| 77 | for i in 0 .. int(n) { |
| 78 | unsafe { |
| 79 | temp_buf[i] = src_[i] |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | for i in 0 .. int(n) { |
| 84 | unsafe { |
| 85 | dest_[i] = temp_buf[i] |
| 86 | } |
| 87 | } |
| 88 | unsafe { free(temp_buf) } |
| 89 | return unsafe { dest } |
| 90 | } |
| 91 | |
| 92 | @[export: 'calloc'] |
| 93 | @[unsafe] |
| 94 | fn __calloc(nmemb usize, size usize) &C.void { |
| 95 | new_area := unsafe { malloc(int(nmemb) * int(size)) } |
| 96 | unsafe { memset(new_area, 0, nmemb * size) } |
| 97 | return new_area |
| 98 | } |
| 99 | |
| 100 | fn getchar() int { |
| 101 | return 0 |
| 102 | } |
| 103 | |
| 104 | fn memcmp(const_a &C.void, const_b &C.void, 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 | fn vsprintf(str &char, format &char, ap &u8) int { |
| 118 | panic('vsprintf(): string interpolation is not supported in `-freestanding`') |
| 119 | } |
| 120 | |
| 121 | fn vsnprintf(str &char, size usize, format &char, ap &u8) int { |
| 122 | panic('vsnprintf(): string interpolation is not supported in `-freestanding`') |
| 123 | } |
| 124 | |
| 125 | enum Errno { |
| 126 | enoerror |
| 127 | eerror |
| 128 | } |
| 129 | |
| 130 | // not really needed |
| 131 | fn bare_read(buf &u8, count u64) (i64, Errno) { |
| 132 | return 0, Errno.eerror |
| 133 | } |
| 134 | |
| 135 | pub fn bare_print(buf &u8, len u64) { |
| 136 | } |
| 137 | |
| 138 | fn bare_eprint(buf &u8, len u64) { |
| 139 | } |
| 140 | |
| 141 | pub fn write(_fd i64, _buf &u8, _count u64) i64 { |
| 142 | return -1 |
| 143 | } |
| 144 | |
| 145 | @[noreturn] |
| 146 | fn bare_panic(msg string) { |
| 147 | println('V panic' + msg) |
| 148 | exit(1) |
| 149 | } |
| 150 | |
| 151 | fn bare_backtrace() string { |
| 152 | return 'backtraces are not available with `-freestanding`' |
| 153 | } |
| 154 | |
| 155 | @[export: 'exit'] |
| 156 | @[noreturn] |
| 157 | fn __exit(code int) { |
| 158 | unsafe { |
| 159 | // the only way to abort process execution in WASM |
| 160 | mut x := &int(nil) |
| 161 | *x = code |
| 162 | } |
| 163 | for {} |
| 164 | } |
| 165 | |
| 166 | @[export: 'qsort'] |
| 167 | fn __qsort(base voidptr, nmemb usize, size usize, sort_cb FnSortCB) { |
| 168 | panic('qsort() is not yet implemented in `-freestanding`') |
| 169 | } |
| 170 | |