ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440)

This commit is contained in:
Mike 2025-05-09 14:57:52 +03:00 committed by GitHub
parent 9dc69ef2aa
commit 47f8f347b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 68 additions and 6 deletions

View File

@ -1839,6 +1839,12 @@ pub const ppc64le_with_number_register_list = {
'r#': 32
}
pub const loongarch64_no_number_register_list = []string{}
pub const loongarch64_with_number_register_list = {
'f#': 32
'r#': 32
}
pub struct DebuggerStmt {
pub:
pos token.Pos
@ -2658,6 +2664,13 @@ pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject {
res[k] = v
}
}
.loongarch64 {
loongarch64 := gen_all_registers(mut t, loongarch64_no_number_register_list,
loongarch64_with_number_register_list, 64)
for k, v in loongarch64 {
res[k] = v
}
}
.wasm32 {
// no registers
}

View File

@ -53,6 +53,7 @@ pub enum Language {
rv32 // 32-bit risc-v
s390x
ppc64le
loongarch64
wasm32
}
@ -83,6 +84,9 @@ pub fn pref_arch_to_table_language(pref_arch pref.Arch) Language {
.ppc64le {
.ppc64le
}
.loongarch64 {
.loongarch64
}
.js_node, .js_browser, .js_freestanding {
.js
}

View File

@ -3158,7 +3158,7 @@ fn (mut g Gen) asm_stmt(stmt ast.AsmStmt) {
}
// swap destination and operands for att syntax, not for arm64
if template.args.len != 0 && !template.is_directive && stmt.arch != .arm64
&& stmt.arch != .s390x && stmt.arch != .ppc64le {
&& stmt.arch != .s390x && stmt.arch != .ppc64le && stmt.arch != .loongarch64 {
template.args.prepend(template.args.last())
template.args.delete(template.args.len - 1)
}
@ -3235,7 +3235,7 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
ast.IntegerLiteral {
if stmt.arch == .arm64 {
g.write('#${arg.val}')
} else if stmt.arch == .s390x || stmt.arch == .ppc64le {
} else if stmt.arch == .s390x || stmt.arch == .ppc64le || stmt.arch == .loongarch64 {
g.write('${arg.val}')
} else {
g.write('\$${arg.val}')
@ -3252,10 +3252,14 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) {
g.write('\$${arg.val.str()}')
}
ast.AsmRegister {
if !stmt.is_basic {
g.write('%') // escape percent with percent in extended assembly
if stmt.arch == .loongarch64 {
g.write('$${arg.name}')
} else {
if !stmt.is_basic {
g.write('%') // escape percent with percent in extended assembly
}
g.write('%${arg.name}')
}
g.write('%${arg.name}')
}
ast.AsmAddressing {
if arg.segment != '' {

View File

@ -1321,7 +1321,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
p.check(.name)
}
// dots are part of instructions for some riscv extensions and webassembly, arm64
if arch in [.rv32, .rv64, .wasm32, .arm64] {
if arch in [.rv32, .rv64, .wasm32, .arm64, .loongarch64] {
for p.tok.kind == .dot {
name += '.'
p.next()

View File

@ -10,6 +10,7 @@ pub enum Arch {
i386
s390x
ppc64le
loongarch64
js_node
js_browser
js_freestanding
@ -53,6 +54,9 @@ pub fn arch_from_string(arch_str string) !Arch {
's390x' {
return .s390x
}
'loongarch64' {
return .loongarch64
}
'ppc64le' {
return .ppc64le
}

View File

@ -0,0 +1,37 @@
// vtest build: gcc
asm loongarch64 {
move r20, r21
}
fn test_inline_asm() {
a, mut b := 10, 0
asm loongarch64 {
move r20, a
move b, r20
; +r (b)
; r (a)
; r20
}
assert a == b
mut c := 0
asm loongarch64 {
li.w c, 5
; +r (c)
}
assert c == 5
d, e, mut f := 10, 2, 0
asm loongarch64 {
move f, d
add.w f, f, e
addi.w f, f, 5
; +r (f)
; r (d)
r (e)
}
assert d == 10
assert e == 2
assert f == 17
}