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"
|
2016-04-06 21:45:29 -07:00
|
|
|
"cmd/internal/bio"
|
2015-02-13 14:40:36 -05:00
|
|
|
"fmt"
|
|
|
|
|
"unicode"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
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
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func exportf(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
|
|
|
|
|
|
|
|
// Mark n's symbol as exported
|
|
|
|
|
func exportsym(n *Node) {
|
|
|
|
|
if n == nil || n.Sym == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-03-06 20:00:54 +02:00
|
|
|
if n.Sym.Export() || n.Sym.Package() {
|
|
|
|
|
if n.Sym.Package() {
|
2017-03-14 09:46:45 -07:00
|
|
|
Fatalf("export/package mismatch: %v", n.Sym)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-06 20:00:54 +02:00
|
|
|
n.Sym.SetExport(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
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
|
|
|
}
|
2016-11-02 09:47:43 -07:00
|
|
|
|
2017-01-11 11:24:35 -08:00
|
|
|
// Ensure original types are on exportlist before type aliases.
|
|
|
|
|
if n.Sym.isAlias() {
|
2016-11-02 09:47:43 -07:00
|
|
|
exportlist = append(exportlist, n.Sym.Def)
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2017-01-23 14:24:24 -08:00
|
|
|
if n.Type != nil && n.Type.IsKind(TFUNC) && n.Type.Recv() != nil { // method
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-19 12:58:16 -07:00
|
|
|
if exportname(n.Sym.Name) || initname(n.Sym.Name) {
|
2015-02-13 14:40:36 -05:00
|
|
|
exportsym(n)
|
|
|
|
|
}
|
2017-03-06 20:00:54 +02:00
|
|
|
if asmhdr != "" && n.Sym.Pkg == localpkg && !n.Sym.Asm() {
|
|
|
|
|
n.Sym.SetAsm(true)
|
2016-03-04 19:04:50 -08:00
|
|
|
asmlist = append(asmlist, n)
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case ONAME:
|
cmd/compile: fix liveness computation for heap-escaped parameters
The liveness computation of parameters generally was never
correct, but forcing all parameters to be live throughout the
function covered up that problem. The new SSA back end is
too clever: even though it currently keeps the parameter values live
throughout the function, it may find optimizations that mean
the current values are not written back to the original parameter
stack slots immediately or ever (for example if a parameter is set
to nil, SSA constant propagation may replace all later uses of the
parameter with a constant nil, eliminating the need to write the nil
value back to the stack slot), so the liveness code must now
track the actual operations on the stack slots, exposing these
problems.
One small problem in the handling of arguments is that nodarg
can return ONAME PPARAM nodes with adjusted offsets, so that
there are actually multiple *Node pointers for the same parameter
in the instruction stream. This might be possible to correct, but
not in this CL. For now, we fix this by using n.Orig instead of n
when considering PPARAM and PPARAMOUT nodes.
The major problem in the handling of arguments is general
confusion in the liveness code about the meaning of PPARAM|PHEAP
and PPARAMOUT|PHEAP nodes, especially as contrasted with PAUTO|PHEAP.
The difference between these two is that when a local variable "moves"
to the heap, it's really just allocated there to start with; in contrast,
when an argument moves to the heap, the actual data has to be copied
there from the stack at the beginning of the function, and when a
result "moves" to the heap the value in the heap has to be copied
back to the stack when the function returns
This general confusion is also present in the SSA back end.
The PHEAP bit worked decently when I first introduced it 7 years ago (!)
in 391425ae. The back end did nothing sophisticated, and in particular
there was no analysis at all: no escape analysis, no liveness analysis,
and certainly no SSA back end. But the complications caused in the
various downstream consumers suggest that this should be a detail
kept mainly in the front end.
This CL therefore eliminates both the PHEAP bit and even the idea of
"heap variables" from the back ends.
First, it replaces the PPARAM|PHEAP, PPARAMOUT|PHEAP, and PAUTO|PHEAP
variable classes with the single PAUTOHEAP, a pseudo-class indicating
a variable maintained on the heap and available by indirecting a
local variable kept on the stack (a plain PAUTO).
Second, walkexpr replaces all references to PAUTOHEAP variables
with indirections of the corresponding PAUTO variable.
The back ends and the liveness code now just see plain indirected
variables. This may actually produce better code, but the real goal
here is to eliminate these little-used and somewhat suspect code
paths in the back end analyses.
The OPARAM node type goes away too.
A followup CL will do the same to PPARAMREF. I'm not sure that
the back ends (SSA in particular) are handling those right either,
and with the framework established in this CL that change is trivial
and the result clearly more correct.
Fixes #15747.
Change-Id: I2770b1ce3cbc93981bfc7166be66a9da12013d74
Reviewed-on: https://go-review.googlesource.com/23393
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-05-25 01:33:24 -04:00
|
|
|
switch n.Class {
|
2015-02-13 14:40:36 -05:00
|
|
|
// 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.
|
2016-09-11 14:43:37 -07:00
|
|
|
if n.Type == nil || n.IsMethod() {
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2015-09-14 20:53:44 +02:00
|
|
|
// methodbyname sorts types by symbol name.
|
2016-03-14 01:20:49 -07:00
|
|
|
type methodbyname []*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
|
|
|
|
|
|
|
|
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
|
2016-08-16 12:55:17 -07:00
|
|
|
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
|
|
|
|
|
exportf("\n$$B\n") // indicate binary export format
|
|
|
|
|
if debugFormat {
|
|
|
|
|
// save a copy of the export data
|
|
|
|
|
var copy bytes.Buffer
|
|
|
|
|
bcopy := bufio.NewWriter(©)
|
|
|
|
|
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-08-13 19:05:37 -07:00
|
|
|
}
|
2016-08-16 12:55:17 -07:00
|
|
|
// export data must contain no '$' so that we can find the end by searching for "$$"
|
|
|
|
|
// TODO(gri) is this still needed?
|
|
|
|
|
if bytes.IndexByte(copy.Bytes(), '$') >= 0 {
|
|
|
|
|
Fatalf("export data contains $")
|
2015-08-13 19:05:37 -07:00
|
|
|
}
|
|
|
|
|
|
2016-08-16 12:55:17 -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
|
2017-03-23 17:39:28 -07:00
|
|
|
Import(mkpkg(""), bufio.NewReader(©)) // must not die
|
2016-08-16 12:55:17 -07:00
|
|
|
pkgs = savedPkgs
|
|
|
|
|
pkgMap = savedPkgMap
|
|
|
|
|
} else {
|
|
|
|
|
size = export(bout.Writer, Debug_export != 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-08-16 12:55:17 -07:00
|
|
|
exportf("\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
|
|
|
}
|
|
|
|
|
|
2016-04-04 15:41:56 -07:00
|
|
|
// importsym declares symbol s as an imported object representable by op.
|
2017-03-23 17:39:28 -07:00
|
|
|
// pkg is the package being imported
|
|
|
|
|
func importsym(pkg *Pkg, s *Sym, op Op) {
|
2015-09-24 23:21:18 +02:00
|
|
|
if s.Def != nil && s.Def.Op != op {
|
2017-03-23 17:39:28 -07:00
|
|
|
pkgstr := fmt.Sprintf("during import %q", pkg.Path)
|
2015-02-13 14:40:36 -05:00
|
|
|
redeclare(s, pkgstr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mark the symbol so it is not reexported
|
|
|
|
|
if s.Def == nil {
|
2016-10-19 12:58:16 -07:00
|
|
|
if exportname(s.Name) || initname(s.Name) {
|
2017-03-06 20:00:54 +02:00
|
|
|
s.SetExport(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2017-03-06 20:00:54 +02:00
|
|
|
s.SetPackage(true) // package scope
|
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.
|
2017-03-23 17:39:28 -07:00
|
|
|
// pkg is the package being imported
|
|
|
|
|
func pkgtype(pkg *Pkg, s *Sym) *Type {
|
|
|
|
|
importsym(pkg, s, OTYPE)
|
2015-02-13 14:40:36 -05:00
|
|
|
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 {
|
2017-03-14 09:46:45 -07:00
|
|
|
Fatalf("pkgtype %v", s)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return s.Def.Type
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-04 15:41:56 -07:00
|
|
|
// importconst declares symbol s as an imported constant with type t and value n.
|
2017-03-23 17:39:28 -07:00
|
|
|
// pkg is the package being imported
|
|
|
|
|
func importconst(pkg *Pkg, s *Sym, t *Type, n *Node) {
|
|
|
|
|
importsym(pkg, s, OLITERAL)
|
cmd/compile: reduce use of **Node parameters
Escape analysis has a hard time with tree-like
structures (see #13493 and #14858).
This is unlikely to change.
As a result, when invoking a function that accepts
a **Node parameter, we usually allocate a *Node
on the heap. This happens a whole lot.
This CL changes functions from taking a **Node
to acting more like append: It both modifies
the input and returns a replacement for it.
Because of the cascading nature of escape analysis,
in order to get the benefits, I had to modify
almost all such functions. The remaining functions
are in racewalk and the backend. I would be happy
to update them as well in a separate CL.
This CL was created by manually updating the
function signatures and the directly impacted
bits of code. The callsites were then automatically
updated using a bespoke script:
https://gist.github.com/josharian/046b1be7aceae244de39
For ease of reviewing and future understanding,
this CL is also broken down into four CLs,
mailed separately, which show the manual
and the automated changes separately.
They are CLs 20990, 20991, 20992, and 20993.
Passes toolstash -cmp.
name old time/op new time/op delta
Template 335ms ± 5% 324ms ± 5% -3.35% (p=0.000 n=23+24)
Unicode 176ms ± 9% 165ms ± 6% -6.12% (p=0.000 n=23+24)
GoTypes 1.10s ± 4% 1.07s ± 2% -2.77% (p=0.000 n=24+24)
Compiler 5.31s ± 3% 5.15s ± 3% -2.95% (p=0.000 n=24+24)
MakeBash 41.6s ± 1% 41.7s ± 2% ~ (p=0.586 n=23+23)
name old alloc/op new alloc/op delta
Template 63.3MB ± 0% 62.4MB ± 0% -1.36% (p=0.000 n=25+23)
Unicode 42.4MB ± 0% 41.6MB ± 0% -1.99% (p=0.000 n=24+25)
GoTypes 220MB ± 0% 217MB ± 0% -1.11% (p=0.000 n=25+25)
Compiler 994MB ± 0% 973MB ± 0% -2.08% (p=0.000 n=24+25)
name old allocs/op new allocs/op delta
Template 681k ± 0% 574k ± 0% -15.71% (p=0.000 n=24+25)
Unicode 518k ± 0% 413k ± 0% -20.34% (p=0.000 n=25+24)
GoTypes 2.08M ± 0% 1.78M ± 0% -14.62% (p=0.000 n=25+25)
Compiler 9.26M ± 0% 7.64M ± 0% -17.48% (p=0.000 n=25+25)
name old text-bytes new text-bytes delta
HelloSize 578k ± 0% 578k ± 0% ~ (all samples are equal)
CmdGoSize 6.46M ± 0% 6.46M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 281k ± 0% 281k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 921k ± 0% 921k ± 0% ~ (all samples are equal)
CmdGoSize 9.86M ± 0% 9.86M ± 0% ~ (all samples are equal)
Change-Id: I277d95bd56d51c166ef7f560647aeaa092f3f475
Reviewed-on: https://go-review.googlesource.com/20959
Reviewed-by: Dave Cheney <dave@cheney.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-03-20 08:03:31 -07:00
|
|
|
n = convlit(n, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if s.Def != nil { // TODO: check if already the same.
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op != OLITERAL {
|
2016-09-15 15:45:10 +10:00
|
|
|
yyerror("expression must be a constant")
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Sym != nil {
|
2016-03-23 16:01:15 +11:00
|
|
|
n1 := *n
|
|
|
|
|
n = &n1
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-04 15:41:56 -07:00
|
|
|
// importvar declares symbol s as an imported variable with type t.
|
2017-03-23 17:39:28 -07:00
|
|
|
// pkg is the package being imported
|
|
|
|
|
func importvar(pkg *Pkg, s *Sym, t *Type) {
|
|
|
|
|
importsym(pkg, s, ONAME)
|
2015-02-13 14:40:36 -05:00
|
|
|
if s.Def != nil && s.Def.Op == ONAME {
|
2016-09-15 14:34:20 +10:00
|
|
|
if eqtype(t, s.Def.Type) {
|
2015-02-13 14:40:36 -05:00
|
|
|
return
|
|
|
|
|
}
|
2017-03-23 17:39:28 -07: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, pkg.Path)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
n := newname(s)
|
2017-03-23 17:39:28 -07:00
|
|
|
s.Importdef = pkg
|
2015-02-13 14:40:36 -05:00
|
|
|
n.Type = t
|
|
|
|
|
declare(n, PEXTERN)
|
|
|
|
|
|
|
|
|
|
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.
|
2017-03-23 17:39:28 -07:00
|
|
|
// pkg is the package being imported
|
|
|
|
|
func importalias(pkg *Pkg, s *Sym, t *Type) {
|
|
|
|
|
importsym(pkg, s, OTYPE)
|
2017-01-11 11:24:35 -08:00
|
|
|
if s.Def != nil && s.Def.Op == OTYPE {
|
|
|
|
|
if eqtype(t, s.Def.Type) {
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-03-23 17:39:28 -07:00
|
|
|
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, pkg.Path)
|
2017-01-11 11:24:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n := newname(s)
|
|
|
|
|
n.Op = OTYPE
|
2017-03-23 17:39:28 -07:00
|
|
|
s.Importdef = pkg
|
2017-01-11 11:24:35 -08:00
|
|
|
n.Type = t
|
|
|
|
|
declare(n, PEXTERN)
|
|
|
|
|
|
|
|
|
|
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 {
|
2015-02-13 14:40:36 -05:00
|
|
|
if isblanksym(n.Sym) {
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(b, "#define %s__size %d\n", t.Sym.Name, int(t.Width))
|
2016-03-17 01:32:18 -07:00
|
|
|
for _, t := range t.Fields().Slice() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if !isblanksym(t.Sym) {
|
2016-03-28 09:40:53 -07:00
|
|
|
fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, t.Sym.Name, int(t.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
|
|
|
}
|