github.com/DQNEO/babygo@v0.0.3/src/runtime/runtime.go (about) 1 // runtime for 2nd generation compiler 2 package runtime 3 4 import "unsafe" 5 6 const heapSize uintptr = 620205360 7 8 var heapHead uintptr 9 var heapCurrent uintptr 10 var heapTail uintptr 11 12 const SYS_BRK int = 12 13 const SYS_EXIT int = 60 14 15 var __argv__ []*uint8 // C argv 16 17 // Environment variables 18 var envp uintptr 19 var envlines []string // []{"FOO=BAR\0", "HOME=/home/...\0", ..} 20 21 type envEntry struct { 22 key string 23 value string 24 } 25 26 var Envs []*envEntry 27 28 func heapInit() { 29 heapHead = brk(0) 30 heapTail = brk(heapHead + heapSize) 31 heapCurrent = heapHead 32 } 33 34 // Inital stack layout is illustrated in this page 35 // http://asm.sourceforge.net/articles/startup.html#st 36 func envInit() { 37 var p uintptr // **byte 38 39 for p = envp; true; p = p + 8 { 40 var bpp **byte = (**byte)(unsafe.Pointer(p)) 41 if *bpp == nil { 42 break 43 } 44 envlines = append(envlines, cstring2string(*bpp)) 45 } 46 47 for _, envline := range envlines { 48 var i int 49 var c byte 50 for i, c = range []byte(envline) { 51 if c == '=' { 52 break 53 } 54 } 55 key := envline[:i] 56 value := envline[i+1:] 57 58 entry := &envEntry{ 59 key: key, 60 value: value, 61 } 62 Envs = append(Envs, entry) 63 64 } 65 } 66 67 func runtime_getenv(key string) string { 68 for _, e := range Envs { 69 if e.key == key { 70 return e.value 71 } 72 } 73 74 return "" 75 } 76 77 func cstring2string(b *uint8) string { 78 var buf []uint8 79 for { 80 if b == nil || *b == 0 { 81 break 82 } 83 buf = append(buf, *b) 84 var p uintptr = uintptr(unsafe.Pointer(b)) + 1 85 b = (*uint8)(unsafe.Pointer(p)) 86 } 87 return string(buf) 88 } 89 90 // create os.Args 91 func runtime_args() []string { 92 var a *uint8 93 var r []string 94 for _, a = range __argv__ { 95 var s string = cstring2string(a) 96 r = append(r, s) 97 } 98 99 return r 100 } 101 102 func brk(addr uintptr) uintptr { 103 var ret uintptr 104 ret = Syscall(uintptr(SYS_BRK), addr, uintptr(0), uintptr(0)) 105 return ret 106 } 107 108 func panic(ifc interface{}) { 109 switch x := ifc.(type) { 110 case string: 111 var s = "panic: " + x + "\n\n" 112 Write(2, []uint8(s)) 113 Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0)) 114 default: 115 var s = "panic: " + "Unknown type" + "\n\n" 116 Write(2, []uint8(s)) 117 Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0)) 118 } 119 } 120 121 func memzeropad(addr1 uintptr, size uintptr) { 122 var p *uint8 = (*uint8)(unsafe.Pointer(addr1)) 123 var isize int = int(size) 124 var i int 125 var up uintptr 126 for i = 0; i < isize; i++ { 127 *p = 0 128 up = uintptr(unsafe.Pointer(p)) + 1 129 p = (*uint8)(unsafe.Pointer(up)) 130 } 131 } 132 133 func memcopy(src uintptr, dst uintptr, length int) { 134 var i int 135 var srcp *uint8 136 var dstp *uint8 137 for i = 0; i < length; i++ { 138 srcp = (*uint8)(unsafe.Pointer(src + uintptr(i))) 139 dstp = (*uint8)(unsafe.Pointer(dst + uintptr(i))) 140 *dstp = *srcp 141 } 142 } 143 144 func malloc(size uintptr) uintptr { 145 if heapCurrent+size > heapTail { 146 Write(2, []uint8("malloc exceeded heap max")) 147 Syscall(uintptr(SYS_EXIT), 1, uintptr(0), uintptr(0)) 148 return 0 149 } 150 var r uintptr 151 r = heapCurrent 152 heapCurrent = heapCurrent + size 153 memzeropad(r, size) 154 return r 155 } 156 157 func makeSlice(elmSize int, slen int, scap int) (uintptr, int, int) { 158 var size uintptr = uintptr(elmSize * scap) 159 var addr uintptr = malloc(size) 160 return addr, slen, scap 161 } 162 163 func append1(old []uint8, elm uint8) (uintptr, int, int) { 164 var new_ []uint8 165 var elmSize int = 1 166 167 var oldlen int = len(old) 168 var newlen int = oldlen + 1 169 170 if cap(old) >= newlen { 171 new_ = old[0:newlen] 172 } else { 173 var newcap int 174 if oldlen == 0 { 175 newcap = 1 176 } else { 177 newcap = oldlen * 2 178 } 179 new_ = makeSlice1(elmSize, newlen, newcap) 180 var oldSize int = oldlen * elmSize 181 if oldlen > 0 { 182 memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize) 183 } 184 } 185 186 new_[oldlen] = elm 187 return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_) 188 } 189 190 func append8(old []int, elm int) (uintptr, int, int) { 191 var new_ []int 192 var elmSize int = 8 193 194 var oldlen int = len(old) 195 var newlen int = oldlen + 1 196 197 if cap(old) >= newlen { 198 new_ = old[0:newlen] 199 } else { 200 var newcap int 201 if oldlen == 0 { 202 newcap = 1 203 } else { 204 newcap = oldlen * 2 205 } 206 new_ = makeSlice8(elmSize, newlen, newcap) 207 var oldSize int = oldlen * elmSize 208 if oldlen > 0 { 209 memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize) 210 } 211 } 212 213 new_[oldlen] = elm 214 return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_) 215 } 216 217 func append16(old []string, elm string) (uintptr, int, int) { 218 var new_ []string 219 var elmSize int = 16 220 221 var oldlen int = len(old) 222 var newlen int = oldlen + 1 223 224 if cap(old) >= newlen { 225 new_ = old[0:newlen] 226 } else { 227 var newcap int 228 if oldlen == 0 { 229 newcap = 1 230 } else { 231 newcap = oldlen * 2 232 } 233 new_ = makeSlice16(elmSize, newlen, newcap) 234 var oldSize int = oldlen * elmSize 235 if oldlen > 0 { 236 memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize) 237 } 238 } 239 240 new_[oldlen] = elm 241 return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_) 242 } 243 244 func append24(old [][]int, elm []int) (uintptr, int, int) { 245 var new_ [][]int 246 var elmSize int = 24 247 248 var oldlen int = len(old) 249 var newlen int = oldlen + 1 250 251 if cap(old) >= newlen { 252 new_ = old[0:newlen] 253 } else { 254 var newcap int 255 if oldlen == 0 { 256 newcap = 1 257 } else { 258 newcap = oldlen * 2 259 } 260 new_ = makeSlice24(elmSize, newlen, newcap) 261 var oldSize int = oldlen * elmSize 262 if oldlen > 0 { 263 memcopy(uintptr(unsafe.Pointer(&old[0])), uintptr(unsafe.Pointer(&new_[0])), oldSize) 264 } 265 } 266 267 new_[oldlen] = elm 268 return uintptr(unsafe.Pointer(&new_[0])), newlen, cap(new_) 269 } 270 271 func catstrings(a string, b string) string { 272 var totallen = len(a) + len(b) 273 var r = make([]uint8, totallen, totallen+1) // +1 is a workaround for syscall.Open. see runtime.s 274 var i int 275 for i = 0; i < len(a); i = i + 1 { 276 r[i] = a[i] 277 } 278 var j int 279 for j = 0; j < len(b); j = j + 1 { 280 r[i+j] = b[j] 281 } 282 return string(r) 283 } 284 285 func cmpstrings(a string, b string) bool { 286 if len(a) != len(b) { 287 return false 288 } 289 var i int 290 for i = 0; i < len(a); i++ { 291 if a[i] != b[i] { 292 return false 293 } 294 } 295 return true 296 } 297 298 // Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil. 299 func cmpinterface(a uintptr, b uintptr, c uintptr, d uintptr) bool { 300 if a == c && b == d { 301 return true 302 } 303 return false 304 } 305 306 func Write(fd int, p []byte) int 307 func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) uintptr 308 309 // Actually this is an alias to makeSlice 310 func makeSlice1(elmSize int, slen int, scap int) []uint8 311 func makeSlice8(elmSize int, slen int, scap int) []int 312 func makeSlice16(elmSize int, slen int, scap int) []string 313 func makeSlice24(elmSize int, slen int, scap int) [][]int