1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen, parser: fix several assembly bugs (#10498)

This commit is contained in:
crthpl 2021-06-17 15:20:46 -07:00 committed by GitHub
parent 39e7290416
commit 4688c75389
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 47 deletions

View File

@ -1950,7 +1950,7 @@ fn (mut g Gen) gen_asm_stmt(stmt ast.AsmStmt) {
g.write(' ') g.write(' ')
} }
// swap destionation and operands for att syntax // swap destionation and operands for att syntax
if template.args.len != 0 { if template.args.len != 0 && !template.is_directive {
template.args.prepend(template.args[template.args.len - 1]) template.args.prepend(template.args[template.args.len - 1])
template.args.delete(template.args.len - 1) template.args.delete(template.args.len - 1)
} }
@ -2052,8 +2052,16 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
g.write(')') g.write(')')
} }
.index_times_scale_plus_displacement { .index_times_scale_plus_displacement {
g.asm_arg(displacement, stmt) if displacement is ast.AsmDisp {
g.write('(') g.asm_arg(displacement, stmt)
g.write('(, ')
} else if displacement is ast.AsmRegister {
g.write('(')
g.asm_arg(displacement, stmt)
g.write(',')
} else {
panic('unexpected $displacement.type_name()')
}
g.asm_arg(index, stmt) g.asm_arg(index, stmt)
g.write(',$scale)') g.write(',$scale)')
} }

View File

@ -885,22 +885,32 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
for p.tok.kind !in [.semicolon, .rcbr] { for p.tok.kind !in [.semicolon, .rcbr] {
template_pos := p.tok.position() template_pos := p.tok.position()
mut name := '' mut name := ''
if p.tok.kind == .name && arch == .amd64 && p.tok.lit in ['rex', 'vex', 'xop'] {
name += p.tok.lit
p.next()
for p.tok.kind == .dot {
p.next()
name += '.' + p.tok.lit
p.check(.name)
}
name += ' '
}
is_directive := p.tok.kind == .dot is_directive := p.tok.kind == .dot
if is_directive { if is_directive {
p.next() p.next()
} }
if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions. if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions.
name = p.tok.kind.str() name += p.tok.kind.str()
p.next() p.next()
} else if p.tok.kind == .number { } else if p.tok.kind == .number {
name = p.tok.lit name += p.tok.lit
p.next() p.next()
} else { } else {
name = p.tok.lit name += p.tok.lit
p.check(.name) p.check(.name)
} }
// dots are part of instructions for some riscv extensions // dots are part of instructions for some riscv extensions
if arch in [.rv32, .rv64, .amd64] { if arch in [.rv32, .rv64] {
for p.tok.kind == .dot { for p.tok.kind == .dot {
name += '.' name += '.'
p.next() p.next()
@ -949,8 +959,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
} }
} }
ast.IntegerLiteral { ast.IntegerLiteral {
if is_directive || number_lit.val.ends_with('b') if (is_directive || number_lit.val.ends_with('b')
|| number_lit.val.ends_with('f') { || number_lit.val.ends_with('f'))
&& !number_lit.val.starts_with('0x') {
args << ast.AsmDisp{ args << ast.AsmDisp{
val: number_lit.val val: number_lit.val
pos: number_lit.pos pos: number_lit.pos
@ -1217,11 +1228,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
} }
} else if p.tok.kind == .number { } else if p.tok.kind == .number {
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }
@ -1241,11 +1253,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.next() p.next()
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }
@ -1262,11 +1275,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
if p.peek_tok.kind == .rsbr { if p.peek_tok.kind == .rsbr {
if p.tok.kind == .number { if p.tok.kind == .number {
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }
@ -1288,11 +1302,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.check(.number) p.check(.number)
p.check(.plus) p.check(.plus)
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }
@ -1308,11 +1323,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
} else if p.tok.kind == .plus { } else if p.tok.kind == .plus {
p.next() p.next()
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }
@ -1333,11 +1349,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.check(.number) p.check(.number)
p.check(.plus) p.check(.plus)
displacement := if p.tok.kind == .name { displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit) p.reg_or_alias()
p.next()
x
} else { } else {
x := ast.AsmArg(p.tok.lit) x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number) p.check(.number)
x x
} }

View File

@ -80,6 +80,7 @@ fn test_inline_asm() {
asm amd64 { asm amd64 {
movq [m], 7 // have to specify size with q movq [m], 7 // have to specify size with q
; ; r (m) ; ; r (m)
; memory
} }
assert l == 7 assert l == 7
@ -98,15 +99,15 @@ fn test_inline_asm() {
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files
mut manu := Manu{} mut o := Manu{}
asm amd64 { asm amd64 {
mov eax, 0 mov eax, 0
cpuid cpuid
; =b (manu.ebx) as ebx0 ; =b (o.ebx) as ebx0
=d (manu.edx) as edx0 =d (o.edx) as edx0
=c (manu.ecx) as ecx0 =c (o.ecx) as ecx0
} }
manu.str() o.str()
} }
[packed] [packed]
@ -129,19 +130,47 @@ fn (m Manu) str() string {
} }
// this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode // this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
// doesn't actually work
[if !macos]
fn test_rip_relative_label() { fn test_rip_relative_label() {
mut a := i64(4) $if !macos {
asm amd64 { mut a := i64(4)
mov a, [rip + one_two_three] // see below asm amd64 {
; =r (a) mov a, [rip + one_two_three] // see below
; =r (a)
}
assert a == 48321074923
} }
assert a == 48321074923
} }
asm amd64 { $if !macos {
.global one_two_three asm amd64 {
one_two_three: .global one_two_three
.quad 48321074923 one_two_three:
.quad 48321074923
}
}
// this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
// doesn't actually work
[if !macos]
fn test_rip_relative_label_byte() {
$if !macos {
mut a := int(4)
asm amd64 {
mov a, [rip + byte_sequence] // see below
; =r (a)
}
assert a == 0x480f3527
}
}
$if !macos {
asm amd64 {
.global one_two_three
byte_sequence:
.byte 0x27, 0x35, 0x0f, 0x48
}
} }
fn test_flag_output() { fn test_flag_output() {