// 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"); }