From a9ace0cd8dbffb0a58f24c5b3e16dd658606dabd Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:21 +0300 Subject: [PATCH] cgen: fix asm volatile with no instructions generating invalid c code (fixes #26719) --- vlib/v/gen/c/cgen.v | 64 ++++++++++--------- ..._empty_template_memory_barrier.c.must_have | 3 + .../asm_empty_template_memory_barrier.vv | 5 ++ 3 files changed, 42 insertions(+), 30 deletions(-) create mode 100644 vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.c.must_have create mode 100644 vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.vv diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index d6d0cb151..f12d8fceb 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4215,41 +4215,45 @@ fn (mut g Gen) asm_stmt(stmt ast.AsmStmt) { } g.writeln(' (') g.indent++ - for template_tmp in stmt.templates { - mut template := template_tmp - g.write('"') - if template.is_directive { - g.write('.') - } - g.write(template.name) - if template.is_label { - g.write(':') - } else { - g.write(' ') - } - // swap destination and operands for att syntax, not for arm64 - if template.args.len != 0 && !template.is_directive - && stmt.arch !in [.arm64, .s390x, .ppc64le, .loongarch64, .rv64, .rv32] { - template.args.prepend(template.args.last()) - template.args.delete(template.args.len - 1) - } - - for i, arg in template.args { - if stmt.arch == .amd64 && (template.name == 'call' || template.name[0] == `j`) - && arg is ast.AsmRegister { - g.write('*') // indirect branching + if stmt.templates.len == 0 { + g.writeln('""') + } else { + for template_tmp in stmt.templates { + mut template := template_tmp + g.write('"') + if template.is_directive { + g.write('.') + } + g.write(template.name) + if template.is_label { + g.write(':') + } else { + g.write(' ') + } + // swap destination and operands for att syntax, not for arm64 + if template.args.len != 0 && !template.is_directive + && stmt.arch !in [.arm64, .s390x, .ppc64le, .loongarch64, .rv64, .rv32] { + template.args.prepend(template.args.last()) + template.args.delete(template.args.len - 1) } - g.asm_arg(arg, stmt) - if i + 1 < template.args.len { - g.write(', ') + for i, arg in template.args { + if stmt.arch == .amd64 && (template.name == 'call' || template.name[0] == `j`) + && arg is ast.AsmRegister { + g.write('*') // indirect branching + } + + g.asm_arg(arg, stmt) + if i + 1 < template.args.len { + g.write(', ') + } } - } - if !template.is_label { - g.write('\\n\\t') + if !template.is_label { + g.write('\\n\\t') + } + g.writeln('"') } - g.writeln('"') } if stmt.output.len != 0 || stmt.input.len != 0 || stmt.clobbered.len != 0 || stmt.is_goto { diff --git a/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.c.must_have b/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.c.must_have new file mode 100644 index 000000000..11616f6d3 --- /dev/null +++ b/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.c.must_have @@ -0,0 +1,3 @@ +__asm__ volatile ( +"" +: : : "memory" diff --git a/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.vv b/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.vv new file mode 100644 index 000000000..b42d9f73b --- /dev/null +++ b/vlib/v/gen/c/testdata/asm_empty_template_memory_barrier.vv @@ -0,0 +1,5 @@ +fn main() { + asm volatile amd64 { + ; ; ; memory + } +} -- 2.39.5