Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions c2rust-transpile/src/translator/assembly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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)));

Expand All @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions c2rust-transpile/tests/snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
23 changes: 23 additions & 0 deletions c2rust-transpile/tests/snapshots/arch-specific/asm.c
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)]
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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)]
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading