diff --git a/c2rust-transpile/src/translator/assembly.rs b/c2rust-transpile/src/translator/assembly.rs index 35270421dc..b935ae24c3 100644 --- a/c2rust-transpile/src/translator/assembly.rs +++ b/c2rust-transpile/src/translator/assembly.rs @@ -883,7 +883,8 @@ impl<'c> Translation<'c> { // c2rust-ast-exporter added it (there's no gcc equivalent); // in this case, we need to do what clang does and pass in // the operand by-address instead of by-value - out_expr = mk().mutbl().borrow_expr(out_expr); + self.use_feature("raw_ref_op"); + out_expr = mk().mutbl().raw_borrow_expr(out_expr); } if let Some(_tied_operand) = tied_operands.get(&(output_idx, true)) { @@ -895,12 +896,13 @@ impl<'c> Translation<'c> { // type conversions into the `c2rust-asm-casts` crate, // so we call into that one from here. - // Convert `x` into `let freshN = &mut x; *x` + // Convert `x` into `let freshN = &raw mut x; *x` + self.use_feature("raw_ref_op"); let output_name = self.renamer.borrow_mut().fresh(); let output_local = mk().local( mk().ident_pat(&output_name), None, - Some(mk().mutbl().borrow_expr(out_expr)), + Some(mk().mutbl().raw_borrow_expr(out_expr)), ); stmts.push(mk().local_stmt(Box::new(output_local))); @@ -924,7 +926,8 @@ impl<'c> Translation<'c> { let mut in_expr = in_expr.into_value(); if operand.mem_only { - in_expr = mk().borrow_expr(in_expr); + self.use_feature("raw_ref_op"); + in_expr = mk().raw_borrow_expr(in_expr); } if let Some(tied_operand) = tied_operands.get(&(input_idx, false)) { self.use_crate(ExternCrate::C2RustAsmCasts); diff --git a/c2rust-transpile/tests/snapshots.rs b/c2rust-transpile/tests/snapshots.rs index 3a608fe532..d3fdde1849 100644 --- a/c2rust-transpile/tests/snapshots.rs +++ b/c2rust-transpile/tests/snapshots.rs @@ -413,6 +413,17 @@ fn test_str_init() { // arch-specific +#[test] +fn test_asm() { + #[cfg(target_arch = "x86_64")] + transpile("asm.c") + .arch_specific(true) + .expect_unresolved_import("c2rust_asm_casts") + .run(); + #[cfg(not(target_arch = "x86_64"))] + transpile("asm.c").arch_specific(true).run(); +} + #[test] fn test_spin() { transpile("spin.c").arch_specific(true).run(); diff --git a/c2rust-transpile/tests/snapshots/arch-specific/asm.c b/c2rust-transpile/tests/snapshots/arch-specific/asm.c new file mode 100644 index 0000000000..7960ea6ad3 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/arch-specific/asm.c @@ -0,0 +1,23 @@ +#ifdef __aarch64__ + +// nothing here yet... + +#endif + +#ifdef __x86_64__ + +// Tests https://github.com/immunant/c2rust/issues/398 +int six(void) { + int out = 0; + int six = 6; + + asm ( + "add %0, %1\n\t" + : "=r"(out) + : "r"(six), "0"(out) + ); + + return out; +} + +#endif diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.aarch64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.aarch64.snap new file mode 100644 index 0000000000..f8a71b69e3 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.aarch64.snap @@ -0,0 +1,13 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/asm.2024.aarch64.rs +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![deny(unsafe_op_in_unsafe_fn)] diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.x86_64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.x86_64.snap new file mode 100644 index 0000000000..aa1d839587 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2021.x86_64.snap @@ -0,0 +1,34 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/asm.2021.x86_64.rs +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![deny(unsafe_op_in_unsafe_fn)] +#![feature(asm, raw_ref_op)] +use ::c2rust_asm_casts::AsmCastTrait; +use ::core::arch::asm; +#[no_mangle] +pub unsafe extern "C" fn six() -> ::core::ffi::c_int { + unsafe { + let mut out: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + let mut six_0: ::core::ffi::c_int = 6 as ::core::ffi::c_int; + let c2rust_fresh0 = &raw mut out; + let c2rust_fresh1; + let c2rust_fresh2 = out; + asm!( + "add {0}, {1}\n", "\t\n", inlateout(reg) + c2rust_asm_casts::AsmCast::cast_in(c2rust_fresh0, c2rust_fresh2) => + c2rust_fresh1, inlateout(reg) six_0 => _, options(preserves_flags, pure, + readonly, att_syntax) + ); + c2rust_asm_casts::AsmCast::cast_out(c2rust_fresh0, c2rust_fresh2, c2rust_fresh1); + return out; + } +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.aarch64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.aarch64.snap new file mode 100644 index 0000000000..f8a71b69e3 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.aarch64.snap @@ -0,0 +1,13 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/asm.2024.aarch64.rs +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![deny(unsafe_op_in_unsafe_fn)] diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.x86_64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.x86_64.snap new file mode 100644 index 0000000000..314a8550c0 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@asm.c.2024.x86_64.snap @@ -0,0 +1,33 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/asm.2024.x86_64.rs +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![deny(unsafe_op_in_unsafe_fn)] +use ::c2rust_asm_casts::AsmCastTrait; +use ::core::arch::asm; +#[unsafe(no_mangle)] +pub unsafe extern "C" fn six() -> ::core::ffi::c_int { + unsafe { + let mut out: ::core::ffi::c_int = 0 as ::core::ffi::c_int; + let mut six_0: ::core::ffi::c_int = 6 as ::core::ffi::c_int; + let c2rust_fresh0 = &raw mut out; + let c2rust_fresh1; + let c2rust_fresh2 = out; + asm!( + "add {0}, {1}\n", "\t\n", inlateout(reg) + c2rust_asm_casts::AsmCast::cast_in(c2rust_fresh0, c2rust_fresh2) => + c2rust_fresh1, inlateout(reg) six_0 => _, options(preserves_flags, pure, + readonly, att_syntax) + ); + c2rust_asm_casts::AsmCast::cast_out(c2rust_fresh0, c2rust_fresh2, c2rust_fresh1); + return out; + } +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2021.x86_64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2021.x86_64.snap index 771666b0ca..19ac398cf1 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2021.x86_64.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2021.x86_64.snap @@ -64,11 +64,11 @@ pub unsafe extern "C" fn VM_CallCompiled( "movq ({2}), %rax\n", "movq ({0}), %r8\n", "movq ({1}), %r9\n", "push %r15\n", "push %r14\n", "push %r13\n", "push %r12\n", "callq *%rax\n", "pop %r12\n", "pop %r13\n", "pop %r14\n", "pop %r15\n", "\n", - "mov {restmp0:x}, %bx\n", in (reg) & (* vm).instructionPointers, in (reg) & - (* vm).dataBase, in (reg) & entryPoint, restmp0 = inlateout(reg) opStackOfs, - inlateout("di") opStack, inlateout("si") programStack, out("rax") _, - out("rcx") _, out("rdx") _, out("r8") _, out("r9") _, out("r10") _, - out("r11") _, options(att_syntax) + "mov {restmp0:x}, %bx\n", in (reg) & raw const (* vm).instructionPointers, in + (reg) & raw const (* vm).dataBase, in (reg) & raw const entryPoint, restmp0 = + inlateout(reg) opStackOfs, inlateout("di") opStack, inlateout("si") + programStack, out("rax") _, out("rcx") _, out("rdx") _, out("r8") _, + out("r9") _, out("r10") _, out("r11") _, options(att_syntax) ); if opStackOfs != 1 as ::core::ffi::c_int || *opStack as ::core::ffi::c_uint != 0xdeadbeef as ::core::ffi::c_uint diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2024.x86_64.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2024.x86_64.snap index c4a70029ab..9b1462482a 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2024.x86_64.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@vm_x86.c.2024.x86_64.snap @@ -63,11 +63,11 @@ pub unsafe extern "C" fn VM_CallCompiled( "movq ({2}), %rax\n", "movq ({0}), %r8\n", "movq ({1}), %r9\n", "push %r15\n", "push %r14\n", "push %r13\n", "push %r12\n", "callq *%rax\n", "pop %r12\n", "pop %r13\n", "pop %r14\n", "pop %r15\n", "\n", - "mov {restmp0:x}, %bx\n", in (reg) & (* vm).instructionPointers, in (reg) & - (* vm).dataBase, in (reg) & entryPoint, restmp0 = inlateout(reg) opStackOfs, - inlateout("di") opStack, inlateout("si") programStack, out("rax") _, - out("rcx") _, out("rdx") _, out("r8") _, out("r9") _, out("r10") _, - out("r11") _, options(att_syntax) + "mov {restmp0:x}, %bx\n", in (reg) & raw const (* vm).instructionPointers, in + (reg) & raw const (* vm).dataBase, in (reg) & raw const entryPoint, restmp0 = + inlateout(reg) opStackOfs, inlateout("di") opStack, inlateout("si") + programStack, out("rax") _, out("rcx") _, out("rdx") _, out("r8") _, + out("r9") _, out("r10") _, out("r11") _, options(att_syntax) ); if opStackOfs != 1 as ::core::ffi::c_int || *opStack as ::core::ffi::c_uint != 0xdeadbeef as ::core::ffi::c_uint