diff options
Diffstat (limited to 'src/lib/runtime/runtime.c')
-rw-r--r-- | src/lib/runtime/runtime.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/src/lib/runtime/runtime.c b/src/lib/runtime/runtime.c new file mode 100644 index 000000000..c5ba3e6a5 --- /dev/null +++ b/src/lib/runtime/runtime.c @@ -0,0 +1,462 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + +int32 panicking = 0; +int32 maxround = sizeof(uintptr); + +int32 +gotraceback(void) +{ + byte *p; + + p = getenv("GOTRACEBACK"); + if(p == nil || p[0] == '\0') + return 1; // default is on + return atoi(p); +} + +void +sys·panicl(int32 lno) +{ + uint8 *sp; + + if(panicking) { + printf("double panic\n"); + exit(3); + } + panicking++; + + printf("\npanic PC=%X\n", (uint64)(uintptr)&lno); + sp = (uint8*)&lno; + if(gotraceback()){ + traceback(sys·getcallerpc(&lno), sp, g); + tracebackothers(g); + } + breakpoint(); // so we can grab it in a debugger + exit(2); +} + +void +sys·throwindex(void) +{ + throw("index out of range"); +} + +void +sys·throwreturn(void) +{ + throw("no return at end of a typed function"); +} + +void +sys·throwinit(void) +{ + throw("recursive call during initialization"); +} + +void +throw(int8 *s) +{ + printf("throw: %s\n", s); + sys·panicl(-1); + *(int32*)0 = 0; // not reached + exit(1); // even more not reached +} + +void +mcpy(byte *t, byte *f, uint32 n) +{ + while(n > 0) { + *t = *f; + t++; + f++; + n--; + } +} + +int32 +mcmp(byte *s1, byte *s2, uint32 n) +{ + uint32 i; + byte c1, c2; + + for(i=0; i<n; i++) { + c1 = s1[i]; + c2 = s2[i]; + if(c1 < c2) + return -1; + if(c1 > c2) + return +1; + } + return 0; +} + + +void +mmov(byte *t, byte *f, uint32 n) +{ + if(t < f) { + while(n > 0) { + *t = *f; + t++; + f++; + n--; + } + } else { + t += n; + f += n; + while(n > 0) { + t--; + f--; + *t = *f; + n--; + } + } +} + +byte* +mchr(byte *p, byte c, byte *ep) +{ + for(; p < ep; p++) + if(*p == c) + return p; + return nil; +} + +uint32 +rnd(uint32 n, uint32 m) +{ + uint32 r; + + if(m > maxround) + m = maxround; + r = n % m; + if(r) + n += m-r; + return n; +} + +static int32 argc; +static uint8** argv; + +Array os·Args; +Array os·Envs; + +void +args(int32 c, uint8 **v) +{ + argc = c; + argv = v; +} + +void +goargs(void) +{ + String *gargv; + String *genvv; + int32 i, envc; + + for(envc=0; argv[argc+1+envc] != 0; envc++) + ; + + gargv = malloc(argc*sizeof gargv[0]); + genvv = malloc(envc*sizeof genvv[0]); + + for(i=0; i<argc; i++) + gargv[i] = gostring(argv[i]); + os·Args.array = (byte*)gargv; + os·Args.nel = argc; + os·Args.cap = argc; + + for(i=0; i<envc; i++) + genvv[i] = gostring(argv[argc+1+i]); + os·Envs.array = (byte*)genvv; + os·Envs.nel = envc; + os·Envs.cap = envc; +} + +byte* +getenv(int8 *s) +{ + int32 i, j, len; + byte *v, *bs; + String* envv; + int32 envc; + + bs = (byte*)s; + len = findnull(bs); + envv = (String*)os·Envs.array; + envc = os·Envs.nel; + for(i=0; i<envc; i++){ + if(envv[i].len <= len) + continue; + v = envv[i].str; + for(j=0; j<len; j++) + if(bs[j] != v[j]) + goto nomatch; + if(v[len] != '=') + goto nomatch; + return v+len+1; + nomatch:; + } + return nil; +} + + +int32 +atoi(byte *p) +{ + int32 n; + + n = 0; + while('0' <= *p && *p <= '9') + n = n*10 + *p++ - '0'; + return n; +} + +void +check(void) +{ + int8 a; + uint8 b; + int16 c; + uint16 d; + int32 e; + uint32 f; + int64 g; + uint64 h; + float32 i; + float64 j; + void* k; + uint16* l; + + if(sizeof(a) != 1) throw("bad a"); + if(sizeof(b) != 1) throw("bad b"); + if(sizeof(c) != 2) throw("bad c"); + if(sizeof(d) != 2) throw("bad d"); + if(sizeof(e) != 4) throw("bad e"); + if(sizeof(f) != 4) throw("bad f"); + if(sizeof(g) != 8) throw("bad g"); + if(sizeof(h) != 8) throw("bad h"); + if(sizeof(i) != 4) throw("bad i"); + if(sizeof(j) != 8) throw("bad j"); + if(sizeof(k) != sizeof(uintptr)) throw("bad k"); + if(sizeof(l) != sizeof(uintptr)) throw("bad l"); +// prints(1"check ok\n"); + + uint32 z; + z = 1; + if(!cas(&z, 1, 2)) + throw("cas1"); + if(z != 2) + throw("cas2"); + + z = 4; + if(cas(&z, 5, 6)) + throw("cas3"); + if(z != 4) + throw("cas4"); + + initsig(); +} + +/* + * map and chan helpers for + * dealing with unknown types + */ +static uintptr +memhash(uint32 s, void *a) +{ + byte *b; + uintptr hash; + + b = a; + if(sizeof(hash) == 4) + hash = 2860486313U; + else + hash = 33054211828000289ULL; + while(s > 0) { + if(sizeof(hash) == 4) + hash = (hash ^ *b) * 3267000013UL; + else + hash = (hash ^ *b) * 23344194077549503ULL; + b++; + s--; + } + return hash; +} + +static uint32 +memequal(uint32 s, void *a, void *b) +{ + byte *ba, *bb; + uint32 i; + + ba = a; + bb = b; + for(i=0; i<s; i++) + if(ba[i] != bb[i]) + return 0; + return 1; +} + +static void +memprint(uint32 s, void *a) +{ + uint64 v; + + v = 0xbadb00b; + switch(s) { + case 1: + v = *(uint8*)a; + break; + case 2: + v = *(uint16*)a; + break; + case 4: + v = *(uint32*)a; + break; + case 8: + v = *(uint64*)a; + break; + } + sys·printint(v); +} + +static void +memcopy(uint32 s, void *a, void *b) +{ + byte *ba, *bb; + uint32 i; + + ba = a; + bb = b; + if(bb == nil) { + for(i=0; i<s; i++) + ba[i] = 0; + return; + } + for(i=0; i<s; i++) + ba[i] = bb[i]; +} + +static uintptr +strhash(uint32 s, String *a) +{ + USED(s); + return memhash((*a).len, (*a).str); +} + +static uint32 +strequal(uint32 s, String *a, String *b) +{ + USED(s); + return cmpstring(*a, *b) == 0; +} + +static void +strprint(uint32 s, String *a) +{ + USED(s); + sys·printstring(*a); +} + +static uintptr +interhash(uint32 s, Iface *a) +{ + USED(s); + return ifacehash(*a); +} + +static void +interprint(uint32 s, Iface *a) +{ + USED(s); + sys·printiface(*a); +} + +static uint32 +interequal(uint32 s, Iface *a, Iface *b) +{ + USED(s); + return ifaceeq(*a, *b); +} + +static uintptr +nilinterhash(uint32 s, Eface *a) +{ + USED(s); + return efacehash(*a); +} + +static void +nilinterprint(uint32 s, Eface *a) +{ + USED(s); + sys·printeface(*a); +} + +static uint32 +nilinterequal(uint32 s, Eface *a, Eface *b) +{ + USED(s); + return efaceeq(*a, *b); +} + +uintptr +nohash(uint32 s, void *a) +{ + USED(s); + USED(a); + throw("hash of unhashable type"); + return 0; +} + +uint32 +noequal(uint32 s, void *a, void *b) +{ + USED(s); + USED(a); + USED(b); + throw("comparing uncomparable types"); + return 0; +} + +static void +noprint(uint32 s, void *a) +{ + USED(s); + USED(a); + throw("print of unprintable type"); +} + +static void +nocopy(uint32 s, void *a, void *b) +{ + USED(s); + USED(a); + USED(b); + throw("copy of uncopyable type"); +} + +Alg +algarray[] = +{ +[AMEM] { memhash, memequal, memprint, memcopy }, +[ANOEQ] { nohash, noequal, memprint, memcopy }, +[ASTRING] { strhash, strequal, strprint, memcopy }, +[AINTER] { interhash, interequal, interprint, memcopy }, +[ANILINTER] { nilinterhash, nilinterequal, nilinterprint, memcopy }, +[AFAKE] { nohash, noequal, noprint, nocopy }, +}; + +#pragma textflag 7 +void +FLUSH(void *v) +{ + USED(v); +} + |