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 }