aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-02-18 14:12:50 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-02-19 21:48:20 +0100
commit4eef71bb2d6b9b0dd4ef30909f09b7eb84aac79d (patch)
tree48e180afda170834baaa1be824ec21e25358f468 /prog
parent85d1218f4108e0fe793f63e57e2edadd5da5764f (diff)
prog: merge foreachSubargOffset into foreachArgImpl
Diffstat (limited to 'prog')
-rw-r--r--prog/analysis.go43
-rw-r--r--prog/encodingexec.go43
2 files changed, 31 insertions, 55 deletions
diff --git a/prog/analysis.go b/prog/analysis.go
index 0c4102a47..2d691934a 100644
--- a/prog/analysis.go
+++ b/prog/analysis.go
@@ -112,12 +112,23 @@ func foreachArgImpl(arg Arg, ctx ArgCtx, f func(Arg, *ArgCtx)) {
if _, ok := a.Type().(*StructType); ok {
ctx.Parent = &a.Inner
}
+ var totalSize uint64
for _, arg1 := range a.Inner {
foreachArgImpl(arg1, ctx, f)
+ if !arg1.Type().BitfieldMiddle() {
+ size := arg1.Size()
+ ctx.Offset += size
+ totalSize += size
+ }
+ }
+ if totalSize > a.Size() {
+ panic(fmt.Sprintf("bad group arg size %v, should be <= %v for %+v",
+ totalSize, a.Size(), a))
}
case *PointerArg:
if a.Res != nil {
ctx.Base = a
+ ctx.Offset = 0
foreachArgImpl(a.Res, ctx, f)
}
case *UnionArg:
@@ -125,38 +136,6 @@ func foreachArgImpl(arg Arg, ctx ArgCtx, f func(Arg, *ArgCtx)) {
}
}
-func foreachSubargOffset(arg Arg, f func(arg Arg, offset uint64)) {
- var rec func(Arg, uint64) uint64
- rec = func(arg1 Arg, offset uint64) uint64 {
- switch a := arg1.(type) {
- case *GroupArg:
- f(arg1, offset)
- var totalSize uint64
- for _, arg2 := range a.Inner {
- size := rec(arg2, offset)
- if !arg2.Type().BitfieldMiddle() {
- offset += size
- totalSize += size
- }
- }
- if totalSize > arg1.Size() {
- panic(fmt.Sprintf("bad group arg size %v, should be <= %v for %+v", totalSize, arg1.Size(), arg1))
- }
- case *UnionArg:
- f(arg1, offset)
- size := rec(a.Option, offset)
- offset += size
- if size > arg1.Size() {
- panic(fmt.Sprintf("bad union arg size %v, should be <= %v for arg %+v with type %+v", size, arg1.Size(), arg1, arg1.Type()))
- }
- default:
- f(arg1, offset)
- }
- return arg1.Size()
- }
- rec(arg, 0)
-}
-
// TODO(dvyukov): combine RequiresBitmasks and RequiresChecksums into a single function
// to not walk the tree twice. They are always used together anyway.
func RequiresBitmasks(p *Prog) bool {
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index d0c8f6c80..b5573f60f 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -86,30 +86,27 @@ func (p *Prog) SerializeForExec(buffer []byte) (int, error) {
}
// Calculate arg offsets within structs.
// Generate copyin instructions that fill in data into pointer arguments.
- ForeachArg(c, func(arg Arg, _ *ArgCtx) {
- if a, ok := arg.(*PointerArg); ok && a.Res != nil {
- foreachSubargOffset(a.Res, func(arg1 Arg, offset uint64) {
- addr := p.Target.PhysicalAddr(arg) + offset
- if isUsed(arg1) || csumUses[arg1] {
- w.args[arg1] = argInfo{Addr: addr}
- }
- if _, ok := arg1.(*GroupArg); ok {
- return
- }
- if _, ok := arg1.(*UnionArg); ok {
- return
- }
- if a1, ok := arg1.(*DataArg); ok &&
- (a1.Type().Dir() == DirOut || len(a1.Data()) == 0) {
- return
- }
- if !IsPad(arg1.Type()) && arg1.Type().Dir() != DirOut {
- w.write(execInstrCopyin)
- w.write(addr)
- w.writeArg(arg1)
- }
- })
+ ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
+ if ctx.Base == nil {
+ return
+ }
+ addr := p.Target.PhysicalAddr(ctx.Base) + ctx.Offset
+ if isUsed(arg) || csumUses[arg] {
+ w.args[arg] = argInfo{Addr: addr}
}
+ if _, ok := arg.(*GroupArg); ok {
+ return
+ }
+ if _, ok := arg.(*UnionArg); ok {
+ return
+ }
+ typ := arg.Type()
+ if typ.Dir() == DirOut || IsPad(typ) || arg.Size() == 0 {
+ return
+ }
+ w.write(execInstrCopyin)
+ w.write(addr)
+ w.writeArg(arg)
})
// Generate checksum calculation instructions starting from the last one,
// since checksum values can depend on values of the latter ones