Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser: allow lock prefix instructions and numbered reg in asm inline #21022

Merged
merged 14 commits into from Mar 16, 2024
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 {
felipensp marked this conversation as resolved.
Show resolved Hide resolved
// 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
}