github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/gc/obj.c (about)

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