aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/check.go3
-rw-r--r--pkg/compiler/consts.go12
-rw-r--r--pkg/compiler/testdata/all.txt2
-rw-r--r--pkg/compiler/testdata/errors.txt10
-rw-r--r--pkg/compiler/types.go44
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{