Skip to content

Commit 4221522

Browse files
authored
parser: allow lock prefix instructions and numbered reg in inline asm blocks (#21022)
1 parent 9d66b34 commit 4221522

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

vlib/v/parser/parser.v

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import os
1515
import hash.fnv1a
1616
import strings
1717

18+
// https://www.felixcloutier.com/x86/lock
19+
const allowed_lock_prefix_ins = ['add', 'adc', 'and', 'btc', 'btr', 'bts', 'cmpxchg', 'cmpxchg8b',
20+
'cmpxchg16b', 'dec', 'inc', 'neg', 'not', 'or', 'sbb', 'sub', 'xor', 'xadd', 'xchg']
21+
1822
@[minify]
1923
pub struct Parser {
2024
pref &pref.Preferences = unsafe { nil }
@@ -1253,6 +1257,17 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
12531257
}
12541258
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.
12551259
name += p.tok.kind.str()
1260+
if p.tok.kind == .key_lock && arch in [.i386, .amd64] {
1261+
p.next()
1262+
1263+
has_suffix := p.tok.lit[p.tok.lit.len - 1] in [`b`, `w`, `l`, `q`]
1264+
if !(p.tok.lit in parser.allowed_lock_prefix_ins || (has_suffix
1265+
&& p.tok.lit[0..p.tok.lit.len - 1] in parser.allowed_lock_prefix_ins)) {
1266+
p.error('The lock prefix cannot be used on this instruction')
1267+
}
1268+
name += ' '
1269+
name += p.tok.lit
1270+
}
12561271
p.next()
12571272
} else if p.tok.kind == .number {
12581273
name += p.tok.lit
@@ -1764,7 +1779,15 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO {
17641779
if p.tok.kind == .at {
17651780
p.next()
17661781
} else {
1767-
p.check(.name)
1782+
if p.tok.kind == .number {
1783+
// Numbered constraints - https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html
1784+
if p.tok.lit.int() >= 10 {
1785+
p.error_with_pos('The digit must be between 0 and 9 only', pos)
1786+
}
1787+
p.check(.number)
1788+
} else {
1789+
p.check(.name)
1790+
}
17681791
}
17691792
}
17701793
mut expr := p.expr(0)

vlib/v/slow_tests/assembly/asm_test.amd64.v

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,21 @@ fn generic_asm[T](var &T) T {
235235
}
236236
return ret
237237
}
238+
239+
fn test_lock_prefix() {
240+
mut rv := u64(123)
241+
mut atom := u64(0)
242+
cmp := u64(1)
243+
xchg := u64(1)
244+
245+
asm amd64 {
246+
lock cmpxchgq '%1', '%2'
247+
; =a (rv)
248+
+m (atom)
249+
; q (xchg)
250+
0 (cmp)
251+
; memory
252+
}
253+
assert rv == 0
254+
assert atom == 0
255+
}

0 commit comments

Comments
 (0)