Merge commit 'ba315abda789c9f59f2100102232bddb30b0d3d3' into sync_cg_clif-2025-03-30

This commit is contained in:
bjorn3
2025-03-30 15:43:48 +00:00
41 changed files with 533 additions and 1419 deletions

View File

@@ -729,8 +729,10 @@ fn codegen_stmt<'tcx>(
let to_ty = fx.monomorphize(to_ty);
fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
ty.builtin_deref(true)
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
ty.builtin_deref(true).is_some_and(|pointee_ty| {
fx.tcx
.type_has_metadata(pointee_ty, ty::TypingEnv::fully_monomorphized())
})
}
if is_wide_ptr(fx, from_ty) {

View File

@@ -71,7 +71,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Typ
},
ty::FnPtr(..) => pointer_ty(tcx),
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
if has_ptr_meta(tcx, *pointee_ty) {
if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
return None;
} else {
pointer_ty(tcx)
@@ -91,7 +91,7 @@ fn clif_pair_type_from_ty<'tcx>(
(clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?)
}
ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) => {
if has_ptr_meta(tcx, *pointee_ty) {
if tcx.type_has_metadata(*pointee_ty, ty::TypingEnv::fully_monomorphized()) {
(pointer_ty(tcx), pointer_ty(tcx))
} else {
return None;
@@ -101,20 +101,6 @@ fn clif_pair_type_from_ty<'tcx>(
})
}
/// Is a pointer to this type a wide ptr?
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) {
return false;
}
let tail = tcx.struct_tail_for_codegen(ty, ty::TypingEnv::fully_monomorphized());
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
_ => bug!("unexpected unsized tail: {:?}", tail),
}
}
pub(crate) fn codegen_icmp_imm(
fx: &mut FunctionCx<'_, '_, '_>,
intcc: IntCC,

View File

@@ -1,21 +1,10 @@
/// The mode to use for compilation.
#[derive(Copy, Clone, Debug)]
pub enum CodegenMode {
/// AOT compile the crate. This is the default.
Aot,
/// JIT compile and execute the crate.
Jit,
/// JIT compile and execute the crate, but only compile functions the first time they are used.
JitLazy,
}
/// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
#[derive(Clone, Debug)]
pub struct BackendConfig {
/// Should the crate be AOT compiled or JIT executed.
///
/// Defaults to AOT compilation. Can be set using `-Cllvm-args=mode=...`.
pub codegen_mode: CodegenMode,
/// Defaults to AOT compilation. Can be set using `-Cllvm-args=jit-mode`.
pub jit_mode: bool,
/// When JIT mode is enable pass these arguments to the program.
///
@@ -27,7 +16,7 @@ impl BackendConfig {
/// Parse the configuration passed in using `-Cllvm-args`.
pub fn from_opts(opts: &[String]) -> Result<Self, String> {
let mut config = BackendConfig {
codegen_mode: CodegenMode::Aot,
jit_mode: false,
jit_args: match std::env::var("CG_CLIF_JIT_ARGS") {
Ok(args) => args.split(' ').map(|arg| arg.to_string()).collect(),
Err(std::env::VarError::NotPresent) => vec![],
@@ -43,20 +32,9 @@ impl BackendConfig {
// testing cg_clif.
continue;
}
if let Some((name, value)) = opt.split_once('=') {
match name {
"mode" => {
config.codegen_mode = match value {
"aot" => CodegenMode::Aot,
"jit" => CodegenMode::Jit,
"jit-lazy" => CodegenMode::JitLazy,
_ => return Err(format!("Unknown codegen mode `{}`", value)),
};
}
_ => return Err(format!("Unknown option `{}`", name)),
}
} else {
return Err(format!("Invalid option `{}`", opt));
match &**opt {
"jit-mode" => config.jit_mode = true,
_ => return Err(format!("Unknown option `{}`", opt)),
}
}

View File

@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::{DebugContext, FullyMonomorphizedLayoutCx, has_ptr_meta};
use crate::{DebugContext, FullyMonomorphizedLayoutCx};
#[derive(Default)]
pub(crate) struct TypeDebugContext<'tcx> {
@@ -129,7 +129,7 @@ impl DebugContext {
let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true);
if !has_ptr_meta(tcx, ptr_type) {
if !tcx.type_has_metadata(ptr_type, ty::TypingEnv::fully_monomorphized()) {
let pointer_type_id =
self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type);
let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id);

View File

@@ -331,7 +331,7 @@ fn produce_final_output_artifacts(
}
fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
let isa = crate::build_isa(sess);
let isa = crate::build_isa(sess, false);
let mut builder =
ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap();

View File

@@ -1,75 +1,27 @@
//! The JIT driver uses [`cranelift_jit`] to JIT execute programs without writing any object
//! files.
use std::cell::RefCell;
use std::ffi::CString;
use std::os::raw::{c_char, c_int};
use std::sync::{Mutex, OnceLock, mpsc};
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use cranelift_jit::{JITBuilder, JITModule};
use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem;
use rustc_session::Session;
use rustc_span::sym;
use crate::CodegenCx;
use crate::debuginfo::TypeDebugContext;
use crate::prelude::*;
use crate::unwind_module::UnwindModule;
use crate::{CodegenCx, CodegenMode};
struct JitState {
jit_module: UnwindModule<JITModule>,
}
thread_local! {
static LAZY_JIT_STATE: RefCell<Option<JitState>> = const { RefCell::new(None) };
}
/// The Sender owned by the rustc thread
static GLOBAL_MESSAGE_SENDER: OnceLock<Mutex<mpsc::Sender<UnsafeMessage>>> = OnceLock::new();
/// A message that is sent from the jitted runtime to the rustc thread.
/// Senders are responsible for upholding `Send` semantics.
enum UnsafeMessage {
/// Request that the specified `Instance` be lazily jitted.
///
/// Nothing accessible through `instance_ptr` may be moved or mutated by the sender after
/// this message is sent.
JitFn {
instance_ptr: *const Instance<'static>,
trampoline_ptr: *const u8,
tx: mpsc::Sender<*const u8>,
},
}
unsafe impl Send for UnsafeMessage {}
impl UnsafeMessage {
/// Send the message.
fn send(self) {
thread_local! {
/// The Sender owned by the local thread
static LOCAL_MESSAGE_SENDER: mpsc::Sender<UnsafeMessage> =
GLOBAL_MESSAGE_SENDER
.get().unwrap()
.lock().unwrap()
.clone();
}
LOCAL_MESSAGE_SENDER.with(|sender| {
sender.send(self).expect("rustc thread hung up before lazy JIT request was sent")
})
}
}
fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>, CodegenCx) {
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
let isa = crate::build_isa(tcx.sess);
let isa = crate::build_isa(tcx.sess, true);
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
jit_builder.hotswap(hotswap);
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
@@ -79,7 +31,7 @@ fn create_jit_module(tcx: TyCtxt<'_>, hotswap: bool) -> (UnwindModule<JITModule>
(jit_module, cx)
}
pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<String>) -> ! {
pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
if !tcx.sess.opts.output_types.should_codegen() {
tcx.dcx().fatal("JIT mode doesn't work with `cargo check`");
}
@@ -88,8 +40,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
tcx.dcx().fatal("can't jit non-executable crate");
}
let (mut jit_module, mut cx) =
create_jit_module(tcx, matches!(codegen_mode, CodegenMode::JitLazy));
let (mut jit_module, mut cx) = create_jit_module(tcx);
let mut cached_context = Context::new();
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
@@ -105,21 +56,15 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
super::predefine_mono_items(tcx, &mut jit_module, &mono_items);
for (mono_item, _) in mono_items {
match mono_item {
MonoItem::Fn(inst) => match codegen_mode {
CodegenMode::Aot => unreachable!(),
CodegenMode::Jit => {
codegen_and_compile_fn(
tcx,
&mut cx,
&mut cached_context,
&mut jit_module,
inst,
);
}
CodegenMode::JitLazy => {
codegen_shim(tcx, &mut cached_context, &mut jit_module, inst)
}
},
MonoItem::Fn(inst) => {
codegen_and_compile_fn(
tcx,
&mut cx,
&mut cached_context,
&mut jit_module,
inst,
);
}
MonoItem::Static(def_id) => {
crate::constant::codegen_static(tcx, &mut jit_module, def_id);
}
@@ -161,41 +106,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, codegen_mode: CodegenMode, jit_args: Vec<
let start_func_id = jit_module.declare_function("main", Linkage::Import, &start_sig).unwrap();
let finalized_start: *const u8 = jit_module.module.get_finalized_function(start_func_id);
LAZY_JIT_STATE.with(|lazy_jit_state| {
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
assert!(lazy_jit_state.is_none());
*lazy_jit_state = Some(JitState { jit_module });
});
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_start) };
let (tx, rx) = mpsc::channel();
GLOBAL_MESSAGE_SENDER.set(Mutex::new(tx)).unwrap();
let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
// Spawn the jitted runtime in a new thread so that this rustc thread can handle messages
// (eg to lazily JIT further functions as required)
std::thread::spawn(move || {
let mut argv = args.iter().map(|arg| arg.as_ptr()).collect::<Vec<_>>();
// Push a null pointer as a terminating argument. This is required by POSIX and
// useful as some dynamic linkers use it as a marker to jump over.
argv.push(std::ptr::null());
// Push a null pointer as a terminating argument. This is required by POSIX and
// useful as some dynamic linkers use it as a marker to jump over.
argv.push(std::ptr::null());
let ret = f(args.len() as c_int, argv.as_ptr());
std::process::exit(ret);
});
// Handle messages
loop {
match rx.recv().unwrap() {
// lazy JIT compilation request - compile requested instance and return pointer to result
UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx } => {
tx.send(jit_fn(instance_ptr, trampoline_ptr))
.expect("jitted runtime hung up before response to lazy JIT request was sent");
}
}
}
let ret = f(args.len() as c_int, argv.as_ptr());
std::process::exit(ret);
}
pub(crate) fn codegen_and_compile_fn<'tcx>(
@@ -227,58 +148,6 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
});
}
extern "C" fn clif_jit_fn(
instance_ptr: *const Instance<'static>,
trampoline_ptr: *const u8,
) -> *const u8 {
// send the JIT request to the rustc thread, with a channel for the response
let (tx, rx) = mpsc::channel();
UnsafeMessage::JitFn { instance_ptr, trampoline_ptr, tx }.send();
// block on JIT compilation result
rx.recv().expect("rustc thread hung up before responding to sent lazy JIT request")
}
fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> *const u8 {
rustc_middle::ty::tls::with(|tcx| {
// lift is used to ensure the correct lifetime for instance.
let instance = tcx.lift(unsafe { *instance_ptr }).unwrap();
LAZY_JIT_STATE.with(|lazy_jit_state| {
let mut lazy_jit_state = lazy_jit_state.borrow_mut();
let lazy_jit_state = lazy_jit_state.as_mut().unwrap();
let jit_module = &mut lazy_jit_state.jit_module;
let name = tcx.symbol_name(instance).name;
let sig = crate::abi::get_function_sig(
tcx,
jit_module.target_config().default_call_conv,
instance,
);
let func_id = jit_module.declare_function(name, Linkage::Export, &sig).unwrap();
let current_ptr = jit_module.module.read_got_entry(func_id);
// If the function's GOT entry has already been updated to point at something other
// than the shim trampoline, don't re-jit but just return the new pointer instead.
// This does not need synchronization as this code is executed only by a sole rustc
// thread.
if current_ptr != trampoline_ptr {
return current_ptr;
}
jit_module.module.prepare_for_function_redefine(func_id).unwrap();
let mut cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
assert!(cx.global_asm.is_empty());
jit_module.finalize_definitions();
jit_module.module.get_finalized_function(func_id)
})
})
}
fn dep_symbol_lookup_fn(
sess: &Session,
crate_info: CrateInfo,
@@ -326,57 +195,3 @@ fn dep_symbol_lookup_fn(
None
})
}
fn codegen_shim<'tcx>(
tcx: TyCtxt<'tcx>,
cached_context: &mut Context,
module: &mut UnwindModule<JITModule>,
inst: Instance<'tcx>,
) {
let pointer_type = module.target_config().pointer_type();
let name = tcx.symbol_name(inst).name;
let sig = crate::abi::get_function_sig(tcx, module.target_config().default_call_conv, inst);
let func_id = module.declare_function(name, Linkage::Export, &sig).unwrap();
let instance_ptr = Box::into_raw(Box::new(inst));
let jit_fn = module
.declare_function(
"__clif_jit_fn",
Linkage::Import,
&Signature {
call_conv: module.target_config().default_call_conv,
params: vec![AbiParam::new(pointer_type), AbiParam::new(pointer_type)],
returns: vec![AbiParam::new(pointer_type)],
},
)
.unwrap();
let context = cached_context;
context.clear();
let trampoline = &mut context.func;
trampoline.signature = sig.clone();
let mut builder_ctx = FunctionBuilderContext::new();
let mut trampoline_builder = FunctionBuilder::new(trampoline, &mut builder_ctx);
let trampoline_fn = module.declare_func_in_func(func_id, trampoline_builder.func);
let jit_fn = module.declare_func_in_func(jit_fn, trampoline_builder.func);
let sig_ref = trampoline_builder.func.import_signature(sig);
let entry_block = trampoline_builder.create_block();
trampoline_builder.append_block_params_for_function_params(entry_block);
let fn_args = trampoline_builder.func.dfg.block_params(entry_block).to_vec();
trampoline_builder.switch_to_block(entry_block);
let instance_ptr = trampoline_builder.ins().iconst(pointer_type, instance_ptr as u64 as i64);
let trampoline_ptr = trampoline_builder.ins().func_addr(pointer_type, trampoline_fn);
let jitted_fn = trampoline_builder.ins().call(jit_fn, &[instance_ptr, trampoline_ptr]);
let jitted_fn = trampoline_builder.func.dfg.inst_results(jitted_fn)[0];
let call_inst = trampoline_builder.ins().call_indirect(sig_ref, jitted_fn, &fn_args);
let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec();
trampoline_builder.ins().return_(&ret_vals);
module.define_function(func_id, context).unwrap();
}

