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
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
}
}
// 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 :
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-03-17 01:47:16 -07:00
if n . Type == nil || n . Type . Recv ( ) != nil {
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 {
2016-03-30 15:09:25 -07:00
if t . IsPtr ( ) {
2016-03-30 10:57:47 -07:00
t = t . Elem ( )
2015-02-13 14:40:36 -05:00
}
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 {
2016-03-30 15:09:25 -07:00
if t . IsPtr ( ) {
2016-03-30 10:57:47 -07:00
t = t . Elem ( )
2015-02-13 14:40:36 -05:00
}
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 :
2016-03-16 18:44:17 -05:00
if n . Sym != nil && n . Sym . Def != 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 ,
2016-06-19 07:20:28 -07:00
OSLICELIT ,
2015-02-13 14:40:36 -05:00
OPTRLIT ,
OMAKEMAP ,
OMAKESLICE ,
OMAKECHAN :
2015-02-23 16:07:24 -05:00
t := n . Type
2015-02-13 14:40:36 -05:00
2016-03-13 23:02:38 -07:00
switch t . Etype {
2016-04-18 14:02:08 -07:00
case TARRAY , TCHAN , TPTR32 , TPTR64 , TSLICE :
2016-03-13 23:02:38 -07:00
if t . Sym == nil {
2016-03-30 10:57:47 -07:00
t = t . Elem ( )
2016-03-13 23:02:38 -07:00
}
2015-02-13 14:40:36 -05:00
}
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
}
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 ( & 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-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
importpkg = mkpkg ( "" )
Import ( bufio . NewReader ( & copy ) ) // must not die
importpkg = nil
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.
func importsym ( s * Sym , op Op ) {
2015-09-24 23:21:18 +02:00
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
}
}
}
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.
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
}
2016-04-04 15:41:56 -07:00
// importconst declares symbol s as an imported constant with type t and value n.
2015-02-13 14:40:36 -05:00
func importconst ( s * Sym , t * Type , n * Node ) {
importsym ( 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 {
Yyerror ( "expression must be a constant" )
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.
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 {
2016-03-15 13:06:58 -07:00
fmt . Printf ( "import var %v %v\n" , s , Tconv ( t , FmtLong ) )
2015-02-13 14:40:36 -05:00
}
}
2016-05-05 09:39:50 -07:00
// importtype and importer.importtype (bimport.go) need to remain in sync.
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 ) {
2016-03-15 13:06:58 -07:00
Yyerror ( "inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)" , pt . Sym , Tconv ( pt , FmtLong ) , pt . Sym . Importdef . Path , Tconv ( t , FmtLong ) , importpkg . Path )
2015-02-13 14:40:36 -05:00
}
if Debug [ 'E' ] != 0 {
2016-03-15 13:06:58 -07:00
fmt . Printf ( "import type %v %v\n" , pt , Tconv ( t , FmtLong ) )
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
}