cmd/5l etc: restore comments lost during C -> Go conversion

It appears that c2go dropped comments inside struct { ... } and enum { ... }.
Restore them.

Identified missing comments by checking for comments present
in the C code but not the Go code, made a list, and then reapplied
with some mechanical help.

Missing comment finder: http://play.golang.org/p/g6qNUAo1Y0

Change-Id: I323ab45c7ef9d51e28eab3b699eb14bee1eef66b
Reviewed-on: https://go-review.googlesource.com/6899
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Russ Cox 2015-03-05 13:57:36 -05:00
parent d970bea885
commit cdb7d7dcc2
36 changed files with 1271 additions and 931 deletions

View file

@ -619,7 +619,7 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
} }
if ld.Debug['w'] == 0 { if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support
dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
ld.Cseek(int64(dwarfoff)) ld.Cseek(int64(dwarfoff))

View file

@ -67,8 +67,8 @@ const (
PtrSize = 4 PtrSize = 4
IntSize = 4 IntSize = 4
RegSize = 4 RegSize = 4
MaxAlign = 8 MaxAlign = 8 // max data alignment
FuncAlign = 4 FuncAlign = 4 // single-instruction alignment
MINLC = 4 MINLC = 4
) )

View file

@ -134,11 +134,11 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
r.Type = ld.R_ADDR r.Type = ld.R_ADDR
return return
// TODO: What is the difference between all these?
// Handle relocations found in Mach-O object files. // Handle relocations found in Mach-O object files.
case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0, case 512 + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0, 512 + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0: 512 + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
// TODO: What is the difference between all these?
r.Type = ld.R_ADDR r.Type = ld.R_ADDR
if targ.Type == ld.SDYNIMPORT { if targ.Type == ld.SDYNIMPORT {

View file

@ -1,37 +1,3 @@
// Inferno utils/6l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/6l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
// Writing object files.
// Inferno utils/6l/l.h // Inferno utils/6l/l.h
// http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h // http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h
// //
@ -62,9 +28,11 @@ package main
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
package main
const ( const (
thechar = '6' thechar = '6'
MaxAlign = 32 MaxAlign = 32 // max data alignment
FuncAlign = 16 FuncAlign = 16
) )

View file

@ -34,7 +34,7 @@ import "cmd/internal/obj/x86"
import "cmd/internal/gc" import "cmd/internal/gc"
const ( const (
NREGVAR = 16 NREGVAR = 16 /* 8 integer + 8 floating */
) )
var regname = []string{ var regname = []string{

View file

@ -1,37 +1,3 @@
// Inferno utils/8l/asm.c
// http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
// Writing object files.
// Inferno utils/8l/l.h // Inferno utils/8l/l.h
// http://code.google.com/p/inferno-os/source/browse/utils/8l/l.h // http://code.google.com/p/inferno-os/source/browse/utils/8l/l.h
// //
@ -62,12 +28,14 @@ package main
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
package main
const ( const (
thechar = '8' thechar = '8'
PtrSize = 4 PtrSize = 4
IntSize = 4 IntSize = 4
RegSize = 4 RegSize = 4
MaxAlign = 32 MaxAlign = 32 // max data alignment
FuncAlign = 16 FuncAlign = 16
MINLC = 1 MINLC = 1
) )

View file

@ -1,42 +1,12 @@
// Derived from Inferno utils/6c/peep.c
// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
// Copyright 2014 The Go Authors. All rights reserved. // Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package main
// Many Power ISA arithmetic and logical instructions come in four // Many Power ISA arithmetic and logical instructions come in four
// standard variants. These bits let us map between variants. // standard variants. These bits let us map between variants.
const ( const (
V_CC = 1 << 0 V_CC = 1 << 0 // xCC (affect CR field 0 flags)
V_V = 1 << 1 V_V = 1 << 1 // xV (affect SO and OV flags)
) )

View file

@ -34,7 +34,7 @@ import "cmd/internal/obj/ppc64"
import "cmd/internal/gc" import "cmd/internal/gc"
const ( const (
NREGVAR = 64 NREGVAR = 64 /* 32 general + 32 floating */
) )
var regname = []string{ var regname = []string{

View file

@ -66,7 +66,7 @@ const (
PtrSize = 8 PtrSize = 8
IntSize = 8 IntSize = 8
RegSize = 8 RegSize = 8
MaxAlign = 32 MaxAlign = 32 // max data alignment
FuncAlign = 8 FuncAlign = 8
MINLC = 4 MINLC = 4
) )

View file

@ -206,15 +206,27 @@ const (
) )
type EscState struct { type EscState struct {
// Fake node that all
// - return values and output variables
// - parameters on imported functions not marked 'safe'
// - assignments to global variables
// flow to.
theSink Node theSink Node
// If an analyzed function is recorded to return
// pieces obtained via indirection from a parameter,
// and later there is a call f(x) to that function,
// we create a link funcParam <- x to record that fact.
// The funcParam node is handled specially in escflood.
funcParam Node funcParam Node
dsts *NodeList
loopdepth int dsts *NodeList // all dst nodes
pdepth int loopdepth int // for detecting nested loop scopes
dstcount int pdepth int // for debug printing in recursions.
edgecount int dstcount int // diagnostic
noesc *NodeList edgecount int // diagnostic
recursive bool noesc *NodeList // list of possible non-escaping nodes, for printing
recursive bool // recursive function or group of mutually recursive functions.
} }
var tags [16]*string var tags [16]*string
@ -530,7 +542,10 @@ func esc(e *EscState, n *Node, up *Node) {
// However, without this special case b will escape, because we assign to OIND/ODOTPTR. // However, without this special case b will escape, because we assign to OIND/ODOTPTR.
case OAS, case OAS,
OASOP: OASOP:
if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && (n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && (n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && n.Left.Left == n.Right.Left.Left { // dst is ONAME dereference // src is slice operation // slice is applied to ONAME dereference // dst and src reference the same base ONAME if (n.Left.Op == OIND || n.Left.Op == ODOTPTR) && n.Left.Left.Op == ONAME && // dst is ONAME dereference
(n.Right.Op == OSLICE || n.Right.Op == OSLICE3 || n.Right.Op == OSLICESTR) && // src is slice operation
(n.Right.Left.Op == OIND || n.Right.Left.Op == ODOTPTR) && n.Right.Left.Left.Op == ONAME && // slice is applied to ONAME dereference
n.Left.Left == n.Right.Left.Left { // dst and src reference the same base ONAME
// Here we also assume that the statement will not contain calls, // Here we also assume that the statement will not contain calls,
// that is, that order will move any calls to init. // that is, that order will move any calls to init.
@ -578,13 +593,12 @@ func esc(e *EscState, n *Node, up *Node) {
if e.loopdepth == 1 { // top level if e.loopdepth == 1 { // top level
break break
} }
fallthrough
// go f(x) - f and x escape
// arguments leak out of scope // arguments leak out of scope
// TODO: leak to a dummy node instead // TODO: leak to a dummy node instead
// fallthrough fallthrough
case OPROC: case OPROC:
// go f(x) - f and x escape
escassign(e, &e.theSink, n.Left.Left) escassign(e, &e.theSink, n.Left.Left)
escassign(e, &e.theSink, n.Left.Right) // ODDDARG for call escassign(e, &e.theSink, n.Left.Right) // ODDDARG for call
@ -899,14 +913,15 @@ func escassign(e *EscState, dst *Node, src *Node) {
OSLICEARR, OSLICEARR,
OSLICE3ARR, OSLICE3ARR,
OSLICESTR: OSLICESTR:
// Conversions, field access, slice all preserve the input value.
escassign(e, dst, src.Left) escassign(e, dst, src.Left)
// Append returns first argument.
case OAPPEND: case OAPPEND:
// Append returns first argument.
escassign(e, dst, src.List.N) escassign(e, dst, src.List.N)
// Index of array preserves input value.
case OINDEX: case OINDEX:
// Index of array preserves input value.
if Isfixedarray(src.Left.Type) { if Isfixedarray(src.Left.Type) {
escassign(e, dst, src.Left) escassign(e, dst, src.Left)
} }

View file

@ -32,6 +32,8 @@ const (
) )
const ( const (
// These values are known by runtime.
// The MEMx and NOEQx values must run in parallel. See algtype.
AMEM = iota AMEM = iota
AMEM0 AMEM0
AMEM8 AMEM8
@ -58,9 +60,9 @@ const (
) )
const ( const (
Mpscale = 29 Mpscale = 29 // safely smaller than bits in a long
Mpprec = 16 Mpprec = 16 // Mpscale*Mpprec is max number of bits
Mpnorm = Mpprec - 1 Mpnorm = Mpprec - 1 // significant words in a normalized float
Mpbase = 1 << Mpscale Mpbase = 1 << Mpscale
Mpsign = Mpbase >> 1 Mpsign = Mpbase >> 1
Mpmask = Mpbase - 1 Mpmask = Mpbase - 1
@ -86,42 +88,44 @@ type Mpcplx struct {
type Val struct { type Val struct {
Ctype int16 Ctype int16
U struct { U struct {
Reg int16 Reg int16 // OREGISTER
Bval int16 Bval int16 // bool value CTBOOL
Xval *Mpint Xval *Mpint // int CTINT, rune CTRUNE
Fval *Mpflt Fval *Mpflt // float CTFLT
Cval *Mpcplx Cval *Mpcplx // float CTCPLX
Sval string Sval string // string CTSTR
} }
} }
type Pkg struct { type Pkg struct {
Name string Name string // package name
Path string Path string // string literal used in import statement
Pathsym *Sym Pathsym *Sym
Prefix string Prefix string // escaped path for use in symbol table
Imported uint8 Imported uint8 // export data of this package was parsed
Exported int8 Exported int8 // import line written in export data
Direct int8 Direct int8 // imported directly
Safe bool Safe bool // whether the package is marked as safe
Syms map[string]*Sym Syms map[string]*Sym
} }
type Sym struct { type Sym struct {
Lexical uint16 Lexical uint16
Flags uint8 Flags uint8
Sym uint8 Sym uint8 // huffman encoding in object file
Link *Sym Link *Sym
Uniqgen uint32 Uniqgen uint32
Importdef *Pkg Importdef *Pkg // where imported definition was found
Linkname string Linkname string // link name
// saved and restored by dcopy
Pkg *Pkg Pkg *Pkg
Name string Name string // variable name
Def *Node Def *Node // definition: ONAME OTYPE OPACK or OLITERAL
Label *Label Label *Label // corresponding label (ephemeral)
Block int32 Block int32 // blocknumber to catch redeclaration
Lastlineno int32 Lastlineno int32 // last declaration for diagnostic
Origpkg *Pkg Origpkg *Pkg // original package for . import
Lsym *obj.LSym Lsym *obj.LSym
} }
@ -130,45 +134,63 @@ type Type struct {
Nointerface bool Nointerface bool
Noalg uint8 Noalg uint8
Chan uint8 Chan uint8
Trecur uint8 Trecur uint8 // to detect loops
Printed uint8 Printed uint8
Embedded uint8 Embedded uint8 // TFIELD embedded type
Siggen uint8 Siggen uint8
Funarg uint8 Funarg uint8 // on TSTRUCT and TFIELD
Copyany uint8 Copyany uint8
Local uint8 Local uint8 // created in this file
Deferwidth uint8 Deferwidth uint8
Broke uint8 Broke uint8 // broken type definition.
Isddd uint8 Isddd uint8 // TFIELD is ... argument
Align uint8 Align uint8
Haspointers uint8 Haspointers uint8 // 0 unknown, 1 no, 2 yes
Nod *Node
Orig *Type Nod *Node // canonical OTYPE node
Orig *Type // original type (type literal or predefined type)
Lineno int Lineno int
// TFUNC
Thistuple int Thistuple int
Outtuple int Outtuple int
Intuple int Intuple int
Outnamed uint8 Outnamed uint8
Method *Type Method *Type
Xmethod *Type Xmethod *Type
Sym *Sym Sym *Sym
Vargen int32 Vargen int32 // unique name for OTYPE/ONAME
Nname *Node Nname *Node
Argwid int64 Argwid int64
Type *Type
Width int64 // most nodes
Down *Type Type *Type // actual type for TFIELD, element type for TARRAY, TCHAN, TMAP, TPTRxx
Outer *Type Width int64 // offset in TFIELD, width in all others
Note *string
Bound int64 // TFIELD
Bucket *Type Down *Type // next struct field, also key type in TMAP
Hmap *Type Outer *Type // outer struct
Hiter *Type Note *string // literal string annotation
Map *Type
Maplineno int32 // TARRAY
Embedlineno int32 Bound int64 // negative is dynamic array
// TMAP
Bucket *Type // internal type representing a hash bucket
Hmap *Type // internal type representing a Hmap (map header object)
Hiter *Type // internal type representing hash iterator state
Map *Type // link from the above 3 internal types back to the map type.
Maplineno int32 // first use of TFORW as map key
Embedlineno int32 // first use of TFORW as embedded type
// for TFORW, where to copy the eventual value to
Copyto *NodeList Copyto *NodeList
Lastfn *Node
Lastfn *Node // for usefield
} }
type Label struct { type Label struct {
@ -177,16 +199,18 @@ type Label struct {
Def *Node Def *Node
Use *NodeList Use *NodeList
Link *Label Link *Label
Gotopc *obj.Prog
Labelpc *obj.Prog // for use during gen
Breakpc *obj.Prog Gotopc *obj.Prog // pointer to unresolved gotos
Continpc *obj.Prog Labelpc *obj.Prog // pointer to code
Breakpc *obj.Prog // pointer to code
Continpc *obj.Prog // pointer to code
} }
type InitEntry struct { type InitEntry struct {
Xoffset int64 Xoffset int64 // struct, array only
Key *Node Key *Node // map only
Expr *Node Expr *Node // bytes of run-time computed expressions
} }
type InitPlan struct { type InitPlan struct {
@ -205,14 +229,14 @@ const (
EscNever EscNever
EscBits = 3 EscBits = 3
EscMask = (1 << EscBits) - 1 EscMask = (1 << EscBits) - 1
EscContentEscapes = 1 << EscBits EscContentEscapes = 1 << EscBits // value obtained by indirect of parameter escapes to some returned result
EscReturnBits = EscBits + 1 EscReturnBits = EscBits + 1
) )
const ( const (
SymExport = 1 << 0 SymExport = 1 << 0 // to be exported
SymPackage = 1 << 1 SymPackage = 1 << 1
SymExported = 1 << 2 SymExported = 1 << 2 // already written out by export
SymUniq = 1 << 3 SymUniq = 1 << 3
SymSiggen = 1 << 4 SymSiggen = 1 << 4
SymAsm = 1 << 5 SymAsm = 1 << 5
@ -231,6 +255,7 @@ type Iter struct {
const ( const (
Txxx = iota Txxx = iota
TINT8 TINT8
TUINT8 TUINT8
TINT16 TINT16
@ -242,13 +267,18 @@ const (
TINT TINT
TUINT TUINT
TUINTPTR TUINTPTR
TCOMPLEX64 TCOMPLEX64
TCOMPLEX128 TCOMPLEX128
TFLOAT32 TFLOAT32
TFLOAT64 TFLOAT64
TBOOL TBOOL
TPTR32 TPTR32
TPTR64 TPTR64
TFUNC TFUNC
TARRAY TARRAY
T_old_DARRAY T_old_DARRAY
@ -261,17 +291,23 @@ const (
TANY TANY
TSTRING TSTRING
TUNSAFEPTR TUNSAFEPTR
// pseudo-types for literals
TIDEAL TIDEAL
TNIL TNIL
TBLANK TBLANK
// pseudo-type for frame layout
TFUNCARGS TFUNCARGS
TCHANARGS TCHANARGS
TINTERMETH TINTERMETH
NTYPE NTYPE
) )
const ( const (
CTxxx = iota CTxxx = iota
CTINT CTINT
CTRUNE CTRUNE
CTFLT CTFLT
@ -282,6 +318,8 @@ const (
) )
const ( const (
/* types of channel */
/* must match ../../pkg/nreflect/type.go:/Chandir */
Cxxx = 0 Cxxx = 0
Crecv = 1 << 0 Crecv = 1 << 0
Csend = 1 << 1 Csend = 1 << 1
@ -291,28 +329,30 @@ const (
// declaration context // declaration context
const ( const (
Pxxx = iota Pxxx = iota
PEXTERN PEXTERN // global variable
PAUTO PAUTO // local variables
PPARAM PPARAM // input arguments
PPARAMOUT PPARAMOUT // output results
PPARAMREF PPARAMREF // closure variable reference
PFUNC PFUNC // global function
PDISCARD
PHEAP = 1 << 7 PDISCARD // discard during parse of duplicate import
PHEAP = 1 << 7 // an extra bit to identify an escaped variable
) )
const ( const (
Etop = 1 << 1 Etop = 1 << 1 // evaluated at statement level
Erv = 1 << 2 Erv = 1 << 2 // evaluated in value context
Etype = 1 << 3 Etype = 1 << 3
Ecall = 1 << 4 Ecall = 1 << 4 // call-only expressions are ok
Efnstruct = 1 << 5 Efnstruct = 1 << 5 // multivalue function returns are ok
Eiota = 1 << 6 Eiota = 1 << 6 // iota is ok
Easgn = 1 << 7 Easgn = 1 << 7 // assigning to expression
Eindir = 1 << 8 Eindir = 1 << 8 // indirecting through expression
Eaddr = 1 << 9 Eaddr = 1 << 9 // taking address of expression
Eproc = 1 << 10 Eproc = 1 << 10 // inside a go statement
Ecomplit = 1 << 11 Ecomplit = 1 << 11 // type in composite literal
) )
const ( const (
@ -364,8 +404,8 @@ type Io struct {
eofnl int eofnl int
last int last int
peekc int peekc int
peekc1 int peekc1 int // second peekc for ...
cp string cp string // used for content when bin==nil
importsafe bool importsafe bool
} }
@ -383,14 +423,18 @@ type Idir struct {
* smagic and umagic * smagic and umagic
*/ */
type Magic struct { type Magic struct {
W int W int // input for both - width
S int S int // output for both - shift
Bad int Bad int // output for both - unexpected failure
Sd int64
Sm int64 // magic multiplier for signed literal divisors
Ud uint64 Sd int64 // input - literal divisor
Um uint64 Sm int64 // output - multiplier
Ua int
// magic multiplier for unsigned literal divisors
Ud uint64 // input - literal divisor
Um uint64 // output - multiplier
Ua int // output - adder
} }
/* /*
@ -670,24 +714,30 @@ var Disable_checknil int
var zerosize int64 var zerosize int64
type Flow struct { type Flow struct {
Prog *obj.Prog Prog *obj.Prog // actual instruction
P1 *Flow P1 *Flow // predecessors of this instruction: p1,
P2 *Flow P2 *Flow // and then p2 linked though p2link.
P2link *Flow P2link *Flow
S1 *Flow S1 *Flow // successors of this instruction (at most two: s1 and s2).
S2 *Flow S2 *Flow
Link *Flow Link *Flow // next instruction in function code
Active int32
Id int32 Active int32 // usable by client
Rpo int32
Loop uint16 Id int32 // sequence number in flow graph
Refset uint8 Rpo int32 // reverse post ordering
Data interface{} Loop uint16 // x5 for every loop
Refset uint8 // diagnostic generated
Data interface{} // for use by client
} }
type Graph struct { type Graph struct {
Start *Flow Start *Flow
Num int Num int
// After calling flowrpo, rpo lists the flow nodes in reverse postorder,
// and each non-dead Flow node f has g->rpo[f->rpo] == f.
Rpo []*Flow Rpo []*Flow
} }
@ -695,41 +745,62 @@ type Graph struct {
* interface to back end * interface to back end
*/ */
type ProgInfo struct { type ProgInfo struct {
Flags uint32 Flags uint32 // the bits below
Reguse uint64 Reguse uint64 // registers implicitly used by this instruction
Regset uint64 Regset uint64 // registers implicitly set by this instruction
Regindex uint64 Regindex uint64 // registers used by addressing mode
} }
const ( const (
// Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
Pseudo = 1 << 1 Pseudo = 1 << 1
// There's nothing to say about the instruction,
// but it's still okay to see.
OK = 1 << 2 OK = 1 << 2
// Size of right-side write, or right-side read if no write.
SizeB = 1 << 3 SizeB = 1 << 3
SizeW = 1 << 4 SizeW = 1 << 4
SizeL = 1 << 5 SizeL = 1 << 5
SizeQ = 1 << 6 SizeQ = 1 << 6
SizeF = 1 << 7 SizeF = 1 << 7
SizeD = 1 << 8 SizeD = 1 << 8
// Left side (Prog.from): address taken, read, write.
LeftAddr = 1 << 9 LeftAddr = 1 << 9
LeftRead = 1 << 10 LeftRead = 1 << 10
LeftWrite = 1 << 11 LeftWrite = 1 << 11
// Register in middle (Prog.reg); only ever read. (arm, ppc64)
RegRead = 1 << 12 RegRead = 1 << 12
CanRegRead = 1 << 13 CanRegRead = 1 << 13
// Right side (Prog.to): address taken, read, write.
RightAddr = 1 << 14 RightAddr = 1 << 14
RightRead = 1 << 15 RightRead = 1 << 15
RightWrite = 1 << 16 RightWrite = 1 << 16
Move = 1 << 17
Conv = 1 << 18 // Instruction kinds
Cjmp = 1 << 19 Move = 1 << 17 // straight move
Break = 1 << 20 Conv = 1 << 18 // size conversion
Call = 1 << 21 Cjmp = 1 << 19 // conditional jump
Jump = 1 << 22 Break = 1 << 20 // breaks control flow (no fallthrough)
Skip = 1 << 23 Call = 1 << 21 // function call
Jump = 1 << 22 // jump
Skip = 1 << 23 // data instruction
// Set, use, or kill of carry bit.
// Kill means we never look at the carry bit after this kind of instruction.
SetCarry = 1 << 24 SetCarry = 1 << 24
UseCarry = 1 << 25 UseCarry = 1 << 25
KillCarry = 1 << 26 KillCarry = 1 << 26
ShiftCX = 1 << 27
ImulAXDX = 1 << 28 // Special cases for register use. (amd64, 386)
ShiftCX = 1 << 27 // possible shift by CX
ImulAXDX = 1 << 28 // possible multiply into DX:AX
// Instruction updates whichever of from/to is type D_OREG. (ppc64)
PostInc = 1 << 29 PostInc = 1 << 29
) )

View file

@ -167,6 +167,7 @@ func dumpdata() {
Clearp(Pc) Clearp(Pc)
} }
// Fixup instructions after allocauto (formerly compactframe) has moved all autos around.
func fixautoused(p *obj.Prog) { func fixautoused(p *obj.Prog) {
for lp := &p; ; { for lp := &p; ; {
p = *lp p = *lp
@ -258,6 +259,7 @@ func Isfat(t *Type) bool {
return false return false
} }
// Sweep the prog list to mark any used nodes.
func markautoused(p *obj.Prog) { func markautoused(p *obj.Prog) {
for ; p != nil; p = p.Link { for ; p != nil; p = p.Link {
if p.As == obj.ATYPE || p.As == obj.AVARDEF || p.As == obj.AVARKILL { if p.As == obj.ATYPE || p.As == obj.AVARDEF || p.As == obj.AVARKILL {

View file

@ -41,9 +41,9 @@ import (
// Order holds state during the ordering process. // Order holds state during the ordering process.
type Order struct { type Order struct {
out *NodeList out *NodeList // list of generated statements
temp *NodeList temp *NodeList // head of stack of temporary variables
free *NodeList free *NodeList // free list of NodeList* structs (for use in temp)
} }
// Order rewrites fn->nbody to apply the ordering constraints // Order rewrites fn->nbody to apply the ordering constraints

View file

@ -2,6 +2,17 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Garbage collector liveness bitmap generation.
// The command line flag -live causes this code to print debug information.
// The levels are:
//
// -live (aka -live=1): print liveness lists as code warnings at safe points
// -live=2: print an assembly listing with liveness annotations
// -live=3: print information during each computation phase (much chattier)
//
// Each level includes the earlier output as well.
package gc package gc
import ( import (
@ -34,18 +45,36 @@ const (
// ... // ...
// } // }
type BasicBlock struct { type BasicBlock struct {
pred []*BasicBlock pred []*BasicBlock // predecessors; if none, probably start of CFG
succ []*BasicBlock succ []*BasicBlock // successors; if none, probably ends in return statement
first *obj.Prog first *obj.Prog // first instruction in block
last *obj.Prog last *obj.Prog // last instruction in block
rpo int rpo int // reverse post-order number (also index in cfg)
mark int mark int // mark bit for traversals
lastbitmapindex int lastbitmapindex int // for livenessepilogue
// Summary sets of block effects.
// Computed during livenessprologue using only the content of
// individual blocks:
//
// uevar: upward exposed variables (used before set in block)
// varkill: killed variables (set in block)
// avarinit: addrtaken variables set or used (proof of initialization)
uevar Bvec uevar Bvec
varkill Bvec varkill Bvec
avarinit Bvec
// Computed during livenesssolve using control flow information:
//
// livein: variables live at block entry
// liveout: variables live at block exit
// avarinitany: addrtaken variables possibly initialized at block exit
// (initialized in block or at exit from any predecessor block)
// avarinitall: addrtaken variables certainly initialized at block exit
// (initialized in block or at exit from all predecessor blocks)
livein Bvec livein Bvec
liveout Bvec liveout Bvec
avarinit Bvec
avarinitany Bvec avarinitany Bvec
avarinitall Bvec avarinitall Bvec
} }
@ -56,6 +85,9 @@ type Liveness struct {
ptxt *obj.Prog ptxt *obj.Prog
vars []*Node vars []*Node
cfg []*BasicBlock cfg []*BasicBlock
// An array with a bit vector for each safe point tracking live pointers
// in the arguments and locals area, indexed by bb.rpo.
argslivepointers []Bvec argslivepointers []Bvec
livepointers []Bvec livepointers []Bvec
} }

View file

@ -79,16 +79,25 @@ const (
) )
type Reg struct { type Reg struct {
set Bits set Bits // regopt variables written by this instruction.
use1 Bits use1 Bits // regopt variables read by prog->from.
use2 Bits use2 Bits // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
refbehind Bits refbehind Bits
refahead Bits refahead Bits
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
calbehind Bits calbehind Bits
calahead Bits calahead Bits
regdiff Bits regdiff Bits
act Bits act Bits
regu uint64 regu uint64 // register used bitmap
} }
type Rgn struct { type Rgn struct {
@ -639,14 +648,14 @@ func Uniqs(r *Flow) *Flow {
type TempVar struct { type TempVar struct {
node *Node node *Node
def *Flow def *Flow // definition of temp var
use *Flow use *Flow // use list, chained through Flow.data
freelink *TempVar freelink *TempVar // next free temp in Type.opt list
merge *TempVar merge *TempVar // merge var with this one
start int64 start int64 // smallest Prog.pc in live range
end int64 end int64 // largest Prog.pc in live range
addr uint8 addr uint8 // address taken - no accurate end
removed uint8 removed uint8 // removed from program
} }
type startcmp []*TempVar type startcmp []*TempVar

View file

@ -135,6 +135,13 @@ out:
} }
func walkrange(n *Node) { func walkrange(n *Node) {
// variable name conventions:
// ohv1, hv1, hv2: hidden (old) val 1, 2
// ha, hit: hidden aggregate, iterator
// hn, hp: hidden len, pointer
// hb: hidden bool
// a, v1, v2: not hidden aggregate, val 1, 2
t := n.Type t := n.Type
a := n.Right a := n.Right

View file

@ -11,6 +11,8 @@ package gc
// node with Op=ONAME for a given instance of a variable x. // node with Op=ONAME for a given instance of a variable x.
// The same is true for Op=OTYPE and Op=OLITERAL. // The same is true for Op=OTYPE and Op=OLITERAL.
type Node struct { type Node struct {
// Tree structure.
// Generic recursive walks should follow these fields.
Left *Node Left *Node
Right *Node Right *Node
Ntest *Node Ntest *Node
@ -20,22 +22,23 @@ type Node struct {
Nelse *NodeList Nelse *NodeList
List *NodeList List *NodeList
Rlist *NodeList Rlist *NodeList
Op uint8 Op uint8
Nointerface bool Nointerface bool
Ullman uint8 Ullman uint8 // sethi/ullman number
Addable uint8 Addable uint8 // type of addressability - 0 is not addressable
Trecur uint8 Trecur uint8 // to detect loops
Etype uint8 Etype uint8 // op for OASOP, etype for OTYPE, exclam for export
Bounded bool Bounded bool // bounds check unnecessary
Class uint8 Class uint8 // PPARAM, PAUTO, PEXTERN, etc
Method uint8 Method uint8 // OCALLMETH name
Embedded uint8 Embedded uint8 // ODCLFIELD embedded type
Colas uint8 Colas uint8 // OAS resulting from :=
Diag uint8 Diag uint8 // already printed error about this
Noescape bool Noescape bool // func arguments do not escape
Nosplit bool Nosplit bool // func should not execute on separate stack
Builtin uint8 Builtin uint8 // built-in name, like len or close
Nowritebarrier bool Nowritebarrier bool // emit compiler error instead of write barrier
Walkdef uint8 Walkdef uint8
Typecheck uint8 Typecheck uint8
Local uint8 Local uint8
@ -45,219 +48,255 @@ type Node struct {
Isddd uint8 Isddd uint8
Readonly uint8 Readonly uint8
Implicit uint8 Implicit uint8
Addrtaken uint8 Addrtaken uint8 // address taken, even if not moved to heap
Assigned uint8 Assigned uint8 // is the variable ever assigned to
Captured uint8 Captured uint8 // is the variable captured by a closure
Byval uint8 Byval uint8 // is the variable captured by value or by reference
Dupok uint8 Dupok uint8 // duplicate definitions ok (for func)
Wrapper uint8 Wrapper uint8 // is method wrapper (for func)
Reslice uint8 Reslice uint8 // this is a reslice x = x[0:y] or x = append(x, ...)
Likely int8 Likely int8 // likeliness of if statement
Hasbreak uint8 Hasbreak uint8 // has break statement
Needzero bool Needzero bool // if it contains pointers, needs to be zeroed on function entry
Needctxt bool Needctxt bool // function uses context register (has closure variables)
Esc uint Esc uint // EscXXX
Funcdepth int Funcdepth int
// most nodes
Type *Type Type *Type
Orig *Node Orig *Node // original form, for printing, and tracking copies of ONAMEs
// func
Nname *Node Nname *Node
Shortname *Node Shortname *Node
Enter *NodeList Enter *NodeList
Exit *NodeList Exit *NodeList
Cvars *NodeList Cvars *NodeList // closure params
Dcl *NodeList Dcl *NodeList // autodcl for this func/closure
Inl *NodeList Inl *NodeList // copy of the body for use in inlining
Inldcl *NodeList Inldcl *NodeList // copy of dcl for use in inlining
Closgen int Closgen int
Outerfunc *Node Outerfunc *Node
// OLITERAL/OREGISTER
Val Val Val Val
// ONAME
Ntype *Node Ntype *Node
Defn *Node Defn *Node // ONAME: initializing assignment; OLABEL: labeled statement
Pack *Node Pack *Node // real package for import . names
Curfn *Node Curfn *Node // function for local variables
Paramfld *Type Paramfld *Type // TFIELD for this PPARAM; also for ODOT, curfn
Decldepth int Decldepth int // declaration loop depth, increased for every loop or label
Heapaddr *Node
Outerexpr *Node // ONAME func param with PHEAP
Stackparam *Node Heapaddr *Node // temp holding heap address of param
Alloc *Node Outerexpr *Node // expression copied into closure for variable
Outer *Node Stackparam *Node // OPARAM node referring to stack copy of param
Closure *Node Alloc *Node // allocation call
Top int
// ONAME closure param with PPARAMREF
Outer *Node // outer PPARAMREF in nested closure
Closure *Node // ONAME/PHEAP <-> ONAME/PPARAMREF
Top int // top context (Ecall, Eproc, etc)
// ONAME substitute while inlining
Inlvar *Node Inlvar *Node
// OPACK
Pkg *Pkg Pkg *Pkg
// OARRAYLIT, OMAPLIT, OSTRUCTLIT.
Initplan *InitPlan Initplan *InitPlan
Escflowsrc *NodeList
Escretval *NodeList // Escape analysis.
Escloopdepth int Escflowsrc *NodeList // flow(this, src)
Sym *Sym Escretval *NodeList // on OCALLxxx, list of dummy return values
InlCost int32 Escloopdepth int // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
Sym *Sym // various
InlCost int32 // unique name for OTYPE/ONAME
Vargen int32 Vargen int32
Lineno int32 Lineno int32
Endlineno int32 Endlineno int32
Xoffset int64 Xoffset int64
Stkdelta int64 Stkdelta int64 // offset added by stack frame compaction phase.
Ostk int32 Ostk int32
Iota int32 Iota int32
Walkgen uint32 Walkgen uint32
Esclevel int32 Esclevel int32
Opt interface{} Opt interface{} // for optimization passes
} }
// Node ops. // Node ops.
const ( const (
OXXX = iota OXXX = iota
ONAME
ONONAME // names
OTYPE ONAME // var, const or func name
OPACK ONONAME // unnamed arg or return value: f(int, string) (int, error) { etc }
OLITERAL OTYPE // type name
OADD OPACK // import
OSUB OLITERAL // literal
OOR
OXOR // expressions
OADDSTR OADD // x + y
OADDR OSUB // x - y
OANDAND OOR // x | y
OAPPEND OXOR // x ^ y
OARRAYBYTESTR OADDSTR // s + "foo"
OARRAYBYTESTRTMP OADDR // &x
OARRAYRUNESTR OANDAND // b0 && b1
OSTRARRAYBYTE OAPPEND // append
OSTRARRAYBYTETMP OARRAYBYTESTR // string(bytes)
OSTRARRAYRUNE OARRAYBYTESTRTMP // string(bytes) ephemeral
OAS OARRAYRUNESTR // string(runes)
OAS2 OSTRARRAYBYTE // []byte(s)
OAS2FUNC OSTRARRAYBYTETMP // []byte(s) ephemeral
OAS2RECV OSTRARRAYRUNE // []rune(s)
OAS2MAPR OAS // x = y or x := y
OAS2DOTTYPE OAS2 // x, y, z = xx, yy, zz
OASOP OAS2FUNC // x, y = f()
OCALL OAS2RECV // x, ok = <-c
OCALLFUNC OAS2MAPR // x, ok = m["foo"]
OCALLMETH OAS2DOTTYPE // x, ok = I.(int)
OCALLINTER OASOP // x += y
OCALLPART OCALL // function call, method call or type conversion, possibly preceded by defer or go.
OCAP OCALLFUNC // f()
OCLOSE OCALLMETH // t.Method()
OCLOSURE OCALLINTER // err.Error()
OCMPIFACE OCALLPART // t.Method (without ())
OCMPSTR OCAP // cap
OCOMPLIT OCLOSE // close
OMAPLIT OCLOSURE // f = func() { etc }
OSTRUCTLIT OCMPIFACE // err1 == err2
OARRAYLIT OCMPSTR // s1 == s2
OPTRLIT OCOMPLIT // composite literal, typechecking may convert to a more specific OXXXLIT.
OCONV OMAPLIT // M{"foo":3, "bar":4}
OCONVIFACE OSTRUCTLIT // T{x:3, y:4}
OCONVNOP OARRAYLIT // [2]int{3, 4}
OCOPY OPTRLIT // &T{x:3, y:4}
ODCL OCONV // var i int; var u uint; i = int(u)
ODCLFUNC OCONVIFACE // I(t)
ODCLFIELD OCONVNOP // type Int int; var i int; var j Int; i = int(j)
ODCLCONST OCOPY // copy
ODCLTYPE ODCL // var x int
ODELETE ODCLFUNC // func f() or func (r) f()
ODOT ODCLFIELD // struct field, interface field, or func/method argument/return value.
ODOTPTR ODCLCONST // const pi = 3.14
ODOTMETH ODCLTYPE // type Int int
ODOTINTER ODELETE // delete
OXDOT ODOT // t.x
ODOTTYPE ODOTPTR // p.x that is implicitly (*p).x
ODOTTYPE2 ODOTMETH // t.Method
OEQ ODOTINTER // err.Error
ONE OXDOT // t.x, typechecking may convert to a more specific ODOTXXX.
OLT ODOTTYPE // e = err.(MyErr)
OLE ODOTTYPE2 // e, ok = err.(MyErr)
OGE OEQ // x == y
OGT ONE // x != y
OIND OLT // x < y
OINDEX OLE // x <= y
OINDEXMAP OGE // x >= y
OKEY OGT // x > y
OPARAM OIND // *p
OLEN OINDEX // a[i]
OMAKE OINDEXMAP // m[s]
OMAKECHAN OKEY // The x:3 in t{x:3, y:4}, the 1:2 in a[1:2], the 2:20 in [3]int{2:20}, etc.
OMAKEMAP OPARAM // The on-stack copy of a parameter or return value that escapes.
OMAKESLICE OLEN // len
OMUL OMAKE // make, typechecking may convert to a more specific OMAKEXXX.
ODIV OMAKECHAN // make(chan int)
OMOD OMAKEMAP // make(map[string]int)
OLSH OMAKESLICE // make([]int, 0)
ORSH OMUL // *
OAND ODIV // x / y
OANDNOT OMOD // x % y
ONEW OLSH // x << u
ONOT ORSH // x >> u
OCOM OAND // x & y
OPLUS OANDNOT // x &^ y
OMINUS ONEW // new
OOROR ONOT // !b
OPANIC OCOM // ^x
OPRINT OPLUS // +x
OPRINTN OMINUS // -y
OPAREN OOROR // b1 || b2
OSEND OPANIC // panic
OSLICE OPRINT // print
OSLICEARR OPRINTN // println
OSLICESTR OPAREN // (x)
OSLICE3 OSEND // c <- x
OSLICE3ARR OSLICE // v[1:2], typechecking may convert to a more specific OSLICEXXX.
ORECOVER OSLICEARR // a[1:2]
ORECV OSLICESTR // s[1:2]
ORUNESTR OSLICE3 // v[1:2:3], typechecking may convert to OSLICE3ARR.
OSELRECV OSLICE3ARR // a[1:2:3]
OSELRECV2 ORECOVER // recover
OIOTA ORECV // <-c
OREAL ORUNESTR // string(i)
OIMAG OSELRECV // case x = <-c:
OCOMPLEX OSELRECV2 // case x, ok = <-c:
OBLOCK OIOTA // iota
OBREAK OREAL // real
OCASE OIMAG // imag
OXCASE OCOMPLEX // complex
OCONTINUE
ODEFER // statements
OEMPTY OBLOCK // block of code
OFALL OBREAK // break
OXFALL OCASE // case, after being verified by swt.c's casebody.
OFOR OXCASE // case, before verification.
OGOTO OCONTINUE // continue
OIF ODEFER // defer
OLABEL OEMPTY // no-op
OPROC OFALL // fallthrough, after being verified by swt.c's casebody.
ORANGE OXFALL // fallthrough, before verification.
ORETURN OFOR // for
OSELECT OGOTO // goto
OSWITCH OIF // if
OTYPESW OLABEL // label:
OTCHAN OPROC // go
OTMAP ORANGE // range
OTSTRUCT ORETURN // return
OTINTER OSELECT // select
OTFUNC OSWITCH // switch x
OTARRAY OTYPESW // switch err.(type)
ODDD
ODDDARG // types
OINLCALL OTCHAN // chan int
OEFACE OTMAP // map[string]int
OITAB OTSTRUCT // struct{}
OSPTR OTINTER // interface{}
OCLOSUREVAR OTFUNC // func()
OCFUNC OTARRAY // []int, [8]int, [N]int or [...]int
OCHECKNIL
OVARKILL // misc
OREGISTER ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}.
OINDREG ODDDARG // func f(args ...int), introduced by escape analysis.
OCMP OINLCALL // intermediary representation of an inlined call.
ODEC OEFACE // itable and data words of an empty-interface value.
OINC OITAB // itable word of an interface value.
OEXTEND OSPTR // base pointer of a slice or string.
OHMUL OCLOSUREVAR // variable reference at beginning of closure function
OLROT OCFUNC // reference to c function pointer (not go func value)
ORROTC OCHECKNIL // emit code to ensure pointer/interface not nil
ORETJMP OVARKILL // variable is dead
// thearch-specific registers
OREGISTER // a register, such as AX.
OINDREG // offset plus indirect of a register, such as 8(SP).
// 386/amd64-specific opcodes
OCMP // compare: ACMP.
ODEC // decrement: ADEC.
OINC // increment: AINC.
OEXTEND // extend: ACWD/ACDQ/ACQO.
OHMUL // high mul: AMUL/AIMUL for unsigned/signed (OMUL uses AIMUL for both).
OLROT // left rotate: AROL.
ORROTC // right rotate-carry: ARCR.
ORETJMP // return to other function
OEND OEND
) )

View file

@ -490,7 +490,7 @@ OpSwitch:
case OIND: case OIND:
ntop := Erv | Etype ntop := Erv | Etype
if top&Eaddr == 0 { if top&Eaddr == 0 { // The *x in &*x is not an indirect.
ntop |= Eindir ntop |= Eindir
} }
ntop |= top & Ecomplit ntop |= top & Ecomplit

View file

@ -2950,10 +2950,9 @@ func appendslice(n *Node, init **NodeList) *Node {
nif.Ntest = Nod(OGT, nt, Nodintconst(0)) nif.Ntest = Nod(OGT, nt, Nodintconst(0))
// instantiate growslice(Type*, []any, int) []any // instantiate growslice(Type*, []any, int) []any
fn := syslook("growslice", 1) fn := syslook("growslice", 1) // growslice(<type>, old []T, n int64) (ret []T)
argtype(fn, s.Type.Type) // 1 old []any
argtype(fn, s.Type.Type) argtype(fn, s.Type.Type) // 2 ret []any
argtype(fn, s.Type.Type)
// s = growslice(T, s, n) // s = growslice(T, s, n)
nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt))) nif.Nbody = list1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nt)))
@ -3774,8 +3773,8 @@ func walkdiv(np **Node, init **NodeList) {
// by a constant // by a constant
w := int(nl.Type.Width * 8) w := int(nl.Type.Width * 8)
s := 0 s := 0 // 1 if nr is negative.
pow := powtwo(nr) pow := powtwo(nr) // if >= 0, nr is 1<<pow
if pow >= 1000 { if pow >= 1000 {
// negative power of 2 // negative power of 2
s = 1 s = 1

View file

@ -165,7 +165,7 @@ func decodetype_structfieldoffs(s *LSym, i int) int64 {
return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize+2*Thearch.Intsize+i*structfieldsize()+4*Thearch.Ptrsize:], Thearch.Intsize)) return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize+2*Thearch.Intsize+i*structfieldsize()+4*Thearch.Ptrsize:], Thearch.Intsize))
} }
// InterfaceTYpe.methods.length // InterfaceType.methods.length
func decodetype_ifacemethodcount(s *LSym) int64 { func decodetype_ifacemethodcount(s *LSym) int64 {
return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize)) return int64(decode_inuxi(s.P[commonsize()+Thearch.Ptrsize:], Thearch.Intsize))
} }

View file

@ -2,6 +2,16 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// TODO/NICETOHAVE:
// - eliminate DW_CLS_ if not used
// - package info in compilation units
// - assign global variables and types to their packages
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
// ptype struct '[]uint8' and qualifiers need to be quoted away
// - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean.
// - file:line info for variables
// - make strings a typedef so prettyprinters can see the underlying string type
package ld package ld
import ( import (
@ -176,7 +186,8 @@ const (
DW_AT_go_kind = 0x2900 DW_AT_go_kind = 0x2900
DW_AT_go_key = 0x2901 DW_AT_go_key = 0x2901
DW_AT_go_elem = 0x2902 DW_AT_go_elem = 0x2902
DW_AT_internal_location = 253
DW_AT_internal_location = 253 // params and locals; not emitted
) )
// Index into the abbrevs table below. // Index into the abbrevs table below.
@ -201,7 +212,7 @@ const (
DW_ABRV_IFACETYPE DW_ABRV_IFACETYPE
DW_ABRV_MAPTYPE DW_ABRV_MAPTYPE
DW_ABRV_PTRTYPE DW_ABRV_PTRTYPE
DW_ABRV_BARE_PTRTYPE DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
DW_ABRV_SLICETYPE DW_ABRV_SLICETYPE
DW_ABRV_STRINGTYPE DW_ABRV_STRINGTYPE
DW_ABRV_STRUCTTYPE DW_ABRV_STRUCTTYPE
@ -632,8 +643,8 @@ func dwarfhashstr(s string) uint32 {
type DWAttr struct { type DWAttr struct {
link *DWAttr link *DWAttr
atr uint16 atr uint16 // DW_AT_
cls uint8 cls uint8 // DW_CLS_
value int64 value int64
data interface{} data interface{}
} }
@ -643,9 +654,11 @@ type DWDie struct {
link *DWDie link *DWDie
child *DWDie child *DWDie
attr *DWAttr attr *DWAttr
// offset into .debug_info section, i.e relative to
// infoo. only valid after call to putdie()
offs int64 offs int64
hash []*DWDie hash []*DWDie // optional index of children by name, enabled by mkindex()
hlink *DWDie hlink *DWDie // bucket chain in parent's index
} }
/* /*
@ -1871,7 +1884,7 @@ func writelines() {
const ( const (
CIERESERVE = 16 CIERESERVE = 16
DATAALIGNMENTFACTOR = -4 DATAALIGNMENTFACTOR = -4
FAKERETURNCOLUMN = 16 FAKERETURNCOLUMN = 16 // TODO gdb6 doesn't like > 15?
) )
func putpccfadelta(deltapc int64, cfa int64) { func putpccfadelta(deltapc int64, cfa int64) {

View file

@ -89,6 +89,7 @@ const (
DW_TAG_variant_part = 0x33 DW_TAG_variant_part = 0x33
DW_TAG_variable = 0x34 DW_TAG_variable = 0x34
DW_TAG_volatile_type = 0x35 DW_TAG_volatile_type = 0x35
// Dwarf3
DW_TAG_dwarf_procedure = 0x36 DW_TAG_dwarf_procedure = 0x36
DW_TAG_restrict_type = 0x37 DW_TAG_restrict_type = 0x37
DW_TAG_interface_type = 0x38 DW_TAG_interface_type = 0x38
@ -99,9 +100,12 @@ const (
DW_TAG_imported_unit = 0x3d DW_TAG_imported_unit = 0x3d
DW_TAG_condition = 0x3f DW_TAG_condition = 0x3f
DW_TAG_shared_type = 0x40 DW_TAG_shared_type = 0x40
// Dwarf4
DW_TAG_type_unit = 0x41 DW_TAG_type_unit = 0x41
DW_TAG_rvalue_reference_type = 0x42 DW_TAG_rvalue_reference_type = 0x42
DW_TAG_template_alias = 0x43 DW_TAG_template_alias = 0x43
// User defined
DW_TAG_lo_user = 0x4080 DW_TAG_lo_user = 0x4080
DW_TAG_hi_user = 0xffff DW_TAG_hi_user = 0xffff
) )
@ -118,7 +122,7 @@ const (
DW_CLS_BLOCK DW_CLS_BLOCK
DW_CLS_CONSTANT DW_CLS_CONSTANT
DW_CLS_FLAG DW_CLS_FLAG
DW_CLS_PTR DW_CLS_PTR // lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE DW_CLS_REFERENCE
DW_CLS_ADDRLOC DW_CLS_ADDRLOC
DW_CLS_STRING DW_CLS_STRING
@ -126,185 +130,187 @@ const (
// Table 20 // Table 20
const ( const (
DW_AT_sibling = 0x01 DW_AT_sibling = 0x01 // reference
DW_AT_location = 0x02 DW_AT_location = 0x02 // block, loclistptr
DW_AT_name = 0x03 DW_AT_name = 0x03 // string
DW_AT_ordering = 0x09 DW_AT_ordering = 0x09 // constant
DW_AT_byte_size = 0x0b DW_AT_byte_size = 0x0b // block, constant, reference
DW_AT_bit_offset = 0x0c DW_AT_bit_offset = 0x0c // block, constant, reference
DW_AT_bit_size = 0x0d DW_AT_bit_size = 0x0d // block, constant, reference
DW_AT_stmt_list = 0x10 DW_AT_stmt_list = 0x10 // lineptr
DW_AT_low_pc = 0x11 DW_AT_low_pc = 0x11 // address
DW_AT_high_pc = 0x12 DW_AT_high_pc = 0x12 // address
DW_AT_language = 0x13 DW_AT_language = 0x13 // constant
DW_AT_discr = 0x15 DW_AT_discr = 0x15 // reference
DW_AT_discr_value = 0x16 DW_AT_discr_value = 0x16 // constant
DW_AT_visibility = 0x17 DW_AT_visibility = 0x17 // constant
DW_AT_import = 0x18 DW_AT_import = 0x18 // reference
DW_AT_string_length = 0x19 DW_AT_string_length = 0x19 // block, loclistptr
DW_AT_common_reference = 0x1a DW_AT_common_reference = 0x1a // reference
DW_AT_comp_dir = 0x1b DW_AT_comp_dir = 0x1b // string
DW_AT_const_value = 0x1c DW_AT_const_value = 0x1c // block, constant, string
DW_AT_containing_type = 0x1d DW_AT_containing_type = 0x1d // reference
DW_AT_default_value = 0x1e DW_AT_default_value = 0x1e // reference
DW_AT_inline = 0x20 DW_AT_inline = 0x20 // constant
DW_AT_is_optional = 0x21 DW_AT_is_optional = 0x21 // flag
DW_AT_lower_bound = 0x22 DW_AT_lower_bound = 0x22 // block, constant, reference
DW_AT_producer = 0x25 DW_AT_producer = 0x25 // string
DW_AT_prototyped = 0x27 DW_AT_prototyped = 0x27 // flag
DW_AT_return_addr = 0x2a DW_AT_return_addr = 0x2a // block, loclistptr
DW_AT_start_scope = 0x2c DW_AT_start_scope = 0x2c // constant
DW_AT_bit_stride = 0x2e DW_AT_bit_stride = 0x2e // constant
DW_AT_upper_bound = 0x2f DW_AT_upper_bound = 0x2f // block, constant, reference
DW_AT_abstract_origin = 0x31 DW_AT_abstract_origin = 0x31 // reference
DW_AT_accessibility = 0x32 DW_AT_accessibility = 0x32 // constant
DW_AT_address_class = 0x33 DW_AT_address_class = 0x33 // constant
DW_AT_artificial = 0x34 DW_AT_artificial = 0x34 // flag
DW_AT_base_types = 0x35 DW_AT_base_types = 0x35 // reference
DW_AT_calling_convention = 0x36 DW_AT_calling_convention = 0x36 // constant
DW_AT_count = 0x37 DW_AT_count = 0x37 // block, constant, reference
DW_AT_data_member_location = 0x38 DW_AT_data_member_location = 0x38 // block, constant, loclistptr
DW_AT_decl_column = 0x39 DW_AT_decl_column = 0x39 // constant
DW_AT_decl_file = 0x3a DW_AT_decl_file = 0x3a // constant
DW_AT_decl_line = 0x3b DW_AT_decl_line = 0x3b // constant
DW_AT_declaration = 0x3c DW_AT_declaration = 0x3c // flag
DW_AT_discr_list = 0x3d DW_AT_discr_list = 0x3d // block
DW_AT_encoding = 0x3e DW_AT_encoding = 0x3e // constant
DW_AT_external = 0x3f DW_AT_external = 0x3f // flag
DW_AT_frame_base = 0x40 DW_AT_frame_base = 0x40 // block, loclistptr
DW_AT_friend = 0x41 DW_AT_friend = 0x41 // reference
DW_AT_identifier_case = 0x42 DW_AT_identifier_case = 0x42 // constant
DW_AT_macro_info = 0x43 DW_AT_macro_info = 0x43 // macptr
DW_AT_namelist_item = 0x44 DW_AT_namelist_item = 0x44 // block
DW_AT_priority = 0x45 DW_AT_priority = 0x45 // reference
DW_AT_segment = 0x46 DW_AT_segment = 0x46 // block, loclistptr
DW_AT_specification = 0x47 DW_AT_specification = 0x47 // reference
DW_AT_static_link = 0x48 DW_AT_static_link = 0x48 // block, loclistptr
DW_AT_type = 0x49 DW_AT_type = 0x49 // reference
DW_AT_use_location = 0x4a DW_AT_use_location = 0x4a // block, loclistptr
DW_AT_variable_parameter = 0x4b DW_AT_variable_parameter = 0x4b // flag
DW_AT_virtuality = 0x4c DW_AT_virtuality = 0x4c // constant
DW_AT_vtable_elem_location = 0x4d DW_AT_vtable_elem_location = 0x4d // block, loclistptr
DW_AT_allocated = 0x4e // Dwarf3
DW_AT_associated = 0x4f DW_AT_allocated = 0x4e // block, constant, reference
DW_AT_data_location = 0x50 DW_AT_associated = 0x4f // block, constant, reference
DW_AT_byte_stride = 0x51 DW_AT_data_location = 0x50 // block
DW_AT_entry_pc = 0x52 DW_AT_byte_stride = 0x51 // block, constant, reference
DW_AT_use_UTF8 = 0x53 DW_AT_entry_pc = 0x52 // address
DW_AT_extension = 0x54 DW_AT_use_UTF8 = 0x53 // flag
DW_AT_ranges = 0x55 DW_AT_extension = 0x54 // reference
DW_AT_trampoline = 0x56 DW_AT_ranges = 0x55 // rangelistptr
DW_AT_call_column = 0x57 DW_AT_trampoline = 0x56 // address, flag, reference, string
DW_AT_call_file = 0x58 DW_AT_call_column = 0x57 // constant
DW_AT_call_line = 0x59 DW_AT_call_file = 0x58 // constant
DW_AT_description = 0x5a DW_AT_call_line = 0x59 // constant
DW_AT_binary_scale = 0x5b DW_AT_description = 0x5a // string
DW_AT_decimal_scale = 0x5c DW_AT_binary_scale = 0x5b // constant
DW_AT_small = 0x5d DW_AT_decimal_scale = 0x5c // constant
DW_AT_decimal_sign = 0x5e DW_AT_small = 0x5d // reference
DW_AT_digit_count = 0x5f DW_AT_decimal_sign = 0x5e // constant
DW_AT_picture_string = 0x60 DW_AT_digit_count = 0x5f // constant
DW_AT_mutable = 0x61 DW_AT_picture_string = 0x60 // string
DW_AT_threads_scaled = 0x62 DW_AT_mutable = 0x61 // flag
DW_AT_explicit = 0x63 DW_AT_threads_scaled = 0x62 // flag
DW_AT_object_pointer = 0x64 DW_AT_explicit = 0x63 // flag
DW_AT_endianity = 0x65 DW_AT_object_pointer = 0x64 // reference
DW_AT_elemental = 0x66 DW_AT_endianity = 0x65 // constant
DW_AT_pure = 0x67 DW_AT_elemental = 0x66 // flag
DW_AT_recursive = 0x68 DW_AT_pure = 0x67 // flag
DW_AT_lo_user = 0x2000 DW_AT_recursive = 0x68 // flag
DW_AT_hi_user = 0x3fff
DW_AT_lo_user = 0x2000 // ---
DW_AT_hi_user = 0x3fff // ---
) )
// Table 21 // Table 21
const ( const (
DW_FORM_addr = 0x01 DW_FORM_addr = 0x01 // address
DW_FORM_block2 = 0x03 DW_FORM_block2 = 0x03 // block
DW_FORM_block4 = 0x04 DW_FORM_block4 = 0x04 // block
DW_FORM_data2 = 0x05 DW_FORM_data2 = 0x05 // constant
DW_FORM_data4 = 0x06 DW_FORM_data4 = 0x06 // constant, lineptr, loclistptr, macptr, rangelistptr
DW_FORM_data8 = 0x07 DW_FORM_data8 = 0x07 // constant, lineptr, loclistptr, macptr, rangelistptr
DW_FORM_string = 0x08 DW_FORM_string = 0x08 // string
DW_FORM_block = 0x09 DW_FORM_block = 0x09 // block
DW_FORM_block1 = 0x0a DW_FORM_block1 = 0x0a // block
DW_FORM_data1 = 0x0b DW_FORM_data1 = 0x0b // constant
DW_FORM_flag = 0x0c DW_FORM_flag = 0x0c // flag
DW_FORM_sdata = 0x0d DW_FORM_sdata = 0x0d // constant
DW_FORM_strp = 0x0e DW_FORM_strp = 0x0e // string
DW_FORM_udata = 0x0f DW_FORM_udata = 0x0f // constant
DW_FORM_ref_addr = 0x10 DW_FORM_ref_addr = 0x10 // reference
DW_FORM_ref1 = 0x11 DW_FORM_ref1 = 0x11 // reference
DW_FORM_ref2 = 0x12 DW_FORM_ref2 = 0x12 // reference
DW_FORM_ref4 = 0x13 DW_FORM_ref4 = 0x13 // reference
DW_FORM_ref8 = 0x14 DW_FORM_ref8 = 0x14 // reference
DW_FORM_ref_udata = 0x15 DW_FORM_ref_udata = 0x15 // reference
DW_FORM_indirect = 0x16 DW_FORM_indirect = 0x16 // (see Section 7.5.3)
) )
// Table 24 (#operands, notes) // Table 24 (#operands, notes)
const ( const (
DW_OP_addr = 0x03 DW_OP_addr = 0x03 // 1 constant address (size target specific)
DW_OP_deref = 0x06 DW_OP_deref = 0x06 // 0
DW_OP_const1u = 0x08 DW_OP_const1u = 0x08 // 1 1-byte constant
DW_OP_const1s = 0x09 DW_OP_const1s = 0x09 // 1 1-byte constant
DW_OP_const2u = 0x0a DW_OP_const2u = 0x0a // 1 2-byte constant
DW_OP_const2s = 0x0b DW_OP_const2s = 0x0b // 1 2-byte constant
DW_OP_const4u = 0x0c DW_OP_const4u = 0x0c // 1 4-byte constant
DW_OP_const4s = 0x0d DW_OP_const4s = 0x0d // 1 4-byte constant
DW_OP_const8u = 0x0e DW_OP_const8u = 0x0e // 1 8-byte constant
DW_OP_const8s = 0x0f DW_OP_const8s = 0x0f // 1 8-byte constant
DW_OP_constu = 0x10 DW_OP_constu = 0x10 // 1 ULEB128 constant
DW_OP_consts = 0x11 DW_OP_consts = 0x11 // 1 SLEB128 constant
DW_OP_dup = 0x12 DW_OP_dup = 0x12 // 0
DW_OP_drop = 0x13 DW_OP_drop = 0x13 // 0
DW_OP_over = 0x14 DW_OP_over = 0x14 // 0
DW_OP_pick = 0x15 DW_OP_pick = 0x15 // 1 1-byte stack index
DW_OP_swap = 0x16 DW_OP_swap = 0x16 // 0
DW_OP_rot = 0x17 DW_OP_rot = 0x17 // 0
DW_OP_xderef = 0x18 DW_OP_xderef = 0x18 // 0
DW_OP_abs = 0x19 DW_OP_abs = 0x19 // 0
DW_OP_and = 0x1a DW_OP_and = 0x1a // 0
DW_OP_div = 0x1b DW_OP_div = 0x1b // 0
DW_OP_minus = 0x1c DW_OP_minus = 0x1c // 0
DW_OP_mod = 0x1d DW_OP_mod = 0x1d // 0
DW_OP_mul = 0x1e DW_OP_mul = 0x1e // 0
DW_OP_neg = 0x1f DW_OP_neg = 0x1f // 0
DW_OP_not = 0x20 DW_OP_not = 0x20 // 0
DW_OP_or = 0x21 DW_OP_or = 0x21 // 0
DW_OP_plus = 0x22 DW_OP_plus = 0x22 // 0
DW_OP_plus_uconst = 0x23 DW_OP_plus_uconst = 0x23 // 1 ULEB128 addend
DW_OP_shl = 0x24 DW_OP_shl = 0x24 // 0
DW_OP_shr = 0x25 DW_OP_shr = 0x25 // 0
DW_OP_shra = 0x26 DW_OP_shra = 0x26 // 0
DW_OP_xor = 0x27 DW_OP_xor = 0x27 // 0
DW_OP_skip = 0x2f DW_OP_skip = 0x2f // 1 signed 2-byte constant
DW_OP_bra = 0x28 DW_OP_bra = 0x28 // 1 signed 2-byte constant
DW_OP_eq = 0x29 DW_OP_eq = 0x29 // 0
DW_OP_ge = 0x2a DW_OP_ge = 0x2a // 0
DW_OP_gt = 0x2b DW_OP_gt = 0x2b // 0
DW_OP_le = 0x2c DW_OP_le = 0x2c // 0
DW_OP_lt = 0x2d DW_OP_lt = 0x2d // 0
DW_OP_ne = 0x2e DW_OP_ne = 0x2e // 0
DW_OP_lit0 = 0x30 DW_OP_lit0 = 0x30 // 0 ...
DW_OP_lit31 = 0x4f DW_OP_lit31 = 0x4f // 0 literals 0..31 = (DW_OP_lit0 + literal)
DW_OP_reg0 = 0x50 DW_OP_reg0 = 0x50 // 0 ..
DW_OP_reg31 = 0x6f DW_OP_reg31 = 0x6f // 0 reg 0..31 = (DW_OP_reg0 + regnum)
DW_OP_breg0 = 0x70 DW_OP_breg0 = 0x70 // 1 ...
DW_OP_breg31 = 0x8f DW_OP_breg31 = 0x8f // 1 SLEB128 offset base register 0..31 = (DW_OP_breg0 + regnum)
DW_OP_regx = 0x90 DW_OP_regx = 0x90 // 1 ULEB128 register
DW_OP_fbreg = 0x91 DW_OP_fbreg = 0x91 // 1 SLEB128 offset
DW_OP_bregx = 0x92 DW_OP_bregx = 0x92 // 2 ULEB128 register followed by SLEB128 offset
DW_OP_piece = 0x93 DW_OP_piece = 0x93 // 1 ULEB128 size of piece addressed
DW_OP_deref_size = 0x94 DW_OP_deref_size = 0x94 // 1 1-byte size of data retrieved
DW_OP_xderef_size = 0x95 DW_OP_xderef_size = 0x95 // 1 1-byte size of data retrieved
DW_OP_nop = 0x96 DW_OP_nop = 0x96 // 0
DW_OP_push_object_address = 0x97 DW_OP_push_object_address = 0x97 // 0
DW_OP_call2 = 0x98 DW_OP_call2 = 0x98 // 1 2-byte offset of DIE
DW_OP_call4 = 0x99 DW_OP_call4 = 0x99 // 1 4-byte offset of DIE
DW_OP_call_ref = 0x9a DW_OP_call_ref = 0x9a // 1 4- or 8-byte offset of DIE
DW_OP_form_tls_address = 0x9b DW_OP_form_tls_address = 0x9b // 0
DW_OP_call_frame_cfa = 0x9c DW_OP_call_frame_cfa = 0x9c // 0
DW_OP_bit_piece = 0x9d DW_OP_bit_piece = 0x9d // 2
DW_OP_lo_user = 0xe0 DW_OP_lo_user = 0xe0
DW_OP_hi_user = 0xff DW_OP_hi_user = 0xff
) )
@ -381,6 +387,7 @@ const (
DW_LANG_Fortran90 = 0x0008 DW_LANG_Fortran90 = 0x0008
DW_LANG_Pascal83 = 0x0009 DW_LANG_Pascal83 = 0x0009
DW_LANG_Modula2 = 0x000a DW_LANG_Modula2 = 0x000a
// Dwarf3
DW_LANG_Java = 0x000b DW_LANG_Java = 0x000b
DW_LANG_C99 = 0x000c DW_LANG_C99 = 0x000c
DW_LANG_Ada95 = 0x000d DW_LANG_Ada95 = 0x000d
@ -390,8 +397,11 @@ const (
DW_LANG_ObjC_plus_plus = 0x0011 DW_LANG_ObjC_plus_plus = 0x0011
DW_LANG_UPC = 0x0012 DW_LANG_UPC = 0x0012
DW_LANG_D = 0x0013 DW_LANG_D = 0x0013
// Dwarf4
DW_LANG_Python = 0x0014 DW_LANG_Python = 0x0014
// Dwarf5
DW_LANG_Go = 0x0016 DW_LANG_Go = 0x0016
DW_LANG_lo_user = 0x8000 DW_LANG_lo_user = 0x8000
DW_LANG_hi_user = 0xffff DW_LANG_hi_user = 0xffff
) )
@ -444,6 +454,7 @@ const (
DW_LNS_set_basic_block = 0x07 DW_LNS_set_basic_block = 0x07
DW_LNS_const_add_pc = 0x08 DW_LNS_const_add_pc = 0x08
DW_LNS_fixed_advance_pc = 0x09 DW_LNS_fixed_advance_pc = 0x09
// Dwarf3
DW_LNS_set_prologue_end = 0x0a DW_LNS_set_prologue_end = 0x0a
DW_LNS_set_epilogue_begin = 0x0b DW_LNS_set_epilogue_begin = 0x0b
DW_LNS_set_isa = 0x0c DW_LNS_set_isa = 0x0c
@ -469,32 +480,37 @@ const (
// Table 40. // Table 40.
const ( const (
// operand,...
DW_CFA_nop = 0x00 DW_CFA_nop = 0x00
DW_CFA_set_loc = 0x01 DW_CFA_set_loc = 0x01 // address
DW_CFA_advance_loc1 = 0x02 DW_CFA_advance_loc1 = 0x02 // 1-byte delta
DW_CFA_advance_loc2 = 0x03 DW_CFA_advance_loc2 = 0x03 // 2-byte delta
DW_CFA_advance_loc4 = 0x04 DW_CFA_advance_loc4 = 0x04 // 4-byte delta
DW_CFA_offset_extended = 0x05 DW_CFA_offset_extended = 0x05 // ULEB128 register, ULEB128 offset
DW_CFA_restore_extended = 0x06 DW_CFA_restore_extended = 0x06 // ULEB128 register
DW_CFA_undefined = 0x07 DW_CFA_undefined = 0x07 // ULEB128 register
DW_CFA_same_value = 0x08 DW_CFA_same_value = 0x08 // ULEB128 register
DW_CFA_register = 0x09 DW_CFA_register = 0x09 // ULEB128 register, ULEB128 register
DW_CFA_remember_state = 0x0a DW_CFA_remember_state = 0x0a
DW_CFA_restore_state = 0x0b DW_CFA_restore_state = 0x0b
DW_CFA_def_cfa = 0x0c
DW_CFA_def_cfa_register = 0x0d DW_CFA_def_cfa = 0x0c // ULEB128 register, ULEB128 offset
DW_CFA_def_cfa_offset = 0x0e DW_CFA_def_cfa_register = 0x0d // ULEB128 register
DW_CFA_def_cfa_expression = 0x0f DW_CFA_def_cfa_offset = 0x0e // ULEB128 offset
DW_CFA_expression = 0x10 DW_CFA_def_cfa_expression = 0x0f // BLOCK
DW_CFA_offset_extended_sf = 0x11 DW_CFA_expression = 0x10 // ULEB128 register, BLOCK
DW_CFA_def_cfa_sf = 0x12 DW_CFA_offset_extended_sf = 0x11 // ULEB128 register, SLEB128 offset
DW_CFA_def_cfa_offset_sf = 0x13 DW_CFA_def_cfa_sf = 0x12 // ULEB128 register, SLEB128 offset
DW_CFA_val_offset = 0x14 DW_CFA_def_cfa_offset_sf = 0x13 // SLEB128 offset
DW_CFA_val_offset_sf = 0x15 DW_CFA_val_offset = 0x14 // ULEB128, ULEB128
DW_CFA_val_expression = 0x16 DW_CFA_val_offset_sf = 0x15 // ULEB128, SLEB128
DW_CFA_val_expression = 0x16 // ULEB128, BLOCK
DW_CFA_lo_user = 0x1c DW_CFA_lo_user = 0x1c
DW_CFA_hi_user = 0x3f DW_CFA_hi_user = 0x3f
DW_CFA_advance_loc = 0x1 << 6
DW_CFA_offset = 0x2 << 6 // Opcodes that take an addend operand.
DW_CFA_restore = 0x3 << 6 DW_CFA_advance_loc = 0x1 << 6 // +delta
DW_CFA_offset = 0x2 << 6 // +register (ULEB128 offset)
DW_CFA_restore = 0x3 << 6 // +register
) )

View file

@ -776,6 +776,7 @@ func Elfinit() {
// we use EABI on both linux/arm and freebsd/arm. // we use EABI on both linux/arm and freebsd/arm.
// 32-bit architectures // 32-bit architectures
case '5': case '5':
// we use EABI on both linux/arm and freebsd/arm.
if HEADTYPE == Hlinux || HEADTYPE == Hfreebsd { if HEADTYPE == Hlinux || HEADTYPE == Hfreebsd {
ehdr.flags = 0x5000002 // has entry point, Version5 EABI ehdr.flags = 0x5000002 // has entry point, Version5 EABI
} }
@ -1071,7 +1072,7 @@ const (
ELF_NOTE_NETBSD_NAMESZ = 7 ELF_NOTE_NETBSD_NAMESZ = 7
ELF_NOTE_NETBSD_DESCSZ = 4 ELF_NOTE_NETBSD_DESCSZ = 4
ELF_NOTE_NETBSD_TAG = 1 ELF_NOTE_NETBSD_TAG = 1
ELF_NOTE_NETBSD_VERSION = 599000000 ELF_NOTE_NETBSD_VERSION = 599000000 /* NetBSD 5.99 */
) )
var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00") var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
@ -1671,7 +1672,7 @@ func doelf() {
Addstring(shstrtab, ".shstrtab") Addstring(shstrtab, ".shstrtab")
if Debug['d'] == 0 { if Debug['d'] == 0 { /* -d suppresses dynamic loader format */
Addstring(shstrtab, ".interp") Addstring(shstrtab, ".interp")
Addstring(shstrtab, ".hash") Addstring(shstrtab, ".hash")
Addstring(shstrtab, ".got") Addstring(shstrtab, ".got")
@ -1919,7 +1920,7 @@ func Asmbelf(symo int64) {
Segtext.Filelen += uint64(o) Segtext.Filelen += uint64(o)
} }
if Debug['d'] == 0 { if Debug['d'] == 0 { /* -d suppresses dynamic loader format */
/* interpreter */ /* interpreter */
sh := elfshname(".interp") sh := elfshname(".interp")

View file

@ -37,8 +37,8 @@ func expandpkg(t0 string, pkg string) string {
* package import data * package import data
*/ */
type Import struct { type Import struct {
hash *Import hash *Import // next in hash table
prefix string prefix string // "type", "var", "func", "const"
name string name string
def string def string
file string file string

View file

@ -265,8 +265,8 @@ type ElfSect struct {
type ElfObj struct { type ElfObj struct {
f *Biobuf f *Biobuf
base int64 base int64 // offset in f where ELF begins
length int64 length int64 // length of ELF
is64 int is64 int
name string name string
e binary.ByteOrder e binary.ByteOrder
@ -624,7 +624,7 @@ func ldelf(f *Biobuf, pkg string, length int64, pn string) {
} }
sect = &elfobj.sect[sym.shndx:][0] sect = &elfobj.sect[sym.shndx:][0]
if sect.sym == nil { if sect.sym == nil {
if strings.HasPrefix(sym.name, ".Linfo_string") { if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
continue continue
} }
Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_) Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
@ -901,7 +901,7 @@ func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
case ElfSymBindLocal: case ElfSymBindLocal:
if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) { if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
// binutils for arm generate these elfmapping // binutils for arm generate these mapping
// symbols, ignore these // symbols, ignore these
break break
} }

View file

@ -41,8 +41,8 @@ const (
type LdMachoObj struct { type LdMachoObj struct {
f *Biobuf f *Biobuf
base int64 base int64 // off in f where Mach-O begins
length int64 length int64 // length of Mach-O
is64 bool is64 bool
name string name string
e binary.ByteOrder e binary.ByteOrder

View file

@ -58,7 +58,7 @@ const (
IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16 IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16
IMAGE_SYM_CLASS_REGISTER_PARAM = 17 IMAGE_SYM_CLASS_REGISTER_PARAM = 17
IMAGE_SYM_CLASS_BIT_FIELD = 18 IMAGE_SYM_CLASS_BIT_FIELD = 18
IMAGE_SYM_CLASS_FAR_EXTERNAL = 68 IMAGE_SYM_CLASS_FAR_EXTERNAL = 68 /* Not in PECOFF v8 spec */
IMAGE_SYM_CLASS_BLOCK = 100 IMAGE_SYM_CLASS_BLOCK = 100
IMAGE_SYM_CLASS_FUNCTION = 101 IMAGE_SYM_CLASS_FUNCTION = 101
IMAGE_SYM_CLASS_END_OF_STRUCT = 102 IMAGE_SYM_CLASS_END_OF_STRUCT = 102

View file

@ -129,15 +129,15 @@ var Symsize int32
const ( const (
MAXIO = 8192 MAXIO = 8192
MINFUNC = 16 MINFUNC = 16 // minimum size for a function
) )
type Segment struct { type Segment struct {
Rwx uint8 Rwx uint8 // permission as usual unix bits (5 = r-x etc)
Vaddr uint64 Vaddr uint64 // virtual address
Length uint64 Length uint64 // length in memory
Fileoff uint64 Fileoff uint64 // file offset
Filelen uint64 Filelen uint64 // length on disk
Sect *Section Sect *Section
} }
@ -253,6 +253,8 @@ var Bso Biobuf
var coutbuf Biobuf var coutbuf Biobuf
const ( const (
// Whether to assume that the external linker is "gold"
// (http://sourceware.org/ml/binutils/2008-03/msg00162.html).
AssumeGoldLinker = 0 AssumeGoldLinker = 0
) )
@ -1137,7 +1139,7 @@ var le = Endian{Le16, Le32, Le64}
type Chain struct { type Chain struct {
sym *LSym sym *LSym
up *Chain up *Chain
limit int limit int // limit on entry to sym
} }
var morestack *LSym var morestack *LSym

View file

@ -96,7 +96,14 @@ type IMAGE_EXPORT_DIRECTORY struct {
const ( const (
PEBASE = 0x00400000 PEBASE = 0x00400000
// SectionAlignment must be greater than or equal to FileAlignment.
// The default is the page size for the architecture.
PESECTALIGN = 0x1000 PESECTALIGN = 0x1000
// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
// The default is 512. If the SectionAlignment is less than
// the architecture's page size, then FileAlignment must match SectionAlignment.
PEFILEALIGN = 2 << 8 PEFILEALIGN = 2 << 8
) )
@ -921,7 +928,7 @@ func Asmbpe() {
if pe64 != 0 { if pe64 != 0 {
fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64)) fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE
oh64.Magic = 0x20b oh64.Magic = 0x20b // PE32+
} else { } else {
fh.SizeOfOptionalHeader = uint16(binary.Size(&oh)) fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE

View file

@ -44,7 +44,7 @@ const (
) )
const ( const (
REG_R0 = obj.RBaseARM + iota REG_R0 = obj.RBaseARM + iota // must be 16-aligned
REG_R1 REG_R1
REG_R2 REG_R2
REG_R3 REG_R3
@ -60,7 +60,8 @@ const (
REG_R13 REG_R13
REG_R14 REG_R14
REG_R15 REG_R15
REG_F0
REG_F0 // must be 16-aligned
REG_F1 REG_F1
REG_F2 REG_F2
REG_F3 REG_F3
@ -76,28 +77,37 @@ const (
REG_F13 REG_F13
REG_F14 REG_F14
REG_F15 REG_F15
REG_FPSR
REG_FPSR // must be 2-aligned
REG_FPCR REG_FPCR
REG_CPSR
REG_CPSR // must be 2-aligned
REG_SPSR REG_SPSR
MAXREG MAXREG
REGRET = REG_R0 REGRET = REG_R0
/* compiler allocates R1 up as temps */
/* compiler allocates register variables R3 up */
/* compiler allocates external registers R10 down */
REGEXT = REG_R10 REGEXT = REG_R10
/* these two registers are declared in runtime.h */
REGG = REGEXT - 0 REGG = REGEXT - 0
REGM = REGEXT - 1 REGM = REGEXT - 1
REGCTXT = REG_R7 REGCTXT = REG_R7
REGTMP = REG_R11 REGTMP = REG_R11
REGSP = REG_R13 REGSP = REG_R13
REGLINK = REG_R14 REGLINK = REG_R14
REGPC = REG_R15 REGPC = REG_R15
NFREG = 16 NFREG = 16
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F7 down */
FREGRET = REG_F0 FREGRET = REG_F0
FREGEXT = REG_F7 FREGEXT = REG_F7
FREGTMP = REG_F15 FREGTMP = REG_F15
) )
/* compiler allocates register variables F0 up */
/* compiler allocates external registers F7 down */
const ( const (
C_NONE = iota C_NONE = iota
C_REG C_REG
@ -108,37 +118,46 @@ const (
C_FREG C_FREG
C_PSR C_PSR
C_FCR C_FCR
C_RCON
C_NCON C_RCON /* 0xff rotated */
C_SCON C_NCON /* ~RCON */
C_SCON /* 0xffff */
C_LCON C_LCON
C_LCONADDR C_LCONADDR
C_ZFCON C_ZFCON
C_SFCON C_SFCON
C_LFCON C_LFCON
C_RACON C_RACON
C_LACON C_LACON
C_SBRA C_SBRA
C_LBRA C_LBRA
C_HAUTO
C_FAUTO C_HAUTO /* halfword insn offset (-0xff to 0xff) */
C_HFAUTO C_FAUTO /* float insn offset (0 to 0x3fc, word aligned) */
C_SAUTO C_HFAUTO /* both H and F */
C_SAUTO /* -0xfff to 0xfff */
C_LAUTO C_LAUTO
C_HOREG C_HOREG
C_FOREG C_FOREG
C_HFOREG C_HFOREG
C_SOREG C_SOREG
C_ROREG C_ROREG
C_SROREG C_SROREG /* both nil and R */
C_LOREG C_LOREG
C_PC C_PC
C_SP C_SP
C_HREG C_HREG
C_ADDR
C_ADDR /* reference to relocatable address */
C_TEXTSIZE C_TEXTSIZE
C_GOK C_GOK
C_NCLASS
C_NCLASS /* must be the last */
) )
const ( const (
@ -156,7 +175,13 @@ const (
ACMN ACMN
AORR AORR
ABIC ABIC
AMVN AMVN
/*
* Do not reorder or fragment the conditional branch
* opcodes, or the predication code will break
*/
ABEQ ABEQ
ABNE ABNE
ABCS ABCS
@ -173,6 +198,7 @@ const (
ABLT ABLT
ABGT ABGT
ABLE ABLE
AMOVWD AMOVWD
AMOVWF AMOVWF
AMOVDW AMOVDW
@ -181,6 +207,7 @@ const (
AMOVDF AMOVDF
AMOVF AMOVF
AMOVD AMOVD
ACMPF ACMPF
ACMPD ACMPD
AADDF AADDF
@ -195,6 +222,7 @@ const (
ASQRTD ASQRTD
AABSF AABSF
AABSD AABSD
ASRL ASRL
ASRA ASRA
ASLL ASLL
@ -204,6 +232,7 @@ const (
ADIV ADIV
AMOD AMOD
AMODU AMODU
AMOVB AMOVB
AMOVBS AMOVBS
AMOVBU AMOVBU
@ -214,33 +243,46 @@ const (
AMOVM AMOVM
ASWPBU ASWPBU
ASWPW ASWPW
ARFE ARFE
ASWI ASWI
AMULA AMULA
AWORD AWORD
ABCASE ABCASE
ACASE ACASE
AMULL AMULL
AMULAL AMULAL
AMULLU AMULLU
AMULALU AMULALU
ABX ABX
ABXRET ABXRET
ADWORD ADWORD
ALDREX ALDREX
ASTREX ASTREX
ALDREXD ALDREXD
ASTREXD ASTREXD
APLD APLD
ACLZ ACLZ
AMULWT AMULWT
AMULWB AMULWB
AMULAWT AMULAWT
AMULAWB AMULAWB
ADATABUNDLE ADATABUNDLE
ADATABUNDLEEND ADATABUNDLEEND
AMRC
AMRC // MRC/MCR
ALAST ALAST
// aliases
AB = obj.AJMP AB = obj.AJMP
ABL = obj.ACALL ABL = obj.ACALL
) )
@ -251,9 +293,14 @@ const (
C_SBIT = 1 << 4 C_SBIT = 1 << 4
C_PBIT = 1 << 5 C_PBIT = 1 << 5
C_WBIT = 1 << 6 C_WBIT = 1 << 6
C_FBIT = 1 << 7 C_FBIT = 1 << 7 /* psr flags-only */
C_UBIT = 1 << 7 C_UBIT = 1 << 7 /* up bit, unsigned bit */
// These constants are the ARM condition codes encodings,
// XORed with 14 so that C_SCOND_NONE has value 0,
// so that a zeroed Prog.scond means "always execute".
C_SCOND_XOR = 14 C_SCOND_XOR = 14
C_SCOND_EQ = 0 ^ C_SCOND_XOR C_SCOND_EQ = 0 ^ C_SCOND_XOR
C_SCOND_NE = 1 ^ C_SCOND_XOR C_SCOND_NE = 1 ^ C_SCOND_XOR
C_SCOND_HS = 2 ^ C_SCOND_XOR C_SCOND_HS = 2 ^ C_SCOND_XOR
@ -270,13 +317,10 @@ const (
C_SCOND_LE = 13 ^ C_SCOND_XOR C_SCOND_LE = 13 ^ C_SCOND_XOR
C_SCOND_NONE = 14 ^ C_SCOND_XOR C_SCOND_NONE = 14 ^ C_SCOND_XOR
C_SCOND_NV = 15 ^ C_SCOND_XOR C_SCOND_NV = 15 ^ C_SCOND_XOR
/* D_SHIFT type */
SHIFT_LL = 0 << 5 SHIFT_LL = 0 << 5
SHIFT_LR = 1 << 5 SHIFT_LR = 1 << 5
SHIFT_AR = 2 << 5 SHIFT_AR = 2 << 5
SHIFT_RR = 3 << 5 SHIFT_RR = 3 << 5
) )
/*
* this is the ranlib header
*/
var SYMDEF string

View file

@ -350,8 +350,8 @@ func asmoutnacl(ctxt *obj.Link, origPC int32, p *obj.Prog, o *Optab, out []uint3
if out != nil { if out != nil {
out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c0013f | (uint32(p.To.Reg)&15)<<12 | (uint32(p.To.Reg)&15)<<16 // BIC $0xc000000f, Rx out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c0013f | (uint32(p.To.Reg)&15)<<12 | (uint32(p.To.Reg)&15)<<16 // BIC $0xc000000f, Rx
if p.As == AB { if p.As == AB {
out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff10 | (uint32(p.To.Reg)&15)<<0 // BX Rx // ABL out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff10 | (uint32(p.To.Reg)&15)<<0 // BX Rx
} else { } else { // ABL
out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff30 | (uint32(p.To.Reg)&15)<<0 // BLX Rx out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff30 | (uint32(p.To.Reg)&15)<<0 // BLX Rx
} }
} }
@ -473,7 +473,8 @@ func asmoutnacl(ctxt *obj.Link, origPC int32, p *obj.Prog, o *Optab, out []uint3
break break
} }
if (p.To.Type == obj.TYPE_MEM && p.To.Reg != REG_R13 && p.To.Reg != REG_R9) || (p.From.Type == obj.TYPE_MEM && p.From.Reg != REG_R13 && p.From.Reg != REG_R9) { // MOVW Rx, X(Ry), y != 13 && y != 9 // MOVW X(Rx), Ry, x != 13 && x != 9 if (p.To.Type == obj.TYPE_MEM && p.To.Reg != REG_R13 && p.To.Reg != REG_R9) || // MOVW Rx, X(Ry), y != 13 && y != 9
(p.From.Type == obj.TYPE_MEM && p.From.Reg != REG_R13 && p.From.Reg != REG_R9) { // MOVW X(Rx), Ry, x != 13 && x != 9
var a *obj.Addr var a *obj.Addr
if p.To.Type == obj.TYPE_MEM { if p.To.Type == obj.TYPE_MEM {
a = &p.To a = &p.To

View file

@ -2,6 +2,102 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Writing of Go object files.
//
// Originally, Go object files were Plan 9 object files, but no longer.
// Now they are more like standard object files, in that each symbol is defined
// by an associated memory image (bytes) and a list of relocations to apply
// during linking. We do not (yet?) use a standard file format, however.
// For now, the format is chosen to be as simple as possible to read and write.
// It may change for reasons of efficiency, or we may even switch to a
// standard file format if there are compelling benefits to doing so.
// See golang.org/s/go13linker for more background.
//
// The file format is:
//
// - magic header: "\x00\x00go13ld"
// - byte 1 - version number
// - sequence of strings giving dependencies (imported packages)
// - empty string (marks end of sequence)
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
//
// All integers are stored in a zigzag varint format.
// See golang.org/s/go12symtab for a definition.
//
// Data blocks and strings are both stored as an integer
// followed by that many bytes.
//
// A symbol reference is a string name followed by a version.
// An empty name corresponds to a nil LSym* pointer.
//
// Each symbol is laid out as the following fields (taken from LSym*):
//
// - byte 0xfe (sanity check for synchronization)
// - type [int]
// - name [string]
// - version [int]
// - flags [int]
// 1 dupok
// - size [int]
// - gotype [symbol reference]
// - p [data block]
// - nr [int]
// - r [nr relocations, sorted by off]
//
// If type == STEXT, there are a few more fields:
//
// - args [int]
// - locals [int]
// - nosplit [int]
// - flags [int]
// 1 leaf
// 2 C function
// - nlocal [int]
// - local [nlocal automatics]
// - pcln [pcln table]
//
// Each relocation has the encoding:
//
// - off [int]
// - siz [int]
// - type [int]
// - add [int]
// - xadd [int]
// - sym [symbol reference]
// - xsym [symbol reference]
//
// Each local has the encoding:
//
// - asym [symbol reference]
// - offset [int]
// - type [int]
// - gotype [symbol reference]
//
// The pcln table has the encoding:
//
// - pcsp [data block]
// - pcfile [data block]
// - pcline [data block]
// - npcdata [int]
// - pcdata [npcdata data blocks]
// - nfuncdata [int]
// - funcdata [nfuncdata symbol references]
// - funcdatasym [nfuncdata ints]
// - nfile [int]
// - file [nfile symbol references]
//
// The file layout and meaning of type integers are architecture-independent.
//
// TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings.
// - The actual symbol memory images are interlaced with the symbol
// metadata. They should be separated, to reduce the I/O required to
// load just the metadata.
// - The symbol references should be shortened, either with a symbol
// table or by using a simple backward index to an earlier mentioned symbol.
package obj package obj
import ( import (

View file

@ -39,11 +39,10 @@ import "cmd/internal/obj"
const ( const (
NSNAME = 8 NSNAME = 8
NSYM = 50 NSYM = 50
NREG = 32 NREG = 32 /* number of general registers */
NFREG = 32 NFREG = 32 /* number of floating point registers */
) )
// avoid conflict with ucontext.h. sigh.
const ( const (
REG_R0 = obj.RBasePPC64 + iota REG_R0 = obj.RBasePPC64 + iota
REG_R1 REG_R1
@ -77,6 +76,7 @@ const (
REG_R29 REG_R29
REG_R30 REG_R30
REG_R31 REG_R31
REG_F0 = obj.RBasePPC64 + 32 + iota - 32 REG_F0 = obj.RBasePPC64 + 32 + iota - 32
REG_F1 REG_F1
REG_F2 REG_F2
@ -109,7 +109,9 @@ const (
REG_F29 REG_F29
REG_F30 REG_F30
REG_F31 REG_F31
REG_SPECIAL = obj.RBasePPC64 + 64 REG_SPECIAL = obj.RBasePPC64 + 64
REG_CR0 = obj.RBasePPC64 + 64 + iota - 65 REG_CR0 = obj.RBasePPC64 + 64 + iota - 65
REG_CR1 REG_CR1
REG_CR2 REG_CR2
@ -118,37 +120,41 @@ const (
REG_CR5 REG_CR5
REG_CR6 REG_CR6
REG_CR7 REG_CR7
REG_MSR = obj.RBasePPC64 + 72 + iota - 73 REG_MSR = obj.RBasePPC64 + 72 + iota - 73
REG_FPSCR REG_FPSCR
REG_CR REG_CR
REG_SPR0 = obj.RBasePPC64 + 1024
REG_DCR0 = obj.RBasePPC64 + 2048 REG_SPR0 = obj.RBasePPC64 + 1024 // first of 1024 registers
REG_DCR0 = obj.RBasePPC64 + 2048 // first of 1024 registers
REG_XER = REG_SPR0 + 1 REG_XER = REG_SPR0 + 1
REG_LR = REG_SPR0 + 8 REG_LR = REG_SPR0 + 8
REG_CTR = REG_SPR0 + 9 REG_CTR = REG_SPR0 + 9
REGZERO = REG_R0
REGZERO = REG_R0 /* set to zero */
REGSP = REG_R1 REGSP = REG_R1
REGSB = REG_R2 REGSB = REG_R2
REGRET = REG_R3 REGRET = REG_R3
REGARG = -1 REGARG = -1 /* -1 disables passing the first argument in register */
REGRT1 = REG_R3 REGRT1 = REG_R3 /* reserved for runtime, duffzero and duffcopy */
REGRT2 = REG_R4 REGRT2 = REG_R4 /* reserved for runtime, duffcopy */
REGMIN = REG_R7 REGMIN = REG_R7 /* register variables allocated from here to REGMAX */
REGCTXT = REG_R11 REGCTXT = REG_R11 /* context for closures */
REGTLS = REG_R13 REGTLS = REG_R13 /* C ABI TLS base pointer */
REGMAX = REG_R27 REGMAX = REG_R27
REGEXT = REG_R30 REGEXT = REG_R30 /* external registers allocated from here down */
REGG = REG_R30 REGG = REG_R30 /* G */
REGTMP = REG_R31 REGTMP = REG_R31 /* used by the linker */
FREGRET = REG_F0 FREGRET = REG_F0
FREGMIN = REG_F17 FREGMIN = REG_F17 /* first register variable */
FREGMAX = REG_F26 FREGMAX = REG_F26 /* last register variable for 9g only */
FREGEXT = REG_F26 FREGEXT = REG_F26 /* first external register */
FREGCVI = REG_F27 FREGCVI = REG_F27 /* floating conversion constant */
FREGZERO = REG_F28 FREGZERO = REG_F28 /* both float and double */
FREGHALF = REG_F29 FREGHALF = REG_F29 /* double */
FREGONE = REG_F30 FREGONE = REG_F30 /* double */
FREGTWO = REG_F31 FREGTWO = REG_F31 /* double */
) )
/* /*
@ -166,6 +172,7 @@ const (
) )
const ( const (
/* mark flags */
LABEL = 1 << 0 LABEL = 1 << 0
LEAF = 1 << 1 LEAF = 1 << 1
FLOAT = 1 << 2 FLOAT = 1 << 2
@ -183,19 +190,19 @@ const (
C_REG C_REG
C_FREG C_FREG
C_CREG C_CREG
C_SPR C_SPR /* special processor register */
C_ZCON C_ZCON
C_SCON C_SCON /* 16 bit signed */
C_UCON C_UCON /* 32 bit signed, low 16 bits 0 */
C_ADDCON C_ADDCON /* -0x8000 <= v < 0 */
C_ANDCON C_ANDCON /* 0 < v <= 0xFFFF */
C_LCON C_LCON /* other 32 */
C_DCON C_DCON /* other 64 (could subdivide further) */
C_SACON C_SACON /* $n(REG) where n <= int16 */
C_SECON C_SECON
C_LACON C_LACON /* $n(REG) where int16 < n <= int32 */
C_LECON C_LECON
C_DACON C_DACON /* $n(REG) where int32 < n */
C_SBRA C_SBRA
C_LBRA C_LBRA
C_SAUTO C_SAUTO
@ -214,7 +221,8 @@ const (
C_GOK C_GOK
C_ADDR C_ADDR
C_TEXTSIZE C_TEXTSIZE
C_NCLASS
C_NCLASS /* must be the last */
) )
const ( const (
@ -414,6 +422,7 @@ const (
ASYNC ASYNC
AXOR AXOR
AXORCC AXORCC
ADCBF ADCBF
ADCBI ADCBI
ADCBST ADCBST
@ -430,9 +439,13 @@ const (
ATLBIEL ATLBIEL
ATLBSYNC ATLBSYNC
ATW ATW
ASYSCALL ASYSCALL
AWORD AWORD
ARFCI ARFCI
/* optional on 32-bit */
AFRES AFRES
AFRESCC AFRESCC
AFRSQRTE AFRSQRTE
@ -443,9 +456,12 @@ const (
AFSQRTCC AFSQRTCC
AFSQRTS AFSQRTS
AFSQRTSCC AFSQRTSCC
/* 64-bit */
ACNTLZD ACNTLZD
ACNTLZDCC ACNTLZDCC
ACMPW ACMPW /* CMP with L=0 */
ACMPWU ACMPWU
ADIVD ADIVD
ADIVDCC ADIVDCC
@ -457,6 +473,7 @@ const (
ADIVDUV ADIVDUV
AEXTSW AEXTSW
AEXTSWCC AEXTSWCC
/* AFCFIW; AFCFIWCC */
AFCFID AFCFID
AFCFIDCC AFCFIDCC
AFCTID AFCTID
@ -498,6 +515,8 @@ const (
ASRDCC ASRDCC
ASTDCCC ASTDCCC
ATD ATD
/* 64-bit pseudo operation */
ADWORD ADWORD
AREMD AREMD
AREMDCC AREMDCC
@ -507,8 +526,13 @@ const (
AREMDUCC AREMDUCC
AREMDUV AREMDUV
AREMDUVCC AREMDUVCC
/* more 64-bit operations */
AHRFID AHRFID
ALAST ALAST
// aliases
ABR = obj.AJMP ABR = obj.AJMP
ABL = obj.ACALL ABL = obj.ACALL
ARETURN = obj.ARET ARETURN = obj.ARET

View file

@ -1331,6 +1331,7 @@ func OP_RLW(op uint32, a uint32, s uint32, sh uint32, mb uint32, me uint32) uint
} }
const ( const (
/* each rhs is OPVCC(_, _, _, _) */
OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0 OP_ADD = 31<<26 | 266<<1 | 0<<10 | 0
OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0 OP_ADDI = 14<<26 | 0<<1 | 0<<10 | 0
OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0 OP_ADDIS = 15<<26 | 0<<1 | 0<<10 | 0

View file

@ -264,6 +264,7 @@ const (
AXORB AXORB
AXORL AXORL
AXORW AXORW
AFMOVB AFMOVB
AFMOVBP AFMOVBP
AFMOVD AFMOVD
@ -278,6 +279,7 @@ const (
AFMOVWP AFMOVWP
AFMOVX AFMOVX
AFMOVXP AFMOVXP
AFCOMB AFCOMB
AFCOMBP AFCOMBP
AFCOMD AFCOMD
@ -292,38 +294,46 @@ const (
AFUCOM AFUCOM
AFUCOMP AFUCOMP
AFUCOMPP AFUCOMPP
AFADDDP AFADDDP
AFADDW AFADDW
AFADDL AFADDL
AFADDF AFADDF
AFADDD AFADDD
AFMULDP AFMULDP
AFMULW AFMULW
AFMULL AFMULL
AFMULF AFMULF
AFMULD AFMULD
AFSUBDP AFSUBDP
AFSUBW AFSUBW
AFSUBL AFSUBL
AFSUBF AFSUBF
AFSUBD AFSUBD
AFSUBRDP AFSUBRDP
AFSUBRW AFSUBRW
AFSUBRL AFSUBRL
AFSUBRF AFSUBRF
AFSUBRD AFSUBRD
AFDIVDP AFDIVDP
AFDIVW AFDIVW
AFDIVL AFDIVL
AFDIVF AFDIVF
AFDIVD AFDIVD
AFDIVRDP AFDIVRDP
AFDIVRW AFDIVRW
AFDIVRL AFDIVRL
AFDIVRF AFDIVRF
AFDIVRD AFDIVRD
AFXCHD AFXCHD
AFFREE AFFREE
AFLDCW AFLDCW
AFLDENV AFLDENV
AFRSTOR AFRSTOR
@ -331,6 +341,7 @@ const (
AFSTCW AFSTCW
AFSTENV AFSTENV
AFSTSW AFSTSW
AF2XM1 AF2XM1
AFABS AFABS
AFCHS AFCHS
@ -361,6 +372,8 @@ const (
AFXTRACT AFXTRACT
AFYL2X AFYL2X
AFYL2XP1 AFYL2XP1
// extra 32-bit operations
ACMPXCHGB ACMPXCHGB
ACMPXCHGL ACMPXCHGL
ACMPXCHGW ACMPXCHGW
@ -382,6 +395,8 @@ const (
AXADDB AXADDB
AXADDL AXADDL
AXADDW AXADDW
// conditional move
ACMOVLCC ACMOVLCC
ACMOVLCS ACMOVLCS
ACMOVLEQ ACMOVLEQ
@ -430,6 +445,8 @@ const (
ACMOVWPC ACMOVWPC
ACMOVWPL ACMOVWPL
ACMOVWPS ACMOVWPS
// 64-bit
AADCQ AADCQ
AADDQ AADDQ
AANDQ AANDQ
@ -481,6 +498,8 @@ const (
AXADDQ AXADDQ
AXCHGQ AXCHGQ
AXORQ AXORQ
// media
AADDPD AADDPD
AADDPS AADDPS
AADDSD AADDSD
@ -682,6 +701,7 @@ const (
AUNPCKLPS AUNPCKLPS
AXORPD AXORPD
AXORPS AXORPS
APF2IW APF2IW
APF2IL APF2IL
API2FW API2FW
@ -690,25 +710,32 @@ const (
ARETFL ARETFL
ARETFQ ARETFQ
ASWAPGS ASWAPGS
AMODE AMODE
ACRC32B ACRC32B
ACRC32Q ACRC32Q
AIMUL3Q AIMUL3Q
APREFETCHT0 APREFETCHT0
APREFETCHT1 APREFETCHT1
APREFETCHT2 APREFETCHT2
APREFETCHNTA APREFETCHNTA
AMOVQL AMOVQL
ABSWAPL ABSWAPL
ABSWAPQ ABSWAPQ
AAESENC AAESENC
AAESENCLAST AAESENCLAST
AAESDEC AAESDEC
AAESDECLAST AAESDECLAST
AAESIMC AAESIMC
AAESKEYGENASSIST AAESKEYGENASSIST
APSHUFD APSHUFD
APCLMULQDQ APCLMULQDQ
// from 386
AJCXZW AJCXZW
AFCMOVCC AFCMOVCC
AFCMOVCS AFCMOVCS
@ -722,6 +749,7 @@ const (
AFCOMIP AFCOMIP
AFUCOMI AFUCOMI
AFUCOMIP AFUCOMIP
ALAST ALAST
) )
@ -743,6 +771,7 @@ const (
REG_R13B REG_R13B
REG_R14B REG_R14B
REG_R15B REG_R15B
REG_AX = obj.RBaseAMD64 + 16 + iota - 17 REG_AX = obj.RBaseAMD64 + 16 + iota - 17
REG_CX REG_CX
REG_DX REG_DX
@ -759,12 +788,16 @@ const (
REG_R13 REG_R13
REG_R14 REG_R14
REG_R15 REG_R15
REG_AH = obj.RBaseAMD64 + 32 + iota - 33 REG_AH = obj.RBaseAMD64 + 32 + iota - 33
REG_CH REG_CH
REG_DH REG_DH
REG_BH REG_BH
REG_F0 = obj.RBaseAMD64 + 36 REG_F0 = obj.RBaseAMD64 + 36
REG_M0 = obj.RBaseAMD64 + 44 REG_M0 = obj.RBaseAMD64 + 44
REG_X0 = obj.RBaseAMD64 + 52 + iota - 39 REG_X0 = obj.RBaseAMD64 + 52 + iota - 39
REG_X1 REG_X1
REG_X2 REG_X2
@ -781,31 +814,37 @@ const (
REG_X13 REG_X13
REG_X14 REG_X14
REG_X15 REG_X15
REG_CS = obj.RBaseAMD64 + 68 + iota - 55 REG_CS = obj.RBaseAMD64 + 68 + iota - 55
REG_SS REG_SS
REG_DS REG_DS
REG_ES REG_ES
REG_FS REG_FS
REG_GS REG_GS
REG_GDTR
REG_IDTR REG_GDTR /* global descriptor table register */
REG_LDTR REG_IDTR /* interrupt descriptor table register */
REG_MSW REG_LDTR /* local descriptor table register */
REG_TASK REG_MSW /* machine status word */
REG_TASK /* task register */
REG_CR = obj.RBaseAMD64 + 79 REG_CR = obj.RBaseAMD64 + 79
REG_DR = obj.RBaseAMD64 + 95 REG_DR = obj.RBaseAMD64 + 95
REG_TR = obj.RBaseAMD64 + 103 REG_TR = obj.RBaseAMD64 + 103
REG_TLS = obj.RBaseAMD64 + 111 + iota - 69 REG_TLS = obj.RBaseAMD64 + 111 + iota - 69
MAXREG MAXREG
REGARG = -1 REGARG = -1
REGRET = REG_AX REGRET = REG_AX
FREGRET = REG_X0 FREGRET = REG_X0
REGSP = REG_SP REGSP = REG_SP
REGTMP = REG_DI REGTMP = REG_DI
REGCTXT = REG_DX REGCTXT = REG_DX
REGEXT = REG_R15 REGEXT = REG_R15 /* compiler allocates external registers R15 down */
FREGMIN = REG_X0 + 5 FREGMIN = REG_X0 + 5 /* first register variable */
FREGEXT = REG_X0 + 15 FREGEXT = REG_X0 + 15 /* first external register */
T_TYPE = 1 << 0 T_TYPE = 1 << 0
T_INDEX = 1 << 1 T_INDEX = 1 << 1
T_OFFSET = 1 << 2 T_OFFSET = 1 << 2

View file

@ -40,7 +40,21 @@ import (
// Instruction layout. // Instruction layout.
const ( const (
MaxAlign = 32 MaxAlign = 32 // max data alignment
// Loop alignment constants:
// want to align loop entry to LoopAlign-byte boundary,
// and willing to insert at most MaxLoopPad bytes of NOP to do so.
// We define a loop entry as the target of a backward jump.
//
// gcc uses MaxLoopPad = 10 for its 'generic x86-64' config,
// and it aligns all jump targets, not just backward jump targets.
//
// As of 6/1/2012, the effect of setting MaxLoopPad = 10 here
// is very slight but negative, so the alignment is disabled by
// setting MaxLoopPad = 0. The code is here for reference and
// for future experiments.
//
LoopAlign = 16 LoopAlign = 16
MaxLoopPad = 0 MaxLoopPad = 0
FuncAlign = 16 FuncAlign = 16
@ -173,7 +187,7 @@ const (
Zm_r_3d Zm_r_3d
Zm_r_xm_nr Zm_r_xm_nr
Zr_m_xm_nr Zr_m_xm_nr
Zibm_r Zibm_r /* mmx1,mmx2/mem64,imm8 */
Zmb_r Zmb_r
Zaut_r Zaut_r
Zo_m Zo_m
@ -196,26 +210,28 @@ const (
const ( const (
Px = 0 Px = 0
Px1 = 1 // symbolic; exact value doesn't matter Px1 = 1 // symbolic; exact value doesn't matter
P32 = 0x32 P32 = 0x32 /* 32-bit only */
Pe = 0x66 Pe = 0x66 /* operand escape */
Pm = 0x0f Pm = 0x0f /* 2byte opcode escape */
Pq = 0xff Pq = 0xff /* both escapes: 66 0f */
Pb = 0xfe Pb = 0xfe /* byte operands */
Pf2 = 0xf2 Pf2 = 0xf2 /* xmm escape 1: f2 0f */
Pf3 = 0xf3 Pf3 = 0xf3 /* xmm escape 2: f3 0f */
Pq3 = 0x67 Pq3 = 0x67 /* xmm escape 3: 66 48 0f */
Pw = 0x48 Pw = 0x48 /* Rex.w */
Pw8 = 0x90 // symbolic; exact value doesn't matter Pw8 = 0x90 // symbolic; exact value doesn't matter
Py = 0x80 Py = 0x80 /* defaults to 64-bit mode */
Py1 = 0x81 // symbolic; exact value doesn't matter Py1 = 0x81 // symbolic; exact value doesn't matter
Py3 = 0x83 // symbolic; exact value doesn't matter Py3 = 0x83 // symbolic; exact value doesn't matter
Rxf = 1 << 9
Rxt = 1 << 8 Rxf = 1 << 9 /* internal flag for Rxr on from */
Rxw = 1 << 3 Rxt = 1 << 8 /* internal flag for Rxr on to */
Rxr = 1 << 2 Rxw = 1 << 3 /* =1, 64-bit operand size */
Rxx = 1 << 1 Rxr = 1 << 2 /* extend modrm reg */
Rxb = 1 << 0 Rxx = 1 << 1 /* extend sib index */
Maxand = 10 Rxb = 1 << 0 /* extend modrm r/m, sib base, or opcode reg */
Maxand = 10 /* in -a output width of the byte codes */
) )
var ycover [Ymax * Ymax]uint8 var ycover [Ymax * Ymax]uint8