From 20c6855484620eda011e4e4002c6f7f272a878c4 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 18 Dec 2019 18:30:39 +0100 Subject: prog: refactor bitfields representation All callers of BitfieldMiddle just want static size (0 for middle). Make it so: Size for middle bitfields just returns 0. Removes lots of if's. Introduce Type.UnitSize, which now holds the underlying type for bitfields. This will be needed to fix #1542 b/c even if UnitSize=4 for last bitfield Size can be anywhere from 0 to 4 (not necessary equal to UnitSize due to overlapping). --- prog/analysis.go | 8 +++----- prog/any.go | 16 ++++++++-------- prog/encodingexec.go | 4 ++-- prog/prog.go | 4 +--- prog/size.go | 4 +--- prog/types.go | 38 +++++++++++++++++++++++++++----------- 6 files changed, 42 insertions(+), 32 deletions(-) (limited to 'prog') diff --git a/prog/analysis.go b/prog/analysis.go index f8330ed1c..519d5ba84 100644 --- a/prog/analysis.go +++ b/prog/analysis.go @@ -134,11 +134,9 @@ func foreachArgImpl(arg Arg, ctx ArgCtx, f func(Arg, *ArgCtx)) { var totalSize uint64 for _, arg1 := range a.Inner { foreachArgImpl(arg1, ctx, f) - if !arg1.Type().BitfieldMiddle() { - size := arg1.Size() - ctx.Offset += size - totalSize += size - } + size := arg1.Size() + ctx.Offset += size + totalSize += size } claimedSize := a.Size() varlen := a.Type().Varlen() diff --git a/prog/any.go b/prog/any.go index 3f0cb4825..582f00195 100644 --- a/prog/any.go +++ b/prog/any.go @@ -331,9 +331,7 @@ func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) { if typ, ok := arg.Type().(*StructType); ok && typ.Varlen() && typ.AlignAttr != 0 { var fieldsSize uint64 for _, fld := range arg.Inner { - if !fld.Type().BitfieldMiddle() { - fieldsSize += fld.Size() - } + fieldsSize += fld.Size() } if fieldsSize%typ.AlignAttr != 0 { pad = typ.AlignAttr - fieldsSize%typ.AlignAttr @@ -342,7 +340,8 @@ func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) { var bitfield uint64 for _, fld := range arg.Inner { // Squash bitfields separately. - if bfLen := fld.Type().BitfieldLength(); bfLen != 0 { + if fld.Type().IsBitfield() { + bfLen := fld.Type().BitfieldLength() bfOff := fld.Type().BitfieldOffset() // Note: we can have a ResultArg here as well, // but it is unsupported at the moment. @@ -351,7 +350,7 @@ func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) { panic(fmt.Sprintf("bitfield has bad format %v", bf)) } bitfield |= (v & ((1 << bfLen) - 1)) << bfOff - if !fld.Type().BitfieldMiddle() { + if fld.Size() != 0 { elem := target.ensureDataElem(elems) for i := uint64(0); i < fld.Size(); i++ { elem.data = append(elem.Data(), byte(bitfield)) @@ -370,8 +369,9 @@ func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) { } func (target *Target) squashedValue(arg *ConstArg) (uint64, BinaryFormat) { - bf := arg.Type().Format() - if _, ok := arg.Type().(*CsumType); ok { + typ := arg.Type() + bf := typ.Format() + if _, ok := typ.(*CsumType); ok { // We can't compute value for the checksum here, // but at least leave something recognizable by hints code. // TODO: hints code won't recognize this, because it won't find @@ -383,7 +383,7 @@ func (target *Target) squashedValue(arg *ConstArg) (uint64, BinaryFormat) { v, _ := arg.Value() if bf == FormatBigEndian { bf = FormatNative - switch arg.Size() { + switch typ.UnitSize() { case 2: v = uint64(swap16(uint16(v))) case 4: diff --git a/prog/encodingexec.go b/prog/encodingexec.go index 2d2f02e57..2e69f2116 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -133,7 +133,7 @@ func (w *execContext) writeCopyin(c *Call) { return } typ := arg.Type() - if typ.Dir() == DirOut || IsPad(typ) || arg.Size() == 0 { + if typ.Dir() == DirOut || IsPad(typ) || (arg.Size() == 0 && !typ.IsBitfield()) { return } w.write(execInstrCopyin) @@ -236,7 +236,7 @@ func (w *execContext) writeArg(arg Arg) { case *ConstArg: val, pidStride := a.Value() typ := a.Type() - w.writeConstArg(a.Size(), val, typ.BitfieldOffset(), typ.BitfieldLength(), pidStride, typ.Format()) + w.writeConstArg(typ.UnitSize(), val, typ.BitfieldOffset(), typ.BitfieldLength(), pidStride, typ.Format()) case *ResultArg: if a.Res == nil { w.writeConstArg(a.Size(), a.Val, 0, 0, 0, a.Type().Format()) diff --git a/prog/prog.go b/prog/prog.go index 83e5991d8..575f0da9b 100644 --- a/prog/prog.go +++ b/prog/prog.go @@ -193,9 +193,7 @@ func (arg *GroupArg) Size() uint64 { case *StructType: var size uint64 for _, fld := range arg.Inner { - if !fld.Type().BitfieldMiddle() { - size += fld.Size() - } + size += fld.Size() } if typ.AlignAttr != 0 && size%typ.AlignAttr != 0 { size += typ.AlignAttr - size%typ.AlignAttr diff --git a/prog/size.go b/prog/size.go index 0f3435bbd..2ebf9fc29 100644 --- a/prog/size.go +++ b/prog/size.go @@ -45,9 +45,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A var offset uint64 for _, buf := range args { if elem != buf.Type().FieldName() { - if !buf.Type().BitfieldMiddle() { - offset += buf.Size() - } + offset += buf.Size() continue } buf = InnerArg(buf) diff --git a/prog/types.go b/prog/types.go index 2eec68a4d..6b2d37e07 100644 --- a/prog/types.go +++ b/prog/types.go @@ -60,7 +60,11 @@ type Type interface { Format() BinaryFormat BitfieldOffset() uint64 BitfieldLength() uint64 - BitfieldMiddle() bool // returns true for all but last bitfield in a group + IsBitfield() bool + // For most of the types UnitSize is equal to Size. + // These are different only for all but last bitfield in the group, + // where Size == 0 and UnitSize equals to the underlying bitfield type size. + UnitSize() uint64 DefaultArg() Arg isDefaultArg(arg Arg) bool @@ -78,9 +82,10 @@ func IsPad(t Type) bool { } type TypeCommon struct { - TypeName string - FldName string // for struct fields and named args - TypeSize uint64 // static size of the type, or 0 for variable size types + TypeName string + FldName string // for struct fields and named args + // Static size of the type, or 0 for variable size types and all but last bitfields in the group. + TypeSize uint64 ArgDir Dir IsOptional bool IsVarlen bool @@ -125,7 +130,11 @@ func (t *TypeCommon) BitfieldLength() uint64 { return 0 } -func (t *TypeCommon) BitfieldMiddle() bool { +func (t *TypeCommon) UnitSize() uint64 { + return t.Size() +} + +func (t *TypeCommon) IsBitfield() bool { return false } @@ -180,10 +189,10 @@ func (t *ResourceType) Format() BinaryFormat { type IntTypeCommon struct { TypeCommon - ArgFormat BinaryFormat - BitfieldOff uint64 - BitfieldLen uint64 - BitfieldMdl bool + ArgFormat BinaryFormat + BitfieldOff uint64 + BitfieldLen uint64 + BitfieldUnit uint64 } func (t *IntTypeCommon) String() string { @@ -215,8 +224,15 @@ func (t *IntTypeCommon) BitfieldLength() uint64 { return t.BitfieldLen } -func (t *IntTypeCommon) BitfieldMiddle() bool { - return t.BitfieldMdl +func (t *IntTypeCommon) UnitSize() uint64 { + if t.BitfieldLen != 0 { + return t.BitfieldUnit + } + return t.Size() +} + +func (t *IntTypeCommon) IsBitfield() bool { + return t.BitfieldLen != 0 } type ConstType struct { -- cgit mrf-deployment