diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /src/cmd/gc/obj.c | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-upstream/60.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/cmd/gc/obj.c')
-rw-r--r-- | src/cmd/gc/obj.c | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c new file mode 100644 index 000000000..456aabb88 --- /dev/null +++ b/src/cmd/gc/obj.c @@ -0,0 +1,301 @@ +// 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 "go.h" + +/* + * architecture-independent object file output + */ + +static void outhist(Biobuf *b); +static void dumpglobls(void); + +void +dumpobj(void) +{ + bout = Bopen(outfile, OWRITE); + if(bout == nil) { + flusherrors(); + print("can't create %s: %r\n", outfile); + errorexit(); + } + + Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); + Bprint(bout, " exports automatically generated from\n"); + Bprint(bout, " %s in package \"%s\"\n", curio.infile, localpkg->name); + dumpexport(); + Bprint(bout, "\n!\n"); + + outhist(bout); + + // add nil plist w AEND to catch + // auto-generated trampolines, data + newplist(); + + dumpglobls(); + dumptypestructs(); + dumpdata(); + dumpfuncs(); + + Bterm(bout); +} + +static void +dumpglobls(void) +{ + Node *n; + NodeList *l; + + // add globals + for(l=externdcl; l; l=l->next) { + n = l->n; + if(n->op != ONAME) + continue; + + if(n->type == T) + fatal("external %#N nil type\n", n); + if(n->class == PFUNC) + continue; + if(n->sym->pkg != localpkg) + continue; + dowidth(n->type); + + ggloblnod(n, n->type->width); + } +} + +void +Bputname(Biobuf *b, Sym *s) +{ + Bprint(b, "%s", s->pkg->prefix); + Bputc(b, '.'); + Bwrite(b, s->name, strlen(s->name)+1); +} + +static void +outzfile(Biobuf *b, char *p) +{ + char *q, *q2; + + while(p) { + q = utfrune(p, '/'); + if(windows) { + q2 = utfrune(p, '\\'); + if(q2 && (!q || q2 < q)) + q = q2; + } + if(!q) { + zfile(b, p, strlen(p)); + return; + } + if(q > p) + zfile(b, p, q-p); + p = q + 1; + } +} + +#define isdelim(c) (c == '/' || c == '\\') + +static void +outwinname(Biobuf *b, Hist *h, char *ds, char *p) +{ + if(isdelim(p[0])) { + // full rooted name + zfile(b, ds, 3); // leading "c:/" + outzfile(b, p+1); + } else { + // relative name + if(h->offset == 0 && pathname && pathname[1] == ':') { + if(tolowerrune(ds[0]) == tolowerrune(pathname[0])) { + // using current drive + zfile(b, pathname, 3); // leading "c:/" + outzfile(b, pathname+3); + } else { + // using drive other then current, + // we don't have any simple way to + // determine current working directory + // there, therefore will output name as is + zfile(b, ds, 2); // leading "c:" + } + } + outzfile(b, p); + } +} + +static void +outhist(Biobuf *b) +{ + Hist *h; + int i, depth = 0; + char *p, ds[] = {'c', ':', '/', 0}; + + for(h = hist; h != H; h = h->link) { + p = h->name; + if(p) { + if(windows) { + // if windows variable is set, then, we know already, + // pathname is started with windows drive specifier + // and all '\' were replaced with '/' (see lex.c) + if(isdelim(p[0]) && isdelim(p[1])) { + // file name has network name in it, + // like \\server\share\dir\file.go + zfile(b, "//", 2); // leading "//" + outzfile(b, p+2); + } else if(p[1] == ':') { + // file name has drive letter in it + ds[0] = p[0]; + outwinname(b, h, ds, p+2); + } else { + // no drive letter in file name + outwinname(b, h, pathname, p); + } + } else { + if(p[0] == '/') { + // full rooted name, like /home/rsc/dir/file.go + zfile(b, "/", 1); // leading "/" + outzfile(b, p+1); + } else { + // relative name, like dir/file.go + if(h->offset >= 0 && pathname && pathname[0] == '/') { + zfile(b, "/", 1); // leading "/" + outzfile(b, pathname+1); + } + outzfile(b, p); + } + } + if(h->offset > 0) { + //line directive + depth++; + } + } else if(depth > 0) { + for(i = 0; i < depth; i++) + zhist(b, h->line, h->offset); + depth = 0; + } + zhist(b, h->line, h->offset); + } +} + +void +ieeedtod(uint64 *ieee, double native) +{ + double fr, ho, f; + int exp; + uint32 h, l; + uint64 bits; + + if(native < 0) { + ieeedtod(ieee, -native); + *ieee |= 1ULL<<63; + return; + } + if(native == 0) { + *ieee = 0; + return; + } + fr = frexp(native, &exp); + f = 2097152L; /* shouldnt use fp constants here */ + fr = modf(fr*f, &ho); + h = ho; + h &= 0xfffffL; + f = 65536L; + fr = modf(fr*f, &ho); + l = ho; + l <<= 16; + l |= (int32)(fr*f); + bits = ((uint64)h<<32) | l; + if(exp < -1021) { + // gradual underflow + bits |= 1LL<<52; + bits >>= -1021 - exp; + exp = -1022; + } + bits |= (uint64)(exp+1022L) << 52; + *ieee = bits; +} + +int +duint8(Sym *s, int off, uint8 v) +{ + return duintxx(s, off, v, 1); +} + +int +duint16(Sym *s, int off, uint16 v) +{ + return duintxx(s, off, v, 2); +} + +int +duint32(Sym *s, int off, uint32 v) +{ + return duintxx(s, off, v, 4); +} + +int +duint64(Sym *s, int off, uint64 v) +{ + return duintxx(s, off, v, 8); +} + +int +duintptr(Sym *s, int off, uint64 v) +{ + return duintxx(s, off, v, widthptr); +} + +Sym* +stringsym(char *s, int len) +{ + static int gen; + Sym *sym; + int off, n, m; + struct { + Strlit lit; + char buf[110]; + } tmp; + Pkg *pkg; + + if(len > 100) { + // huge strings are made static to avoid long names + snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen); + pkg = localpkg; + } else { + // small strings get named by their contents, + // so that multiple modules using the same string + // can share it. + tmp.lit.len = len; + memmove(tmp.lit.s, s, len); + tmp.lit.s[len] = '\0'; + snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp); + pkg = gostringpkg; + } + sym = pkglookup(namebuf, pkg); + + // SymUniq flag indicates that data is generated already + if(sym->flags & SymUniq) + return sym; + sym->flags |= SymUniq; + + data(); + off = 0; + + // string header + off = dsymptr(sym, off, sym, widthptr+4); + off = duint32(sym, off, len); + + // string data + for(n=0; n<len; n+=m) { + m = 8; + if(m > len-n) + m = len-n; + off = dsname(sym, off, s+n, m); + } + off = duint8(sym, off, 0); // terminating NUL for runtime + off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment + ggloblsym(sym, off, 1); + text(); + + return sym; +} |