mirror of
https://github.com/golang/go
synced 2024-09-29 14:14:29 -06:00
[dev.regabi] cmd/compile: flatten dependency graph [generated]
This CL shuffles a couple functions around to help flatten the package dependency graph somewhat: 1. ssa.LosesStmtMark is only ever used in associated with an objw.Prog, so we might as well move it to that package. This removes a dependency from objw (a relatively low-level utility package that wraps cmd/internal/obj) on ssa (a large and relatively high-level package). 2. Moves liveness.SetTypeBits into a new package typebits. A single-function package is a bit on the silly side, but reflectdata shouldn't need to depend on liveness (nor vice versa). [git-generate] cd src/cmd/compile/internal/ssa rf ' mv LosesStmtMark prog.go mv prog.go cmd/compile/internal/objw ' cd ../liveness rf ' mv SetTypeBits Set mv Set typebits.go rm typebits.go:/Copyright/+4,/^package/-0 mv typebits.go cmd/compile/internal/typebits ' Change-Id: Ic9a983f0ad6c0cf1a537f99889699a8444699e6e Reviewed-on: https://go-review.googlesource.com/c/go/+/280447 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
parent
f8afb8216a
commit
3383b5c74a
@ -24,6 +24,7 @@ import (
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/compile/internal/typebits"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
@ -375,82 +376,6 @@ func (lv *liveness) blockEffects(b *ssa.Block) *blockEffects {
|
||||
return &lv.be[b.ID]
|
||||
}
|
||||
|
||||
// NOTE: The bitmap for a specific type t could be cached in t after
|
||||
// the first run and then simply copied into bv at the correct offset
|
||||
// on future calls with the same type t.
|
||||
func SetTypeBits(t *types.Type, off int64, bv bitvec.BitVec) {
|
||||
if t.Align > 0 && off&int64(t.Align-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
|
||||
}
|
||||
if !t.HasPointers() {
|
||||
// Note: this case ensures that pointers to go:notinheap types
|
||||
// are not considered pointers by garbage collection and stack copying.
|
||||
return
|
||||
}
|
||||
|
||||
switch t.Kind() {
|
||||
case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) // pointer
|
||||
|
||||
case types.TSTRING:
|
||||
// struct { byte *str; intgo len; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
|
||||
|
||||
case types.TINTER:
|
||||
// struct { Itab *tab; void *data; }
|
||||
// or, when isnilinter(t)==true:
|
||||
// struct { Type *type; void *data; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
// The first word of an interface is a pointer, but we don't
|
||||
// treat it as such.
|
||||
// 1. If it is a non-empty interface, the pointer points to an itab
|
||||
// which is always in persistentalloc space.
|
||||
// 2. If it is an empty interface, the pointer points to a _type.
|
||||
// a. If it is a compile-time-allocated type, it points into
|
||||
// the read-only data section.
|
||||
// b. If it is a reflect-allocated type, it points into the Go heap.
|
||||
// Reflect is responsible for keeping a reference to
|
||||
// the underlying type so it won't be GCd.
|
||||
// If we ever have a moving GC, we need to change this for 2b (as
|
||||
// well as scan itabs to update their itab._type fields).
|
||||
bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot
|
||||
|
||||
case types.TSLICE:
|
||||
// struct { byte *array; uintgo len; uintgo cap; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
|
||||
|
||||
case types.TARRAY:
|
||||
elt := t.Elem()
|
||||
if elt.Width == 0 {
|
||||
// Short-circuit for #20739.
|
||||
break
|
||||
}
|
||||
for i := int64(0); i < t.NumElem(); i++ {
|
||||
SetTypeBits(elt, off, bv)
|
||||
off += elt.Width
|
||||
}
|
||||
|
||||
case types.TSTRUCT:
|
||||
for _, f := range t.Fields().Slice() {
|
||||
SetTypeBits(f.Type, off+f.Offset, bv)
|
||||
}
|
||||
|
||||
default:
|
||||
base.Fatalf("onebitwalktype1: unexpected type, %v", t)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates live pointer value maps for arguments and local variables. The
|
||||
// this argument and the in arguments are always assumed live. The vars
|
||||
// argument is a slice of *Nodes.
|
||||
@ -463,10 +388,10 @@ func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, loc
|
||||
node := vars[i]
|
||||
switch node.Class_ {
|
||||
case ir.PAUTO:
|
||||
SetTypeBits(node.Type(), node.FrameOffset()+lv.stkptrsize, locals)
|
||||
typebits.Set(node.Type(), node.FrameOffset()+lv.stkptrsize, locals)
|
||||
|
||||
case ir.PPARAM, ir.PPARAMOUT:
|
||||
SetTypeBits(node.Type(), node.FrameOffset(), args)
|
||||
typebits.Set(node.Type(), node.FrameOffset(), args)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1309,15 +1234,15 @@ func WriteFuncMap(fn *ir.Func) {
|
||||
off = objw.Uint32(lsym, off, uint32(bv.N))
|
||||
|
||||
if ir.IsMethod(fn) {
|
||||
SetTypeBits(fn.Type().Recvs(), 0, bv)
|
||||
typebits.Set(fn.Type().Recvs(), 0, bv)
|
||||
}
|
||||
if fn.Type().NumParams() > 0 {
|
||||
SetTypeBits(fn.Type().Params(), 0, bv)
|
||||
typebits.Set(fn.Type().Params(), 0, bv)
|
||||
}
|
||||
off = objw.BitVec(lsym, off, bv)
|
||||
|
||||
if fn.Type().NumResults() > 0 {
|
||||
SetTypeBits(fn.Type().Results(), 0, bv)
|
||||
typebits.Set(fn.Type().Results(), 0, bv)
|
||||
off = objw.BitVec(lsym, off, bv)
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,6 @@ package objw
|
||||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/ssa"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/src"
|
||||
@ -173,7 +172,7 @@ func (pp *Progs) Prog(as obj.As) *obj.Prog {
|
||||
p.Pos = pp.Pos
|
||||
if pp.Pos.IsStmt() == src.PosIsStmt {
|
||||
// Clear IsStmt for later Progs at this pos provided that as can be marked as a stmt
|
||||
if ssa.LosesStmtMark(as) {
|
||||
if LosesStmtMark(as) {
|
||||
return p
|
||||
}
|
||||
pp.Pos = pp.Pos.WithNotStmt()
|
||||
@ -216,3 +215,12 @@ func (pp *Progs) SetText(fn *ir.Func) {
|
||||
ptxt.From.Name = obj.NAME_EXTERN
|
||||
ptxt.From.Sym = fn.LSym
|
||||
}
|
||||
|
||||
// LosesStmtMark reports whether a prog with op as loses its statement mark on the way to DWARF.
|
||||
// The attributes from some opcodes are lost in translation.
|
||||
// TODO: this is an artifact of how funcpctab combines information for instructions at a single PC.
|
||||
// Should try to fix it there.
|
||||
func LosesStmtMark(as obj.As) bool {
|
||||
// is_stmt does not work for these; it DOES for ANOP even though that generates no code.
|
||||
return as == obj.APCDATA || as == obj.AFUNCDATA
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ import (
|
||||
"cmd/compile/internal/escape"
|
||||
"cmd/compile/internal/inline"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/liveness"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/typebits"
|
||||
"cmd/compile/internal/typecheck"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/gcprog"
|
||||
@ -1552,7 +1552,7 @@ func fillptrmask(t *types.Type, ptrmask []byte) {
|
||||
}
|
||||
|
||||
vec := bitvec.New(8 * int32(len(ptrmask)))
|
||||
liveness.SetTypeBits(t, 0, vec)
|
||||
typebits.Set(t, 0, vec)
|
||||
|
||||
nptr := types.PtrDataSize(t) / int64(types.PtrSize)
|
||||
for i := int64(0); i < nptr; i++ {
|
||||
|
@ -5,7 +5,6 @@
|
||||
package ssa
|
||||
|
||||
import (
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"sort"
|
||||
@ -23,15 +22,6 @@ func isPoorStatementOp(op Op) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// LosesStmtMark reports whether a prog with op as loses its statement mark on the way to DWARF.
|
||||
// The attributes from some opcodes are lost in translation.
|
||||
// TODO: this is an artifact of how funcpctab combines information for instructions at a single PC.
|
||||
// Should try to fix it there.
|
||||
func LosesStmtMark(as obj.As) bool {
|
||||
// is_stmt does not work for these; it DOES for ANOP even though that generates no code.
|
||||
return as == obj.APCDATA || as == obj.AFUNCDATA
|
||||
}
|
||||
|
||||
// nextGoodStatementIndex returns an index at i or later that is believed
|
||||
// to be a good place to start the statement for b. This decision is
|
||||
// based on v's Op, the possibility of a better later operation, and
|
||||
|
@ -6277,7 +6277,7 @@ type State struct {
|
||||
// Prog appends a new Prog.
|
||||
func (s *State) Prog(as obj.As) *obj.Prog {
|
||||
p := s.pp.Prog(as)
|
||||
if ssa.LosesStmtMark(as) {
|
||||
if objw.LosesStmtMark(as) {
|
||||
return p
|
||||
}
|
||||
// Float a statement start to the beginning of any same-line run.
|
||||
|
87
src/cmd/compile/internal/typebits/typebits.go
Normal file
87
src/cmd/compile/internal/typebits/typebits.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2013 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 typebits
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/bitvec"
|
||||
"cmd/compile/internal/types"
|
||||
)
|
||||
|
||||
// NOTE: The bitmap for a specific type t could be cached in t after
|
||||
// the first run and then simply copied into bv at the correct offset
|
||||
// on future calls with the same type t.
|
||||
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
|
||||
if t.Align > 0 && off&int64(t.Align-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid initial alignment: type %v has alignment %d, but offset is %v", t, t.Align, off)
|
||||
}
|
||||
if !t.HasPointers() {
|
||||
// Note: this case ensures that pointers to go:notinheap types
|
||||
// are not considered pointers by garbage collection and stack copying.
|
||||
return
|
||||
}
|
||||
|
||||
switch t.Kind() {
|
||||
case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) // pointer
|
||||
|
||||
case types.TSTRING:
|
||||
// struct { byte *str; intgo len; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) //pointer in first slot
|
||||
|
||||
case types.TINTER:
|
||||
// struct { Itab *tab; void *data; }
|
||||
// or, when isnilinter(t)==true:
|
||||
// struct { Type *type; void *data; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid alignment, %v", t)
|
||||
}
|
||||
// The first word of an interface is a pointer, but we don't
|
||||
// treat it as such.
|
||||
// 1. If it is a non-empty interface, the pointer points to an itab
|
||||
// which is always in persistentalloc space.
|
||||
// 2. If it is an empty interface, the pointer points to a _type.
|
||||
// a. If it is a compile-time-allocated type, it points into
|
||||
// the read-only data section.
|
||||
// b. If it is a reflect-allocated type, it points into the Go heap.
|
||||
// Reflect is responsible for keeping a reference to
|
||||
// the underlying type so it won't be GCd.
|
||||
// If we ever have a moving GC, we need to change this for 2b (as
|
||||
// well as scan itabs to update their itab._type fields).
|
||||
bv.Set(int32(off/int64(types.PtrSize) + 1)) // pointer in second slot
|
||||
|
||||
case types.TSLICE:
|
||||
// struct { byte *array; uintgo len; uintgo cap; }
|
||||
if off&int64(types.PtrSize-1) != 0 {
|
||||
base.Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
|
||||
}
|
||||
bv.Set(int32(off / int64(types.PtrSize))) // pointer in first slot (BitsPointer)
|
||||
|
||||
case types.TARRAY:
|
||||
elt := t.Elem()
|
||||
if elt.Width == 0 {
|
||||
// Short-circuit for #20739.
|
||||
break
|
||||
}
|
||||
for i := int64(0); i < t.NumElem(); i++ {
|
||||
Set(elt, off, bv)
|
||||
off += elt.Width
|
||||
}
|
||||
|
||||
case types.TSTRUCT:
|
||||
for _, f := range t.Fields().Slice() {
|
||||
Set(f.Type, off+f.Offset, bv)
|
||||
}
|
||||
|
||||
default:
|
||||
base.Fatalf("onebitwalktype1: unexpected type, %v", t)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user