mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Change-Id: I2fc5cff7495b5db4eb8f286a5335787241f1a850
GitHub-Last-Rev: 1d226f14c8
GitHub-Pull-Request: golang/go#41917
Reviewed-on: https://go-review.googlesource.com/c/go/+/261317
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Robert Griesemer <gri@golang.org>
233 lines
5.3 KiB
Go
233 lines
5.3 KiB
Go
// 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 (
|
|
"cmd/compile/internal/types"
|
|
"cmd/internal/bio"
|
|
"cmd/internal/src"
|
|
"fmt"
|
|
)
|
|
|
|
var (
|
|
Debug_export int // if set, print debugging information about export data
|
|
)
|
|
|
|
func exportf(bout *bio.Writer, format string, args ...interface{}) {
|
|
fmt.Fprintf(bout, format, args...)
|
|
if Debug_export != 0 {
|
|
fmt.Printf(format, args...)
|
|
}
|
|
}
|
|
|
|
var asmlist []*Node
|
|
|
|
// exportsym marks n for export (or reexport).
|
|
func exportsym(n *Node) {
|
|
if n.Sym.OnExportList() {
|
|
return
|
|
}
|
|
n.Sym.SetOnExportList(true)
|
|
|
|
if Debug['E'] != 0 {
|
|
fmt.Printf("export symbol %v\n", n.Sym)
|
|
}
|
|
|
|
exportlist = append(exportlist, n)
|
|
}
|
|
|
|
func initname(s string) bool {
|
|
return s == "init"
|
|
}
|
|
|
|
func autoexport(n *Node, ctxt Class) {
|
|
if n.Sym.Pkg != localpkg {
|
|
return
|
|
}
|
|
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
|
|
return
|
|
}
|
|
if n.Type != nil && n.Type.IsKind(TFUNC) && n.IsMethod() {
|
|
return
|
|
}
|
|
|
|
if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) {
|
|
exportsym(n)
|
|
}
|
|
if asmhdr != "" && !n.Sym.Asm() {
|
|
n.Sym.SetAsm(true)
|
|
asmlist = append(asmlist, n)
|
|
}
|
|
}
|
|
|
|
func dumpexport(bout *bio.Writer) {
|
|
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
|
|
exportf(bout, "\n$$B\n") // indicate binary export format
|
|
off := bout.Offset()
|
|
iexport(bout.Writer)
|
|
size := bout.Offset() - off
|
|
exportf(bout, "\n$$\n")
|
|
|
|
if Debug_export != 0 {
|
|
fmt.Printf("BenchmarkExportSize:%s 1 %d bytes\n", myimportpath, size)
|
|
}
|
|
}
|
|
|
|
func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
|
|
n := asNode(s.PkgDef())
|
|
if n == nil {
|
|
// iimport should have created a stub ONONAME
|
|
// declaration for all imported symbols. The exception
|
|
// is declarations for Runtimepkg, which are populated
|
|
// by loadsys instead.
|
|
if s.Pkg != Runtimepkg {
|
|
Fatalf("missing ONONAME for %v\n", s)
|
|
}
|
|
|
|
n = dclname(s)
|
|
s.SetPkgDef(asTypesNode(n))
|
|
s.Importdef = ipkg
|
|
}
|
|
if n.Op != ONONAME && n.Op != op {
|
|
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
|
}
|
|
return n
|
|
}
|
|
|
|
// importtype returns the named type declared by symbol s.
|
|
// If no such type has been declared yet, a forward declaration is returned.
|
|
// ipkg is the package being imported
|
|
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
|
n := importsym(ipkg, s, OTYPE)
|
|
if n.Op != OTYPE {
|
|
t := types.New(TFORW)
|
|
t.Sym = s
|
|
t.Nod = asTypesNode(n)
|
|
|
|
n.Op = OTYPE
|
|
n.Pos = pos
|
|
n.Type = t
|
|
n.SetClass(PEXTERN)
|
|
}
|
|
|
|
t := n.Type
|
|
if t == nil {
|
|
Fatalf("importtype %v", s)
|
|
}
|
|
return t
|
|
}
|
|
|
|
// importobj declares symbol s as an imported object representable by op.
|
|
// ipkg is the package being imported
|
|
func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t *types.Type) *Node {
|
|
n := importsym(ipkg, s, op)
|
|
if n.Op != ONONAME {
|
|
if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) {
|
|
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
n.Op = op
|
|
n.Pos = pos
|
|
n.SetClass(ctxt)
|
|
if ctxt == PFUNC {
|
|
n.Sym.SetFunc(true)
|
|
}
|
|
n.Type = t
|
|
return n
|
|
}
|
|
|
|
// importconst declares symbol s as an imported constant with type t and value val.
|
|
// ipkg is the package being imported
|
|
func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val Val) {
|
|
n := importobj(ipkg, pos, s, OLITERAL, PEXTERN, t)
|
|
if n == nil { // TODO: Check that value matches.
|
|
return
|
|
}
|
|
|
|
n.SetVal(val)
|
|
|
|
if Debug['E'] != 0 {
|
|
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
|
}
|
|
}
|
|
|
|
// importfunc declares symbol s as an imported function with type t.
|
|
// ipkg is the package being imported
|
|
func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
|
n := importobj(ipkg, pos, s, ONAME, PFUNC, t)
|
|
if n == nil {
|
|
return
|
|
}
|
|
|
|
n.Func = new(Func)
|
|
t.SetNname(asTypesNode(n))
|
|
|
|
if Debug['E'] != 0 {
|
|
fmt.Printf("import func %v%S\n", s, t)
|
|
}
|
|
}
|
|
|
|
// importvar declares symbol s as an imported variable with type t.
|
|
// ipkg is the package being imported
|
|
func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
|
n := importobj(ipkg, pos, s, ONAME, PEXTERN, t)
|
|
if n == nil {
|
|
return
|
|
}
|
|
|
|
if Debug['E'] != 0 {
|
|
fmt.Printf("import var %v %L\n", s, t)
|
|
}
|
|
}
|
|
|
|
// importalias declares symbol s as an imported type alias with type t.
|
|
// ipkg is the package being imported
|
|
func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
|
n := importobj(ipkg, pos, s, OTYPE, PEXTERN, t)
|
|
if n == nil {
|
|
return
|
|
}
|
|
|
|
if Debug['E'] != 0 {
|
|
fmt.Printf("import type %v = %L\n", s, t)
|
|
}
|
|
}
|
|
|
|
func dumpasmhdr() {
|
|
b, err := bio.Create(asmhdr)
|
|
if err != nil {
|
|
Fatalf("%v", err)
|
|
}
|
|
fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", localpkg.Name)
|
|
for _, n := range asmlist {
|
|
if n.Sym.IsBlank() {
|
|
continue
|
|
}
|
|
switch n.Op {
|
|
case OLITERAL:
|
|
t := n.Val().Ctype()
|
|
if t == CTFLT || t == CTCPLX {
|
|
break
|
|
}
|
|
fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym.Name, n.Val())
|
|
|
|
case OTYPE:
|
|
t := n.Type
|
|
if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() {
|
|
break
|
|
}
|
|
fmt.Fprintf(b, "#define %s__size %d\n", n.Sym.Name, int(t.Width))
|
|
for _, f := range t.Fields().Slice() {
|
|
if !f.Sym.IsBlank() {
|
|
fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, f.Sym.Name, int(f.Offset))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
b.Close()
|
|
}
|