aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Konovalov <andreyknvl@google.com>2016-10-11 21:01:06 +0200
committerAndrey Konovalov <andreyknvl@google.com>2016-10-13 15:38:53 +0200
commit7686d19affbd3f592a64517679df85b9d49f4628 (patch)
tree624a97c2ea4c7e0ff01b13caef53c293085d0583
parentb3f098b002f4b68f0e3d38717bc610da268d0d18 (diff)
Add big-endian ints
-rw-r--r--prog/encodingexec.go2
-rw-r--r--prog/prog.go33
-rw-r--r--sys/decl.go25
-rw-r--r--sysgen/sysgen.go99
4 files changed, 107 insertions, 52 deletions
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index 6ba68b37e..239ef3514 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -148,7 +148,7 @@ func (w *execContext) writeArg(arg *Arg) {
case ArgConst:
w.write(ExecArgConst)
w.write(arg.Size(arg.Type))
- w.write(arg.Val)
+ w.write(arg.Value(arg.Type))
case ArgResult:
w.write(ExecArgResult)
w.write(arg.Size(arg.Type))
diff --git a/prog/prog.go b/prog/prog.go
index e0a3ab235..9953f3ef0 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -79,6 +79,39 @@ func (a *Arg) InnerArg(typ sys.Type) *Arg {
}
}
+func encodeValue(value, size uintptr, bigEndian bool) uintptr {
+ if !bigEndian {
+ return value
+ }
+ switch size {
+ case 2:
+ return uintptr(swap16(uint16(value)))
+ case 4:
+ return uintptr(swap32(uint32(value)))
+ case 8:
+ return uintptr(swap64(uint64(value)))
+ default:
+ panic(fmt.Sprintf("bad size %v for value %v", size, value))
+ }
+}
+
+// Returns value taking endianness into consideration.
+func (a *Arg) Value(typ sys.Type) uintptr {
+ switch t := typ.(type) {
+ case sys.IntType:
+ return encodeValue(a.Val, t.Size(), t.BigEndian)
+ case sys.ConstType:
+ return encodeValue(a.Val, t.Size(), t.BigEndian)
+ case sys.FlagsType:
+ return encodeValue(a.Val, t.Size(), t.BigEndian)
+ case sys.LenType:
+ return encodeValue(a.Val, t.Size(), t.BigEndian)
+ case sys.FileoffType:
+ return encodeValue(a.Val, t.Size(), t.BigEndian)
+ }
+ return a.Val
+}
+
func (a *Arg) Size(typ sys.Type) uintptr {
switch typ1 := typ.(type) {
case sys.IntType, sys.LenType, sys.FlagsType, sys.ConstType, sys.StrConstType,
diff --git a/sys/decl.go b/sys/decl.go
index ba38399ba..da121b9e7 100644
--- a/sys/decl.go
+++ b/sys/decl.go
@@ -90,8 +90,9 @@ func (t ResourceType) InnerType() Type {
type FileoffType struct {
TypeCommon
- TypeSize uintptr
- File string
+ TypeSize uintptr
+ BigEndian bool
+ File string
}
func (t FileoffType) Size() uintptr {
@@ -167,9 +168,10 @@ func (t VmaType) InnerType() Type {
type LenType struct {
TypeCommon
- TypeSize uintptr
- ByteSize bool // want size in bytes instead of array size
- Buf string
+ TypeSize uintptr
+ BigEndian bool
+ ByteSize bool // want size in bytes instead of array size
+ Buf string
}
func (t LenType) Size() uintptr {
@@ -186,8 +188,9 @@ func (t LenType) InnerType() Type {
type FlagsType struct {
TypeCommon
- TypeSize uintptr
- Vals []uintptr
+ TypeSize uintptr
+ BigEndian bool
+ Vals []uintptr
}
func (t FlagsType) Size() uintptr {
@@ -204,9 +207,10 @@ func (t FlagsType) InnerType() Type {
type ConstType struct {
TypeCommon
- TypeSize uintptr
- Val uintptr
- IsPad bool
+ TypeSize uintptr
+ BigEndian bool
+ Val uintptr
+ IsPad bool
}
func (t ConstType) Size() uintptr {
@@ -252,6 +256,7 @@ const (
type IntType struct {
TypeCommon
TypeSize uintptr
+ BigEndian bool
Kind IntKind
RangeBegin int64
RangeEnd int64
diff --git a/sysgen/sysgen.go b/sysgen/sysgen.go
index 28507db88..d197b774b 100644
--- a/sysgen/sysgen.go
+++ b/sysgen/sysgen.go
@@ -23,6 +23,10 @@ var (
flagV = flag.Int("v", 0, "verbosity")
)
+const (
+ ptrSize = 8
+)
+
func main() {
flag.Parse()
@@ -325,6 +329,27 @@ func generateStructs(desc *Description, consts map[string]uint64, out io.Writer)
fmt.Fprintf(out, "}\n")
}
+func parseRange(buffer string, consts map[string]uint64) (string, string) {
+ lookupConst := func(name string) string {
+ if v, ok := consts[name]; ok {
+ return fmt.Sprint(v)
+ }
+ return name
+ }
+
+ parts := strings.Split(buffer, ":")
+ switch len(parts) {
+ case 1:
+ v := lookupConst(buffer)
+ return v, v
+ case 2:
+ return lookupConst(parts[0]), lookupConst(parts[1])
+ default:
+ failf("bad range: %v", buffer)
+ return "", ""
+ }
+}
+
func generateArg(
parent, name, typ string,
a []string,
@@ -350,18 +375,19 @@ func generateArg(
switch typ {
case "fileoff":
canBeArg = true
- var size uint64
+ size := uint64(ptrSize)
+ bigEndian := false
if isField {
if want := 2; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
- size = typeToSize(a[1])
+ size, bigEndian = decodeIntType(a[1])
} else {
if want := 1; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
}
- fmt.Fprintf(out, "FileoffType{%v, File: \"%v\", TypeSize: %v}", common(), a[0], size)
+ fmt.Fprintf(out, "FileoffType{%v, File: \"%v\", TypeSize: %v, BigEndian: %v}", common(), a[0], size, bigEndian)
case "buffer":
canBeArg = true
if want := 1; len(a) != want {
@@ -409,26 +435,28 @@ func generateArg(
fmt.Fprintf(out, "VmaType{%v}", common())
case "len", "bytesize":
canBeArg = true
- var size uint64
+ size := uint64(ptrSize)
+ bigEndian := false
if isField {
if want := 2; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
- size = typeToSize(a[1])
+ size, bigEndian = decodeIntType(a[1])
} else {
if want := 1; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
}
- fmt.Fprintf(out, "LenType{%v, Buf: \"%v\", TypeSize: %v, ByteSize: %v}", common(), a[0], size, typ == "bytesize")
+ fmt.Fprintf(out, "LenType{%v, Buf: \"%v\", TypeSize: %v, BigEndian: %v, ByteSize: %v}", common(), a[0], size, bigEndian, typ == "bytesize")
case "flags":
canBeArg = true
- var size uint64
+ size := uint64(ptrSize)
+ bigEndian := false
if isField {
if want := 2; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
- size = typeToSize(a[1])
+ size, bigEndian = decodeIntType(a[1])
} else {
if want := 1; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
@@ -439,18 +467,19 @@ func generateArg(
failf("unknown flag %v", a[0])
}
if len(vals) == 0 {
- fmt.Fprintf(out, "IntType{%v, TypeSize: %v}", common(), size)
+ fmt.Fprintf(out, "IntType{%v, TypeSize: %v, BigEndian: %v}", common(), size, bigEndian)
} else {
- fmt.Fprintf(out, "FlagsType{%v, TypeSize: %v, Vals: []uintptr{%v}}", common(), size, strings.Join(vals, ","))
+ fmt.Fprintf(out, "FlagsType{%v, TypeSize: %v, BigEndian: %v, Vals: []uintptr{%v}}", common(), size, bigEndian, strings.Join(vals, ","))
}
case "const":
canBeArg = true
- var size uint64
+ size := uint64(ptrSize)
+ bigEndian := false
if isField {
if want := 2; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
- size = typeToSize(a[1])
+ size, bigEndian = decodeIntType(a[1])
} else {
if want := 1; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
@@ -465,27 +494,22 @@ func generateArg(
val = "0"
skipSyscall(fmt.Sprintf("missing const %v", a[0]))
}
- fmt.Fprintf(out, "ConstType{%v, TypeSize: %v, Val: uintptr(%v)}", common(), size, val)
+ fmt.Fprintf(out, "ConstType{%v, TypeSize: %v, BigEndian: %v, Val: uintptr(%v)}", common(), size, bigEndian, val)
case "strconst":
canBeArg = true
if want := 1; len(a) != want {
failf("wrong number of arguments for %v arg %v, want %v, got %v", typ, name, want, len(a))
}
fmt.Fprintf(out, "PtrType{%v, Dir: %v, Type: StrConstType{%v, Val: \"%v\"}}", common(), fmtDir("in"), common(), a[0]+"\\x00")
- case "int8", "int16", "int32", "int64", "intptr":
+ case "int8", "int16", "int32", "int64", "intptr", "int16be", "int32be", "int64be", "intptrbe":
canBeArg = true
+ size, bigEndian := decodeIntType(typ)
switch len(a) {
case 0:
- fmt.Fprintf(out, "IntType{%v, TypeSize: %v}", common(), typeToSize(typ))
+ fmt.Fprintf(out, "IntType{%v, TypeSize: %v, BigEndian: %v}", common(), size, bigEndian)
case 1:
- var lo, hi int64
- if _, err := fmt.Sscanf(a[0], "%d:%d", &lo, &hi); err != nil {
- failf("failed to parse int range: %v (%v)", a[0], err)
- }
- if lo >= hi {
- failf("bad int range: %v", a[0])
- }
- fmt.Fprintf(out, "IntType{%v, TypeSize: %v, Kind: IntRange, RangeBegin: %v, RangeEnd: %v}", common(), typeToSize(typ), lo, hi)
+ begin, end := parseRange(a[0], consts)
+ fmt.Fprintf(out, "IntType{%v, TypeSize: %v, BigEndian: %v, Kind: IntRange, RangeBegin: %v, RangeEnd: %v}", common(), size, bigEndian, begin, end)
default:
failf("wrong number of arguments for %v arg %v, want 0 or 1, got %v", typ, name, len(a))
}
@@ -524,23 +548,11 @@ func generateArg(
fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRandLen}", common(), generateType(a[0], desc, consts))
}
} else {
- var begin, end uintptr
- var beginStr, endStr string
- if _, err := fmt.Sscanf(a[1], "%d:%d", &begin, &end); err == nil {
- beginStr = fmt.Sprint(begin)
- endStr = fmt.Sprint(end)
- } else {
- sz := a[1]
- if v, ok := consts[sz]; ok {
- sz = fmt.Sprint(v)
- }
- beginStr = sz
- endStr = sz
- }
+ begin, end := parseRange(a[1], consts)
if a[0] == "int8" {
- fmt.Fprintf(out, "BufferType{%v, Kind: BufferBlobRange, RangeBegin: %v, RangeEnd: %v}", common(), beginStr, endStr)
+ fmt.Fprintf(out, "BufferType{%v, Kind: BufferBlobRange, RangeBegin: %v, RangeEnd: %v}", common(), begin, end)
} else {
- fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), beginStr, endStr)
+ fmt.Fprintf(out, "ArrayType{%v, Type: %v, Kind: ArrayRangeLen, RangeBegin: %v, RangeEnd: %v}", common(), generateType(a[0], desc, consts), begin, end)
}
}
case "ptr":
@@ -600,17 +612,22 @@ func fmtDir(s string) string {
}
}
-func typeToSize(typ string) uint64 {
+func decodeIntType(typ string) (uint64, bool) {
+ bigEndian := false
+ if strings.HasSuffix(typ, "be") {
+ bigEndian = true
+ typ = typ[:len(typ)-2]
+ }
switch typ {
case "int8", "int16", "int32", "int64", "intptr":
default:
failf("unknown type %v", typ)
}
- sz := int64(64) // TODO: assume that pointer is 8 bytes for now
+ sz := int64(ptrSize * 8)
if typ != "intptr" {
sz, _ = strconv.ParseInt(typ[3:], 10, 64)
}
- return uint64(sz / 8)
+ return uint64(sz / 8), bigEndian
}
func isIdentifier(s string) bool {