View File

@@ -612,6 +612,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
generated_asm.push_str(".att_syntax\n");
}
if self.arch == InlineAsmArch::AArch64 {
for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
if feature.name == sym::neon {
continue;
}
writeln!(generated_asm, ".arch_extension {}", feature.name).unwrap();
}
}
// The actual inline asm
for piece in self.template {
match piece {
@@ -652,6 +661,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
.emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
.unwrap(),
},
InlineAsmArch::AArch64 => match reg {
InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
// rustc emits v0 rather than q0
reg.emit(
&mut generated_asm,
InlineAsmArch::AArch64,
Some(modifier.unwrap_or('q')),
)
.unwrap()
}
_ => reg
.emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier)
.unwrap(),
},
_ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
}
}
@@ -665,6 +688,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
}
generated_asm.push('\n');
if self.arch == InlineAsmArch::AArch64 {
for feature in &self.tcx.codegen_fn_attrs(self.enclosing_def_id).target_features {
if feature.name == sym::neon {
continue;
}
writeln!(generated_asm, ".arch_extension no{}", feature.name).unwrap();
}
}
if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
generated_asm.push_str(".intel_syntax noprefix\n");
}
@@ -809,7 +841,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
}
InlineAsmArch::AArch64 => {
generated_asm.push_str(" str ");
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
match reg {
InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
// rustc emits v0 rather than q0
reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
}
_ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
}
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
}
InlineAsmArch::RiscV64 => {
@@ -851,7 +889,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
}
InlineAsmArch::AArch64 => {
generated_asm.push_str(" ldr ");
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
match reg {
InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
// rustc emits v0 rather than q0
reg.emit(generated_asm, InlineAsmArch::AArch64, Some('q')).unwrap()
}
_ => reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(),
}
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
}
InlineAsmArch::RiscV64 => {

View File

@@ -54,6 +54,14 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
);
}
"llvm.fptosi.sat.v4i32.v4f32" => {
intrinsic_args!(fx, args => (a); intrinsic);
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
fx.bcx.ins().fcvt_to_sint_sat(types::I32, lane)
});
}
_ => {
fx.tcx
.dcx()

View File

@@ -1,5 +1,9 @@
//! Emulate AArch64 LLVM intrinsics
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_target::asm::*;
use crate::inline_asm::{CInlineAsmOperand, codegen_inline_asm_inner};
use crate::intrinsics::*;
use crate::prelude::*;
@@ -17,7 +21,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
fx.bcx.ins().fence();
}
"llvm.aarch64.neon.ld1x4.v16i8.p0i8" => {
"llvm.aarch64.neon.ld1x4.v16i8.p0" => {
intrinsic_args!(fx, args => (ptr); intrinsic);
let ptr = ptr.load_scalar(fx);
@@ -49,6 +53,121 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
});
}
"llvm.aarch64.neon.fcvtns.v4i32.v4f32" => {
intrinsic_args!(fx, args => (a); intrinsic);
// Note: Using inline asm instead of fcvt_to_sint as the latter rounds to zero rather than to nearest
let a_ptr = a.force_stack(fx).0.get_addr(fx);
let res_place = CPlace::new_stack_slot(fx, ret.layout());
let res_ptr = res_place.to_ptr().get_addr(fx);
codegen_inline_asm_inner(
fx,
&[InlineAsmTemplatePiece::String(
"ldr q0, [x0]
fcvtns v0.4s, v0.4s
str q0, [x1]"
.into(),
)],
&[
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x0,
)),
value: a_ptr,
},
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x1,
)),
value: res_ptr,
},
],
InlineAsmOptions::NOSTACK,
);
let res = res_place.to_cvalue(fx);
ret.write_cvalue_transmute(fx, res);
}
"llvm.aarch64.neon.frecpe.v4f32" => {
intrinsic_args!(fx, args => (a); intrinsic);
let a_ptr = a.force_stack(fx).0.get_addr(fx);
let res_place = CPlace::new_stack_slot(fx, ret.layout());
let res_ptr = res_place.to_ptr().get_addr(fx);
codegen_inline_asm_inner(
fx,
&[InlineAsmTemplatePiece::String(
"ldr q0, [x0]
frecpe v0.4s, v0.4s
str q0, [x1]"
.into(),
)],
&[
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x0,
)),
value: a_ptr,
},
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x1,
)),
value: res_ptr,
},
],
InlineAsmOptions::NOSTACK,
);
let res = res_place.to_cvalue(fx);
ret.write_cvalue_transmute(fx, res);
}
"llvm.aarch64.neon.frecps.v4f32" => {
intrinsic_args!(fx, args => (a, b); intrinsic);
let a_ptr = a.force_stack(fx).0.get_addr(fx);
let b_ptr = b.force_stack(fx).0.get_addr(fx);
let res_place = CPlace::new_stack_slot(fx, ret.layout());
let res_ptr = res_place.to_ptr().get_addr(fx);
codegen_inline_asm_inner(
fx,
&[InlineAsmTemplatePiece::String(
"ldr q0, [x0]
ldr q1, [x1]
frecps v0.4s, v0.4s, v1.4s
str q0, [x2]"
.into(),
)],
&[
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x0,
)),
value: a_ptr,
},
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x1,
)),
value: b_ptr,
},
CInlineAsmOperand::In {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::AArch64(
AArch64InlineAsmReg::x2,
)),
value: res_ptr,
},
],
InlineAsmOptions::NOSTACK,
);
let res = res_place.to_cvalue(fx);
ret.write_cvalue_transmute(fx, res);
}
_ if intrinsic.starts_with("llvm.aarch64.neon.sqadd.v")
|| intrinsic.starts_with("llvm.aarch64.neon.uqadd.v") =>
{
@@ -134,7 +253,7 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
}
let res = CValue::by_val(
fx.bcx.ins().uextend(types::I32, res_val),
fx.layout_of(fx.tcx.types.u32),
fx.layout_of(fx.tcx.types.i32),
);
ret.write_cvalue(fx, res);
}

