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
22 changes: 21 additions & 1 deletion vlib/v/parser/parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,19 @@ 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()
allowed_ins := ['add', 'adc', 'and', 'btc', 'btr', 'bts', 'cmpxchg', 'cmpxch8b',
'cmpxchg16b', 'dec', 'inc', 'neg', 'not', 'or', 'sbb', 'sub', 'xor', 'xadd',
'xchg']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a const instead? I think this may be used in future as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would be a bit nicer as a constant, for code that uses lots of inline assembly, it will avoid some allocations. On the other hand, such code is rare, while a constant will be initialized every time the compiler is ran 🤔 .

Still, I think that the benefit of not doing allocations each time is greater.

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
}
p.next()
} else if p.tok.kind == .number {
name += p.tok.lit
Expand Down Expand Up @@ -1764,7 +1777,14 @@ 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
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
Original file line number Diff line number Diff line change
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
}