From bf2569a9a880ea6fbd908042fecccab8a96a2640 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 22 Sep 2021 13:06:30 +0300 Subject: [PATCH] all: support `mut volatile x := 123` declarations (#11940) --- doc/docs.md | 1 + vlib/v/ast/ast.v | 2 ++ vlib/v/fmt/fmt.v | 3 +++ vlib/v/gen/c/cgen.v | 3 +++ vlib/v/gen/c/testdata/volatile.c.must_have | 2 ++ vlib/v/gen/c/testdata/volatile.out | 2 ++ vlib/v/gen/c/testdata/volatile.vv | 4 ++++ vlib/v/parser/assign.v | 5 +++++ vlib/v/parser/expr.v | 2 +- vlib/v/parser/parser.v | 8 +++++++- vlib/v/tests/struct_test.v | 5 +---- vlib/v/tests/volatile_vars_test.v | 14 ++++++++++++++ vlib/v/token/token.v | 2 ++ 13 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 vlib/v/gen/c/testdata/volatile.c.must_have create mode 100644 vlib/v/gen/c/testdata/volatile.out create mode 100644 vlib/v/gen/c/testdata/volatile.vv create mode 100644 vlib/v/tests/volatile_vars_test.v diff --git a/doc/docs.md b/doc/docs.md index 74c295b9cf..744a99aa75 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -5530,6 +5530,7 @@ type typeof union unsafe +volatile __offsetof ``` See also [V Types](#v-types). diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index aee1efe656..8be7718a50 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -703,6 +703,7 @@ pub mut: typ Type is_mut bool is_static bool + is_volatile bool is_optional bool share ShareType } @@ -996,6 +997,7 @@ pub mut: left_types []Type right_types []Type is_static bool // for translated code only + is_volatile bool // for disabling variable access optimisations (needed for hardware drivers) is_simple bool // `x+=2` in `for x:=1; ; x+=2` has_cross_var bool } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index c282fc42f5..e11197d5e3 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -1719,6 +1719,9 @@ pub fn (mut f Fmt) ident(node ast.Ident) { if var_info.is_static { f.write('static ') } + if var_info.is_volatile { + f.write('volatile ') + } } f.write_language_prefix(node.language) if node.name == 'it' && f.it_name != '' && !f.inside_lambda { // allow `it` in lambdas diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 293971b69f..9f1ff6e164 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2374,6 +2374,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { if assign_stmt.is_static { g.write('static ') } + if assign_stmt.is_volatile { + g.write('volatile ') + } mut return_type := ast.void_type is_decl := assign_stmt.op == .decl_assign g.assign_op = assign_stmt.op diff --git a/vlib/v/gen/c/testdata/volatile.c.must_have b/vlib/v/gen/c/testdata/volatile.c.must_have new file mode 100644 index 0000000000..a88594038a --- /dev/null +++ b/vlib/v/gen/c/testdata/volatile.c.must_have @@ -0,0 +1,2 @@ +volatile int *zzz = HEAP(int, (123)); +volatile int* pzzz = &(*(zzz)); diff --git a/vlib/v/gen/c/testdata/volatile.out b/vlib/v/gen/c/testdata/volatile.out new file mode 100644 index 0000000000..f3da5b535e --- /dev/null +++ b/vlib/v/gen/c/testdata/volatile.out @@ -0,0 +1,2 @@ +123 +&123 diff --git a/vlib/v/gen/c/testdata/volatile.vv b/vlib/v/gen/c/testdata/volatile.vv new file mode 100644 index 0000000000..2c95812473 --- /dev/null +++ b/vlib/v/gen/c/testdata/volatile.vv @@ -0,0 +1,4 @@ +mut volatile zzz := 123 +mut volatile pzzz := &zzz +println(zzz) +println(&int(voidptr(pzzz))) diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index 76c074ae05..a477969714 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -156,6 +156,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme } } mut is_static := false + mut is_volatile := false for i, lx in left { match mut lx { ast.Ident { @@ -174,6 +175,9 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme } is_static = true } + if iv.is_volatile { + is_volatile = true + } } r0 := right[0] mut v := ast.Var{ @@ -232,5 +236,6 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme has_cross_var: has_cross_var is_simple: p.inside_for && p.tok.kind == .lcbr is_static: is_static + is_volatile: is_volatile } } diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index e96fdaf4c3..14a0b390cb 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -32,7 +32,7 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr { } // Prefix match p.tok.kind { - .key_mut, .key_shared, .key_atomic, .key_static { + .key_mut, .key_shared, .key_atomic, .key_static, .key_volatile { ident := p.parse_ident(ast.Language.v) node = ident if p.inside_defer { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 34c471f853..9193e87380 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -865,7 +865,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { mut arch := pref.arch_from_string(p.tok.lit) or { pref.Arch._auto } mut is_volatile := false mut is_goto := false - if p.tok.lit == 'volatile' && p.tok.kind == .name { + if p.tok.kind == .key_volatile { arch = pref.arch_from_string(p.peek_tok.lit) or { pref.Arch._auto } is_volatile = true p.next() @@ -1820,6 +1820,10 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident { if is_static { p.next() } + is_volatile := p.tok.kind == .key_volatile + if is_volatile { + p.next() + } if p.tok.kind != .name { p.error('unexpected token `$p.tok.lit`') return ast.Ident{ @@ -1838,6 +1842,7 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident { info: ast.IdentVar{ is_mut: false is_static: false + is_volatile: false } scope: p.scope } @@ -1861,6 +1866,7 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident { info: ast.IdentVar{ is_mut: is_mut is_static: is_static + is_volatile: is_volatile share: ast.sharetype_from_flags(is_shared, is_atomic) } scope: p.scope diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index 3349c9fe6e..1e89c25483 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -60,7 +60,6 @@ struct ReservedKeywords { typedef int unsigned int void int - volatile int while int } @@ -120,18 +119,16 @@ fn test_at() { fn test_reserved_keywords() { // Make sure we can initialize them correctly using full syntax. - rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3} + rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3} // Test a few as it'll take too long to test all. If it's initialized // correctly, other fields are also probably valid. assert rk_holder.unix == 5 assert rk_holder.while == 3 rk_holder2 := ReservedKeywords{ inline: 9 - volatile: 11 } // Make sure partial initialization works too. assert rk_holder2.inline == 9 - assert rk_holder2.volatile == 11 assert rk_holder2.while == 0 // Zero value as not specified. } diff --git a/vlib/v/tests/volatile_vars_test.v b/vlib/v/tests/volatile_vars_test.v new file mode 100644 index 0000000000..42c62a1225 --- /dev/null +++ b/vlib/v/tests/volatile_vars_test.v @@ -0,0 +1,14 @@ +fn test_volatile_var() { + mut volatile zzz := 123 + assert zzz == 123 +} + +fn test_volatile_pointer() { + x := 123 + y := 456 + mut volatile p := unsafe { &x } + println(p) + p = unsafe { &y } + println(p) + assert unsafe { *p == y } +} diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index eb7ebe2799..1f787ee107 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -126,6 +126,7 @@ pub enum Kind { key_union key_pub key_static + key_volatile key_unsafe keyword_end _end_ @@ -303,6 +304,7 @@ fn build_token_str() []string { s[Kind.key_global] = '__global' s[Kind.key_union] = 'union' s[Kind.key_static] = 'static' + s[Kind.key_volatile] = 'volatile' s[Kind.key_as] = 'as' s[Kind.key_defer] = 'defer' s[Kind.key_match] = 'match'