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 (
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
"cmd/compile/internal/types"
|
2016-04-06 21:45:29 -07:00
|
|
|
"cmd/internal/bio"
|
2017-08-28 13:02:58 -07:00
|
|
|
"cmd/internal/src"
|
2015-02-13 14:40:36 -05:00
|
|
|
"fmt"
|
|
|
|
|
)
|
|
|
|
|
|
2015-08-13 19:05:37 -07:00
|
|
|
var (
|
2016-08-16 12:55:17 -07:00
|
|
|
Debug_export int // if set, print debugging information about export data
|
2015-08-13 19:05:37 -07:00
|
|
|
)
|
|
|
|
|
|
2017-08-30 17:43:19 -07:00
|
|
|
func exportf(bout *bio.Writer, format string, args ...interface{}) {
|
2017-03-13 14:30:44 +11:00
|
|
|
fmt.Fprintf(bout, format, args...)
|
2015-08-13 19:05:37 -07:00
|
|
|
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
|
|
|
|
2018-04-02 15:38:57 -07:00
|
|
|
// exportsym marks n for export (or reexport).
|
2015-02-13 14:40:36 -05:00
|
|
|
func exportsym(n *Node) {
|
2018-04-02 15:38:57 -07:00
|
|
|
if n.Sym.OnExportList() {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
2018-04-02 15:38:57 -07:00
|
|
|
n.Sym.SetOnExportList(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if Debug['E'] != 0 {
|
2018-04-02 16:15:25 -07:00
|
|
|
fmt.Printf("export symbol %v\n", n.Sym)
|
cmd/compile: simplify reexport logic
Currently, we reexport any package-scope constant, function, type, or
variable declarations needed by an inlineable function body. However,
now that we have an early pass to walk inlineable function bodies
(golang.org/cl/74110), we can simplify the logic for finding these
declarations.
The binary export format supports writing out type declarations
in-place at their first use. Also, it always writes out constants by
value, so their declarations never need to be reexported.
Notably, we attempted this before (golang.org/cl/36170) and had to
revert it (golang.org/cl/45911). However, this was because while
writing out inline bodies, we could discover variable/function
dependencies. By collecting variable/function dependencies during
inlineable function discovery, we avoid this problem.
While here, get rid of isInlineable. We already typecheck inlineable
function bodies during inlFlood, so it's become a no-op. Just move the
comment explaining parameter numbering to its caller.
Change-Id: Ibbfaafce793733675d3a2ad98791758583055666
Reviewed-on: https://go-review.googlesource.com/103864
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-03-30 18:58:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exportlist = append(exportlist, n)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func initname(s string) bool {
|
|
|
|
|
return s == "init"
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-10-26 14:57:36 -07:00
|
|
|
func autoexport(n *Node, ctxt Class) {
|
2018-04-02 15:38:57 -07:00
|
|
|
if n.Sym.Pkg != localpkg {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-10-20 11:56:31 +01:00
|
|
|
if n.Type != nil && n.Type.IsKind(TFUNC) && n.IsMethod() {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-09 15:22:01 -07:00
|
|
|
if types.IsExported(n.Sym.Name) || initname(n.Sym.Name) {
|
2015-02-13 14:40:36 -05:00
|
|
|
exportsym(n)
|
|
|
|
|
}
|
2018-04-02 15:38:57 -07:00
|
|
|
if asmhdr != "" && !n.Sym.Asm() {
|
2017-03-06 20:00:54 +02:00
|
|
|
n.Sym.SetAsm(true)
|
2016-03-04 19:04:50 -08:00
|
|
|
asmlist = append(asmlist, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-14 20:53:44 +02:00
|
|
|
// methodbyname sorts types by symbol name.
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
type methodbyname []*types.Field
|
2015-02-13 14:40:36 -05:00
|
|
|
|
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
|
|
|
|
2017-08-30 17:43:19 -07:00
|
|
|
func dumpexport(bout *bio.Writer) {
|
2016-08-16 12:55:17 -07:00
|
|
|
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
|
2017-08-30 17:43:19 -07:00
|
|
|
exportf(bout, "\n$$B\n") // indicate binary export format
|
2018-04-01 01:55:55 -07:00
|
|
|
off := bout.Offset()
|
2018-10-03 10:56:23 -07:00
|
|
|
iexport(bout.Writer)
|
2018-04-01 01:55:55 -07:00
|
|
|
size := bout.Offset() - off
|
2017-08-30 17:43:19 -07:00
|
|
|
exportf(bout, "\n$$\n")
|
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
|
|
|
}
|
|
|
|
|
|
2018-06-11 09:11:29 +01:00
|
|
|
func importsym(ipkg *types.Pkg, s *types.Sym, op Op) *Node {
|
2018-06-21 16:12:17 -07:00
|
|
|
n := asNode(s.PkgDef())
|
2018-04-17 14:40:56 -07:00
|
|
|
if n == nil {
|
2018-04-01 01:55:55 -07:00
|
|
|
// iimport should have created a stub ONONAME
|
|
|
|
|
// declaration for all imported symbols. The exception
|
|
|
|
|
// is declarations for Runtimepkg, which are populated
|
|
|
|
|
// by loadsys instead.
|
2018-10-03 10:56:23 -07:00
|
|
|
if s.Pkg != Runtimepkg {
|
2018-04-01 01:55:55 -07:00
|
|
|
Fatalf("missing ONONAME for %v\n", s)
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:40:56 -07:00
|
|
|
n = dclname(s)
|
2018-06-21 16:12:17 -07:00
|
|
|
s.SetPkgDef(asTypesNode(n))
|
2018-04-17 14:40:56 -07:00
|
|
|
s.Importdef = ipkg
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2018-04-17 14:40:56 -07:00
|
|
|
if n.Op != ONONAME && n.Op != op {
|
|
|
|
|
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
|
|
|
|
}
|
|
|
|
|
return n
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-04 15:41:56 -07:00
|
|
|
// pkgtype returns the named type declared by symbol s.
|
|
|
|
|
// If no such type has been declared yet, a forward declaration is returned.
|
2018-04-17 14:40:56 -07:00
|
|
|
// ipkg is the package being imported
|
|
|
|
|
func importtype(ipkg *types.Pkg, pos src.XPos, s *types.Sym) *types.Type {
|
2018-06-11 09:11:29 +01:00
|
|
|
n := importsym(ipkg, s, OTYPE)
|
2018-04-17 14:40:56 -07:00
|
|
|
if n.Op != OTYPE {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
t := types.New(TFORW)
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Sym = s
|
2018-04-17 14:40:56 -07:00
|
|
|
t.Nod = asTypesNode(n)
|
|
|
|
|
|
|
|
|
|
n.Op = OTYPE
|
|
|
|
|
n.Pos = pos
|
|
|
|
|
n.Type = t
|
|
|
|
|
n.SetClass(PEXTERN)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:40:56 -07:00
|
|
|
t := n.Type
|
|
|
|
|
if t == nil {
|
|
|
|
|
Fatalf("importtype %v", s)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2018-04-17 14:40:56 -07:00
|
|
|
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 {
|
2018-06-11 09:11:29 +01:00
|
|
|
n := importsym(ipkg, s, op)
|
2018-04-17 14:40:56 -07:00
|
|
|
if n.Op != ONONAME {
|
2018-10-18 15:24:50 -07:00
|
|
|
if n.Op == op && (n.Class() != ctxt || !types.Identical(n.Type, t)) {
|
2018-04-17 14:40:56 -07:00
|
|
|
redeclare(lineno, s, fmt.Sprintf("during import %q", ipkg.Path))
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n.Op = op
|
|
|
|
|
n.Pos = pos
|
|
|
|
|
n.SetClass(ctxt)
|
|
|
|
|
n.Type = t
|
|
|
|
|
return n
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-02 17:33:38 -07:00
|
|
|
// importconst declares symbol s as an imported constant with type t and value val.
|
2018-04-17 14:40:56 -07:00
|
|
|
// 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.
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:40:56 -07:00
|
|
|
n.SetVal(val)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if Debug['E'] != 0 {
|
2018-04-17 14:40:56 -07:00
|
|
|
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:40:56 -07:00
|
|
|
// 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
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-17 14:40:56 -07:00
|
|
|
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
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if Debug['E'] != 0 {
|
2016-09-09 21:08:46 -07:00
|
|
|
fmt.Printf("import var %v %L\n", s, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-11 11:24:35 -08:00
|
|
|
// importalias declares symbol s as an imported type alias with type t.
|
2018-04-17 14:40:56 -07:00
|
|
|
// 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
|
2017-01-11 11:24:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Debug['E'] != 0 {
|
|
|
|
|
fmt.Printf("import type %v = %L\n", s, t)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func dumpasmhdr() {
|
2016-04-06 21:45:29 -07:00
|
|
|
b, err := bio.Create(asmhdr)
|
2015-02-13 14:40:36 -05:00
|
|
|
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 {
|
2017-04-21 07:51:41 -07:00
|
|
|
if n.Sym.IsBlank() {
|
2015-02-13 14:40:36 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case OLITERAL:
|
2016-08-30 15:01:48 -07:00
|
|
|
fmt.Fprintf(b, "#define const_%s %#v\n", n.Sym.Name, n.Val())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTYPE:
|
2016-03-04 19:04:50 -08:00
|
|
|
t := n.Type
|
2016-04-01 20:11:30 -07:00
|
|
|
if !t.IsStruct() || t.StructType().Map != nil || t.IsFuncArgStruct() {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
2017-11-29 11:58:03 -08:00
|
|
|
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))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 21:45:29 -07:00
|
|
|
b.Close()
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|