Skip to content

Commit cba05a7

Browse files
committed
Support naked functions
Fixes rust-lang/rustc_codegen_cranelift#1203
1 parent 0627c63 commit cba05a7

File tree

7 files changed

+231
-48
lines changed

7 files changed

+231
-48
lines changed

Diff for: build_system/build_sysroot.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ fn build_clif_sysroot_for_triple(
276276
if channel == "release" {
277277
build_cmd.arg("--release");
278278
}
279-
build_cmd.arg("--features").arg("compiler-builtins-no-asm backtrace panic-unwind");
279+
build_cmd.arg("--features").arg("backtrace panic-unwind");
280280
build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
281281
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
282282
if compiler.triple.contains("apple") {

Diff for: example/mini_core_hello_world.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
never_type,
55
linkage,
66
extern_types,
7+
naked_functions,
78
thread_local,
89
repr_simd,
910
raw_ref_op
@@ -340,6 +341,7 @@ fn main() {
340341
))]
341342
unsafe {
342343
global_asm_test();
344+
naked_test();
343345
}
344346

345347
// Both statics have a reference that points to the same anonymous allocation.
@@ -395,6 +397,14 @@ global_asm! {
395397
"
396398
}
397399

400+
#[cfg(all(not(jit), not(no_unstable_features), target_arch = "x86_64"))]
401+
#[naked]
402+
extern "C" fn naked_test() {
403+
unsafe {
404+
asm!("ret", options(noreturn));
405+
}
406+
}
407+
398408
#[repr(C)]
399409
enum c_void {
400410
_1,

Diff for: src/base.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
66
use cranelift_module::ModuleError;
77
use rustc_ast::InlineAsmOptions;
88
use rustc_index::IndexVec;
9+
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
910
use rustc_middle::ty::adjustment::PointerCoercion;
1011
use rustc_middle::ty::layout::FnAbiOf;
1112
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -14,6 +15,7 @@ use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphizat
1415

1516
use crate::constant::ConstantCx;
1617
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
18+
use crate::inline_asm::codegen_naked_asm;
1719
use crate::prelude::*;
1820
use crate::pretty_clif::CommentWriter;
1921

@@ -32,7 +34,7 @@ pub(crate) fn codegen_fn<'tcx>(
3234
cached_func: Function,
3335
module: &mut dyn Module,
3436
instance: Instance<'tcx>,
35-
) -> CodegenedFunction {
37+
) -> Option<CodegenedFunction> {
3638
debug_assert!(!instance.args.has_infer());
3739

3840
let symbol_name = tcx.symbol_name(instance).name.to_string();
@@ -48,6 +50,37 @@ pub(crate) fn codegen_fn<'tcx>(
4850
String::from_utf8_lossy(&buf).into_owned()
4951
});
5052

53+
if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
54+
assert_eq!(mir.basic_blocks.len(), 1);
55+
assert!(mir.basic_blocks[START_BLOCK].statements.is_empty());
56+
57+
match &mir.basic_blocks[START_BLOCK].terminator().kind {
58+
TerminatorKind::InlineAsm {
59+
template,
60+
operands,
61+
options,
62+
line_spans: _,
63+
targets: _,
64+
unwind: _,
65+
} => {
66+
codegen_naked_asm(
67+
tcx,
68+
cx,
69+
module,
70+
instance,
71+
mir.basic_blocks[START_BLOCK].terminator().source_info.span,
72+
&symbol_name,
73+
template,
74+
operands,
75+
*options,
76+
);
77+
}
78+
_ => unreachable!(),
79+
}
80+
81+
return None;
82+
}
83+
5184
// Declare function
5285
let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
5386
let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
@@ -128,7 +161,7 @@ pub(crate) fn codegen_fn<'tcx>(
128161
// Verify function
129162
verify_func(tcx, &clif_comments, &func);
130163

131-
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
164+
Some(CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx })
132165
}
133166

134167
pub(crate) fn compile_fn(

Diff for: src/driver/aot.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -482,15 +482,16 @@ fn module_codegen(
482482
for (mono_item, _) in mono_items {
483483
match mono_item {
484484
MonoItem::Fn(inst) => {
485-
let codegened_function = crate::base::codegen_fn(
485+
if let Some(codegened_function) = crate::base::codegen_fn(
486486
tcx,
487487
&mut cx,
488488
&mut type_dbg,
489489
Function::new(),
490490
&mut module,
491491
inst,
492-
);
493-
codegened_functions.push(codegened_function);
492+
) {
493+
codegened_functions.push(codegened_function);
494+
}
494495
}
495496
MonoItem::Static(def_id) => {
496497
let data_id = crate::constant::codegen_static(tcx, &mut module, def_id);

Diff for: src/driver/jit.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -232,16 +232,16 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
232232
crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
233233

234234
let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
235-
let codegened_func = crate::base::codegen_fn(
235+
if let Some(codegened_func) = crate::base::codegen_fn(
236236
tcx,
237237
cx,
238238
&mut TypeDebugContext::default(),
239239
cached_func,
240240
module,
241241
instance,
242-
);
243-
244-
crate::base::compile_fn(cx, cached_context, module, codegened_func);
242+
) {
243+
crate::base::compile_fn(cx, cached_context, module, codegened_func);
244+
}
245245
});
246246
}
247247

Diff for: src/driver/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! [`codegen_static`]: crate::constant::codegen_static
66
77
use rustc_data_structures::profiling::SelfProfilerRef;
8+
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
89
use rustc_middle::mir::mono::{MonoItem, MonoItemData};
910

1011
use crate::prelude::*;
@@ -33,7 +34,20 @@ fn predefine_mono_items<'tcx>(
3334
data.visibility,
3435
is_compiler_builtins,
3536
);
36-
module.declare_function(name, linkage, &sig).unwrap();
37+
let is_naked = tcx
38+
.codegen_fn_attrs(instance.def_id())
39+
.flags
40+
.contains(CodegenFnAttrFlags::NAKED);
41+
module
42+
.declare_function(
43+
name,
44+
// Naked functions are defined in a separate object
45+
// file from the codegen unit rustc expects them to
46+
// be defined in.
47+
if is_naked { Linkage::Import } else { linkage },
48+
&sig,
49+
)
50+
.unwrap();
3751
}
3852
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
3953
}

0 commit comments

Comments
 (0)