Skip to content

Commit

Permalink
parser: allow lock prefix instructions and numbered reg in inline asm…
Browse files Browse the repository at this point in the history
… blocks (#21022)
  • Loading branch information
felipensp committed Mar 16, 2024
1 parent 9d66b34 commit 4221522
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
25 changes: 24 additions & 1 deletion vlib/v/parser/parser.v
Expand Up @@ -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 }
Expand Down Expand Up @@ -1253,6 +1257,17 @@ 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()

has_suffix := p.tok.lit[p.tok.lit.len - 1] in [`b`, `w`, `l`, `q`]
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 += ' '
name += p.tok.lit
}
p.next()
} else if p.tok.kind == .number {
name += p.tok.lit
Expand Down Expand Up @@ -1764,7 +1779,15 @@ 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 {
// 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)
}
p.check(.number)
} else {
p.check(.name)
}
}
}
mut expr := p.expr(0)
Expand Down
18 changes: 18 additions & 0 deletions vlib/v/slow_tests/assembly/asm_test.amd64.v
Expand Up @@ -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
}

0 comments on commit 4221522

Please sign in to comment.