diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index 0e5dafe9a2..fec3a603f9 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -60,7 +60,7 @@ isobjfile(char *f) n = Bread(b, buf1, 5); if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<')) v = 1; /* good enough for our purposes */ - else{ + else { Bseek(b, 0, 0); n = Bread(b, buf2, SARMAG); v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0; @@ -347,22 +347,27 @@ main(int argc, char *argv[]) lastp = firstp; if(INITENTRY == nil) { - INITENTRY = "_rt0"; - a = mal(strlen(INITENTRY)+strlen(goarch)+strlen(goos)+10); - strcpy(a, INITENTRY); - strcat(a, "_"); - strcat(a, goarch); - strcat(a, "_"); - strcat(a, goos); - INITENTRY = a; + INITENTRY = mal(strlen(goarch)+strlen(goos)+10); + sprint(INITENTRY, "_rt0_%s_%s", goarch, goos); } - lookup(INITENTRY, 0)->type = SXREF; + if(!debug['l']) { + a = mal(strlen(goroot)+strlen(goarch)+strlen(goos)+20); + sprint(a, "%s/lib/rt0_%s_%s.6", goroot, goarch, goos); + objfile(a); + } + while(*argv) objfile(*argv++); - if(!debug['l']) + + if(!debug['l']) { loadlib(); + a = mal(strlen(goroot)+strlen(goarch)+20); + sprint(a, "%s/lib/rt_%s.6", goroot, goarch); + objfile(a); + } + firstp = firstp->link; if(firstp == P) errorexit(); diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 1d77cc4c4f..4cd88d94db 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -321,6 +321,7 @@ struct Io EXTERN Io curio; EXTERN Io pushedio; +EXTERN char* infile; EXTERN char* outfile; EXTERN char* package; EXTERN Biobuf* bout; diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index d0edaa19c8..2ed4bd63e9 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -49,7 +49,8 @@ mainlex(int argc, char *argv[]) lexinit(); - curio.infile = argv[0]; + infile = argv[0]; + curio.infile = infile; curio.bin = Bopen(curio.infile, OREAD); if(curio.bin == nil) @@ -1066,6 +1067,7 @@ mkpackage(char* pkg) { Sym *s; long h; + char *p; if(bout != nil) { yyerror("mkpackage: called again %s %s", pkg, package); @@ -1082,7 +1084,16 @@ mkpackage(char* pkg) if(outfile == nil) { // BOTCH need to get .6 from backend - snprint(namebuf, sizeof(namebuf), "%s.6", package); + p = strrchr(infile, '/'); + if(p == nil) + p = infile; + else + p = p+1; + snprint(namebuf, sizeof(namebuf), "%s", p); + p = strrchr(namebuf, '.'); + if(p != nil) + *p = 0; + strncat(namebuf, ".6", sizeof(namebuf)); outfile = strdup(namebuf); } } diff --git a/src/runtime/make.bash b/src/runtime/make.bash new file mode 100644 index 0000000000..903607325f --- /dev/null +++ b/src/runtime/make.bash @@ -0,0 +1,14 @@ +# 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. + +set -ex + +6a rt0_amd64_darwin.s +mv rt0_amd64_darwin.6 ../../lib/rt0_amd64_darwin.6 + +6a rt0_amd64_linux.s +mv rt0_amd64_linux.6 ../../lib/rt0_amd64_linux.6 + +6c runtime.c +mv runtime.6 ../../lib/rt_amd64.6 diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c new file mode 100644 index 0000000000..c99333ba7b --- /dev/null +++ b/src/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/runtime/runtime.h b/src/runtime/runtime.h new file mode 100644 index 0000000000..65c3278e59 --- /dev/null +++ b/src/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*);