aboutsummaryrefslogtreecommitdiffstats
path: root/prog/prog.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-04-26 14:14:14 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-05-01 13:31:17 +0200
commite54e9781a4e043b3140b0c908ba4f4e469fd317e (patch)
tree16e6387d78a8577c5f3d9fb8d05a51752da6338e /prog/prog.go
parent3f4dbb2f6fff9479d6c250e224bc3cb7f5cd66ed (diff)
prog: remove Dir from Type
Having Dir is Type is handy, but forces us to duplicate lots of types. E.g. if a struct is referenced as both in and out, then we need to have 2 copies and 2 copies of structs/types it includes. If also prevents us from having the struct type as struct identity (because we can have up to 3 of them). Revert to the old way we used to do it: propagate Dir as we walk syscall arguments. This moves lots of dir passing from pkg/compiler to prog package. Now Arg contains the dir, so once we build the tree, we can use dirs as before. Reduces size of sys/linux/gen/amd64.go from 6058336 to 5661150 (-6.6%). Update #1580
Diffstat (limited to 'prog/prog.go')
-rw-r--r--prog/prog.go60
1 files changed, 33 insertions, 27 deletions
diff --git a/prog/prog.go b/prog/prog.go
index 1600c0a28..017a0dbbb 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -22,6 +22,7 @@ type Call struct {
type Arg interface {
Type() Type
+ Dir() Dir
Size() uint64
validate(ctx *validCtx) error
@@ -30,20 +31,25 @@ type Arg interface {
type ArgCommon struct {
typ Type
+ dir Dir
}
func (arg *ArgCommon) Type() Type {
return arg.typ
}
+func (arg *ArgCommon) Dir() Dir {
+ return arg.dir
+}
+
// Used for ConstType, IntType, FlagsType, LenType, ProcType and CsumType.
type ConstArg struct {
ArgCommon
Val uint64
}
-func MakeConstArg(t Type, v uint64) *ConstArg {
- return &ConstArg{ArgCommon: ArgCommon{typ: t}, Val: v}
+func MakeConstArg(t Type, dir Dir, v uint64) *ConstArg {
+ return &ConstArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Val: v}
}
func (arg *ConstArg) Size() uint64 {
@@ -84,34 +90,37 @@ type PointerArg struct {
Res Arg // pointee (nil for vma)
}
-func MakePointerArg(t Type, addr uint64, data Arg) *PointerArg {
+func MakePointerArg(t Type, dir Dir, addr uint64, data Arg) *PointerArg {
if data == nil {
panic("nil pointer data arg")
}
return &PointerArg{
- ArgCommon: ArgCommon{typ: t},
+ ArgCommon: ArgCommon{typ: t, dir: DirIn}, // pointers are always in
Address: addr,
Res: data,
}
}
-func MakeVmaPointerArg(t Type, addr, size uint64) *PointerArg {
+func MakeVmaPointerArg(t Type, dir Dir, addr, size uint64) *PointerArg {
if addr%1024 != 0 {
panic("unaligned vma address")
}
return &PointerArg{
- ArgCommon: ArgCommon{typ: t},
+ ArgCommon: ArgCommon{typ: t, dir: dir},
Address: addr,
VmaSize: size,
}
}
-func MakeSpecialPointerArg(t Type, index uint64) *PointerArg {
+func MakeSpecialPointerArg(t Type, dir Dir, index uint64) *PointerArg {
if index >= maxSpecialPointers {
panic("bad special pointer index")
}
+ if _, ok := t.(*PtrType); ok {
+ dir = DirIn // pointers are always in
+ }
return &PointerArg{
- ArgCommon: ArgCommon{typ: t},
+ ArgCommon: ArgCommon{typ: t, dir: dir},
Address: -index,
}
}
@@ -138,18 +147,18 @@ type DataArg struct {
size uint64 // for out Args
}
-func MakeDataArg(t Type, data []byte) *DataArg {
- if t.Dir() == DirOut {
+func MakeDataArg(t Type, dir Dir, data []byte) *DataArg {
+ if dir == DirOut {
panic("non-empty output data arg")
}
- return &DataArg{ArgCommon: ArgCommon{typ: t}, data: append([]byte{}, data...)}
+ return &DataArg{ArgCommon: ArgCommon{typ: t, dir: dir}, data: append([]byte{}, data...)}
}
-func MakeOutDataArg(t Type, size uint64) *DataArg {
- if t.Dir() != DirOut {
+func MakeOutDataArg(t Type, dir Dir, size uint64) *DataArg {
+ if dir != DirOut {
panic("empty input data arg")
}
- return &DataArg{ArgCommon: ArgCommon{typ: t}, size: size}
+ return &DataArg{ArgCommon: ArgCommon{typ: t, dir: dir}, size: size}
}
func (arg *DataArg) Size() uint64 {
@@ -160,14 +169,14 @@ func (arg *DataArg) Size() uint64 {
}
func (arg *DataArg) Data() []byte {
- if arg.Type().Dir() == DirOut {
+ if arg.Dir() == DirOut {
panic("getting data of output data arg")
}
return arg.data
}
func (arg *DataArg) SetData(data []byte) {
- if arg.Type().Dir() == DirOut {
+ if arg.Dir() == DirOut {
panic("setting data of output data arg")
}
arg.data = append([]byte{}, data...)
@@ -180,8 +189,8 @@ type GroupArg struct {
Inner []Arg
}
-func MakeGroupArg(t Type, inner []Arg) *GroupArg {
- return &GroupArg{ArgCommon: ArgCommon{typ: t}, Inner: inner}
+func MakeGroupArg(t Type, dir Dir, inner []Arg) *GroupArg {
+ return &GroupArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Inner: inner}
}
func (arg *GroupArg) Size() uint64 {
@@ -227,8 +236,8 @@ type UnionArg struct {
Option Arg
}
-func MakeUnionArg(t Type, opt Arg) *UnionArg {
- return &UnionArg{ArgCommon: ArgCommon{typ: t}, Option: opt}
+func MakeUnionArg(t Type, dir Dir, opt Arg) *UnionArg {
+ return &UnionArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Option: opt}
}
func (arg *UnionArg) Size() uint64 {
@@ -250,8 +259,8 @@ type ResultArg struct {
uses map[*ResultArg]bool // ArgResult args that use this arg
}
-func MakeResultArg(t Type, r *ResultArg, v uint64) *ResultArg {
- arg := &ResultArg{ArgCommon: ArgCommon{typ: t}, Res: r, Val: v}
+func MakeResultArg(t Type, dir Dir, r *ResultArg, v uint64) *ResultArg {
+ arg := &ResultArg{ArgCommon: ArgCommon{typ: t, dir: dir}, Res: r, Val: v}
if r == nil {
return arg
}
@@ -266,10 +275,7 @@ func MakeReturnArg(t Type) *ResultArg {
if t == nil {
return nil
}
- if t.Dir() != DirOut {
- panic("return arg is not out")
- }
- return &ResultArg{ArgCommon: ArgCommon{typ: t}}
+ return &ResultArg{ArgCommon: ArgCommon{typ: t, dir: DirOut}}
}
func (arg *ResultArg) Size() uint64 {
@@ -369,7 +375,7 @@ func removeArg(arg0 Arg) {
delete(uses, a)
}
for arg1 := range a.uses {
- arg2 := arg1.Type().DefaultArg().(*ResultArg)
+ arg2 := arg1.Type().DefaultArg(arg1.Dir()).(*ResultArg)
replaceResultArg(arg1, arg2)
}
})