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

pull/10500/head
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(' ')
}
// 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.delete(template.args.len - 1)
}
@ -2052,8 +2052,16 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
g.write(')')
}
.index_times_scale_plus_displacement {
g.asm_arg(displacement, stmt)
g.write('(')
if displacement is ast.AsmDisp {
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.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] {
template_pos := p.tok.position()
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
if is_directive {
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.
name = p.tok.kind.str()
name += p.tok.kind.str()
p.next()
} else if p.tok.kind == .number {
name = p.tok.lit
name += p.tok.lit
p.next()
} else {
name = p.tok.lit
name += p.tok.lit
p.check(.name)
}
// 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 {
name += '.'
p.next()
@ -949,8 +959,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
}
}
ast.IntegerLiteral {
if is_directive || number_lit.val.ends_with('b')
|| number_lit.val.ends_with('f') {
if (is_directive || number_lit.val.ends_with('b')
|| number_lit.val.ends_with('f'))
&& !number_lit.val.starts_with('0x') {
args << ast.AsmDisp{
val: number_lit.val
pos: number_lit.pos
@ -1217,11 +1228,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
}
} else if p.tok.kind == .number {
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}
@ -1241,11 +1253,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.next()
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}
@ -1262,11 +1275,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
if p.peek_tok.kind == .rsbr {
if p.tok.kind == .number {
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}
@ -1288,11 +1302,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.check(.number)
p.check(.plus)
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}
@ -1308,11 +1323,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
} else if p.tok.kind == .plus {
p.next()
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}
@ -1333,11 +1349,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing {
p.check(.number)
p.check(.plus)
displacement := if p.tok.kind == .name {
x := ast.AsmArg(p.tok.lit)
p.next()
x
p.reg_or_alias()
} else {
x := ast.AsmArg(p.tok.lit)
x := ast.AsmArg(ast.AsmDisp{
val: p.tok.lit
pos: p.tok.position()
})
p.check(.number)
x
}

View File

@ -80,6 +80,7 @@ fn test_inline_asm() {
asm amd64 {
movq [m], 7 // have to specify size with q
; ; r (m)
; memory
}
assert l == 7
@ -98,15 +99,15 @@ fn test_inline_asm() {
assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files
mut manu := Manu{}
mut o := Manu{}
asm amd64 {
mov eax, 0
cpuid
; =b (manu.ebx) as ebx0
=d (manu.edx) as edx0
=c (manu.ecx) as ecx0
; =b (o.ebx) as ebx0
=d (o.edx) as edx0
=c (o.ecx) as ecx0
}
manu.str()
o.str()
}
[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
// doesn't actually work
[if !macos]
fn test_rip_relative_label() {
mut a := i64(4)
asm amd64 {
mov a, [rip + one_two_three] // see below
; =r (a)
$if !macos {
mut a := i64(4)
asm amd64 {
mov a, [rip + one_two_three] // see below
; =r (a)
}
assert a == 48321074923
}
assert a == 48321074923
}
asm amd64 {
.global one_two_three
one_two_three:
.quad 48321074923
$if !macos {
asm amd64 {
.global one_two_three
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() {