aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-12-18 18:30:39 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-12-19 19:32:45 +0100
commit20c6855484620eda011e4e4002c6f7f272a878c4 (patch)
treee8143cbd4d72702e02a91cd68883c7117681954b /prog
parentaf9047c60a3db32d5e43c29321f8f531db051a63 (diff)
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).
Diffstat (limited to 'prog')
-rw-r--r--prog/analysis.go8
-rw-r--r--prog/any.go16
-rw-r--r--prog/encodingexec.go4
-rw-r--r--prog/prog.go4
-rw-r--r--prog/size.go4
-rw-r--r--prog/types.go38
6 files changed, 42 insertions, 32 deletions
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 {