2015-02-13 14:40:36 -05:00
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gc
import (
2016-03-11 13:39:20 -05:00
"bufio"
2015-08-13 19:05:37 -07:00
"bytes"
2015-02-13 14:40:36 -05:00
"cmd/internal/obj"
"fmt"
"sort"
"unicode"
"unicode/utf8"
)
2015-08-13 19:05:37 -07:00
var (
newexport int // if set, use new export format
Debug_export int // if set, print debugging information about export data
exportsize int
)
func exportf ( format string , args ... interface { } ) {
n , _ := fmt . Fprintf ( bout , format , args ... )
exportsize += n
if Debug_export != 0 {
fmt . Printf ( format , args ... )
}
}
2016-03-04 19:04:50 -08:00
var asmlist [ ] * Node
2015-02-13 14:40:36 -05:00
// Mark n's symbol as exported
func exportsym ( n * Node ) {
if n == nil || n . Sym == nil {
return
}
if n . Sym . Flags & ( SymExport | SymPackage ) != 0 {
if n . Sym . Flags & SymPackage != 0 {
2015-04-17 12:03:22 -04:00
Yyerror ( "export/package mismatch: %v" , n . Sym )
2015-02-13 14:40:36 -05:00
}
return
}
n . Sym . Flags |= SymExport
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "export symbol %v\n" , n . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , n )
2015-02-13 14:40:36 -05:00
}
func exportname ( s string ) bool {
2015-08-13 19:05:37 -07:00
if r := s [ 0 ] ; r < utf8 . RuneSelf {
return 'A' <= r && r <= 'Z'
2015-02-13 14:40:36 -05:00
}
r , _ := utf8 . DecodeRuneInString ( s )
return unicode . IsUpper ( r )
}
2015-02-17 22:13:49 -05:00
func initname ( s string ) bool {
return s == "init"
2015-02-13 14:40:36 -05:00
}
// exportedsym reports whether a symbol will be visible
// to files that import our package.
2015-02-17 22:13:49 -05:00
func exportedsym ( sym * Sym ) bool {
2015-02-13 14:40:36 -05:00
// Builtins are visible everywhere.
if sym . Pkg == builtinpkg || sym . Origpkg == builtinpkg {
2015-02-17 22:13:49 -05:00
return true
2015-02-13 14:40:36 -05:00
}
2015-02-17 22:13:49 -05:00
return sym . Pkg == localpkg && exportname ( sym . Name )
2015-02-13 14:40:36 -05:00
}
2015-10-26 14:57:36 -07:00
func autoexport ( n * Node , ctxt Class ) {
2015-02-13 14:40:36 -05:00
if n == nil || n . Sym == nil {
return
}
if ( ctxt != PEXTERN && ctxt != PFUNC ) || dclcontext != PEXTERN {
return
}
2015-05-27 00:44:05 -04:00
if n . Name . Param != nil && n . Name . Param . Ntype != nil && n . Name . Param . Ntype . Op == OTFUNC && n . Name . Param . Ntype . Left != nil { // method
2015-02-13 14:40:36 -05:00
return
}
// -A is for cmd/gc/mkbuiltin script, so export everything
2015-02-17 22:13:49 -05:00
if Debug [ 'A' ] != 0 || exportname ( n . Sym . Name ) || initname ( n . Sym . Name ) {
2015-02-13 14:40:36 -05:00
exportsym ( n )
}
2015-02-17 22:13:49 -05:00
if asmhdr != "" && n . Sym . Pkg == localpkg && n . Sym . Flags & SymAsm == 0 {
2015-02-13 14:40:36 -05:00
n . Sym . Flags |= SymAsm
2016-03-04 19:04:50 -08:00
asmlist = append ( asmlist , n )
2015-02-13 14:40:36 -05:00
}
}
func dumppkg ( p * Pkg ) {
2015-09-08 05:46:31 +02:00
if p == nil || p == localpkg || p . Exported || p == builtinpkg {
2015-02-13 14:40:36 -05:00
return
}
2015-09-08 05:46:31 +02:00
p . Exported = true
2015-02-23 16:07:24 -05:00
suffix := ""
2015-09-08 05:46:31 +02:00
if ! p . Direct {
2015-02-13 14:40:36 -05:00
suffix = " // indirect"
}
2015-08-13 19:05:37 -07:00
exportf ( "\timport %s %q%s\n" , p . Name , p . Path , suffix )
2015-02-13 14:40:36 -05:00
}
// Look for anything we need for the inline body
2016-03-08 10:26:20 -08:00
func reexportdeplist ( ll Nodes ) {
2016-03-08 15:10:26 -08:00
for _ , n := range ll . Slice ( ) {
reexportdep ( n )
2016-02-27 14:31:33 -08:00
}
}
2015-02-13 14:40:36 -05:00
func reexportdep ( n * Node ) {
2015-02-17 22:13:49 -05:00
if n == nil {
2015-02-13 14:40:36 -05:00
return
}
//print("reexportdep %+hN\n", n);
switch n . Op {
case ONAME :
switch n . Class &^ PHEAP {
// methods will be printed along with their type
// nodes for T.Method expressions
case PFUNC :
if n . Left != nil && n . Left . Op == OTYPE {
break
}
// nodes for method calls.
2015-02-17 22:13:49 -05:00
if n . Type == nil || n . Type . Thistuple > 0 {
2015-02-13 14:40:36 -05:00
break
}
fallthrough
case PEXTERN :
2015-02-17 22:13:49 -05:00
if n . Sym != nil && ! exportedsym ( n . Sym ) {
2015-02-13 14:40:36 -05:00
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "reexport name %v\n" , n . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , n )
2015-02-13 14:40:36 -05:00
}
}
2015-08-13 19:05:37 -07:00
// Local variables in the bodies need their type.
2015-02-13 14:40:36 -05:00
case ODCL :
2015-02-23 16:07:24 -05:00
t := n . Left . Type
2015-02-13 14:40:36 -05:00
if t != Types [ t . Etype ] && t != idealbool && t != idealstring {
2015-03-01 07:54:01 +00:00
if Isptr [ t . Etype ] {
2015-02-13 14:40:36 -05:00
t = t . Type
}
2015-02-17 22:13:49 -05:00
if t != nil && t . Sym != nil && t . Sym . Def != nil && ! exportedsym ( t . Sym ) {
2015-02-13 14:40:36 -05:00
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "reexport type %v from declaration\n" , t . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , t . Sym . Def )
2015-02-13 14:40:36 -05:00
}
}
case OLITERAL :
2015-02-23 16:07:24 -05:00
t := n . Type
2015-02-13 14:40:36 -05:00
if t != Types [ n . Type . Etype ] && t != idealbool && t != idealstring {
2015-03-01 07:54:01 +00:00
if Isptr [ t . Etype ] {
2015-02-13 14:40:36 -05:00
t = t . Type
}
2015-02-17 22:13:49 -05:00
if t != nil && t . Sym != nil && t . Sym . Def != nil && ! exportedsym ( t . Sym ) {
2015-02-13 14:40:36 -05:00
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "reexport literal type %v\n" , t . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , t . Sym . Def )
2015-02-13 14:40:36 -05:00
}
}
fallthrough
case OTYPE :
2015-02-17 22:13:49 -05:00
if n . Sym != nil && ! exportedsym ( n . Sym ) {
2015-02-13 14:40:36 -05:00
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "reexport literal/type %v\n" , n . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , n )
2015-02-13 14:40:36 -05:00
}
2015-08-13 19:05:37 -07:00
// for operations that need a type when rendered, put the type on the export list.
2015-02-13 14:40:36 -05:00
case OCONV ,
OCONVIFACE ,
OCONVNOP ,
ORUNESTR ,
OARRAYBYTESTR ,
OARRAYRUNESTR ,
OSTRARRAYBYTE ,
OSTRARRAYRUNE ,
ODOTTYPE ,
ODOTTYPE2 ,
OSTRUCTLIT ,
OARRAYLIT ,
OPTRLIT ,
OMAKEMAP ,
OMAKESLICE ,
OMAKECHAN :
2015-02-23 16:07:24 -05:00
t := n . Type
2015-02-13 14:40:36 -05:00
2015-02-17 22:13:49 -05:00
if t . Sym == nil && t . Type != nil {
2015-02-13 14:40:36 -05:00
t = t . Type
}
2015-02-17 22:13:49 -05:00
if t != nil && t . Sym != nil && t . Sym . Def != nil && ! exportedsym ( t . Sym ) {
2015-02-13 14:40:36 -05:00
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "reexport type for expression %v\n" , t . Sym )
2015-02-13 14:40:36 -05:00
}
2015-08-12 14:29:50 -07:00
exportlist = append ( exportlist , t . Sym . Def )
2015-02-13 14:40:36 -05:00
}
}
reexportdep ( n . Left )
reexportdep ( n . Right )
reexportdeplist ( n . List )
reexportdeplist ( n . Rlist )
reexportdeplist ( n . Ninit )
2016-03-04 13:16:48 -08:00
reexportdeplist ( n . Nbody )
2015-02-13 14:40:36 -05:00
}
func dumpexportconst ( s * Sym ) {
2015-02-23 16:07:24 -05:00
n := s . Def
2015-02-13 14:40:36 -05:00
typecheck ( & n , Erv )
if n == nil || n . Op != OLITERAL {
2015-08-30 23:10:03 +02:00
Fatalf ( "dumpexportconst: oconst nil: %v" , s )
2015-02-13 14:40:36 -05:00
}
2015-02-23 16:07:24 -05:00
t := n . Type // may or may not be specified
2015-02-13 14:40:36 -05:00
dumpexporttype ( t )
2015-02-17 22:13:49 -05:00
if t != nil && ! isideal ( t ) {
2015-08-13 19:05:37 -07:00
exportf ( "\tconst %v %v = %v\n" , Sconv ( s , obj . FmtSharp ) , Tconv ( t , obj . FmtSharp ) , Vconv ( n . Val ( ) , obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
} else {
2015-08-13 19:05:37 -07:00
exportf ( "\tconst %v = %v\n" , Sconv ( s , obj . FmtSharp ) , Vconv ( n . Val ( ) , obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
}
}
func dumpexportvar ( s * Sym ) {
2015-02-23 16:07:24 -05:00
n := s . Def
2015-02-13 14:40:36 -05:00
typecheck ( & n , Erv | Ecall )
if n == nil || n . Type == nil {
2015-04-17 12:03:22 -04:00
Yyerror ( "variable exported but not defined: %v" , s )
2015-02-13 14:40:36 -05:00
return
}
2015-02-23 16:07:24 -05:00
t := n . Type
2015-02-13 14:40:36 -05:00
dumpexporttype ( t )
if t . Etype == TFUNC && n . Class == PFUNC {
2016-02-27 14:31:33 -08:00
if n . Func != nil && len ( n . Func . Inl . Slice ( ) ) != 0 {
2015-02-13 14:40:36 -05:00
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
if Debug [ 'l' ] < 2 {
typecheckinl ( n )
}
// NOTE: The space after %#S here is necessary for ld's export data parser.
2016-03-04 13:16:48 -08:00
exportf ( "\tfunc %v %v { %v }\n" , Sconv ( s , obj . FmtSharp ) , Tconv ( t , obj . FmtShort | obj . FmtSharp ) , Hconv ( n . Func . Inl , obj . FmtSharp | obj . FmtBody ) )
2015-02-13 14:40:36 -05:00
2016-03-04 13:16:48 -08:00
reexportdeplist ( n . Func . Inl )
2015-02-13 14:40:36 -05:00
} else {
2015-08-13 19:05:37 -07:00
exportf ( "\tfunc %v %v\n" , Sconv ( s , obj . FmtSharp ) , Tconv ( t , obj . FmtShort | obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
}
} else {
2015-08-13 19:05:37 -07:00
exportf ( "\tvar %v %v\n" , Sconv ( s , obj . FmtSharp ) , Tconv ( t , obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
}
}
2015-09-14 20:53:44 +02:00
// methodbyname sorts types by symbol name.
2015-02-13 14:40:36 -05:00
type methodbyname [ ] * Type
2015-09-14 20:53:44 +02:00
func ( x methodbyname ) Len ( ) int { return len ( x ) }
func ( x methodbyname ) Swap ( i , j int ) { x [ i ] , x [ j ] = x [ j ] , x [ i ] }
func ( x methodbyname ) Less ( i , j int ) bool { return x [ i ] . Sym . Name < x [ j ] . Sym . Name }
2015-02-13 14:40:36 -05:00
func dumpexporttype ( t * Type ) {
if t == nil {
return
}
2015-09-08 03:51:30 +02:00
if t . Printed || t == Types [ t . Etype ] || t == bytetype || t == runetype || t == errortype {
2015-02-13 14:40:36 -05:00
return
}
2015-09-08 03:51:30 +02:00
t . Printed = true
2015-02-13 14:40:36 -05:00
if t . Sym != nil && t . Etype != TFIELD {
dumppkg ( t . Sym . Pkg )
}
dumpexporttype ( t . Type )
dumpexporttype ( t . Down )
if t . Sym == nil || t . Etype == TFIELD {
return
}
2015-09-14 20:53:44 +02:00
var m [ ] * Type
2016-03-10 01:50:58 -08:00
for f , it := IterMethods ( t ) ; f != nil ; f = it . Next ( ) {
2015-02-13 14:40:36 -05:00
dumpexporttype ( f )
2015-09-14 20:53:44 +02:00
m = append ( m , f )
2015-02-13 14:40:36 -05:00
}
2015-09-14 20:53:44 +02:00
sort . Sort ( methodbyname ( m ) )
2015-02-13 14:40:36 -05:00
2015-08-13 19:05:37 -07:00
exportf ( "\ttype %v %v\n" , Sconv ( t . Sym , obj . FmtSharp ) , Tconv ( t , obj . FmtSharp | obj . FmtLong ) )
2015-09-14 20:53:44 +02:00
for _ , f := range m {
2015-02-17 22:13:49 -05:00
if f . Nointerface {
2015-08-13 19:05:37 -07:00
exportf ( "\t//go:nointerface\n" )
2015-02-13 14:40:36 -05:00
}
2016-02-27 14:31:33 -08:00
if f . Type . Nname != nil && len ( f . Type . Nname . Func . Inl . Slice ( ) ) != 0 { // nname was set by caninl
2015-02-13 14:40:36 -05:00
// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
if Debug [ 'l' ] < 2 {
typecheckinl ( f . Type . Nname )
}
2016-03-09 20:54:59 -08:00
exportf ( "\tfunc (%v) %v %v { %v }\n" , Tconv ( f . Type . Recv ( ) , obj . FmtSharp ) , Sconv ( f . Sym , obj . FmtShort | obj . FmtByte | obj . FmtSharp ) , Tconv ( f . Type , obj . FmtShort | obj . FmtSharp ) , Hconv ( f . Type . Nname . Func . Inl , obj . FmtSharp ) )
2016-03-04 13:16:48 -08:00
reexportdeplist ( f . Type . Nname . Func . Inl )
2015-02-13 14:40:36 -05:00
} else {
2016-03-09 20:54:59 -08:00
exportf ( "\tfunc (%v) %v %v\n" , Tconv ( f . Type . Recv ( ) , obj . FmtSharp ) , Sconv ( f . Sym , obj . FmtShort | obj . FmtByte | obj . FmtSharp ) , Tconv ( f . Type , obj . FmtShort | obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
}
}
}
func dumpsym ( s * Sym ) {
if s . Flags & SymExported != 0 {
return
}
s . Flags |= SymExported
if s . Def == nil {
2015-04-17 12:03:22 -04:00
Yyerror ( "unknown export symbol: %v" , s )
2015-02-13 14:40:36 -05:00
return
}
// print("dumpsym %O %+S\n", s->def->op, s);
dumppkg ( s . Pkg )
switch s . Def . Op {
default :
2016-03-07 08:23:55 -08:00
Yyerror ( "unexpected export symbol: %v %v" , Oconv ( s . Def . Op , 0 ) , s )
2015-02-13 14:40:36 -05:00
case OLITERAL :
dumpexportconst ( s )
case OTYPE :
if s . Def . Type . Etype == TFORW {
2015-04-17 12:03:22 -04:00
Yyerror ( "export of incomplete type %v" , s )
2015-02-13 14:40:36 -05:00
} else {
dumpexporttype ( s . Def . Type )
}
case ONAME :
dumpexportvar ( s )
}
}
func dumpexport ( ) {
2015-04-19 23:56:30 -04:00
if buildid != "" {
2015-08-13 19:05:37 -07:00
exportf ( "build id %q\n" , buildid )
}
size := 0 // size of export section without enclosing markers
if forceNewExport || newexport != 0 {
// binary export
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
exportf ( "\n$$B\n" ) // indicate binary format
const verifyExport = true // enable to check format changes
if verifyExport {
// save a copy of the export data
var copy bytes . Buffer
bcopy := obj . Binitw ( & copy )
size = Export ( bcopy , Debug_export != 0 )
bcopy . Flush ( ) // flushing to bytes.Buffer cannot fail
if n , err := bout . Write ( copy . Bytes ( ) ) ; n != size || err != nil {
Fatalf ( "error writing export data: got %d bytes, want %d bytes, err = %v" , n , size , err )
}
2015-10-23 16:01:09 -07:00
// export data must contain no '$' so that we can find the end by searching for "$$"
if bytes . IndexByte ( copy . Bytes ( ) , '$' ) >= 0 {
Fatalf ( "export data contains $" )
2015-08-13 19:05:37 -07:00
}
2015-02-13 14:40:36 -05:00
2015-08-13 19:05:37 -07:00
// verify that we can read the copied export data back in
// (use empty package map to avoid collisions)
savedPkgMap := pkgMap
savedPkgs := pkgs
pkgMap = make ( map [ string ] * Pkg )
pkgs = nil
importpkg = mkpkg ( "" )
2016-03-11 13:39:20 -05:00
Import ( bufio . NewReader ( & copy ) ) // must not die
2015-08-13 19:05:37 -07:00
importpkg = nil
pkgs = savedPkgs
pkgMap = savedPkgMap
} else {
size = Export ( bout , Debug_export != 0 )
}
exportf ( "\n$$\n" )
} else {
// textual export
lno := lineno
exportf ( "\n$$\n" ) // indicate textual format
exportsize = 0
exportf ( "package %s" , localpkg . Name )
if safemode != 0 {
exportf ( " safe" )
}
exportf ( "\n" )
for _ , p := range pkgs {
if p . Direct {
dumppkg ( p )
}
2015-02-13 14:40:36 -05:00
}
2015-08-13 19:05:37 -07:00
// exportlist grows during iteration - cannot use range
for len ( exportlist ) > 0 {
n := exportlist [ 0 ]
exportlist = exportlist [ 1 : ]
lineno = n . Lineno
dumpsym ( n . Sym )
}
size = exportsize
exportf ( "\n$$\n" )
lineno = lno
2015-02-13 14:40:36 -05:00
}
2015-08-13 19:05:37 -07:00
if Debug_export != 0 {
fmt . Printf ( "export data size = %d bytes\n" , size )
}
2015-02-13 14:40:36 -05:00
}
2015-10-22 09:51:12 +09:00
// import
2015-02-13 14:40:36 -05:00
2015-10-22 09:51:12 +09:00
// return the sym for ss, which should match lexical
2015-09-24 23:21:18 +02:00
func importsym ( s * Sym , op Op ) * Sym {
if s . Def != nil && s . Def . Op != op {
2015-03-02 16:03:26 -05:00
pkgstr := fmt . Sprintf ( "during import %q" , importpkg . Path )
2015-02-13 14:40:36 -05:00
redeclare ( s , pkgstr )
}
// mark the symbol so it is not reexported
if s . Def == nil {
2015-12-01 12:05:30 -08:00
if Debug [ 'A' ] != 0 || exportname ( s . Name ) || initname ( s . Name ) {
2015-02-13 14:40:36 -05:00
s . Flags |= SymExport
} else {
s . Flags |= SymPackage // package scope
}
}
return s
}
2015-10-22 09:51:12 +09:00
// return the type pkg.name, forward declaring if needed
2015-02-13 14:40:36 -05:00
func pkgtype ( s * Sym ) * Type {
importsym ( s , OTYPE )
if s . Def == nil || s . Def . Op != OTYPE {
2015-02-23 16:07:24 -05:00
t := typ ( TFORW )
2015-02-13 14:40:36 -05:00
t . Sym = s
s . Def = typenod ( t )
2015-05-26 23:08:39 -04:00
s . Def . Name = new ( Name )
2015-02-13 14:40:36 -05:00
}
if s . Def . Type == nil {
2015-04-17 12:03:22 -04:00
Yyerror ( "pkgtype %v" , s )
2015-02-13 14:40:36 -05:00
}
return s . Def . Type
}
2015-03-02 16:21:15 -05:00
var numImport = make ( map [ string ] int )
2015-03-02 16:03:26 -05:00
func importimport ( s * Sym , path string ) {
2015-02-13 14:40:36 -05:00
// Informational: record package name
// associated with import path, for use in
// human-readable messages.
2015-03-02 16:03:26 -05:00
if isbadimport ( path ) {
2015-02-13 14:40:36 -05:00
errorexit ( )
}
2015-03-02 16:03:26 -05:00
p := mkpkg ( path )
2015-02-13 14:40:36 -05:00
if p . Name == "" {
p . Name = s . Name
2015-03-02 16:21:15 -05:00
numImport [ s . Name ] ++
2015-02-13 14:40:36 -05:00
} else if p . Name != s . Name {
2015-03-02 16:03:26 -05:00
Yyerror ( "conflicting names %s and %s for package %q" , p . Name , s . Name , p . Path )
2015-02-13 14:40:36 -05:00
}
2015-03-02 16:03:26 -05:00
if incannedimport == 0 && myimportpath != "" && path == myimportpath {
Yyerror ( "import %q: package depends on %q (import cycle)" , importpkg . Path , path )
2015-02-13 14:40:36 -05:00
errorexit ( )
}
}
func importconst ( s * Sym , t * Type , n * Node ) {
importsym ( s , OLITERAL )
Convlit ( & n , t )
if s . Def != nil { // TODO: check if already the same.
return
}
if n . Op != OLITERAL {
Yyerror ( "expression must be a constant" )
return
}
if n . Sym != nil {
2015-02-23 16:07:24 -05:00
n1 := Nod ( OXXX , nil , nil )
2015-02-13 14:40:36 -05:00
* n1 = * n
n = n1
}
n . Orig = newname ( s )
n . Sym = s
declare ( n , PEXTERN )
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "import const %v\n" , s )
2015-02-13 14:40:36 -05:00
}
}
func importvar ( s * Sym , t * Type ) {
importsym ( s , ONAME )
if s . Def != nil && s . Def . Op == ONAME {
if Eqtype ( t , s . Def . Type ) {
return
}
2015-04-17 12:03:22 -04:00
Yyerror ( "inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)" , s , s . Def . Type , s . Importdef . Path , t , importpkg . Path )
2015-02-13 14:40:36 -05:00
}
2015-02-23 16:07:24 -05:00
n := newname ( s )
2015-02-13 14:40:36 -05:00
s . Importdef = importpkg
n . Type = t
declare ( n , PEXTERN )
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "import var %v %v\n" , s , Tconv ( t , obj . FmtLong ) )
2015-02-13 14:40:36 -05:00
}
}
func importtype ( pt * Type , t * Type ) {
// override declaration in unsafe.go for Pointer.
// there is no way in Go code to define unsafe.Pointer
// so we have to supply it.
if incannedimport != 0 && importpkg . Name == "unsafe" && pt . Nod . Sym . Name == "Pointer" {
t = Types [ TUNSAFEPTR ]
}
if pt . Etype == TFORW {
2015-02-23 16:07:24 -05:00
n := pt . Nod
2015-02-13 14:40:36 -05:00
copytype ( pt . Nod , t )
pt . Nod = n // unzero nod
pt . Sym . Importdef = importpkg
2016-03-02 11:01:25 -08:00
pt . Sym . Lastlineno = lineno
2015-02-13 14:40:36 -05:00
declare ( n , PEXTERN )
checkwidth ( pt )
} else if ! Eqtype ( pt . Orig , t ) {
2015-04-17 12:03:22 -04:00
Yyerror ( "inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)" , pt . Sym , Tconv ( pt , obj . FmtLong ) , pt . Sym . Importdef . Path , Tconv ( t , obj . FmtLong ) , importpkg . Path )
2015-02-13 14:40:36 -05:00
}
if Debug [ 'E' ] != 0 {
2015-04-17 12:03:22 -04:00
fmt . Printf ( "import type %v %v\n" , pt , Tconv ( t , obj . FmtLong ) )
2015-02-13 14:40:36 -05:00
}
}
func dumpasmhdr ( ) {
b , err := obj . Bopenw ( asmhdr )
if err != nil {
2015-08-30 23:10:03 +02:00
Fatalf ( "%v" , err )
2015-02-13 14:40:36 -05:00
}
2016-03-04 19:04:50 -08:00
fmt . Fprintf ( b , "// generated by compile -asmhdr from package %s\n\n" , localpkg . Name )
for _ , n := range asmlist {
2015-02-13 14:40:36 -05:00
if isblanksym ( n . Sym ) {
continue
}
switch n . Op {
case OLITERAL :
2015-05-27 00:47:05 -04:00
fmt . Fprintf ( b , "#define const_%s %v\n" , n . Sym . Name , Vconv ( n . Val ( ) , obj . FmtSharp ) )
2015-02-13 14:40:36 -05:00
case OTYPE :
2016-03-04 19:04:50 -08:00
t := n . Type
2015-09-08 03:51:30 +02:00
if t . Etype != TSTRUCT || t . Map != nil || t . Funarg {
2015-02-13 14:40:36 -05:00
break
}
fmt . Fprintf ( b , "#define %s__size %d\n" , t . Sym . Name , int ( t . Width ) )
2016-03-10 01:50:58 -08:00
for t , it := IterFields ( t ) ; t != nil ; t = it . Next ( ) {
2015-02-13 14:40:36 -05:00
if ! isblanksym ( t . Sym ) {
fmt . Fprintf ( b , "#define %s_%s %d\n" , n . Sym . Name , t . Sym . Name , int ( t . Width ) )
}
}
}
}
obj . Bterm ( b )
}