The Go Programming Language

Text file src/cmd/gc/obj.c

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	#include "go.h"
     6	
     7	/*
     8	 * architecture-independent object file output
     9	 */
    10	
    11	static	void	outhist(Biobuf *b);
    12	static	void	dumpglobls(void);
    13	
    14	void
    15	dumpobj(void)
    16	{
    17		bout = Bopen(outfile, OWRITE);
    18		if(bout == nil) {
    19			flusherrors();
    20			print("can't create %s: %r\n", outfile);
    21			errorexit();
    22		}
    23	
    24		Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
    25		Bprint(bout, "  exports automatically generated from\n");
    26		Bprint(bout, "  %s in package \"%s\"\n", curio.infile, localpkg->name);
    27		dumpexport();
    28		Bprint(bout, "\n!\n");
    29	
    30		outhist(bout);
    31	
    32		// add nil plist w AEND to catch
    33		// auto-generated trampolines, data
    34		newplist();
    35	
    36		dumpglobls();
    37		dumptypestructs();
    38		dumpdata();
    39		dumpfuncs();
    40	
    41		Bterm(bout);
    42	}
    43	
    44	static void
    45	dumpglobls(void)
    46	{
    47		Node *n;
    48		NodeList *l;
    49	
    50		// add globals
    51		for(l=externdcl; l; l=l->next) {
    52			n = l->n;
    53			if(n->op != ONAME)
    54				continue;
    55	
    56			if(n->type == T)
    57				fatal("external %#N nil type\n", n);
    58			if(n->class == PFUNC)
    59				continue;
    60			if(n->sym->pkg != localpkg)
    61				continue;
    62			dowidth(n->type);
    63	
    64			ggloblnod(n, n->type->width);
    65		}
    66	}
    67	
    68	void
    69	Bputname(Biobuf *b, Sym *s)
    70	{
    71		Bprint(b, "%s", s->pkg->prefix);
    72		Bputc(b, '.');
    73		Bwrite(b, s->name, strlen(s->name)+1);
    74	}
    75	
    76	static void
    77	outzfile(Biobuf *b, char *p)
    78	{
    79		char *q, *q2;
    80	
    81		while(p) {
    82			q = utfrune(p, '/');
    83			if(windows) {
    84				q2 = utfrune(p, '\\');
    85				if(q2 && (!q || q2 < q))
    86					q = q2;
    87			}
    88			if(!q) {
    89				zfile(b, p, strlen(p));
    90				return;
    91			}
    92			if(q > p)
    93				zfile(b, p, q-p);
    94			p = q + 1;
    95		}
    96	}
    97	
    98	#define isdelim(c) (c == '/' || c == '\\')
    99	
   100	static void
   101	outwinname(Biobuf *b, Hist *h, char *ds, char *p)
   102	{
   103		if(isdelim(p[0])) {
   104			// full rooted name
   105			zfile(b, ds, 3);	// leading "c:/"
   106			outzfile(b, p+1);
   107		} else {
   108			// relative name
   109			if(h->offset == 0 && pathname && pathname[1] == ':') {
   110				if(tolowerrune(ds[0]) == tolowerrune(pathname[0])) {
   111					// using current drive
   112					zfile(b, pathname, 3);	// leading "c:/"
   113					outzfile(b, pathname+3);
   114				} else {
   115					// using drive other then current,
   116					// we don't have any simple way to
   117					// determine current working directory
   118					// there, therefore will output name as is
   119					zfile(b, ds, 2);	// leading "c:"
   120				}
   121			}
   122			outzfile(b, p);
   123		}
   124	}
   125	
   126	static void
   127	outhist(Biobuf *b)
   128	{
   129		Hist *h;
   130		char *p, ds[] = {'c', ':', '/', 0};
   131	
   132		for(h = hist; h != H; h = h->link) {
   133			p = h->name;
   134			if(p) {
   135				if(windows) {
   136					// if windows variable is set, then, we know already,
   137					// pathname is started with windows drive specifier
   138					// and all '\' were replaced with '/' (see lex.c)
   139					if(isdelim(p[0]) && isdelim(p[1])) {
   140						// file name has network name in it, 
   141						// like \\server\share\dir\file.go
   142						zfile(b, "//", 2);	// leading "//"
   143						outzfile(b, p+2);
   144					} else if(p[1] == ':') {
   145						// file name has drive letter in it
   146						ds[0] = p[0];
   147						outwinname(b, h, ds, p+2);
   148					} else {
   149						// no drive letter in file name
   150						outwinname(b, h, pathname, p);
   151					}
   152				} else {
   153					if(p[0] == '/') {
   154						// full rooted name, like /home/rsc/dir/file.go
   155						zfile(b, "/", 1);	// leading "/"
   156						outzfile(b, p+1);
   157					} else {
   158						// relative name, like dir/file.go
   159						if(h->offset >= 0 && pathname && pathname[0] == '/') {
   160							zfile(b, "/", 1);	// leading "/"
   161							outzfile(b, pathname+1);
   162						}
   163						outzfile(b, p);
   164					}
   165				}
   166			
   167			}
   168			zhist(b, h->line, h->offset);
   169		}
   170	}
   171	
   172	void
   173	ieeedtod(uint64 *ieee, double native)
   174	{
   175		double fr, ho, f;
   176		int exp;
   177		uint32 h, l;
   178		uint64 bits;
   179	
   180		if(native < 0) {
   181			ieeedtod(ieee, -native);
   182			*ieee |= 1ULL<<63;
   183			return;
   184		}
   185		if(native == 0) {
   186			*ieee = 0;
   187			return;
   188		}
   189		fr = frexp(native, &exp);
   190		f = 2097152L;		/* shouldnt use fp constants here */
   191		fr = modf(fr*f, &ho);
   192		h = ho;
   193		h &= 0xfffffL;
   194		f = 65536L;
   195		fr = modf(fr*f, &ho);
   196		l = ho;
   197		l <<= 16;
   198		l |= (int32)(fr*f);
   199		bits = ((uint64)h<<32) | l;
   200		if(exp < -1021) {
   201			// gradual underflow
   202			bits |= 1LL<<52;
   203			bits >>= -1021 - exp;
   204			exp = -1022;
   205		}
   206		bits |= (uint64)(exp+1022L) << 52;
   207		*ieee = bits;
   208	}
   209	
   210	int
   211	duint8(Sym *s, int off, uint8 v)
   212	{
   213		return duintxx(s, off, v, 1);
   214	}
   215	
   216	int
   217	duint16(Sym *s, int off, uint16 v)
   218	{
   219		return duintxx(s, off, v, 2);
   220	}
   221	
   222	int
   223	duint32(Sym *s, int off, uint32 v)
   224	{
   225		return duintxx(s, off, v, 4);
   226	}
   227	
   228	int
   229	duint64(Sym *s, int off, uint64 v)
   230	{
   231		return duintxx(s, off, v, 8);
   232	}
   233	
   234	int
   235	duintptr(Sym *s, int off, uint64 v)
   236	{
   237		return duintxx(s, off, v, widthptr);
   238	}
   239	
   240	Sym*
   241	stringsym(char *s, int len)
   242	{
   243		static int gen;
   244		Sym *sym;
   245		int off, n, m;
   246		struct {
   247			Strlit lit;
   248			char buf[110];
   249		} tmp;
   250		Pkg *pkg;
   251	
   252		if(len > 100) {
   253			// huge strings are made static to avoid long names
   254			snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
   255			pkg = localpkg;
   256		} else {
   257			// small strings get named by their contents,
   258			// so that multiple modules using the same string
   259			// can share it.
   260			tmp.lit.len = len;
   261			memmove(tmp.lit.s, s, len);
   262			tmp.lit.s[len] = '\0';
   263			snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp);
   264			pkg = gostringpkg;
   265		}
   266		sym = pkglookup(namebuf, pkg);
   267		
   268		// SymUniq flag indicates that data is generated already
   269		if(sym->flags & SymUniq)
   270			return sym;
   271		sym->flags |= SymUniq;
   272		
   273		data();
   274		off = 0;
   275		
   276		// string header
   277		off = dsymptr(sym, off, sym, widthptr+4);
   278		off = duint32(sym, off, len);
   279		
   280		// string data
   281		for(n=0; n<len; n+=m) {
   282			m = 8;
   283			if(m > len-n)
   284				m = len-n;
   285			off = dsname(sym, off, s+n, m);
   286		}
   287		off = duint8(sym, off, 0);  // terminating NUL for runtime
   288		off = (off+widthptr-1)&~(widthptr-1);  // round to pointer alignment
   289		ggloblsym(sym, off, 1);
   290		text();
   291		
   292		return sym;	
   293	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.