From df8ac289757a0ea0dcbe2ecb25dcbb24e79c3f41 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Wed, 4 Jun 2008 15:52:48 -0700 Subject: [PATCH] initial runtime code checkin SVN=121183 --- src/lib/runtime/runtime.c | 595 ++++++++++++++++++++++++++++++++++++++ src/lib/runtime/runtime.h | 107 +++++++ 2 files changed, 702 insertions(+) create mode 100644 src/lib/runtime/runtime.c create mode 100644 src/lib/runtime/runtime.h diff --git a/src/lib/runtime/runtime.c b/src/lib/runtime/runtime.c new file mode 100644 index 00000000000..c99333ba7bc --- /dev/null +++ b/src/lib/runtime/runtime.c @@ -0,0 +1,595 @@ +// 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 debug = 0; + +void +sys_printbool(bool v) +{ + if(v) { + sys_write(1, (byte*)"true", 4); + return; + } + sys_write(1, (byte*)"false", 5); +} + +void +sys_printfloat(float64 v) +{ + sys_write(1, "printfloat", 10); +} + +void +sys_printint(int64 v) +{ + byte buf[100]; + int32 i, s; + + s = 0; + if(v < 0) { + v = -v; + s = 1; + if(v < 0) { + sys_write(1, (byte*)"-oo", 3); + return; + } + } + + for(i=nelem(buf)-1; i>0; i--) { + buf[i] = v%10 + '0'; + if(v < 10) + break; + v = v/10; + } + if(s) { + i--; + buf[i] = '-'; + } + sys_write(1, buf+i, nelem(buf)-i); +} + +void +sys_printpointer(void *p) +{ + uint64 v; + byte buf[100]; + int32 i; + + v = (int64)p; + for(i=nelem(buf)-1; i>0; i--) { + buf[i] = v%16 + '0'; + if(buf[i] > '9') + buf[i] += 'a'-'0'-10; + if(v < 16) + break; + v = v/16; + } + sys_write(1, buf+i, nelem(buf)-i); +} + +void +sys_panicl(int32 lno) +{ + prints("\npanic on line "); + sys_printint(lno); + prints("\n"); + *(int32*)0 = 0; +} + +void +sys_printstring(string v) +{ + sys_write(1, v->str, v->len); +} + +int32 +strlen(int8 *s) +{ + int32 l; + + for(l=0; s[l]!=0; l++) + ; + return l; +} + +void +prints(int8 *s) +{ + sys_write(1, s, strlen(s)); +} + +dump(byte *p, int32 n) +{ + uint32 v; + int32 i; + + for(i=0; i>4)); + sys_printpointer((byte*)(p[i]&0xf)); + if((i&15) == 15) + prints("\n"); + else + prints(" "); + } + if(n & 15) + prints("\n"); +} + +static uint8* hunk; +static uint32 nhunk; +static uint64 nmmap; +static uint64 nmal; +enum +{ + NHUNK = 20<<20, + + PROT_NONE = 0x00, + PROT_READ = 0x01, + PROT_WRITE = 0x02, + PROT_EXEC = 0x04, + + MAP_FILE = 0x0000, + MAP_SHARED = 0x0001, + MAP_PRIVATE = 0x0002, + MAP_FIXED = 0x0010, + MAP_ANON = 0x1000, +}; + +static void +throw(int8 *s) +{ + prints("throw: "); + prints(s); + prints("\n"); + sys_exit(1); +} + +static void +mcpy(byte *t, byte *f, uint32 n) +{ + while(n > 0) { + *t = *f; + t++; + f++; + n--; + } +} + +static byte* +brk(uint32 n) +{ + byte* v; + + v = sys_mmap(nil, NHUNK, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); + sys_memclr(v, n); + nmmap += n; + return v; +} + +static void* +mal(uint32 n) +{ + byte* v; + + // round to keep everything 64-bit alligned + while(n & 7) + n++; + + nmal += n; + + // do we have enough in contiguous hunk + if(n > nhunk) { + + // if it is big allocate it separately + if(n > NHUNK) + return brk(n); + + // allocate a new contiguous hunk + hunk = brk(NHUNK); + nhunk = NHUNK; + } + + // allocate from the contiguous hunk + v = hunk; + hunk += n; + nhunk -= n; + return v; +} + +void +sys_mal(uint32 n, uint8 *ret) +{ + ret = mal(n); + FLUSH(&ret); +} + +void +sys_catstring(string s1, string s2, string s3) +{ + uint32 l; + + if(s1->len == 0) { + s3 = s2; + goto out; + } + if(s2->len == 0) { + s3 = s1; + goto out; + } + + l = s1->len + s2->len; + + s3 = mal(sizeof(s3->len)+l); + s3->len = l; + mcpy(s3->str, s1->str, s1->len); + mcpy(s3->str+s1->len, s2->str, s2->len); + +out: + FLUSH(&s3); +} + +void +sys_cmpstring(string s1, string s2, int32 v) +{ + uint32 i, l; + byte c1, c2; + + l = s1->len; + if(s2->len < l) + l = s2->len; + for(i=0; istr[i]; + c2 = s2->str[i]; + if(c1 < c2) { + v = -1; + goto out; + } + if(c1 > c2) { + v = +1; + goto out; + } + } + if(s1->len < s2->len) { + v = -1; + goto out; + } + if(s1->len > s2->len) { + v = +1; + goto out; + } + v = 0; + +out: + FLUSH(&v); +} + +static int32 +strcmp(byte *s1, byte *s2) +{ + uint32 i; + byte c1, c2; + + for(i=0;; i++) { + c1 = s1[i]; + c2 = s2[i]; + if(c1 < c2) + return -1; + if(c1 > c2) + return +1; + if(c1 == 0) + return 0; + } +} + +static void +prbounds(int8* s, int32 a, int32 b, int32 c) +{ + int32 i; + + prints(s); + prints(" "); + sys_printint(a); + prints("<"); + sys_printint(b); + prints(">"); + sys_printint(c); + prints("\n"); + throw("bounds"); +} + +void +sys_slicestring(string si, int32 lindex, int32 hindex, string so) +{ + string s, str; + int32 l; + + if(lindex < 0 || lindex > si->len || + hindex < lindex || hindex > si->len) + prbounds("slice", lindex, si->len, hindex); + + l = hindex-lindex; + so = mal(sizeof(so->len)+l); + so->len = l; + mcpy(so->str, si->str+lindex, l); + FLUSH(&so); +} + +void +sys_indexstring(string s, int32 i, byte b) +{ + if(i < 0 || i >= s->len) + prbounds("index", 0, i, s->len); + + b = s->str[i]; + FLUSH(&b); +} + +/* + * this is the plan9 runetochar + * extended for 36 bits in 7 bytes + * note that it truncates to 32 bits + * through the argument passing. + */ +static int32 +runetochar(byte *str, uint32 c) +{ + int32 i, n; + uint32 mask, mark; + + /* + * one character in 7 bits + */ + if(c <= 0x07FUL) { + str[0] = c; + return 1; + } + + /* + * every new character picks up 5 bits + * one less in the first byte and + * six more in an extension byte + */ + mask = 0x7ffUL; + mark = 0xC0UL; + for(n=1;; n++) { + if(c <= mask) + break; + mask = (mask<<5) | 0x1fUL; + mark = (mark>>1) | 0x80UL; + } + + /* + * lay down the bytes backwards + * n is the number of extension bytes + * mask is the max codepoint + * mark is the zeroth byte indicator + */ + for(i=n; i>0; i--) { + str[i] = 0x80UL | (c&0x3fUL); + c >>= 6; + } + + str[0] = mark|c; + return n+1; +} + +void +sys_intstring(int64 v, string s) +{ + int32 l; + + s = mal(sizeof(s->len)+8); + s->len = runetochar(s->str, v); + FLUSH(&s); +} + +void +sys_byteastring(byte *a, int32 l, string s) +{ + s = mal(sizeof(s->len)+l); + s->len = l; + mcpy(s->str, a, l); + FLUSH(&s); +} + +static Map* hash[1009]; + +static Map* +hashmap(Sigi *si, Sigs *ss) +{ + int32 ns, ni; + uint32 ihash, h; + byte *sname, *iname; + Map *m; + + h = ((uint32)si + (uint32)ss) % nelem(hash); + for(m=hash[h]; m!=nil; m=m->link) { + if(m->si == si && m->ss == ss) { + if(m->bad) { + throw("bad hashmap"); + m = nil; + } + // prints("old hashmap\n"); + return m; + } + } + + ni = si[0].offset; // first word has size + m = mal(sizeof(*m) + ni*sizeof(m->fun[0])); + m->si = si; + m->ss = ss; + + ni = 1; // skip first word + ns = 0; + +loop1: + // pick up next name from + // interface signature + iname = si[ni].name; + if(iname == nil) { + m->link = hash[h]; + hash[h] = m; + // prints("new hashmap\n"); + return m; + } + ihash = si[ni].hash; + +loop2: + // pick up and comapre next name + // from structure signature + sname = ss[ns].name; + if(sname == nil) { + prints((int8*)iname); + prints(": "); + throw("hashmap: failed to find method"); + m->bad = 1; + m->link = hash[h]; + hash[h] = m; + return nil; + } + if(ihash != ss[ns].hash || + strcmp(sname, iname) != 0) { + ns++; + goto loop2; + } + + m->fun[si[ni].offset] = ss[ns].fun; + ni++; + goto loop1; +} + +void +sys_ifaces2i(Sigi *si, Sigs *ss, Map *m, void *s) +{ + + if(debug) { + prints("s2i sigi="); + sys_printpointer(si); + prints(" sigs="); + sys_printpointer(ss); + prints(" s="); + sys_printpointer(s); + } + + if(s == nil) { + throw("ifaces2i: nil pointer"); + m = nil; + FLUSH(&m); + return; + } + + m = hashmap(si, ss); + + if(debug) { + prints(" returning m="); + sys_printpointer(m); + prints(" s="); + sys_printpointer(s); + prints("\n"); + dump((byte*)m, 64); + } + + FLUSH(&m); +} + +void +sys_ifacei2i(Sigi *si, Map *m, void *s) +{ + + if(debug) { + prints("i2i sigi="); + sys_printpointer(si); + prints(" m="); + sys_printpointer(m); + prints(" s="); + sys_printpointer(s); + } + + if(m == nil) { + throw("ifacei2i: nil map"); + s = nil; + FLUSH(&s); + return; + } + + if(m->si == nil) { + throw("ifacei2i: nil pointer"); + return; + } + + if(m->si != si) { + m = hashmap(si, m->ss); + FLUSH(&m); + } + + if(debug) { + prints(" returning m="); + sys_printpointer(m); + prints(" s="); + sys_printpointer(s); + prints("\n"); + dump((byte*)m, 64); + } +} + +void +sys_ifacei2s(Sigs *ss, Map *m, void *s) +{ + + if(debug) { + prints("i2s m="); + sys_printpointer(m); + prints(" s="); + sys_printpointer(s); + prints("\n"); + } + + if(m == nil) { + throw("ifacei2s: nil map"); + s = nil; + FLUSH(&s); + return; + } + + if(m->ss != ss) { + dump((byte*)m, 64); + throw("ifacei2s: wrong pointer"); + s = nil; + FLUSH(&s); + return; + } +} + +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) != 8) throw("bad k"); + if(sizeof(l) != 8) throw("bad l"); +// prints(1"check ok\n"); +} diff --git a/src/lib/runtime/runtime.h b/src/lib/runtime/runtime.h new file mode 100644 index 00000000000..65c3278e599 --- /dev/null +++ b/src/lib/runtime/runtime.h @@ -0,0 +1,107 @@ +// 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. + + +/* + * basic types + */ +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; +typedef signed long long int int64; +typedef unsigned long long int uint64; +typedef float float32; +typedef double float64; + +/* + * get rid of C types + */ +#define unsigned XXunsigned +#define signed XXsigned +#define char XXchar +#define short XXshort +#define int XXint +#define long XXlong +#define float XXfloat +#define double XXdouble + +/* + * defined types + */ +typedef uint8 bool; +typedef uint8 byte; +typedef struct +{ + int32 len; + byte str[1]; +} *string; +typedef struct +{ + byte* name; + uint32 hash; + void (*fun)(void); +} Sigs; +typedef struct +{ + byte* name; + uint32 hash; + uint32 offset; +} Sigi; +typedef struct Map Map; +struct Map +{ + Sigi* si; + Sigs* ss; + Map* link; + int32 bad; + int32 unused; + void (*fun[])(void); +}; + +/* + * defined constants + */ +enum +{ + true = 1, + false = 0, +}; + +/* + * defined macros + * you need super-goru privilege + * to add this list. + */ +#define nelem(x) (sizeof(x)/sizeof((x)[0])) +#define nil ((void*)0) + +/* + * very low level + */ +void FLUSH(void*); +void prints(int8*); +void sys_exit(int32); +void sys_write(int32, void*, int32); +void sys_breakpoint(void); +uint8* sys_mmap(byte*, uint32, int32, int32, int32, uint32); +void sys_memclr(byte*, uint32); + +/* + * runtime + */ +void sys_printbool(bool); +void sys_printfloat(float64); +void sys_printint(int64); +void sys_printstring(string); +void sys_catstring(string, string, string); +void sys_cmpstring(string, string, int32); +void sys_slicestring(string, int32, int32, string); +void sys_indexstring(string, int32, byte); +void sys_intstring(int64, string); +void sys_ifaces2i(Sigi*, Sigs*, Map*, void*); +void sys_ifacei2i(Sigi*, Map*, void*); +void sys_ifacei2s(Sigs*, Map*, void*);