From 47f8f347b185b08dcf8b0186f396198f7f093ec9 Mon Sep 17 00:00:00 2001 From: Mike <45243121+tankf33der@users.noreply.github.com> Date: Fri, 9 May 2025 14:57:52 +0300 Subject: [PATCH] ast,cgen,parser,pref: support loongarch64 inline assembly, add test (#24440) --- vlib/v/ast/ast.v | 13 +++++++ vlib/v/ast/types.v | 4 ++ vlib/v/gen/c/cgen.v | 14 ++++--- vlib/v/parser/parser.v | 2 +- vlib/v/pref/arch.c.v | 4 ++ .../assembly/asm_test.loongarch64.v | 37 +++++++++++++++++++ 6 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 vlib/v/slow_tests/assembly/asm_test.loongarch64.v diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 3b3d85996d..06b7aef7a0 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -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 } diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index dd9d36a43c..1ba6ae6bd7 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -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 } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 5c9d79b053..3a6f32e916 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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 != '' { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index bbea0b4707..3916e8bdc2 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -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() diff --git a/vlib/v/pref/arch.c.v b/vlib/v/pref/arch.c.v index 9846ea2e81..7d86c18800 100644 --- a/vlib/v/pref/arch.c.v +++ b/vlib/v/pref/arch.c.v @@ -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 } diff --git a/vlib/v/slow_tests/assembly/asm_test.loongarch64.v b/vlib/v/slow_tests/assembly/asm_test.loongarch64.v new file mode 100644 index 0000000000..ea70bcd3c9 --- /dev/null +++ b/vlib/v/slow_tests/assembly/asm_test.loongarch64.v @@ -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 +}