From 78ccaa7cdd3e6a3d9bc505886962635ade3ed2ca Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 3 Mar 2024 16:19:00 -0300 Subject: [PATCH 01/10] fix --- vlib/v/checker/checker.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2aaf3593f419c9..b79c4aad7ad750 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3148,7 +3148,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { tt := c.table.type_to_str(to_type) c.error('cannot cast `${ft}` to `${tt}`', node.pos) } - } else if mut to_sym.info is ast.Interface { + } else if !from_type.has_option_or_result() && mut to_sym.info is ast.Interface { if c.type_implements(from_type, to_type, node.pos) { if !from_type.is_any_kind_of_pointer() && from_sym.kind != .interface_ && !c.inside_unsafe { From 2fcbe394142f5f1210c9723f543f7f82d0474eab Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 3 Mar 2024 16:19:00 -0300 Subject: [PATCH 02/10] fix --- vlib/v/checker/checker.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2aaf3593f419c9..b79c4aad7ad750 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3148,7 +3148,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { tt := c.table.type_to_str(to_type) c.error('cannot cast `${ft}` to `${tt}`', node.pos) } - } else if mut to_sym.info is ast.Interface { + } else if !from_type.has_option_or_result() && mut to_sym.info is ast.Interface { if c.type_implements(from_type, to_type, node.pos) { if !from_type.is_any_kind_of_pointer() && from_sym.kind != .interface_ && !c.inside_unsafe { From c220b6d8adc9e7324d9949f9f0c3cc260f988ae2 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 14 Mar 2024 10:20:01 -0300 Subject: [PATCH 03/10] allow lock prefix instr --- vlib/v/parser/parser.v | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d47fc90cc0e649..14c7b248dd5a0f 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1253,6 +1253,11 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { } if p.tok.kind in [.key_in, .key_lock, .key_orelse, .key_select, .key_return] { // `in`, `lock`, `or`, `select`, `return` are v keywords that are also x86/arm/riscv/wasm instructions. name += p.tok.kind.str() + if p.tok.kind == .key_lock && arch in [.i386, .amd64] { + p.next() + name += ' ' + name += p.tok.lit + } p.next() } else if p.tok.kind == .number { name += p.tok.lit @@ -1345,6 +1350,24 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { addressing.segment = segment args << addressing } + .lpar { + mut arg := '(' + p.next() + if p.tok.kind == .mod { + arg += '%' + p.next() + if p.tok.kind == .name { + arg += p.tok.lit + p.next() + } + if p.tok.kind == .rpar { + arg += ')' + p.next() + } + } + args << arg + println('>>> ${arg}') + } .rcbr { break } From c9875d4fbb95d875765b4f05e876deff75526f7f Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 14 Mar 2024 10:26:21 -0300 Subject: [PATCH 04/10] remove print --- vlib/v/parser/parser.v | 1 - 1 file changed, 1 deletion(-) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 14c7b248dd5a0f..44774c20d2fb25 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1366,7 +1366,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { } } args << arg - println('>>> ${arg}') } .rcbr { break From 25062dde64a27b39f32aa3656b668a67c471e909 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 14 Mar 2024 10:28:03 -0300 Subject: [PATCH 05/10] fix --- vlib/v/parser/parser.v | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 44774c20d2fb25..7205988d602605 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1350,23 +1350,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { addressing.segment = segment args << addressing } - .lpar { - mut arg := '(' - p.next() - if p.tok.kind == .mod { - arg += '%' - p.next() - if p.tok.kind == .name { - arg += p.tok.lit - p.next() - } - if p.tok.kind == .rpar { - arg += ')' - p.next() - } - } - args << arg - } .rcbr { break } From 0d889219218b41f2590c0fc7f6621912f9dc49aa Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 14 Mar 2024 10:53:05 -0300 Subject: [PATCH 06/10] fix --- vlib/v/parser/parser.v | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 7205988d602605..9e012795d142e3 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1769,7 +1769,11 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO { if p.tok.kind == .at { p.next() } else { - p.check(.name) + if p.tok.kind == .number { + p.check(.number) + } else { + p.check(.name) + } } } mut expr := p.expr(0) From 2fb5722c31007d97bba11b2c9a729f052a557b42 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 15 Mar 2024 07:39:42 -0300 Subject: [PATCH 07/10] add checking --- vlib/v/parser/parser.v | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 9e012795d142e3..a886d6bc8e07e3 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1770,6 +1770,9 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO { p.next() } else { if p.tok.kind == .number { + if p.tok.lit.int() >= 10 { + p.error_with_pos('The digit must be between 0 and 9 only', pos) + } p.check(.number) } else { p.check(.name) From 9eb5d915e5d0a6847a0eed6804f2ee53af4f4a94 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 15 Mar 2024 08:09:19 -0300 Subject: [PATCH 08/10] add checking --- vlib/v/parser/parser.v | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index a886d6bc8e07e3..6d86cfb5075517 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1255,6 +1255,14 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { name += p.tok.kind.str() if p.tok.kind == .key_lock && arch in [.i386, .amd64] { p.next() + allowed_ins := ['add', 'adc', 'and', 'btc', 'btr', 'bts', 'cmpxchg', 'cmpxch8b', + 'cmpxchg16b', 'dec', 'inc', 'neg', 'not', 'or', 'sbb', 'sub', 'xor', 'xadd', + 'xchg'] + has_suffix := p.tok.lit[p.tok.lit.len - 1] in [`b`, `w`, `l`, `q`] + if !(p.tok.lit in allowed_ins + || (has_suffix && p.tok.lit[0..p.tok.lit.len - 1] in allowed_ins)) { + p.error('The lock prefix cannot be used on this instruction') + } name += ' ' name += p.tok.lit } From 44a25991d2fb2531f288620313c1a076a8071806 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 15 Mar 2024 08:35:36 -0300 Subject: [PATCH 09/10] add test --- vlib/v/slow_tests/assembly/asm_test.amd64.v | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/vlib/v/slow_tests/assembly/asm_test.amd64.v b/vlib/v/slow_tests/assembly/asm_test.amd64.v index 2cbc822b4ef490..98b78e64d74713 100644 --- a/vlib/v/slow_tests/assembly/asm_test.amd64.v +++ b/vlib/v/slow_tests/assembly/asm_test.amd64.v @@ -235,3 +235,21 @@ fn generic_asm[T](var &T) T { } return ret } + +fn test_lock_prefix() { + mut rv := u64(123) + mut atom := u64(0) + cmp := u64(1) + xchg := u64(1) + + asm amd64 { + lock cmpxchgq '%1', '%2' + ; =a (rv) + +m (atom) + ; q (xchg) + 0 (cmp) + ; memory + } + assert rv == 0 + assert atom == 0 +} From 808d0e5b4822a1af00df9f1c35a1a36a5d4c5260 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 15 Mar 2024 22:13:03 -0300 Subject: [PATCH 10/10] add link ref --- vlib/v/parser/parser.v | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 6d86cfb5075517..3a1786fbfd8622 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -15,6 +15,10 @@ import os import hash.fnv1a import strings +// https://www.felixcloutier.com/x86/lock +const allowed_lock_prefix_ins = ['add', 'adc', 'and', 'btc', 'btr', 'bts', 'cmpxchg', 'cmpxchg8b', + 'cmpxchg16b', 'dec', 'inc', 'neg', 'not', 'or', 'sbb', 'sub', 'xor', 'xadd', 'xchg'] + @[minify] pub struct Parser { pref &pref.Preferences = unsafe { nil } @@ -1255,12 +1259,10 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { name += p.tok.kind.str() if p.tok.kind == .key_lock && arch in [.i386, .amd64] { p.next() - allowed_ins := ['add', 'adc', 'and', 'btc', 'btr', 'bts', 'cmpxchg', 'cmpxch8b', - 'cmpxchg16b', 'dec', 'inc', 'neg', 'not', 'or', 'sbb', 'sub', 'xor', 'xadd', - 'xchg'] + has_suffix := p.tok.lit[p.tok.lit.len - 1] in [`b`, `w`, `l`, `q`] - if !(p.tok.lit in allowed_ins - || (has_suffix && p.tok.lit[0..p.tok.lit.len - 1] in allowed_ins)) { + if !(p.tok.lit in parser.allowed_lock_prefix_ins || (has_suffix + && p.tok.lit[0..p.tok.lit.len - 1] in parser.allowed_lock_prefix_ins)) { p.error('The lock prefix cannot be used on this instruction') } name += ' ' @@ -1778,6 +1780,7 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO { p.next() } else { if p.tok.kind == .number { + // Numbered constraints - https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html if p.tok.lit.int() >= 10 { p.error_with_pos('The digit must be between 0 and 9 only', pos) }