Skip to content

Commit 9c9d35a

Browse files
committed
Fix calling custom call conv functions from inline asm
1 parent 1111eb5 commit 9c9d35a

2 files changed

Lines changed: 44 additions & 15 deletions

File tree

example/std_example.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![cfg_attr(target_arch = "x86_64", feature(abi_custom))]
12
#![feature(core_intrinsics, coroutines, coroutine_trait, repr_simd, tuple_trait, unboxed_closures)]
23
#![allow(internal_features)]
34

@@ -167,6 +168,9 @@ fn main() {
167168

168169
rust_call_abi();
169170

171+
#[cfg(target_arch = "x86_64")]
172+
inline_asm_call_custom_abi();
173+
170174
const fn no_str() -> Option<Box<str>> {
171175
None
172176
}
@@ -678,3 +682,17 @@ fn map(a: Option<(u8, Box<Instruction>)>) -> Option<Box<Instruction>> {
678682
Some((_, instr)) => Some(instr),
679683
}
680684
}
685+
686+
#[cfg(target_arch = "x86_64")]
687+
fn inline_asm_call_custom_abi() {
688+
use std::arch::{asm, naked_asm};
689+
690+
#[unsafe(naked)]
691+
unsafe extern "custom" fn double() {
692+
naked_asm!("add rax, rax", "ret");
693+
}
694+
695+
let mut x: u64 = 21;
696+
unsafe { asm!("call {}", sym double, inout("rax") x) };
697+
assert_eq!(x, 42);
698+
}

src/inline_asm.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
use std::fmt::Write;
44

55
use cranelift_codegen::isa::CallConv;
6+
use rustc_abi::CanonAbi;
67
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
78
use rustc_hir::LangItem;
9+
use rustc_middle::ty::layout::FnAbiOf;
810
use rustc_span::sym;
911
use rustc_target::asm::*;
1012
use rustc_target::spec::Arch;
@@ -120,21 +122,30 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
120122
.unwrap();
121123
let symbol = fx.tcx.symbol_name(instance);
122124

123-
// Pass a wrapper rather than the function itself as the function itself may not
124-
// be exported from the main codegen unit and may thus be unreachable from the
125-
// object file created by an external assembler.
126-
let wrapper_name = format!(
127-
"{}__inline_asm_{}_wrapper_n{}",
128-
fx.symbol_name,
129-
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
130-
fx.inline_asm_index,
131-
);
132-
fx.inline_asm_index += 1;
133-
let sig =
134-
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
135-
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
136-
137-
CInlineAsmOperand::Symbol { symbol: wrapper_name }
125+
if FullyMonomorphizedLayoutCx(fx.tcx)
126+
.fn_abi_of_instance(instance, ty::List::empty())
127+
.conv
128+
== CanonAbi::Custom
129+
{
130+
// We can't create a wrapper for custom ABI functions.
131+
CInlineAsmOperand::Symbol { symbol: symbol.name.to_owned() }
132+
} else {
133+
// Pass a wrapper rather than the function itself as the function itself may not
134+
// be exported from the main codegen unit and may thus be unreachable from the
135+
// object file created by an external assembler.
136+
let wrapper_name = format!(
137+
"{}__inline_asm_{}_wrapper_n{}",
138+
fx.symbol_name,
139+
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
140+
fx.inline_asm_index,
141+
);
142+
fx.inline_asm_index += 1;
143+
let sig =
144+
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
145+
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
146+
147+
CInlineAsmOperand::Symbol { symbol: wrapper_name }
148+
}
138149
} else {
139150
span_bug!(span, "invalid type for asm sym (fn)");
140151
}

0 commit comments

Comments
 (0)