Skip to content

Commit 5eebd91

Browse files
authored
parser: fix asm modifier parsing (allow for =r, =&r, +r, +&r,=m,=rm,=@ccl, =*r) (fix #25070) (#25072)
1 parent 4e8b246 commit 5eebd91

2 files changed

Lines changed: 58 additions & 27 deletions

File tree

‎vlib/v/parser/asm.v‎

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -592,40 +592,51 @@ fn (mut p Parser) asm_ios(output bool) []ast.AsmIO {
592592
if p.tok.kind == .lpar {
593593
constraint = if output { '+r' } else { 'r' } // default constraint, though vfmt fmts to `+r` and `r`
594594
} else {
595-
constraint += match p.tok.kind {
596-
.assign {
597-
'='
598-
}
599-
.plus {
600-
'+'
601-
}
602-
.mod {
603-
'%'
595+
// https://gcc.gnu.org/onlinedocs/gcc/Modifiers.html
596+
if output {
597+
// Output constraint
598+
if p.tok.kind == .assign {
599+
constraint += '='
600+
} else if p.tok.kind == .plus {
601+
constraint += '+'
602+
} else {
603+
p.error_with_pos('Output constraint must starts with `=` or `+`',
604+
pos)
605+
return []
604606
}
605-
.amp {
606-
'&'
607+
p.next()
608+
if p.tok.kind == .amp {
609+
constraint += '&'
610+
p.next()
611+
} else if p.tok.kind == .mul {
612+
constraint += '*'
613+
p.next()
607614
}
608-
else {
609-
''
615+
} else {
616+
// Input constraint
617+
if p.tok.kind == .mod {
618+
constraint += '%'
619+
p.next()
620+
} else if p.tok.kind == .mul {
621+
constraint += '*'
622+
p.next()
610623
}
611624
}
612-
if constraint != '' {
613-
p.next()
614-
}
615-
constraint += p.tok.lit
616625
if p.tok.kind == .at {
626+
// hack: `@ccl` is a single token .at, not .at + .name
627+
constraint += p.tok.lit
617628
p.next()
618-
} else {
619-
if p.tok.kind == .number {
620-
// Numbered constraints - https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html
621-
if p.tok.lit.int() >= 10 {
622-
p.error_with_pos('The digit must be between 0 and 9 only', pos)
623-
return []
624-
}
625-
p.check(.number)
626-
} else {
627-
p.check(.name)
629+
} else if p.tok.kind == .number && !output {
630+
// Numbered constraints - https://gcc.gnu.org/onlinedocs/gcc/Simple-Constraints.html
631+
if p.tok.lit.int() >= 10 {
632+
p.error_with_pos('The digit must be between 0 and 9 only', pos)
633+
return []
628634
}
635+
constraint += p.tok.lit
636+
p.check(.number)
637+
} else {
638+
constraint += p.tok.lit
639+
p.check(.name)
629640
}
630641
}
631642
mut expr := p.expr(0)

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ fn test_inline_asm() {
110110
; ; eax
111111
}
112112
assert o.str()[0].is_capital()
113+
114+
x := u64(100)
115+
y := u64(200)
116+
mut hi := u64(0)
117+
mut lo := u64(0)
118+
asm amd64 {
119+
mov rax, x
120+
mulq y
121+
mov lo, rax
122+
mov hi, rdx
123+
; =*m (lo)
124+
=&r (hi)
125+
; rm (x)
126+
r (y)
127+
; rax
128+
rdx
129+
cc
130+
}
131+
assert hi == 0
132+
assert lo == 20000
113133
}
114134

115135
@[packed]

0 commit comments

Comments
 (0)