View File

@@ -42,7 +42,6 @@ use std::sync::Arc;
use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::back::versioned_llvm_target;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -214,15 +213,14 @@ impl CodegenBackend for CraneliftCodegenBackend {
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
.unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
});
match config.codegen_mode {
CodegenMode::Aot => driver::aot::run_aot(tcx, metadata, need_metadata_module),
CodegenMode::Jit | CodegenMode::JitLazy => {
#[cfg(feature = "jit")]
driver::jit::run_jit(tcx, config.codegen_mode, config.jit_args);
if config.jit_mode {
#[cfg(feature = "jit")]
driver::jit::run_jit(tcx, config.jit_args);
#[cfg(not(feature = "jit"))]
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
}
#[cfg(not(feature = "jit"))]
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
} else {
driver::aot::run_aot(tcx, metadata, need_metadata_module)
}
}
@@ -247,21 +245,19 @@ fn enable_verifier(sess: &Session) -> bool {
}
fn target_triple(sess: &Session) -> target_lexicon::Triple {
// FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS.
// See <https://github.com/bytecodealliance/target-lexicon/pull/113>
match versioned_llvm_target(sess).parse() {
match sess.target.llvm_target.parse() {
Ok(triple) => triple,
Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)),
}
}
fn build_isa(sess: &Session) -> Arc<dyn TargetIsa + 'static> {
fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
use target_lexicon::BinaryFormat;
let target_triple = crate::target_triple(sess);
let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap();
flags_builder.set("is_pic", if jit { "false" } else { "true" }).unwrap();
let enable_verifier = if enable_verifier(sess) { "true" } else { "false" };
flags_builder.set("enable_verifier", enable_verifier).unwrap();
flags_builder.set("regalloc_checker", enable_verifier).unwrap();

