diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-12-08 19:03:09 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-12-08 19:08:08 +0100 |
| commit | c7918378631992d874c99736272ed342d5d77b2c (patch) | |
| tree | 5e67097471fda876d532c270dc4b7f3db0e850c5 /pkg/compiler | |
| parent | 33508266251f6db13ef34741e36b1dce2c9e1b49 (diff) | |
executor: fix handling of big-endian bitfields
Currently we apply big-endian-ness and bitfield-ness in the wrong order in copyin.
This leads to totally bogus result. Fix this.
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/check.go | 3 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors.txt | 1 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 18 |
3 files changed, 17 insertions, 5 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 6ec2fa9e2..cc0535449 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -751,7 +751,8 @@ func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFla comp.error(t.Pos, "%v can't be type alias target", t.Ident) return } - if flags&checkIsResourceBase != 0 && !desc.ResourceBase { + if flags&checkIsResourceBase != 0 && + (desc.CanBeResourceBase == nil || !desc.CanBeResourceBase(comp, t)) { comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident) return } diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt index fed520e6e..55ec40901 100644 --- a/pkg/compiler/testdata/errors.txt +++ b/pkg/compiler/testdata/errors.txt @@ -65,6 +65,7 @@ resource r2[r0]: 2 resource r3[int32:1] ### unexpected ':', only struct fields can be bitfields resource r4[int32[opt]] ### resource base can't be marked as opt resource r5[non_existent] ### unknown type non_existent +resource r6[int64be] ### int64be can't be resource base (int types can) resource r9["foo"] ### unexpected string "foo", expect type foo$7(a r0, a1 r2[opt]) diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 98edc9d74..30ff8884a 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -18,11 +18,12 @@ type typeDesc struct { CantBeOpt bool // can't be marked as opt? NeedBase bool // needs base type when used as field? AllowColon bool // allow colon (int8:2) on fields? - ResourceBase bool // can be resource base type? OptArgs int // number of optional arguments in Args array Args []namedArg // type arguments // CanBeArgRet returns if this type can be syscall argument/return (false if nil). CanBeArgRet func(comp *compiler, t *ast.Type) (bool, bool) + // CanBeResourceBase returns if this type can be a resource base type (false if nil. + CanBeResourceBase func(comp *compiler, t *ast.Type) bool // Check does custom verification of the type (optional, consts are not patched yet). Check func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) // CheckConsts does custom verification of the type (optional, consts are patched). @@ -67,9 +68,16 @@ var typeInt = &typeDesc{ CanBeArgRet: canBeArg, CanBeTypedef: true, AllowColon: true, - ResourceBase: true, OptArgs: 1, Args: []namedArg{{Name: "range", Type: typeArgIntRange}}, + CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { + // Big-endian resources can always be converted to non-big-endian, + // since we will always revert bytes during copyout and during copyin, + // so the result is the same as not reverting at all. + // Big-endian resources are also not implemented and don't have tests. + _, be := comp.parseIntType(t.Ident) + return !be + }, Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) { typeArgBase.Type.Check(comp, t) }, @@ -653,8 +661,10 @@ var typeArgType = &typeArg{} var typeResource = &typeDesc{ // No Names, but getTypeDesc knows how to match it. - CanBeArgRet: canBeArgRet, - ResourceBase: true, + CanBeArgRet: canBeArgRet, + CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { + return true + }, // Gen is assigned below to avoid initialization loop. } |
