diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-07-07 20:07:30 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-07-08 22:52:24 +0200 |
| commit | 306ca0571c5d906ce76df97bd1ea54f4e0e50240 (patch) | |
| tree | a579718e096c53dc5386f4af2fbabb3318eaf1ed /prog/any.go | |
| parent | 93213ec0d3c4522c8844a51b718eb56ce62f395b (diff) | |
prog, pkg/compiler: support fmt type
fmt type allows to convert intergers and resources
to string representation.
Diffstat (limited to 'prog/any.go')
| -rw-r--r-- | prog/any.go | 196 |
1 files changed, 137 insertions, 59 deletions
diff --git a/prog/any.go b/prog/any.go index 92e466280..3f0cb4825 100644 --- a/prog/any.go +++ b/prog/any.go @@ -13,6 +13,9 @@ type anyTypes struct { res16 *ResourceType res32 *ResourceType res64 *ResourceType + resdec *ResourceType + reshex *ResourceType + resoct *ResourceType } // This generates type descriptions for: @@ -27,6 +30,9 @@ type anyTypes struct { // res16 ANYRES16 // res32 ANYRES32 // res64 ANYRES64 +// resdec fmt[dec, ANYRES64] +// reshex fmt[hex, ANYRES64] +// resoct fmt[oct, ANYRES64] // ] [varlen] func initAnyTypes(target *Target) { target.any.union = &UnionType{ @@ -65,7 +71,7 @@ func initAnyTypes(target *Target) { IsVarlen: true, }, } - createResource := func(name, base string, size uint64) *ResourceType { + createResource := func(name, base string, bf BinaryFormat, size uint64) *ResourceType { return &ResourceType{ TypeCommon: TypeCommon{ TypeName: name, @@ -74,6 +80,7 @@ func initAnyTypes(target *Target) { TypeSize: size, IsOptional: true, }, + ArgFormat: bf, Desc: &ResourceDesc{ Name: name, Kind: []string{name}, @@ -89,9 +96,12 @@ func initAnyTypes(target *Target) { }, } } - target.any.res16 = createResource("ANYRES16", "int16", 2) - target.any.res32 = createResource("ANYRES32", "int32", 4) - target.any.res64 = createResource("ANYRES64", "int64", 8) + target.any.res16 = createResource("ANYRES16", "int16", FormatNative, 2) + target.any.res32 = createResource("ANYRES32", "int32", FormatNative, 4) + target.any.res64 = createResource("ANYRES64", "int64", FormatNative, 8) + target.any.resdec = createResource("ANYRESDEC", "int64", FormatStrDec, 20) + target.any.reshex = createResource("ANYRESHEX", "int64", FormatStrHex, 18) + target.any.resoct = createResource("ANYRESOCT", "int64", FormatStrOct, 23) target.any.union.StructDesc = &StructDesc{ TypeCommon: TypeCommon{ TypeName: "ANYUNION", @@ -106,6 +116,9 @@ func initAnyTypes(target *Target) { target.any.res16, target.any.res32, target.any.res64, + target.any.resdec, + target.any.reshex, + target.any.resoct, }, } } @@ -220,28 +233,9 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { var pad uint64 switch arg := a.(type) { case *ConstArg: - if IsPad(arg.Type()) { - pad = arg.Size() - } else { - v := target.squashConst(arg) - elem := target.ensureDataElem(elems) - for i := uint64(0); i < arg.Size(); i++ { - elem.data = append(elem.Data(), byte(v)) - v >>= 8 - } - } + target.squashConst(arg, elems) case *ResultArg: - switch arg.Size() { - case 2: - arg.typ = target.any.res16 - case 4: - arg.typ = target.any.res32 - case 8: - arg.typ = target.any.res64 - default: - panic("bad size") - } - *elems = append(*elems, MakeUnionArg(target.any.union, arg)) + target.squashResult(arg, elems) case *PointerArg: if arg.Res != nil { target.squashPtr(arg, false) @@ -267,40 +261,107 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { elem.data = append(elem.Data(), arg.Data()...) } case *GroupArg: - 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() - } - } - if fieldsSize%typ.AlignAttr != 0 { - pad = typ.AlignAttr - fieldsSize%typ.AlignAttr - } + target.squashGroup(arg, elems) + default: + panic("bad arg kind") + } + if pad != 0 { + elem := target.ensureDataElem(elems) + elem.data = append(elem.Data(), make([]byte, pad)...) + } +} + +func (target *Target) squashConst(arg *ConstArg, elems *[]Arg) { + if IsPad(arg.Type()) { + elem := target.ensureDataElem(elems) + elem.data = append(elem.Data(), make([]byte, arg.Size())...) + return + } + v, bf := target.squashedValue(arg) + var data []byte + switch bf { + case FormatNative: + for i := uint64(0); i < arg.Size(); i++ { + data = append(data, byte(v)) + v >>= 8 + } + case FormatStrDec: + data = []byte(fmt.Sprintf("%020v", v)) + case FormatStrHex: + data = []byte(fmt.Sprintf("0x%016x", v)) + case FormatStrOct: + data = []byte(fmt.Sprintf("%023o", v)) + default: + panic(fmt.Sprintf("unknown binary format: %v", bf)) + } + if uint64(len(data)) != arg.Size() { + panic("squashed value of wrong size") + } + elem := target.ensureDataElem(elems) + elem.data = append(elem.Data(), data...) +} + +func (target *Target) squashResult(arg *ResultArg, elems *[]Arg) { + switch arg.Type().Format() { + case FormatNative, FormatBigEndian: + switch arg.Size() { + case 2: + arg.typ = target.any.res16 + case 4: + arg.typ = target.any.res32 + case 8: + arg.typ = target.any.res64 + default: + panic("bad size") } - var bitfield uint64 + case FormatStrDec: + arg.typ = target.any.resdec + case FormatStrHex: + arg.typ = target.any.reshex + case FormatStrOct: + arg.typ = target.any.resoct + default: + panic("bad") + } + *elems = append(*elems, MakeUnionArg(target.any.union, arg)) +} + +func (target *Target) squashGroup(arg *GroupArg, elems *[]Arg) { + var pad uint64 + if typ, ok := arg.Type().(*StructType); ok && typ.Varlen() && typ.AlignAttr != 0 { + var fieldsSize uint64 for _, fld := range arg.Inner { - // Squash bitfields separately. - if bfLen := fld.Type().BitfieldLength(); bfLen != 0 { - bfOff := fld.Type().BitfieldOffset() - // Note: we can have a ResultArg here as well, - // but it is unsupported at the moment. - v := target.squashConst(fld.(*ConstArg)) - bitfield |= (v & ((1 << bfLen) - 1)) << bfOff - if !fld.Type().BitfieldMiddle() { - elem := target.ensureDataElem(elems) - for i := uint64(0); i < fld.Size(); i++ { - elem.data = append(elem.Data(), byte(bitfield)) - bitfield >>= 8 - } - bitfield = 0 + if !fld.Type().BitfieldMiddle() { + fieldsSize += fld.Size() + } + } + if fieldsSize%typ.AlignAttr != 0 { + pad = typ.AlignAttr - fieldsSize%typ.AlignAttr + } + } + var bitfield uint64 + for _, fld := range arg.Inner { + // Squash bitfields separately. + if bfLen := fld.Type().BitfieldLength(); bfLen != 0 { + bfOff := fld.Type().BitfieldOffset() + // Note: we can have a ResultArg here as well, + // but it is unsupported at the moment. + v, bf := target.squashedValue(fld.(*ConstArg)) + if bf != FormatNative { + panic(fmt.Sprintf("bitfield has bad format %v", bf)) + } + bitfield |= (v & ((1 << bfLen) - 1)) << bfOff + if !fld.Type().BitfieldMiddle() { + elem := target.ensureDataElem(elems) + for i := uint64(0); i < fld.Size(); i++ { + elem.data = append(elem.Data(), byte(bitfield)) + bitfield >>= 8 } - continue + bitfield = 0 } - target.squashPtrImpl(fld, elems) + continue } - default: - panic("bad arg kind") + target.squashPtrImpl(fld, elems) } if pad != 0 { elem := target.ensureDataElem(elems) @@ -308,15 +369,32 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { } } -func (target *Target) squashConst(arg *ConstArg) uint64 { - // Note: we need a constant value, but it depends on pid for proc. - v := arg.ValueForProc(0) +func (target *Target) squashedValue(arg *ConstArg) (uint64, BinaryFormat) { + bf := arg.Type().Format() if _, ok := arg.Type().(*CsumType); ok { // We can't compute value for the checksum here, // but at least leave something recognizable by hints code. - v = 0xabcdef1234567890 + // TODO: hints code won't recognize this, because it won't find + // the const in any arg. We either need to put this const as + // actual csum arg value, or special case it in hints. + return 0xabcdef1234567890, FormatNative + } + // Note: we need a constant value, but it depends on pid for proc. + v, _ := arg.Value() + if bf == FormatBigEndian { + bf = FormatNative + switch arg.Size() { + case 2: + v = uint64(swap16(uint16(v))) + case 4: + v = uint64(swap32(uint32(v))) + case 8: + v = swap64(v) + default: + panic(fmt.Sprintf("bad const size %v", arg.Size())) + } } - return v + return v, bf } func (target *Target) ensureDataElem(elems *[]Arg) *DataArg { |
