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