github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/gc/export.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 #include "y.tab.h" 9 10 static NodeList *asmlist; 11 12 static void dumpexporttype(Type *t); 13 14 // Mark n's symbol as exported 15 void 16 exportsym(Node *n) 17 { 18 if(n == N || n->sym == S) 19 return; 20 if(n->sym->flags & (SymExport|SymPackage)) { 21 if(n->sym->flags & SymPackage) 22 yyerror("export/package mismatch: %S", n->sym); 23 return; 24 } 25 n->sym->flags |= SymExport; 26 27 if(debug['E']) 28 print("export symbol %S\n", n->sym); 29 exportlist = list(exportlist, n); 30 } 31 32 int 33 exportname(char *s) 34 { 35 Rune r; 36 37 if((uchar)s[0] < Runeself) 38 return 'A' <= s[0] && s[0] <= 'Z'; 39 chartorune(&r, s); 40 return isupperrune(r); 41 } 42 43 static int 44 initname(char *s) 45 { 46 return strcmp(s, "init") == 0; 47 } 48 49 // exportedsym reports whether a symbol will be visible 50 // to files that import our package. 51 static int 52 exportedsym(Sym *sym) 53 { 54 // Builtins are visible everywhere. 55 if(sym->pkg == builtinpkg || sym->origpkg == builtinpkg) 56 return 1; 57 58 return sym->pkg == localpkg && exportname(sym->name); 59 } 60 61 void 62 autoexport(Node *n, int ctxt) 63 { 64 if(n == N || n->sym == S) 65 return; 66 if((ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN) 67 return; 68 if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left) // method 69 return; 70 // -A is for cmd/gc/mkbuiltin script, so export everything 71 if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name)) 72 exportsym(n); 73 if(asmhdr && n->sym->pkg == localpkg && !(n->sym->flags & SymAsm)) { 74 n->sym->flags |= SymAsm; 75 asmlist = list(asmlist, n); 76 } 77 78 } 79 80 static void 81 dumppkg(Pkg *p) 82 { 83 char *suffix; 84 85 if(p == nil || p == localpkg || p->exported || p == builtinpkg) 86 return; 87 p->exported = 1; 88 suffix = ""; 89 if(!p->direct) 90 suffix = " // indirect"; 91 Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix); 92 } 93 94 // Look for anything we need for the inline body 95 static void reexportdep(Node *n); 96 static void 97 reexportdeplist(NodeList *ll) 98 { 99 for(; ll ;ll=ll->next) 100 reexportdep(ll->n); 101 } 102 103 static void 104 reexportdep(Node *n) 105 { 106 Type *t; 107 108 if(!n) 109 return; 110 111 //print("reexportdep %+hN\n", n); 112 switch(n->op) { 113 case ONAME: 114 switch(n->class&~PHEAP) { 115 case PFUNC: 116 // methods will be printed along with their type 117 // nodes for T.Method expressions 118 if(n->left && n->left->op == OTYPE) 119 break; 120 // nodes for method calls. 121 if(!n->type || n->type->thistuple > 0) 122 break; 123 // fallthrough 124 case PEXTERN: 125 if(n->sym && !exportedsym(n->sym)) { 126 if(debug['E']) 127 print("reexport name %S\n", n->sym); 128 exportlist = list(exportlist, n); 129 } 130 } 131 break; 132 133 case ODCL: 134 // Local variables in the bodies need their type. 135 t = n->left->type; 136 if(t != types[t->etype] && t != idealbool && t != idealstring) { 137 if(isptr[t->etype]) 138 t = t->type; 139 if(t && t->sym && t->sym->def && !exportedsym(t->sym)) { 140 if(debug['E']) 141 print("reexport type %S from declaration\n", t->sym); 142 exportlist = list(exportlist, t->sym->def); 143 } 144 } 145 break; 146 147 case OLITERAL: 148 t = n->type; 149 if(t != types[n->type->etype] && t != idealbool && t != idealstring) { 150 if(isptr[t->etype]) 151 t = t->type; 152 if(t && t->sym && t->sym->def && !exportedsym(t->sym)) { 153 if(debug['E']) 154 print("reexport literal type %S\n", t->sym); 155 exportlist = list(exportlist, t->sym->def); 156 } 157 } 158 // fallthrough 159 case OTYPE: 160 if(n->sym && !exportedsym(n->sym)) { 161 if(debug['E']) 162 print("reexport literal/type %S\n", n->sym); 163 exportlist = list(exportlist, n); 164 } 165 break; 166 167 // for operations that need a type when rendered, put the type on the export list. 168 case OCONV: 169 case OCONVIFACE: 170 case OCONVNOP: 171 case ORUNESTR: 172 case OARRAYBYTESTR: 173 case OARRAYRUNESTR: 174 case OSTRARRAYBYTE: 175 case OSTRARRAYRUNE: 176 case ODOTTYPE: 177 case ODOTTYPE2: 178 case OSTRUCTLIT: 179 case OARRAYLIT: 180 case OPTRLIT: 181 case OMAKEMAP: 182 case OMAKESLICE: 183 case OMAKECHAN: 184 t = n->type; 185 if(!t->sym && t->type) 186 t = t->type; 187 if(t && t->sym && t->sym->def && !exportedsym(t->sym)) { 188 if(debug['E']) 189 print("reexport type for expression %S\n", t->sym); 190 exportlist = list(exportlist, t->sym->def); 191 } 192 break; 193 } 194 195 reexportdep(n->left); 196 reexportdep(n->right); 197 reexportdeplist(n->list); 198 reexportdeplist(n->rlist); 199 reexportdeplist(n->ninit); 200 reexportdep(n->ntest); 201 reexportdep(n->nincr); 202 reexportdeplist(n->nbody); 203 reexportdeplist(n->nelse); 204 } 205 206 207 static void 208 dumpexportconst(Sym *s) 209 { 210 Node *n; 211 Type *t; 212 213 n = s->def; 214 typecheck(&n, Erv); 215 if(n == N || n->op != OLITERAL) 216 fatal("dumpexportconst: oconst nil: %S", s); 217 218 t = n->type; // may or may not be specified 219 dumpexporttype(t); 220 221 if(t != T && !isideal(t)) 222 Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val); 223 else 224 Bprint(bout, "\tconst %#S = %#V\n", s, &n->val); 225 } 226 227 static void 228 dumpexportvar(Sym *s) 229 { 230 Node *n; 231 Type *t; 232 233 n = s->def; 234 typecheck(&n, Erv|Ecall); 235 if(n == N || n->type == T) { 236 yyerror("variable exported but not defined: %S", s); 237 return; 238 } 239 240 t = n->type; 241 dumpexporttype(t); 242 243 if(t->etype == TFUNC && n->class == PFUNC) { 244 if (n->inl) { 245 // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet. 246 // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package 247 if(debug['l'] < 2) 248 typecheckinl(n); 249 // NOTE: The space after %#S here is necessary for ld's export data parser. 250 Bprint(bout, "\tfunc %#S %#hT { %#H }\n", s, t, n->inl); 251 reexportdeplist(n->inl); 252 } else 253 Bprint(bout, "\tfunc %#S %#hT\n", s, t); 254 } else 255 Bprint(bout, "\tvar %#S %#T\n", s, t); 256 } 257 258 static int 259 methcmp(const void *va, const void *vb) 260 { 261 Type *a, *b; 262 263 a = *(Type**)va; 264 b = *(Type**)vb; 265 return strcmp(a->sym->name, b->sym->name); 266 } 267 268 static void 269 dumpexporttype(Type *t) 270 { 271 Type *f; 272 Type **m; 273 int i, n; 274 275 if(t == T) 276 return; 277 if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype) 278 return; 279 t->printed = 1; 280 281 if(t->sym != S && t->etype != TFIELD) 282 dumppkg(t->sym->pkg); 283 284 dumpexporttype(t->type); 285 dumpexporttype(t->down); 286 287 if (t->sym == S || t->etype == TFIELD) 288 return; 289 290 n = 0; 291 for(f=t->method; f!=T; f=f->down) { 292 dumpexporttype(f); 293 n++; 294 } 295 296 m = mal(n*sizeof m[0]); 297 i = 0; 298 for(f=t->method; f!=T; f=f->down) 299 m[i++] = f; 300 qsort(m, n, sizeof m[0], methcmp); 301 302 Bprint(bout, "\ttype %#S %#lT\n", t->sym, t); 303 for(i=0; i<n; i++) { 304 f = m[i]; 305 if(f->nointerface) 306 Bprint(bout, "\t//go:nointerface\n"); 307 if (f->type->nname && f->type->nname->inl) { // nname was set by caninl 308 // when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet. 309 // currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package 310 if(debug['l'] < 2) 311 typecheckinl(f->type->nname); 312 Bprint(bout, "\tfunc (%#T) %#hhS %#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl); 313 reexportdeplist(f->type->nname->inl); 314 } else 315 Bprint(bout, "\tfunc (%#T) %#hhS %#hT\n", getthisx(f->type)->type, f->sym, f->type); 316 } 317 } 318 319 static void 320 dumpsym(Sym *s) 321 { 322 if(s->flags & SymExported) 323 return; 324 s->flags |= SymExported; 325 326 if(s->def == N) { 327 yyerror("unknown export symbol: %S", s); 328 return; 329 } 330 // print("dumpsym %O %+S\n", s->def->op, s); 331 dumppkg(s->pkg); 332 333 switch(s->def->op) { 334 default: 335 yyerror("unexpected export symbol: %O %S", s->def->op, s); 336 break; 337 338 case OLITERAL: 339 dumpexportconst(s); 340 break; 341 342 case OTYPE: 343 if(s->def->type->etype == TFORW) 344 yyerror("export of incomplete type %S", s); 345 else 346 dumpexporttype(s->def->type); 347 break; 348 349 case ONAME: 350 dumpexportvar(s); 351 break; 352 } 353 } 354 355 void 356 dumpexport(void) 357 { 358 NodeList *l; 359 int32 i, lno; 360 Pkg *p; 361 362 lno = lineno; 363 364 Bprint(bout, "\n$$\npackage %s", localpkg->name); 365 if(safemode) 366 Bprint(bout, " safe"); 367 Bprint(bout, "\n"); 368 369 for(i=0; i<nelem(phash); i++) 370 for(p=phash[i]; p; p=p->link) 371 if(p->direct) 372 dumppkg(p); 373 374 for(l=exportlist; l; l=l->next) { 375 lineno = l->n->lineno; 376 dumpsym(l->n->sym); 377 } 378 379 Bprint(bout, "\n$$\n"); 380 lineno = lno; 381 } 382 383 /* 384 * import 385 */ 386 387 /* 388 * return the sym for ss, which should match lexical 389 */ 390 Sym* 391 importsym(Sym *s, int op) 392 { 393 char *pkgstr; 394 395 if(s->def != N && s->def->op != op) { 396 pkgstr = smprint("during import \"%Z\"", importpkg->path); 397 redeclare(s, pkgstr); 398 } 399 400 // mark the symbol so it is not reexported 401 if(s->def == N) { 402 if(exportname(s->name) || initname(s->name)) 403 s->flags |= SymExport; 404 else 405 s->flags |= SymPackage; // package scope 406 } 407 return s; 408 } 409 410 /* 411 * return the type pkg.name, forward declaring if needed 412 */ 413 Type* 414 pkgtype(Sym *s) 415 { 416 Type *t; 417 418 importsym(s, OTYPE); 419 if(s->def == N || s->def->op != OTYPE) { 420 t = typ(TFORW); 421 t->sym = s; 422 s->def = typenod(t); 423 } 424 if(s->def->type == T) 425 yyerror("pkgtype %S", s); 426 return s->def->type; 427 } 428 429 void 430 importimport(Sym *s, Strlit *z) 431 { 432 // Informational: record package name 433 // associated with import path, for use in 434 // human-readable messages. 435 Pkg *p; 436 437 if(isbadimport(z)) 438 errorexit(); 439 p = mkpkg(z); 440 if(p->name == nil) { 441 p->name = s->name; 442 pkglookup(s->name, nil)->npkg++; 443 } else if(strcmp(p->name, s->name) != 0) 444 yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path); 445 446 if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) { 447 yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z); 448 errorexit(); 449 } 450 } 451 452 void 453 importconst(Sym *s, Type *t, Node *n) 454 { 455 Node *n1; 456 457 importsym(s, OLITERAL); 458 convlit(&n, t); 459 460 if(s->def != N) // TODO: check if already the same. 461 return; 462 463 if(n->op != OLITERAL) { 464 yyerror("expression must be a constant"); 465 return; 466 } 467 468 if(n->sym != S) { 469 n1 = nod(OXXX, N, N); 470 *n1 = *n; 471 n = n1; 472 } 473 n->orig = newname(s); 474 n->sym = s; 475 declare(n, PEXTERN); 476 477 if(debug['E']) 478 print("import const %S\n", s); 479 } 480 481 void 482 importvar(Sym *s, Type *t) 483 { 484 Node *n; 485 486 importsym(s, ONAME); 487 if(s->def != N && s->def->op == ONAME) { 488 if(eqtype(t, s->def->type)) 489 return; 490 yyerror("inconsistent definition for var %S during import\n\t%T (in \"%Z\")\n\t%T (in \"%Z\")", s, s->def->type, s->importdef->path, t, importpkg->path); 491 } 492 n = newname(s); 493 s->importdef = importpkg; 494 n->type = t; 495 declare(n, PEXTERN); 496 497 if(debug['E']) 498 print("import var %S %lT\n", s, t); 499 } 500 501 void 502 importtype(Type *pt, Type *t) 503 { 504 Node *n; 505 506 // override declaration in unsafe.go for Pointer. 507 // there is no way in Go code to define unsafe.Pointer 508 // so we have to supply it. 509 if(incannedimport && 510 strcmp(importpkg->name, "unsafe") == 0 && 511 strcmp(pt->nod->sym->name, "Pointer") == 0) { 512 t = types[TUNSAFEPTR]; 513 } 514 515 if(pt->etype == TFORW) { 516 n = pt->nod; 517 copytype(pt->nod, t); 518 pt->nod = n; // unzero nod 519 pt->sym->importdef = importpkg; 520 pt->sym->lastlineno = parserline(); 521 declare(n, PEXTERN); 522 checkwidth(pt); 523 } else if(!eqtype(pt->orig, t)) 524 yyerror("inconsistent definition for type %S during import\n\t%lT (in \"%Z\")\n\t%lT (in \"%Z\")", pt->sym, pt, pt->sym->importdef->path, t, importpkg->path); 525 526 if(debug['E']) 527 print("import type %T %lT\n", pt, t); 528 } 529 530 void 531 dumpasmhdr(void) 532 { 533 Biobuf *b; 534 NodeList *l; 535 Node *n; 536 Type *t; 537 538 b = Bopen(asmhdr, OWRITE); 539 if(b == nil) 540 fatal("open %s: %r", asmhdr); 541 Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name); 542 for(l=asmlist; l; l=l->next) { 543 n = l->n; 544 if(isblanksym(n->sym)) 545 continue; 546 switch(n->op) { 547 case OLITERAL: 548 Bprint(b, "#define const_%s %#V\n", n->sym->name, &n->val); 549 break; 550 case OTYPE: 551 t = n->type; 552 if(t->etype != TSTRUCT || t->map != T || t->funarg) 553 break; 554 Bprint(b, "#define %s__size %d\n", t->sym->name, (int)t->width); 555 for(t=t->type; t != T; t=t->down) 556 if(!isblanksym(t->sym)) 557 Bprint(b, "#define %s_%s %d\n", n->sym->name, t->sym->name, (int)t->width); 558 break; 559 } 560 } 561 562 Bterm(b); 563 }