diff options
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/check.go | 3 | ||||
| -rw-r--r-- | pkg/compiler/consts.go | 12 | ||||
| -rw-r--r-- | pkg/compiler/testdata/all.txt | 2 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors.txt | 10 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 44 |
5 files changed, 54 insertions, 17 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 2a14b9cc0..2369daae5 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -634,7 +634,8 @@ func (comp *compiler) collectUsedType(structs, flags, strflags map[string]bool, } return } - if desc == typeFlags { + if desc == typeFlags || + (desc == typeInt && len(t.Args) > 0 && t.Args[0].Ident != "") { flags[t.Args[0].Ident] = true return } diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go index e9f7227e7..6fe3e7bc0 100644 --- a/pkg/compiler/consts.go +++ b/pkg/compiler/consts.go @@ -123,6 +123,13 @@ func (comp *compiler) addConst(infos map[string]*constInfo, pos ast.Pos, name st if _, builtin := comp.builtinConsts[name]; builtin { return } + // In case of intN[identA], identA may refer to a constant or to a set of + // flags. To avoid marking all flags as constants, we must check here + // whether identA refers to a flag. We have a check in the compiler to + // ensure an identifier can never refer to both a constant and flags. + if _, isFlag := comp.intFlags[name]; isFlag { + return + } info := getConstInfo(infos, pos) info.consts[name] = &Const{ Pos: pos, @@ -297,6 +304,11 @@ func (comp *compiler) patchConst(val *uint64, id *string, consts map[string]uint *val = v return true } + // This check is necessary because in intN[identA], identA may be a + // constant or a set of flags. + if _, isFlag := comp.intFlags[*id]; isFlag { + return true + } if missing != nil && *missing == "" { *missing = *id } diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt index 6fd9f7cc6..1b3873bf5 100644 --- a/pkg/compiler/testdata/all.txt +++ b/pkg/compiler/testdata/all.txt @@ -20,6 +20,7 @@ foo_12(a int64[0:-1, 0x1000]) foo_13() (disabled) foo_14() r0 (timeout[100]) foo_15() r0 (disabled, timeout[C1], prog_timeout[C2]) +foo_16(a int32[int_flags]) resource r0[intptr] @@ -180,6 +181,7 @@ bitfield0 { f3 int16:8[-127:0] f4 int16:8[0:255] f5 int64:64[-1:1] + f6 int32:4[int_flags] } foo_bitfield0(a ptr[in, bitfield0]) diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt index 87b9e5f68..bc3054a64 100644 --- a/pkg/compiler/testdata/errors.txt +++ b/pkg/compiler/testdata/errors.txt @@ -88,7 +88,7 @@ foo$11(a buffer["in"]) ### unexpected string "in" for direction argument of ptr foo$12(a buffer[10]) ### unexpected int 10 for direction argument of ptr type, expect [in out inout] foo$13(a int32[2:3]) foo$14(a int32[2:2]) -foo$16(a int32[3]) ### first argument of int32 needs to be a range +foo$16(a int32[3]) ### first argument of int32 needs to be a range or flag foo$17(a ptr[in, int32]) foo$18(a ptr[in, int32[2:3]]) foo$19(a ptr[in, int32[opt]]) @@ -104,7 +104,7 @@ foo$30(a ptr[in, string[no]]) ### unknown string flags no foo$31(a int8, b ptr[in, csum[a, inet]]) ### wrong number of arguments for type csum, expect csum target, kind, [proto], base type foo$32(a int8, b ptr[in, csum[a, inet, 1, int32]]) ### only pseudo csum can have proto foo$33(a int8, b ptr[in, csum[a, pseudo, 1, int32]]) -foo$34(a int32["foo"]) ### unexpected string "foo" for range argument of int32 type, expect int +foo$34(a int32["foo"]) ### unexpected string "foo" for value argument of int32 type, expect identifier or int foo$35(a ptr[in, s3[opt]]) ### s3 can't be marked as opt foo$36(a const[1:2]) ### unexpected ':' foo$39(a fileoff:1) ### type alias fileoff with ':' @@ -129,16 +129,17 @@ foo$59(a s1) ### s1 can't be syscall argument foo$60() s1 ### s1 can't be syscall return foo$61(a u6) ### u6 can't be syscall argument foo$62() u6 ### u6 can't be syscall return -foo$63(a int32[1[2]]) ### range argument has subargs +foo$63(a int32[1[2]]) ### value argument has subargs foo$64(a ptr[in, flags[f1[int32], int32]]) ### flags argument has subargs foo$65(a int32, b len[1]) ### unexpected int 1 for len target argument of len type, expect identifier foo$66(a int32, b len[a:1]) ### unexpected int 1 after colon, expect identifier foo$67(x int32[1:2:3, opt]) ### unexpected ':' -foo$68(a int32[15, 2]) ### first argument of int32 needs to be a range +foo$68(a int32[15, 2]) ### first argument of int32 needs to be a range or flag foo$69() (foo) ### unknown syscall foo$69 attribute foo foo$70() ("foo") ### unexpected string "foo", expect attribute foo$71() (42) ### unexpected int 42, expect attribute foo$72() (disabled, disabled) ### duplicate syscall foo$72 attribute disabled +foo$73(a int32[int_flags, 2]) ### align argument of int32 is not supported unless first argument is a range opt { ### struct uses reserved name opt f1 int32 @@ -146,6 +147,7 @@ opt { ### struct uses reserved name opt in = 1, 2 ### flags uses reserved name in out = "1", "2" ### string flags uses reserved name out +int_flags = 0, 1, 0xabc, 'x', -11 out [ ### union uses reserved name out f1 int32 diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 028c54b4b..1dd2361f2 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -76,7 +76,7 @@ var typeInt = &typeDesc{ MaxColon: 1, OptArgs: 2, Args: []namedArg{ - {Name: "range", Type: typeArgIntRange}, + {Name: "value", Type: typeArgIntValue}, {Name: "align", Type: typeArgIntAlign}, }, CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { @@ -89,8 +89,16 @@ var typeInt = &typeDesc{ }, Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) { typeArgBase.Type.Check(comp, t) - if len(args) > 0 && len(args[0].Colon) == 0 { - comp.error(args[0].Pos, "first argument of %v needs to be a range", t.Ident) + if len(args) > 0 { + _, isIntFlag := comp.intFlags[args[0].Ident] + if len(args[0].Colon) == 0 && !isIntFlag { + comp.error(args[0].Pos, "first argument of %v needs to be a range or flag", t.Ident) + return + } + } + if len(args) > 1 && len(args[0].Colon) == 0 { + comp.error(args[1].Pos, "align argument of %v is not supported unless first argument is a range", + t.Ident) } }, CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) { @@ -129,9 +137,20 @@ var typeInt = &typeDesc{ }, Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type { size, be := comp.parseIntType(t.Ident) + var bitLen uint64 + if len(t.Colon) != 0 { + bitLen = t.Colon[0].Value + } + base.TypeSize = size + base.TypeAlign = getIntAlignment(comp, base) + base = genIntCommon(base.TypeCommon, bitLen, be) + kind, rangeBegin, rangeEnd, align := prog.IntPlain, uint64(0), uint64(0), uint64(0) if len(args) > 0 { rangeArg := args[0] + if _, isIntFlag := comp.intFlags[rangeArg.Ident]; isIntFlag { + return generateFlagsType(comp, base, rangeArg.Ident) + } kind, rangeBegin, rangeEnd = prog.IntRange, rangeArg.Value, rangeArg.Value if len(rangeArg.Colon) != 0 { rangeEnd = rangeArg.Colon[0].Value @@ -140,14 +159,8 @@ var typeInt = &typeDesc{ align = args[1].Value } } - var bitLen uint64 - if len(t.Colon) != 0 { - bitLen = t.Colon[0].Value - } - base.TypeSize = size - base.TypeAlign = getIntAlignment(comp, base) return &prog.IntType{ - IntTypeCommon: genIntCommon(base.TypeCommon, bitLen, be), + IntTypeCommon: base, Kind: kind, RangeBegin: rangeBegin, RangeEnd: rangeEnd, @@ -1006,9 +1019,16 @@ var typeArgInt = &typeArg{ Kind: kindInt, } -var typeArgIntRange = &typeArg{ - Kind: kindInt, +var typeArgIntValue = &typeArg{ + Kind: kindInt | kindIdent, MaxColon: 1, + Check: func(comp *compiler, t *ast.Type) { + // If the first arg is not a range, then it should be a valid flags. + if len(t.Colon) == 0 && t.Ident != "" && comp.intFlags[t.Ident] == nil { + comp.error(t.Pos, "unknown flags %v", t.Ident) + return + } + }, } var typeArgIntAlign = &typeArg{ |
