2020-09-23 15:13:49 +02:00
|
|
|
//! Codegen of a single function
|
|
|
|
|
|
2023-10-09 08:52:46 +00:00
|
|
|
use cranelift_codegen::CodegenError;
|
2024-09-22 19:05:04 -04:00
|
|
|
use cranelift_codegen::ir::UserFuncName;
|
2024-04-23 09:37:28 +00:00
|
|
|
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
2023-10-09 08:52:46 +00:00
|
|
|
use cranelift_module::ModuleError;
|
2021-09-04 22:14:09 +02:00
|
|
|
use rustc_ast::InlineAsmOptions;
|
2024-07-15 23:43:52 +00:00
|
|
|
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
2024-12-06 12:10:30 +00:00
|
|
|
use rustc_data_structures::profiling::SelfProfilerRef;
|
2023-04-19 10:57:17 +00:00
|
|
|
use rustc_index::IndexVec;
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_middle::ty::TypeVisitableExt;
|
2023-07-05 20:07:03 +02:00
|
|
|
use rustc_middle::ty::adjustment::PointerCoercion;
|
2024-11-19 16:13:55 +01:00
|
|
|
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
|
2022-03-20 16:55:21 +01:00
|
|
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
2019-04-21 14:41:23 +02:00
|
|
|
|
2021-04-30 14:49:58 +02:00
|
|
|
use crate::constant::ConstantCx;
|
2024-03-28 11:43:35 +00:00
|
|
|
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
|
2018-07-30 16:57:40 +02:00
|
|
|
use crate::prelude::*;
|
2022-02-23 11:49:34 +01:00
|
|
|
use crate::pretty_clif::CommentWriter;
|
2025-05-23 15:51:51 +01:00
|
|
|
use crate::{codegen_f16_f128, enable_verifier};
|
2018-06-17 18:05:11 +02:00
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
pub(crate) struct CodegenedFunction {
|
|
|
|
|
symbol_name: String,
|
|
|
|
|
func_id: FuncId,
|
|
|
|
|
func: Function,
|
|
|
|
|
clif_comments: CommentWriter,
|
|
|
|
|
func_debug_cx: Option<FunctionDebugContext>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn codegen_fn<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
cx: &mut crate::CodegenCx,
|
2024-03-28 11:43:35 +00:00
|
|
|
type_dbg: &mut TypeDebugContext<'tcx>,
|
2022-08-24 18:40:58 +02:00
|
|
|
cached_func: Function,
|
|
|
|
|
module: &mut dyn Module,
|
|
|
|
|
instance: Instance<'tcx>,
|
2024-12-12 20:31:20 +00:00
|
|
|
) -> CodegenedFunction {
|
2023-07-11 22:35:29 +01:00
|
|
|
debug_assert!(!instance.args.has_infer());
|
2020-11-27 20:48:53 +01:00
|
|
|
|
2023-02-09 12:38:16 +01:00
|
|
|
let symbol_name = tcx.symbol_name(instance).name.to_string();
|
|
|
|
|
let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name);
|
|
|
|
|
|
2020-04-25 11:42:46 +02:00
|
|
|
let mir = tcx.instance_mir(instance.def);
|
2021-07-07 11:14:20 +02:00
|
|
|
let _mir_guard = crate::PrintOnPanic(|| {
|
|
|
|
|
let mut buf = Vec::new();
|
2022-03-20 16:55:21 +01:00
|
|
|
with_no_trimmed_paths!({
|
Introduce `MirDumper` and `MirWriter`.
MIR dumping is a mess. There are lots of functions and entry points,
e.g. `dump_mir`, `dump_mir_with_options`, `dump_polonius_mir`,
`dump_mir_to_writer`. Also, it's crucial that `create_dump_file` is
never called without `dump_enabled` first being checked, but there is no
mechanism for ensuring this and it's hard to tell if it is satisfied on
all paths. (`dump_enabled` is checked twice on some paths, however!)
This commit introduces `MirWriter`, which controls the MIR writing, and
encapsulates the `extra_data` closure and `options`. Two existing
functions are now methods of this type. It sets reasonable defaults,
allowing the removal of many `|_, _| Ok(())` closures.
The commit also introduces `MirDumper`, which is layered on top of
`MirWriter`, and which manages the creation of the dump files,
encapsulating pass names, disambiguators, etc. Four existing functions
are now methods of this type.
- `MirDumper::new` will only succeed if dumps are enabled, and will
return `None` otherwise, which makes it impossible to dump when you
shouldn't.
- It also sets reasonable defaults for various things like
disambiguators, which means you no longer need to specify them in many
cases. When they do need to be specified, it's now done via setter
methods.
- It avoids some repetition. E.g. `dump_nll_mir` previously specifed the
pass name `"nll"` four times and the disambiguator `&0` three times;
now it specifies them just once, to put them in the `MirDumper`.
- For Polonius, the `extra_data` closure can now be specified earlier,
which avoids having to pass some arguments through some functions.
2025-08-15 14:38:17 +10:00
|
|
|
let writer = pretty::MirWriter::new(tcx);
|
|
|
|
|
writer.write_mir_fn(mir, &mut buf).unwrap();
|
2022-03-20 16:55:21 +01:00
|
|
|
});
|
2021-07-07 11:14:20 +02:00
|
|
|
String::from_utf8_lossy(&buf).into_owned()
|
|
|
|
|
});
|
2018-08-14 18:52:43 +02:00
|
|
|
|
2019-05-14 16:12:58 +02:00
|
|
|
// Declare function
|
2022-12-14 19:30:46 +01:00
|
|
|
let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
|
2022-08-24 18:40:58 +02:00
|
|
|
let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
|
2020-08-22 18:53:34 +02:00
|
|
|
|
2020-08-22 19:05:22 +02:00
|
|
|
// Make the FunctionBuilder
|
|
|
|
|
let mut func_ctx = FunctionBuilderContext::new();
|
2022-08-24 18:40:58 +02:00
|
|
|
let mut func = cached_func;
|
|
|
|
|
func.clear();
|
2022-10-23 16:22:55 +02:00
|
|
|
func.name = UserFuncName::user(0, func_id.as_u32());
|
2020-08-22 18:53:34 +02:00
|
|
|
func.signature = sig;
|
|
|
|
|
func.collect_debug_info();
|
|
|
|
|
|
2020-08-22 16:40:58 +02:00
|
|
|
let mut bcx = FunctionBuilder::new(&mut func, &mut func_ctx);
|
2018-06-17 18:05:11 +02:00
|
|
|
|
2020-04-19 04:55:07 -04:00
|
|
|
// Predefine blocks
|
2020-02-14 18:23:29 +01:00
|
|
|
let start_block = bcx.create_block();
|
2021-03-05 19:12:59 +01:00
|
|
|
let block_map: IndexVec<BasicBlock, Block> =
|
2022-07-05 00:00:00 +00:00
|
|
|
(0..mir.basic_blocks.len()).map(|_| bcx.create_block()).collect();
|
2018-06-17 18:05:11 +02:00
|
|
|
|
2024-11-20 11:59:52 +01:00
|
|
|
let fn_abi = FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty());
|
2024-11-02 14:53:30 +00:00
|
|
|
|
2019-05-14 16:12:58 +02:00
|
|
|
// Make FunctionCx
|
2021-12-20 18:56:35 +01:00
|
|
|
let target_config = module.target_config();
|
|
|
|
|
let pointer_type = target_config.pointer_type();
|
2024-11-02 14:53:30 +00:00
|
|
|
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance, fn_abi);
|
2024-03-28 11:43:35 +00:00
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
|
2024-03-28 11:43:35 +00:00
|
|
|
Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span))
|
2022-08-24 18:40:58 +02:00
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
2018-06-20 15:15:28 +02:00
|
|
|
let mut fx = FunctionCx {
|
2020-08-22 16:17:58 +02:00
|
|
|
cx,
|
2021-04-30 14:49:58 +02:00
|
|
|
module,
|
2020-08-22 16:45:50 +02:00
|
|
|
tcx,
|
2021-12-20 18:56:35 +01:00
|
|
|
target_config,
|
2018-11-03 13:14:28 +01:00
|
|
|
pointer_type,
|
2021-04-30 14:49:58 +02:00
|
|
|
constants_cx: ConstantCx::new(),
|
2022-08-24 18:40:58 +02:00
|
|
|
func_debug_cx,
|
2018-12-01 11:49:44 +01:00
|
|
|
|
2018-06-23 18:54:15 +02:00
|
|
|
instance,
|
2021-04-30 14:49:58 +02:00
|
|
|
symbol_name,
|
2018-06-20 15:15:28 +02:00
|
|
|
mir,
|
2024-03-28 11:43:35 +00:00
|
|
|
fn_abi,
|
2018-12-01 11:49:44 +01:00
|
|
|
|
2018-06-23 18:54:15 +02:00
|
|
|
bcx,
|
2020-02-14 18:23:29 +01:00
|
|
|
block_map,
|
2020-09-16 18:45:19 +02:00
|
|
|
local_map: IndexVec::with_capacity(mir.local_decls.len()),
|
2020-01-11 16:49:42 +01:00
|
|
|
caller_location: None, // set by `codegen_fn_prelude`
|
2018-12-01 11:49:44 +01:00
|
|
|
|
2018-12-21 21:42:29 +01:00
|
|
|
clif_comments,
|
2020-06-27 11:58:44 +02:00
|
|
|
next_ssa_var: 0,
|
2018-06-20 15:15:28 +02:00
|
|
|
};
|
|
|
|
|
|
2023-02-09 12:38:16 +01:00
|
|
|
tcx.prof.generic_activity("codegen clif ir").run(|| codegen_fn_body(&mut fx, start_block));
|
2023-01-24 18:56:42 +01:00
|
|
|
fx.bcx.seal_all_blocks();
|
|
|
|
|
fx.bcx.finalize();
|
2018-08-14 18:52:43 +02:00
|
|
|
|
2019-05-14 16:12:58 +02:00
|
|
|
// Recover all necessary data from fx, before accessing func will prevent future access to it.
|
2022-08-24 18:40:58 +02:00
|
|
|
let symbol_name = fx.symbol_name;
|
2022-02-23 11:49:34 +01:00
|
|
|
let clif_comments = fx.clif_comments;
|
2022-08-24 18:40:58 +02:00
|
|
|
let func_debug_cx = fx.func_debug_cx;
|
2021-04-30 14:49:58 +02:00
|
|
|
|
|
|
|
|
fx.constants_cx.finalize(fx.tcx, &mut *fx.module);
|
2019-05-14 16:12:58 +02:00
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
if cx.should_write_ir {
|
|
|
|
|
crate::pretty_clif::write_clif_file(
|
|
|
|
|
tcx.output_filenames(()),
|
|
|
|
|
&symbol_name,
|
|
|
|
|
"unopt",
|
|
|
|
|
module.isa(),
|
|
|
|
|
&func,
|
|
|
|
|
&clif_comments,
|
|
|
|
|
);
|
|
|
|
|
}
|
2018-08-14 18:52:43 +02:00
|
|
|
|
2019-05-14 16:12:58 +02:00
|
|
|
// Verify function
|
2022-02-23 11:49:34 +01:00
|
|
|
verify_func(tcx, &clif_comments, &func);
|
|
|
|
|
|
2024-12-12 20:31:20 +00:00
|
|
|
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
|
2022-02-23 11:49:34 +01:00
|
|
|
}
|
|
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
pub(crate) fn compile_fn(
|
|
|
|
|
cx: &mut crate::CodegenCx,
|
2024-12-06 12:10:30 +00:00
|
|
|
profiler: &SelfProfilerRef,
|
2022-08-24 18:40:58 +02:00
|
|
|
cached_context: &mut Context,
|
2022-02-23 11:49:34 +01:00
|
|
|
module: &mut dyn Module,
|
2022-08-24 18:40:58 +02:00
|
|
|
codegened_func: CodegenedFunction,
|
2022-02-23 11:49:34 +01:00
|
|
|
) {
|
2023-02-09 12:38:16 +01:00
|
|
|
let _timer =
|
2024-12-06 12:10:30 +00:00
|
|
|
profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
|
2023-02-09 12:38:16 +01:00
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
let clif_comments = codegened_func.clif_comments;
|
2022-02-23 11:49:34 +01:00
|
|
|
|
|
|
|
|
// Store function in context
|
2022-08-24 18:40:58 +02:00
|
|
|
let context = cached_context;
|
2022-02-23 11:49:34 +01:00
|
|
|
context.clear();
|
2022-08-24 18:40:58 +02:00
|
|
|
context.func = codegened_func.func;
|
2019-12-28 12:41:03 +01:00
|
|
|
|
2022-07-25 16:07:57 +02:00
|
|
|
#[cfg(any())] // This is never true
|
|
|
|
|
let _clif_guard = {
|
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
|
|
let func_clone = context.func.clone();
|
|
|
|
|
let clif_comments_clone = clif_comments.clone();
|
|
|
|
|
let mut clif = String::new();
|
|
|
|
|
for flag in module.isa().flags().iter() {
|
|
|
|
|
writeln!(clif, "set {}", flag).unwrap();
|
|
|
|
|
}
|
|
|
|
|
write!(clif, "target {}", module.isa().triple().architecture.to_string()).unwrap();
|
|
|
|
|
for isa_flag in module.isa().isa_flags().iter() {
|
|
|
|
|
write!(clif, " {}", isa_flag).unwrap();
|
|
|
|
|
}
|
|
|
|
|
writeln!(clif, "\n").unwrap();
|
2023-06-15 17:56:01 +00:00
|
|
|
writeln!(clif, "; symbol {}", codegened_func.symbol_name).unwrap();
|
2022-07-25 16:07:57 +02:00
|
|
|
crate::PrintOnPanic(move || {
|
|
|
|
|
let mut clif = clif.clone();
|
|
|
|
|
::cranelift_codegen::write::decorate_function(
|
|
|
|
|
&mut &clif_comments_clone,
|
|
|
|
|
&mut clif,
|
|
|
|
|
&func_clone,
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
clif
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
2019-12-28 12:41:03 +01:00
|
|
|
// Define function
|
2024-12-06 12:10:30 +00:00
|
|
|
profiler.generic_activity("define function").run(|| {
|
2022-08-24 18:40:58 +02:00
|
|
|
context.want_disasm = cx.should_write_ir;
|
2023-07-22 13:32:34 +00:00
|
|
|
match module.define_function(codegened_func.func_id, context) {
|
|
|
|
|
Ok(()) => {}
|
|
|
|
|
Err(ModuleError::Compilation(CodegenError::ImplLimitExceeded)) => {
|
2023-12-18 11:15:13 +11:00
|
|
|
let early_dcx = rustc_session::EarlyDiagCtxt::new(
|
2023-07-22 13:32:34 +00:00
|
|
|
rustc_session::config::ErrorOutputType::default(),
|
|
|
|
|
);
|
2023-12-20 14:53:50 +11:00
|
|
|
early_dcx.early_fatal(format!(
|
2023-07-22 13:32:34 +00:00
|
|
|
"backend implementation limit exceeded while compiling {name}",
|
|
|
|
|
name = codegened_func.symbol_name
|
|
|
|
|
));
|
|
|
|
|
}
|
2025-04-15 14:42:32 +00:00
|
|
|
Err(ModuleError::Compilation(CodegenError::Verifier(err))) => {
|
|
|
|
|
let early_dcx = rustc_session::EarlyDiagCtxt::new(
|
|
|
|
|
rustc_session::config::ErrorOutputType::default(),
|
|
|
|
|
);
|
|
|
|
|
let _ = early_dcx.early_err(format!("{:?}", err));
|
|
|
|
|
let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error(
|
|
|
|
|
&context.func,
|
|
|
|
|
Some(Box::new(&clif_comments)),
|
|
|
|
|
err,
|
|
|
|
|
);
|
|
|
|
|
early_dcx.early_fatal(format!("cranelift verify error:\n{}", pretty_error));
|
|
|
|
|
}
|
2023-07-22 13:32:34 +00:00
|
|
|
Err(err) => {
|
|
|
|
|
panic!("Error while defining {name}: {err:?}", name = codegened_func.symbol_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-28 12:10:48 +02:00
|
|
|
});
|
2019-02-18 18:26:59 +01:00
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
if cx.should_write_ir {
|
|
|
|
|
// Write optimized function to file for debugging
|
|
|
|
|
crate::pretty_clif::write_clif_file(
|
|
|
|
|
&cx.output_filenames,
|
|
|
|
|
&codegened_func.symbol_name,
|
|
|
|
|
"opt",
|
|
|
|
|
module.isa(),
|
|
|
|
|
&context.func,
|
|
|
|
|
&clif_comments,
|
|
|
|
|
);
|
|
|
|
|
|
2023-04-29 12:00:43 +00:00
|
|
|
if let Some(disasm) = &context.compiled_code().unwrap().vcode {
|
2022-08-24 18:40:58 +02:00
|
|
|
crate::pretty_clif::write_ir_file(
|
|
|
|
|
&cx.output_filenames,
|
|
|
|
|
&format!("{}.vcode", codegened_func.symbol_name),
|
|
|
|
|
|file| file.write_all(disasm.as_bytes()),
|
|
|
|
|
)
|
|
|
|
|
}
|
2020-12-27 10:30:38 +01:00
|
|
|
}
|
|
|
|
|
|
2019-05-14 16:12:58 +02:00
|
|
|
// Define debuginfo for function
|
2020-08-22 18:53:34 +02:00
|
|
|
let debug_context = &mut cx.debug_context;
|
2024-12-06 12:10:30 +00:00
|
|
|
profiler.generic_activity("generate debug info").run(|| {
|
2020-06-13 17:03:34 +02:00
|
|
|
if let Some(debug_context) = debug_context {
|
2022-08-24 18:40:58 +02:00
|
|
|
codegened_func.func_debug_cx.unwrap().finalize(
|
|
|
|
|
debug_context,
|
|
|
|
|
codegened_func.func_id,
|
2020-08-28 12:10:48 +02:00
|
|
|
context,
|
|
|
|
|
);
|
2020-06-13 17:03:34 +02:00
|
|
|
}
|
2020-01-10 14:15:14 +01:00
|
|
|
});
|
2018-08-14 18:52:43 +02:00
|
|
|
}
|
2018-06-17 18:05:11 +02:00
|
|
|
|
2024-12-06 12:10:30 +00:00
|
|
|
fn verify_func(tcx: TyCtxt<'_>, writer: &crate::pretty_clif::CommentWriter, func: &Function) {
|
|
|
|
|
if !enable_verifier(tcx.sess) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-09 12:38:16 +01:00
|
|
|
tcx.prof.generic_activity("verify clif ir").run(|| {
|
2020-06-20 18:44:49 +02:00
|
|
|
let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder());
|
|
|
|
|
match cranelift_codegen::verify_function(&func, &flags) {
|
2020-01-10 14:15:14 +01:00
|
|
|
Ok(_) => {}
|
|
|
|
|
Err(err) => {
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().err(format!("{:?}", err));
|
2020-06-20 18:44:49 +02:00
|
|
|
let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error(
|
2020-01-10 14:15:14 +01:00
|
|
|
&func,
|
|
|
|
|
Some(Box::new(writer)),
|
|
|
|
|
err,
|
|
|
|
|
);
|
2023-12-18 22:21:37 +11:00
|
|
|
tcx.dcx().fatal(format!("cranelift verify error:\n{}", pretty_error));
|
2020-01-10 14:15:14 +01:00
|
|
|
}
|
2018-08-14 18:52:43 +02:00
|
|
|
}
|
2020-01-10 14:15:14 +01:00
|
|
|
});
|
2018-08-14 18:52:43 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-24 18:40:58 +02:00
|
|
|
fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|
|
|
|
let arg_uninhabited = fx
|
|
|
|
|
.mir
|
|
|
|
|
.args_iter()
|
2024-10-29 13:37:59 -07:00
|
|
|
.any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).is_uninhabited());
|
2022-08-24 18:40:58 +02:00
|
|
|
if arg_uninhabited {
|
|
|
|
|
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
|
|
|
|
|
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
2022-08-24 18:40:58 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2023-02-09 12:38:16 +01:00
|
|
|
fx.tcx
|
|
|
|
|
.prof
|
|
|
|
|
.generic_activity("codegen prelude")
|
|
|
|
|
.run(|| crate::abi::codegen_fn_prelude(fx, start_block));
|
2022-08-24 18:40:58 +02:00
|
|
|
|
2024-04-11 10:42:48 +00:00
|
|
|
let reachable_blocks = traversal::mono_reachable_as_bitset(fx.mir, fx.tcx, fx.instance);
|
|
|
|
|
|
|
|
|
|
for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() {
|
2020-02-14 18:23:29 +01:00
|
|
|
let block = fx.get_block(bb);
|
|
|
|
|
fx.bcx.switch_to_block(block);
|
2020-02-01 16:47:35 +01:00
|
|
|
|
2024-04-11 10:42:48 +00:00
|
|
|
if !reachable_blocks.contains(bb) {
|
|
|
|
|
// We want to skip this block, because it's not reachable. But we still create
|
|
|
|
|
// the block so terminators in other blocks can reference it.
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
2024-04-11 10:42:48 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-30 16:33:55 +02:00
|
|
|
if bb_data.is_cleanup {
|
|
|
|
|
// Unwinding after panicking is not supported
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-04-30 14:49:58 +02:00
|
|
|
// FIXME Once unwinding is supported and Cranelift supports marking blocks as cold, do
|
|
|
|
|
// so for cleanup blocks.
|
2020-02-01 16:47:35 +01:00
|
|
|
}
|
2018-06-17 18:05:11 +02:00
|
|
|
|
2018-07-20 13:51:34 +02:00
|
|
|
fx.bcx.ins().nop();
|
2018-06-17 18:05:11 +02:00
|
|
|
for stmt in &bb_data.statements {
|
2019-01-17 18:07:27 +01:00
|
|
|
fx.set_debug_loc(stmt.source_info);
|
2020-11-03 11:00:04 +01:00
|
|
|
codegen_stmt(fx, block, stmt);
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
|
2021-03-29 10:45:09 +02:00
|
|
|
if fx.clif_comments.enabled() {
|
2018-12-28 17:07:40 +01:00
|
|
|
let mut terminator_head = "\n".to_string();
|
2022-03-20 16:55:21 +01:00
|
|
|
with_no_trimmed_paths!({
|
|
|
|
|
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
|
|
|
|
|
});
|
2020-02-14 18:23:29 +01:00
|
|
|
let inst = fx.bcx.func.layout.last_inst(block).unwrap();
|
2025-05-20 12:16:04 +00:00
|
|
|
fx.add_post_comment(inst, terminator_head);
|
2018-12-28 17:07:40 +01:00
|
|
|
}
|
2018-07-20 13:51:34 +02:00
|
|
|
|
2021-09-04 19:25:09 +02:00
|
|
|
let source_info = bb_data.terminator().source_info;
|
|
|
|
|
fx.set_debug_loc(source_info);
|
2019-01-17 18:07:27 +01:00
|
|
|
|
2023-01-24 18:56:42 +01:00
|
|
|
let _print_guard =
|
|
|
|
|
crate::PrintOnPanic(|| format!("terminator {:?}", bb_data.terminator().kind));
|
|
|
|
|
|
2018-07-20 13:51:34 +02:00
|
|
|
match &bb_data.terminator().kind {
|
2018-06-17 18:05:11 +02:00
|
|
|
TerminatorKind::Goto { target } => {
|
2020-03-30 18:44:14 +02:00
|
|
|
if let TerminatorKind::Return = fx.mir[*target].terminator().kind {
|
|
|
|
|
let mut can_immediately_return = true;
|
|
|
|
|
for stmt in &fx.mir[*target].statements {
|
|
|
|
|
if let StatementKind::StorageDead(_) = stmt.kind {
|
|
|
|
|
} else {
|
|
|
|
|
// FIXME Can sometimes happen, see rust-lang/rust#70531
|
|
|
|
|
can_immediately_return = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if can_immediately_return {
|
|
|
|
|
crate::abi::codegen_return(fx);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 18:23:29 +01:00
|
|
|
let block = fx.get_block(*target);
|
|
|
|
|
fx.bcx.ins().jump(block, &[]);
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
TerminatorKind::Return => {
|
2018-08-11 11:01:48 +02:00
|
|
|
crate::abi::codegen_return(fx);
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
2025-04-09 13:50:59 +00:00
|
|
|
TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
|
2023-03-16 00:00:00 +00:00
|
|
|
if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() {
|
|
|
|
|
let target = fx.get_block(*target);
|
|
|
|
|
fx.bcx.ins().jump(target, &[]);
|
|
|
|
|
continue;
|
2019-08-20 13:37:49 +02:00
|
|
|
}
|
2020-11-03 11:00:04 +01:00
|
|
|
let cond = codegen_operand(fx, cond).load_scalar(fx);
|
2020-01-11 17:57:18 +01:00
|
|
|
|
2020-02-14 18:23:29 +01:00
|
|
|
let target = fx.get_block(*target);
|
|
|
|
|
let failure = fx.bcx.create_block();
|
2020-01-11 17:57:18 +01:00
|
|
|
|
2018-07-20 13:51:34 +02:00
|
|
|
if *expected {
|
2023-03-15 14:41:48 +00:00
|
|
|
fx.bcx.ins().brif(cond, target, &[], failure, &[]);
|
2018-08-09 15:36:02 +02:00
|
|
|
} else {
|
2023-03-15 14:41:48 +00:00
|
|
|
fx.bcx.ins().brif(cond, failure, &[], target, &[]);
|
2018-06-30 16:27:11 +02:00
|
|
|
};
|
2020-01-10 12:14:28 +01:00
|
|
|
|
|
|
|
|
fx.bcx.switch_to_block(failure);
|
2020-09-21 14:56:19 +02:00
|
|
|
fx.bcx.ins().nop();
|
2020-04-25 19:07:25 +02:00
|
|
|
|
2023-05-01 18:30:54 -04:00
|
|
|
match &**msg {
|
2020-04-25 19:07:25 +02:00
|
|
|
AssertKind::BoundsCheck { ref len, ref index } => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let len = codegen_operand(fx, len).load_scalar(fx);
|
|
|
|
|
let index = codegen_operand(fx, index).load_scalar(fx);
|
2022-05-15 12:32:19 +02:00
|
|
|
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
2020-09-29 13:22:01 +02:00
|
|
|
|
|
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
|
|
|
|
rustc_hir::LangItem::PanicBoundsCheck,
|
|
|
|
|
&[index, len, location],
|
2025-04-09 13:50:59 +00:00
|
|
|
*unwind,
|
2025-06-04 06:26:56 +00:00
|
|
|
source_info.span,
|
2020-09-29 13:22:01 +02:00
|
|
|
);
|
2020-04-25 19:07:25 +02:00
|
|
|
}
|
2022-11-10 11:37:28 -05:00
|
|
|
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
|
|
|
|
|
let required = codegen_operand(fx, required).load_scalar(fx);
|
|
|
|
|
let found = codegen_operand(fx, found).load_scalar(fx);
|
|
|
|
|
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
|
|
|
|
|
|
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
2023-07-22 13:32:34 +00:00
|
|
|
rustc_hir::LangItem::PanicMisalignedPointerDereference,
|
2022-11-10 11:37:28 -05:00
|
|
|
&[required, found, location],
|
2025-04-09 13:50:59 +00:00
|
|
|
*unwind,
|
2025-06-04 06:26:56 +00:00
|
|
|
source_info.span,
|
2022-11-10 11:37:28 -05:00
|
|
|
);
|
|
|
|
|
}
|
2024-12-17 13:00:22 +00:00
|
|
|
AssertKind::NullPointerDereference => {
|
|
|
|
|
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
|
|
|
|
|
|
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
|
|
|
|
rustc_hir::LangItem::PanicNullPointerDereference,
|
|
|
|
|
&[location],
|
2025-04-09 13:50:59 +00:00
|
|
|
*unwind,
|
2025-06-04 06:26:56 +00:00
|
|
|
source_info.span,
|
2024-12-17 13:00:22 +00:00
|
|
|
)
|
|
|
|
|
}
|
2025-05-15 19:09:13 +00:00
|
|
|
AssertKind::InvalidEnumConstruction(source) => {
|
|
|
|
|
let source = codegen_operand(fx, source).load_scalar(fx);
|
|
|
|
|
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
|
|
|
|
|
|
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
|
|
|
|
rustc_hir::LangItem::PanicInvalidEnumConstruction,
|
|
|
|
|
&[source, location],
|
|
|
|
|
*unwind,
|
|
|
|
|
source_info.span,
|
|
|
|
|
)
|
|
|
|
|
}
|
2020-04-25 19:07:25 +02:00
|
|
|
_ => {
|
2024-03-17 22:26:39 -04:00
|
|
|
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
|
|
|
|
|
|
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
|
|
|
|
msg.panic_function(),
|
|
|
|
|
&[location],
|
2025-04-09 13:50:59 +00:00
|
|
|
*unwind,
|
2025-06-04 06:26:56 +00:00
|
|
|
source_info.span,
|
2024-03-17 22:26:39 -04:00
|
|
|
);
|
2020-04-25 19:07:25 +02:00
|
|
|
}
|
2020-09-29 13:22:01 +02:00
|
|
|
}
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 16:03:27 -08:00
|
|
|
TerminatorKind::SwitchInt { discr, targets } => {
|
|
|
|
|
let discr = codegen_operand(fx, discr);
|
|
|
|
|
let switch_ty = discr.layout().ty;
|
|
|
|
|
let discr = discr.load_scalar(fx);
|
2020-08-30 13:02:53 +02:00
|
|
|
|
2020-12-27 10:30:38 +01:00
|
|
|
let use_bool_opt = switch_ty.kind() == fx.tcx.types.bool.kind()
|
|
|
|
|
|| (targets.iter().count() == 1 && targets.iter().next().unwrap().0 == 0);
|
|
|
|
|
if use_bool_opt {
|
2020-10-15 10:34:13 +02:00
|
|
|
assert_eq!(targets.iter().count(), 1);
|
|
|
|
|
let (then_value, then_block) = targets.iter().next().unwrap();
|
|
|
|
|
let then_block = fx.get_block(then_block);
|
|
|
|
|
let else_block = fx.get_block(targets.otherwise());
|
|
|
|
|
let test_zero = match then_value {
|
|
|
|
|
0 => true,
|
|
|
|
|
1 => false,
|
|
|
|
|
_ => unreachable!("{:?}", targets),
|
2020-08-30 13:02:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let (discr, is_inverted) =
|
|
|
|
|
crate::optimize::peephole::maybe_unwrap_bool_not(&mut fx.bcx, discr);
|
|
|
|
|
let test_zero = if is_inverted { !test_zero } else { test_zero };
|
2020-12-27 10:30:38 +01:00
|
|
|
if let Some(taken) = crate::optimize::peephole::maybe_known_branch_taken(
|
|
|
|
|
&fx.bcx, discr, test_zero,
|
|
|
|
|
) {
|
|
|
|
|
if taken {
|
|
|
|
|
fx.bcx.ins().jump(then_block, &[]);
|
|
|
|
|
} else {
|
|
|
|
|
fx.bcx.ins().jump(else_block, &[]);
|
|
|
|
|
}
|
2020-08-30 13:02:53 +02:00
|
|
|
} else {
|
2020-12-27 10:30:38 +01:00
|
|
|
if test_zero {
|
2023-03-15 14:41:48 +00:00
|
|
|
fx.bcx.ins().brif(discr, else_block, &[], then_block, &[]);
|
2020-12-27 10:30:38 +01:00
|
|
|
} else {
|
2023-03-15 14:41:48 +00:00
|
|
|
fx.bcx.ins().brif(discr, then_block, &[], else_block, &[]);
|
2020-12-27 10:30:38 +01:00
|
|
|
}
|
2020-08-30 13:02:53 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
let mut switch = ::cranelift_frontend::Switch::new();
|
2020-10-15 10:34:13 +02:00
|
|
|
for (value, block) in targets.iter() {
|
|
|
|
|
let block = fx.get_block(block);
|
|
|
|
|
switch.set_entry(value, block);
|
2020-08-30 13:02:53 +02:00
|
|
|
}
|
2020-10-15 10:34:13 +02:00
|
|
|
let otherwise_block = fx.get_block(targets.otherwise());
|
2020-08-30 13:02:53 +02:00
|
|
|
switch.emit(&mut fx.bcx, discr, otherwise_block);
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
TerminatorKind::Call {
|
|
|
|
|
func,
|
|
|
|
|
args,
|
|
|
|
|
destination,
|
2022-04-16 09:27:54 -04:00
|
|
|
target,
|
2020-06-12 18:41:50 +02:00
|
|
|
fn_span,
|
2025-04-09 13:50:59 +00:00
|
|
|
unwind,
|
2023-06-18 05:24:38 +00:00
|
|
|
call_source: _,
|
2018-07-31 12:25:16 +02:00
|
|
|
} => {
|
2023-02-09 12:38:16 +01:00
|
|
|
fx.tcx.prof.generic_activity("codegen call").run(|| {
|
2022-05-15 12:32:19 +02:00
|
|
|
crate::abi::codegen_terminator_call(
|
|
|
|
|
fx,
|
|
|
|
|
mir::SourceInfo { span: *fn_span, ..source_info },
|
|
|
|
|
func,
|
|
|
|
|
args,
|
|
|
|
|
*destination,
|
2022-04-16 09:27:54 -04:00
|
|
|
*target,
|
2025-04-09 13:50:59 +00:00
|
|
|
*unwind,
|
2022-05-15 12:32:19 +02:00
|
|
|
)
|
2020-08-28 12:10:48 +02:00
|
|
|
});
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
2024-02-15 19:54:37 +00:00
|
|
|
// FIXME(explicit_tail_calls): add support for tail calls to the cranelift backend, once cranelift supports tail calls
|
|
|
|
|
TerminatorKind::TailCall { fn_span, .. } => span_bug!(
|
|
|
|
|
*fn_span,
|
|
|
|
|
"tail calls are not yet supported in `rustc_codegen_cranelift` backend"
|
|
|
|
|
),
|
2020-05-18 11:35:23 +02:00
|
|
|
TerminatorKind::InlineAsm {
|
2024-09-05 19:45:40 +02:00
|
|
|
asm_macro: _,
|
2020-05-18 11:35:23 +02:00
|
|
|
template,
|
|
|
|
|
operands,
|
2020-07-10 14:45:45 +02:00
|
|
|
options,
|
2023-12-26 15:28:42 +00:00
|
|
|
targets,
|
2020-06-04 19:57:12 +02:00
|
|
|
line_spans: _,
|
2022-10-08 23:47:59 +01:00
|
|
|
unwind: _,
|
2020-05-18 11:35:23 +02:00
|
|
|
} => {
|
2021-09-04 22:14:09 +02:00
|
|
|
if options.contains(InlineAsmOptions::MAY_UNWIND) {
|
2023-12-18 22:21:37 +11:00
|
|
|
fx.tcx.dcx().span_fatal(
|
2021-09-04 19:25:09 +02:00
|
|
|
source_info.span,
|
|
|
|
|
"cranelift doesn't support unwinding from inline assembly.",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-26 15:28:42 +00:00
|
|
|
let have_labels = if options.contains(InlineAsmOptions::NORETURN) {
|
|
|
|
|
!targets.is_empty()
|
|
|
|
|
} else {
|
|
|
|
|
targets.len() > 1
|
|
|
|
|
};
|
|
|
|
|
if have_labels {
|
|
|
|
|
fx.tcx.dcx().span_fatal(
|
|
|
|
|
source_info.span,
|
|
|
|
|
"cranelift doesn't support labels in inline assembly.",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-16 21:15:07 +00:00
|
|
|
crate::inline_asm::codegen_inline_asm_terminator(
|
2020-07-10 14:45:45 +02:00
|
|
|
fx,
|
2021-09-04 19:25:09 +02:00
|
|
|
source_info.span,
|
2020-07-10 14:45:45 +02:00
|
|
|
template,
|
|
|
|
|
operands,
|
|
|
|
|
*options,
|
2023-12-26 15:28:42 +00:00
|
|
|
targets.get(0).copied(),
|
2020-07-10 14:45:45 +02:00
|
|
|
);
|
2020-05-18 11:35:23 +02:00
|
|
|
}
|
2023-08-21 09:57:10 +02:00
|
|
|
TerminatorKind::UnwindTerminate(reason) => {
|
2025-06-04 06:26:56 +00:00
|
|
|
codegen_unwind_terminate(fx, source_info.span, *reason);
|
2023-01-24 18:56:42 +01:00
|
|
|
}
|
2023-08-19 13:10:25 +02:00
|
|
|
TerminatorKind::UnwindResume => {
|
2022-03-20 16:55:21 +01:00
|
|
|
// FIXME implement unwinding
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
2019-03-23 13:06:35 +01:00
|
|
|
}
|
|
|
|
|
TerminatorKind::Unreachable => {
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.set_cold_block(block);
|
|
|
|
|
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
2018-06-17 19:10:00 +02:00
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
TerminatorKind::Yield { .. }
|
2020-06-11 13:12:35 +02:00
|
|
|
| TerminatorKind::FalseEdge { .. }
|
2018-09-11 19:27:57 +02:00
|
|
|
| TerminatorKind::FalseUnwind { .. }
|
2023-10-19 16:06:43 +00:00
|
|
|
| TerminatorKind::CoroutineDrop => {
|
2020-11-03 11:00:04 +01:00
|
|
|
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
|
2018-06-18 18:39:07 +02:00
|
|
|
}
|
2025-04-30 13:12:22 +00:00
|
|
|
TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
|
2024-08-26 16:45:15 +03:00
|
|
|
assert!(
|
|
|
|
|
async_fut.is_none() && drop.is_none(),
|
|
|
|
|
"Async Drop must be expanded or reset to sync before codegen"
|
|
|
|
|
);
|
2020-11-03 11:00:04 +01:00
|
|
|
let drop_place = codegen_place(fx, *place);
|
2025-04-09 13:50:59 +00:00
|
|
|
crate::abi::codegen_drop(fx, source_info, drop_place, *target, *unwind);
|
2018-06-28 20:27:43 +02:00
|
|
|
}
|
2018-06-30 16:27:11 +02:00
|
|
|
};
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-02 20:18:04 +00:00
|
|
|
fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: &Statement<'tcx>) {
|
2020-06-20 18:44:49 +02:00
|
|
|
let _print_guard = crate::PrintOnPanic(|| format!("stmt {:?}", stmt));
|
2018-07-14 16:39:49 +02:00
|
|
|
|
2019-01-17 18:07:27 +01:00
|
|
|
fx.set_debug_loc(stmt.source_info);
|
|
|
|
|
|
2018-09-05 20:04:21 +02:00
|
|
|
match &stmt.kind {
|
|
|
|
|
StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful
|
|
|
|
|
_ => {
|
2021-03-29 10:45:09 +02:00
|
|
|
if fx.clif_comments.enabled() {
|
|
|
|
|
let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap();
|
2023-04-29 12:00:43 +00:00
|
|
|
with_no_trimmed_paths!({
|
2025-05-20 12:16:04 +00:00
|
|
|
fx.add_post_comment(inst, format!("{:?}", stmt));
|
2023-04-29 12:00:43 +00:00
|
|
|
});
|
2021-03-29 10:45:09 +02:00
|
|
|
}
|
2018-09-05 20:04:21 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-06-30 16:27:11 +02:00
|
|
|
|
2018-06-17 18:05:11 +02:00
|
|
|
match &stmt.kind {
|
2021-03-05 19:12:59 +01:00
|
|
|
StatementKind::SetDiscriminant { place, variant_index } => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let place = codegen_place(fx, **place);
|
2019-08-14 12:01:41 +02:00
|
|
|
crate::discriminant::codegen_set_discriminant(fx, place, *variant_index);
|
2018-06-24 14:29:56 +02:00
|
|
|
}
|
2019-09-14 11:21:18 +02:00
|
|
|
StatementKind::Assign(to_place_and_rval) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let lval = codegen_place(fx, to_place_and_rval.0);
|
2018-06-26 19:44:19 +02:00
|
|
|
let dest_layout = lval.layout();
|
2020-10-28 08:25:06 +01:00
|
|
|
match to_place_and_rval.1 {
|
|
|
|
|
Rvalue::Use(ref operand) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let val = codegen_operand(fx, operand);
|
2018-06-26 19:44:19 +02:00
|
|
|
lval.write_cvalue(fx, val);
|
2018-06-27 16:01:30 +02:00
|
|
|
}
|
2022-06-13 16:37:41 +03:00
|
|
|
Rvalue::CopyForDeref(place) => {
|
|
|
|
|
let cplace = codegen_place(fx, place);
|
|
|
|
|
let val = cplace.to_cvalue(fx);
|
|
|
|
|
lval.write_cvalue(fx, val)
|
|
|
|
|
}
|
2024-08-12 10:57:57 +02:00
|
|
|
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
|
2020-10-28 08:25:06 +01:00
|
|
|
let place = codegen_place(fx, place);
|
2020-08-25 18:31:59 +02:00
|
|
|
let ref_ = place.place_ref(fx, lval.layout());
|
|
|
|
|
lval.write_cvalue(fx, ref_);
|
2018-06-27 16:01:30 +02:00
|
|
|
}
|
2020-06-04 19:57:12 +02:00
|
|
|
Rvalue::ThreadLocalRef(def_id) => {
|
2020-10-28 08:25:06 +01:00
|
|
|
let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout());
|
2020-06-04 19:57:12 +02:00
|
|
|
lval.write_cvalue(fx, val);
|
|
|
|
|
}
|
2021-03-29 10:45:09 +02:00
|
|
|
Rvalue::BinaryOp(bin_op, ref lhs_rhs) => {
|
|
|
|
|
let lhs = codegen_operand(fx, &lhs_rhs.0);
|
|
|
|
|
let rhs = codegen_operand(fx, &lhs_rhs.1);
|
2018-06-23 18:26:54 +02:00
|
|
|
|
2024-05-16 02:07:31 -07:00
|
|
|
let res = if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
|
|
|
|
crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs)
|
|
|
|
|
} else {
|
|
|
|
|
crate::num::codegen_binop(fx, bin_op, lhs, rhs)
|
|
|
|
|
};
|
2018-06-28 20:13:51 +02:00
|
|
|
lval.write_cvalue(fx, res);
|
2018-06-20 15:29:50 +02:00
|
|
|
}
|
2020-10-28 08:25:06 +01:00
|
|
|
Rvalue::UnaryOp(un_op, ref operand) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2018-09-14 19:49:33 +02:00
|
|
|
let layout = operand.layout();
|
2018-06-27 15:57:52 +02:00
|
|
|
let res = match un_op {
|
2024-04-21 16:11:01 -07:00
|
|
|
UnOp::Not => {
|
|
|
|
|
let val = operand.load_scalar(fx);
|
|
|
|
|
match layout.ty.kind() {
|
|
|
|
|
ty::Bool => {
|
|
|
|
|
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
|
|
|
|
|
CValue::by_val(res, layout)
|
|
|
|
|
}
|
|
|
|
|
ty::Uint(_) | ty::Int(_) => {
|
|
|
|
|
CValue::by_val(fx.bcx.ins().bnot(val), layout)
|
|
|
|
|
}
|
|
|
|
|
_ => unreachable!("un op Not for {:?}", layout.ty),
|
2018-09-14 19:49:33 +02:00
|
|
|
}
|
2024-04-21 16:11:01 -07:00
|
|
|
}
|
|
|
|
|
UnOp::Neg => {
|
|
|
|
|
let val = operand.load_scalar(fx);
|
|
|
|
|
match layout.ty.kind() {
|
|
|
|
|
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
|
2025-05-23 15:51:51 +01:00
|
|
|
// FIXME(bytecodealliance/wasmtime#8312): Remove
|
|
|
|
|
// once backend lowerings have been added to
|
|
|
|
|
// Cranelift.
|
|
|
|
|
ty::Float(FloatTy::F16) => {
|
|
|
|
|
CValue::by_val(codegen_f16_f128::neg_f16(fx, val), layout)
|
|
|
|
|
}
|
|
|
|
|
ty::Float(FloatTy::F128) => {
|
|
|
|
|
CValue::by_val(codegen_f16_f128::neg_f128(fx, val), layout)
|
|
|
|
|
}
|
2024-04-21 16:11:01 -07:00
|
|
|
ty::Float(_) => CValue::by_val(fx.bcx.ins().fneg(val), layout),
|
|
|
|
|
_ => unreachable!("un op Neg for {:?}", layout.ty),
|
2020-08-28 12:10:48 +02:00
|
|
|
}
|
2024-04-21 16:11:01 -07:00
|
|
|
}
|
2024-10-29 13:37:59 -07:00
|
|
|
UnOp::PtrMetadata => match layout.backend_repr {
|
|
|
|
|
BackendRepr::Scalar(_) => CValue::zst(dest_layout),
|
|
|
|
|
BackendRepr::ScalarPair(_, _) => {
|
2024-04-21 16:11:01 -07:00
|
|
|
CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout)
|
|
|
|
|
}
|
|
|
|
|
_ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"),
|
2018-07-31 12:25:16 +02:00
|
|
|
},
|
2018-06-27 15:57:52 +02:00
|
|
|
};
|
2019-10-06 15:51:43 +02:00
|
|
|
lval.write_cvalue(fx, res);
|
2018-06-27 15:57:52 +02:00
|
|
|
}
|
2020-11-27 20:48:53 +01:00
|
|
|
Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
|
2020-11-27 20:48:53 +01:00
|
|
|
ref operand,
|
|
|
|
|
to_ty,
|
|
|
|
|
) => {
|
2020-10-28 08:25:06 +01:00
|
|
|
let from_ty = fx.monomorphize(operand.ty(&fx.mir.local_decls, fx.tcx));
|
2019-12-17 16:58:34 +01:00
|
|
|
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
2020-09-05 10:38:49 +02:00
|
|
|
match *from_ty.kind() {
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::FnDef(def_id, args) => {
|
2019-02-03 13:29:04 +01:00
|
|
|
let func_ref = fx.get_function_ref(
|
2020-08-28 12:10:48 +02:00
|
|
|
Instance::resolve_for_fn_ptr(
|
|
|
|
|
fx.tcx,
|
2024-11-15 13:53:31 +01:00
|
|
|
ty::TypingEnv::fully_monomorphized(),
|
2020-08-28 12:10:48 +02:00
|
|
|
def_id,
|
2023-07-11 22:35:29 +01:00
|
|
|
args,
|
2020-08-28 12:10:48 +02:00
|
|
|
)
|
2024-12-04 21:03:12 -05:00
|
|
|
.unwrap(),
|
2019-02-03 13:29:04 +01:00
|
|
|
);
|
|
|
|
|
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
|
2019-12-17 16:58:34 +01:00
|
|
|
lval.write_cvalue(fx, CValue::by_val(func_addr, to_layout));
|
2019-02-03 13:29:04 +01:00
|
|
|
}
|
2019-12-17 16:58:34 +01:00
|
|
|
_ => bug!("Trying to ReifyFnPointer on non FnDef {:?}", from_ty),
|
2019-02-03 13:29:04 +01:00
|
|
|
}
|
2018-06-20 15:29:50 +02:00
|
|
|
}
|
2020-11-27 20:48:53 +01:00
|
|
|
Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer, _),
|
2020-11-27 20:48:53 +01:00
|
|
|
ref operand,
|
|
|
|
|
to_ty,
|
|
|
|
|
) => {
|
2019-12-17 16:58:34 +01:00
|
|
|
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2020-03-29 11:52:30 +02:00
|
|
|
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
2018-06-23 18:26:54 +02:00
|
|
|
}
|
2024-06-14 23:01:22 -07:00
|
|
|
Rvalue::Cast(
|
|
|
|
|
CastKind::PointerCoercion(
|
|
|
|
|
PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer,
|
2024-09-15 19:35:06 +02:00
|
|
|
_,
|
2024-06-14 23:01:22 -07:00
|
|
|
),
|
|
|
|
|
..,
|
|
|
|
|
) => {
|
|
|
|
|
bug!(
|
|
|
|
|
"{:?} is for borrowck, and should never appear in codegen",
|
|
|
|
|
to_place_and_rval.1
|
|
|
|
|
);
|
|
|
|
|
}
|
2022-06-01 13:24:44 -04:00
|
|
|
Rvalue::Cast(
|
2022-10-04 21:39:43 +03:00
|
|
|
CastKind::IntToInt
|
|
|
|
|
| CastKind::FloatToFloat
|
|
|
|
|
| CastKind::FloatToInt
|
|
|
|
|
| CastKind::IntToFloat
|
|
|
|
|
| CastKind::FnPtrToPtr
|
|
|
|
|
| CastKind::PtrToPtr
|
2024-04-03 15:17:00 +02:00
|
|
|
| CastKind::PointerExposeProvenance
|
2024-03-23 12:21:20 +01:00
|
|
|
| CastKind::PointerWithExposedProvenance,
|
2022-06-01 13:24:44 -04:00
|
|
|
ref operand,
|
|
|
|
|
to_ty,
|
|
|
|
|
) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2018-07-18 16:22:29 +02:00
|
|
|
let from_ty = operand.layout().ty;
|
2019-09-14 17:53:36 +02:00
|
|
|
let to_ty = fx.monomorphize(to_ty);
|
2019-02-24 17:25:13 +01:00
|
|
|
|
2024-10-03 15:05:23 +02:00
|
|
|
fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
2025-03-03 12:43:05 +00:00
|
|
|
ty.builtin_deref(true).is_some_and(|pointee_ty| {
|
|
|
|
|
fx.tcx
|
|
|
|
|
.type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized())
|
|
|
|
|
})
|
2019-02-24 17:25:13 +01:00
|
|
|
}
|
|
|
|
|
|
2024-10-03 15:05:23 +02:00
|
|
|
if is_wide_ptr(fx, from_ty) {
|
|
|
|
|
if is_wide_ptr(fx, to_ty) {
|
|
|
|
|
// wide-ptr -> wide-ptr
|
2020-03-29 11:52:30 +02:00
|
|
|
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
2019-02-24 17:25:13 +01:00
|
|
|
} else {
|
2024-10-03 15:05:23 +02:00
|
|
|
// wide-ptr -> thin-ptr
|
2019-03-02 21:09:28 +01:00
|
|
|
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
2019-06-11 15:32:30 +02:00
|
|
|
lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout))
|
2019-02-16 16:37:30 +01:00
|
|
|
}
|
2019-02-24 17:25:13 +01:00
|
|
|
} else {
|
|
|
|
|
let to_clif_ty = fx.clif_type(to_ty).unwrap();
|
|
|
|
|
let from = operand.load_scalar(fx);
|
|
|
|
|
|
2019-08-31 22:58:09 +05:30
|
|
|
let res = clif_int_or_float_cast(
|
|
|
|
|
fx,
|
|
|
|
|
from,
|
|
|
|
|
type_sign(from_ty),
|
|
|
|
|
to_clif_ty,
|
|
|
|
|
type_sign(to_ty),
|
|
|
|
|
);
|
2019-06-11 15:32:30 +02:00
|
|
|
lval.write_cvalue(fx, CValue::by_val(res, dest_layout));
|
2018-07-18 14:21:13 +02:00
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
}
|
2020-08-28 12:10:48 +02:00
|
|
|
Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
|
2020-10-28 08:25:06 +01:00
|
|
|
ref operand,
|
2020-08-28 12:10:48 +02:00
|
|
|
_to_ty,
|
|
|
|
|
) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2020-09-05 10:38:49 +02:00
|
|
|
match *operand.layout().ty.kind() {
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Closure(def_id, args) => {
|
2019-06-06 20:31:09 +02:00
|
|
|
let instance = Instance::resolve_closure(
|
2020-08-22 16:47:31 +02:00
|
|
|
fx.tcx,
|
2019-02-24 18:15:23 +01:00
|
|
|
def_id,
|
2023-07-11 22:35:29 +01:00
|
|
|
args,
|
2019-02-24 18:15:23 +01:00
|
|
|
ty::ClosureKind::FnOnce,
|
2024-12-04 21:03:12 -05:00
|
|
|
);
|
2019-02-24 18:15:23 +01:00
|
|
|
let func_ref = fx.get_function_ref(instance);
|
|
|
|
|
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
|
2019-06-11 15:32:30 +02:00
|
|
|
lval.write_cvalue(fx, CValue::by_val(func_addr, lval.layout()));
|
2019-02-24 18:15:23 +01:00
|
|
|
}
|
2019-08-31 22:58:09 +05:30
|
|
|
_ => bug!("{} cannot be cast to a fn ptr", operand.layout().ty),
|
2019-02-24 18:15:23 +01:00
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
}
|
2023-07-05 20:07:03 +02:00
|
|
|
Rvalue::Cast(
|
2024-09-15 19:35:06 +02:00
|
|
|
CastKind::PointerCoercion(PointerCoercion::Unsize, _),
|
2023-07-05 20:07:03 +02:00
|
|
|
ref operand,
|
|
|
|
|
_to_ty,
|
|
|
|
|
) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2023-04-29 12:00:43 +00:00
|
|
|
crate::unsize::coerce_unsized_into(fx, operand, lval);
|
2018-07-31 12:25:16 +02:00
|
|
|
}
|
2023-02-24 18:32:52 -08:00
|
|
|
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
|
|
|
|
|
let operand = codegen_operand(fx, operand);
|
|
|
|
|
lval.write_cvalue_transmute(fx, operand);
|
|
|
|
|
}
|
2018-06-23 18:26:54 +02:00
|
|
|
Rvalue::Discriminant(place) => {
|
2020-10-28 08:25:06 +01:00
|
|
|
let place = codegen_place(fx, place);
|
2019-08-18 16:19:33 +02:00
|
|
|
let value = place.to_cvalue(fx);
|
2022-08-24 18:40:58 +02:00
|
|
|
crate::discriminant::codegen_get_discriminant(fx, lval, value, dest_layout);
|
2018-06-20 15:29:50 +02:00
|
|
|
}
|
2020-10-28 08:25:06 +01:00
|
|
|
Rvalue::Repeat(ref operand, times) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
2024-09-20 20:38:11 -04:00
|
|
|
let times = fx
|
|
|
|
|
.monomorphize(times)
|
|
|
|
|
.try_to_target_usize(fx.tcx)
|
|
|
|
|
.expect("expected monomorphic const in codegen");
|
2021-03-29 10:45:09 +02:00
|
|
|
if operand.layout().size.bytes() == 0 {
|
|
|
|
|
// Do nothing for ZST's
|
|
|
|
|
} else if fx.clif_type(operand.layout().ty) == Some(types::I8) {
|
2020-09-14 11:32:18 +02:00
|
|
|
let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64);
|
|
|
|
|
// FIXME use emit_small_memset where possible
|
|
|
|
|
let addr = lval.to_ptr().get_addr(fx);
|
|
|
|
|
let val = operand.load_scalar(fx);
|
2021-12-20 18:56:35 +01:00
|
|
|
fx.bcx.call_memset(fx.target_config, addr, val, times);
|
2020-09-14 11:32:18 +02:00
|
|
|
} else {
|
|
|
|
|
let loop_block = fx.bcx.create_block();
|
2020-09-14 11:44:53 +02:00
|
|
|
let loop_block2 = fx.bcx.create_block();
|
2020-09-14 11:32:18 +02:00
|
|
|
let done_block = fx.bcx.create_block();
|
|
|
|
|
let index = fx.bcx.append_block_param(loop_block, fx.pointer_type);
|
|
|
|
|
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
|
2025-05-05 15:07:38 +00:00
|
|
|
fx.bcx.ins().jump(loop_block, &[zero.into()]);
|
2020-09-14 11:32:18 +02:00
|
|
|
|
|
|
|
|
fx.bcx.switch_to_block(loop_block);
|
2020-09-14 11:44:53 +02:00
|
|
|
let done = fx.bcx.ins().icmp_imm(IntCC::Equal, index, times as i64);
|
2023-03-15 14:41:48 +00:00
|
|
|
fx.bcx.ins().brif(done, done_block, &[], loop_block2, &[]);
|
2020-09-14 11:44:53 +02:00
|
|
|
|
|
|
|
|
fx.bcx.switch_to_block(loop_block2);
|
2018-08-08 12:30:25 +02:00
|
|
|
let to = lval.place_index(fx, index);
|
|
|
|
|
to.write_cvalue(fx, operand);
|
2020-09-14 11:32:18 +02:00
|
|
|
let index = fx.bcx.ins().iadd_imm(index, 1);
|
2025-05-05 15:07:38 +00:00
|
|
|
fx.bcx.ins().jump(loop_block, &[index.into()]);
|
2020-09-14 11:32:18 +02:00
|
|
|
|
|
|
|
|
fx.bcx.switch_to_block(done_block);
|
2020-09-21 14:56:19 +02:00
|
|
|
fx.bcx.ins().nop();
|
2018-08-08 12:30:25 +02:00
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
}
|
2021-09-06 18:33:23 +01:00
|
|
|
Rvalue::ShallowInitBox(ref operand, content_ty) => {
|
|
|
|
|
let content_ty = fx.monomorphize(content_ty);
|
2023-07-05 20:13:26 +01:00
|
|
|
let box_layout = fx.layout_of(Ty::new_box(fx.tcx, content_ty));
|
2021-09-06 18:33:23 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
|
|
|
|
let operand = operand.load_scalar(fx);
|
|
|
|
|
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
|
|
|
|
|
}
|
2022-09-11 00:37:49 -07:00
|
|
|
Rvalue::NullaryOp(ref null_op, ty) => {
|
2024-11-19 16:13:55 +01:00
|
|
|
assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
|
2021-09-07 16:06:07 +01:00
|
|
|
let layout = fx.layout_of(fx.monomorphize(ty));
|
|
|
|
|
let val = match null_op {
|
|
|
|
|
NullOp::SizeOf => layout.size.bytes(),
|
2025-09-28 14:40:39 -07:00
|
|
|
NullOp::AlignOf => layout.align.bytes(),
|
2024-06-08 11:26:56 +02:00
|
|
|
NullOp::OffsetOf(fields) => fx
|
|
|
|
|
.tcx
|
2024-11-15 13:53:31 +01:00
|
|
|
.offset_of_subfield(
|
|
|
|
|
ty::TypingEnv::fully_monomorphized(),
|
|
|
|
|
layout,
|
|
|
|
|
fields.iter(),
|
|
|
|
|
)
|
2024-06-08 11:26:56 +02:00
|
|
|
.bytes(),
|
2024-03-17 10:12:25 +01:00
|
|
|
NullOp::UbChecks => {
|
2024-04-03 08:54:03 -04:00
|
|
|
let val = fx.tcx.sess.ub_checks();
|
2024-02-07 10:26:00 -05:00
|
|
|
let val = CValue::by_val(
|
2025-01-15 13:54:04 -08:00
|
|
|
fx.bcx.ins().iconst(types::I8, i64::from(val)),
|
2024-02-07 10:26:00 -05:00
|
|
|
fx.layout_of(fx.tcx.types.bool),
|
2024-12-02 20:35:13 +00:00
|
|
|
);
|
|
|
|
|
lval.write_cvalue(fx, val);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
NullOp::ContractChecks => {
|
|
|
|
|
let val = fx.tcx.sess.contract_checks();
|
|
|
|
|
let val = CValue::by_val(
|
2025-01-15 13:54:04 -08:00
|
|
|
fx.bcx.ins().iconst(types::I8, i64::from(val)),
|
2024-12-02 20:35:13 +00:00
|
|
|
fx.layout_of(fx.tcx.types.bool),
|
2024-02-07 10:26:00 -05:00
|
|
|
);
|
|
|
|
|
lval.write_cvalue(fx, val);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-09-07 16:06:07 +01:00
|
|
|
};
|
2023-04-29 12:00:43 +00:00
|
|
|
let val = CValue::by_val(
|
|
|
|
|
fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()),
|
|
|
|
|
fx.layout_of(fx.tcx.types.usize),
|
|
|
|
|
);
|
2018-08-08 12:44:41 +02:00
|
|
|
lval.write_cvalue(fx, val);
|
2018-08-08 12:45:34 +02:00
|
|
|
}
|
2024-04-11 21:45:05 -07:00
|
|
|
Rvalue::Aggregate(ref kind, ref operands)
|
|
|
|
|
if matches!(**kind, AggregateKind::RawPtr(..)) =>
|
|
|
|
|
{
|
|
|
|
|
let ty = to_place_and_rval.1.ty(&fx.mir.local_decls, fx.tcx);
|
|
|
|
|
let layout = fx.layout_of(fx.monomorphize(ty));
|
|
|
|
|
let [data, meta] = &*operands.raw else {
|
|
|
|
|
bug!("RawPtr fields: {operands:?}");
|
|
|
|
|
};
|
|
|
|
|
let data = codegen_operand(fx, data);
|
|
|
|
|
let meta = codegen_operand(fx, meta);
|
2025-01-24 14:58:33 +00:00
|
|
|
assert!(data.layout().ty.is_raw_ptr());
|
|
|
|
|
assert!(layout.ty.is_raw_ptr());
|
2024-04-23 09:37:28 +00:00
|
|
|
let ptr_val = if meta.layout().is_zst() {
|
|
|
|
|
data.cast_pointer_to(layout)
|
|
|
|
|
} else {
|
|
|
|
|
CValue::by_val_pair(data.load_scalar(fx), meta.load_scalar(fx), layout)
|
|
|
|
|
};
|
2024-04-11 21:45:05 -07:00
|
|
|
lval.write_cvalue(fx, ptr_val);
|
|
|
|
|
}
|
2023-02-09 12:38:16 +01:00
|
|
|
Rvalue::Aggregate(ref kind, ref operands) => {
|
|
|
|
|
let (variant_index, variant_dest, active_field_index) = match **kind {
|
|
|
|
|
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
|
|
|
|
|
let variant_dest = lval.downcast_variant(fx, variant_index);
|
|
|
|
|
(variant_index, variant_dest, active_field_index)
|
2018-08-09 11:41:34 +02:00
|
|
|
}
|
2023-03-25 18:43:03 -07:00
|
|
|
_ => (FIRST_VARIANT, lval, None),
|
2023-02-09 12:38:16 +01:00
|
|
|
};
|
|
|
|
|
if active_field_index.is_some() {
|
|
|
|
|
assert_eq!(operands.len(), 1);
|
|
|
|
|
}
|
2023-04-01 20:11:38 -07:00
|
|
|
for (i, operand) in operands.iter_enumerated() {
|
2023-02-09 12:38:16 +01:00
|
|
|
let operand = codegen_operand(fx, operand);
|
|
|
|
|
let field_index = active_field_index.unwrap_or(i);
|
|
|
|
|
let to = if let mir::AggregateKind::Array(_) = **kind {
|
2023-04-01 20:11:38 -07:00
|
|
|
let array_index = i64::from(field_index.as_u32());
|
|
|
|
|
let index = fx.bcx.ins().iconst(fx.pointer_type, array_index);
|
2023-02-09 12:38:16 +01:00
|
|
|
variant_dest.place_index(fx, index)
|
|
|
|
|
} else {
|
2023-04-01 20:11:38 -07:00
|
|
|
variant_dest.place_field(fx, field_index)
|
2023-02-09 12:38:16 +01:00
|
|
|
};
|
|
|
|
|
to.write_cvalue(fx, operand);
|
2018-08-09 11:41:34 +02:00
|
|
|
}
|
2023-02-09 12:38:16 +01:00
|
|
|
crate::discriminant::codegen_set_discriminant(fx, lval, variant_index);
|
|
|
|
|
}
|
2025-01-31 02:04:10 +00:00
|
|
|
Rvalue::WrapUnsafeBinder(ref operand, _to_ty) => {
|
|
|
|
|
let operand = codegen_operand(fx, operand);
|
|
|
|
|
lval.write_cvalue_transmute(fx, operand);
|
|
|
|
|
}
|
2018-06-20 15:29:50 +02:00
|
|
|
}
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
2018-07-31 12:25:16 +02:00
|
|
|
StatementKind::StorageLive(_)
|
|
|
|
|
| StatementKind::StorageDead(_)
|
2022-04-05 17:14:59 -04:00
|
|
|
| StatementKind::Deinit(_)
|
2022-12-29 23:44:16 +00:00
|
|
|
| StatementKind::ConstEvalCounter
|
2018-07-31 12:25:16 +02:00
|
|
|
| StatementKind::Nop
|
2018-09-23 10:16:26 +02:00
|
|
|
| StatementKind::FakeRead(..)
|
2018-11-03 12:49:55 +01:00
|
|
|
| StatementKind::Retag { .. }
|
2022-09-06 18:41:01 +02:00
|
|
|
| StatementKind::PlaceMention(..)
|
2024-09-02 01:13:07 +08:00
|
|
|
| StatementKind::BackwardIncompatibleDropHint { .. }
|
2018-12-21 13:45:06 +01:00
|
|
|
| StatementKind::AscribeUserType(..) => {}
|
2018-08-09 15:08:54 +02:00
|
|
|
|
2024-06-30 11:28:14 +00:00
|
|
|
StatementKind::Coverage { .. } => unreachable!(),
|
2022-07-12 10:05:00 +00:00
|
|
|
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
|
|
|
|
|
// We ignore `assume` intrinsics, they are only useful for optimizations
|
|
|
|
|
NonDivergingIntrinsic::Assume(_) => {}
|
|
|
|
|
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
|
|
|
|
|
src,
|
|
|
|
|
dst,
|
|
|
|
|
count,
|
|
|
|
|
}) => {
|
|
|
|
|
let dst = codegen_operand(fx, dst);
|
|
|
|
|
let pointee = dst
|
|
|
|
|
.layout()
|
2024-11-09 13:48:06 +00:00
|
|
|
.pointee_info_at(fx, rustc_abi::Size::ZERO)
|
2022-07-12 10:05:00 +00:00
|
|
|
.expect("Expected pointer");
|
|
|
|
|
let dst = dst.load_scalar(fx);
|
|
|
|
|
let src = codegen_operand(fx, src).load_scalar(fx);
|
|
|
|
|
let count = codegen_operand(fx, count).load_scalar(fx);
|
|
|
|
|
let elem_size: u64 = pointee.size.bytes();
|
|
|
|
|
let bytes = if elem_size != 1 {
|
|
|
|
|
fx.bcx.ins().imul_imm(count, elem_size as i64)
|
|
|
|
|
} else {
|
|
|
|
|
count
|
|
|
|
|
};
|
|
|
|
|
fx.bcx.call_memcpy(fx.target_config, dst, src, bytes);
|
|
|
|
|
}
|
|
|
|
|
},
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 19:12:59 +01:00
|
|
|
fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx>) -> Value {
|
2020-09-05 10:38:49 +02:00
|
|
|
match *place.layout().ty.kind() {
|
2018-11-13 18:28:10 +01:00
|
|
|
ty::Array(_elem_ty, len) => {
|
2024-09-20 20:38:11 -04:00
|
|
|
let len = fx
|
|
|
|
|
.monomorphize(len)
|
|
|
|
|
.try_to_target_usize(fx.tcx)
|
|
|
|
|
.expect("expected monomorphic const in codegen") as i64;
|
2018-11-13 18:28:10 +01:00
|
|
|
fx.bcx.ins().iconst(fx.pointer_type, len)
|
|
|
|
|
}
|
2023-04-29 12:00:43 +00:00
|
|
|
ty::Slice(_elem_ty) => place.to_ptr_unsized().1,
|
2018-11-13 18:28:10 +01:00
|
|
|
_ => bug!("Rvalue::Len({:?})", place),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-03 11:00:04 +01:00
|
|
|
pub(crate) fn codegen_place<'tcx>(
|
2021-03-05 19:12:59 +01:00
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
2020-04-02 17:23:15 +02:00
|
|
|
place: Place<'tcx>,
|
2018-07-31 12:25:16 +02:00
|
|
|
) -> CPlace<'tcx> {
|
2020-01-13 21:38:46 +01:00
|
|
|
let mut cplace = fx.get_local_place(place.local);
|
2019-07-24 11:56:24 +02:00
|
|
|
|
2020-04-02 17:23:15 +02:00
|
|
|
for elem in place.projection {
|
2020-06-04 19:57:12 +02:00
|
|
|
match elem {
|
2019-09-14 11:21:18 +02:00
|
|
|
PlaceElem::Deref => {
|
2022-07-25 16:07:57 +02:00
|
|
|
cplace = cplace.place_deref(fx);
|
2019-09-14 11:21:18 +02:00
|
|
|
}
|
2023-09-27 11:20:17 +00:00
|
|
|
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
|
2025-01-31 01:24:37 +00:00
|
|
|
PlaceElem::Subtype(ty) | PlaceElem::UnwrapUnsafeBinder(ty) => {
|
|
|
|
|
cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty));
|
|
|
|
|
}
|
2019-09-14 11:21:18 +02:00
|
|
|
PlaceElem::Field(field, _ty) => {
|
|
|
|
|
cplace = cplace.place_field(fx, field);
|
|
|
|
|
}
|
|
|
|
|
PlaceElem::Index(local) => {
|
|
|
|
|
let index = fx.get_local_place(local).to_cvalue(fx).load_scalar(fx);
|
|
|
|
|
cplace = cplace.place_index(fx, index);
|
|
|
|
|
}
|
2021-03-05 19:12:59 +01:00
|
|
|
PlaceElem::ConstantIndex { offset, min_length: _, from_end } => {
|
2020-09-05 10:38:49 +02:00
|
|
|
let offset: u64 = offset;
|
2019-09-14 11:21:18 +02:00
|
|
|
let index = if !from_end {
|
2020-09-05 10:38:49 +02:00
|
|
|
fx.bcx.ins().iconst(fx.pointer_type, offset as i64)
|
2019-09-14 11:21:18 +02:00
|
|
|
} else {
|
|
|
|
|
let len = codegen_array_len(fx, cplace);
|
2020-09-05 10:38:49 +02:00
|
|
|
fx.bcx.ins().iadd_imm(len, -(offset as i64))
|
2019-09-14 11:21:18 +02:00
|
|
|
};
|
|
|
|
|
cplace = cplace.place_index(fx, index);
|
|
|
|
|
}
|
2019-12-16 11:33:57 +01:00
|
|
|
PlaceElem::Subslice { from, to, from_end } => {
|
2019-09-14 11:21:18 +02:00
|
|
|
// These indices are generated by slice patterns.
|
|
|
|
|
// slice[from:-to] in Python terms.
|
|
|
|
|
|
2020-09-05 10:38:49 +02:00
|
|
|
let from: u64 = from;
|
|
|
|
|
let to: u64 = to;
|
|
|
|
|
|
|
|
|
|
match cplace.layout().ty.kind() {
|
2020-01-18 10:23:51 +01:00
|
|
|
ty::Array(elem_ty, _len) => {
|
|
|
|
|
assert!(!from_end, "array subslices are never `from_end`");
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
let elem_layout = fx.layout_of(*elem_ty);
|
2020-03-29 11:51:43 +02:00
|
|
|
let ptr = cplace.to_ptr();
|
2019-12-20 16:02:47 +01:00
|
|
|
cplace = CPlace::for_ptr(
|
2020-09-05 10:38:49 +02:00
|
|
|
ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * (from as i64)),
|
2023-07-05 20:13:26 +01:00
|
|
|
fx.layout_of(Ty::new_array(fx.tcx, *elem_ty, to - from)),
|
2019-09-14 11:21:18 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
ty::Slice(elem_ty) => {
|
2019-12-16 11:33:57 +01:00
|
|
|
assert!(from_end, "slice subslices should be `from_end`");
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
let elem_layout = fx.layout_of(*elem_ty);
|
2023-04-29 12:00:43 +00:00
|
|
|
let (ptr, len) = cplace.to_ptr_unsized();
|
2019-12-20 16:02:47 +01:00
|
|
|
cplace = CPlace::for_ptr_with_extra(
|
2020-09-05 10:38:49 +02:00
|
|
|
ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * (from as i64)),
|
|
|
|
|
fx.bcx.ins().iadd_imm(len, -(from as i64 + to as i64)),
|
2019-09-14 11:21:18 +02:00
|
|
|
cplace.layout(),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
_ => unreachable!(),
|
2019-02-24 12:38:06 +01:00
|
|
|
}
|
2019-09-14 11:21:18 +02:00
|
|
|
}
|
|
|
|
|
PlaceElem::Downcast(_adt_def, variant) => {
|
|
|
|
|
cplace = cplace.downcast_variant(fx, variant);
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-14 11:21:18 +02:00
|
|
|
|
|
|
|
|
cplace
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-03 11:00:04 +01:00
|
|
|
pub(crate) fn codegen_operand<'tcx>(
|
2021-03-05 19:12:59 +01:00
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
2018-07-31 12:25:16 +02:00
|
|
|
operand: &Operand<'tcx>,
|
|
|
|
|
) -> CValue<'tcx> {
|
2018-06-17 18:05:11 +02:00
|
|
|
match operand {
|
2018-07-31 12:25:16 +02:00
|
|
|
Operand::Move(place) | Operand::Copy(place) => {
|
2020-11-03 11:00:04 +01:00
|
|
|
let cplace = codegen_place(fx, *place);
|
2018-06-20 15:15:28 +02:00
|
|
|
cplace.to_cvalue(fx)
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
2022-10-23 16:22:55 +02:00
|
|
|
Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_),
|
2018-06-17 18:05:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-09-29 13:22:01 +02:00
|
|
|
|
2023-01-24 18:56:42 +01:00
|
|
|
pub(crate) fn codegen_panic_nounwind<'tcx>(
|
|
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
|
|
|
|
msg_str: &str,
|
2025-06-04 06:26:56 +00:00
|
|
|
span: Span,
|
2023-01-24 18:56:42 +01:00
|
|
|
) {
|
|
|
|
|
let msg_ptr = fx.anonymous_str(msg_str);
|
|
|
|
|
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
|
|
|
|
|
let args = [msg_ptr, msg_len];
|
|
|
|
|
|
2025-04-09 13:50:59 +00:00
|
|
|
codegen_panic_inner(
|
|
|
|
|
fx,
|
|
|
|
|
rustc_hir::LangItem::PanicNounwind,
|
|
|
|
|
&args,
|
|
|
|
|
UnwindAction::Terminate(UnwindTerminateReason::Abi),
|
|
|
|
|
span,
|
|
|
|
|
);
|
2023-01-24 18:56:42 +01:00
|
|
|
}
|
|
|
|
|
|
2023-08-21 09:57:10 +02:00
|
|
|
pub(crate) fn codegen_unwind_terminate<'tcx>(
|
2023-01-24 18:56:42 +01:00
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
2025-06-04 06:26:56 +00:00
|
|
|
span: Span,
|
2023-08-21 09:57:10 +02:00
|
|
|
reason: UnwindTerminateReason,
|
2023-01-24 18:56:42 +01:00
|
|
|
) {
|
2025-04-24 13:02:28 +00:00
|
|
|
codegen_panic_inner(fx, reason.lang_item(), &[], UnwindAction::Unreachable, span);
|
2023-01-24 18:56:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn codegen_panic_inner<'tcx>(
|
2021-03-05 19:12:59 +01:00
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
2020-09-29 13:22:01 +02:00
|
|
|
lang_item: rustc_hir::LangItem,
|
|
|
|
|
args: &[Value],
|
2025-04-09 13:50:59 +00:00
|
|
|
_unwind: UnwindAction,
|
2025-06-04 06:26:56 +00:00
|
|
|
span: Span,
|
2020-09-29 13:22:01 +02:00
|
|
|
) {
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
|
|
|
|
|
|
2023-12-19 12:46:39 +00:00
|
|
|
let def_id = fx.tcx.require_lang_item(lang_item, span);
|
2020-09-29 13:22:01 +02:00
|
|
|
|
2024-12-04 21:03:12 -05:00
|
|
|
let instance = Instance::mono(fx.tcx, def_id);
|
2024-03-15 14:13:11 -04:00
|
|
|
|
|
|
|
|
if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) {
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.ins().trap(TrapCode::user(2).unwrap());
|
2024-03-15 14:13:11 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-29 13:22:01 +02:00
|
|
|
let symbol_name = fx.tcx.symbol_name(instance).name;
|
|
|
|
|
|
2025-04-09 13:50:59 +00:00
|
|
|
// FIXME implement cleanup on exceptions
|
|
|
|
|
|
2020-09-29 13:22:01 +02:00
|
|
|
fx.lib_call(
|
2023-03-15 14:41:48 +00:00
|
|
|
symbol_name,
|
2023-01-24 18:56:42 +01:00
|
|
|
args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
|
2020-09-29 13:22:01 +02:00
|
|
|
vec![],
|
|
|
|
|
args,
|
|
|
|
|
);
|
|
|
|
|
|
2024-11-02 14:53:30 +00:00
|
|
|
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
2020-09-29 13:22:01 +02:00
|
|
|
}
|