github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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 reports 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 ORUNESTR:
   165  	case OARRAYBYTESTR:
   166  	case OARRAYRUNESTR:
   167  	case OSTRARRAYBYTE:
   168  	case OSTRARRAYRUNE:
   169  	case ODOTTYPE:
   170  	case ODOTTYPE2:
   171  	case OSTRUCTLIT:
   172  	case OARRAYLIT:
   173  	case OPTRLIT:
   174  	case OMAKEMAP:
   175  	case OMAKESLICE:
   176  	case OMAKECHAN:
   177  		t = n->type;
   178  		if(!t->sym && t->type)
   179  			t = t->type;
   180  		if(t && t->sym && t->sym->def && !exportedsym(t->sym)) {
   181  			if(debug['E'])
   182  				print("reexport type for expression %S\n", t->sym);
   183  			exportlist = list(exportlist, t->sym->def);
   184  		}
   185  		break;
   186  	}
   187  
   188  	reexportdep(n->left);
   189  	reexportdep(n->right);
   190  	reexportdeplist(n->list);
   191  	reexportdeplist(n->rlist);
   192  	reexportdeplist(n->ninit);
   193  	reexportdep(n->ntest);
   194  	reexportdep(n->nincr);
   195  	reexportdeplist(n->nbody);
   196  	reexportdeplist(n->nelse);
   197  }
   198  
   199  
   200  static void
   201  dumpexportconst(Sym *s)
   202  {
   203  	Node *n;
   204  	Type *t;
   205  
   206  	n = s->def;
   207  	typecheck(&n, Erv);
   208  	if(n == N || n->op != OLITERAL)
   209  		fatal("dumpexportconst: oconst nil: %S", s);
   210  
   211  	t = n->type;	// may or may not be specified
   212  	dumpexporttype(t);
   213  
   214  	if(t != T && !isideal(t))
   215  		Bprint(bout, "\tconst %#S %#T = %#V\n", s, t, &n->val);
   216  	else
   217  		Bprint(bout, "\tconst %#S = %#V\n", s, &n->val);
   218  }
   219  
   220  static void
   221  dumpexportvar(Sym *s)
   222  {
   223  	Node *n;
   224  	Type *t;
   225  
   226  	n = s->def;
   227  	typecheck(&n, Erv|Ecall);
   228  	if(n == N || n->type == T) {
   229  		yyerror("variable exported but not defined: %S", s);
   230  		return;
   231  	}
   232  
   233  	t = n->type;
   234  	dumpexporttype(t);
   235  
   236  	if(t->etype == TFUNC && n->class == PFUNC) {
   237  		if (n->inl) {
   238  			// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
   239  			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
   240  			if(debug['l'] < 2)
   241  				typecheckinl(n);
   242  			// NOTE: The space after %#S here is necessary for ld's export data parser.
   243  			Bprint(bout, "\tfunc %#S %#hT { %#H }\n", s, t, n->inl);
   244  			reexportdeplist(n->inl);
   245  		} else
   246  			Bprint(bout, "\tfunc %#S %#hT\n", s, t);
   247  	} else
   248  		Bprint(bout, "\tvar %#S %#T\n", s, t);
   249  }
   250  
   251  static int
   252  methcmp(const void *va, const void *vb)
   253  {
   254  	Type *a, *b;
   255  	
   256  	a = *(Type**)va;
   257  	b = *(Type**)vb;
   258  	return strcmp(a->sym->name, b->sym->name);
   259  }
   260  
   261  static void
   262  dumpexporttype(Type *t)
   263  {
   264  	Type *f;
   265  	Type **m;
   266  	int i, n;
   267  
   268  	if(t == T)
   269  		return;
   270  	if(t->printed || t == types[t->etype] || t == bytetype || t == runetype || t == errortype)
   271  		return;
   272  	t->printed = 1;
   273  
   274  	if(t->sym != S && t->etype != TFIELD)
   275  		dumppkg(t->sym->pkg);
   276  
   277  	dumpexporttype(t->type);
   278  	dumpexporttype(t->down);
   279  
   280  	if (t->sym == S || t->etype == TFIELD)
   281  		return;
   282  
   283  	n = 0;
   284  	for(f=t->method; f!=T; f=f->down) {	
   285  		dumpexporttype(f);
   286  		n++;
   287  	}
   288  
   289  	m = mal(n*sizeof m[0]);
   290  	i = 0;
   291  	for(f=t->method; f!=T; f=f->down)
   292  		m[i++] = f;
   293  	qsort(m, n, sizeof m[0], methcmp);
   294  
   295  	Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
   296  	for(i=0; i<n; i++) {
   297  		f = m[i];
   298  		if(f->nointerface)
   299  			Bprint(bout, "\t//go:nointerface\n");
   300  		if (f->type->nname && f->type->nname->inl) { // nname was set by caninl
   301  			// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
   302  			// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
   303  			if(debug['l'] < 2)
   304  				typecheckinl(f->type->nname);
   305  			Bprint(bout, "\tfunc (%#T) %#hhS %#hT { %#H }\n", getthisx(f->type)->type, f->sym, f->type, f->type->nname->inl);
   306  			reexportdeplist(f->type->nname->inl);
   307  		} else
   308  			Bprint(bout, "\tfunc (%#T) %#hhS %#hT\n", getthisx(f->type)->type, f->sym, f->type);
   309  	}
   310  }
   311  
   312  static void
   313  dumpsym(Sym *s)
   314  {
   315  	if(s->flags & SymExported)
   316  		return;
   317  	s->flags |= SymExported;
   318  
   319  	if(s->def == N) {
   320  		yyerror("unknown export symbol: %S", s);
   321  		return;
   322  	}
   323  //	print("dumpsym %O %+S\n", s->def->op, s);
   324  	dumppkg(s->pkg);
   325  
   326  	switch(s->def->op) {
   327  	default:
   328  		yyerror("unexpected export symbol: %O %S", s->def->op, s);
   329  		break;
   330  
   331  	case OLITERAL:
   332  		dumpexportconst(s);
   333  		break;
   334  
   335  	case OTYPE:
   336  		if(s->def->type->etype == TFORW)
   337  			yyerror("export of incomplete type %S", s);
   338  		else
   339  			dumpexporttype(s->def->type);
   340  		break;
   341  
   342  	case ONAME:
   343  		dumpexportvar(s);
   344  		break;
   345  	}
   346  }
   347  
   348  void
   349  dumpexport(void)
   350  {
   351  	NodeList *l;
   352  	int32 i, lno;
   353  	Pkg *p;
   354  
   355  	lno = lineno;
   356  
   357  	Bprint(bout, "\n$$\npackage %s", localpkg->name);
   358  	if(safemode)
   359  		Bprint(bout, " safe");
   360  	Bprint(bout, "\n");
   361  
   362  	for(i=0; i<nelem(phash); i++)
   363  		for(p=phash[i]; p; p=p->link)
   364  			if(p->direct)
   365  				dumppkg(p);
   366  
   367  	for(l=exportlist; l; l=l->next) {
   368  		lineno = l->n->lineno;
   369  		dumpsym(l->n->sym);
   370  	}
   371  
   372  	Bprint(bout, "\n$$\n");
   373  	lineno = lno;
   374  }
   375  
   376  /*
   377   * import
   378   */
   379  
   380  /*
   381   * return the sym for ss, which should match lexical
   382   */
   383  Sym*
   384  importsym(Sym *s, int op)
   385  {
   386  	char *pkgstr;
   387  
   388  	if(s->def != N && s->def->op != op) {
   389  		pkgstr = smprint("during import \"%Z\"", importpkg->path);
   390  		redeclare(s, pkgstr);
   391  	}
   392  
   393  	// mark the symbol so it is not reexported
   394  	if(s->def == N) {
   395  		if(exportname(s->name) || initname(s->name))
   396  			s->flags |= SymExport;
   397  		else
   398  			s->flags |= SymPackage;	// package scope
   399  	}
   400  	return s;
   401  }
   402  
   403  /*
   404   * return the type pkg.name, forward declaring if needed
   405   */
   406  Type*
   407  pkgtype(Sym *s)
   408  {
   409  	Type *t;
   410  
   411  	importsym(s, OTYPE);
   412  	if(s->def == N || s->def->op != OTYPE) {
   413  		t = typ(TFORW);
   414  		t->sym = s;
   415  		s->def = typenod(t);
   416  	}
   417  	if(s->def->type == T)
   418  		yyerror("pkgtype %S", s);
   419  	return s->def->type;
   420  }
   421  
   422  void
   423  importimport(Sym *s, Strlit *z)
   424  {
   425  	// Informational: record package name
   426  	// associated with import path, for use in
   427  	// human-readable messages.
   428  	Pkg *p;
   429  
   430  	if(isbadimport(z))
   431  		errorexit();
   432  	p = mkpkg(z);
   433  	if(p->name == nil) {
   434  		p->name = s->name;
   435  		pkglookup(s->name, nil)->npkg++;
   436  	} else if(strcmp(p->name, s->name) != 0)
   437  		yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path);
   438  	
   439  	if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) {
   440  		yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z);
   441  		errorexit();
   442  	}
   443  }
   444  
   445  void
   446  importconst(Sym *s, Type *t, Node *n)
   447  {
   448  	Node *n1;
   449  
   450  	importsym(s, OLITERAL);
   451  	convlit(&n, t);
   452  
   453  	if(s->def != N)	 // TODO: check if already the same.
   454  		return;
   455  
   456  	if(n->op != OLITERAL) {
   457  		yyerror("expression must be a constant");
   458  		return;
   459  	}
   460  
   461  	if(n->sym != S) {
   462  		n1 = nod(OXXX, N, N);
   463  		*n1 = *n;
   464  		n = n1;
   465  	}
   466  	n->orig = newname(s);
   467  	n->sym = s;
   468  	declare(n, PEXTERN);
   469  
   470  	if(debug['E'])
   471  		print("import const %S\n", s);
   472  }
   473  
   474  void
   475  importvar(Sym *s, Type *t)
   476  {
   477  	Node *n;
   478  
   479  	importsym(s, ONAME);
   480  	if(s->def != N && s->def->op == ONAME) {
   481  		if(eqtype(t, s->def->type))
   482  			return;
   483  		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);
   484  	}
   485  	n = newname(s);
   486  	s->importdef = importpkg;
   487  	n->type = t;
   488  	declare(n, PEXTERN);
   489  
   490  	if(debug['E'])
   491  		print("import var %S %lT\n", s, t);
   492  }
   493  
   494  void
   495  importtype(Type *pt, Type *t)
   496  {
   497  	Node *n;
   498  
   499  	// override declaration in unsafe.go for Pointer.
   500  	// there is no way in Go code to define unsafe.Pointer
   501  	// so we have to supply it.
   502  	if(incannedimport &&
   503  	   strcmp(importpkg->name, "unsafe") == 0 &&
   504  	   strcmp(pt->nod->sym->name, "Pointer") == 0) {
   505  		t = types[TUNSAFEPTR];
   506  	}
   507  
   508  	if(pt->etype == TFORW) {
   509  		n = pt->nod;
   510  		copytype(pt->nod, t);
   511  		pt->nod = n;		// unzero nod
   512  		pt->sym->importdef = importpkg;
   513  		pt->sym->lastlineno = parserline();
   514  		declare(n, PEXTERN);
   515  		checkwidth(pt);
   516  	} else if(!eqtype(pt->orig, t))
   517  		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);
   518  
   519  	if(debug['E'])
   520  		print("import type %T %lT\n", pt, t);
   521  }