View File

@@ -395,8 +395,12 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
in_lhs: CValue<'tcx>,
in_rhs: CValue<'tcx>,
) -> CValue<'tcx> {
let is_thin_ptr =
in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
let is_thin_ptr = in_lhs
.layout()
.ty
.builtin_deref(true)
.map(|ty| !fx.tcx.type_has_metadata(ty, ty::TypingEnv::fully_monomorphized()))
.unwrap_or(true);
if is_thin_ptr {
match bin_op {

View File

@@ -746,7 +746,7 @@ impl<'tcx> CPlace<'tcx> {
};
let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
if has_ptr_meta(fx.tcx, field_layout.ty) {
if fx.tcx.type_has_metadata(field_layout.ty, ty::TypingEnv::fully_monomorphized()) {
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
} else {
CPlace::for_ptr(field_ptr, field_layout)
@@ -832,7 +832,7 @@ impl<'tcx> CPlace<'tcx> {
pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
if has_ptr_meta(fx.tcx, inner_layout.ty) {
if fx.tcx.type_has_metadata(inner_layout.ty, ty::TypingEnv::fully_monomorphized()) {
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
} else {
@@ -845,7 +845,7 @@ impl<'tcx> CPlace<'tcx> {
fx: &mut FunctionCx<'_, '_, 'tcx>,
layout: TyAndLayout<'tcx>,
) -> CValue<'tcx> {
if has_ptr_meta(fx.tcx, self.layout().ty) {
if fx.tcx.type_has_metadata(self.layout().ty, ty::TypingEnv::fully_monomorphized()) {
let (ptr, extra) = self.to_ptr_unsized();
CValue::by_val_pair(ptr.get_addr(fx), extra, layout)
} else {