From 0fed1a5f57fc8ffba7dccfddbfffeb77282888b9 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 1 Jul 2022 13:01:41 -0700 Subject: [PATCH 001/100] Enable raw-dylib for binaries --- src/archive.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index 0812f930b5dea..f3f3628fceeac 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -204,12 +204,16 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - fn inject_dll_import_lib( - &mut self, + fn sess(&self) -> &Session { + self.sess + } + + fn create_dll_import_lib( + _sess: &Session, _lib_name: &str, _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir, - ) { - bug!("injecting dll imports is not supported"); + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); } } From a6260ecd81e2eb928b7532649888e0b19540f82f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 26 Jul 2022 18:53:46 +0200 Subject: [PATCH 002/100] Merge commit 'd3a2366ee877075c59b38bd8ced55f224fc7ef51' into sync_cg_clif-2022-07-26 --- src/intrinsics/llvm.rs | 145 +++++----- src/intrinsics/mod.rs | 622 ++++++++++++++++++++++++----------------- src/intrinsics/simd.rs | 399 ++++++++++++++++---------- 3 files changed, 705 insertions(+), 461 deletions(-) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 77ac46540a9ba..869670c8cfac7 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -13,15 +13,11 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( ret: CPlace<'tcx>, target: Option, ) { - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); - crate::trap::trap_unimplemented(fx, intrinsic); - }; - + match intrinsic { // Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8` - "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd", (c a) { + "llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => { + intrinsic_args!(fx, args => (a); intrinsic); + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); let lane_ty = fx.clif_type(lane_ty).unwrap(); assert!(lane_count <= 32); @@ -29,7 +25,8 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let mut res = fx.bcx.ins().iconst(types::I32, 0); for lane in (0..lane_count).rev() { - let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); + let a_lane = + a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); // cast float to int let a_lane = match lane_ty { @@ -49,26 +46,29 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32)); ret.write_cvalue(fx, res); - }; - "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd", (c x, c y, o kind) { - let kind = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const"); - let flt_cc = match kind.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind)) { + } + "llvm.x86.sse2.cmp.ps" | "llvm.x86.sse2.cmp.pd" => { + let (x, y, kind) = match args { + [x, y, kind] => (x, y, kind), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + let kind = crate::constant::mir_operand_get_const_val(fx, kind) + .expect("llvm.x86.sse2.cmp.* kind not const"); + + let flt_cc = match kind + .try_to_bits(Size::from_bytes(1)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", kind)) + { 0 => FloatCC::Equal, 1 => FloatCC::LessThan, 2 => FloatCC::LessThanOrEqual, - 7 => { - unimplemented!("Compares corresponding elements in `a` and `b` to see if neither is `NaN`."); - } - 3 => { - unimplemented!("Compares corresponding elements in `a` and `b` to see if either is `NaN`."); - } + 7 => FloatCC::Ordered, + 3 => FloatCC::Unordered, 4 => FloatCC::NotEqual, - 5 => { - unimplemented!("not less than"); - } - 6 => { - unimplemented!("not less than or equal"); - } + 5 => FloatCC::UnorderedOrGreaterThanOrEqual, + 6 => FloatCC::UnorderedOrGreaterThan, kind => unreachable!("kind {:?}", kind), }; @@ -79,50 +79,67 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }; bool_to_zero_or_max_uint(fx, res_lane_ty, res_lane) }); - }; - "llvm.x86.sse2.psrli.d", (c a, o imm8) { - let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); - simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { - match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { - imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), - _ => fx.bcx.ins().iconst(types::I32, 0), - } + } + "llvm.x86.sse2.psrli.d" => { + let (a, imm8) = match args { + [a, imm8] => (a, imm8), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let a = codegen_operand(fx, a); + let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8) + .expect("llvm.x86.sse2.psrli.d imm8 not const"); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8 + .try_to_bits(Size::from_bytes(4)) + .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) + { + imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), + _ => fx.bcx.ins().iconst(types::I32, 0), }); - }; - "llvm.x86.sse2.pslli.d", (c a, o imm8) { - let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); - simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| { - match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { - imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)), - _ => fx.bcx.ins().iconst(types::I32, 0), - } + } + "llvm.x86.sse2.pslli.d" => { + let (a, imm8) = match args { + [a, imm8] => (a, imm8), + _ => bug!("wrong number of args for intrinsic {intrinsic}"), + }; + let a = codegen_operand(fx, a); + let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8) + .expect("llvm.x86.sse2.psrli.d imm8 not const"); + + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| match imm8 + .try_to_bits(Size::from_bytes(4)) + .unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) + { + imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)), + _ => fx.bcx.ins().iconst(types::I32, 0), }); - }; - "llvm.x86.sse2.storeu.dq", (v mem_addr, c a) { + } + "llvm.x86.sse2.storeu.dq" => { + intrinsic_args!(fx, args => (mem_addr, a); intrinsic); + let mem_addr = mem_addr.load_scalar(fx); + // FIXME correctly handle the unalignment let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout()); dest.write_cvalue(fx, a); - }; - "llvm.x86.addcarry.64", (v c_in, c a, c b) { - llvm_add_sub( - fx, - BinOp::Add, - ret, - c_in, - a, - b - ); - }; - "llvm.x86.subborrow.64", (v b_in, c a, c b) { - llvm_add_sub( - fx, - BinOp::Sub, - ret, - b_in, - a, - b - ); - }; + } + "llvm.x86.addcarry.64" => { + intrinsic_args!(fx, args => (c_in, a, b); intrinsic); + let c_in = c_in.load_scalar(fx); + + llvm_add_sub(fx, BinOp::Add, ret, c_in, a, b); + } + "llvm.x86.subborrow.64" => { + intrinsic_args!(fx, args => (b_in, a, b); intrinsic); + let b_in = b_in.load_scalar(fx); + + llvm_add_sub(fx, BinOp::Sub, ret, b_in, a, b); + } + _ => { + fx.tcx + .sess + .warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); + crate::trap::trap_unimplemented(fx, intrinsic); + } } let dest = target.expect("all llvm intrinsics used by stdlib should return"); diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 8d8db1da58183..b2a83e1d4ebc9 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1,50 +1,14 @@ //! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"` //! and LLVM intrinsics that have symbol names starting with `llvm.`. -macro_rules! intrinsic_pat { - (_) => { - _ - }; - ($name:ident) => { - sym::$name - }; - (kw.$name:ident) => { - kw::$name - }; - ($name:literal) => { - $name - }; -} - -macro_rules! intrinsic_arg { - (o $fx:expr, $arg:ident) => {}; - (c $fx:expr, $arg:ident) => { - let $arg = codegen_operand($fx, $arg); - }; - (v $fx:expr, $arg:ident) => { - let $arg = codegen_operand($fx, $arg).load_scalar($fx); - }; -} - -macro_rules! intrinsic_match { - ($fx:expr, $intrinsic:expr, $args:expr, - _ => $unknown:block; - $( - $($($name:tt).*)|+ $(if $cond:expr)?, ($($a:ident $arg:ident),*) $content:block; - )*) => { - match $intrinsic { - $( - $(intrinsic_pat!($($name).*))|* $(if $cond)? => { - if let [$($arg),*] = $args { - $(intrinsic_arg!($a $fx, $arg);)* - $content - } else { - bug!("wrong number of args for intrinsic {:?}", $intrinsic); - } - } - )* - _ => $unknown, - } +macro_rules! intrinsic_args { + ($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => { + #[allow(unused_parens)] + let ($($arg),*) = if let [$($arg),*] = $args { + ($(codegen_operand($fx, $arg)),*) + } else { + $crate::intrinsics::bug_on_incorrect_arg_count($intrinsic); + }; } } @@ -62,6 +26,10 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::prelude::*; use cranelift_codegen::ir::AtomicRmwOp; +fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! { + bug!("wrong number of args for intrinsic {}", intrinsic); +} + fn report_atomic_type_validation_error<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: Symbol, @@ -351,28 +319,31 @@ fn codegen_regular_intrinsic_call<'tcx>( ) { let usize_layout = fx.layout_of(fx.tcx.types.usize); - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.span_fatal(source_info.span, &format!("unsupported intrinsic {}", intrinsic)); - }; + match intrinsic { + sym::assume => { + intrinsic_args!(fx, args => (_a); intrinsic); + } + sym::likely | sym::unlikely => { + intrinsic_args!(fx, args => (a); intrinsic); - assume, (c _a) {}; - likely | unlikely, (c a) { ret.write_cvalue(fx, a); - }; - breakpoint, () { + } + sym::breakpoint => { + intrinsic_args!(fx, args => (); intrinsic); + fx.bcx.ins().debugtrap(); - }; - copy | copy_nonoverlapping, (v src, v dst, v count) { + } + sym::copy | sym::copy_nonoverlapping => { + intrinsic_args!(fx, args => (src, dst, count); intrinsic); + let src = src.load_scalar(fx); + let dst = dst.load_scalar(fx); + let count = count.load_scalar(fx); + let elem_ty = substs.type_at(0); let elem_size: u64 = fx.layout_of(elem_ty).size.bytes(); assert_eq!(args.len(), 3); - let byte_amount = if elem_size != 1 { - fx.bcx.ins().imul_imm(count, elem_size as i64) - } else { - count - }; + let byte_amount = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; if intrinsic == sym::copy_nonoverlapping { // FIXME emit_small_memcpy @@ -381,17 +352,19 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME emit_small_memmove fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } - }; - // NOTE: the volatile variants have src and dst swapped - volatile_copy_memory | volatile_copy_nonoverlapping_memory, (v dst, v src, v count) { + } + sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => { + // NOTE: the volatile variants have src and dst swapped + intrinsic_args!(fx, args => (dst, src, count); intrinsic); + let dst = dst.load_scalar(fx); + let src = src.load_scalar(fx); + let count = count.load_scalar(fx); + let elem_ty = substs.type_at(0); let elem_size: u64 = fx.layout_of(elem_ty).size.bytes(); assert_eq!(args.len(), 3); - let byte_amount = if elem_size != 1 { - fx.bcx.ins().imul_imm(count, elem_size as i64) - } else { - count - }; + let byte_amount = + if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; // FIXME make the copy actually volatile when using emit_small_mem{cpy,move} if intrinsic == sym::volatile_copy_nonoverlapping_memory { @@ -401,8 +374,10 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME emit_small_memmove fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } - }; - size_of_val, (c ptr) { + } + sym::size_of_val => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); // Note: Can't use is_unsized here as truly unsized types need to take the fixed size // branch @@ -411,14 +386,13 @@ fn codegen_regular_intrinsic_call<'tcx>( let (size, _align) = crate::unsize::size_and_align_of_dst(fx, layout, info); size } else { - fx - .bcx - .ins() - .iconst(fx.pointer_type, layout.size.bytes() as i64) + fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64) }; ret.write_cvalue(fx, CValue::by_val(size, usize_layout)); - }; - min_align_of_val, (c ptr) { + } + sym::min_align_of_val => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); // Note: Can't use is_unsized here as truly unsized types need to take the fixed size // branch @@ -427,26 +401,37 @@ fn codegen_regular_intrinsic_call<'tcx>( let (_size, align) = crate::unsize::size_and_align_of_dst(fx, layout, info); align } else { - fx - .bcx - .ins() - .iconst(fx.pointer_type, layout.align.abi.bytes() as i64) + fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64) }; ret.write_cvalue(fx, CValue::by_val(align, usize_layout)); - }; + } + + sym::vtable_size => { + intrinsic_args!(fx, args => (vtable); intrinsic); + let vtable = vtable.load_scalar(fx); - vtable_size, (v vtable) { let size = crate::vtable::size_of_obj(fx, vtable); ret.write_cvalue(fx, CValue::by_val(size, usize_layout)); - }; + } + + sym::vtable_align => { + intrinsic_args!(fx, args => (vtable); intrinsic); + let vtable = vtable.load_scalar(fx); - vtable_align, (v vtable) { let align = crate::vtable::min_align_of_obj(fx, vtable); ret.write_cvalue(fx, CValue::by_val(align, usize_layout)); - }; + } + + sym::unchecked_add + | sym::unchecked_sub + | sym::unchecked_mul + | sym::unchecked_div + | sym::exact_div + | sym::unchecked_rem + | sym::unchecked_shl + | sym::unchecked_shr => { + intrinsic_args!(fx, args => (x, y); intrinsic); - unchecked_add | unchecked_sub | unchecked_mul | unchecked_div | exact_div | unchecked_rem - | unchecked_shl | unchecked_shr, (c x, c y) { // FIXME trap on overflow let bin_op = match intrinsic { sym::unchecked_add => BinOp::Add, @@ -460,8 +445,10 @@ fn codegen_regular_intrinsic_call<'tcx>( }; let res = crate::num::codegen_int_binop(fx, bin_op, x, y); ret.write_cvalue(fx, res); - }; - add_with_overflow | sub_with_overflow | mul_with_overflow, (c x, c y) { + } + sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { + intrinsic_args!(fx, args => (x, y); intrinsic); + assert_eq!(x.layout().ty, y.layout().ty); let bin_op = match intrinsic { sym::add_with_overflow => BinOp::Add, @@ -470,15 +457,12 @@ fn codegen_regular_intrinsic_call<'tcx>( _ => unreachable!(), }; - let res = crate::num::codegen_checked_int_binop( - fx, - bin_op, - x, - y, - ); + let res = crate::num::codegen_checked_int_binop(fx, bin_op, x, y); ret.write_cvalue(fx, res); - }; - saturating_add | saturating_sub, (c lhs, c rhs) { + } + sym::saturating_add | sym::saturating_sub => { + intrinsic_args!(fx, args => (lhs, rhs); intrinsic); + assert_eq!(lhs.layout().ty, rhs.layout().ty); let bin_op = match intrinsic { sym::saturating_add => BinOp::Add, @@ -488,12 +472,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let signed = type_sign(lhs.layout().ty); - let checked_res = crate::num::codegen_checked_int_binop( - fx, - bin_op, - lhs, - rhs, - ); + let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs); let (val, has_overflow) = checked_res.load_scalar_pair(fx); let clif_ty = fx.clif_type(lhs.layout().ty).unwrap(); @@ -505,13 +484,15 @@ fn codegen_regular_intrinsic_call<'tcx>( (sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val), (sym::saturating_add, true) => { let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let rhs_ge_zero = + fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); fx.bcx.ins().select(has_overflow, sat_val, val) } (sym::saturating_sub, true) => { let rhs = rhs.load_scalar(fx); - let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); + let rhs_ge_zero = + fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0); let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max); fx.bcx.ins().select(has_overflow, sat_val, val) } @@ -521,23 +502,32 @@ fn codegen_regular_intrinsic_call<'tcx>( let res = CValue::by_val(val, lhs.layout()); ret.write_cvalue(fx, res); - }; - rotate_left, (c x, v y) { + } + sym::rotate_left => { + intrinsic_args!(fx, args => (x, y); intrinsic); + let y = y.load_scalar(fx); + let layout = x.layout(); let x = x.load_scalar(fx); let res = fx.bcx.ins().rotl(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); - }; - rotate_right, (c x, v y) { + } + sym::rotate_right => { + intrinsic_args!(fx, args => (x, y); intrinsic); + let y = y.load_scalar(fx); + let layout = x.layout(); let x = x.load_scalar(fx); let res = fx.bcx.ins().rotr(x, y); ret.write_cvalue(fx, CValue::by_val(res, layout)); - }; + } // The only difference between offset and arith_offset is regarding UB. Because Cranelift // doesn't have UB both are codegen'ed the same way - offset | arith_offset, (c base, v offset) { + sym::offset | sym::arith_offset => { + intrinsic_args!(fx, args => (base, offset); intrinsic); + let offset = offset.load_scalar(fx); + let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty; let pointee_size = fx.layout_of(pointee_ty).size.bytes(); let ptr_diff = if pointee_size != 1 { @@ -548,12 +538,18 @@ fn codegen_regular_intrinsic_call<'tcx>( let base_val = base.load_scalar(fx); let res = fx.bcx.ins().iadd(base_val, ptr_diff); ret.write_cvalue(fx, CValue::by_val(res, base.layout())); - }; + } + + sym::transmute => { + intrinsic_args!(fx, args => (from); intrinsic); - transmute, (c from) { ret.write_cvalue_transmute(fx, from); - }; - write_bytes | volatile_set_memory, (c dst, v val, v count) { + } + sym::write_bytes | sym::volatile_set_memory => { + intrinsic_args!(fx, args => (dst, val, count); intrinsic); + let val = val.load_scalar(fx); + let count = count.load_scalar(fx); + let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty; let pointee_size = fx.layout_of(pointee_ty).size.bytes(); let count = if pointee_size != 1 { @@ -565,34 +561,42 @@ fn codegen_regular_intrinsic_call<'tcx>( // FIXME make the memset actually volatile when switching to emit_small_memset // FIXME use emit_small_memset fx.bcx.call_memset(fx.target_config, dst_ptr, val, count); - }; - ctlz | ctlz_nonzero, (c arg) { + } + sym::ctlz | sym::ctlz_nonzero => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + // FIXME trap on `ctlz_nonzero` with zero arg. let res = fx.bcx.ins().clz(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - cttz | cttz_nonzero, (c arg) { + } + sym::cttz | sym::cttz_nonzero => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + // FIXME trap on `cttz_nonzero` with zero arg. let res = fx.bcx.ins().ctz(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - ctpop, (c arg) { + } + sym::ctpop => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = fx.bcx.ins().popcnt(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - bitreverse, (c arg) { + } + sym::bitreverse => { + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = fx.bcx.ins().bitrev(val); let res = CValue::by_val(res, arg.layout()); ret.write_cvalue(fx, res); - }; - bswap, (c arg) { + } + sym::bswap => { // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value { match bcx.func.dfg.value_type(v) { @@ -668,11 +672,15 @@ fn codegen_regular_intrinsic_call<'tcx>( ty => unreachable!("bswap {}", ty), } } + intrinsic_args!(fx, args => (arg); intrinsic); let val = arg.load_scalar(fx); + let res = CValue::by_val(swap(&mut fx.bcx, val), arg.layout()); ret.write_cvalue(fx, res); - }; - assert_inhabited | assert_zero_valid | assert_uninit_valid, () { + } + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { + intrinsic_args!(fx, args => (); intrinsic); + let layout = fx.layout_of(substs.type_at(0)); if layout.abi.is_uninhabited() { with_no_trimmed_paths!({ @@ -689,7 +697,10 @@ fn codegen_regular_intrinsic_call<'tcx>( with_no_trimmed_paths!({ crate::base::codegen_panic( fx, - &format!("attempted to zero-initialize type `{}`, which is invalid", layout.ty), + &format!( + "attempted to zero-initialize type `{}`, which is invalid", + layout.ty + ), source_info, ); }); @@ -700,41 +711,53 @@ fn codegen_regular_intrinsic_call<'tcx>( with_no_trimmed_paths!({ crate::base::codegen_panic( fx, - &format!("attempted to leave type `{}` uninitialized, which is invalid", layout.ty), + &format!( + "attempted to leave type `{}` uninitialized, which is invalid", + layout.ty + ), source_info, ) }); return; } - }; + } + + sym::volatile_load | sym::unaligned_volatile_load => { + intrinsic_args!(fx, args => (ptr); intrinsic); - volatile_load | unaligned_volatile_load, (c ptr) { // Cranelift treats loads as volatile by default // FIXME correctly handle unaligned_volatile_load - let inner_layout = - fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty); + let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty); let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout); ret.write_cvalue(fx, val); - }; - volatile_store | unaligned_volatile_store, (v ptr, c val) { + } + sym::volatile_store | sym::unaligned_volatile_store => { + intrinsic_args!(fx, args => (ptr, val); intrinsic); + let ptr = ptr.load_scalar(fx); + // Cranelift treats stores as volatile by default // FIXME correctly handle unaligned_volatile_store let dest = CPlace::for_ptr(Pointer::new(ptr), val.layout()); dest.write_cvalue(fx, val); - }; + } + + sym::pref_align_of + | sym::needs_drop + | sym::type_id + | sym::type_name + | sym::variant_count => { + intrinsic_args!(fx, args => (); intrinsic); - pref_align_of | needs_drop | type_id | type_name | variant_count, () { let const_val = fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap(); - let val = crate::constant::codegen_const_value( - fx, - const_val, - ret.layout().ty, - ); + let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); - }; + } - ptr_offset_from | ptr_offset_from_unsigned, (v ptr, v base) { + sym::ptr_offset_from | sym::ptr_offset_from_unsigned => { + intrinsic_args!(fx, args => (ptr, base); intrinsic); + let ptr = ptr.load_scalar(fx); + let base = base.load_scalar(fx); let ty = substs.type_at(0); let pointee_size: u64 = fx.layout_of(ty).size.bytes(); @@ -750,31 +773,44 @@ fn codegen_regular_intrinsic_call<'tcx>( CValue::by_val(fx.bcx.ins().sdiv_imm(diff_bytes, pointee_size as i64), isize_layout) }; ret.write_cvalue(fx, val); - }; + } + + sym::ptr_guaranteed_eq => { + intrinsic_args!(fx, args => (a, b); intrinsic); - ptr_guaranteed_eq, (c a, c b) { let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b); ret.write_cvalue(fx, val); - }; + } + + sym::ptr_guaranteed_ne => { + intrinsic_args!(fx, args => (a, b); intrinsic); - ptr_guaranteed_ne, (c a, c b) { let val = crate::num::codegen_ptr_binop(fx, BinOp::Ne, a, b); ret.write_cvalue(fx, val); - }; + } + + sym::caller_location => { + intrinsic_args!(fx, args => (); intrinsic); - caller_location, () { let caller_location = fx.get_caller_location(source_info); ret.write_cvalue(fx, caller_location); - }; + } + + _ if intrinsic.as_str().starts_with("atomic_fence") => { + intrinsic_args!(fx, args => (); intrinsic); - _ if intrinsic.as_str().starts_with("atomic_fence"), () { fx.bcx.ins().fence(); - }; - _ if intrinsic.as_str().starts_with("atomic_singlethreadfence"), () { + } + _ if intrinsic.as_str().starts_with("atomic_singlethreadfence") => { + intrinsic_args!(fx, args => (); intrinsic); + // FIXME use a compiler fence once Cranelift supports it fx.bcx.ins().fence(); - }; - _ if intrinsic.as_str().starts_with("atomic_load"), (v ptr) { + } + _ if intrinsic.as_str().starts_with("atomic_load") => { + intrinsic_args!(fx, args => (ptr); intrinsic); + let ptr = ptr.load_scalar(fx); + let ty = substs.type_at(0); match ty.kind() { ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => { @@ -786,7 +822,9 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().jump(ret_block, &[]); return; } else { - fx.tcx.sess.span_fatal(source_info.span, "128bit atomics not yet supported"); + fx.tcx + .sess + .span_fatal(source_info.span, "128bit atomics not yet supported"); } } ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -801,8 +839,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = CValue::by_val(val, fx.layout_of(ty)); ret.write_cvalue(fx, val); - }; - _ if intrinsic.as_str().starts_with("atomic_store"), (v ptr, c val) { + } + _ if intrinsic.as_str().starts_with("atomic_store") => { + intrinsic_args!(fx, args => (ptr, val); intrinsic); + let ptr = ptr.load_scalar(fx); + let ty = substs.type_at(0); match ty.kind() { ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => { @@ -814,7 +855,9 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().jump(ret_block, &[]); return; } else { - fx.tcx.sess.span_fatal(source_info.span, "128bit atomics not yet supported"); + fx.tcx + .sess + .span_fatal(source_info.span, "128bit atomics not yet supported"); } } ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -827,8 +870,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let val = val.load_scalar(fx); fx.bcx.ins().atomic_store(MemFlags::trusted(), val, ptr); - }; - _ if intrinsic.as_str().starts_with("atomic_xchg"), (v ptr, c new) { + } + _ if intrinsic.as_str().starts_with("atomic_xchg") => { + intrinsic_args!(fx, args => (ptr, new); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = new.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -845,8 +891,12 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_cxchg"), (v ptr, c test_old, c new) { // both atomic_cxchg_* and atomic_cxchgweak_* + } + _ if intrinsic.as_str().starts_with("atomic_cxchg") => { + // both atomic_cxchg_* and atomic_cxchgweak_* + intrinsic_args!(fx, args => (ptr, test_old, new); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = new.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -862,11 +912,15 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = fx.bcx.ins().atomic_cas(MemFlags::trusted(), ptr, test_old, new); let is_eq = fx.bcx.ins().icmp(IntCC::Equal, old, test_old); - let ret_val = CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout()); + let ret_val = + CValue::by_val_pair(old, fx.bcx.ins().bint(types::I8, is_eq), ret.layout()); ret.write_cvalue(fx, ret_val) - }; + } + + _ if intrinsic.as_str().starts_with("atomic_xadd") => { + intrinsic_args!(fx, args => (ptr, amount); intrinsic); + let ptr = ptr.load_scalar(fx); - _ if intrinsic.as_str().starts_with("atomic_xadd"), (v ptr, c amount) { let layout = amount.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -879,12 +933,16 @@ fn codegen_regular_intrinsic_call<'tcx>( let amount = amount.load_scalar(fx); - let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount); + let old = + fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount); let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_xsub"), (v ptr, c amount) { + } + _ if intrinsic.as_str().starts_with("atomic_xsub") => { + intrinsic_args!(fx, args => (ptr, amount); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = amount.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -897,12 +955,16 @@ fn codegen_regular_intrinsic_call<'tcx>( let amount = amount.load_scalar(fx); - let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount); + let old = + fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount); let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_and"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_and") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -919,8 +981,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_or"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_or") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -937,8 +1002,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_xor"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_xor") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -955,8 +1023,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_nand"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_nand") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -973,8 +1044,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_max"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_max") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -991,8 +1065,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_umax"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_umax") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1009,8 +1086,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_min"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_min") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1027,8 +1107,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; - _ if intrinsic.as_str().starts_with("atomic_umin"), (v ptr, c src) { + } + _ if intrinsic.as_str().starts_with("atomic_umin") => { + intrinsic_args!(fx, args => (ptr, src); intrinsic); + let ptr = ptr.load_scalar(fx); + let layout = src.layout(); match layout.ty.kind() { ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {} @@ -1045,30 +1128,51 @@ fn codegen_regular_intrinsic_call<'tcx>( let old = CValue::by_val(old, layout); ret.write_cvalue(fx, old); - }; + } + + sym::minnumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); - minnumf32, (v a, v b) { let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); - }; - minnumf64, (v a, v b) { + } + sym::minnumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_min(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); - }; - maxnumf32, (v a, v b) { + } + sym::maxnumf32 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32)); ret.write_cvalue(fx, val); - }; - maxnumf64, (v a, v b) { + } + sym::maxnumf64 => { + intrinsic_args!(fx, args => (a, b); intrinsic); + let a = a.load_scalar(fx); + let b = b.load_scalar(fx); + let val = crate::num::codegen_float_max(fx, a, b); let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64)); ret.write_cvalue(fx, val); - }; + } + + kw::Try => { + intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic); + let f = f.load_scalar(fx); + let data = data.load_scalar(fx); + let _catch_fn = catch_fn.load_scalar(fx); - kw.Try, (v f, v data, v _catch_fn) { // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { call_conv: fx.target_config.default_call_conv, @@ -1081,20 +1185,30 @@ fn codegen_regular_intrinsic_call<'tcx>( let layout = ret.layout(); let ret_val = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size)); ret.write_cvalue(fx, ret_val); - }; + } - fadd_fast | fsub_fast | fmul_fast | fdiv_fast | frem_fast, (c x, c y) { - let res = crate::num::codegen_float_binop(fx, match intrinsic { - sym::fadd_fast => BinOp::Add, - sym::fsub_fast => BinOp::Sub, - sym::fmul_fast => BinOp::Mul, - sym::fdiv_fast => BinOp::Div, - sym::frem_fast => BinOp::Rem, - _ => unreachable!(), - }, x, y); + sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => { + intrinsic_args!(fx, args => (x, y); intrinsic); + + let res = crate::num::codegen_float_binop( + fx, + match intrinsic { + sym::fadd_fast => BinOp::Add, + sym::fsub_fast => BinOp::Sub, + sym::fmul_fast => BinOp::Mul, + sym::fdiv_fast => BinOp::Div, + sym::frem_fast => BinOp::Rem, + _ => unreachable!(), + }, + x, + y, + ); ret.write_cvalue(fx, res); - }; - float_to_int_unchecked, (v f) { + } + sym::float_to_int_unchecked => { + intrinsic_args!(fx, args => (f); intrinsic); + let f = f.load_scalar(fx); + let res = crate::cast::clif_int_or_float_cast( fx, f, @@ -1103,66 +1217,74 @@ fn codegen_regular_intrinsic_call<'tcx>( type_sign(ret.layout().ty), ); ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); - }; + } + + sym::raw_eq => { + intrinsic_args!(fx, args => (lhs_ref, rhs_ref); intrinsic); + let lhs_ref = lhs_ref.load_scalar(fx); + let rhs_ref = rhs_ref.load_scalar(fx); - raw_eq, (v lhs_ref, v rhs_ref) { let size = fx.layout_of(substs.type_at(0)).layout.size(); // FIXME add and use emit_small_memcmp - let is_eq_value = - if size == Size::ZERO { - // No bytes means they're trivially equal - fx.bcx.ins().iconst(types::I8, 1) - } else if let Some(clty) = size.bits().try_into().ok().and_then(Type::int) { - // Can't use `trusted` for these loads; they could be unaligned. - let mut flags = MemFlags::new(); - flags.set_notrap(); - let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); - let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); - let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); - fx.bcx.ins().bint(types::I8, eq) - } else { - // Just call `memcmp` (like slices do in core) when the - // size is too large or it's not a power-of-two. - let signed_bytes = i64::try_from(size.bytes()).unwrap(); - let bytes_val = fx.bcx.ins().iconst(fx.pointer_type, signed_bytes); - let params = vec![AbiParam::new(fx.pointer_type); 3]; - let returns = vec![AbiParam::new(types::I32)]; - let args = &[lhs_ref, rhs_ref, bytes_val]; - let cmp = fx.lib_call("memcmp", params, returns, args)[0]; - let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); - fx.bcx.ins().bint(types::I8, eq) - }; + let is_eq_value = if size == Size::ZERO { + // No bytes means they're trivially equal + fx.bcx.ins().iconst(types::I8, 1) + } else if let Some(clty) = size.bits().try_into().ok().and_then(Type::int) { + // Can't use `trusted` for these loads; they could be unaligned. + let mut flags = MemFlags::new(); + flags.set_notrap(); + let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); + let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); + let eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val); + fx.bcx.ins().bint(types::I8, eq) + } else { + // Just call `memcmp` (like slices do in core) when the + // size is too large or it's not a power-of-two. + let signed_bytes = i64::try_from(size.bytes()).unwrap(); + let bytes_val = fx.bcx.ins().iconst(fx.pointer_type, signed_bytes); + let params = vec![AbiParam::new(fx.pointer_type); 3]; + let returns = vec![AbiParam::new(types::I32)]; + let args = &[lhs_ref, rhs_ref, bytes_val]; + let cmp = fx.lib_call("memcmp", params, returns, args)[0]; + let eq = fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0); + fx.bcx.ins().bint(types::I8, eq) + }; ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); - }; + } + + sym::const_allocate => { + intrinsic_args!(fx, args => (_size, _align); intrinsic); - const_allocate, (c _size, c _align) { // returns a null pointer at runtime. let null = fx.bcx.ins().iconst(fx.pointer_type, 0); ret.write_cvalue(fx, CValue::by_val(null, ret.layout())); - }; + } - const_deallocate, (c _ptr, c _size, c _align) { + sym::const_deallocate => { + intrinsic_args!(fx, args => (_ptr, _size, _align); intrinsic); // nop at runtime. - }; + } + + sym::black_box => { + intrinsic_args!(fx, args => (a); intrinsic); - black_box, (c a) { // FIXME implement black_box semantics ret.write_cvalue(fx, a); - }; + } // FIXME implement variadics in cranelift - va_copy, (o _dest, o _src) { + sym::va_copy | sym::va_arg | sym::va_end => { fx.tcx.sess.span_fatal( source_info.span, "Defining variadic functions is not yet supported by Cranelift", ); - }; - va_arg | va_end, (o _valist) { - fx.tcx.sess.span_fatal( - source_info.span, - "Defining variadic functions is not yet supported by Cranelift", - ); - }; + } + + _ => { + fx.tcx + .sess + .span_fatal(source_info.span, &format!("unsupported intrinsic {}", intrinsic)); + } } let ret_block = fx.get_block(destination.unwrap()); diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index d1ca9edf2e0f1..30e3d112594a6 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -25,13 +25,10 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ret: CPlace<'tcx>, span: Span, ) { - intrinsic_match! { - fx, intrinsic, args, - _ => { - fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); - }; + match intrinsic { + sym::simd_cast => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_cast, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -45,9 +42,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( clif_int_or_float_cast(fx, lane, from_signed, ret_lane_clif_ty, to_signed) }); - }; + } + + sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => { + intrinsic_args!(fx, args => (x, y); intrinsic); - simd_eq | simd_ne | simd_lt | simd_le | simd_gt | simd_ge, (c x, c y) { if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -57,7 +56,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, res_lane_ty, x_lane, y_lane| { let res_lane = match (lane_ty.kind(), intrinsic) { (ty::Uint(_), sym::simd_eq) => fx.bcx.ins().icmp(IntCC::Equal, x_lane, y_lane), - (ty::Uint(_), sym::simd_ne) => fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane), + (ty::Uint(_), sym::simd_ne) => { + fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane) + } (ty::Uint(_), sym::simd_lt) => { fx.bcx.ins().icmp(IntCC::UnsignedLessThan, x_lane, y_lane) } @@ -72,8 +73,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } (ty::Int(_), sym::simd_eq) => fx.bcx.ins().icmp(IntCC::Equal, x_lane, y_lane), - (ty::Int(_), sym::simd_ne) => fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane), - (ty::Int(_), sym::simd_lt) => fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane), + (ty::Int(_), sym::simd_ne) => { + fx.bcx.ins().icmp(IntCC::NotEqual, x_lane, y_lane) + } + (ty::Int(_), sym::simd_lt) => { + fx.bcx.ins().icmp(IntCC::SignedLessThan, x_lane, y_lane) + } (ty::Int(_), sym::simd_le) => { fx.bcx.ins().icmp(IntCC::SignedLessThanOrEqual, x_lane, y_lane) } @@ -84,13 +89,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().icmp(IntCC::SignedGreaterThanOrEqual, x_lane, y_lane) } - (ty::Float(_), sym::simd_eq) => fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane), - (ty::Float(_), sym::simd_ne) => fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane), - (ty::Float(_), sym::simd_lt) => fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane), + (ty::Float(_), sym::simd_eq) => { + fx.bcx.ins().fcmp(FloatCC::Equal, x_lane, y_lane) + } + (ty::Float(_), sym::simd_ne) => { + fx.bcx.ins().fcmp(FloatCC::NotEqual, x_lane, y_lane) + } + (ty::Float(_), sym::simd_lt) => { + fx.bcx.ins().fcmp(FloatCC::LessThan, x_lane, y_lane) + } (ty::Float(_), sym::simd_le) => { fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, x_lane, y_lane) } - (ty::Float(_), sym::simd_gt) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane), + (ty::Float(_), sym::simd_gt) => { + fx.bcx.ins().fcmp(FloatCC::GreaterThan, x_lane, y_lane) + } (ty::Float(_), sym::simd_ge) => { fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, x_lane, y_lane) } @@ -103,10 +116,19 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let res_lane = fx.bcx.ins().bint(ty, res_lane); fx.bcx.ins().ineg(res_lane) }); - }; + } // simd_shuffle32(x: T, y: T, idx: [u32; 32]) -> U - _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) { + _ if intrinsic.as_str().starts_with("simd_shuffle") => { + let (x, y, idx) = match args { + [x, y, idx] => (x, y, idx), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let x = codegen_operand(fx, x); + let y = codegen_operand(fx, y); + if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -119,11 +141,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // version of this intrinsic. let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); match idx_ty.kind() { - ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { - len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len + .try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()) + .unwrap_or_else(|| { span_bug!(span, "could not evaluate shuffle index array length") - }).try_into().unwrap() - } + }) + .try_into() + .unwrap(), _ => { fx.tcx.sess.span_err( span, @@ -154,24 +178,30 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; - let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const"); + let idx_const = crate::constant::mir_operand_get_const_val(fx, idx) + .expect("simd_shuffle* idx not const"); let idx_bytes = match idx_const { ConstValue::ByRef { alloc, offset } => { - let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */); + let size = Size::from_bytes( + 4 * ret_lane_count, /* size_of([u32; ret_lane_count]) */ + ); alloc.inner().get_bytes(fx, alloc_range(offset, size)).unwrap() } _ => unreachable!("{:?}", idx_const), }; - (0..ret_lane_count).map(|i| { - let i = usize::try_from(i).unwrap(); - let idx = rustc_middle::mir::interpret::read_target_uint( - fx.tcx.data_layout.endian, - &idx_bytes[4*i.. 4*i + 4], - ).expect("read_target_uint"); - u16::try_from(idx).expect("try_from u32") - }).collect::>() + (0..ret_lane_count) + .map(|i| { + let i = usize::try_from(i).unwrap(); + let idx = rustc_middle::mir::interpret::read_target_uint( + fx.tcx.data_layout.endian, + &idx_bytes[4 * i..4 * i + 4], + ) + .expect("read_target_uint"); + u16::try_from(idx).expect("try_from u32") + }) + .collect::>() }; for &idx in &indexes { @@ -187,43 +217,63 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap()); out_lane.write_cvalue(fx, in_lane); } - }; + } + + sym::simd_insert => { + let (base, idx, val) = match args { + [base, idx, val] => (base, idx, val), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let base = codegen_operand(fx, base); + let val = codegen_operand(fx, val); - simd_insert, (c base, o idx, c val) { // FIXME validate - let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { + let idx_const = if let Some(idx_const) = + crate::constant::mir_operand_get_const_val(fx, idx) + { idx_const } else { - fx.tcx.sess.span_fatal( - span, - "Index argument for `simd_insert` is not a constant", - ); + fx.tcx.sess.span_fatal(span, "Index argument for `simd_insert` is not a constant"); }; - let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const + .try_to_bits(Size::from_bytes(4 /* u32*/)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { - fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count)); + fx.tcx.sess.span_fatal( + fx.mir.span, + &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count), + ); } ret.write_cvalue(fx, base); let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap())); ret_lane.write_cvalue(fx, val); - }; + } + + sym::simd_extract => { + let (v, idx) = match args { + [v, idx] => (v, idx), + _ => { + bug!("wrong number of args for intrinsic {intrinsic}"); + } + }; + let v = codegen_operand(fx, v); - simd_extract, (c v, o idx) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } - let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) { + let idx_const = if let Some(idx_const) = + crate::constant::mir_operand_get_const_val(fx, idx) + { idx_const } else { - fx.tcx.sess.span_warn( - span, - "Index argument for `simd_extract` is not a constant", - ); + fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); let res = crate::trap::trap_unimplemented_ret_value( fx, ret.layout(), @@ -233,89 +283,105 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; }; - let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const + .try_to_bits(Size::from_bytes(4 /* u32*/)) + .unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { - fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count)); + fx.tcx.sess.span_fatal( + fx.mir.span, + &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count), + ); } let ret_lane = v.value_lane(fx, idx.try_into().unwrap()); ret.write_cvalue(fx, ret_lane); - }; + } + + sym::simd_neg => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_neg, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; } - simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { - match lane_ty.kind() { + simd_for_each_lane( + fx, + a, + ret, + &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { ty::Int(_) => fx.bcx.ins().ineg(lane), ty::Float(_) => fx.bcx.ins().fneg(lane), _ => unreachable!(), - } - }); - }; - - simd_add | simd_sub | simd_mul | simd_div | simd_rem - | simd_shl | simd_shr | simd_and | simd_or | simd_xor, (c x, c y) { - if !x.layout().ty.is_simd() { - report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); - return; - } + }, + ); + } + + sym::simd_add + | sym::simd_sub + | sym::simd_mul + | sym::simd_div + | sym::simd_rem + | sym::simd_shl + | sym::simd_shr + | sym::simd_and + | sym::simd_or + | sym::simd_xor => { + intrinsic_args!(fx, args => (x, y); intrinsic); // FIXME use vector instructions when possible - simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| match ( - lane_ty.kind(), - intrinsic, - ) { - (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), - (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), - - (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), - (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), - (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), - (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), - (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), - - (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), - (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), - (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), - (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), - (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( - "fmodf", - vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], - vec![AbiParam::new(types::F32)], - &[x_lane, y_lane], - )[0], - (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( - "fmod", - vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], - vec![AbiParam::new(types::F64)], - &[x_lane, y_lane], - )[0], - - (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), - (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), - (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), - (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), - (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), - (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), - - _ => unreachable!(), + simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { + match (lane_ty.kind(), intrinsic) { + (ty::Uint(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Uint(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Uint(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Uint(_), sym::simd_div) => fx.bcx.ins().udiv(x_lane, y_lane), + (ty::Uint(_), sym::simd_rem) => fx.bcx.ins().urem(x_lane, y_lane), + + (ty::Int(_), sym::simd_add) => fx.bcx.ins().iadd(x_lane, y_lane), + (ty::Int(_), sym::simd_sub) => fx.bcx.ins().isub(x_lane, y_lane), + (ty::Int(_), sym::simd_mul) => fx.bcx.ins().imul(x_lane, y_lane), + (ty::Int(_), sym::simd_div) => fx.bcx.ins().sdiv(x_lane, y_lane), + (ty::Int(_), sym::simd_rem) => fx.bcx.ins().srem(x_lane, y_lane), + + (ty::Float(_), sym::simd_add) => fx.bcx.ins().fadd(x_lane, y_lane), + (ty::Float(_), sym::simd_sub) => fx.bcx.ins().fsub(x_lane, y_lane), + (ty::Float(_), sym::simd_mul) => fx.bcx.ins().fmul(x_lane, y_lane), + (ty::Float(_), sym::simd_div) => fx.bcx.ins().fdiv(x_lane, y_lane), + (ty::Float(FloatTy::F32), sym::simd_rem) => fx.lib_call( + "fmodf", + vec![AbiParam::new(types::F32), AbiParam::new(types::F32)], + vec![AbiParam::new(types::F32)], + &[x_lane, y_lane], + )[0], + (ty::Float(FloatTy::F64), sym::simd_rem) => fx.lib_call( + "fmod", + vec![AbiParam::new(types::F64), AbiParam::new(types::F64)], + vec![AbiParam::new(types::F64)], + &[x_lane, y_lane], + )[0], + + (ty::Uint(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Uint(_), sym::simd_shr) => fx.bcx.ins().ushr(x_lane, y_lane), + (ty::Uint(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Uint(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Uint(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + (ty::Int(_), sym::simd_shl) => fx.bcx.ins().ishl(x_lane, y_lane), + (ty::Int(_), sym::simd_shr) => fx.bcx.ins().sshr(x_lane, y_lane), + (ty::Int(_), sym::simd_and) => fx.bcx.ins().band(x_lane, y_lane), + (ty::Int(_), sym::simd_or) => fx.bcx.ins().bor(x_lane, y_lane), + (ty::Int(_), sym::simd_xor) => fx.bcx.ins().bxor(x_lane, y_lane), + + _ => unreachable!(), + } }); - }; + } + + sym::simd_fma => { + intrinsic_args!(fx, args => (a, b, c); intrinsic); - simd_fma, (c a, c b, c c) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -333,16 +399,22 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let c_lane = c.value_lane(fx, lane); let res_lane = match lane_ty.kind() { - ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty), - ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty), + ty::Float(FloatTy::F32) => { + fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty) + } + ty::Float(FloatTy::F64) => { + fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty) + } _ => unreachable!(), }; ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } - }; + } + + sym::simd_fmin | sym::simd_fmax => { + intrinsic_args!(fx, args => (x, y); intrinsic); - simd_fmin | simd_fmax, (c x, c y) { if !x.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty); return; @@ -351,7 +423,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // FIXME use vector instructions when possible simd_pair_for_each_lane(fx, x, y, ret, &|fx, lane_ty, _ret_lane_ty, x_lane, y_lane| { match lane_ty.kind() { - ty::Float(_) => {}, + ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } match intrinsic { @@ -360,16 +432,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!(), } }); - }; + } + + sym::simd_round => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_round, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; } - simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { - match lane_ty.kind() { + simd_for_each_lane( + fx, + a, + ret, + &|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() { ty::Float(FloatTy::F32) => fx.lib_call( "roundf", vec![AbiParam::new(types::F32)], @@ -383,11 +460,13 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( &[lane], )[0], _ => unreachable!("{:?}", lane_ty), - } - }); - }; + }, + ); + } + + sym::simd_fabs | sym::simd_fsqrt | sym::simd_ceil | sym::simd_floor | sym::simd_trunc => { + intrinsic_args!(fx, args => (a); intrinsic); - simd_fabs | simd_fsqrt | simd_ceil | simd_floor | simd_trunc, (c a) { if !a.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty); return; @@ -395,7 +474,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( simd_for_each_lane(fx, a, ret, &|fx, lane_ty, _ret_lane_ty, lane| { match lane_ty.kind() { - ty::Float(_) => {}, + ty::Float(_) => {} _ => unreachable!("{:?}", lane_ty), } match intrinsic { @@ -407,9 +486,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => unreachable!(), } }); - }; + } + + sym::simd_reduce_add_ordered | sym::simd_reduce_add_unordered => { + intrinsic_args!(fx, args => (v, acc); intrinsic); + let acc = acc.load_scalar(fx); - simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) { // FIXME there must be no acc param for integer vectors if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -423,9 +505,12 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().iadd(a, b) } }); - }; + } + + sym::simd_reduce_mul_ordered | sym::simd_reduce_mul_unordered => { + intrinsic_args!(fx, args => (v, acc); intrinsic); + let acc = acc.load_scalar(fx); - simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v, v acc) { // FIXME there must be no acc param for integer vectors if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); @@ -439,54 +524,66 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( fx.bcx.ins().imul(a, b) } }); - }; + } + + sym::simd_reduce_all => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_all, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce_bool(fx, v, ret, &|fx, a, b| fx.bcx.ins().band(a, b)); - }; + } + + sym::simd_reduce_any => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_any, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce_bool(fx, v, ret, &|fx, a, b| fx.bcx.ins().bor(a, b)); - }; + } + + sym::simd_reduce_and => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_and, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().band(a, b)); - }; + } + + sym::simd_reduce_or => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_or, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().bor(a, b)); - }; + } + + sym::simd_reduce_xor => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_xor, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; } simd_reduce(fx, v, None, ret, &|fx, _ty, a, b| fx.bcx.ins().bxor(a, b)); - }; + } + + sym::simd_reduce_min => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_min, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; @@ -501,9 +598,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; fx.bcx.ins().select(lt, a, b) }); - }; + } + + sym::simd_reduce_max => { + intrinsic_args!(fx, args => (v); intrinsic); - simd_reduce_max, (c v) { if !v.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty); return; @@ -518,9 +617,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; fx.bcx.ins().select(gt, a, b) }); - }; + } + + sym::simd_select => { + intrinsic_args!(fx, args => (m, a, b); intrinsic); - simd_select, (c m, c a, c b) { if !m.layout().ty.is_simd() { report_simd_type_validation_error(fx, intrinsic, span, m.layout().ty); return; @@ -540,15 +641,19 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let b_lane = b.value_lane(fx, lane).load_scalar(fx); let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0); - let res_lane = CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); + let res_lane = + CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout); ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } - }; + } // simd_saturating_* // simd_bitmask // simd_scatter // simd_gather + _ => { + fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic)); + } } } From e34bb03197af68ef03a52ba0acbb9a44c958c253 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 27 Jul 2022 17:41:41 +0200 Subject: [PATCH 003/100] Rustup to rustc 1.64.0-nightly (4d6d601c8 2022-07-26) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 3ab395d89d50e..ca1813a6ed04c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-07-25" +channel = "nightly-2022-07-27" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From e0697a309d8081310f9c94ae5f9fefde0924f670 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 08:39:19 +0000 Subject: [PATCH 004/100] Move output argument from ArchiveBuilder::new to .build() --- src/archive.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index c92c105113954..9d39b4aa661a0 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -19,7 +19,6 @@ enum ArchiveEntry { pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, - dst: PathBuf, use_gnu_style_archive: bool, no_builtin_ranlib: bool, @@ -30,10 +29,9 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session, output: &Path) -> Self { + fn new(sess: &'a Session) -> Self { ArArchiveBuilder { sess, - dst: output.to_path_buf(), use_gnu_style_archive: sess.target.archive_format == "gnu", // FIXME fix builtin ranlib on macOS no_builtin_ranlib: sess.target.is_like_osx, @@ -74,7 +72,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self) -> bool { + fn build(mut self, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder), Gnu(ar::GnuBuilder), @@ -163,7 +161,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let mut builder = if self.use_gnu_style_archive { BuilderKind::Gnu( ar::GnuBuilder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -178,7 +176,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } else { BuilderKind::Bsd( ar::Builder::new( - File::create(&self.dst).unwrap_or_else(|err| { + File::create(output).unwrap_or_else(|err| { sess.fatal(&format!( "error opening destination during archive building: {}", err @@ -209,7 +207,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { // Run ranlib to be able to link the archive let status = std::process::Command::new(ranlib) - .arg(self.dst) + .arg(output) .status() .expect("Couldn't run ranlib"); From 34b37e76ddebb1c231930b530a0ca1e8f3d86c7f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 08:43:15 +0000 Subject: [PATCH 005/100] Inline inject_dll_import_lib --- src/archive.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index 9d39b4aa661a0..e28c3813d3f38 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -219,10 +219,6 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - fn sess(&self) -> &Session { - self.sess - } - fn create_dll_import_lib( _sess: &Session, _lib_name: &str, From 451817e48f7852017dd1ddc27bfa7709d74f646c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:07:49 +0000 Subject: [PATCH 006/100] Introduce an ArchiveBuilderBuilder This avoids monomorphizing all linker code for each codegen backend and will allow passing in extra information to the archive builder from the codegen backend. --- src/archive.rs | 60 +++++++++++++++++++++++++++----------------------- src/lib.rs | 2 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index e28c3813d3f38..b4c7909617079 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -5,7 +5,7 @@ use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; -use rustc_codegen_ssa::back::archive::ArchiveBuilder; +use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use rustc_session::Session; use object::read::archive::ArchiveFile; @@ -17,6 +17,32 @@ enum ArchiveEntry { File(PathBuf), } +pub(crate) struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a> { + Box::new(ArArchiveBuilder { + sess, + use_gnu_style_archive: sess.target.archive_format == "gnu", + // FIXME fix builtin ranlib on macOS + no_builtin_ranlib: sess.target.is_like_osx, + + src_archives: vec![], + entries: vec![], + }) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[rustc_session::cstore::DllImport], + _tmpdir: &Path, + ) -> PathBuf { + bug!("creating dll imports is not supported"); + } +} + pub(crate) struct ArArchiveBuilder<'a> { sess: &'a Session, use_gnu_style_archive: bool, @@ -29,18 +55,6 @@ pub(crate) struct ArArchiveBuilder<'a> { } impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { - fn new(sess: &'a Session) -> Self { - ArArchiveBuilder { - sess, - use_gnu_style_archive: sess.target.archive_format == "gnu", - // FIXME fix builtin ranlib on macOS - no_builtin_ranlib: sess.target.is_like_osx, - - src_archives: vec![], - entries: vec![], - } - } - fn add_file(&mut self, file: &Path) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), @@ -48,10 +62,11 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { )); } - fn add_archive(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()> - where - F: FnMut(&str) -> bool + 'static, - { + fn add_archive( + &mut self, + archive_path: &Path, + mut skip: Box bool + 'static>, + ) -> std::io::Result<()> { let read_cache = ReadCache::new(std::fs::File::open(&archive_path)?); let archive = ArchiveFile::parse(&read_cache).unwrap(); let archive_index = self.src_archives.len(); @@ -72,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { Ok(()) } - fn build(mut self, output: &Path) -> bool { + fn build(mut self: Box, output: &Path) -> bool { enum BuilderKind { Bsd(ar::Builder), Gnu(ar::GnuBuilder), @@ -218,13 +233,4 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { any_members } - - fn create_dll_import_lib( - _sess: &Session, - _lib_name: &str, - _dll_imports: &[rustc_session::cstore::DllImport], - _tmpdir: &Path, - ) -> PathBuf { - bug!("creating dll imports is not supported"); - } } diff --git a/src/lib.rs b/src/lib.rs index 568bb20a3f4a7..bb0793b1deb2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -226,7 +226,7 @@ impl CodegenBackend for CraneliftCodegenBackend { ) -> Result<(), ErrorGuaranteed> { use rustc_codegen_ssa::back::link::link_binary; - link_binary::>(sess, &codegen_results, outputs) + link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) } } From 49e773183e504f4f73cfcb7dfd5a397b8c94be1e Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Thu, 28 Jul 2022 20:08:05 +0100 Subject: [PATCH 007/100] Update to cranelift 0.86 (#1250) --- Cargo.lock | 129 +++++++++++++++++++++++++++-------------- Cargo.toml | 12 ++-- src/abi/pass_mode.rs | 2 +- src/common.rs | 2 +- src/intrinsics/mod.rs | 2 +- src/value_and_place.rs | 4 +- 6 files changed, 97 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 532049c858d4f..352fd39a30826 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" [[package]] name = "ar" @@ -50,18 +50,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8" +checksum = "529ffacce2249ac60edba2941672dfedf3d96558b415d0d8083cd007456e0f55" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea" +checksum = "427d105f617efc8cb55f8d036a7fded2e227892d8780b4985e5551f8d27c4a92" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -77,30 +77,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6" +checksum = "551674bed85b838d45358e3eab4f0ffaa6790c70dc08184204b9a54b41cdb7d1" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2" +checksum = "2b3a63ae57498c3eb495360944a33571754241e15e47e3bcae6082f40fec5866" [[package]] name = "cranelift-entity" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d" +checksum = "11aa8aa624c72cc1c94ea3d0739fa61248260b5b14d3646f51593a88d67f3e6e" [[package]] name = "cranelift-frontend" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c" +checksum = "544ee8f4d1c9559c9aa6d46e7aaeac4a13856d620561094f35527356c7d21bd0" dependencies = [ "cranelift-codegen", "log", @@ -110,15 +110,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b" +checksum = "ed16b14363d929b8c37e3c557d0a7396791b383ecc302141643c054343170aad" [[package]] name = "cranelift-jit" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3c5ed067f2c81577e431f3039148a9c187b33cc79e0d1731fede27d801ec56" +checksum = "0308e7418208639fb96c1a3dc04955fa41c4bc92dfce9106635185f71d5caf46" dependencies = [ "anyhow", "cranelift-codegen", @@ -129,14 +129,14 @@ dependencies = [ "log", "region", "target-lexicon", - "winapi", + "windows-sys", ] [[package]] name = "cranelift-module" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee6784303bf9af235237a4885f7417e09a35df896d38ea969a0081064b3ede4" +checksum = "76979aac10dbcf0c222cd5902565bc93597ac30bbe9d879a2aa5f2402d1561f2" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6" +checksum = "51617cf8744634f2ed3c989c3c40cd6444f63377c6d994adab0d85807f3eb682" dependencies = [ "cranelift-codegen", "libc", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.85.3" +version = "0.86.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf38b2c505db749276793116c0cb30bd096206c7810e471677a453134881881" +checksum = "50e649a13f3951ad3b8cb13a3a774481c12159a98eb386b04583573c57d7cf56" dependencies = [ "anyhow", "cranelift-codegen", @@ -187,9 +187,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -198,9 +198,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "indexmap", ] @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "object" @@ -284,15 +284,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "regalloc2" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c" +checksum = "76ff2e57a7d050308b3fde0f707aa240b491b190e3855f212860f11bb3af4205" dependencies = [ "fxhash", "log", @@ -340,15 +340,15 @@ checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" [[package]] name = "smallvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "target-lexicon" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" [[package]] name = "version_check" @@ -358,9 +358,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" @@ -383,3 +383,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index 61e977e3e69bf..3f343a49e0cee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.85.3", features = ["unwind", "all-arch"] } -cranelift-frontend = "0.85.3" -cranelift-module = "0.85.3" -cranelift-native = "0.85.3" -cranelift-jit = { version = "0.85.3", optional = true } -cranelift-object = "0.85.3" +cranelift-codegen = { version = "0.86.1", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.86.1" +cranelift-module = "0.86.1" +cranelift-native = "0.86.1" +cranelift-jit = { version = "0.86.1", optional = true } +cranelift-object = "0.86.1" target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} object = { version = "0.28.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 6c10baa53d415..2f8c697bd1e02 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -23,7 +23,7 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam { (RegKind::Integer, 9..=16) => types::I128, (RegKind::Float, 4) => types::F32, (RegKind::Float, 8) => types::F64, - (RegKind::Vector, size) => types::I8.by(u16::try_from(size).unwrap()).unwrap(), + (RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(), _ => unreachable!("{:?}", reg), }; AbiParam::new(clif_ty) diff --git a/src/common.rs b/src/common.rs index f9dc1b5169e1a..fc4953cea6fe0 100644 --- a/src/common.rs +++ b/src/common.rs @@ -74,7 +74,7 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option unreachable!(), }; - match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) { + match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { // Cranelift currently only implements icmp for 128bit vectors. Some(vector_ty) if vector_ty.bits() == 128 => vector_ty, _ => return None, diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index b2a83e1d4ebc9..f552c13958d57 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -53,7 +53,7 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx _ => unreachable!(), }; - match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) { + match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { // Cranelift currently only implements icmp for 128bit vectors. Some(vector_ty) if vector_ty.bits() == 128 => Some(vector_ty), _ => None, diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 45ae2bd8f07cb..e48d095d13962 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -122,7 +122,7 @@ impl<'tcx> CValue<'tcx> { let clif_ty = match layout.abi { Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar), Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element) - .by(u16::try_from(count).unwrap()) + .by(u32::try_from(count).unwrap()) .unwrap(), _ => unreachable!("{:?}", layout.ty), }; @@ -519,7 +519,7 @@ impl<'tcx> CPlace<'tcx> { if let ty::Array(element, len) = dst_layout.ty.kind() { // Can only happen for vector types let len = - u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); + u32::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap(); let data = match from.0 { From 6fd1660650c8bf8d00ccdf53506f3eedf67f40fd Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 29 Jul 2022 08:39:18 +0100 Subject: [PATCH 008/100] Add Windows build artifacts to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5aeaf3a178804..38dd5b260638e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ perf.data.old *.string* /y.bin /y.bin.dSYM +/y.exe +/y.pdb /build /build_sysroot/sysroot_src /build_sysroot/compiler-builtins From 3ce83dc4697ad6698ae45e6cdefa8ae3894c57a3 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 10:32:54 +0100 Subject: [PATCH 009/100] Move test.sh to y.rs test --- .cirrus.yml | 2 +- .github/workflows/main.yml | 2 +- build_system/build_backend.rs | 5 +- build_system/build_sysroot.rs | 12 +- build_system/mod.rs | 42 ++- build_system/prepare.rs | 3 +- build_system/tests.rs | 504 ++++++++++++++++++++++++++++++++++ build_system/utils.rs | 24 +- config.txt | 33 +++ scripts/tests.sh | 203 -------------- test.sh | 13 - 11 files changed, 605 insertions(+), 238 deletions(-) create mode 100644 build_system/tests.rs delete mode 100755 scripts/tests.sh delete mode 100755 test.sh diff --git a/.cirrus.yml b/.cirrus.yml index 61da6a2491c52..732edd66196d7 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,4 +22,4 @@ task: - # Reduce amount of benchmark runs as they are slow - export COMPILE_RUNS=2 - export RUN_RUNS=2 - - ./test.sh + - ./y.rs test diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa556a21bf8c3..a36c570ddc814 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -103,7 +103,7 @@ jobs: # Enable extra checks export CG_CLIF_ENABLE_VERIFIER=1 - ./test.sh + ./y.rs test - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 48faec8bc4b94..04f8be6f8206a 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -1,12 +1,11 @@ use std::env; -use std::path::{Path, PathBuf}; use std::process::Command; pub(crate) fn build_backend( channel: &str, host_triple: &str, use_unstable_features: bool, -) -> PathBuf { +) { let mut cmd = Command::new("cargo"); cmd.arg("build").arg("--target").arg(host_triple); @@ -38,6 +37,4 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); - - Path::new("target").join(host_triple).join(channel) } diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 16cce83dd9c85..dddd5a673c529 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -10,10 +10,12 @@ pub(crate) fn build_sysroot( channel: &str, sysroot_kind: SysrootKind, target_dir: &Path, - cg_clif_build_dir: PathBuf, + cg_clif_build_dir: &Path, host_triple: &str, target_triple: &str, ) { + eprintln!("[BUILD] sysroot {:?}", sysroot_kind); + if target_dir.exists() { fs::remove_dir_all(target_dir).unwrap(); } @@ -35,11 +37,17 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { + let wrapper_name = if cfg!(windows) { + format!("{wrapper}.exe") + } else { + wrapper.to_string() + }; + let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd .arg(PathBuf::from("scripts").join(format!("{wrapper}.rs"))) .arg("-o") - .arg(target_dir.join(wrapper)) + .arg(target_dir.join(wrapper_name)) .arg("-g"); spawn_and_wait(build_cargo_wrapper_cmd); } diff --git a/build_system/mod.rs b/build_system/mod.rs index b897b7fbacfcd..d1f8ad3e817a5 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -1,5 +1,5 @@ use std::env; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; use std::process; mod build_backend; @@ -8,6 +8,7 @@ mod config; mod prepare; mod rustc_info; mod utils; +mod tests; fn usage() { eprintln!("Usage:"); @@ -15,6 +16,9 @@ fn usage() { eprintln!( " ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); + eprintln!( + " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -25,11 +29,13 @@ macro_rules! arg_error { }}; } +#[derive(PartialEq, Debug)] enum Command { Build, + Test, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub(crate) enum SysrootKind { None, Clif, @@ -52,6 +58,7 @@ pub fn main() { process::exit(0); } Some("build") => Command::Build, + Some("test") => Command::Test, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -115,14 +122,27 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = + let cg_clif_build_dir = Path::new("target").join(&host_triple).join(&channel); + + if command == Command::Test { + // TODO: Should we also build_backend here? + tests::run_tests( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ).expect("Failed to run tests"); + } else { build_backend::build_backend(channel, &host_triple, use_unstable_features); - build_sysroot::build_sysroot( - channel, - sysroot_kind, - &target_dir, - cg_clif_build_dir, - &host_triple, - &target_triple, - ); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 8bb00352d3fe3..7e0fd182d984a 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -50,8 +50,7 @@ pub(crate) fn prepare() { spawn_and_wait(build_cmd); fs::copy( Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), - // FIXME use get_file_name here too once testing is migrated to rust - "simple-raytracer/raytracer_cg_llvm", + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), ) .unwrap(); } diff --git a/build_system/tests.rs b/build_system/tests.rs new file mode 100644 index 0000000000000..74e4b51095fc3 --- /dev/null +++ b/build_system/tests.rs @@ -0,0 +1,504 @@ +use super::build_sysroot; +use super::config; +use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; +use build_system::SysrootKind; +use std::env; +use std::ffi::OsStr; +use std::fs; +use std::path::{Path, PathBuf}; +use std::process::Command; + +type Result = std::result::Result>; + +struct TestCase { + config: &'static str, + func: &'static dyn Fn(&TestRunner), +} + +impl TestCase { + const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self { + Self { config, func } + } +} + +const NO_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("build.mini_core", &|runner| { + runner.run_rustc(["example/mini_core.rs", "--crate-name", "mini_core", "--crate-type", "lib,dylib", "--target", &runner.target_triple]); + }), + + TestCase::new("build.example", &|runner| { + runner.run_rustc(["example/example.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + }), + + TestCase::new("jit.mini_core_hello_world", &|runner| { + let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); + spawn_and_wait(jit_cmd); + + eprintln!("[JIT-lazy] mini_core_hello_world"); + let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); + spawn_and_wait(jit_cmd); + }), + + TestCase::new("aot.mini_core_hello_world", &|runner| { + runner.run_rustc(["example/mini_core_hello_world.rs", "--crate-name", "mini_core_hello_world", "--crate-type", "bin", "-g", "--target", &runner.target_triple]); + runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); + }), +]; + + +const BASE_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| { + runner.run_rustc(["example/arbitrary_self_types_pointers_and_wrappers.rs", "--crate-name", "arbitrary_self_types_pointers_and_wrappers", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []); + }), + + TestCase::new("aot.issue_91827_extern_types", &|runner| { + runner.run_rustc(["example/issue-91827-extern-types.rs", "--crate-name", "issue_91827_extern_types", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("issue_91827_extern_types", []); + }), + + TestCase::new("build.alloc_system", &|runner| { + runner.run_rustc(["example/alloc_system.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + }), + + TestCase::new("aot.alloc_example", &|runner| { + runner.run_rustc(["example/alloc_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("alloc_example", []); + }), + + TestCase::new("jit.std_example", &|runner| { + runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + + eprintln!("[JIT-lazy] std_example"); + runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + }), + + TestCase::new("aot.std_example", &|runner| { + runner.run_rustc(["example/std_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("std_example", ["arg"]); + }), + + TestCase::new("aot.dst_field_align", &|runner| { + runner.run_rustc(["example/dst-field-align.rs", "--crate-name", "dst_field_align", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("dst_field_align", []); + }), + + TestCase::new("aot.subslice-patterns-const-eval", &|runner| { + runner.run_rustc(["example/subslice-patterns-const-eval.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("subslice-patterns-const-eval", []); + }), + + TestCase::new("aot.track-caller-attribute", &|runner| { + runner.run_rustc(["example/track-caller-attribute.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("track-caller-attribute", []); + }), + + TestCase::new("aot.float-minmax-pass", &|runner| { + runner.run_rustc(["example/float-minmax-pass.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_out_command("float-minmax-pass", []); + }), + + TestCase::new("aot.mod_bench", &|runner| { + runner.run_rustc(["example/mod_bench.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_out_command("mod_bench", []); + }), +]; + +const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ + TestCase::new("test.rust-random/rand", &|runner| { + runner.in_dir(["rand"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + eprintln!("[TEST] rust-random/rand"); + runner.run_cargo(["test", "--workspace"]); + } else { + eprintln!("[AOT] rust-random/rand"); + runner.run_cargo(["build", "--workspace", "--target", &runner.target_triple, "--tests"]); + } + }); + }), + + TestCase::new("bench.simple-raytracer", &|runner| { + runner.in_dir(["simple-raytracer"], |runner| { + let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()); + + if runner.host_triple == runner.target_triple { + eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); + let mut bench_compile = Command::new("hyperfine"); + bench_compile.arg("--runs"); + bench_compile.arg(&run_runs); + bench_compile.arg("--warmup"); + bench_compile.arg("1"); + bench_compile.arg("--prepare"); + bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"]))); + + if cfg!(windows) { + bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\""); + } else { + bench_compile.arg("RUSTFLAGS='' cargo build"); + } + + bench_compile.arg(format!("{:?}", runner.cargo_command(["build"]))); + spawn_and_wait(bench_compile); + + + + eprintln!("[BENCH RUN] ebobby/simple-raytracer"); + fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")).unwrap(); + + let mut bench_run = Command::new("hyperfine"); + bench_run.arg("--runs"); + bench_run.arg(&run_runs); + bench_run.arg(PathBuf::from("./raytracer_cg_llvm")); + bench_run.arg(PathBuf::from("./raytracer_cg_clif")); + spawn_and_wait(bench_run); + } else { + runner.run_cargo(["clean"]); + eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)"); + eprintln!("[COMPILE] ebobby/simple-raytracer"); + runner.run_cargo(["build", "--target", &runner.target_triple]); + eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)"); + } + }); + }), + + TestCase::new("test.libcore", &|runner| { + runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test"]); + } else { + eprintln!("Cross-Compiling: Not running tests"); + runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]); + } + }); + }), + + TestCase::new("test.regex-shootout-regex-dna", &|runner| { + runner.in_dir(["regex"], |runner| { + runner.run_cargo(["clean"]); + + // newer aho_corasick versions throw a deprecation warning + let mut lint_rust_flags = runner.rust_flags.clone(); + lint_rust_flags.push("--cap-lints".to_string()); + lint_rust_flags.push("warn".to_string()); + + let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + build_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + + spawn_and_wait(build_cmd); + + if runner.host_triple == runner.target_triple { + let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + run_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + + + let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); + let expected_path = PathBuf::from("examples/regexdna-output.txt"); + let expected = fs::read_to_string(&expected_path).unwrap(); + + let output = spawn_and_wait_with_input(run_cmd, input); + // Make sure `[codegen mono items] start` doesn't poison the diff + let output = output.lines() + .filter(|line| !line.contains("codegen mono items")) + .filter(|line| !line.contains("Spawned thread")) + .chain(Some("")) // This just adds the trailing newline + .collect::>() + .join("\r\n"); + + + if output != expected { + let res_path = PathBuf::from("res.txt"); + fs::write(&res_path, &output).unwrap(); + + if cfg!(windows) { + println!("Output files don't match!"); + println!("Expected Output:\n{}", expected); + println!("Actual Output:\n{}", output); + } else { + let mut diff = Command::new("diff"); + diff.arg("-u"); + diff.arg(res_path); + diff.arg(expected_path); + spawn_and_wait(diff); + } + + std::process::exit(1); + } + } + }); + }), + + TestCase::new("test.regex", &|runner| { + runner.in_dir(["regex"], |runner| { + runner.run_cargo(["clean"]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + } else { + eprintln!("Cross-Compiling: Not running tests"); + runner.run_cargo(["build", "--tests", "--target", &runner.target_triple]); + } + }); + }), + + TestCase::new("test.portable-simd", &|runner| { + runner.in_dir(["portable-simd"], |runner| { + runner.run_cargo(["clean"]); + runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]); + + if runner.host_triple == runner.target_triple { + runner.run_cargo(["test", "-q"]); + } + }); + }), +]; + + + +pub(crate) fn run_tests( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: &Path, + host_triple: &str, + target_triple: &str, +) -> Result<()> { + let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string()); + + if config::get_bool("testsuite.no_sysroot") { + build_sysroot::build_sysroot( + channel, + SysrootKind::None, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); + + let _ = remove_out_dir(); + runner.run_testsuite(NO_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] no_sysroot tests"); + } + + let run_base_sysroot = config::get_bool("testsuite.base_sysroot"); + let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot"); + + if run_base_sysroot || run_extended_sysroot { + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } + + if run_base_sysroot { + runner.run_testsuite(BASE_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] base_sysroot tests"); + } + + if run_extended_sysroot { + runner.run_testsuite(EXTENDED_SYSROOT_SUITE); + } else { + eprintln!("[SKIP] extended_sysroot tests"); + } + + Ok(()) +} + + +fn remove_out_dir() -> Result<()> { + let out_dir = Path::new("target").join("out"); + Ok(fs::remove_dir_all(out_dir)?) +} + +struct TestRunner { + root_dir: PathBuf, + out_dir: PathBuf, + jit_supported: bool, + rust_flags: Vec, + run_wrapper: Vec, + host_triple: String, + target_triple: String, +} + +impl TestRunner { + pub fn new(host_triple: String, target_triple: String) -> Self { + let root_dir = env::current_dir().unwrap(); + + let mut out_dir = root_dir.clone(); + out_dir.push("target"); + out_dir.push("out"); + + let is_native = host_triple == target_triple; + let jit_supported = target_triple.contains("x86_64") && is_native; + + let env_rust_flags = env::var("RUSTFLAGS").ok(); + let env_run_wrapper = env::var("RUN_WRAPPER").ok(); + + let mut rust_flags: Vec<&str> = env_rust_flags.iter().map(|s| s.as_str()).collect(); + let mut run_wrapper: Vec<&str> = env_run_wrapper.iter().map(|s| s.as_str()).collect(); + + if !is_native { + match target_triple.as_str() { + "aarch64-unknown-linux-gnu" => { + // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. + rust_flags.insert(0, "-Clinker=aarch64-linux-gnu-gcc"); + run_wrapper.extend(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]); + }, + "x86_64-pc-windows-gnu" => { + // We are cross-compiling for Windows. Run tests in wine. + run_wrapper.push("wine".into()); + } + _ => { + println!("Unknown non-native platform"); + } + } + } + + // FIXME fix `#[linkage = "extern_weak"]` without this + if host_triple.contains("darwin") { + rust_flags.push("-Clink-arg=-undefined"); + rust_flags.push("-Clink-arg=dynamic_lookup"); + } + + Self { + root_dir, + out_dir, + jit_supported, + rust_flags: rust_flags.iter().map(|s| s.to_string()).collect(), + run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), + host_triple, + target_triple, + } + } + + pub fn run_testsuite(&self, tests: &[TestCase]) { + for &TestCase { config, func } in tests { + let is_jit_test = config.contains("jit"); + let (tag, testname) = config.split_once('.').unwrap(); + let tag = tag.to_uppercase(); + + if !config::get_bool(config) || (is_jit_test && !self.jit_supported) { + eprintln!("[{tag}] {testname} (skipped)"); + continue; + } else { + eprintln!("[{tag}] {testname}"); + } + + func(self); + } + } + + fn in_dir<'a, I, F>(&self, dir: I, callback: F) + where + I: IntoIterator, + F: FnOnce(&TestRunner), + { + let current = env::current_dir().unwrap(); + let mut new = current.clone(); + for d in dir { + new.push(d); + } + + env::set_current_dir(new).unwrap(); + callback(self); + env::set_current_dir(current).unwrap(); + } + + fn rustc_command(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut rustc_clif = self.root_dir.clone(); + rustc_clif.push("build"); + rustc_clif.push("rustc-clif"); + if cfg!(windows) { + rustc_clif.set_extension("exe"); + } + + let mut cmd = Command::new(rustc_clif); + cmd.args(self.rust_flags.iter()); + cmd.arg("-L"); + cmd.arg(format!("crate={}", self.out_dir.display())); + cmd.arg("--out-dir"); + cmd.arg(format!("{}", self.out_dir.display())); + cmd.arg("-Cdebuginfo=2"); + cmd.args(args); + cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd + } + + fn run_rustc(&self, args: I) + where + I: IntoIterator, + S: AsRef, + { + spawn_and_wait(self.rustc_command(args)); + } + + fn run_out_command<'a, I>(&self, name: &str, args: I) + where + I: IntoIterator, + { + let mut full_cmd = vec![]; + + // Prepend the RUN_WRAPPER's + for rw in self.run_wrapper.iter() { + full_cmd.push(rw.to_string()); + } + + full_cmd.push({ + let mut out_path = self.out_dir.clone(); + out_path.push(name); + out_path.to_str().unwrap().to_string() + }); + + for arg in args.into_iter() { + full_cmd.push(arg.to_string()); + } + + let mut cmd_iter = full_cmd.into_iter(); + let first = cmd_iter.next().unwrap(); + + let mut cmd = Command::new(first); + cmd.args(cmd_iter); + + spawn_and_wait(cmd); + } + + fn cargo_command(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut cargo_clif = self.root_dir.clone(); + cargo_clif.push("build"); + cargo_clif.push("cargo-clif"); + if cfg!(windows) { + cargo_clif.set_extension("exe"); + } + + let mut cmd = Command::new(cargo_clif); + cmd.args(args); + cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd + } + + fn run_cargo<'a, I>(&self, args: I) + where + I: IntoIterator, + { + spawn_and_wait(self.cargo_command(args)); + } +} diff --git a/build_system/utils.rs b/build_system/utils.rs index 12b5d70fad853..2d2778d2fc0c7 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,6 +1,7 @@ use std::fs; use std::path::Path; -use std::process::{self, Command}; +use std::process::{self, Command, Stdio}; +use std::io::Write; #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { @@ -18,6 +19,27 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) { } } +#[track_caller] +pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String { + let mut child = cmd + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to spawn child process"); + + let mut stdin = child.stdin.take().expect("Failed to open stdin"); + std::thread::spawn(move || { + stdin.write_all(input.as_bytes()).expect("Failed to write to stdin"); + }); + + let output = child.wait_with_output().expect("Failed to read stdout"); + if !output.status.success() { + process::exit(1); + } + + String::from_utf8(output.stdout).unwrap() +} + pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { for entry in fs::read_dir(from).unwrap() { let entry = entry.unwrap(); diff --git a/config.txt b/config.txt index b14db27d6206f..5e4d230776d51 100644 --- a/config.txt +++ b/config.txt @@ -15,3 +15,36 @@ # This option can be changed while the build system is already running for as long as sysroot # building hasn't started yet. #keep_sysroot + + +# Testsuite +# +# Each test suite item has a corresponding key here. The default is to run all tests. +# Comment any of these lines to skip individual tests. + +testsuite.no_sysroot +build.mini_core +build.example +jit.mini_core_hello_world +aot.mini_core_hello_world + +testsuite.base_sysroot +aot.arbitrary_self_types_pointers_and_wrappers +aot.issue_91827_extern_types +build.alloc_system +aot.alloc_example +jit.std_example +aot.std_example +aot.dst_field_align +aot.subslice-patterns-const-eval +aot.track-caller-attribute +aot.float-minmax-pass +aot.mod_bench + +testsuite.extended_sysroot +test.rust-random/rand +bench.simple-raytracer +test.libcore +test.regex-shootout-regex-dna +test.regex +test.portable-simd diff --git a/scripts/tests.sh b/scripts/tests.sh deleted file mode 100755 index 9b5ffa4096049..0000000000000 --- a/scripts/tests.sh +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/env bash - -set -e - -export CG_CLIF_DISPLAY_CG_TIME=1 -export CG_CLIF_DISABLE_INCR_CACHE=1 - -export HOST_TRIPLE=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ") -export TARGET_TRIPLE=${TARGET_TRIPLE:-$HOST_TRIPLE} - -export RUN_WRAPPER='' - -case "$TARGET_TRIPLE" in - x86_64*) - export JIT_SUPPORTED=1 - ;; - *) - export JIT_SUPPORTED=0 - ;; -esac - -if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then - export JIT_SUPPORTED=0 - if [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then - # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - export RUSTFLAGS='-Clinker=aarch64-linux-gnu-gcc '$RUSTFLAGS - export RUN_WRAPPER='qemu-aarch64 -L /usr/aarch64-linux-gnu' - elif [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then - # We are cross-compiling for Windows. Run tests in wine. - export RUN_WRAPPER='wine' - else - echo "Unknown non-native platform" - fi -fi - -# FIXME fix `#[linkage = "extern_weak"]` without this -if [[ "$(uname)" == 'Darwin' ]]; then - export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" -fi - -MY_RUSTC="$(pwd)/build/rustc-clif $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2" - -function no_sysroot_tests() { - echo "[BUILD] mini_core" - $MY_RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target "$TARGET_TRIPLE" - - echo "[BUILD] example" - $MY_RUSTC example/example.rs --crate-type lib --target "$TARGET_TRIPLE" - - if [[ "$JIT_SUPPORTED" = "1" ]]; then - echo "[JIT] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" - - echo "[JIT-lazy] mini_core_hello_world" - CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE" - else - echo "[JIT] mini_core_hello_world (skipped)" - fi - - echo "[AOT] mini_core_hello_world" - $MY_RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd - # (echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd -} - -function base_sysroot_tests() { - echo "[AOT] arbitrary_self_types_pointers_and_wrappers" - $MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers - - echo "[AOT] issue_91827_extern_types" - $MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/issue_91827_extern_types - - echo "[BUILD] alloc_system" - $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" - - echo "[AOT] alloc_example" - $MY_RUSTC example/alloc_example.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/alloc_example - - if [[ "$JIT_SUPPORTED" = "1" ]]; then - echo "[JIT] std_example" - $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" - - echo "[JIT-lazy] std_example" - $MY_RUSTC -Zunstable-options -Cllvm-args=mode=jit-lazy -Cprefer-dynamic example/std_example.rs --target "$HOST_TRIPLE" - else - echo "[JIT] std_example (skipped)" - fi - - echo "[AOT] std_example" - $MY_RUSTC example/std_example.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/std_example arg - - echo "[AOT] dst_field_align" - $MY_RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/dst_field_align - - echo "[AOT] subslice-patterns-const-eval" - $MY_RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/subslice-patterns-const-eval - - echo "[AOT] track-caller-attribute" - $MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/track-caller-attribute - - echo "[AOT] float-minmax-pass" - $MY_RUSTC example/float-minmax-pass.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/float-minmax-pass - - echo "[AOT] mod_bench" - $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE" - $RUN_WRAPPER ./target/out/mod_bench -} - -function extended_sysroot_tests() { - pushd rand - ../build/cargo-clif clean - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[TEST] rust-random/rand" - ../build/cargo-clif test --workspace - else - echo "[AOT] rust-random/rand" - ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests - fi - popd - - pushd simple-raytracer - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo-clif clean" \ - "RUSTFLAGS='' cargo build" \ - "../build/cargo-clif build" - - echo "[BENCH RUN] ebobby/simple-raytracer" - cp ./target/debug/main ./raytracer_cg_clif - hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif - else - ../build/cargo-clif clean - echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" - echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo-clif build --target $TARGET_TRIPLE - echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" - fi - popd - - pushd build_sysroot/sysroot_src/library/core/tests - echo "[TEST] libcore" - ../../../../../build/cargo-clif clean - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo-clif test - else - ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests - fi - popd - - pushd regex - echo "[TEST] rust-lang/regex example shootout-regex-dna" - ../build/cargo-clif clean - export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning - # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo-clif build --example shootout-regex-dna --target $TARGET_TRIPLE - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - cat examples/regexdna-input.txt \ - | ../build/cargo-clif run --example shootout-regex-dna --target $TARGET_TRIPLE \ - | grep -v "Spawned thread" > res.txt - diff -u res.txt examples/regexdna-output.txt - fi - - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - echo "[TEST] rust-lang/regex tests" - ../build/cargo-clif test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q - else - echo "[AOT] rust-lang/regex tests" - ../build/cargo-clif build --tests --target $TARGET_TRIPLE - fi - popd - - pushd portable-simd - echo "[TEST] rust-lang/portable-simd" - ../build/cargo-clif clean - ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE - if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../build/cargo-clif test -q - fi - popd -} - -case "$1" in - "no_sysroot") - no_sysroot_tests - ;; - "base_sysroot") - base_sysroot_tests - ;; - "extended_sysroot") - extended_sysroot_tests - ;; - *) - echo "unknown test suite" - ;; -esac diff --git a/test.sh b/test.sh deleted file mode 100755 index a10924628bb0e..0000000000000 --- a/test.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -e - -./y.rs build --sysroot none "$@" - -rm -r target/out || true - -scripts/tests.sh no_sysroot - -./y.rs build "$@" - -scripts/tests.sh base_sysroot -scripts/tests.sh extended_sysroot From c115933fb7be123b6dacc6e95cb87ae44e6d5296 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 12:48:46 +0100 Subject: [PATCH 010/100] Run tests on windows CI --- .github/workflows/main.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a36c570ddc814..1a947d3551cb3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,19 +159,21 @@ jobs: ./y.exe prepare - name: Build - #name: Test + run: ./y.exe build + + - name: Test run: | # Enable backtraces for easier debugging - #export RUST_BACKTRACE=1 + export RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - #export COMPILE_RUNS=2 - #export RUN_RUNS=2 + export COMPILE_RUNS=2 + export RUN_RUNS=2 # Enable extra checks - #export CG_CLIF_ENABLE_VERIFIER=1 + export CG_CLIF_ENABLE_VERIFIER=1 - ./y.exe build + ./y.exe test - name: Package prebuilt cg_clif # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs From d0599350a742dfee6f1ff9e60ac91fc2b673a972 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 12:50:05 +0100 Subject: [PATCH 011/100] Misc cleanups to the test runner --- build_system/build_backend.rs | 5 ++- build_system/mod.rs | 45 +++++++++++++------------- build_system/tests.rs | 59 ++++++++++++++--------------------- 3 files changed, 50 insertions(+), 59 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 04f8be6f8206a..ddc099b538823 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -1,11 +1,12 @@ use std::env; +use std::path::{Path, PathBuf}; use std::process::Command; pub(crate) fn build_backend( channel: &str, host_triple: &str, use_unstable_features: bool, -) { +) -> PathBuf { let mut cmd = Command::new("cargo"); cmd.arg("build").arg("--target").arg(host_triple); @@ -37,4 +38,6 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); + + Path::new("target").join(&host_triple).join(&channel) } diff --git a/build_system/mod.rs b/build_system/mod.rs index d1f8ad3e817a5..af75cef04e09e 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -1,5 +1,5 @@ use std::env; -use std::path::{PathBuf, Path}; +use std::path::PathBuf; use std::process; mod build_backend; @@ -122,27 +122,28 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = Path::new("target").join(&host_triple).join(&channel); + let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); - if command == Command::Test { - // TODO: Should we also build_backend here? - tests::run_tests( - channel, - sysroot_kind, - &target_dir, - &cg_clif_build_dir, - &host_triple, - &target_triple, - ).expect("Failed to run tests"); - } else { - build_backend::build_backend(channel, &host_triple, use_unstable_features); - build_sysroot::build_sysroot( - channel, - sysroot_kind, - &target_dir, - &cg_clif_build_dir, - &host_triple, - &target_triple, - ); + match command { + Command::Test => { + tests::run_tests( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + }, + Command::Build => { + build_sysroot::build_sysroot( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } } diff --git a/build_system/tests.rs b/build_system/tests.rs index 74e4b51095fc3..f2166b20fcb22 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -8,8 +8,6 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -type Result = std::result::Result>; - struct TestCase { config: &'static str, func: &'static dyn Fn(&TestRunner), @@ -183,18 +181,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.run_cargo(["clean"]); // newer aho_corasick versions throw a deprecation warning - let mut lint_rust_flags = runner.rust_flags.clone(); - lint_rust_flags.push("--cap-lints".to_string()); - lint_rust_flags.push("warn".to_string()); + let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); - build_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); - run_cmd.env("RUSTFLAGS", lint_rust_flags.join(" ")); + run_cmd.env("RUSTFLAGS", lint_rust_flags); let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); @@ -205,7 +201,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ // Make sure `[codegen mono items] start` doesn't poison the diff let output = output.lines() .filter(|line| !line.contains("codegen mono items")) - .filter(|line| !line.contains("Spawned thread")) .chain(Some("")) // This just adds the trailing newline .collect::>() .join("\r\n"); @@ -267,7 +262,7 @@ pub(crate) fn run_tests( cg_clif_build_dir: &Path, host_triple: &str, target_triple: &str, -) -> Result<()> { +) { let runner = TestRunner::new(host_triple.to_string(), target_triple.to_string()); if config::get_bool("testsuite.no_sysroot") { @@ -280,7 +275,7 @@ pub(crate) fn run_tests( &target_triple, ); - let _ = remove_out_dir(); + let _ = fs::remove_dir_all(Path::new("target").join("out")); runner.run_testsuite(NO_SYSROOT_SUITE); } else { eprintln!("[SKIP] no_sysroot tests"); @@ -311,22 +306,16 @@ pub(crate) fn run_tests( } else { eprintln!("[SKIP] extended_sysroot tests"); } - - Ok(()) } -fn remove_out_dir() -> Result<()> { - let out_dir = Path::new("target").join("out"); - Ok(fs::remove_dir_all(out_dir)?) -} struct TestRunner { root_dir: PathBuf, out_dir: PathBuf, jit_supported: bool, - rust_flags: Vec, - run_wrapper: Vec, + rust_flags: String, + run_wrapper: String, host_triple: String, target_triple: String, } @@ -342,22 +331,19 @@ impl TestRunner { let is_native = host_triple == target_triple; let jit_supported = target_triple.contains("x86_64") && is_native; - let env_rust_flags = env::var("RUSTFLAGS").ok(); - let env_run_wrapper = env::var("RUN_WRAPPER").ok(); - - let mut rust_flags: Vec<&str> = env_rust_flags.iter().map(|s| s.as_str()).collect(); - let mut run_wrapper: Vec<&str> = env_run_wrapper.iter().map(|s| s.as_str()).collect(); + let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); + let mut run_wrapper = String::new(); if !is_native { match target_triple.as_str() { "aarch64-unknown-linux-gnu" => { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - rust_flags.insert(0, "-Clinker=aarch64-linux-gnu-gcc"); - run_wrapper.extend(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]); + rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc {}", rust_flags); + run_wrapper = "qemu-aarch64 -L /usr/aarch64-linux-gnu".to_string(); }, "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. - run_wrapper.push("wine".into()); + run_wrapper = "wine".to_string(); } _ => { println!("Unknown non-native platform"); @@ -367,16 +353,15 @@ impl TestRunner { // FIXME fix `#[linkage = "extern_weak"]` without this if host_triple.contains("darwin") { - rust_flags.push("-Clink-arg=-undefined"); - rust_flags.push("-Clink-arg=dynamic_lookup"); + rust_flags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rust_flags); } Self { root_dir, out_dir, jit_supported, - rust_flags: rust_flags.iter().map(|s| s.to_string()).collect(), - run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), + rust_flags, + run_wrapper, host_triple, target_triple, } @@ -384,9 +369,9 @@ impl TestRunner { pub fn run_testsuite(&self, tests: &[TestCase]) { for &TestCase { config, func } in tests { - let is_jit_test = config.contains("jit"); let (tag, testname) = config.split_once('.').unwrap(); let tag = tag.to_uppercase(); + let is_jit_test = tag == "JIT"; if !config::get_bool(config) || (is_jit_test && !self.jit_supported) { eprintln!("[{tag}] {testname} (skipped)"); @@ -428,14 +413,16 @@ impl TestRunner { } let mut cmd = Command::new(rustc_clif); - cmd.args(self.rust_flags.iter()); + if !self.rust_flags.is_empty() { + cmd.arg(&self.rust_flags); + } cmd.arg("-L"); cmd.arg(format!("crate={}", self.out_dir.display())); cmd.arg("--out-dir"); cmd.arg(format!("{}", self.out_dir.display())); cmd.arg("-Cdebuginfo=2"); cmd.args(args); - cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd.env("RUSTFLAGS", &self.rust_flags); cmd } @@ -454,8 +441,8 @@ impl TestRunner { let mut full_cmd = vec![]; // Prepend the RUN_WRAPPER's - for rw in self.run_wrapper.iter() { - full_cmd.push(rw.to_string()); + if !self.run_wrapper.is_empty() { + full_cmd.push(self.run_wrapper.clone()); } full_cmd.push({ @@ -491,7 +478,7 @@ impl TestRunner { let mut cmd = Command::new(cargo_clif); cmd.args(args); - cmd.env("RUSTFLAGS", self.rust_flags.join(" ")); + cmd.env("RUSTFLAGS", &self.rust_flags); cmd } From 437b441ff5e9fd5e9d837db1cb03529344b41db1 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 13:06:37 +0100 Subject: [PATCH 012/100] Use get_file_name everywhere for better cross compilation support --- build_system/build_sysroot.rs | 11 +++---- build_system/mod.rs | 61 ++++++++++++++++++----------------- build_system/prepare.rs | 6 ++-- build_system/rustc_info.rs | 4 ++- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index dddd5a673c529..14e82a77f86a1 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", target_triple); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,11 +37,10 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = if cfg!(windows) { - format!("{wrapper}.exe") - } else { - wrapper.to_string() - }; + let crate_name = wrapper.replace('-', "_"); + let wrapper_name = get_file_name(&crate_name, "bin", target_triple); + let wrapper_name = wrapper_name.replace('_', "-"); + let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/mod.rs b/build_system/mod.rs index af75cef04e09e..0124d47de7594 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -48,13 +48,42 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); + + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = config::get_value("target") { + target_triple + } else { + host_triple.clone() + }; + + if target_triple.ends_with("-msvc") { + eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); + eprintln!("Switch to the MinGW toolchain for Windows support."); + eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); + eprintln!("set the global default target to MinGW"); + // process::exit(1); + } + + let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { if args.next().is_some() { - arg_error!("./x.rs prepare doesn't expect arguments"); + arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(); + prepare::prepare(&target_triple); process::exit(0); } Some("build") => Command::Build, @@ -95,35 +124,7 @@ pub fn main() { } target_dir = std::env::current_dir().unwrap().join(target_dir); - let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { - host_triple - } else if let Some(host_triple) = config::get_value("host") { - host_triple - } else { - rustc_info::get_host_triple() - }; - let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { - if target_triple != "" { - target_triple - } else { - host_triple.clone() // Empty target triple can happen on GHA - } - } else if let Some(target_triple) = config::get_value("target") { - target_triple - } else { - host_triple.clone() - }; - - if target_triple.ends_with("-msvc") { - eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); - eprintln!("Switch to the MinGW toolchain for Windows support."); - eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); - eprintln!("set the global default target to MinGW"); - process::exit(1); - } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); - match command { Command::Test => { tests::run_tests( diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 7e0fd182d984a..4580c4b654979 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare() { +pub(crate) fn prepare(target_triple: &str) { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare() { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", target_triple)), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", target_triple)), ) .unwrap(); } diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index 9206bb02bd3da..f9689eb2a8c54 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -43,7 +43,7 @@ pub(crate) fn get_default_sysroot() -> PathBuf { Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() } -pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { let file_name = Command::new("rustc") .stderr(Stdio::inherit()) .args(&[ @@ -51,6 +51,8 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { crate_name, "--crate-type", crate_type, + "--target", + target, "--print", "file-names", "-", From ae4fe1d57dd2a00523705f0425a82a759c9bfa3c Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 14:07:02 +0100 Subject: [PATCH 013/100] Use get_file_name in tests --- build_system/build_sysroot.rs | 7 ++----- build_system/rustc_info.rs | 9 +++++++++ build_system/tests.rs | 11 +++-------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 14e82a77f86a1..cd3216cd62439 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -2,7 +2,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::{self, Command}; -use super::rustc_info::{get_file_name, get_rustc_version}; +use super::rustc_info::{get_file_name, get_wrapper_file_name, get_rustc_version}; use super::utils::{spawn_and_wait, try_hard_link}; use super::SysrootKind; @@ -37,10 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let crate_name = wrapper.replace('-', "_"); - let wrapper_name = get_file_name(&crate_name, "bin", target_triple); - let wrapper_name = wrapper_name.replace('_', "-"); - + let wrapper_name = get_wrapper_file_name(wrapper, "bin", target_triple); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index f9689eb2a8c54..63e1d16ead60b 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -65,3 +65,12 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> assert!(file_name.contains(crate_name)); file_name } + +/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to +/// underscores (`_`). This is specially made for the the rustc and cargo wrappers +/// which have a dash in the name, and that is not allowed in a crate name. +pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { + let crate_name = crate_name.replace('-', "_"); + let wrapper_name = get_file_name(&crate_name, crate_type, target); + wrapper_name.replace('_', "-") +} diff --git a/build_system/tests.rs b/build_system/tests.rs index f2166b20fcb22..20d600effd340 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -1,5 +1,6 @@ use super::build_sysroot; use super::config; +use super::rustc_info::get_wrapper_file_name; use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; use build_system::SysrootKind; use std::env; @@ -407,10 +408,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push("rustc-clif"); - if cfg!(windows) { - rustc_clif.set_extension("exe"); - } + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.target_triple)); let mut cmd = Command::new(rustc_clif); if !self.rust_flags.is_empty() { @@ -471,10 +469,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push("cargo-clif"); - if cfg!(windows) { - cargo_clif.set_extension("exe"); - } + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.target_triple)); let mut cmd = Command::new(cargo_clif); cmd.args(args); From aa2f4072f60c5c129a5597cc59ad908aa502868e Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 15:40:44 +0100 Subject: [PATCH 014/100] Use Windows Env vars in CI --- .github/workflows/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a947d3551cb3..832572bcf3596 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -164,14 +164,14 @@ jobs: - name: Test run: | # Enable backtraces for easier debugging - export RUST_BACKTRACE=1 + $Env:RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - export COMPILE_RUNS=2 - export RUN_RUNS=2 + $Env:COMPILE_RUNS=2 + $Env:RUN_RUNS=2 # Enable extra checks - export CG_CLIF_ENABLE_VERIFIER=1 + $Env:CG_CLIF_ENABLE_VERIFIER=1 ./y.exe test From 8ec3d20882f434b9cdbca5c8ed4f3630883b32aa Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 16:35:35 +0100 Subject: [PATCH 015/100] Fix test.regex test --- build_system/tests.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 20d600effd340..22c8c8a4605cd 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -186,7 +186,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); - spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { @@ -233,11 +232,18 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); + // newer aho_corasick versions throw a deprecation warning + let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); + if runner.host_triple == runner.target_triple { - runner.run_cargo(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + let mut run_cmd = runner.cargo_command(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + run_cmd.env("RUSTFLAGS", lint_rust_flags); + spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - runner.run_cargo(["build", "--tests", "--target", &runner.target_triple]); + let mut build_cmd = runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); + build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); + spawn_and_wait(build_cmd); } }); }), From f8747f0a53dc5b1284fab7610df39f4861b311e4 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 20:24:04 +0100 Subject: [PATCH 016/100] Fix aarch64 cross compilation --- build_system/tests.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 22c8c8a4605cd..5c69beeaab5fb 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -322,7 +322,7 @@ struct TestRunner { out_dir: PathBuf, jit_supported: bool, rust_flags: String, - run_wrapper: String, + run_wrapper: Vec, host_triple: String, target_triple: String, } @@ -339,18 +339,18 @@ impl TestRunner { let jit_supported = target_triple.contains("x86_64") && is_native; let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); - let mut run_wrapper = String::new(); + let mut run_wrapper = Vec::new(); if !is_native { match target_triple.as_str() { "aarch64-unknown-linux-gnu" => { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. - rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc {}", rust_flags); - run_wrapper = "qemu-aarch64 -L /usr/aarch64-linux-gnu".to_string(); + rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags); + run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]; }, "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. - run_wrapper = "wine".to_string(); + run_wrapper = vec!["wine"]; } _ => { println!("Unknown non-native platform"); @@ -368,7 +368,7 @@ impl TestRunner { out_dir, jit_supported, rust_flags, - run_wrapper, + run_wrapper: run_wrapper.iter().map(|s| s.to_string()).collect(), host_triple, target_triple, } @@ -446,7 +446,7 @@ impl TestRunner { // Prepend the RUN_WRAPPER's if !self.run_wrapper.is_empty() { - full_cmd.push(self.run_wrapper.clone()); + full_cmd.extend(self.run_wrapper.iter().cloned()); } full_cmd.push({ @@ -459,6 +459,7 @@ impl TestRunner { full_cmd.push(arg.to_string()); } + println!("full_CMD: {:?}", full_cmd); let mut cmd_iter = full_cmd.into_iter(); let first = cmd_iter.next().unwrap(); From 393613439a09c7d2c36832eb532a13f140a46552 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 17:16:10 +0100 Subject: [PATCH 017/100] Fix some cross compilation scenarios in test runner --- build_system/build_sysroot.rs | 4 ++-- build_system/tests.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index cd3216cd62439..ed1c04808c58e 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", target_triple); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", host_triple); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,7 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = get_wrapper_file_name(wrapper, "bin", target_triple); + let wrapper_name = get_wrapper_file_name(wrapper, "bin", host_triple); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/tests.rs b/build_system/tests.rs index 5c69beeaab5fb..bc13066b02088 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -414,7 +414,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.target_triple)); + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); let mut cmd = Command::new(rustc_clif); if !self.rust_flags.is_empty() { @@ -476,7 +476,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.target_triple)); + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.host_triple)); let mut cmd = Command::new(cargo_clif); cmd.args(args); From 6ea108bae3358ffee78fcdfb4b442dd8d81b29b4 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 21:08:21 +0100 Subject: [PATCH 018/100] Split flags whitespace This is probably the wrong way to do this... --- build_system/tests.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index bc13066b02088..e4a776259c06c 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -417,9 +417,7 @@ impl TestRunner { rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); let mut cmd = Command::new(rustc_clif); - if !self.rust_flags.is_empty() { - cmd.arg(&self.rust_flags); - } + cmd.args(self.rust_flags.split_whitespace()); cmd.arg("-L"); cmd.arg(format!("crate={}", self.out_dir.display())); cmd.arg("--out-dir"); From 78372d6b411523bc9d1f081ff3951d39367e8f5f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 21:08:59 +0100 Subject: [PATCH 019/100] Log cloned regex output --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 832572bcf3596..a75c4f97529b8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,6 +79,10 @@ jobs: git config --global user.email "user@example.com" git config --global user.name "User" ./y.rs prepare + + + - name: log expected output + run: cat -e regex/examples/regexdna-output.txt - name: Build without unstable features env: From bec651ef47efae5732e7b17c4d49e2718544d4c8 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:05:39 +0100 Subject: [PATCH 020/100] Compare lines iterator instead of full output This avoids differences in line endings. --- .github/workflows/main.yml | 4 ---- build_system/tests.rs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a75c4f97529b8..832572bcf3596 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,10 +79,6 @@ jobs: git config --global user.email "user@example.com" git config --global user.name "User" ./y.rs prepare - - - - name: log expected output - run: cat -e regex/examples/regexdna-output.txt - name: Build without unstable features env: diff --git a/build_system/tests.rs b/build_system/tests.rs index e4a776259c06c..2c96c5cc1754d 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -206,7 +206,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ .join("\r\n"); - if output != expected { + let output_matches = expected.lines().eq(output.lines()); + if !output_matches { let res_path = PathBuf::from("res.txt"); fs::write(&res_path, &output).unwrap(); @@ -457,7 +458,6 @@ impl TestRunner { full_cmd.push(arg.to_string()); } - println!("full_CMD: {:?}", full_cmd); let mut cmd_iter = full_cmd.into_iter(); let first = cmd_iter.next().unwrap(); From 2f1380036cff86b97de98434b5e59592624d4d54 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:32:06 +0100 Subject: [PATCH 021/100] Cleanup meaningless changes --- build_system/build_backend.rs | 2 +- build_system/mod.rs | 4 ++-- build_system/prepare.rs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index ddc099b538823..48faec8bc4b94 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -39,5 +39,5 @@ pub(crate) fn build_backend( eprintln!("[BUILD] rustc_codegen_cranelift"); super::utils::spawn_and_wait(cmd); - Path::new("target").join(&host_triple).join(&channel) + Path::new("target").join(host_triple).join(channel) } diff --git a/build_system/mod.rs b/build_system/mod.rs index 0124d47de7594..3a6d58a2a6df8 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -73,7 +73,7 @@ pub fn main() { eprintln!("Switch to the MinGW toolchain for Windows support."); eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); eprintln!("set the global default target to MinGW"); - // process::exit(1); + process::exit(1); } @@ -83,7 +83,7 @@ pub fn main() { if args.next().is_some() { arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(&target_triple); + prepare::prepare(&host_triple); process::exit(0); } Some("build") => Command::Build, diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 4580c4b654979..b499aaa703cd3 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare(target_triple: &str) { +pub(crate) fn prepare(host_triple: &str) { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare(target_triple: &str) { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", target_triple)), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", target_triple)), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", host_triple)), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", host_triple)), ) .unwrap(); } From 5d7936650d174515730458b29b83e99153365d89 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 22:58:34 +0100 Subject: [PATCH 022/100] Don't run tests on Windows CI --- .github/workflows/main.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 832572bcf3596..e8897e9ae8145 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -159,21 +159,19 @@ jobs: ./y.exe prepare - name: Build - run: ./y.exe build - - - name: Test + #name: Test run: | # Enable backtraces for easier debugging - $Env:RUST_BACKTRACE=1 + #$Env:RUST_BACKTRACE=1 # Reduce amount of benchmark runs as they are slow - $Env:COMPILE_RUNS=2 - $Env:RUN_RUNS=2 + #$Env:COMPILE_RUNS=2 + #$Env:RUN_RUNS=2 # Enable extra checks - $Env:CG_CLIF_ENABLE_VERIFIER=1 + #$Env:CG_CLIF_ENABLE_VERIFIER=1 - ./y.exe test + ./y.exe build - name: Package prebuilt cg_clif # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs From f588bfa0956dbd7880c08a22c612e9831df2e3d8 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 23:04:59 +0100 Subject: [PATCH 023/100] Assume host target in get_file_name --- build_system/build_sysroot.rs | 4 +-- build_system/mod.rs | 58 +++++++++++++++++------------------ build_system/prepare.rs | 6 ++-- build_system/rustc_info.rs | 8 ++--- build_system/tests.rs | 4 +-- 5 files changed, 38 insertions(+), 42 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index ed1c04808c58e..6e4b57cf4d309 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -23,7 +23,7 @@ pub(crate) fn build_sysroot( fs::create_dir_all(target_dir.join("lib")).unwrap(); // Copy the backend - let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib", host_triple); + let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib"); let cg_clif_dylib_path = target_dir .join(if cfg!(windows) { // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the @@ -37,7 +37,7 @@ pub(crate) fn build_sysroot( // Build and copy rustc and cargo wrappers for wrapper in ["rustc-clif", "cargo-clif"] { - let wrapper_name = get_wrapper_file_name(wrapper, "bin", host_triple); + let wrapper_name = get_wrapper_file_name(wrapper, "bin"); let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd diff --git a/build_system/mod.rs b/build_system/mod.rs index 3a6d58a2a6df8..4772a5a77784e 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -48,42 +48,13 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); - - let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { - host_triple - } else if let Some(host_triple) = config::get_value("host") { - host_triple - } else { - rustc_info::get_host_triple() - }; - let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { - if target_triple != "" { - target_triple - } else { - host_triple.clone() // Empty target triple can happen on GHA - } - } else if let Some(target_triple) = config::get_value("target") { - target_triple - } else { - host_triple.clone() - }; - - if target_triple.ends_with("-msvc") { - eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); - eprintln!("Switch to the MinGW toolchain for Windows support."); - eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); - eprintln!("set the global default target to MinGW"); - process::exit(1); - } - - let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { if args.next().is_some() { arg_error!("./y.rs prepare doesn't expect arguments"); } - prepare::prepare(&host_triple); + prepare::prepare(); process::exit(0); } Some("build") => Command::Build, @@ -124,6 +95,33 @@ pub fn main() { } target_dir = std::env::current_dir().unwrap().join(target_dir); + let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") { + host_triple + } else if let Some(host_triple) = config::get_value("host") { + host_triple + } else { + rustc_info::get_host_triple() + }; + let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") { + if target_triple != "" { + target_triple + } else { + host_triple.clone() // Empty target triple can happen on GHA + } + } else if let Some(target_triple) = config::get_value("target") { + target_triple + } else { + host_triple.clone() + }; + + if target_triple.ends_with("-msvc") { + eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift."); + eprintln!("Switch to the MinGW toolchain for Windows support."); + eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to"); + eprintln!("set the global default target to MinGW"); + process::exit(1); + } + let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); match command { Command::Test => { diff --git a/build_system/prepare.rs b/build_system/prepare.rs index b499aaa703cd3..7e0fd182d984a 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -8,7 +8,7 @@ use std::process::Command; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::utils::{copy_dir_recursively, spawn_and_wait}; -pub(crate) fn prepare(host_triple: &str) { +pub(crate) fn prepare() { prepare_sysroot(); eprintln!("[INSTALL] hyperfine"); @@ -49,8 +49,8 @@ pub(crate) fn prepare(host_triple: &str) { build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer"); spawn_and_wait(build_cmd); fs::copy( - Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin", host_triple)), - Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin", host_triple)), + Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), + Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), ) .unwrap(); } diff --git a/build_system/rustc_info.rs b/build_system/rustc_info.rs index 63e1d16ead60b..913b589afcc87 100644 --- a/build_system/rustc_info.rs +++ b/build_system/rustc_info.rs @@ -43,7 +43,7 @@ pub(crate) fn get_default_sysroot() -> PathBuf { Path::new(String::from_utf8(default_sysroot).unwrap().trim()).to_owned() } -pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { +pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { let file_name = Command::new("rustc") .stderr(Stdio::inherit()) .args(&[ @@ -51,8 +51,6 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> crate_name, "--crate-type", crate_type, - "--target", - target, "--print", "file-names", "-", @@ -69,8 +67,8 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str, target: &str) -> /// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to /// underscores (`_`). This is specially made for the the rustc and cargo wrappers /// which have a dash in the name, and that is not allowed in a crate name. -pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str, target: &str) -> String { +pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String { let crate_name = crate_name.replace('-', "_"); - let wrapper_name = get_file_name(&crate_name, crate_type, target); + let wrapper_name = get_file_name(&crate_name, crate_type); wrapper_name.replace('_', "-") } diff --git a/build_system/tests.rs b/build_system/tests.rs index 2c96c5cc1754d..2b4ae39a75ea8 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -415,7 +415,7 @@ impl TestRunner { { let mut rustc_clif = self.root_dir.clone(); rustc_clif.push("build"); - rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin", &self.host_triple)); + rustc_clif.push(get_wrapper_file_name("rustc-clif", "bin")); let mut cmd = Command::new(rustc_clif); cmd.args(self.rust_flags.split_whitespace()); @@ -474,7 +474,7 @@ impl TestRunner { { let mut cargo_clif = self.root_dir.clone(); cargo_clif.push("build"); - cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin", &self.host_triple)); + cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin")); let mut cmd = Command::new(cargo_clif); cmd.args(args); From d489fb9a59338051e1f488c87d8ee55bd25e0208 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 23:07:03 +0100 Subject: [PATCH 024/100] Don't pass RUSTFLAGS to rustc in tests --- build_system/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 2b4ae39a75ea8..f6f3f4831e15d 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -425,7 +425,6 @@ impl TestRunner { cmd.arg(format!("{}", self.out_dir.display())); cmd.arg("-Cdebuginfo=2"); cmd.args(args); - cmd.env("RUSTFLAGS", &self.rust_flags); cmd } From 0db9094231138fb29895fc181d534a2a547d168a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 31 Jul 2022 10:15:56 +0000 Subject: [PATCH 025/100] Rustfmt --- build_system/build_sysroot.rs | 2 +- build_system/mod.rs | 7 +- build_system/tests.rs | 234 ++++++++++++++++++++++++++-------- build_system/utils.rs | 2 +- 4 files changed, 187 insertions(+), 58 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 6e4b57cf4d309..7e205b0fd0b3b 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -2,7 +2,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::{self, Command}; -use super::rustc_info::{get_file_name, get_wrapper_file_name, get_rustc_version}; +use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name}; use super::utils::{spawn_and_wait, try_hard_link}; use super::SysrootKind; diff --git a/build_system/mod.rs b/build_system/mod.rs index 4772a5a77784e..8c7d05993a51b 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -7,8 +7,8 @@ mod build_sysroot; mod config; mod prepare; mod rustc_info; -mod utils; mod tests; +mod utils; fn usage() { eprintln!("Usage:"); @@ -122,7 +122,8 @@ pub fn main() { process::exit(1); } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple, use_unstable_features); + let cg_clif_build_dir = + build_backend::build_backend(channel, &host_triple, use_unstable_features); match command { Command::Test => { tests::run_tests( @@ -133,7 +134,7 @@ pub fn main() { &host_triple, &target_triple, ); - }, + } Command::Build => { build_sysroot::build_sysroot( channel, diff --git a/build_system/tests.rs b/build_system/tests.rs index f6f3f4831e15d..3f225b4efa2b1 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -22,85 +22,195 @@ impl TestCase { const NO_SYSROOT_SUITE: &[TestCase] = &[ TestCase::new("build.mini_core", &|runner| { - runner.run_rustc(["example/mini_core.rs", "--crate-name", "mini_core", "--crate-type", "lib,dylib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mini_core.rs", + "--crate-name", + "mini_core", + "--crate-type", + "lib,dylib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("build.example", &|runner| { - runner.run_rustc(["example/example.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/example.rs", + "--crate-type", + "lib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("jit.mini_core_hello_world", &|runner| { - let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + let mut jit_cmd = runner.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit", + "-Cprefer-dynamic", + "example/mini_core_hello_world.rs", + "--cfg", + "jit", + "--target", + &runner.host_triple, + ]); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); spawn_and_wait(jit_cmd); eprintln!("[JIT-lazy] mini_core_hello_world"); - let mut jit_cmd = runner.rustc_command(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/mini_core_hello_world.rs", "--cfg", "jit", "--target", &runner.host_triple]); + let mut jit_cmd = runner.rustc_command([ + "-Zunstable-options", + "-Cllvm-args=mode=jit-lazy", + "-Cprefer-dynamic", + "example/mini_core_hello_world.rs", + "--cfg", + "jit", + "--target", + &runner.host_triple, + ]); jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd"); spawn_and_wait(jit_cmd); }), - TestCase::new("aot.mini_core_hello_world", &|runner| { - runner.run_rustc(["example/mini_core_hello_world.rs", "--crate-name", "mini_core_hello_world", "--crate-type", "bin", "-g", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mini_core_hello_world.rs", + "--crate-name", + "mini_core_hello_world", + "--crate-type", + "bin", + "-g", + "--target", + &runner.target_triple, + ]); runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]); }), ]; - const BASE_SYSROOT_SUITE: &[TestCase] = &[ TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| { - runner.run_rustc(["example/arbitrary_self_types_pointers_and_wrappers.rs", "--crate-name", "arbitrary_self_types_pointers_and_wrappers", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/arbitrary_self_types_pointers_and_wrappers.rs", + "--crate-name", + "arbitrary_self_types_pointers_and_wrappers", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []); }), - TestCase::new("aot.issue_91827_extern_types", &|runner| { - runner.run_rustc(["example/issue-91827-extern-types.rs", "--crate-name", "issue_91827_extern_types", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/issue-91827-extern-types.rs", + "--crate-name", + "issue_91827_extern_types", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("issue_91827_extern_types", []); }), - TestCase::new("build.alloc_system", &|runner| { - runner.run_rustc(["example/alloc_system.rs", "--crate-type", "lib", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/alloc_system.rs", + "--crate-type", + "lib", + "--target", + &runner.target_triple, + ]); }), - TestCase::new("aot.alloc_example", &|runner| { - runner.run_rustc(["example/alloc_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/alloc_example.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("alloc_example", []); }), - TestCase::new("jit.std_example", &|runner| { - runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + runner.run_rustc([ + "-Zunstable-options", + "-Cllvm-args=mode=jit", + "-Cprefer-dynamic", + "example/std_example.rs", + "--target", + &runner.host_triple, + ]); eprintln!("[JIT-lazy] std_example"); - runner.run_rustc(["-Zunstable-options", "-Cllvm-args=mode=jit-lazy", "-Cprefer-dynamic", "example/std_example.rs", "--target", &runner.host_triple]); + runner.run_rustc([ + "-Zunstable-options", + "-Cllvm-args=mode=jit-lazy", + "-Cprefer-dynamic", + "example/std_example.rs", + "--target", + &runner.host_triple, + ]); }), - TestCase::new("aot.std_example", &|runner| { - runner.run_rustc(["example/std_example.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/std_example.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("std_example", ["arg"]); }), - TestCase::new("aot.dst_field_align", &|runner| { - runner.run_rustc(["example/dst-field-align.rs", "--crate-name", "dst_field_align", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/dst-field-align.rs", + "--crate-name", + "dst_field_align", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("dst_field_align", []); }), - TestCase::new("aot.subslice-patterns-const-eval", &|runner| { - runner.run_rustc(["example/subslice-patterns-const-eval.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/subslice-patterns-const-eval.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("subslice-patterns-const-eval", []); }), - TestCase::new("aot.track-caller-attribute", &|runner| { - runner.run_rustc(["example/track-caller-attribute.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/track-caller-attribute.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("track-caller-attribute", []); }), - TestCase::new("aot.float-minmax-pass", &|runner| { - runner.run_rustc(["example/float-minmax-pass.rs", "--crate-type", "bin", "-Cpanic=abort", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/float-minmax-pass.rs", + "--crate-type", + "bin", + "-Cpanic=abort", + "--target", + &runner.target_triple, + ]); runner.run_out_command("float-minmax-pass", []); }), - TestCase::new("aot.mod_bench", &|runner| { - runner.run_rustc(["example/mod_bench.rs", "--crate-type", "bin", "--target", &runner.target_triple]); + runner.run_rustc([ + "example/mod_bench.rs", + "--crate-type", + "bin", + "--target", + &runner.target_triple, + ]); runner.run_out_command("mod_bench", []); }), ]; @@ -115,11 +225,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ runner.run_cargo(["test", "--workspace"]); } else { eprintln!("[AOT] rust-random/rand"); - runner.run_cargo(["build", "--workspace", "--target", &runner.target_triple, "--tests"]); + runner.run_cargo([ + "build", + "--workspace", + "--target", + &runner.target_triple, + "--tests", + ]); } }); }), - TestCase::new("bench.simple-raytracer", &|runner| { runner.in_dir(["simple-raytracer"], |runner| { let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()); @@ -143,10 +258,9 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ bench_compile.arg(format!("{:?}", runner.cargo_command(["build"]))); spawn_and_wait(bench_compile); - - eprintln!("[BENCH RUN] ebobby/simple-raytracer"); - fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")).unwrap(); + fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")) + .unwrap(); let mut bench_run = Command::new("hyperfine"); bench_run.arg("--runs"); @@ -163,7 +277,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.libcore", &|runner| { runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| { runner.run_cargo(["clean"]); @@ -176,7 +289,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.regex-shootout-regex-dna", &|runner| { runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); @@ -184,28 +296,40 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ // newer aho_corasick versions throw a deprecation warning let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); - let mut build_cmd = runner.cargo_command(["build", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + let mut build_cmd = runner.cargo_command([ + "build", + "--example", + "shootout-regex-dna", + "--target", + &runner.target_triple, + ]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); if runner.host_triple == runner.target_triple { - let mut run_cmd = runner.cargo_command(["run", "--example", "shootout-regex-dna", "--target", &runner.target_triple]); + let mut run_cmd = runner.cargo_command([ + "run", + "--example", + "shootout-regex-dna", + "--target", + &runner.target_triple, + ]); run_cmd.env("RUSTFLAGS", lint_rust_flags); - - let input = fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); + let input = + fs::read_to_string(PathBuf::from("examples/regexdna-input.txt")).unwrap(); let expected_path = PathBuf::from("examples/regexdna-output.txt"); let expected = fs::read_to_string(&expected_path).unwrap(); let output = spawn_and_wait_with_input(run_cmd, input); // Make sure `[codegen mono items] start` doesn't poison the diff - let output = output.lines() + let output = output + .lines() .filter(|line| !line.contains("codegen mono items")) .chain(Some("")) // This just adds the trailing newline .collect::>() .join("\r\n"); - let output_matches = expected.lines().eq(output.lines()); if !output_matches { let res_path = PathBuf::from("res.txt"); @@ -228,7 +352,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ } }); }), - TestCase::new("test.regex", &|runner| { runner.in_dir(["regex"], |runner| { runner.run_cargo(["clean"]); @@ -237,18 +360,27 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); if runner.host_triple == runner.target_triple { - let mut run_cmd = runner.cargo_command(["test", "--tests", "--", "--exclude-should-panic", "--test-threads", "1", "-Zunstable-options", "-q"]); + let mut run_cmd = runner.cargo_command([ + "test", + "--tests", + "--", + "--exclude-should-panic", + "--test-threads", + "1", + "-Zunstable-options", + "-q", + ]); run_cmd.env("RUSTFLAGS", lint_rust_flags); spawn_and_wait(run_cmd); } else { eprintln!("Cross-Compiling: Not running tests"); - let mut build_cmd = runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); + let mut build_cmd = + runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); spawn_and_wait(build_cmd); } }); }), - TestCase::new("test.portable-simd", &|runner| { runner.in_dir(["portable-simd"], |runner| { runner.run_cargo(["clean"]); @@ -261,8 +393,6 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ }), ]; - - pub(crate) fn run_tests( channel: &str, sysroot_kind: SysrootKind, @@ -316,8 +446,6 @@ pub(crate) fn run_tests( } } - - struct TestRunner { root_dir: PathBuf, out_dir: PathBuf, @@ -348,7 +476,7 @@ impl TestRunner { // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu. rust_flags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rust_flags); run_wrapper = vec!["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu"]; - }, + } "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. run_wrapper = vec!["wine"]; diff --git a/build_system/utils.rs b/build_system/utils.rs index 2d2778d2fc0c7..3282778e25486 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,7 +1,7 @@ use std::fs; +use std::io::Write; use std::path::Path; use std::process::{self, Command, Stdio}; -use std::io::Write; #[track_caller] pub(crate) fn try_hard_link(src: impl AsRef, dst: impl AsRef) { From 46fa744e6914bb4f09bc250f059e1879b65a7160 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 09:49:54 +0100 Subject: [PATCH 026/100] Disable JIT on windows --- build_system/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/tests.rs b/build_system/tests.rs index 3f225b4efa2b1..dc83b10958e01 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -465,7 +465,7 @@ impl TestRunner { out_dir.push("out"); let is_native = host_triple == target_triple; - let jit_supported = target_triple.contains("x86_64") && is_native; + let jit_supported = target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); let mut run_wrapper = Vec::new(); From 8f5330e28c0f694958044752aaea75fa5aeaa211 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 09:57:43 +0100 Subject: [PATCH 027/100] Fix mini_core printf linking on windows Link against legacy_stdio_definitions on windows which provides printf as a linkable symbol. --- example/mini_core.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 8b6042a3d6638..f0e85ca478eea 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -575,11 +575,19 @@ pub mod intrinsics { } pub mod libc { + // With the new Universal CRT, msvc has switched to all the printf functions being inline wrapper + // functions. legacy_stdio_definitions.lib which provides the printf wrapper functions as normal + // symbols to link against. + #[cfg_attr(unix, link(name = "c"))] + #[cfg_attr(target_env="msvc", link(name="legacy_stdio_definitions"))] + extern "C" { + pub fn printf(format: *const i8, ...) -> i32; + } + #[cfg_attr(unix, link(name = "c"))] #[cfg_attr(target_env = "msvc", link(name = "msvcrt"))] extern "C" { pub fn puts(s: *const i8) -> i32; - pub fn printf(format: *const i8, ...) -> i32; pub fn malloc(size: usize) -> *mut u8; pub fn free(ptr: *mut u8); pub fn memcpy(dst: *mut u8, src: *const u8, size: usize); From e0fab632f1bd7473a08d4bb682f1bcc329efe01f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 11:38:56 +0100 Subject: [PATCH 028/100] Add windows support to mini_core tests --- example/mini_core.rs | 2 +- example/mini_core_hello_world.rs | 98 +++++++++++++++++++++++++++----- 2 files changed, 85 insertions(+), 15 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index f0e85ca478eea..42f8aa50ba1a9 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -535,7 +535,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { } #[lang = "box_free"] -unsafe fn box_free(ptr: Unique, alloc: ()) { +unsafe fn box_free(ptr: Unique, _alloc: ()) { libc::free(ptr.pointer.0 as *mut u8); } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index aa1f239bae23e..412320997d507 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -139,7 +139,7 @@ pub struct bool_11 { field10: bool, } -extern "C" fn bool_struct_in_11(arg0: bool_11) {} +extern "C" fn bool_struct_in_11(_arg0: bool_11) {} #[allow(unreachable_code)] // FIXME false positive fn main() { @@ -375,6 +375,7 @@ struct pthread_attr_t { } #[link(name = "pthread")] +#[cfg(not(target_env="msvc"))] extern "C" { fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; @@ -391,6 +392,86 @@ extern "C" { ) -> c_int; } +type DWORD = u32; +type LPDWORD = *mut u32; + +type LPVOID = *mut c_void; +type HANDLE = *mut c_void; + +#[link(name = "msvcrt")] +#[cfg(target_env="msvc")] +extern "C" { + fn WaitForSingleObject( + hHandle: LPVOID, + dwMilliseconds: DWORD + ) -> DWORD; + + fn CreateThread( + lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway + dwStackSize: usize, + lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, + lpParameter: LPVOID, + dwCreationFlags: DWORD, + lpThreadId: LPDWORD + ) -> HANDLE; +} + +enum Thread { + Windows(HANDLE), + Pthread(pthread_t) +} + +impl Thread { + unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self { + #[cfg(not(target_env="msvc"))] + { + let mut attr: pthread_attr_t = zeroed(); + let mut thread: pthread_t = 0; + + if pthread_attr_init(&mut attr) != 0 { + assert!(false); + } + + if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 { + assert!(false); + } + + Thread::Pthread(thread) + } + + #[cfg(target_env="msvc")] + { + let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32); + + if (handle as u64) == 0 { + assert!(false); + } + + Thread::Windows(handle) + } + } + + + unsafe fn join(self) { + match self { + #[cfg(not(target_env="msvc"))] + Thread::Pthread(thread) => { + let mut res = 0 as *mut c_void; + pthread_join(thread, &mut res); + } + #[cfg(target_env="msvc")] + Thread::Windows(handle) => { + let wait_time = 5000; // in milliseconds + assert!(WaitForSingleObject(handle, wait_time) == 0); + } + _ => assert!(false), + } + } +} + + + + #[thread_local] #[cfg(not(jit))] static mut TLS: u8 = 42; @@ -404,21 +485,10 @@ extern "C" fn mutate_tls(_: *mut c_void) -> *mut c_void { #[cfg(not(jit))] fn test_tls() { unsafe { - let mut attr: pthread_attr_t = zeroed(); - let mut thread: pthread_t = 0; - assert_eq!(TLS, 42); - if pthread_attr_init(&mut attr) != 0 { - assert!(false); - } - - if pthread_create(&mut thread, &attr, mutate_tls, 0 as *mut c_void) != 0 { - assert!(false); - } - - let mut res = 0 as *mut c_void; - pthread_join(thread, &mut res); + let thread = Thread::create(mutate_tls); + thread.join(); // TLS of main thread must not have been changed by the other thread. assert_eq!(TLS, 42); From c9bb51961cf9b124c974f61ec4d0da59e4459c0b Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 19:41:08 +0100 Subject: [PATCH 029/100] Misc Cleanups --- example/mini_core_hello_world.rs | 49 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 412320997d507..7e9cbe1bba5c7 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -375,7 +375,7 @@ struct pthread_attr_t { } #[link(name = "pthread")] -#[cfg(not(target_env="msvc"))] +#[cfg(unix)] extern "C" { fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; @@ -399,14 +399,14 @@ type LPVOID = *mut c_void; type HANDLE = *mut c_void; #[link(name = "msvcrt")] -#[cfg(target_env="msvc")] +#[cfg(windows)] extern "C" { fn WaitForSingleObject( hHandle: LPVOID, dwMilliseconds: DWORD ) -> DWORD; - fn CreateThread( + fn CreateThread( lpThreadAttributes: LPVOID, // Technically LPSECURITY_ATTRIBUTES, but we don't use it anyway dwStackSize: usize, lpStartAddress: extern "C" fn(_: *mut c_void) -> *mut c_void, @@ -416,14 +416,16 @@ extern "C" { ) -> HANDLE; } -enum Thread { - Windows(HANDLE), - Pthread(pthread_t) +struct Thread { + #[cfg(windows)] + handle: HANDLE, + #[cfg(unix)] + handle: pthread_t, } impl Thread { unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self { - #[cfg(not(target_env="msvc"))] + #[cfg(unix)] { let mut attr: pthread_attr_t = zeroed(); let mut thread: pthread_t = 0; @@ -436,10 +438,12 @@ impl Thread { assert!(false); } - Thread::Pthread(thread) + Thread { + handle: thread, + } } - #[cfg(target_env="msvc")] + #[cfg(windows)] { let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32); @@ -447,24 +451,25 @@ impl Thread { assert!(false); } - Thread::Windows(handle) + Thread { + handle, + } } } unsafe fn join(self) { - match self { - #[cfg(not(target_env="msvc"))] - Thread::Pthread(thread) => { - let mut res = 0 as *mut c_void; - pthread_join(thread, &mut res); - } - #[cfg(target_env="msvc")] - Thread::Windows(handle) => { - let wait_time = 5000; // in milliseconds - assert!(WaitForSingleObject(handle, wait_time) == 0); - } - _ => assert!(false), + #[cfg(unix)] + { + let mut res = 0 as *mut c_void; + pthread_join(self.handle, &mut res); + } + + #[cfg(windows)] + { + // The INFINITE macro is used to signal operations that do not timeout. + let infinite = 0xffffffff; + assert!(WaitForSingleObject(self.handle, infinite) == 0); } } } From 8c8fc6af33c0a10340535fb9eb6ab9b7648bf742 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 2 Aug 2022 08:08:45 +0100 Subject: [PATCH 030/100] Use native cranelift instructions when lowering float intrinsics --- src/intrinsics/mod.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index f552c13958d57..77caf741acf3b 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -301,7 +301,38 @@ fn codegen_float_intrinsic_call<'tcx>( _ => unreachable!(), }; - let res = fx.easy_call(name, &args, ty); + let layout = fx.layout_of(ty); + let res = match intrinsic { + sym::copysignf32 | sym::copysignf64 => { + let a = args[0].load_scalar(fx); + let b = args[1].load_scalar(fx); + CValue::by_val(fx.bcx.ins().fcopysign(a, b), layout) + } + sym::fabsf32 + | sym::fabsf64 + | sym::floorf32 + | sym::floorf64 + | sym::ceilf32 + | sym::ceilf64 + | sym::truncf32 + | sym::truncf64 => { + let a = args[0].load_scalar(fx); + + let val = match intrinsic { + sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(a), + sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(a), + sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(a), + sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(a), + _ => unreachable!(), + }; + + CValue::by_val(val, layout) + } + // These intrinsics aren't supported natively by Cranelift. + // Lower them to a libcall. + _ => fx.easy_call(name, &args, ty), + }; + ret.write_cvalue(fx, res); true From 012acdf8aeb86087ec34214a33f01e81c6a847b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:13:36 +0000 Subject: [PATCH 031/100] Update dependencies --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 352fd39a30826..069f8cda1fae3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" [[package]] name = "ar" @@ -232,9 +232,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" [[package]] name = "libloading" @@ -290,9 +290,9 @@ checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "regalloc2" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ff2e57a7d050308b3fde0f707aa240b491b190e3855f212860f11bb3af4205" +checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" dependencies = [ "fxhash", "log", From 41d547892c03a34b32666f9c629147742fae579f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:13:57 +0000 Subject: [PATCH 032/100] Re-introduce test.sh as convenience wrapper around ./y.rs test --- test.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 test.sh diff --git a/test.sh b/test.sh new file mode 100755 index 0000000000000..3d929a1d50ce2 --- /dev/null +++ b/test.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +exec ./y.rs test From e7bc81cc772b37757077f6b0574eeb5382af3ac4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 12:57:19 +0000 Subject: [PATCH 033/100] Disable incr comp globally on CI --- build_system/build_backend.rs | 7 +++---- build_system/mod.rs | 7 +++++++ build_system/utils.rs | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index 48faec8bc4b94..cf04967222f7e 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -2,6 +2,8 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::Command; +use super::utils::is_ci; + pub(crate) fn build_backend( channel: &str, host_triple: &str, @@ -14,12 +16,9 @@ pub(crate) fn build_backend( let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default(); - if env::var("CI").as_ref().map(|val| &**val) == Ok("true") { + if is_ci() { // Deny warnings on CI rustflags += " -Dwarnings"; - - // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway - cmd.env("CARGO_BUILD_INCREMENTAL", "false"); } if use_unstable_features { diff --git a/build_system/mod.rs b/build_system/mod.rs index 8c7d05993a51b..88c4150dbba41 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -2,6 +2,8 @@ use std::env; use std::path::PathBuf; use std::process; +use self::utils::is_ci; + mod build_backend; mod build_sysroot; mod config; @@ -48,6 +50,11 @@ pub fn main() { // The target dir is expected in the default location. Guard against the user changing it. env::set_var("CARGO_TARGET_DIR", "target"); + if is_ci() { + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + env::set_var("CARGO_BUILD_INCREMENTAL", "false"); + } + let mut args = env::args().skip(1); let command = match args.next().as_deref() { Some("prepare") => { diff --git a/build_system/utils.rs b/build_system/utils.rs index 3282778e25486..bdf8f8ecd9970 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -1,3 +1,4 @@ +use std::env; use std::fs; use std::io::Write; use std::path::Path; @@ -55,3 +56,7 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { } } } + +pub(crate) fn is_ci() -> bool { + env::var("CI").as_ref().map(|val| &**val) == Ok("true") +} From 3c97227a433c244f34fb8bb23afe41f259431d9b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 5 Aug 2022 13:17:13 +0000 Subject: [PATCH 034/100] Fix previous commit --- build_system/build_backend.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_system/build_backend.rs b/build_system/build_backend.rs index cf04967222f7e..9e59b8199b412 100644 --- a/build_system/build_backend.rs +++ b/build_system/build_backend.rs @@ -19,6 +19,9 @@ pub(crate) fn build_backend( if is_ci() { // Deny warnings on CI rustflags += " -Dwarnings"; + + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + cmd.env("CARGO_BUILD_INCREMENTAL", "false"); } if use_unstable_features { From 3bd9821342d57081aea18cbb53271a20769eaf03 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 13:34:55 +0100 Subject: [PATCH 035/100] Initial ABI Checker support --- .gitignore | 1 + build_system/abi_checker.rs | 67 +++++++++++++++++++++++++++++++++++++ build_system/mod.rs | 16 +++++++++ build_system/prepare.rs | 7 ++++ 4 files changed, 91 insertions(+) create mode 100644 build_system/abi_checker.rs diff --git a/.gitignore b/.gitignore index 38dd5b260638e..6fd3e4443de5c 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ perf.data.old /regex /simple-raytracer /portable-simd +/abi-checker diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs new file mode 100644 index 0000000000000..1aff4acc21b3d --- /dev/null +++ b/build_system/abi_checker.rs @@ -0,0 +1,67 @@ +use super::build_sysroot; +use super::utils::spawn_and_wait_with_input; +use build_system::SysrootKind; +use std::env; +use std::path::Path; +use std::process::Command; + +pub(crate) fn run( + channel: &str, + sysroot_kind: SysrootKind, + target_dir: &Path, + cg_clif_build_dir: &Path, + host_triple: &str, + target_triple: &str, +) { + assert_eq!( + host_triple, target_triple, + "abi-checker not supported on cross-compilation scenarios" + ); + + eprintln!("Building sysroot for abi-checker"); + build_sysroot::build_sysroot( + channel, + sysroot_kind, + target_dir, + cg_clif_build_dir, + host_triple, + target_triple, + ); + + eprintln!("Running abi-checker"); + let mut abi_checker_path = env::current_dir().unwrap(); + abi_checker_path.push("abi-checker"); + env::set_current_dir(abi_checker_path.clone()).unwrap(); + + let build_dir = abi_checker_path.parent().unwrap().join("build"); + let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join( + env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, + ); + println!("cg_clif_dylib_path: {}", cg_clif_dylib_path.display()); + + let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; + + for pair in pairs { + eprintln!("[ABI-CHECKER] Running pair {pair}"); + + let mut cmd = Command::new("cargo"); + cmd.arg("run"); + cmd.arg("--target"); + cmd.arg(target_triple); + cmd.arg("--"); + cmd.arg("--pairs"); + cmd.arg(pair); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); + + let output = spawn_and_wait_with_input(cmd, "".to_string()); + + // TODO: The correct thing to do here is to check the exit code, but abi-checker + // currently doesn't return 0 on success, so check for the test fail count. + // See: https://github.com/Gankra/abi-checker/issues/10 + let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); + if failed { + panic!("abi-checker for pair {} failed!", pair); + } + } +} diff --git a/build_system/mod.rs b/build_system/mod.rs index 88c4150dbba41..c5b3e6619b770 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -4,6 +4,7 @@ use std::process; use self::utils::is_ci; +mod abi_checker; mod build_backend; mod build_sysroot; mod config; @@ -21,6 +22,9 @@ fn usage() { eprintln!( " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); + eprintln!( + " ./y.rs abi-checker [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -35,6 +39,7 @@ macro_rules! arg_error { enum Command { Build, Test, + AbiChecker, } #[derive(Copy, Clone, Debug)] @@ -66,6 +71,7 @@ pub fn main() { } Some("build") => Command::Build, Some("test") => Command::Test, + Some("abi-checker") => Command::AbiChecker, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -152,5 +158,15 @@ pub fn main() { &target_triple, ); } + Command::AbiChecker => { + abi_checker::run( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); + } } } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 7e0fd182d984a..12aafdc1fb3ee 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -14,6 +14,13 @@ pub(crate) fn prepare() { eprintln!("[INSTALL] hyperfine"); Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); + clone_repo_shallow_github( + "abi-checker", + "Gankra", + "abi-checker", + "7c1571da6e43f9a37347623e7d5c7d51be664a7b", + ); + clone_repo_shallow_github( "rand", "rust-random", From fb6362e093eca9ad754327b0134aaee3cb3864c3 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 15:59:45 +0100 Subject: [PATCH 036/100] Test adding abi-checker to CI --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e8897e9ae8145..0b259369e6107 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,6 +105,11 @@ jobs: ./y.rs test + + - name: Run abi-checker + if: matrix.env.TARGET_TRIPLE == '' + run: ./y.rs abi-checker + - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build From 569312278f1d38cd5634d4fd6fa1beef6ded69e2 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 20:51:20 +0100 Subject: [PATCH 037/100] Add abi-checker to clean_all.sh --- clean_all.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clean_all.sh b/clean_all.sh index ea1f8c1e8920a..62e52bd195800 100755 --- a/clean_all.sh +++ b/clean_all.sh @@ -3,4 +3,4 @@ set -e rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf target/ build/ perf.data{,.old} y.bin -rm -rf rand/ regex/ simple-raytracer/ portable-simd/ +rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ From e5ba71a71b79525fdd649624af63fc8770f90835 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 20:51:47 +0100 Subject: [PATCH 038/100] Pass all pairs to abi-checker --- build_system/abi_checker.rs | 41 ++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index 1aff4acc21b3d..21d9afc823138 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -37,31 +37,26 @@ pub(crate) fn run( let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join( env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, ); - println!("cg_clif_dylib_path: {}", cg_clif_dylib_path.display()); let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"]; - for pair in pairs { - eprintln!("[ABI-CHECKER] Running pair {pair}"); - - let mut cmd = Command::new("cargo"); - cmd.arg("run"); - cmd.arg("--target"); - cmd.arg(target_triple); - cmd.arg("--"); - cmd.arg("--pairs"); - cmd.arg(pair); - cmd.arg("--add-rustc-codegen-backend"); - cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); - - let output = spawn_and_wait_with_input(cmd, "".to_string()); - - // TODO: The correct thing to do here is to check the exit code, but abi-checker - // currently doesn't return 0 on success, so check for the test fail count. - // See: https://github.com/Gankra/abi-checker/issues/10 - let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); - if failed { - panic!("abi-checker for pair {} failed!", pair); - } + let mut cmd = Command::new("cargo"); + cmd.arg("run"); + cmd.arg("--target"); + cmd.arg(target_triple); + cmd.arg("--"); + cmd.arg("--pairs"); + cmd.args(pairs); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); + + let output = spawn_and_wait_with_input(cmd, "".to_string()); + + // TODO: The correct thing to do here is to check the exit code, but abi-checker + // currently doesn't return 0 on success, so check for the test fail count. + // See: https://github.com/Gankra/abi-checker/issues/10 + let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); + if failed { + panic!("abi-checker failed!"); } } From 7610be478f9e67a4e0e13cddb50f171e82cc3170 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 6 Aug 2022 21:24:38 +0100 Subject: [PATCH 039/100] Move abi-checker to y.rs test --- .github/workflows/main.yml | 5 ----- build_system/abi_checker.rs | 14 ++++++++++---- build_system/mod.rs | 14 ++++---------- config.txt | 2 ++ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b259369e6107..e8897e9ae8145 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,11 +105,6 @@ jobs: ./y.rs test - - - name: Run abi-checker - if: matrix.env.TARGET_TRIPLE == '' - run: ./y.rs abi-checker - - name: Package prebuilt cg_clif run: tar cvfJ cg_clif.tar.xz build diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index 21d9afc823138..b6dc0fa69223f 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -1,4 +1,5 @@ use super::build_sysroot; +use super::config; use super::utils::spawn_and_wait_with_input; use build_system::SysrootKind; use std::env; @@ -13,10 +14,15 @@ pub(crate) fn run( host_triple: &str, target_triple: &str, ) { - assert_eq!( - host_triple, target_triple, - "abi-checker not supported on cross-compilation scenarios" - ); + if !config::get_bool("testsuite.abi-checker") { + eprintln!("[SKIP] abi-checker"); + return; + } + + if host_triple != target_triple { + eprintln!("[SKIP] abi-checker (cross-compilation not supported)"); + return; + } eprintln!("Building sysroot for abi-checker"); build_sysroot::build_sysroot( diff --git a/build_system/mod.rs b/build_system/mod.rs index c5b3e6619b770..c3706dc6f8203 100644 --- a/build_system/mod.rs +++ b/build_system/mod.rs @@ -22,9 +22,6 @@ fn usage() { eprintln!( " ./y.rs test [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" ); - eprintln!( - " ./y.rs abi-checker [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" - ); } macro_rules! arg_error { @@ -39,7 +36,6 @@ macro_rules! arg_error { enum Command { Build, Test, - AbiChecker, } #[derive(Copy, Clone, Debug)] @@ -71,7 +67,6 @@ pub fn main() { } Some("build") => Command::Build, Some("test") => Command::Test, - Some("abi-checker") => Command::AbiChecker, Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), Some(command) => arg_error!("Unknown command {}", command), None => { @@ -147,9 +142,8 @@ pub fn main() { &host_triple, &target_triple, ); - } - Command::Build => { - build_sysroot::build_sysroot( + + abi_checker::run( channel, sysroot_kind, &target_dir, @@ -158,8 +152,8 @@ pub fn main() { &target_triple, ); } - Command::AbiChecker => { - abi_checker::run( + Command::Build => { + build_sysroot::build_sysroot( channel, sysroot_kind, &target_dir, diff --git a/config.txt b/config.txt index 5e4d230776d51..2264d301d5920 100644 --- a/config.txt +++ b/config.txt @@ -48,3 +48,5 @@ test.libcore test.regex-shootout-regex-dna test.regex test.portable-simd + +testsuite.abi-checker From 8520535694e376b91d63c1243a9080b9f155aeff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 6 Aug 2022 17:18:59 -0400 Subject: [PATCH 040/100] make NOP dyn casts not require anything about the vtable --- src/unsize.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/unsize.rs b/src/unsize.rs index 052ca0a082b3c..dd9d891ddbdee 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -29,6 +29,7 @@ pub(crate) fn unsized_info<'tcx>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } From 1cde1a31a17feb9cd61c65176694f26886ca5e22 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 8 Aug 2022 09:04:26 -0400 Subject: [PATCH 041/100] also update anyhow in codegen_cranelift --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 532049c858d4f..402fbb16f97ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,9 +15,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "c794e162a5eff65c72ef524dfe393eb923c354e350bb78b9c7383df13f3bc142" [[package]] name = "ar" From 526553e4a35926f0a06dbdd48fec904db6483b03 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 8 Aug 2022 18:30:01 +0200 Subject: [PATCH 042/100] Rustup to rustc 1.65.0-nightly (d394408fb 2022-08-07) --- build_sysroot/Cargo.lock | 12 ++++++------ rust-toolchain | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 7b2cdd273366f..e9bd9167acd8b 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.75" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784" +checksum = "413b6b13f725a46cdec40364e0c1d564a22cf0aaac5f1e267a129d956478a6b4" dependencies = [ "rustc-std-workspace-core", ] @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7668753748e445859e4e373c3d41117235d9feed578392f5a3a73efdc751ca4a" +checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6" dependencies = [ "compiler_builtins", "libc", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index ca1813a6ed04c..9b9ed85f6c751 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-07-27" +channel = "nightly-2022-08-08" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From fa6480e43d3b9195fdc2077e32a3ee653409ee89 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 9 Aug 2022 12:27:34 +0000 Subject: [PATCH 043/100] Remove most trap functions and remove all trapnz usages --- src/base.rs | 18 ++++-------------- src/discriminant.rs | 20 +++++++++++--------- src/inline_asm.rs | 18 ++++++++++++++++-- src/intrinsics/cpuid.rs | 2 +- src/intrinsics/llvm.rs | 1 + src/intrinsics/mod.rs | 6 +----- src/intrinsics/simd.rs | 15 ++++++++++----- src/trap.rs | 25 +------------------------ 8 files changed, 45 insertions(+), 60 deletions(-) diff --git a/src/base.rs b/src/base.rs index 122e103ff62bc..2c04cf4726825 100644 --- a/src/base.rs +++ b/src/base.rs @@ -90,7 +90,8 @@ pub(crate) fn codegen_fn<'tcx>( if !crate::constant::check_constants(&mut fx) { fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - crate::trap::trap_unreachable(&mut fx, "compilation should have been aborted"); + // compilation should have been aborted + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } else 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]); @@ -457,17 +458,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { template, operands, *options, + *destination, ); - - match *destination { - Some(destination) => { - let destination_block = fx.get_block(destination); - fx.bcx.ins().jump(destination_block, &[]); - } - None => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } - } } TerminatorKind::Resume | TerminatorKind::Abort => { // FIXME implement unwinding @@ -711,9 +703,7 @@ fn codegen_stmt<'tcx>( Rvalue::Discriminant(place) => { let place = codegen_place(fx, place); let value = place.to_cvalue(fx); - let discr = - crate::discriminant::codegen_get_discriminant(fx, value, dest_layout); - lval.write_cvalue(fx, discr); + crate::discriminant::codegen_get_discriminant(fx, lval, value, dest_layout); } Rvalue::Repeat(ref operand, times) => { let operand = codegen_operand(fx, operand); diff --git a/src/discriminant.rs b/src/discriminant.rs index f619bb5ed5e58..e41ae1fbdbac5 100644 --- a/src/discriminant.rs +++ b/src/discriminant.rs @@ -62,16 +62,14 @@ pub(crate) fn codegen_set_discriminant<'tcx>( pub(crate) fn codegen_get_discriminant<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, + dest: CPlace<'tcx>, value: CValue<'tcx>, dest_layout: TyAndLayout<'tcx>, -) -> CValue<'tcx> { +) { let layout = value.layout(); - if layout.abi == Abi::Uninhabited { - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached); - // Return a dummy value - return CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout); + if layout.abi.is_uninhabited() { + return; } let (tag_scalar, tag_field, tag_encoding) = match &layout.variants { @@ -89,7 +87,9 @@ pub(crate) fn codegen_get_discriminant<'tcx>( } else { ty::ScalarInt::try_from_uint(discr_val, dest_layout.size).unwrap() }; - return CValue::const_val(fx, dest_layout, discr_val); + let res = CValue::const_val(fx, dest_layout, discr_val); + dest.write_cvalue(fx, res); + return; } Variants::Multiple { tag, tag_field, tag_encoding, variants: _ } => { (tag, *tag_field, tag_encoding) @@ -110,7 +110,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>( _ => false, }; let val = clif_intcast(fx, tag, cast_to, signed); - CValue::by_val(val, dest_layout) + let res = CValue::by_val(val, dest_layout); + dest.write_cvalue(fx, res); } TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check @@ -170,7 +171,8 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32())); let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant); - CValue::by_val(discr, dest_layout) + let res = CValue::by_val(discr, dest_layout); + dest.write_cvalue(fx, res); } } } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 241de5e36530c..7b1a39c675cde 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -15,13 +15,13 @@ pub(crate) fn codegen_inline_asm<'tcx>( template: &[InlineAsmTemplatePiece], operands: &[InlineAsmOperand<'tcx>], options: InlineAsmOptions, + destination: Option, ) { // FIXME add .eh_frame unwind info directives if !template.is_empty() { if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::User(1)); + fx.bcx.ins().trap(TrapCode::User(1)); return; } else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) && matches!( @@ -101,12 +101,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( ebx_place.write_cvalue(fx, CValue::by_val(ebx, fx.layout_of(fx.tcx.types.u32))); ecx_place.write_cvalue(fx, CValue::by_val(ecx, fx.layout_of(fx.tcx.types.u32))); edx_place.write_cvalue(fx, CValue::by_val(edx, fx.layout_of(fx.tcx.types.u32))); + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); return; } else if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { // ___chkstk, ___chkstk_ms and __alloca are only used on Windows crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); + return; } else if fx.tcx.symbol_name(fx.instance).name == "__alloca" { crate::trap::trap_unimplemented(fx, "Alloca is not supported"); + return; } } @@ -175,6 +179,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( } call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); + + match destination { + Some(destination) => { + let destination_block = fx.get_block(destination); + fx.bcx.ins().jump(destination_block, &[]); + } + None => { + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + } + } } struct InlineAssemblyGenerator<'a, 'tcx> { diff --git a/src/intrinsics/cpuid.rs b/src/intrinsics/cpuid.rs index d02dfd93c3ee3..5120b89c4e8b0 100644 --- a/src/intrinsics/cpuid.rs +++ b/src/intrinsics/cpuid.rs @@ -62,7 +62,7 @@ pub(crate) fn codegen_cpuid_call<'tcx>( fx.bcx.ins().jump(dest, &[zero, zero, proc_info_ecx, proc_info_edx]); fx.bcx.switch_to_block(unsupported_leaf); - crate::trap::trap_unreachable( + crate::trap::trap_unimplemented( fx, "__cpuid_count arch intrinsic doesn't yet support specified leaf", ); diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 869670c8cfac7..a799dca938e21 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -139,6 +139,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( .sess .warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); crate::trap::trap_unimplemented(fx, intrinsic); + return; } } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 77caf741acf3b..cb620822f2d61 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -44,7 +44,7 @@ fn report_atomic_type_validation_error<'tcx>( ), ); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option { @@ -849,8 +849,6 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - let ret_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(ret_block, &[]); return; } else { fx.tcx @@ -882,8 +880,6 @@ fn codegen_regular_intrinsic_call<'tcx>( if fx.tcx.is_compiler_builtins(LOCAL_CRATE) { // special case for compiler-builtins to avoid having to patch it crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported"); - let ret_block = fx.get_block(destination.unwrap()); - fx.bcx.ins().jump(ret_block, &[]); return; } else { fx.tcx diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 30e3d112594a6..c7efdb392b75e 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -14,7 +14,7 @@ fn report_simd_type_validation_error( ) { fx.tcx.sess.span_err(span, &format!("invalid monomorphization of `{}` intrinsic: expected SIMD input type, found non-SIMD `{}`", intrinsic, ty)); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } pub(super) fn codegen_simd_intrinsic_call<'tcx>( @@ -157,7 +157,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ), ); // Prevent verifier error - crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); return; } } @@ -274,12 +274,17 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( idx_const } else { fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant"); - let res = crate::trap::trap_unimplemented_ret_value( + let trap_block = fx.bcx.create_block(); + let dummy_block = fx.bcx.create_block(); + let true_ = fx.bcx.ins().iconst(types::I8, 1); + fx.bcx.ins().brnz(true_, trap_block, &[]); + fx.bcx.ins().jump(dummy_block, &[]); + fx.bcx.switch_to_block(trap_block); + crate::trap::trap_unimplemented( fx, - ret.layout(), "Index argument for `simd_extract` is not a constant", ); - ret.write_cvalue(fx, res); + fx.bcx.switch_to_block(dummy_block); return; }; diff --git a/src/trap.rs b/src/trap.rs index 923269c4de9ab..82a2ec5795496 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -25,33 +25,10 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { fx.bcx.ins().call(puts, &[msg_ptr]); } -/// Use this for example when a function call should never return. This will fill the current block, -/// so you can **not** add instructions to it afterwards. -/// -/// Trap code: user65535 -pub(crate) fn trap_unreachable(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef) { - codegen_print(fx, msg.as_ref()); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); -} /// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen. -/// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions -/// to it afterwards. /// /// Trap code: user65535 pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef) { codegen_print(fx, msg.as_ref()); - let true_ = fx.bcx.ins().iconst(types::I32, 1); - fx.bcx.ins().trapnz(true_, TrapCode::User(!0)); -} - -/// Like `trap_unimplemented` but returns a fake value of the specified type. -/// -/// Trap code: user65535 -pub(crate) fn trap_unimplemented_ret_value<'tcx>( - fx: &mut FunctionCx<'_, '_, 'tcx>, - dest_layout: TyAndLayout<'tcx>, - msg: impl AsRef, -) -> CValue<'tcx> { - trap_unimplemented(fx, msg); - CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout) + fx.bcx.ins().trap(TrapCode::User(!0)); } From a7443a61ab2581ec9cdd3be08807ce599a5d56b8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 15:06:17 +0000 Subject: [PATCH 044/100] Move some code into codegen_fn_content --- src/base.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2c04cf4726825..439b636031bef 100644 --- a/src/base.rs +++ b/src/base.rs @@ -82,27 +82,7 @@ pub(crate) fn codegen_fn<'tcx>( next_ssa_var: 0, }; - let arg_uninhabited = fx - .mir - .args_iter() - .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited()); - - if !crate::constant::check_constants(&mut fx) { - fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); - fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - // compilation should have been aborted - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } else 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]); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); - } else { - tcx.sess.time("codegen clif ir", || { - tcx.sess - .time("codegen prelude", || crate::abi::codegen_fn_prelude(&mut fx, start_block)); - codegen_fn_content(&mut fx); - }); - } + tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); // Recover all necessary data from fx, before accessing func will prevent future access to it. let instance = fx.instance; @@ -269,7 +249,27 @@ pub(crate) fn verify_func( }); } -fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { +fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { + if !crate::constant::check_constants(fx) { + fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); + fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); + // compilation should have been aborted + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; + } + + let arg_uninhabited = fx + .mir + .args_iter() + .any(|arg| fx.layout_of(fx.monomorphize(fx.mir.local_decls[arg].ty)).abi.is_uninhabited()); + 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]); + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + return; + } + fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block)); + for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() { let block = fx.get_block(bb); fx.bcx.switch_to_block(block); From a10da0f76898eca1ebd398748b98b205f4284297 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 18:29:46 +0000 Subject: [PATCH 045/100] Split non-compile parts of codegen_fn out into a separate function The new codegen_and_compile_fn function only calls codegen_fn and then compile_fn. This makes it possible for both parts to be called separately by the driver. --- src/base.rs | 67 +++++++++++++++++++++++++++++------------------ src/driver/aot.rs | 6 ++--- src/driver/jit.rs | 6 +++-- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/base.rs b/src/base.rs index 439b636031bef..8e3f905166b93 100644 --- a/src/base.rs +++ b/src/base.rs @@ -5,6 +5,7 @@ use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::SymbolName; use indexmap::IndexSet; @@ -12,17 +13,39 @@ use crate::constant::ConstantCx; use crate::prelude::*; use crate::pretty_clif::CommentWriter; -pub(crate) fn codegen_fn<'tcx>( +struct CodegenedFunction<'tcx> { + instance: Instance<'tcx>, + symbol_name: SymbolName<'tcx>, + func_id: FuncId, + func: Function, + clif_comments: CommentWriter, + source_info_set: IndexSet, + local_map: IndexVec>, +} + +pub(crate) fn codegen_and_compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, module: &mut dyn Module, instance: Instance<'tcx>, ) { let tcx = cx.tcx; - let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); + + let codegened_func = codegen_fn(cx, module, instance); + + compile_fn(cx, module, codegened_func); +} + +fn codegen_fn<'tcx>( + cx: &mut crate::CodegenCx<'tcx>, + module: &mut dyn Module, + instance: Instance<'tcx>, +) -> CodegenedFunction<'tcx> { debug_assert!(!instance.substs.needs_infer()); + let tcx = cx.tcx; + let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); @@ -104,36 +127,30 @@ pub(crate) fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - compile_fn( - cx, - module, + CodegenedFunction { instance, - symbol_name.name, + symbol_name, func_id, func, clif_comments, source_info_set, local_map, - ); + } } fn compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, module: &mut dyn Module, - instance: Instance<'tcx>, - symbol_name: &str, - func_id: FuncId, - func: Function, - mut clif_comments: CommentWriter, - source_info_set: IndexSet, - local_map: IndexVec>, + codegened_func: CodegenedFunction<'tcx>, ) { let tcx = cx.tcx; + let mut clif_comments = codegened_func.clif_comments; + // Store function in context let context = &mut cx.cached_context; context.clear(); - context.func = func; + context.func = codegened_func.func; // If the return block is not reachable, then the SSA builder may have inserted an `iconst.i128` // instruction, which doesn't have an encoding. @@ -150,7 +167,7 @@ fn compile_fn<'tcx>( crate::optimize::optimize_function( tcx, module.isa(), - instance, + codegened_func.instance, context, &mut clif_comments, ); @@ -186,7 +203,7 @@ fn compile_fn<'tcx>( // Define function tcx.sess.time("define function", || { context.want_disasm = crate::pretty_clif::should_write_ir(tcx); - module.define_function(func_id, context).unwrap(); + module.define_function(codegened_func.func_id, context).unwrap(); }); // Write optimized function to file for debugging @@ -194,7 +211,7 @@ fn compile_fn<'tcx>( tcx, "opt", module.isa(), - instance, + codegened_func.instance, &context.func, &clif_comments, ); @@ -202,7 +219,7 @@ fn compile_fn<'tcx>( if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { crate::pretty_clif::write_ir_file( tcx, - || format!("{}.vcode", tcx.symbol_name(instance).name), + || format!("{}.vcode", tcx.symbol_name(codegened_func.instance).name), |file| file.write_all(disasm.as_bytes()), ) } @@ -214,16 +231,16 @@ fn compile_fn<'tcx>( tcx.sess.time("generate debug info", || { if let Some(debug_context) = debug_context { debug_context.define_function( - instance, - func_id, - symbol_name, + codegened_func.instance, + codegened_func.func_id, + codegened_func.symbol_name.name, isa, context, - &source_info_set, - local_map, + &codegened_func.source_info_set, + codegened_func.local_map, ); } - unwind_context.add_function(func_id, &context, isa); + unwind_context.add_function(codegened_func.func_id, &context, isa); }); } diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3cd1ef5639ef9..802e8ebd6f604 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -131,9 +131,9 @@ fn module_codegen( for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx - .sess - .time("codegen fn", || crate::base::codegen_fn(&mut cx, &mut module, inst)); + cx.tcx.sess.time("codegen fn", || { + crate::base::codegen_and_compile_fn(&mut cx, &mut module, inst) + }); } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), MonoItem::GlobalAsm(item_id) => { diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a56a91000596c..a7ea2b182abff 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -129,7 +129,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_fn(&mut cx, &mut jit_module, inst) + crate::base::codegen_and_compile_fn(&mut cx, &mut jit_module, inst) }); } CodegenMode::JitLazy => codegen_shim(&mut cx, &mut jit_module, inst), @@ -259,7 +259,9 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> false, Symbol::intern("dummy_cgu_name"), ); - tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, jit_module, instance)); + tcx.sess.time("codegen fn", || { + crate::base::codegen_and_compile_fn(&mut cx, jit_module, instance) + }); assert!(cx.global_asm.is_empty()); jit_module.finalize_definitions(); From 8a336a2ae1ebcbafb47d5c9c8b30ea956aaa58f9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 10 Aug 2022 18:47:05 +0000 Subject: [PATCH 046/100] Move cached_context out of CodegenCx --- src/base.rs | 15 +++++++++------ src/driver/aot.rs | 8 +++++++- src/driver/jit.rs | 33 ++++++++++++++++++++++++++------- src/lib.rs | 2 -- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/base.rs b/src/base.rs index 8e3f905166b93..c68d33465bc2a 100644 --- a/src/base.rs +++ b/src/base.rs @@ -25,6 +25,7 @@ struct CodegenedFunction<'tcx> { pub(crate) fn codegen_and_compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_context: &mut Context, module: &mut dyn Module, instance: Instance<'tcx>, ) { @@ -32,13 +33,15 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); - let codegened_func = codegen_fn(cx, module, instance); + let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); + let codegened_func = codegen_fn(cx, cached_func, module, instance); - compile_fn(cx, module, codegened_func); + compile_fn(cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_func: Function, module: &mut dyn Module, instance: Instance<'tcx>, ) -> CodegenedFunction<'tcx> { @@ -61,11 +64,10 @@ fn codegen_fn<'tcx>( let sig = get_function_sig(tcx, module.isa().triple(), instance); let func_id = module.declare_function(symbol_name.name, Linkage::Local, &sig).unwrap(); - cx.cached_context.clear(); - // Make the FunctionBuilder let mut func_ctx = FunctionBuilderContext::new(); - let mut func = std::mem::replace(&mut cx.cached_context.func, Function::new()); + let mut func = cached_func; + func.clear(); func.name = ExternalName::user(0, func_id.as_u32()); func.signature = sig; func.collect_debug_info(); @@ -140,6 +142,7 @@ fn codegen_fn<'tcx>( fn compile_fn<'tcx>( cx: &mut crate::CodegenCx<'tcx>, + cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction<'tcx>, ) { @@ -148,7 +151,7 @@ fn compile_fn<'tcx>( let mut clif_comments = codegened_func.clif_comments; // Store function in context - let context = &mut cx.cached_context; + let context = cached_context; context.clear(); context.func = codegened_func.func; diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 802e8ebd6f604..6aa2863794344 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -128,11 +128,17 @@ fn module_codegen( cgu_name, ); super::predefine_mono_items(tcx, &mut module, &mono_items); + let mut cached_context = Context::new(); for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, &mut module, inst) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut cached_context, + &mut module, + inst, + ) }); } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), diff --git a/src/driver/jit.rs b/src/driver/jit.rs index a7ea2b182abff..1b046d7ec6e8b 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -111,6 +111,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { &backend_config, matches!(backend_config.codegen_mode, CodegenMode::JitLazy), ); + let mut cached_context = Context::new(); let (_, cgus) = tcx.collect_and_partition_mono_items(()); let mono_items = cgus @@ -129,10 +130,17 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { cx.tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, &mut jit_module, inst) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut cached_context, + &mut jit_module, + inst, + ) }); } - CodegenMode::JitLazy => codegen_shim(&mut cx, &mut jit_module, inst), + CodegenMode::JitLazy => { + codegen_shim(&mut cx, &mut cached_context, &mut jit_module, inst) + } }, MonoItem::Static(def_id) => { crate::constant::codegen_static(tcx, &mut jit_module, def_id); @@ -260,7 +268,12 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> Symbol::intern("dummy_cgu_name"), ); tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn(&mut cx, jit_module, instance) + crate::base::codegen_and_compile_fn( + &mut cx, + &mut Context::new(), + jit_module, + instance, + ) }); assert!(cx.global_asm.is_empty()); @@ -336,7 +349,12 @@ fn load_imported_symbols_for_jit( imported_symbols } -fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: Instance<'tcx>) { +fn codegen_shim<'tcx>( + cx: &mut CodegenCx<'tcx>, + cached_context: &mut Context, + module: &mut JITModule, + inst: Instance<'tcx>, +) { let tcx = cx.tcx; let pointer_type = module.target_config().pointer_type(); @@ -359,8 +377,9 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In ) .unwrap(); - cx.cached_context.clear(); - let trampoline = &mut cx.cached_context.func; + let context = cached_context; + context.clear(); + let trampoline = &mut context.func; trampoline.signature = sig.clone(); let mut builder_ctx = FunctionBuilderContext::new(); @@ -383,5 +402,5 @@ fn codegen_shim<'tcx>(cx: &mut CodegenCx<'tcx>, module: &mut JITModule, inst: In let ret_vals = trampoline_builder.func.dfg.inst_results(call_inst).to_vec(); trampoline_builder.ins().return_(&ret_vals); - module.define_function(func_id, &mut cx.cached_context).unwrap(); + module.define_function(func_id, context).unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index bb0793b1deb2e..a3f8cc4dfa35f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,7 +123,6 @@ struct CodegenCx<'tcx> { tcx: TyCtxt<'tcx>, global_asm: String, inline_asm_index: Cell, - cached_context: Context, debug_context: Option>, unwind_context: UnwindContext, cgu_name: Symbol, @@ -150,7 +149,6 @@ impl<'tcx> CodegenCx<'tcx> { tcx, global_asm: String::new(), inline_asm_index: Cell::new(0), - cached_context: Context::new(), debug_context, unwind_context, cgu_name, From 07bcd111f8d3b60dbc3722215c78f25372a11c6f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:38:07 +0000 Subject: [PATCH 047/100] Return ModuleCodegenResult from reuse_workproduct_for_cgu --- src/driver/aot.rs | 60 ++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6aa2863794344..6f1732f970710 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -79,11 +79,7 @@ fn emit_module( ) } -fn reuse_workproduct_for_cgu( - tcx: TyCtxt<'_>, - cgu: &CodegenUnit<'_>, - work_products: &mut FxHashMap, -) -> CompiledModule { +fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); let source_file = rustc_incremental::in_incr_comp_dir_sess( @@ -99,15 +95,16 @@ fn reuse_workproduct_for_cgu( )); } - work_products.insert(cgu.work_product_id(), work_product); - - CompiledModule { - name: cgu.name().to_string(), - kind: ModuleKind::Regular, - object: Some(obj_out), - dwarf_object: None, - bytecode: None, - } + ModuleCodegenResult( + CompiledModule { + name: cgu.name().to_string(), + kind: ModuleKind::Regular, + object: Some(obj_out), + dwarf_object: None, + bytecode: None, + }, + Some((cgu.work_product_id(), work_product)), + ) } fn module_codegen( @@ -215,26 +212,31 @@ pub(crate) fn run_aot( let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { cgus.iter() .map(|cgu| { - let cgu_reuse = determine_cgu_reuse(tcx, cgu); + let cgu_reuse = if backend_config.disable_incr_cache { + CguReuse::No + } else { + determine_cgu_reuse(tcx, cgu) + }; tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); - match cgu_reuse { - _ if backend_config.disable_incr_cache => {} - CguReuse::No => {} - CguReuse::PreLto => { - return reuse_workproduct_for_cgu(tcx, &*cgu, &mut work_products); + let module_codegen_result = match cgu_reuse { + CguReuse::No => { + let dep_node = cgu.codegen_dep_node(tcx); + tcx.dep_graph + .with_task( + dep_node, + tcx, + (backend_config.clone(), cgu.name()), + module_codegen, + Some(rustc_middle::dep_graph::hash_result), + ) + .0 } + CguReuse::PreLto => reuse_workproduct_for_cgu(tcx, &*cgu), CguReuse::PostLto => unreachable!(), - } + }; - let dep_node = cgu.codegen_dep_node(tcx); - let (ModuleCodegenResult(module, work_product), _) = tcx.dep_graph.with_task( - dep_node, - tcx, - (backend_config.clone(), cgu.name()), - module_codegen, - Some(rustc_middle::dep_graph::hash_result), - ); + let ModuleCodegenResult(module, work_product) = module_codegen_result; if let Some((id, product)) = work_product { work_products.insert(id, product); From c5adc96532205a12c94c1407e6b6b35f7c7a2b64 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 11 Aug 2022 13:49:08 +0000 Subject: [PATCH 048/100] Introduce OngoingCodegen type --- src/driver/aot.rs | 67 ++++++++++++++++++++++++++++++++--------------- src/lib.rs | 4 +-- 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6f1732f970710..c417de04ab434 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -27,6 +27,41 @@ impl HashStable for ModuleCodegenResult { } } +pub(crate) struct OngoingCodegen { + modules: Vec, + allocator_module: Option, + metadata_module: Option, + metadata: EncodedMetadata, + crate_info: CrateInfo, + work_products: FxHashMap, +} + +impl OngoingCodegen { + pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { + let mut work_products = self.work_products; + let mut modules = vec![]; + + for module_codegen_result in self.modules { + let ModuleCodegenResult(module, work_product) = module_codegen_result; + if let Some((work_product_id, work_product)) = work_product { + work_products.insert(work_product_id, work_product); + } + modules.push(module); + } + + ( + CodegenResults { + modules, + allocator_module: self.allocator_module, + metadata_module: self.metadata_module, + metadata: self.metadata, + crate_info: self.crate_info, + }, + work_products, + ) + } +} + fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); @@ -192,9 +227,7 @@ pub(crate) fn run_aot( backend_config: BackendConfig, metadata: EncodedMetadata, need_metadata_module: bool, -) -> Box<(CodegenResults, FxHashMap)> { - let mut work_products = FxHashMap::default(); - +) -> Box { let cgus = if tcx.sess.opts.output_types.should_codegen() { tcx.collect_and_partition_mono_items(()).1 } else { @@ -219,7 +252,7 @@ pub(crate) fn run_aot( }; tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); - let module_codegen_result = match cgu_reuse { + match cgu_reuse { CguReuse::No => { let dep_node = cgu.codegen_dep_node(tcx); tcx.dep_graph @@ -234,21 +267,15 @@ pub(crate) fn run_aot( } CguReuse::PreLto => reuse_workproduct_for_cgu(tcx, &*cgu), CguReuse::PostLto => unreachable!(), - }; - - let ModuleCodegenResult(module, work_product) = module_codegen_result; - - if let Some((id, product)) = work_product { - work_products.insert(id, product); } - - module }) .collect::>() }); tcx.sess.abort_if_errors(); + let mut work_products = FxHashMap::default(); + let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); @@ -316,16 +343,14 @@ pub(crate) fn run_aot( } .to_owned(); - Box::new(( - CodegenResults { - modules, - allocator_module, - metadata_module, - metadata, - crate_info: CrateInfo::new(tcx, target_cpu), - }, + Box::new(OngoingCodegen { + modules, + allocator_module, + metadata_module, + metadata, + crate_info: CrateInfo::new(tcx, target_cpu), work_products, - )) + }) } fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { diff --git a/src/lib.rs b/src/lib.rs index a3f8cc4dfa35f..49d10012c4f13 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -211,9 +211,7 @@ impl CodegenBackend for CraneliftCodegenBackend { _sess: &Session, _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorGuaranteed> { - Ok(*ongoing_codegen - .downcast::<(CodegenResults, FxHashMap)>() - .unwrap()) + Ok(ongoing_codegen.downcast::().unwrap().join()) } fn link( From 7cc97ebcbb3fe637e2467f2e4fc45d94dae013e8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:11:47 +0000 Subject: [PATCH 049/100] Extract global_asm module --- src/driver/aot.rs | 109 +------------------------------------------ src/global_asm.rs | 116 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 119 insertions(+), 107 deletions(-) create mode 100644 src/global_asm.rs diff --git a/src/driver/aot.rs b/src/driver/aot.rs index c417de04ab434..6482dce274676 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,9 +1,6 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. -use std::path::PathBuf; - -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -175,23 +172,7 @@ fn module_codegen( } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), MonoItem::GlobalAsm(item_id) => { - let item = cx.tcx.hir().item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { - if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { - cx.global_asm.push_str("\n.intel_syntax noprefix\n"); - } else { - cx.global_asm.push_str("\n.att_syntax\n"); - } - for piece in asm.template { - match *piece { - InlineAsmTemplatePiece::String(ref s) => cx.global_asm.push_str(s), - InlineAsmTemplatePiece::Placeholder { .. } => todo!(), - } - } - cx.global_asm.push_str("\n.att_syntax\n\n"); - } else { - bug!("Expected GlobalAsm found {:?}", item); - } + crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); } } } @@ -217,7 +198,7 @@ fn module_codegen( ) }); - codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); + crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); codegen_result } @@ -353,92 +334,6 @@ pub(crate) fn run_aot( }) } -fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { - use std::io::Write; - use std::process::{Command, Stdio}; - - if global_asm.is_empty() { - return; - } - - if cfg!(not(feature = "inline_asm")) - || tcx.sess.target.is_like_osx - || tcx.sess.target.is_like_windows - { - if global_asm.contains("__rust_probestack") { - return; - } - - // FIXME fix linker error on macOS - if cfg!(not(feature = "inline_asm")) { - tcx.sess.fatal( - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); - } else { - tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); - } - } - - let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); - let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); - - // Remove all LLVM style comments - let global_asm = global_asm - .lines() - .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line }) - .collect::>() - .join("\n"); - - let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); - - // Assemble `global_asm` - let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); - let mut child = Command::new(assembler) - .arg("-o") - .arg(&global_asm_object_file) - .stdin(Stdio::piped()) - .spawn() - .expect("Failed to spawn `as`."); - child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); - let status = child.wait().expect("Failed to wait for `as`."); - if !status.success() { - tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); - } - - // Link the global asm and main object file together - let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); - std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(linker) - .arg("-r") // Create a new object file - .arg("-o") - .arg(output_object_file) - .arg(&main_object_file) - .arg(&global_asm_object_file) - .status() - .unwrap(); - if !status.success() { - tcx.sess.fatal(&format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - )); - } - - std::fs::remove_file(global_asm_object_file).unwrap(); - std::fs::remove_file(main_object_file).unwrap(); -} - -fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { - let mut new_filename = path.file_stem().unwrap().to_owned(); - new_filename.push(postfix); - if let Some(extension) = path.extension() { - new_filename.push("."); - new_filename.push(extension); - } - path.set_file_name(new_filename); - path -} - // Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953 fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse { if !tcx.dep_graph.is_fully_enabled() { diff --git a/src/global_asm.rs b/src/global_asm.rs new file mode 100644 index 0000000000000..5962a86a6864c --- /dev/null +++ b/src/global_asm.rs @@ -0,0 +1,116 @@ +//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a +//! standalone executable. + +use std::path::PathBuf; + +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_hir::ItemId; +use rustc_session::config::OutputType; + +use crate::prelude::*; + +pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { + let item = tcx.hir().item(item_id); + if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { + global_asm.push_str("\n.intel_syntax noprefix\n"); + } else { + global_asm.push_str("\n.att_syntax\n"); + } + for piece in asm.template { + match *piece { + InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), + InlineAsmTemplatePiece::Placeholder { .. } => todo!(), + } + } + global_asm.push_str("\n.att_syntax\n\n"); + } else { + bug!("Expected GlobalAsm found {:?}", item); + } +} + +pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { + use std::io::Write; + use std::process::{Command, Stdio}; + + if global_asm.is_empty() { + return; + } + + if cfg!(not(feature = "inline_asm")) + || tcx.sess.target.is_like_osx + || tcx.sess.target.is_like_windows + { + if global_asm.contains("__rust_probestack") { + return; + } + + // FIXME fix linker error on macOS + if cfg!(not(feature = "inline_asm")) { + tcx.sess.fatal( + "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", + ); + } else { + tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); + } + } + + let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); + let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); + + // Remove all LLVM style comments + let global_asm = global_asm + .lines() + .map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line }) + .collect::>() + .join("\n"); + + let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); + + // Assemble `global_asm` + let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); + let mut child = Command::new(assembler) + .arg("-o") + .arg(&global_asm_object_file) + .stdin(Stdio::piped()) + .spawn() + .expect("Failed to spawn `as`."); + child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); + let status = child.wait().expect("Failed to wait for `as`."); + if !status.success() { + tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); + } + + // Link the global asm and main object file together + let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); + std::fs::rename(&output_object_file, &main_object_file).unwrap(); + let status = Command::new(linker) + .arg("-r") // Create a new object file + .arg("-o") + .arg(output_object_file) + .arg(&main_object_file) + .arg(&global_asm_object_file) + .status() + .unwrap(); + if !status.success() { + tcx.sess.fatal(&format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), + )); + } + + std::fs::remove_file(global_asm_object_file).unwrap(); + std::fs::remove_file(main_object_file).unwrap(); +} + +fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { + let mut new_filename = path.file_stem().unwrap().to_owned(); + new_filename.push(postfix); + if let Some(extension) = path.extension() { + new_filename.push("."); + new_filename.push(extension); + } + path.set_file_name(new_filename); + path +} diff --git a/src/lib.rs b/src/lib.rs index 49d10012c4f13..6ea160d26ce5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,7 @@ mod constant; mod debuginfo; mod discriminant; mod driver; +mod global_asm; mod inline_asm; mod intrinsics; mod linkage; From 066f844fff7b6bf227c375a293fe15af88cf85ac Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:28:41 +0000 Subject: [PATCH 050/100] Move some sess.fatal calls out of compile_global_asm --- src/driver/aot.rs | 5 ++++- src/global_asm.rs | 43 +++++++++++++++++++++++++++++-------------- src/toolchain.rs | 6 ++---- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 6482dce274676..0816ebc4599ec 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -198,7 +198,10 @@ fn module_codegen( ) }); - crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); + match crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm) { + Ok(()) => {} + Err(err) => tcx.sess.fatal(&err.to_string()), + } codegen_result } diff --git a/src/global_asm.rs b/src/global_asm.rs index 5962a86a6864c..5cd7abfdfb554 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -1,7 +1,9 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::io::{self, Write}; use std::path::PathBuf; +use std::process::{Command, Stdio}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::ItemId; @@ -29,12 +31,13 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } -pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) { - use std::io::Write; - use std::process::{Command, Stdio}; - +pub(crate) fn compile_global_asm( + tcx: TyCtxt<'_>, + cgu_name: &str, + global_asm: &str, +) -> io::Result<()> { if global_asm.is_empty() { - return; + return Ok(()); } if cfg!(not(feature = "inline_asm")) @@ -42,16 +45,20 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s || tcx.sess.target.is_like_windows { if global_asm.contains("__rust_probestack") { - return; + return Ok(()); } // FIXME fix linker error on macOS if cfg!(not(feature = "inline_asm")) { - tcx.sess.fatal( + return Err(io::Error::new( + io::ErrorKind::Unsupported, "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - ); + )); } else { - tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows"); + return Err(io::Error::new( + io::ErrorKind::Unsupported, + "asm! and global_asm! are not yet supported on macOS and Windows", + )); } } @@ -78,7 +85,10 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); let status = child.wait().expect("Failed to wait for `as`."); if !status.success() { - tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm)); + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Failed to assemble `{}`", global_asm), + )); } // Link the global asm and main object file together @@ -93,15 +103,20 @@ pub(crate) fn compile_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &s .status() .unwrap(); if !status.success() { - tcx.sess.fatal(&format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), + return Err(io::Error::new( + io::ErrorKind::Other, + format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), + ), )); } std::fs::remove_file(global_asm_object_file).unwrap(); std::fs::remove_file(main_object_file).unwrap(); + + Ok(()) } fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { diff --git a/src/toolchain.rs b/src/toolchain.rs index f86236ef3eafc..b6b465e1f4e0a 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -8,10 +8,8 @@ use rustc_session::Session; /// Tries to infer the path of a binary for the target toolchain from the linker name. pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf { let (mut linker, _linker_flavor) = linker_and_flavor(sess); - let linker_file_name = linker - .file_name() - .and_then(|name| name.to_str()) - .unwrap_or_else(|| sess.fatal("couldn't extract file name from specified linker")); + let linker_file_name = + linker.file_name().unwrap().to_str().expect("linker filename should be valid UTF-8"); if linker_file_name == "ld.lld" { if tool != "ld" { From aca05cf6038278d7774311720534437f0ec42bc2 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 12 Aug 2022 12:48:40 +0200 Subject: [PATCH 051/100] Fix alignment flag for emit_small_memory_copy Do not unconditionally pass the "aligned" MemFlag when calling emit_small_memory_copy. Instead, allow the back end to rely on the alignment info passed separately to this routine. --- src/value_and_place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index e48d095d13962..9e945d8362162 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -614,7 +614,7 @@ impl<'tcx> CPlace<'tcx> { dst_align, src_align, true, - MemFlags::trusted(), + flags, ); } CValueInner::ByRef(_, Some(_)) => todo!(), From 48b312f04a89c72cf6db2cbb08bbc7fe6fce9bdb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 09:55:59 +0000 Subject: [PATCH 052/100] Don't take TyCtxt as argument for compile_global_asm This allows it to be executed on a background thread. --- src/driver/aot.rs | 21 ++++++++++--- src/global_asm.rs | 77 +++++++++++++++++++++++++++-------------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 0816ebc4599ec..0ca634affb4b6 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,8 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::sync::Arc; + use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -14,6 +16,7 @@ use rustc_session::Session; use cranelift_codegen::isa::TargetIsa; use cranelift_object::{ObjectBuilder, ObjectModule}; +use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); @@ -141,7 +144,11 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo fn module_codegen( tcx: TyCtxt<'_>, - (backend_config, cgu_name): (BackendConfig, rustc_span::Symbol), + (backend_config, global_asm_config, cgu_name): ( + BackendConfig, + Arc, + rustc_span::Symbol, + ), ) -> ModuleCodegenResult { let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); @@ -198,9 +205,13 @@ fn module_codegen( ) }); - match crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm) { + match crate::global_asm::compile_global_asm( + &global_asm_config, + cgu.name().as_str(), + &cx.global_asm, + ) { Ok(()) => {} - Err(err) => tcx.sess.fatal(&err.to_string()), + Err(err) => tcx.sess.fatal(&err), } codegen_result @@ -226,6 +237,8 @@ pub(crate) fn run_aot( } } + let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx)); + let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { cgus.iter() .map(|cgu| { @@ -243,7 +256,7 @@ pub(crate) fn run_aot( .with_task( dep_node, tcx, - (backend_config.clone(), cgu.name()), + (backend_config.clone(), global_asm_config.clone(), cgu.name()), module_codegen, Some(rustc_middle::dep_graph::hash_result), ) diff --git a/src/global_asm.rs b/src/global_asm.rs index 5cd7abfdfb554..14288e99242ac 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -1,13 +1,14 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. -use std::io::{self, Write}; +use std::io::Write; use std::path::PathBuf; use std::process::{Command, Stdio}; +use std::sync::Arc; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::ItemId; -use rustc_session::config::OutputType; +use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -31,40 +32,56 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } +#[derive(Debug)] +pub(crate) struct GlobalAsmConfig { + asm_enabled: bool, + assembler: PathBuf, + linker: PathBuf, + output_filenames: Arc, +} + +impl GlobalAsmConfig { + pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { + let asm_enabled = cfg!(feature = "inline_asm") + && !tcx.sess.target.is_like_osx + && !tcx.sess.target.is_like_windows; + + GlobalAsmConfig { + asm_enabled, + assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), + linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"), + output_filenames: tcx.output_filenames(()).clone(), + } + } +} + pub(crate) fn compile_global_asm( - tcx: TyCtxt<'_>, + config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, -) -> io::Result<()> { +) -> Result<(), String> { if global_asm.is_empty() { return Ok(()); } - if cfg!(not(feature = "inline_asm")) - || tcx.sess.target.is_like_osx - || tcx.sess.target.is_like_windows - { + if !config.asm_enabled { if global_asm.contains("__rust_probestack") { return Ok(()); } // FIXME fix linker error on macOS if cfg!(not(feature = "inline_asm")) { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", - )); + return Err( + "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift" + .to_owned(), + ); } else { - return Err(io::Error::new( - io::ErrorKind::Unsupported, - "asm! and global_asm! are not yet supported on macOS and Windows", - )); + return Err( + "asm! and global_asm! are not yet supported on macOS and Windows".to_owned() + ); } } - let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as"); - let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld"); - // Remove all LLVM style comments let global_asm = global_asm .lines() @@ -72,11 +89,11 @@ pub(crate) fn compile_global_asm( .collect::>() .join("\n"); - let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); + let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)); // Assemble `global_asm` let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); - let mut child = Command::new(assembler) + let mut child = Command::new(&config.assembler) .arg("-o") .arg(&global_asm_object_file) .stdin(Stdio::piped()) @@ -85,16 +102,13 @@ pub(crate) fn compile_global_asm( child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); let status = child.wait().expect("Failed to wait for `as`."); if !status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!("Failed to assemble `{}`", global_asm), - )); + return Err(format!("Failed to assemble `{}`", global_asm)); } // Link the global asm and main object file together let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(linker) + let status = Command::new(&config.linker) .arg("-r") // Create a new object file .arg("-o") .arg(output_object_file) @@ -103,13 +117,10 @@ pub(crate) fn compile_global_asm( .status() .unwrap(); if !status.success() { - return Err(io::Error::new( - io::ErrorKind::Other, - format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - ), + return Err(format!( + "Failed to link `{}` and `{}` together", + main_object_file.display(), + global_asm_object_file.display(), )); } From 8bcab190183f2a1807ff3d10fcdf7ea74306cf2f Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 12 Aug 2022 13:46:31 +0200 Subject: [PATCH 053/100] Ignore ptr_bitops_tagging test on s390x This test requires dynamic stack re-alignment on s390x, which is currently unsupported (see issue #1258). --- patches/0023-sysroot-Ignore-failing-tests.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/patches/0023-sysroot-Ignore-failing-tests.patch b/patches/0023-sysroot-Ignore-failing-tests.patch index 50ef0bd9418c7..f3cd7ee77e26e 100644 --- a/patches/0023-sysroot-Ignore-failing-tests.patch +++ b/patches/0023-sysroot-Ignore-failing-tests.patch @@ -46,5 +46,17 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { +diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs +index 13b12db..96fe4b9 100644 +--- a/library/core/tests/atomic.rs ++++ b/library/core/tests/atomic.rs +@@ -185,6 +185,7 @@ fn ptr_bitops() { + } + + #[test] ++#[cfg_attr(target_arch = "s390x", ignore)] // s390x backend doesn't support stack alignment >8 bytes + #[cfg(any(not(target_arch = "arm"), target_os = "linux"))] // Missing intrinsic in compiler-builtins + fn ptr_bitops_tagging() { + #[repr(align(16))] -- 2.21.0 (Apple Git-122) From e45f6000a0bd46d4b7580db59c86f3d30adbc270 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 12:27:47 +0000 Subject: [PATCH 054/100] Remove the partial linking hack for global asm support --- src/driver/aot.rs | 102 +++++++++++++++++++++++++++++++++++++--------- src/global_asm.rs | 34 +++------------- 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 0ca634affb4b6..4122ce1822406 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::path::PathBuf; use std::sync::Arc; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; @@ -19,7 +20,11 @@ use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; -struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); +struct ModuleCodegenResult( + CompiledModule, + Option, + Option<(WorkProductId, WorkProduct)>, +); impl HashStable for ModuleCodegenResult { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { @@ -42,11 +47,15 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult(module, work_product) = module_codegen_result; + let ModuleCodegenResult(module_regular, module_global_asm, work_product) = + module_codegen_result; if let Some((work_product_id, work_product)) = work_product { work_products.insert(work_product_id, work_product); } - modules.push(module); + modules.push(module_regular); + if let Some(module_global_asm) = module_global_asm { + modules.push(module_global_asm); + } } ( @@ -80,6 +89,7 @@ fn emit_module( module: ObjectModule, debug: Option>, unwind_context: UnwindContext, + global_asm_object_file: Option, ) -> ModuleCodegenResult { let mut product = module.finish(); @@ -100,6 +110,12 @@ fn emit_module( let work_product = if backend_config.disable_incr_cache { None + } else if let Some(global_asm_object_file) = &global_asm_object_file { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + tcx.sess, + &name, + &[("o", &tmp_file), ("asm.o", global_asm_object_file)], + ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, @@ -109,35 +125,78 @@ fn emit_module( }; ModuleCodegenResult( - CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }, + CompiledModule { + name: name.clone(), + kind, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + }, + global_asm_object_file.map(|global_asm_object_file| CompiledModule { + name: format!("{name}.asm"), + kind, + object: Some(global_asm_object_file), + dwarf_object: None, + bytecode: None, + }), work_product, ) } fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); - let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); - let source_file = rustc_incremental::in_incr_comp_dir_sess( + let obj_out_regular = + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), ); - if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { + + if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) { tcx.sess.err(&format!( "unable to copy {} to {}: {}", - source_file.display(), - obj_out.display(), + source_file_regular.display(), + obj_out_regular.display(), err )); } + let obj_out_global_asm = + crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); + let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); + if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) + { + tcx.sess.err(&format!( + "unable to copy {} to {}: {}", + source_file_regular.display(), + obj_out_regular.display(), + err + )); + } + true + } else { + false + }; ModuleCodegenResult( CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, - object: Some(obj_out), + object: Some(obj_out_regular), dwarf_object: None, bytecode: None, }, + if has_global_asm { + Some(CompiledModule { + name: cgu.name().to_string(), + kind: ModuleKind::Regular, + object: Some(obj_out_global_asm), + dwarf_object: None, + bytecode: None, + }) + } else { + None + }, Some((cgu.work_product_id(), work_product)), ) } @@ -191,6 +250,15 @@ fn module_codegen( cgu.is_primary(), ); + let global_asm_object_file = match crate::global_asm::compile_global_asm( + &global_asm_config, + cgu.name().as_str(), + &cx.global_asm, + ) { + Ok(global_asm_object_file) => global_asm_object_file, + Err(err) => tcx.sess.fatal(&err), + }; + let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; let codegen_result = tcx.sess.time("write object file", || { @@ -202,18 +270,10 @@ fn module_codegen( module, debug_context, unwind_context, + global_asm_object_file, ) }); - match crate::global_asm::compile_global_asm( - &global_asm_config, - cgu.name().as_str(), - &cx.global_asm, - ) { - Ok(()) => {} - Err(err) => tcx.sess.fatal(&err), - } - codegen_result } @@ -281,7 +341,7 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult(module, work_product) = emit_module( + let ModuleCodegenResult(module, module_global_asm, work_product) = emit_module( tcx, &backend_config, "allocator_shim".to_string(), @@ -289,7 +349,9 @@ pub(crate) fn run_aot( allocator_module, None, allocator_unwind_context, + None, ); + assert!(module_global_asm.is_none()); if let Some((id, product)) = work_product { work_products.insert(id, product); } diff --git a/src/global_asm.rs b/src/global_asm.rs index 14288e99242ac..8e711988f814d 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -36,7 +36,6 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, pub(crate) struct GlobalAsmConfig { asm_enabled: bool, assembler: PathBuf, - linker: PathBuf, output_filenames: Arc, } @@ -49,7 +48,6 @@ impl GlobalAsmConfig { GlobalAsmConfig { asm_enabled, assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), - linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"), output_filenames: tcx.output_filenames(()).clone(), } } @@ -59,14 +57,14 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, -) -> Result<(), String> { +) -> Result, String> { if global_asm.is_empty() { - return Ok(()); + return Ok(None); } if !config.asm_enabled { if global_asm.contains("__rust_probestack") { - return Ok(()); + return Ok(None); } // FIXME fix linker error on macOS @@ -105,32 +103,10 @@ pub(crate) fn compile_global_asm( return Err(format!("Failed to assemble `{}`", global_asm)); } - // Link the global asm and main object file together - let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); - std::fs::rename(&output_object_file, &main_object_file).unwrap(); - let status = Command::new(&config.linker) - .arg("-r") // Create a new object file - .arg("-o") - .arg(output_object_file) - .arg(&main_object_file) - .arg(&global_asm_object_file) - .status() - .unwrap(); - if !status.success() { - return Err(format!( - "Failed to link `{}` and `{}` together", - main_object_file.display(), - global_asm_object_file.display(), - )); - } - - std::fs::remove_file(global_asm_object_file).unwrap(); - std::fs::remove_file(main_object_file).unwrap(); - - Ok(()) + Ok(Some(global_asm_object_file)) } -fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { +pub(crate) fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf { let mut new_filename = path.file_stem().unwrap().to_owned(); new_filename.push(postfix); if let Some(extension) = path.extension() { From f76ca2247998bff4e10b73fcb464a0a83edbfeb0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 12:30:24 +0000 Subject: [PATCH 055/100] Enable inline asm on macOS --- Readme.md | 4 +--- example/mini_core_hello_world.rs | 14 ++++++++++++-- src/global_asm.rs | 8 ++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Readme.md b/Readme.md index 8a2db5a43ecbf..1e84c7fa3657b 100644 --- a/Readme.md +++ b/Readme.md @@ -52,9 +52,7 @@ configuration options. ## Not yet supported * Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) - * On Linux there is support for invoking an external assembler for `global_asm!` and `asm!`. - `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You - have to specify specific registers instead. + * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work) ## License diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 7e9cbe1bba5c7..e83be3a3df5c4 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -321,7 +321,7 @@ fn main() { #[cfg(not(any(jit, windows)))] test_tls(); - #[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] + #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] unsafe { global_asm_test(); } @@ -343,7 +343,7 @@ fn main() { } } -#[cfg(all(not(jit), target_arch = "x86_64", target_os = "linux"))] +#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] extern "C" { fn global_asm_test(); } @@ -358,6 +358,16 @@ global_asm! { " } +#[cfg(all(not(jit), target_arch = "x86_64", target_os = "darwin"))] +global_asm! { + " + .global _global_asm_test + _global_asm_test: + // comment that would normally be removed by LLVM + ret + " +} + #[repr(C)] enum c_void { _1, diff --git a/src/global_asm.rs b/src/global_asm.rs index 8e711988f814d..917a6fff72779 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -41,9 +41,7 @@ pub(crate) struct GlobalAsmConfig { impl GlobalAsmConfig { pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { - let asm_enabled = cfg!(feature = "inline_asm") - && !tcx.sess.target.is_like_osx - && !tcx.sess.target.is_like_windows; + let asm_enabled = cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows; GlobalAsmConfig { asm_enabled, @@ -74,9 +72,7 @@ pub(crate) fn compile_global_asm( .to_owned(), ); } else { - return Err( - "asm! and global_asm! are not yet supported on macOS and Windows".to_owned() - ); + return Err("asm! and global_asm! are not yet supported on Windows".to_owned()); } } From db7d8a811d646cc9f30eb550d2aed7ff3530bb40 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:03:18 +0000 Subject: [PATCH 056/100] Give fields of ModuleCodegenResult names --- src/driver/aot.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 4122ce1822406..3bbd286b3d79d 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -20,11 +20,11 @@ use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; -struct ModuleCodegenResult( - CompiledModule, - Option, - Option<(WorkProductId, WorkProduct)>, -); +struct ModuleCodegenResult { + module_regular: CompiledModule, + module_global_asm: Option, + work_product: Option<(WorkProductId, WorkProduct)>, +} impl HashStable for ModuleCodegenResult { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { @@ -47,7 +47,7 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult(module_regular, module_global_asm, work_product) = + let ModuleCodegenResult { module_regular, module_global_asm, work_product } = module_codegen_result; if let Some((work_product_id, work_product)) = work_product { work_products.insert(work_product_id, work_product); @@ -124,15 +124,15 @@ fn emit_module( ) }; - ModuleCodegenResult( - CompiledModule { + ModuleCodegenResult { + module_regular: CompiledModule { name: name.clone(), kind, object: Some(tmp_file), dwarf_object: None, bytecode: None, }, - global_asm_object_file.map(|global_asm_object_file| CompiledModule { + module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), kind, object: Some(global_asm_object_file), @@ -140,7 +140,7 @@ fn emit_module( bytecode: None, }), work_product, - ) + } } fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { @@ -178,15 +178,15 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo false }; - ModuleCodegenResult( - CompiledModule { + ModuleCodegenResult { + module_regular: CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_regular), dwarf_object: None, bytecode: None, }, - if has_global_asm { + module_global_asm: if has_global_asm { Some(CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, @@ -197,8 +197,8 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo } else { None }, - Some((cgu.work_product_id(), work_product)), - ) + work_product: Some((cgu.work_product_id(), work_product)), + } } fn module_codegen( @@ -341,7 +341,7 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult(module, module_global_asm, work_product) = emit_module( + let ModuleCodegenResult { module_regular, module_global_asm, work_product } = emit_module( tcx, &backend_config, "allocator_shim".to_string(), @@ -355,7 +355,7 @@ pub(crate) fn run_aot( if let Some((id, product)) = work_product { work_products.insert(id, product); } - Some(module) + Some(module_regular) } else { None }; From d3512b1d8e04ab8ab78ea5111a177605d13dfff1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:15:51 +0000 Subject: [PATCH 057/100] Don't attempt to do incr comp for the allocator shim The allocator shim doesn't get reused and the allocator shim is just under 2kb, so reusing it is likely more expensive than regenerating it. --- src/driver/aot.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3bbd286b3d79d..ee89d0701aa37 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -38,12 +38,11 @@ pub(crate) struct OngoingCodegen { metadata_module: Option, metadata: EncodedMetadata, crate_info: CrateInfo, - work_products: FxHashMap, } impl OngoingCodegen { pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { - let mut work_products = self.work_products; + let mut work_products = FxHashMap::default(); let mut modules = vec![]; for module_codegen_result in self.modules { @@ -331,8 +330,6 @@ pub(crate) fn run_aot( tcx.sess.abort_if_errors(); - let mut work_products = FxHashMap::default(); - let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); @@ -341,21 +338,27 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let ModuleCodegenResult { module_regular, module_global_asm, work_product } = emit_module( - tcx, - &backend_config, - "allocator_shim".to_string(), - ModuleKind::Allocator, - allocator_module, - None, - allocator_unwind_context, - None, - ); - assert!(module_global_asm.is_none()); - if let Some((id, product)) = work_product { - work_products.insert(id, product); + let name = "allocator_shim".to_owned(); + + let mut product = allocator_module.finish(); + allocator_unwind_context.emit(&mut product); + + let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let obj = product.object.write().unwrap(); + + tcx.sess.prof.artifact_size("object_file", &*name, obj.len().try_into().unwrap()); + + if let Err(err) = std::fs::write(&tmp_file, obj) { + tcx.sess.fatal(&format!("error writing object file: {}", err)); } - Some(module_regular) + + Some(CompiledModule { + name, + kind: ModuleKind::Allocator, + object: Some(tmp_file), + dwarf_object: None, + bytecode: None, + }) } else { None }; @@ -408,7 +411,6 @@ pub(crate) fn run_aot( metadata_module, metadata, crate_info: CrateInfo::new(tcx, target_cpu), - work_products, }) } From ab7c706306c65527b5b8b9620e34a65d852cd279 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:40:48 +0000 Subject: [PATCH 058/100] Move build_isa call into make_module --- src/driver/aot.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index ee89d0701aa37..415631ba3e6e9 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -14,7 +14,6 @@ use rustc_session::cgu_reuse_tracker::CguReuse; use rustc_session::config::{DebugInfo, OutputType}; use rustc_session::Session; -use cranelift_codegen::isa::TargetIsa; use cranelift_object::{ObjectBuilder, ObjectModule}; use crate::global_asm::GlobalAsmConfig; @@ -70,7 +69,9 @@ impl OngoingCodegen { } } -fn make_module(sess: &Session, isa: Box, name: String) -> ObjectModule { +fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule { + let isa = crate::build_isa(sess, backend_config); + let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); // Unlike cg_llvm, cg_clif defaults to disabling -Zfunction-sections. For cg_llvm binary size @@ -211,8 +212,7 @@ fn module_codegen( let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); - let isa = crate::build_isa(tcx.sess, &backend_config); - let mut module = make_module(tcx.sess, isa, cgu_name.as_str().to_string()); + let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); let mut cx = crate::CodegenCx::new( tcx, @@ -330,9 +330,7 @@ pub(crate) fn run_aot( tcx.sess.abort_if_errors(); - let isa = crate::build_isa(tcx.sess, &backend_config); - let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); - assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); + let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string()); let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true); let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); From 6206c4e927595afcaef0496025512282f847f645 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 18:55:39 +0000 Subject: [PATCH 059/100] Stream object file to disk This reduces memory usage and may improve performance slightly. --- src/driver/aot.rs | 70 ++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 415631ba3e6e9..ff6310bd8af2d 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -1,6 +1,7 @@ //! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a //! standalone executable. +use std::fs::File; use std::path::PathBuf; use std::sync::Arc; @@ -81,11 +82,10 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule::new(builder) } -fn emit_module( +fn emit_cgu( tcx: TyCtxt<'_>, backend_config: &BackendConfig, name: String, - kind: ModuleKind, module: ObjectModule, debug: Option>, unwind_context: UnwindContext, @@ -99,14 +99,7 @@ fn emit_module( unwind_context.emit(&mut product); - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); - let obj = product.object.write().unwrap(); - - tcx.sess.prof.artifact_size("object_file", name.clone(), obj.len().try_into().unwrap()); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); - } + let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); let work_product = if backend_config.disable_incr_cache { None @@ -114,27 +107,21 @@ fn emit_module( rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, &name, - &[("o", &tmp_file), ("asm.o", global_asm_object_file)], + &[("o", &module_regular.object.as_ref().unwrap()), ("asm.o", global_asm_object_file)], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( tcx.sess, &name, - &[("o", &tmp_file)], + &[("o", &module_regular.object.as_ref().unwrap())], ) }; ModuleCodegenResult { - module_regular: CompiledModule { - name: name.clone(), - kind, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - }, + module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), - kind, + kind: ModuleKind::Regular, object: Some(global_asm_object_file), dwarf_object: None, bytecode: None, @@ -143,6 +130,27 @@ fn emit_module( } } +fn emit_module( + tcx: TyCtxt<'_>, + object: cranelift_object::object::write::Object<'_>, + kind: ModuleKind, + name: String, +) -> CompiledModule { + let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let mut file = match File::create(&tmp_file) { + Ok(file) => file, + Err(err) => tcx.sess.fatal(&format!("error creating object file: {}", err)), + }; + + if let Err(err) = object.write_stream(&mut file) { + tcx.sess.fatal(&format!("error writing object file: {}", err)); + } + + tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); + + CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None } +} + fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = @@ -261,11 +269,10 @@ fn module_codegen( let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; let codegen_result = tcx.sess.time("write object file", || { - emit_module( + emit_cgu( tcx, &backend_config, cgu.name().as_str().to_string(), - ModuleKind::Regular, module, debug_context, unwind_context, @@ -336,27 +343,10 @@ pub(crate) fn run_aot( crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); let allocator_module = if created_alloc_shim { - let name = "allocator_shim".to_owned(); - let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); - let obj = product.object.write().unwrap(); - - tcx.sess.prof.artifact_size("object_file", &*name, obj.len().try_into().unwrap()); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); - } - - Some(CompiledModule { - name, - kind: ModuleKind::Allocator, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - }) + Some(emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned())) } else { None }; From c2f0b3a1bf5ed437df3e276960f64bf3c47222e0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 12 Aug 2022 19:10:16 +0000 Subject: [PATCH 060/100] Move copy to incr comp cache to codegen join phase The copy depends on Session, which is only available on the main thread. As such the copy can't be done on future codegen threads. --- src/driver/aot.rs | 58 +++++++++++++++++++++++++++-------------------- src/lib.rs | 30 ++++++++++++------------ 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index ff6310bd8af2d..7e5e3453834c5 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -23,7 +23,7 @@ use crate::{prelude::*, BackendConfig}; struct ModuleCodegenResult { module_regular: CompiledModule, module_global_asm: Option, - work_product: Option<(WorkProductId, WorkProduct)>, + existing_work_product: Option<(WorkProductId, WorkProduct)>, } impl HashStable for ModuleCodegenResult { @@ -41,16 +41,44 @@ pub(crate) struct OngoingCodegen { } impl OngoingCodegen { - pub(crate) fn join(self) -> (CodegenResults, FxHashMap) { + pub(crate) fn join( + self, + sess: &Session, + backend_config: &BackendConfig, + ) -> (CodegenResults, FxHashMap) { let mut work_products = FxHashMap::default(); let mut modules = vec![]; for module_codegen_result in self.modules { - let ModuleCodegenResult { module_regular, module_global_asm, work_product } = + let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } = module_codegen_result; - if let Some((work_product_id, work_product)) = work_product { + + if let Some((work_product_id, work_product)) = existing_work_product { work_products.insert(work_product_id, work_product); + } else { + let work_product = if backend_config.disable_incr_cache { + None + } else if let Some(module_global_asm) = &module_global_asm { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module_regular.name, + &[ + ("o", &module_regular.object.as_ref().unwrap()), + ("asm.o", &module_global_asm.object.as_ref().unwrap()), + ], + ) + } else { + rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module_regular.name, + &[("o", &module_regular.object.as_ref().unwrap())], + ) + }; + if let Some((work_product_id, work_product)) = work_product { + work_products.insert(work_product_id, work_product); + } } + modules.push(module_regular); if let Some(module_global_asm) = module_global_asm { modules.push(module_global_asm); @@ -84,7 +112,6 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> fn emit_cgu( tcx: TyCtxt<'_>, - backend_config: &BackendConfig, name: String, module: ObjectModule, debug: Option>, @@ -101,22 +128,6 @@ fn emit_cgu( let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); - let work_product = if backend_config.disable_incr_cache { - None - } else if let Some(global_asm_object_file) = &global_asm_object_file { - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( - tcx.sess, - &name, - &[("o", &module_regular.object.as_ref().unwrap()), ("asm.o", global_asm_object_file)], - ) - } else { - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( - tcx.sess, - &name, - &[("o", &module_regular.object.as_ref().unwrap())], - ) - }; - ModuleCodegenResult { module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { @@ -126,7 +137,7 @@ fn emit_cgu( dwarf_object: None, bytecode: None, }), - work_product, + existing_work_product: None, } } @@ -205,7 +216,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo } else { None }, - work_product: Some((cgu.work_product_id(), work_product)), + existing_work_product: Some((cgu.work_product_id(), work_product)), } } @@ -271,7 +282,6 @@ fn module_codegen( let codegen_result = tcx.sess.time("write object file", || { emit_cgu( tcx, - &backend_config, cgu.name().as_str().to_string(), module, debug_context, diff --git a/src/lib.rs b/src/lib.rs index 6ea160d26ce5e..909f4f00f1edf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -158,7 +158,7 @@ impl<'tcx> CodegenCx<'tcx> { } pub struct CraneliftCodegenBackend { - pub config: Option, + pub config: RefCell>, } impl CodegenBackend for CraneliftCodegenBackend { @@ -168,6 +168,13 @@ impl CodegenBackend for CraneliftCodegenBackend { Lto::No | Lto::ThinLocal => {} Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."), } + + let mut config = self.config.borrow_mut(); + if config.is_none() { + let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args) + .unwrap_or_else(|err| sess.fatal(&err)); + *config = Some(new_config); + } } fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { @@ -185,15 +192,7 @@ impl CodegenBackend for CraneliftCodegenBackend { need_metadata_module: bool, ) -> Box { tcx.sess.abort_if_errors(); - let config = if let Some(config) = self.config.clone() { - config - } else { - if !tcx.sess.unstable_options() && !tcx.sess.opts.cg.llvm_args.is_empty() { - tcx.sess.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif"); - } - BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) - .unwrap_or_else(|err| tcx.sess.fatal(&err)) - }; + let config = self.config.borrow().clone().unwrap(); match config.codegen_mode { CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module), CodegenMode::Jit | CodegenMode::JitLazy => { @@ -209,10 +208,13 @@ impl CodegenBackend for CraneliftCodegenBackend { fn join_codegen( &self, ongoing_codegen: Box, - _sess: &Session, + sess: &Session, _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorGuaranteed> { - Ok(ongoing_codegen.downcast::().unwrap().join()) + Ok(ongoing_codegen + .downcast::() + .unwrap() + .join(sess, self.config.borrow().as_ref().unwrap())) } fn link( @@ -309,5 +311,5 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box Box { - Box::new(CraneliftCodegenBackend { config: None }) + Box::new(CraneliftCodegenBackend { config: RefCell::new(None) }) } From 0706df5f8cfd5bdd164d10bb67facc2a6c5f6b8f Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 12 Aug 2022 21:47:36 +0100 Subject: [PATCH 061/100] Update abi-checker version --- build_system/abi_checker.rs | 12 ++---------- build_system/prepare.rs | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index b6dc0fa69223f..67dbd0a38a4fb 100644 --- a/build_system/abi_checker.rs +++ b/build_system/abi_checker.rs @@ -1,6 +1,6 @@ use super::build_sysroot; use super::config; -use super::utils::spawn_and_wait_with_input; +use super::utils::spawn_and_wait; use build_system::SysrootKind; use std::env; use std::path::Path; @@ -56,13 +56,5 @@ pub(crate) fn run( cmd.arg("--add-rustc-codegen-backend"); cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); - let output = spawn_and_wait_with_input(cmd, "".to_string()); - - // TODO: The correct thing to do here is to check the exit code, but abi-checker - // currently doesn't return 0 on success, so check for the test fail count. - // See: https://github.com/Gankra/abi-checker/issues/10 - let failed = !(output.contains("0 failed") && output.contains("0 completely failed")); - if failed { - panic!("abi-checker failed!"); - } + spawn_and_wait(cmd); } diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 12aafdc1fb3ee..24a233d38068a 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -18,7 +18,7 @@ pub(crate) fn prepare() { "abi-checker", "Gankra", "abi-checker", - "7c1571da6e43f9a37347623e7d5c7d51be664a7b", + "a2232d45f202846f5c02203c9f27355360f9a2ff", ); clone_repo_shallow_github( From 69c6749aee93ee3c5dd3b9b394eef612d48dd6cd Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Fri, 12 Aug 2022 23:47:12 +0100 Subject: [PATCH 062/100] Disable some abi-checker tests --- build_system/prepare.rs | 1 + ...29-abi-checker-Disable-failing-tests.patch | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 patches/0029-abi-checker-Disable-failing-tests.patch diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 24a233d38068a..d23b7f00dcf16 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -20,6 +20,7 @@ pub(crate) fn prepare() { "abi-checker", "a2232d45f202846f5c02203c9f27355360f9a2ff", ); + apply_patches("abi-checker", Path::new("abi-checker")); clone_repo_shallow_github( "rand", diff --git a/patches/0029-abi-checker-Disable-failing-tests.patch b/patches/0029-abi-checker-Disable-failing-tests.patch new file mode 100644 index 0000000000000..526366a759876 --- /dev/null +++ b/patches/0029-abi-checker-Disable-failing-tests.patch @@ -0,0 +1,36 @@ +From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001 +From: Afonso Bordado +Date: Fri, 12 Aug 2022 22:51:58 +0000 +Subject: [PATCH] Disable abi-checker tests + +--- + src/report.rs | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/report.rs b/src/report.rs +index 7346f5e..8347762 100644 +--- a/src/report.rs ++++ b/src/report.rs +@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl + // + // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES + ++ // Currently MSVC has some broken ABI issues. Furthermore, they cause ++ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link. ++ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ ++ // structs is broken in the current release of cranelift for aarch64. ++ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634 ++ if cfg!(target_arch = "aarch64") && test.test_name == "structs" { ++ result.run = Link; ++ result.check = Pass(Link); ++ } ++ + // END OF VENDOR RESERVED AREA + // + // +-- +2.34.1 From 484041cefeab79874b5dd134a7e9b4b189e3c5a2 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 13 Aug 2022 10:02:16 +0100 Subject: [PATCH 063/100] Rename abi-checker patch (#1262) --- ...g-tests.patch => 0001-abi-checker-Disable-failing-tests.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename patches/{0029-abi-checker-Disable-failing-tests.patch => 0001-abi-checker-Disable-failing-tests.patch} (100%) diff --git a/patches/0029-abi-checker-Disable-failing-tests.patch b/patches/0001-abi-checker-Disable-failing-tests.patch similarity index 100% rename from patches/0029-abi-checker-Disable-failing-tests.patch rename to patches/0001-abi-checker-Disable-failing-tests.patch From 4c0766ce6cae86b0f340683d90a5ed02cace81f7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Aug 2022 09:03:28 +0000 Subject: [PATCH 064/100] Move error reporting out of emit_cgu Error reporting requires a Session, which isn't available on background threads. --- src/driver/aot.rs | 48 +++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 7e5e3453834c5..817ce7f7e6d3a 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -33,7 +33,7 @@ impl HashStable for ModuleCodegenResult { } pub(crate) struct OngoingCodegen { - modules: Vec, + modules: Vec>, allocator_module: Option, metadata_module: Option, metadata: EncodedMetadata, @@ -50,6 +50,10 @@ impl OngoingCodegen { let mut modules = vec![]; for module_codegen_result in self.modules { + let module_codegen_result = match module_codegen_result { + Ok(module_codegen_result) => module_codegen_result, + Err(err) => sess.fatal(&err), + }; let ModuleCodegenResult { module_regular, module_global_asm, existing_work_product } = module_codegen_result; @@ -117,7 +121,7 @@ fn emit_cgu( debug: Option>, unwind_context: UnwindContext, global_asm_object_file: Option, -) -> ModuleCodegenResult { +) -> Result { let mut product = module.finish(); if let Some(mut debug) = debug { @@ -126,9 +130,9 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone()); + let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone())?; - ModuleCodegenResult { + Ok(ModuleCodegenResult { module_regular, module_global_asm: global_asm_object_file.map(|global_asm_object_file| CompiledModule { name: format!("{name}.asm"), @@ -138,7 +142,7 @@ fn emit_cgu( bytecode: None, }), existing_work_product: None, - } + }) } fn emit_module( @@ -146,23 +150,26 @@ fn emit_module( object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, -) -> CompiledModule { +) -> Result { let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); let mut file = match File::create(&tmp_file) { Ok(file) => file, - Err(err) => tcx.sess.fatal(&format!("error creating object file: {}", err)), + Err(err) => return Err(format!("error creating object file: {}", err)), }; if let Err(err) = object.write_stream(&mut file) { - tcx.sess.fatal(&format!("error writing object file: {}", err)); + return Err(format!("error writing object file: {}", err)); } tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); - CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None } + Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }) } -fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCodegenResult { +fn reuse_workproduct_for_cgu( + tcx: TyCtxt<'_>, + cgu: &CodegenUnit<'_>, +) -> Result { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); @@ -172,7 +179,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo ); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) { - tcx.sess.err(&format!( + return Err(format!( "unable to copy {} to {}: {}", source_file_regular.display(), obj_out_regular.display(), @@ -185,7 +192,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { - tcx.sess.err(&format!( + return Err(format!( "unable to copy {} to {}: {}", source_file_regular.display(), obj_out_regular.display(), @@ -197,7 +204,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo false }; - ModuleCodegenResult { + Ok(ModuleCodegenResult { module_regular: CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, @@ -217,7 +224,7 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo None }, existing_work_product: Some((cgu.work_product_id(), work_product)), - } + }) } fn module_codegen( @@ -227,7 +234,7 @@ fn module_codegen( Arc, rustc_span::Symbol, ), -) -> ModuleCodegenResult { +) -> Result { let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); @@ -279,7 +286,7 @@ fn module_codegen( let debug_context = cx.debug_context; let unwind_context = cx.unwind_context; - let codegen_result = tcx.sess.time("write object file", || { + tcx.sess.time("write object file", || { emit_cgu( tcx, cgu.name().as_str().to_string(), @@ -288,9 +295,7 @@ fn module_codegen( unwind_context, global_asm_object_file, ) - }); - - codegen_result + }) } pub(crate) fn run_aot( @@ -356,7 +361,10 @@ pub(crate) fn run_aot( let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - Some(emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned())) + match emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned()) { + Ok(allocator_module) => Some(allocator_module), + Err(err) => tcx.sess.fatal(err), + } } else { None }; From 9461fd2cb061c7016207c22dc77f7ad906066279 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Aug 2022 12:18:41 +0000 Subject: [PATCH 065/100] Remove TyCtxt parameter from emit_cgu TyCtxt isn't available on background threads. --- src/driver/aot.rs | 27 +++++++++++++++++++-------- src/global_asm.rs | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 817ce7f7e6d3a..9d819e3995bbc 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -7,12 +7,13 @@ use std::sync::Arc; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::mir::mono::{CodegenUnit, MonoItem}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{DebugInfo, OutputType}; +use rustc_session::config::{DebugInfo, OutputFilenames, OutputType}; use rustc_session::Session; use cranelift_object::{ObjectBuilder, ObjectModule}; @@ -115,7 +116,8 @@ fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> } fn emit_cgu( - tcx: TyCtxt<'_>, + output_filenames: &OutputFilenames, + prof: &SelfProfilerRef, name: String, module: ObjectModule, debug: Option>, @@ -130,7 +132,8 @@ fn emit_cgu( unwind_context.emit(&mut product); - let module_regular = emit_module(tcx, product.object, ModuleKind::Regular, name.clone())?; + let module_regular = + emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?; Ok(ModuleCodegenResult { module_regular, @@ -146,12 +149,13 @@ fn emit_cgu( } fn emit_module( - tcx: TyCtxt<'_>, + output_filenames: &OutputFilenames, + prof: &SelfProfilerRef, object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, name: String, ) -> Result { - let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name)); + let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); let mut file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -161,7 +165,7 @@ fn emit_module( return Err(format!("error writing object file: {}", err)); } - tcx.sess.prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); + prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); Ok(CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None }) } @@ -288,7 +292,8 @@ fn module_codegen( let unwind_context = cx.unwind_context; tcx.sess.time("write object file", || { emit_cgu( - tcx, + &global_asm_config.output_filenames, + &tcx.sess.prof, cgu.name().as_str().to_string(), module, debug_context, @@ -361,7 +366,13 @@ pub(crate) fn run_aot( let mut product = allocator_module.finish(); allocator_unwind_context.emit(&mut product); - match emit_module(tcx, product.object, ModuleKind::Allocator, "allocator_shim".to_owned()) { + match emit_module( + tcx.output_filenames(()), + &tcx.sess.prof, + product.object, + ModuleKind::Allocator, + "allocator_shim".to_owned(), + ) { Ok(allocator_module) => Some(allocator_module), Err(err) => tcx.sess.fatal(err), } diff --git a/src/global_asm.rs b/src/global_asm.rs index 917a6fff72779..dcbcaba30feed 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -36,7 +36,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, pub(crate) struct GlobalAsmConfig { asm_enabled: bool, assembler: PathBuf, - output_filenames: Arc, + pub(crate) output_filenames: Arc, } impl GlobalAsmConfig { From 1662702a881a2137b5c82b43394ffb40dc3e964a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 14 Aug 2022 16:37:30 +0000 Subject: [PATCH 066/100] Work around new asm! usage in measureme This is necessary to fix rustc bootstraps --- src/inline_asm.rs | 156 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 37 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 7b1a39c675cde..9221abb822572 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -20,10 +20,14 @@ pub(crate) fn codegen_inline_asm<'tcx>( // FIXME add .eh_frame unwind info directives if !template.is_empty() { + // Used by panic_abort if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { fx.bcx.ins().trap(TrapCode::User(1)); return; - } else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) + } + + // Used by stdarch + if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string()) && matches!( template[1], InlineAsmTemplatePiece::Placeholder { @@ -47,51 +51,46 @@ pub(crate) fn codegen_inline_asm<'tcx>( { assert_eq!(operands.len(), 4); let (leaf, eax_place) = match operands[1] { - InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)) - ); - ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place.unwrap()), - ) - } + InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + ref in_value, + out_place: Some(out_place), + } => ( + crate::base::codegen_operand(fx, in_value).load_scalar(fx), + crate::base::codegen_place(fx, out_place), + ), _ => unreachable!(), }; let ebx_place = match operands[0] { - InlineAsmOperand::Out { reg, late: true, place } => { - assert_eq!( - reg, + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86( - X86InlineAsmRegClass::reg - )) - ); - crate::base::codegen_place(fx, place.unwrap()) - } + X86InlineAsmRegClass::reg, + )), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), _ => unreachable!(), }; let (sub_leaf, ecx_place) = match operands[2] { - InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)) - ); - ( - crate::base::codegen_operand(fx, in_value).load_scalar(fx), - crate::base::codegen_place(fx, out_place.unwrap()), - ) - } + InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + late: true, + ref in_value, + out_place: Some(out_place), + } => ( + crate::base::codegen_operand(fx, in_value).load_scalar(fx), + crate::base::codegen_place(fx, out_place), + ), _ => unreachable!(), }; let edx_place = match operands[3] { - InlineAsmOperand::Out { reg, late: true, place } => { - assert_eq!( - reg, - InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)) - ); - crate::base::codegen_place(fx, place.unwrap()) - } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), _ => unreachable!(), }; @@ -104,7 +103,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( let destination_block = fx.get_block(destination.unwrap()); fx.bcx.ins().jump(destination_block, &[]); return; - } else if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { + } + + // Used by compiler-builtins + if fx.tcx.symbol_name(fx.instance).name.starts_with("___chkstk") { // ___chkstk, ___chkstk_ms and __alloca are only used on Windows crate::trap::trap_unimplemented(fx, "Stack probes are not supported"); return; @@ -112,6 +114,86 @@ pub(crate) fn codegen_inline_asm<'tcx>( crate::trap::trap_unimplemented(fx, "Alloca is not supported"); return; } + + // Used by measureme + if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string()) + && template[1] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[2] == InlineAsmTemplatePiece::String("mov %rbx, ".to_string()) + && matches!( + template[3], + InlineAsmTemplatePiece::Placeholder { + operand_idx: 0, + modifier: Some('r'), + span: _ + } + ) + && template[4] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[5] == InlineAsmTemplatePiece::String("cpuid".to_string()) + && template[6] == InlineAsmTemplatePiece::String("\n".to_string()) + && template[7] == InlineAsmTemplatePiece::String("mov ".to_string()) + && matches!( + template[8], + InlineAsmTemplatePiece::Placeholder { + operand_idx: 0, + modifier: Some('r'), + span: _ + } + ) + && template[9] == InlineAsmTemplatePiece::String(", %rbx".to_string()) + { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } else if template[0] == InlineAsmTemplatePiece::String("rdpmc".to_string()) { + // Return zero dummy values for all performance counters + match operands[0] { + InlineAsmOperand::In { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)), + value: _, + } => {} + _ => unreachable!(), + }; + let lo = match operands[1] { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), + _ => unreachable!(), + }; + let hi = match operands[2] { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)), + late: true, + place: Some(place), + } => crate::base::codegen_place(fx, place), + _ => unreachable!(), + }; + + let u32_layout = fx.layout_of(fx.tcx.types.u32); + let zero = fx.bcx.ins().iconst(types::I32, 0); + lo.write_cvalue(fx, CValue::by_val(zero, u32_layout)); + hi.write_cvalue(fx, CValue::by_val(zero, u32_layout)); + + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } else if template[0] == InlineAsmTemplatePiece::String("lock xadd ".to_string()) + && matches!( + template[1], + InlineAsmTemplatePiece::Placeholder { operand_idx: 1, modifier: None, span: _ } + ) + && template[2] == InlineAsmTemplatePiece::String(", (".to_string()) + && matches!( + template[3], + InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } + ) + && template[4] == InlineAsmTemplatePiece::String(")".to_string()) + { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } } let mut inputs = Vec::new(); From 1cac888e4361aea0abbaf8c0ee52509f1742bfe0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:21:41 +0200 Subject: [PATCH 067/100] Rustup to rustc 1.65.0-nightly (801821d15 2022-08-14) --- build_sysroot/Cargo.lock | 8 ++++---- rust-toolchain | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index e9bd9167acd8b..9713f13ccb33a 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413b6b13f725a46cdec40364e0c1d564a22cf0aaac5f1e267a129d956478a6b4" +checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca" dependencies = [ "rustc-std-workspace-core", ] @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.127" +version = "0.2.131" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" +checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index 9b9ed85f6c751..1405265959db1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-08-08" +channel = "nightly-2022-08-15" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 701b2747c331fb311ab67e50519bb226d86b76dc Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:03:32 +0000 Subject: [PATCH 068/100] Remove optimize_function It currently doesn't have any optimizations at all. --- src/base.rs | 13 +------------ src/optimize/mod.rs | 17 ----------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/base.rs b/src/base.rs index c68d33465bc2a..2603da1918280 100644 --- a/src/base.rs +++ b/src/base.rs @@ -148,7 +148,7 @@ fn compile_fn<'tcx>( ) { let tcx = cx.tcx; - let mut clif_comments = codegened_func.clif_comments; + let clif_comments = codegened_func.clif_comments; // Store function in context let context = cached_context; @@ -165,17 +165,6 @@ fn compile_fn<'tcx>( // invalidate it when it would change. context.domtree.clear(); - // Perform rust specific optimizations - tcx.sess.time("optimize clif ir", || { - crate::optimize::optimize_function( - tcx, - module.isa(), - codegened_func.instance, - context, - &mut clif_comments, - ); - }); - #[cfg(any())] // This is never true let _clif_guard = { use std::fmt::Write; diff --git a/src/optimize/mod.rs b/src/optimize/mod.rs index d1f89adb3bb91..0df7e82294bd2 100644 --- a/src/optimize/mod.rs +++ b/src/optimize/mod.rs @@ -1,20 +1,3 @@ //! Various optimizations specific to cg_clif -use cranelift_codegen::isa::TargetIsa; - -use crate::prelude::*; - pub(crate) mod peephole; - -pub(crate) fn optimize_function<'tcx>( - tcx: TyCtxt<'tcx>, - isa: &dyn TargetIsa, - instance: Instance<'tcx>, - ctx: &mut Context, - clif_comments: &mut crate::pretty_clif::CommentWriter, -) { - // FIXME classify optimizations over opt levels once we have more - - crate::pretty_clif::write_clif_file(tcx, "preopt", isa, instance, &ctx.func, &*clif_comments); - crate::base::verify_func(tcx, &*clif_comments, &ctx.func); -} From b181f2b3769f1185d328efb1569c3da72e5edaa0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:07:18 +0000 Subject: [PATCH 069/100] Replace instance param of write_clif_file with symbol_name --- src/base.rs | 6 +++--- src/pretty_clif.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index 2603da1918280..85cdc6824a62d 100644 --- a/src/base.rs +++ b/src/base.rs @@ -119,9 +119,9 @@ fn codegen_fn<'tcx>( crate::pretty_clif::write_clif_file( tcx, + symbol_name.name, "unopt", module.isa(), - instance, &func, &clif_comments, ); @@ -201,9 +201,9 @@ fn compile_fn<'tcx>( // Write optimized function to file for debugging crate::pretty_clif::write_clif_file( tcx, + codegened_func.symbol_name.name, "opt", module.isa(), - codegened_func.instance, &context.func, &clif_comments, ); @@ -211,7 +211,7 @@ fn compile_fn<'tcx>( if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { crate::pretty_clif::write_ir_file( tcx, - || format!("{}.vcode", tcx.symbol_name(codegened_func.instance).name), + || format!("{}.vcode", codegened_func.symbol_name.name), |file| file.write_all(disasm.as_bytes()), ) } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 1d1ec21680e30..0081ec842eb66 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -231,16 +231,16 @@ pub(crate) fn write_ir_file( pub(crate) fn write_clif_file<'tcx>( tcx: TyCtxt<'tcx>, + symbol_name: &str, postfix: &str, isa: &dyn cranelift_codegen::isa::TargetIsa, - instance: Instance<'tcx>, func: &cranelift_codegen::ir::Function, mut clif_comments: &CommentWriter, ) { // FIXME work around filename too long errors write_ir_file( tcx, - || format!("{}.{}.clif", tcx.symbol_name(instance).name, postfix), + || format!("{}.{}.clif", symbol_name, postfix), |file| { let mut clif = String::new(); cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func) From c820b7cd607cd2fa7eec88785d92d10461b39053 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:43:32 +0000 Subject: [PATCH 070/100] Remove TyCtxt field from CodegenCx --- src/base.rs | 66 ++++++++++++++++++++++++---------------------- src/driver/aot.rs | 3 ++- src/driver/jit.rs | 10 +++---- src/lib.rs | 7 +++-- src/pretty_clif.rs | 59 +++++++++++++++++++---------------------- 5 files changed, 73 insertions(+), 72 deletions(-) diff --git a/src/base.rs b/src/base.rs index 85cdc6824a62d..6a276df40bacc 100644 --- a/src/base.rs +++ b/src/base.rs @@ -24,22 +24,23 @@ struct CodegenedFunction<'tcx> { } pub(crate) fn codegen_and_compile_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, instance: Instance<'tcx>, ) { - let tcx = cx.tcx; let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); - let codegened_func = codegen_fn(cx, cached_func, module, instance); + let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(cx, cached_context, module, codegened_func); + compile_fn(tcx, cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_func: Function, module: &mut dyn Module, @@ -47,8 +48,6 @@ fn codegen_fn<'tcx>( ) -> CodegenedFunction<'tcx> { debug_assert!(!instance.substs.needs_infer()); - let tcx = cx.tcx; - let mir = tcx.instance_mir(instance.def); let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); @@ -117,14 +116,16 @@ fn codegen_fn<'tcx>( fx.constants_cx.finalize(fx.tcx, &mut *fx.module); - crate::pretty_clif::write_clif_file( - tcx, - symbol_name.name, - "unopt", - module.isa(), - &func, - &clif_comments, - ); + if cx.should_write_ir { + crate::pretty_clif::write_clif_file( + tcx.output_filenames(()), + symbol_name.name, + "unopt", + module.isa(), + &func, + &clif_comments, + ); + } // Verify function verify_func(tcx, &clif_comments, &func); @@ -141,13 +142,12 @@ fn codegen_fn<'tcx>( } fn compile_fn<'tcx>( + tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction<'tcx>, ) { - let tcx = cx.tcx; - let clif_comments = codegened_func.clif_comments; // Store function in context @@ -194,26 +194,28 @@ fn compile_fn<'tcx>( // Define function tcx.sess.time("define function", || { - context.want_disasm = crate::pretty_clif::should_write_ir(tcx); + context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); }); - // Write optimized function to file for debugging - crate::pretty_clif::write_clif_file( - tcx, - codegened_func.symbol_name.name, - "opt", - module.isa(), - &context.func, - &clif_comments, - ); - - if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { - crate::pretty_clif::write_ir_file( - tcx, - || format!("{}.vcode", codegened_func.symbol_name.name), - |file| file.write_all(disasm.as_bytes()), - ) + 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.name, + "opt", + module.isa(), + &context.func, + &clif_comments, + ); + + if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { + crate::pretty_clif::write_ir_file( + &cx.output_filenames, + &format!("{}.vcode", codegened_func.symbol_name.name), + |file| file.write_all(disasm.as_bytes()), + ) + } } // Define debuginfo for function diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 9d819e3995bbc..b2ad3cc4c4cde 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -256,8 +256,9 @@ fn module_codegen( for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { - cx.tcx.sess.time("codegen fn", || { + tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut cached_context, &mut module, diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 1b046d7ec6e8b..de71b76da4efe 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -129,8 +129,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { MonoItem::Fn(inst) => match backend_config.codegen_mode { CodegenMode::Aot => unreachable!(), CodegenMode::Jit => { - cx.tcx.sess.time("codegen fn", || { + tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut cached_context, &mut jit_module, @@ -139,7 +140,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { }); } CodegenMode::JitLazy => { - codegen_shim(&mut cx, &mut cached_context, &mut jit_module, inst) + codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) } }, MonoItem::Static(def_id) => { @@ -269,6 +270,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> ); tcx.sess.time("codegen fn", || { crate::base::codegen_and_compile_fn( + tcx, &mut cx, &mut Context::new(), jit_module, @@ -350,13 +352,11 @@ fn load_imported_symbols_for_jit( } fn codegen_shim<'tcx>( - cx: &mut CodegenCx<'tcx>, + tcx: TyCtxt<'tcx>, cached_context: &mut Context, module: &mut JITModule, inst: Instance<'tcx>, ) { - let tcx = cx.tcx; - let pointer_type = module.target_config().pointer_type(); let name = tcx.symbol_name(inst).name; diff --git a/src/lib.rs b/src/lib.rs index 909f4f00f1edf..1e851e31ac304 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_driver; use std::any::Any; use std::cell::{Cell, RefCell}; +use std::sync::Arc; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -121,7 +122,8 @@ impl String> Drop for PrintOnPanic { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx<'tcx> { - tcx: TyCtxt<'tcx>, + output_filenames: Arc, + should_write_ir: bool, global_asm: String, inline_asm_index: Cell, debug_context: Option>, @@ -147,7 +149,8 @@ impl<'tcx> CodegenCx<'tcx> { None }; CodegenCx { - tcx, + output_filenames: tcx.output_filenames(()).clone(), + should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), inline_asm_index: Cell::new(0), debug_context, diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 0081ec842eb66..a7af162687c34 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -62,7 +62,7 @@ use cranelift_codegen::{ }; use rustc_middle::ty::layout::FnAbiOf; -use rustc_session::config::OutputType; +use rustc_session::config::{OutputFilenames, OutputType}; use crate::prelude::*; @@ -205,15 +205,11 @@ pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool { } pub(crate) fn write_ir_file( - tcx: TyCtxt<'_>, - name: impl FnOnce() -> String, + output_filenames: &OutputFilenames, + name: &str, write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>, ) { - if !should_write_ir(tcx) { - return; - } - - let clif_output_dir = tcx.output_filenames(()).with_extension("clif"); + let clif_output_dir = output_filenames.with_extension("clif"); match std::fs::create_dir(&clif_output_dir) { Ok(()) => {} @@ -221,16 +217,20 @@ pub(crate) fn write_ir_file( res @ Err(_) => res.unwrap(), } - let clif_file_name = clif_output_dir.join(name()); + let clif_file_name = clif_output_dir.join(name); let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file)); if let Err(err) = res { - tcx.sess.warn(&format!("error writing ir file: {}", err)); + // Using early_warn as no Session is available here + rustc_session::early_warn( + rustc_session::config::ErrorOutputType::default(), + &format!("error writing ir file: {}", err), + ); } } -pub(crate) fn write_clif_file<'tcx>( - tcx: TyCtxt<'tcx>, +pub(crate) fn write_clif_file( + output_filenames: &OutputFilenames, symbol_name: &str, postfix: &str, isa: &dyn cranelift_codegen::isa::TargetIsa, @@ -238,27 +238,22 @@ pub(crate) fn write_clif_file<'tcx>( mut clif_comments: &CommentWriter, ) { // FIXME work around filename too long errors - write_ir_file( - tcx, - || format!("{}.{}.clif", symbol_name, postfix), - |file| { - let mut clif = String::new(); - cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func) - .unwrap(); + write_ir_file(output_filenames, &format!("{}.{}.clif", symbol_name, postfix), |file| { + let mut clif = String::new(); + cranelift_codegen::write::decorate_function(&mut clif_comments, &mut clif, func).unwrap(); - for flag in isa.flags().iter() { - writeln!(file, "set {}", flag)?; - } - write!(file, "target {}", isa.triple().architecture.to_string())?; - for isa_flag in isa.isa_flags().iter() { - write!(file, " {}", isa_flag)?; - } - writeln!(file, "\n")?; - writeln!(file)?; - file.write_all(clif.as_bytes())?; - Ok(()) - }, - ); + for flag in isa.flags().iter() { + writeln!(file, "set {}", flag)?; + } + write!(file, "target {}", isa.triple().architecture.to_string())?; + for isa_flag in isa.isa_flags().iter() { + write!(file, " {}", isa_flag)?; + } + writeln!(file, "\n")?; + writeln!(file)?; + file.write_all(clif.as_bytes())?; + Ok(()) + }); } impl fmt::Debug for FunctionCx<'_, '_, '_> { From 2079b4bb0890f4ac806fa7f8cbe16e3c64ba9bee Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Wed, 17 Aug 2022 14:46:05 +0100 Subject: [PATCH 071/100] Use `stack_store` instead of `stack_addr`+`store` when building structs --- src/abi/pass_mode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 2f8c697bd1e02..3192575b8ad4e 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -193,7 +193,7 @@ pub(super) fn from_casted_value<'tcx>( // larger alignment than the integer. size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, }); - let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); + let ptr = Pointer::stack_slot(stack_slot); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); for param in abi_params { From df1b25171c8b2b209d1c667ea8a2e41a81c108f2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:47:52 +0000 Subject: [PATCH 072/100] Remove TyCtxt parameter from compile_fn --- src/base.rs | 7 +++---- src/lib.rs | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/base.rs b/src/base.rs index 6a276df40bacc..a7c7f66e166bf 100644 --- a/src/base.rs +++ b/src/base.rs @@ -36,7 +36,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(tcx, cx, cached_context, module, codegened_func); + compile_fn(cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( @@ -142,7 +142,6 @@ fn codegen_fn<'tcx>( } fn compile_fn<'tcx>( - tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx<'tcx>, cached_context: &mut Context, module: &mut dyn Module, @@ -193,7 +192,7 @@ fn compile_fn<'tcx>( }; // Define function - tcx.sess.time("define function", || { + cx.profiler.verbose_generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); }); @@ -222,7 +221,7 @@ fn compile_fn<'tcx>( let isa = module.isa(); let debug_context = &mut cx.debug_context; let unwind_context = &mut cx.unwind_context; - tcx.sess.time("generate debug info", || { + cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { debug_context.define_function( codegened_func.instance, diff --git a/src/lib.rs b/src/lib.rs index 1e851e31ac304..f4ffbbcf86ece 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ use std::sync::Arc; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -122,6 +123,7 @@ impl String> Drop for PrintOnPanic { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx<'tcx> { + profiler: SelfProfilerRef, output_filenames: Arc, should_write_ir: bool, global_asm: String, @@ -149,6 +151,7 @@ impl<'tcx> CodegenCx<'tcx> { None }; CodegenCx { + profiler: tcx.prof.clone(), output_filenames: tcx.output_filenames(()).clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), From 5fc1366dfa0b5c9615be028e75f4f237f165831b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:55:44 +0000 Subject: [PATCH 073/100] Register debuginfo for lazy jit shim --- src/driver/jit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index de71b76da4efe..00e7263446b7c 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -140,7 +140,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { }); } CodegenMode::JitLazy => { - codegen_shim(tcx, &mut cached_context, &mut jit_module, inst) + codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst) } }, MonoItem::Static(def_id) => { @@ -353,6 +353,7 @@ fn load_imported_symbols_for_jit( fn codegen_shim<'tcx>( tcx: TyCtxt<'tcx>, + cx: &mut CodegenCx<'tcx>, cached_context: &mut Context, module: &mut JITModule, inst: Instance<'tcx>, @@ -403,4 +404,5 @@ fn codegen_shim<'tcx>( trampoline_builder.ins().return_(&ret_vals); module.define_function(func_id, context).unwrap(); + cx.unwind_context.add_function(func_id, context, module.isa()); } From a49416da6ddcbcbd40f7aadb06b71d77c23e8220 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:14:04 +0000 Subject: [PATCH 074/100] Remove stub local debuginfo implementation It isn't actually wired up and temporarily removing it will make changes to the debuginfo generation code much simpler. --- src/base.rs | 14 +-- src/debuginfo/mod.rs | 230 +------------------------------------------ 2 files changed, 5 insertions(+), 239 deletions(-) diff --git a/src/base.rs b/src/base.rs index a7c7f66e166bf..fe04567af66c2 100644 --- a/src/base.rs +++ b/src/base.rs @@ -20,7 +20,6 @@ struct CodegenedFunction<'tcx> { func: Function, clif_comments: CommentWriter, source_info_set: IndexSet, - local_map: IndexVec>, } pub(crate) fn codegen_and_compile_fn<'tcx>( @@ -112,7 +111,6 @@ fn codegen_fn<'tcx>( let instance = fx.instance; let clif_comments = fx.clif_comments; let source_info_set = fx.source_info_set; - let local_map = fx.local_map; fx.constants_cx.finalize(fx.tcx, &mut *fx.module); @@ -130,15 +128,7 @@ fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - CodegenedFunction { - instance, - symbol_name, - func_id, - func, - clif_comments, - source_info_set, - local_map, - } + CodegenedFunction { instance, symbol_name, func_id, func, clif_comments, source_info_set } } fn compile_fn<'tcx>( @@ -227,10 +217,8 @@ fn compile_fn<'tcx>( codegened_func.instance, codegened_func.func_id, codegened_func.symbol_name.name, - isa, context, &codegened_func.source_info_set, - codegened_func.local_map, ); } unwind_context.add_function(codegened_func.func_id, &context, isa); diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 693092ba543ea..7a330ff7d359e 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -7,18 +7,11 @@ mod unwind; use crate::prelude::*; -use rustc_index::vec::IndexVec; - -use cranelift_codegen::entity::EntityRef; -use cranelift_codegen::ir::{Endianness, LabelValueLoc, ValueLabel}; +use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::TargetIsa; -use cranelift_codegen::ValueLocRange; -use gimli::write::{ - Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location, - LocationList, Range, RangeList, UnitEntryId, -}; -use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64}; +use gimli::write::{Address, AttributeValue, DwarfUnit, LineProgram, LineString, Range, RangeList}; +use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; @@ -30,8 +23,6 @@ pub(crate) struct DebugContext<'tcx> { dwarf: DwarfUnit, unit_range_list: RangeList, - - types: FxHashMap, UnitEntryId>, } impl<'tcx> DebugContext<'tcx> { @@ -101,113 +92,7 @@ impl<'tcx> DebugContext<'tcx> { root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0))); } - DebugContext { - tcx, - - endian, - - dwarf, - unit_range_list: RangeList(Vec::new()), - - types: FxHashMap::default(), - } - } - - fn dwarf_ty(&mut self, ty: Ty<'tcx>) -> UnitEntryId { - if let Some(type_id) = self.types.get(&ty) { - return *type_id; - } - - let new_entry = |dwarf: &mut DwarfUnit, tag| dwarf.unit.add(dwarf.unit.root(), tag); - - let primitive = |dwarf: &mut DwarfUnit, ate| { - let type_id = new_entry(dwarf, gimli::DW_TAG_base_type); - let type_entry = dwarf.unit.get_mut(type_id); - type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(ate)); - type_id - }; - - let name = format!("{}", ty); - let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(); - - let type_id = match ty.kind() { - ty::Bool => primitive(&mut self.dwarf, gimli::DW_ATE_boolean), - ty::Char => primitive(&mut self.dwarf, gimli::DW_ATE_UTF), - ty::Uint(_) => primitive(&mut self.dwarf, gimli::DW_ATE_unsigned), - ty::Int(_) => primitive(&mut self.dwarf, gimli::DW_ATE_signed), - ty::Float(_) => primitive(&mut self.dwarf, gimli::DW_ATE_float), - ty::Ref(_, pointee_ty, _mutbl) - | ty::RawPtr(ty::TypeAndMut { ty: pointee_ty, mutbl: _mutbl }) => { - let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_pointer_type); - - // Ensure that type is inserted before recursing to avoid duplicates - self.types.insert(ty, type_id); - - let pointee = self.dwarf_ty(*pointee_ty); - - let type_entry = self.dwarf.unit.get_mut(type_id); - - //type_entry.set(gimli::DW_AT_mutable, AttributeValue::Flag(mutbl == rustc_hir::Mutability::Mut)); - type_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(pointee)); - - type_id - } - ty::Adt(adt_def, _substs) if adt_def.is_struct() && !layout.is_unsized() => { - let type_id = new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type); - - // Ensure that type is inserted before recursing to avoid duplicates - self.types.insert(ty, type_id); - - let variant = adt_def.non_enum_variant(); - - for (field_idx, field_def) in variant.fields.iter().enumerate() { - let field_offset = layout.fields.offset(field_idx); - let field_layout = layout.field( - &layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() }, - field_idx, - ); - - let field_type = self.dwarf_ty(field_layout.ty); - - let field_id = self.dwarf.unit.add(type_id, gimli::DW_TAG_member); - let field_entry = self.dwarf.unit.get_mut(field_id); - - field_entry.set( - gimli::DW_AT_name, - AttributeValue::String(field_def.name.as_str().to_string().into_bytes()), - ); - field_entry.set( - gimli::DW_AT_data_member_location, - AttributeValue::Udata(field_offset.bytes()), - ); - field_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(field_type)); - } - - type_id - } - _ => new_entry(&mut self.dwarf, gimli::DW_TAG_structure_type), - }; - - let type_entry = self.dwarf.unit.get_mut(type_id); - - type_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes())); - type_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes())); - - self.types.insert(ty, type_id); - - type_id - } - - fn define_local(&mut self, scope: UnitEntryId, name: String, ty: Ty<'tcx>) -> UnitEntryId { - let dw_ty = self.dwarf_ty(ty); - - let var_id = self.dwarf.unit.add(scope, gimli::DW_TAG_variable); - let var_entry = self.dwarf.unit.get_mut(var_id); - - var_entry.set(gimli::DW_AT_name, AttributeValue::String(name.into_bytes())); - var_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty)); - - var_id + DebugContext { tcx, endian, dwarf, unit_range_list: RangeList(Vec::new()) } } pub(crate) fn define_function( @@ -215,10 +100,8 @@ impl<'tcx> DebugContext<'tcx> { instance: Instance<'tcx>, func_id: FuncId, name: &str, - isa: &dyn TargetIsa, context: &Context, source_info_set: &indexmap::IndexSet, - local_map: IndexVec>, ) { let symbol = func_id.as_u32() as usize; let mir = self.tcx.instance_mir(instance.def); @@ -248,110 +131,5 @@ impl<'tcx> DebugContext<'tcx> { ); // Using Udata for DW_AT_high_pc requires at least DWARF4 func_entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(end))); - - // FIXME make it more reliable and implement scopes before re-enabling this. - if false { - let value_labels_ranges = std::collections::HashMap::new(); // FIXME - - for (local, _local_decl) in mir.local_decls.iter_enumerated() { - let ty = self.tcx.subst_and_normalize_erasing_regions( - instance.substs, - ty::ParamEnv::reveal_all(), - mir.local_decls[local].ty, - ); - let var_id = self.define_local(entry_id, format!("{:?}", local), ty); - - let location = place_location( - self, - isa, - symbol, - &local_map, - &value_labels_ranges, - Place { local, projection: ty::List::empty() }, - ); - - let var_entry = self.dwarf.unit.get_mut(var_id); - var_entry.set(gimli::DW_AT_location, location); - } - } - - // FIXME create locals for all entries in mir.var_debug_info - } -} - -fn place_location<'tcx>( - debug_context: &mut DebugContext<'tcx>, - isa: &dyn TargetIsa, - symbol: usize, - local_map: &IndexVec>, - #[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap< - ValueLabel, - Vec, - >, - place: Place<'tcx>, -) -> AttributeValue { - assert!(place.projection.is_empty()); // FIXME implement them - - match local_map[place.local].inner() { - CPlaceInner::Var(_local, var) => { - let value_label = cranelift_codegen::ir::ValueLabel::new(var.index()); - if let Some(value_loc_ranges) = value_labels_ranges.get(&value_label) { - let loc_list = LocationList( - value_loc_ranges - .iter() - .map(|value_loc_range| Location::StartEnd { - begin: Address::Symbol { - symbol, - addend: i64::from(value_loc_range.start), - }, - end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) }, - data: translate_loc(isa, value_loc_range.loc).unwrap(), - }) - .collect(), - ); - let loc_list_id = debug_context.dwarf.unit.locations.add(loc_list); - - AttributeValue::LocationListRef(loc_list_id) - } else { - // FIXME set value labels for unused locals - - AttributeValue::Exprloc(Expression::new()) - } - } - CPlaceInner::VarPair(_, _, _) => { - // FIXME implement this - - AttributeValue::Exprloc(Expression::new()) - } - CPlaceInner::VarLane(_, _, _) => { - // FIXME implement this - - AttributeValue::Exprloc(Expression::new()) - } - CPlaceInner::Addr(_, _) => { - // FIXME implement this (used by arguments and returns) - - AttributeValue::Exprloc(Expression::new()) - - // For PointerBase::Stack: - //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot)).unwrap()) - } - } -} - -// Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137 -fn translate_loc(isa: &dyn TargetIsa, loc: LabelValueLoc) -> Option { - match loc { - LabelValueLoc::Reg(reg) => { - let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap(); - let mut expr = Expression::new(); - expr.op_reg(gimli::Register(machine_reg)); - Some(expr) - } - LabelValueLoc::SPOffset(offset) => { - let mut expr = Expression::new(); - expr.op_breg(X86_64::RSP, offset); - Some(expr) - } } } From e5493a5ea260a4f112a081c4bc488d85049ca36c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:19:29 +0000 Subject: [PATCH 075/100] Remove Instance param of DebugContext::define_function --- src/base.rs | 8 ++++---- src/debuginfo/mod.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/base.rs b/src/base.rs index fe04567af66c2..b35f02e2d2d75 100644 --- a/src/base.rs +++ b/src/base.rs @@ -14,11 +14,11 @@ use crate::prelude::*; use crate::pretty_clif::CommentWriter; struct CodegenedFunction<'tcx> { - instance: Instance<'tcx>, symbol_name: SymbolName<'tcx>, func_id: FuncId, func: Function, clif_comments: CommentWriter, + function_span: Span, source_info_set: IndexSet, } @@ -108,8 +108,8 @@ fn codegen_fn<'tcx>( tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); // Recover all necessary data from fx, before accessing func will prevent future access to it. - let instance = fx.instance; let clif_comments = fx.clif_comments; + let function_span = fx.mir.span; let source_info_set = fx.source_info_set; fx.constants_cx.finalize(fx.tcx, &mut *fx.module); @@ -128,7 +128,7 @@ fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - CodegenedFunction { instance, symbol_name, func_id, func, clif_comments, source_info_set } + CodegenedFunction { symbol_name, func_id, func, clif_comments, function_span, source_info_set } } fn compile_fn<'tcx>( @@ -214,10 +214,10 @@ fn compile_fn<'tcx>( cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { debug_context.define_function( - codegened_func.instance, codegened_func.func_id, codegened_func.symbol_name.name, context, + codegened_func.function_span, &codegened_func.source_info_set, ); } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 7a330ff7d359e..9a0787508b751 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -97,14 +97,13 @@ impl<'tcx> DebugContext<'tcx> { pub(crate) fn define_function( &mut self, - instance: Instance<'tcx>, func_id: FuncId, name: &str, context: &Context, + function_span: Span, source_info_set: &indexmap::IndexSet, ) { let symbol = func_id.as_u32() as usize; - let mir = self.tcx.instance_mir(instance.def); // FIXME: add to appropriate scope instead of root let scope = self.dwarf.unit.root(); @@ -116,7 +115,8 @@ impl<'tcx> DebugContext<'tcx> { entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id)); entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id)); - let end = self.create_debug_lines(symbol, entry_id, context, mir.span, source_info_set); + let end = + self.create_debug_lines(symbol, entry_id, context, function_span, source_info_set); self.unit_range_list.0.push(Range::StartLength { begin: Address::Symbol { symbol, addend: 0 }, From 259b21fd46b9ccfd084bce3ec8043543ca9ea61a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:25:26 +0000 Subject: [PATCH 076/100] Remove TyCtxt from DebugContext And explicitly thread it through everwhere it is needed. --- src/base.rs | 10 ++++++---- src/common.rs | 2 +- src/debuginfo/emit.rs | 2 +- src/debuginfo/line_info.rs | 10 +++++----- src/debuginfo/mod.rs | 13 ++++++------- src/driver/aot.rs | 2 +- src/driver/jit.rs | 8 ++++---- src/lib.rs | 8 ++++---- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/base.rs b/src/base.rs index b35f02e2d2d75..b2026f30d17a4 100644 --- a/src/base.rs +++ b/src/base.rs @@ -24,7 +24,7 @@ struct CodegenedFunction<'tcx> { pub(crate) fn codegen_and_compile_fn<'tcx>( tcx: TyCtxt<'tcx>, - cx: &mut crate::CodegenCx<'tcx>, + cx: &mut crate::CodegenCx, cached_context: &mut Context, module: &mut dyn Module, instance: Instance<'tcx>, @@ -35,12 +35,12 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(cx, cached_context, module, codegened_func); + compile_fn(tcx, cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( tcx: TyCtxt<'tcx>, - cx: &mut crate::CodegenCx<'tcx>, + cx: &mut crate::CodegenCx, cached_func: Function, module: &mut dyn Module, instance: Instance<'tcx>, @@ -132,7 +132,8 @@ fn codegen_fn<'tcx>( } fn compile_fn<'tcx>( - cx: &mut crate::CodegenCx<'tcx>, + tcx: TyCtxt<'tcx>, + cx: &mut crate::CodegenCx, cached_context: &mut Context, module: &mut dyn Module, codegened_func: CodegenedFunction<'tcx>, @@ -214,6 +215,7 @@ fn compile_fn<'tcx>( cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { debug_context.define_function( + tcx, codegened_func.func_id, codegened_func.symbol_name.name, context, diff --git a/src/common.rs b/src/common.rs index fc4953cea6fe0..1adb64da8bd6a 100644 --- a/src/common.rs +++ b/src/common.rs @@ -232,7 +232,7 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool { } pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { - pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>, + pub(crate) cx: &'clif mut crate::CodegenCx, pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, pub(crate) target_config: TargetFrontendConfig, // Cached from module diff --git a/src/debuginfo/emit.rs b/src/debuginfo/emit.rs index 589910ede9688..9583cd2ec60f8 100644 --- a/src/debuginfo/emit.rs +++ b/src/debuginfo/emit.rs @@ -9,7 +9,7 @@ use gimli::{RunTimeEndian, SectionId}; use super::object::WriteDebugInfo; use super::DebugContext; -impl DebugContext<'_> { +impl DebugContext { pub(crate) fn emit(&mut self, product: &mut ObjectProduct) { let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone()); let root = self.dwarf.unit.root(); diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index bbcb9591373dd..de402a4c713f3 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -96,9 +96,9 @@ fn line_program_add_file( } } -impl<'tcx> DebugContext<'tcx> { - pub(super) fn emit_location(&mut self, entry_id: UnitEntryId, span: Span) { - let loc = self.tcx.sess.source_map().lookup_char_pos(span.lo()); +impl DebugContext { + fn emit_location(&mut self, tcx: TyCtxt<'_>, entry_id: UnitEntryId, span: Span) { + let loc = tcx.sess.source_map().lookup_char_pos(span.lo()); let file_id = line_program_add_file( &mut self.dwarf.unit.line_program, @@ -115,13 +115,13 @@ impl<'tcx> DebugContext<'tcx> { pub(super) fn create_debug_lines( &mut self, + tcx: TyCtxt<'_>, symbol: usize, entry_id: UnitEntryId, context: &Context, function_span: Span, source_info_set: &indexmap::IndexSet, ) -> CodeOffset { - let tcx = self.tcx; let line_program = &mut self.dwarf.unit.line_program; let line_strings = &mut self.dwarf.line_strings; @@ -211,7 +211,7 @@ impl<'tcx> DebugContext<'tcx> { ); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end))); - self.emit_location(entry_id, function_span); + self.emit_location(tcx, entry_id, function_span); func_end } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 9a0787508b751..3e42905c84069 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -16,17 +16,15 @@ use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; -pub(crate) struct DebugContext<'tcx> { - tcx: TyCtxt<'tcx>, - +pub(crate) struct DebugContext { endian: RunTimeEndian, dwarf: DwarfUnit, unit_range_list: RangeList, } -impl<'tcx> DebugContext<'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self { +impl DebugContext { + pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa) -> Self { let encoding = Encoding { format: Format::Dwarf32, // FIXME this should be configurable @@ -92,11 +90,12 @@ impl<'tcx> DebugContext<'tcx> { root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0))); } - DebugContext { tcx, endian, dwarf, unit_range_list: RangeList(Vec::new()) } + DebugContext { endian, dwarf, unit_range_list: RangeList(Vec::new()) } } pub(crate) fn define_function( &mut self, + tcx: TyCtxt<'_>, func_id: FuncId, name: &str, context: &Context, @@ -116,7 +115,7 @@ impl<'tcx> DebugContext<'tcx> { entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id)); let end = - self.create_debug_lines(symbol, entry_id, context, function_span, source_info_set); + self.create_debug_lines(tcx, symbol, entry_id, context, function_span, source_info_set); self.unit_range_list.0.push(Range::StartLength { begin: Address::Symbol { symbol, addend: 0 }, diff --git a/src/driver/aot.rs b/src/driver/aot.rs index b2ad3cc4c4cde..971e5eeea8731 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -120,7 +120,7 @@ fn emit_cgu( prof: &SelfProfilerRef, name: String, module: ObjectModule, - debug: Option>, + debug: Option, unwind_context: UnwindContext, global_asm_object_file: Option, ) -> Result { diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 00e7263446b7c..0e77e4004c0bb 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -61,11 +61,11 @@ impl UnsafeMessage { } } -fn create_jit_module<'tcx>( - tcx: TyCtxt<'tcx>, +fn create_jit_module( + tcx: TyCtxt<'_>, backend_config: &BackendConfig, hotswap: bool, -) -> (JITModule, CodegenCx<'tcx>) { +) -> (JITModule, CodegenCx) { let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string()); let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info); @@ -353,7 +353,7 @@ fn load_imported_symbols_for_jit( fn codegen_shim<'tcx>( tcx: TyCtxt<'tcx>, - cx: &mut CodegenCx<'tcx>, + cx: &mut CodegenCx, cached_context: &mut Context, module: &mut JITModule, inst: Instance<'tcx>, diff --git a/src/lib.rs b/src/lib.rs index f4ffbbcf86ece..40dab58523c20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,20 +122,20 @@ impl String> Drop for PrintOnPanic { /// The codegen context holds any information shared between the codegen of individual functions /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). -struct CodegenCx<'tcx> { +struct CodegenCx { profiler: SelfProfilerRef, output_filenames: Arc, should_write_ir: bool, global_asm: String, inline_asm_index: Cell, - debug_context: Option>, + debug_context: Option, unwind_context: UnwindContext, cgu_name: Symbol, } -impl<'tcx> CodegenCx<'tcx> { +impl CodegenCx { fn new( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, backend_config: BackendConfig, isa: &dyn TargetIsa, debug_info: bool, From 312563f3c46c52e60afd499788b4950248e2c8d4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:57:21 +0000 Subject: [PATCH 077/100] Use walk_chain for function span too This is a correctness fix --- src/debuginfo/line_info.rs | 85 ++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index de402a4c713f3..eb1365167717f 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -5,6 +5,7 @@ use std::path::{Component, Path}; use crate::prelude::*; +use rustc_data_structures::sync::Lrc; use rustc_span::{ FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm, }; @@ -47,9 +48,33 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] { } } -pub(crate) const MD5_LEN: usize = 16; +fn get_span_loc(tcx: TyCtxt<'_>, function_span: Span, span: Span) -> (Lrc, u64, u64) { + // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131 + // In order to have a good line stepping behavior in debugger, we overwrite debug + // locations of macro expansions with that of the outermost expansion site + // (unless the crate is being compiled with `-Z debug-macros`). + let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros { + span + } else { + // Walk up the macro expansion chain until we reach a non-expanded span. + // We also stop at the function body level because no line stepping can occur + // at the level above that. + rustc_span::hygiene::walk_chain(span, function_span.ctxt()) + }; + + match tcx.sess.source_map().lookup_line(span.lo()) { + Ok(SourceFileAndLine { sf: file, line }) => { + let line_pos = file.line_begin_pos(span.lo()); + + (file, u64::try_from(line).unwrap() + 1, u64::from((span.lo() - line_pos).to_u32()) + 1) + } + Err(file) => (file, 0, 0), + } +} + +const MD5_LEN: usize = 16; -pub(crate) fn make_file_info(hash: SourceFileHash) -> Option { +fn make_file_info(hash: SourceFileHash) -> Option { if hash.kind == SourceFileHashAlgorithm::Md5 { let mut buf = [0u8; MD5_LEN]; buf.copy_from_slice(hash.hash_bytes()); @@ -97,22 +122,6 @@ fn line_program_add_file( } impl DebugContext { - fn emit_location(&mut self, tcx: TyCtxt<'_>, entry_id: UnitEntryId, span: Span) { - let loc = tcx.sess.source_map().lookup_char_pos(span.lo()); - - let file_id = line_program_add_file( - &mut self.dwarf.unit.line_program, - &mut self.dwarf.line_strings, - &loc.file, - ); - - let entry = self.dwarf.unit.get_mut(entry_id); - - entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); - entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(loc.line as u64)); - entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(loc.col.to_usize() as u64)); - } - pub(super) fn create_debug_lines( &mut self, tcx: TyCtxt<'_>, @@ -136,31 +145,7 @@ impl DebugContext { } last_span = Some(span); - // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131 - // In order to have a good line stepping behavior in debugger, we overwrite debug - // locations of macro expansions with that of the outermost expansion site - // (unless the crate is being compiled with `-Z debug-macros`). - let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros { - span - } else { - // Walk up the macro expansion chain until we reach a non-expanded span. - // We also stop at the function body level because no line stepping can occur - // at the level above that. - rustc_span::hygiene::walk_chain(span, function_span.ctxt()) - }; - - let (file, line, col) = match tcx.sess.source_map().lookup_line(span.lo()) { - Ok(SourceFileAndLine { sf: file, line }) => { - let line_pos = file.line_begin_pos(span.lo()); - - ( - file, - u64::try_from(line).unwrap() + 1, - u64::from((span.lo() - line_pos).to_u32()) + 1, - ) - } - Err(file) => (file, 0, 0), - }; + let (file, line, col) = get_span_loc(tcx, function_span, span); // line_program_add_file is very slow. // Optimize for the common case of the current file not being changed. @@ -204,14 +189,24 @@ impl DebugContext { assert_ne!(func_end, 0); + let (function_file, function_line, function_col) = + get_span_loc(tcx, function_span, function_span); + + let function_file_id = line_program_add_file( + &mut self.dwarf.unit.line_program, + &mut self.dwarf.line_strings, + &function_file, + ); + let entry = self.dwarf.unit.get_mut(entry_id); entry.set( gimli::DW_AT_low_pc, AttributeValue::Address(Address::Symbol { symbol, addend: 0 }), ); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end))); - - self.emit_location(tcx, entry_id, function_span); + entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(function_file_id))); + entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(function_line)); + entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(function_col)); func_end } From dbf545730849375ce43f593432f2bff5eddd3eec Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:11:41 +0000 Subject: [PATCH 078/100] Introduce FunctionDebugContext This will make it easier to move TyCtxt requiring operations before clif ir compilation. --- src/base.rs | 4 ++-- src/debuginfo/mod.rs | 50 ++++++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/base.rs b/src/base.rs index b2026f30d17a4..73af2ea33be3a 100644 --- a/src/base.rs +++ b/src/base.rs @@ -214,10 +214,10 @@ fn compile_fn<'tcx>( let unwind_context = &mut cx.unwind_context; cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { - debug_context.define_function( + debug_context.define_function(codegened_func.symbol_name.name).finalize( + debug_context, tcx, codegened_func.func_id, - codegened_func.symbol_name.name, context, codegened_func.function_span, &codegened_func.source_info_set, diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 3e42905c84069..0726807000da6 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -10,7 +10,9 @@ use crate::prelude::*; use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::TargetIsa; -use gimli::write::{Address, AttributeValue, DwarfUnit, LineProgram, LineString, Range, RangeList}; +use gimli::write::{ + Address, AttributeValue, DwarfUnit, LineProgram, LineString, Range, RangeList, UnitEntryId, +}; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; pub(crate) use emit::{DebugReloc, DebugRelocName}; @@ -23,6 +25,10 @@ pub(crate) struct DebugContext { unit_range_list: RangeList, } +pub(crate) struct FunctionDebugContext { + entry_id: UnitEntryId, +} + impl DebugContext { pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa) -> Self { let encoding = Encoding { @@ -93,17 +99,7 @@ impl DebugContext { DebugContext { endian, dwarf, unit_range_list: RangeList(Vec::new()) } } - pub(crate) fn define_function( - &mut self, - tcx: TyCtxt<'_>, - func_id: FuncId, - name: &str, - context: &Context, - function_span: Span, - source_info_set: &indexmap::IndexSet, - ) { - let symbol = func_id.as_u32() as usize; - + pub(crate) fn define_function(&mut self, name: &str) -> FunctionDebugContext { // FIXME: add to appropriate scope instead of root let scope = self.dwarf.unit.root(); @@ -114,15 +110,37 @@ impl DebugContext { entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id)); entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id)); - let end = - self.create_debug_lines(tcx, symbol, entry_id, context, function_span, source_info_set); + FunctionDebugContext { entry_id } + } +} + +impl FunctionDebugContext { + pub(crate) fn finalize( + self, + debug_context: &mut DebugContext, + tcx: TyCtxt<'_>, + func_id: FuncId, + context: &Context, + function_span: Span, + source_info_set: &indexmap::IndexSet, + ) { + let symbol = func_id.as_u32() as usize; + + let end = debug_context.create_debug_lines( + tcx, + symbol, + self.entry_id, + context, + function_span, + source_info_set, + ); - self.unit_range_list.0.push(Range::StartLength { + debug_context.unit_range_list.0.push(Range::StartLength { begin: Address::Symbol { symbol, addend: 0 }, length: u64::from(end), }); - let func_entry = self.dwarf.unit.get_mut(entry_id); + let func_entry = debug_context.dwarf.unit.get_mut(self.entry_id); // Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped. func_entry.set( gimli::DW_AT_low_pc, From 01be0ddacfa84559947d024c6060a99c63c48e29 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:17:33 +0000 Subject: [PATCH 079/100] Move FunctionDebugContext creation to codegen_fn --- src/base.rs | 22 ++++++++++++++++++++-- src/common.rs | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index 73af2ea33be3a..34dbf96be7ddb 100644 --- a/src/base.rs +++ b/src/base.rs @@ -10,6 +10,7 @@ use rustc_middle::ty::SymbolName; use indexmap::IndexSet; use crate::constant::ConstantCx; +use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; use crate::pretty_clif::CommentWriter; @@ -18,6 +19,7 @@ struct CodegenedFunction<'tcx> { func_id: FuncId, func: Function, clif_comments: CommentWriter, + func_debug_cx: Option, function_span: Span, source_info_set: IndexSet, } @@ -82,6 +84,12 @@ fn codegen_fn<'tcx>( let pointer_type = target_config.pointer_type(); let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); + let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context { + Some(debug_context.define_function(symbol_name.name)) + } else { + None + }; + let mut fx = FunctionCx { cx, module, @@ -89,6 +97,7 @@ fn codegen_fn<'tcx>( target_config, pointer_type, constants_cx: ConstantCx::new(), + func_debug_cx, instance, symbol_name, @@ -109,6 +118,7 @@ fn codegen_fn<'tcx>( // Recover all necessary data from fx, before accessing func will prevent future access to it. let clif_comments = fx.clif_comments; + let func_debug_cx = fx.func_debug_cx; let function_span = fx.mir.span; let source_info_set = fx.source_info_set; @@ -128,7 +138,15 @@ fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - CodegenedFunction { symbol_name, func_id, func, clif_comments, function_span, source_info_set } + CodegenedFunction { + symbol_name, + func_id, + func, + clif_comments, + func_debug_cx, + function_span, + source_info_set, + } } fn compile_fn<'tcx>( @@ -214,7 +232,7 @@ fn compile_fn<'tcx>( let unwind_context = &mut cx.unwind_context; cx.profiler.verbose_generic_activity("generate debug info").run(|| { if let Some(debug_context) = debug_context { - debug_context.define_function(codegened_func.symbol_name.name).finalize( + codegened_func.func_debug_cx.unwrap().finalize( debug_context, tcx, codegened_func.func_id, diff --git a/src/common.rs b/src/common.rs index 1adb64da8bd6a..655ceacf72982 100644 --- a/src/common.rs +++ b/src/common.rs @@ -9,6 +9,7 @@ use rustc_target::abi::{Integer, Primitive}; use rustc_target::spec::{HasTargetSpec, Target}; use crate::constant::ConstantCx; +use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type { @@ -238,6 +239,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) target_config: TargetFrontendConfig, // Cached from module pub(crate) pointer_type: Type, // Cached from module pub(crate) constants_cx: ConstantCx, + pub(crate) func_debug_cx: Option, pub(crate) instance: Instance<'tcx>, pub(crate) symbol_name: SymbolName<'tcx>, From 1e57774011ab634a04c0efd3bf2e956ee8997245 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:23:36 +0000 Subject: [PATCH 080/100] Move set_function_span earlier --- src/base.rs | 2 +- src/debuginfo/line_info.rs | 44 ++++++++++++++++++++++---------------- src/debuginfo/mod.rs | 19 +++++++++++----- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/base.rs b/src/base.rs index 34dbf96be7ddb..8440a03335a42 100644 --- a/src/base.rs +++ b/src/base.rs @@ -85,7 +85,7 @@ fn codegen_fn<'tcx>( let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context { - Some(debug_context.define_function(symbol_name.name)) + Some(debug_context.define_function(tcx, symbol_name.name, mir.span)) } else { None }; diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index eb1365167717f..5a13b9681c0fc 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -3,6 +3,7 @@ use std::ffi::OsStr; use std::path::{Component, Path}; +use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; use rustc_data_structures::sync::Lrc; @@ -15,7 +16,6 @@ use cranelift_codegen::MachSrcLoc; use gimli::write::{ Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable, - UnitEntryId, }; // OPTIMIZATION: It is cheaper to do this in one pass than using `.parent()` and `.file_name()`. @@ -121,19 +121,39 @@ fn line_program_add_file( } } -impl DebugContext { +impl FunctionDebugContext { + pub(super) fn set_function_span( + &mut self, + debug_context: &mut DebugContext, + tcx: TyCtxt<'_>, + span: Span, + ) { + let (file, line, column) = get_span_loc(tcx, span, span); + + let file_id = line_program_add_file( + &mut debug_context.dwarf.unit.line_program, + &mut debug_context.dwarf.line_strings, + &file, + ); + + let entry = debug_context.dwarf.unit.get_mut(self.entry_id); + entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); + entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line)); + entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column)); + } + pub(super) fn create_debug_lines( &mut self, + debug_context: &mut DebugContext, tcx: TyCtxt<'_>, symbol: usize, - entry_id: UnitEntryId, context: &Context, function_span: Span, source_info_set: &indexmap::IndexSet, ) -> CodeOffset { - let line_program = &mut self.dwarf.unit.line_program; + let line_program = &mut debug_context.dwarf.unit.line_program; - let line_strings = &mut self.dwarf.line_strings; + let line_strings = &mut debug_context.dwarf.line_strings; let mut last_span = None; let mut last_file = None; let mut create_row_for_span = |line_program: &mut LineProgram, span: Span| { @@ -189,24 +209,12 @@ impl DebugContext { assert_ne!(func_end, 0); - let (function_file, function_line, function_col) = - get_span_loc(tcx, function_span, function_span); - - let function_file_id = line_program_add_file( - &mut self.dwarf.unit.line_program, - &mut self.dwarf.line_strings, - &function_file, - ); - - let entry = self.dwarf.unit.get_mut(entry_id); + let entry = debug_context.dwarf.unit.get_mut(self.entry_id); entry.set( gimli::DW_AT_low_pc, AttributeValue::Address(Address::Symbol { symbol, addend: 0 }), ); entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end))); - entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(function_file_id))); - entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(function_line)); - entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(function_col)); func_end } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 0726807000da6..169b7d1ef4c0e 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -99,7 +99,12 @@ impl DebugContext { DebugContext { endian, dwarf, unit_range_list: RangeList(Vec::new()) } } - pub(crate) fn define_function(&mut self, name: &str) -> FunctionDebugContext { + pub(crate) fn define_function( + &mut self, + tcx: TyCtxt<'_>, + name: &str, + function_span: Span, + ) -> FunctionDebugContext { // FIXME: add to appropriate scope instead of root let scope = self.dwarf.unit.root(); @@ -110,13 +115,17 @@ impl DebugContext { entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id)); entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id)); - FunctionDebugContext { entry_id } + let mut function_debug_context = FunctionDebugContext { entry_id }; + + function_debug_context.set_function_span(self, tcx, function_span); + + function_debug_context } } impl FunctionDebugContext { pub(crate) fn finalize( - self, + mut self, debug_context: &mut DebugContext, tcx: TyCtxt<'_>, func_id: FuncId, @@ -126,10 +135,10 @@ impl FunctionDebugContext { ) { let symbol = func_id.as_u32() as usize; - let end = debug_context.create_debug_lines( + let end = self.create_debug_lines( + debug_context, tcx, symbol, - self.entry_id, context, function_span, source_info_set, From 0534a555ccb1a62c2f379bbd2e8cd323e6652e31 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:48:22 +0000 Subject: [PATCH 081/100] Make line_program_add_file a DebugContext method --- src/debuginfo/line_info.rs | 105 ++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 5a13b9681c0fc..4fdaaf4ffe0a0 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -84,39 +84,41 @@ fn make_file_info(hash: SourceFileHash) -> Option { } } -fn line_program_add_file( - line_program: &mut LineProgram, - line_strings: &mut LineStringTable, - file: &SourceFile, -) -> FileId { - match &file.name { - FileName::Real(path) => { - let (dir_path, file_name) = split_path_dir_and_file(path.remapped_path_if_available()); - let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str()); - let file_name = osstr_as_utf8_bytes(file_name); - - let dir_id = if !dir_name.is_empty() { - let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings); - line_program.add_directory(dir_name) - } else { - line_program.default_directory() - }; - let file_name = LineString::new(file_name, line_program.encoding(), line_strings); - - let info = make_file_info(file.src_hash); - - line_program.file_has_md5 &= info.is_some(); - line_program.add_file(file_name, dir_id, info) - } - // FIXME give more appropriate file names - filename => { - let dir_id = line_program.default_directory(); - let dummy_file_name = LineString::new( - filename.prefer_remapped().to_string().into_bytes(), - line_program.encoding(), - line_strings, - ); - line_program.add_file(dummy_file_name, dir_id, None) +impl DebugContext { + pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId { + let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program; + let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings; + + match &source_file.name { + FileName::Real(path) => { + let (dir_path, file_name) = + split_path_dir_and_file(path.remapped_path_if_available()); + let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str()); + let file_name = osstr_as_utf8_bytes(file_name); + + let dir_id = if !dir_name.is_empty() { + let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings); + line_program.add_directory(dir_name) + } else { + line_program.default_directory() + }; + let file_name = LineString::new(file_name, line_program.encoding(), line_strings); + + let info = make_file_info(source_file.src_hash); + + line_program.file_has_md5 &= info.is_some(); + line_program.add_file(file_name, dir_id, info) + } + // FIXME give more appropriate file names + filename => { + let dir_id = line_program.default_directory(); + let dummy_file_name = LineString::new( + filename.prefer_remapped().to_string().into_bytes(), + line_program.encoding(), + line_strings, + ); + line_program.add_file(dummy_file_name, dir_id, None) + } } } } @@ -130,11 +132,7 @@ impl FunctionDebugContext { ) { let (file, line, column) = get_span_loc(tcx, span, span); - let file_id = line_program_add_file( - &mut debug_context.dwarf.unit.line_program, - &mut debug_context.dwarf.line_strings, - &file, - ); + let file_id = debug_context.add_source_file(&file); let entry = debug_context.dwarf.unit.get_mut(self.entry_id); entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); @@ -151,15 +149,12 @@ impl FunctionDebugContext { function_span: Span, source_info_set: &indexmap::IndexSet, ) -> CodeOffset { - let line_program = &mut debug_context.dwarf.unit.line_program; - - let line_strings = &mut debug_context.dwarf.line_strings; let mut last_span = None; let mut last_file = None; - let mut create_row_for_span = |line_program: &mut LineProgram, span: Span| { + let mut create_row_for_span = |debug_context: &mut DebugContext, span: Span| { if let Some(last_span) = last_span { if span == last_span { - line_program.generate_row(); + debug_context.dwarf.unit.line_program.generate_row(); return; } } @@ -177,33 +172,37 @@ impl FunctionDebugContext { true }; if current_file_changed { - let file_id = line_program_add_file(line_program, line_strings, &file); - line_program.row().file = file_id; + let file_id = debug_context.add_source_file(&file); + debug_context.dwarf.unit.line_program.row().file = file_id; last_file = Some(file); } - line_program.row().line = line; - line_program.row().column = col; - line_program.generate_row(); + debug_context.dwarf.unit.line_program.row().line = line; + debug_context.dwarf.unit.line_program.row().column = col; + debug_context.dwarf.unit.line_program.generate_row(); }; - line_program.begin_sequence(Some(Address::Symbol { symbol, addend: 0 })); + debug_context + .dwarf + .unit + .line_program + .begin_sequence(Some(Address::Symbol { symbol, addend: 0 })); let mut func_end = 0; let mcr = context.mach_compile_result.as_ref().unwrap(); for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() { - line_program.row().address_offset = u64::from(start); + debug_context.dwarf.unit.line_program.row().address_offset = u64::from(start); if !loc.is_default() { let source_info = *source_info_set.get_index(loc.bits() as usize).unwrap(); - create_row_for_span(line_program, source_info.span); + create_row_for_span(debug_context, source_info.span); } else { - create_row_for_span(line_program, function_span); + create_row_for_span(debug_context, function_span); } func_end = end; } - line_program.end_sequence(u64::from(func_end)); + debug_context.dwarf.unit.line_program.end_sequence(u64::from(func_end)); let func_end = mcr.buffer.total_size(); From 6421427b74f87ae463a623edd684c34b50790bb2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 18:19:40 +0000 Subject: [PATCH 082/100] Move Span lowering from debuginfo finalization to codegen This removes the dependency on TyCtxt from the debuginfo finalization code. --- src/base.rs | 24 +------- src/common.rs | 37 +++++++++++- src/debuginfo/line_info.rs | 119 ++++++++++++++----------------------- src/debuginfo/mod.rs | 34 ++++++----- 4 files changed, 100 insertions(+), 114 deletions(-) diff --git a/src/base.rs b/src/base.rs index 8440a03335a42..5f6d9f374fddf 100644 --- a/src/base.rs +++ b/src/base.rs @@ -7,8 +7,6 @@ use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::SymbolName; -use indexmap::IndexSet; - use crate::constant::ConstantCx; use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; @@ -20,8 +18,6 @@ struct CodegenedFunction<'tcx> { func: Function, clif_comments: CommentWriter, func_debug_cx: Option, - function_span: Span, - source_info_set: IndexSet, } pub(crate) fn codegen_and_compile_fn<'tcx>( @@ -37,7 +33,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( let cached_func = std::mem::replace(&mut cached_context.func, Function::new()); let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance); - compile_fn(tcx, cx, cached_context, module, codegened_func); + compile_fn(cx, cached_context, module, codegened_func); } fn codegen_fn<'tcx>( @@ -110,7 +106,7 @@ fn codegen_fn<'tcx>( caller_location: None, // set by `codegen_fn_prelude` clif_comments, - source_info_set: indexmap::IndexSet::new(), + last_source_file: None, next_ssa_var: 0, }; @@ -119,8 +115,6 @@ fn codegen_fn<'tcx>( // Recover all necessary data from fx, before accessing func will prevent future access to it. let clif_comments = fx.clif_comments; let func_debug_cx = fx.func_debug_cx; - let function_span = fx.mir.span; - let source_info_set = fx.source_info_set; fx.constants_cx.finalize(fx.tcx, &mut *fx.module); @@ -138,19 +132,10 @@ fn codegen_fn<'tcx>( // Verify function verify_func(tcx, &clif_comments, &func); - CodegenedFunction { - symbol_name, - func_id, - func, - clif_comments, - func_debug_cx, - function_span, - source_info_set, - } + CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx } } fn compile_fn<'tcx>( - tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx, cached_context: &mut Context, module: &mut dyn Module, @@ -234,11 +219,8 @@ fn compile_fn<'tcx>( if let Some(debug_context) = debug_context { codegened_func.func_debug_cx.unwrap().finalize( debug_context, - tcx, codegened_func.func_id, context, - codegened_func.function_span, - &codegened_func.source_info_set, ); } unwind_context.add_function(codegened_func.func_id, &context, isa); diff --git a/src/common.rs b/src/common.rs index 655ceacf72982..4a80b79a9dc1b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,9 +1,13 @@ use cranelift_codegen::isa::TargetFrontendConfig; +use gimli::write::FileId; + +use rustc_data_structures::sync::Lrc; use rustc_index::vec::IndexVec; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, }; use rustc_middle::ty::SymbolName; +use rustc_span::SourceFile; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Integer, Primitive}; use rustc_target::spec::{HasTargetSpec, Target}; @@ -254,7 +258,11 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) caller_location: Option>, pub(crate) clif_comments: crate::pretty_clif::CommentWriter, - pub(crate) source_info_set: indexmap::IndexSet, + + /// Last accessed source file and it's debuginfo file id. + /// + /// For optimization purposes only + pub(crate) last_source_file: Option<(Lrc, FileId)>, /// This should only be accessed by `CPlace::new_var`. pub(crate) next_ssa_var: u32, @@ -338,8 +346,31 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) { - let (index, _) = self.source_info_set.insert_full(source_info); - self.bcx.set_srcloc(SourceLoc::new(index as u32)); + if let Some(debug_context) = &mut self.cx.debug_context { + let (file, line, column) = + DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span); + + // add_source_file is very slow. + // Optimize for the common case of the current file not being changed. + let mut cached_file_id = None; + if let Some((ref last_source_file, last_file_id)) = self.last_source_file { + // If the allocations are not equal, the files may still be equal, but that + // doesn't matter, as this is just an optimization. + if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) { + cached_file_id = Some(last_file_id); + } + } + + let file_id = if let Some(file_id) = cached_file_id { + file_id + } else { + debug_context.add_source_file(&file) + }; + + let source_loc = + self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column); + self.bcx.set_srcloc(source_loc); + } } // Note: must be kept in sync with get_caller_location from cg_ssa diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 4fdaaf4ffe0a0..ff6a21eef0d12 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -48,30 +48,6 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] { } } -fn get_span_loc(tcx: TyCtxt<'_>, function_span: Span, span: Span) -> (Lrc, u64, u64) { - // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131 - // In order to have a good line stepping behavior in debugger, we overwrite debug - // locations of macro expansions with that of the outermost expansion site - // (unless the crate is being compiled with `-Z debug-macros`). - let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros { - span - } else { - // Walk up the macro expansion chain until we reach a non-expanded span. - // We also stop at the function body level because no line stepping can occur - // at the level above that. - rustc_span::hygiene::walk_chain(span, function_span.ctxt()) - }; - - match tcx.sess.source_map().lookup_line(span.lo()) { - Ok(SourceFileAndLine { sf: file, line }) => { - let line_pos = file.line_begin_pos(span.lo()); - - (file, u64::try_from(line).unwrap() + 1, u64::from((span.lo() - line_pos).to_u32()) + 1) - } - Err(file) => (file, 0, 0), - } -} - const MD5_LEN: usize = 16; fn make_file_info(hash: SourceFileHash) -> Option { @@ -85,6 +61,38 @@ fn make_file_info(hash: SourceFileHash) -> Option { } impl DebugContext { + pub(crate) fn get_span_loc( + tcx: TyCtxt<'_>, + function_span: Span, + span: Span, + ) -> (Lrc, u64, u64) { + // Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131 + // In order to have a good line stepping behavior in debugger, we overwrite debug + // locations of macro expansions with that of the outermost expansion site + // (unless the crate is being compiled with `-Z debug-macros`). + let span = if !span.from_expansion() || tcx.sess.opts.unstable_opts.debug_macros { + span + } else { + // Walk up the macro expansion chain until we reach a non-expanded span. + // We also stop at the function body level because no line stepping can occur + // at the level above that. + rustc_span::hygiene::walk_chain(span, function_span.ctxt()) + }; + + match tcx.sess.source_map().lookup_line(span.lo()) { + Ok(SourceFileAndLine { sf: file, line }) => { + let line_pos = file.line_begin_pos(span.lo()); + + ( + file, + u64::try_from(line).unwrap() + 1, + u64::from((span.lo() - line_pos).to_u32()) + 1, + ) + } + Err(file) => (file, 0, 0), + } + } + pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId { let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program; let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings; @@ -124,63 +132,26 @@ impl DebugContext { } impl FunctionDebugContext { - pub(super) fn set_function_span( - &mut self, - debug_context: &mut DebugContext, - tcx: TyCtxt<'_>, - span: Span, - ) { - let (file, line, column) = get_span_loc(tcx, span, span); - - let file_id = debug_context.add_source_file(&file); - - let entry = debug_context.dwarf.unit.get_mut(self.entry_id); - entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); - entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line)); - entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column)); + pub(crate) fn add_dbg_loc(&mut self, file_id: FileId, line: u64, column: u64) -> SourceLoc { + let (index, _) = self.source_loc_set.insert_full((file_id, line, column)); + SourceLoc::new(u32::try_from(index).unwrap()) } pub(super) fn create_debug_lines( &mut self, debug_context: &mut DebugContext, - tcx: TyCtxt<'_>, symbol: usize, context: &Context, - function_span: Span, - source_info_set: &indexmap::IndexSet, ) -> CodeOffset { - let mut last_span = None; - let mut last_file = None; - let mut create_row_for_span = |debug_context: &mut DebugContext, span: Span| { - if let Some(last_span) = last_span { - if span == last_span { - debug_context.dwarf.unit.line_program.generate_row(); - return; - } - } - last_span = Some(span); - - let (file, line, col) = get_span_loc(tcx, function_span, span); + let create_row_for_span = + |debug_context: &mut DebugContext, source_loc: (FileId, u64, u64)| { + let (file_id, line, col) = source_loc; - // line_program_add_file is very slow. - // Optimize for the common case of the current file not being changed. - let current_file_changed = if let Some(last_file) = &last_file { - // If the allocations are not equal, then the files may still be equal, but that - // is not a problem, as this is just an optimization. - !rustc_data_structures::sync::Lrc::ptr_eq(last_file, &file) - } else { - true - }; - if current_file_changed { - let file_id = debug_context.add_source_file(&file); debug_context.dwarf.unit.line_program.row().file = file_id; - last_file = Some(file); - } - - debug_context.dwarf.unit.line_program.row().line = line; - debug_context.dwarf.unit.line_program.row().column = col; - debug_context.dwarf.unit.line_program.generate_row(); - }; + debug_context.dwarf.unit.line_program.row().line = line; + debug_context.dwarf.unit.line_program.row().column = col; + debug_context.dwarf.unit.line_program.generate_row(); + }; debug_context .dwarf @@ -194,10 +165,10 @@ impl FunctionDebugContext { for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() { debug_context.dwarf.unit.line_program.row().address_offset = u64::from(start); if !loc.is_default() { - let source_info = *source_info_set.get_index(loc.bits() as usize).unwrap(); - create_row_for_span(debug_context, source_info.span); + let source_loc = *self.source_loc_set.get_index(loc.bits() as usize).unwrap(); + create_row_for_span(debug_context, source_loc); } else { - create_row_for_span(debug_context, function_span); + create_row_for_span(debug_context, self.function_source_loc); } func_end = end; } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 169b7d1ef4c0e..c55db2017ee68 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -11,9 +11,11 @@ use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::TargetIsa; use gimli::write::{ - Address, AttributeValue, DwarfUnit, LineProgram, LineString, Range, RangeList, UnitEntryId, + Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList, + UnitEntryId, }; use gimli::{Encoding, Format, LineEncoding, RunTimeEndian}; +use indexmap::IndexSet; pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; @@ -27,6 +29,8 @@ pub(crate) struct DebugContext { pub(crate) struct FunctionDebugContext { entry_id: UnitEntryId, + function_source_loc: (FileId, u64, u64), + source_loc_set: indexmap::IndexSet<(FileId, u64, u64)>, } impl DebugContext { @@ -105,6 +109,10 @@ impl DebugContext { name: &str, function_span: Span, ) -> FunctionDebugContext { + let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span); + + let file_id = self.add_source_file(&file); + // FIXME: add to appropriate scope instead of root let scope = self.dwarf.unit.root(); @@ -115,11 +123,15 @@ impl DebugContext { entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id)); entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id)); - let mut function_debug_context = FunctionDebugContext { entry_id }; + entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id))); + entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line)); + entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column)); - function_debug_context.set_function_span(self, tcx, function_span); - - function_debug_context + FunctionDebugContext { + entry_id, + function_source_loc: (file_id, line, column), + source_loc_set: IndexSet::new(), + } } } @@ -127,22 +139,12 @@ impl FunctionDebugContext { pub(crate) fn finalize( mut self, debug_context: &mut DebugContext, - tcx: TyCtxt<'_>, func_id: FuncId, context: &Context, - function_span: Span, - source_info_set: &indexmap::IndexSet, ) { let symbol = func_id.as_u32() as usize; - let end = self.create_debug_lines( - debug_context, - tcx, - symbol, - context, - function_span, - source_info_set, - ); + let end = self.create_debug_lines(debug_context, symbol, context); debug_context.unit_range_list.0.push(Range::StartLength { begin: Address::Symbol { symbol, addend: 0 }, From 535c6ddc8bf66d8997c9a89ce457974e2c2c11ec Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 18 Aug 2022 18:59:14 +0000 Subject: [PATCH 083/100] Small cleanup --- src/driver/aot.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 971e5eeea8731..3220d16f72539 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -280,25 +280,20 @@ fn module_codegen( cgu.is_primary(), ); - let global_asm_object_file = match crate::global_asm::compile_global_asm( + let global_asm_object_file = crate::global_asm::compile_global_asm( &global_asm_config, cgu.name().as_str(), &cx.global_asm, - ) { - Ok(global_asm_object_file) => global_asm_object_file, - Err(err) => tcx.sess.fatal(&err), - }; + )?; - let debug_context = cx.debug_context; - let unwind_context = cx.unwind_context; tcx.sess.time("write object file", || { emit_cgu( &global_asm_config.output_filenames, - &tcx.sess.prof, + &cx.profiler, cgu.name().as_str().to_string(), module, - debug_context, - unwind_context, + cx.debug_context, + cx.unwind_context, global_asm_object_file, ) }) From bd1ab724064f2bcc59ddc6157d6cae9ca344939b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 19 Aug 2022 13:33:06 +0400 Subject: [PATCH 084/100] Replace most uses of `pointer::offset` with `add` and `sub` --- example/alloc_system.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/alloc_system.rs b/example/alloc_system.rs index cf95c89bc3156..50261c1939739 100644 --- a/example/alloc_system.rs +++ b/example/alloc_system.rs @@ -94,7 +94,7 @@ mod platform { struct Header(*mut u8); const HEAP_ZERO_MEMORY: DWORD = 0x00000008; unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { - &mut *(ptr as *mut Header).offset(-1) + &mut *(ptr as *mut Header).sub(1) } unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { let aligned = ptr.add(align - (ptr as usize & (align - 1))); From b14c7337db5861288afc3b26ba006859ed052d39 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 22 Aug 2022 18:53:10 +0000 Subject: [PATCH 085/100] Update to Cranelift 0.87.0 --- Cargo.lock | 62 +++++++++++++++++--------------------- Cargo.toml | 14 ++++----- src/abi/pass_mode.rs | 2 +- src/base.rs | 2 +- src/debuginfo/line_info.rs | 2 +- src/inline_asm.rs | 2 +- src/value_and_place.rs | 4 +-- 7 files changed, 41 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea7e8f45db378..edae7e471578a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,18 +50,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529ffacce2249ac60edba2941672dfedf3d96558b415d0d8083cd007456e0f55" +checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427d105f617efc8cb55f8d036a7fded2e227892d8780b4985e5551f8d27c4a92" +checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -77,30 +77,30 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551674bed85b838d45358e3eab4f0ffaa6790c70dc08184204b9a54b41cdb7d1" +checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3a63ae57498c3eb495360944a33571754241e15e47e3bcae6082f40fec5866" +checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99" [[package]] name = "cranelift-entity" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11aa8aa624c72cc1c94ea3d0739fa61248260b5b14d3646f51593a88d67f3e6e" +checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5" [[package]] name = "cranelift-frontend" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "544ee8f4d1c9559c9aa6d46e7aaeac4a13856d620561094f35527356c7d21bd0" +checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a" dependencies = [ "cranelift-codegen", "log", @@ -110,15 +110,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed16b14363d929b8c37e3c557d0a7396791b383ecc302141643c054343170aad" +checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e" [[package]] name = "cranelift-jit" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0308e7418208639fb96c1a3dc04955fa41c4bc92dfce9106635185f71d5caf46" +checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029" dependencies = [ "anyhow", "cranelift-codegen", @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76979aac10dbcf0c222cd5902565bc93597ac30bbe9d879a2aa5f2402d1561f2" +checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8" dependencies = [ "anyhow", "cranelift-codegen", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51617cf8744634f2ed3c989c3c40cd6444f63377c6d994adab0d85807f3eb682" +checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd" dependencies = [ "cranelift-codegen", "libc", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.86.1" +version = "0.87.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e649a13f3951ad3b8cb13a3a774481c12159a98eb386b04583573c57d7cf56" +checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816" dependencies = [ "anyhow", "cranelift-codegen", @@ -207,19 +207,13 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "indexmap" version = "1.9.1" @@ -227,7 +221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown", ] [[package]] @@ -272,12 +266,12 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", - "hashbrown 0.11.2", + "hashbrown", "indexmap", "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 3f343a49e0cee..e7c3427485480 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,15 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.86.1", features = ["unwind", "all-arch"] } -cranelift-frontend = "0.86.1" -cranelift-module = "0.86.1" -cranelift-native = "0.86.1" -cranelift-jit = { version = "0.86.1", optional = true } -cranelift-object = "0.86.1" +cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.87.0" +cranelift-module = "0.87.0" +cranelift-native = "0.87.0" +cranelift-jit = { version = "0.87.0", optional = true } +cranelift-object = "0.87.0" target-lexicon = "0.12.0" gimli = { version = "0.26.0", default-features = false, features = ["write"]} -object = { version = "0.28.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.9.1" diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 3192575b8ad4e..f4ad76b3bab3c 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -184,7 +184,7 @@ pub(super) fn from_casted_value<'tcx>( let abi_params = cast_target_to_abi_params(cast); let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); let layout_size = u32::try_from(layout.size.bytes()).unwrap(); - let stack_slot = fx.bcx.create_stack_slot(StackSlotData { + let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. diff --git a/src/base.rs b/src/base.rs index 5f6d9f374fddf..3a4c2b8454958 100644 --- a/src/base.rs +++ b/src/base.rs @@ -202,7 +202,7 @@ fn compile_fn<'tcx>( &clif_comments, ); - if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm { + if let Some(disasm) = &context.compiled_code().unwrap().disasm { crate::pretty_clif::write_ir_file( &cx.output_filenames, &format!("{}.vcode", codegened_func.symbol_name.name), diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index ff6a21eef0d12..3ad0c420eaf0b 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -161,7 +161,7 @@ impl FunctionDebugContext { let mut func_end = 0; - let mcr = context.mach_compile_result.as_ref().unwrap(); + let mcr = context.compiled_code().unwrap(); for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() { debug_context.dwarf.unit.line_program.row().address_offset = u64::from(start); if !loc.is_default() { diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 9221abb822572..8b3d475cb1802 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -733,7 +733,7 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.bcx.func.create_stack_slot(StackSlotData { + let stack_slot = fx.bcx.func.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, size: u32::try_from(slot_size.bytes()).unwrap(), }); diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 9e945d8362162..2ee98546c992a 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -330,7 +330,7 @@ impl<'tcx> CPlace<'tcx> { .fatal(&format!("values of type {} are too big to store on the stack", layout.ty)); } - let stack_slot = fx.bcx.create_stack_slot(StackSlotData { + let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. @@ -472,7 +472,7 @@ impl<'tcx> CPlace<'tcx> { } _ if src_ty.is_vector() || dst_ty.is_vector() => { // FIXME do something more efficient for transmutes between vectors and integers. - let stack_slot = fx.bcx.create_stack_slot(StackSlotData { + let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. From 156bda8bc708cca60e9de18743d833c8d97dd7ff Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 23 Aug 2022 11:42:24 +0100 Subject: [PATCH 086/100] Avoid masking shift amounts (#1268) Cranelift 0.87 now follows its own documentation regarding shift amounts, and implicitly masks them if the arch requires it. [0] [0]: https://github.com/bytecodealliance/wasmtime/commit/05089321740a07757dff0a285176b2651a49aae2 --- src/num.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/num.rs b/src/num.rs index 4ce8adb182e0f..679974710df97 100644 --- a/src/num.rs +++ b/src/num.rs @@ -150,18 +150,12 @@ pub(crate) fn codegen_int_binop<'tcx>( BinOp::BitXor => b.bxor(lhs, rhs), BinOp::BitAnd => b.band(lhs, rhs), BinOp::BitOr => b.bor(lhs, rhs), - BinOp::Shl => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - fx.bcx.ins().ishl(lhs, actual_shift) - } + BinOp::Shl => b.ishl(lhs, rhs), BinOp::Shr => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); if signed { - fx.bcx.ins().sshr(lhs, actual_shift) + b.sshr(lhs, rhs) } else { - fx.bcx.ins().ushr(lhs, actual_shift) + b.ushr(lhs, rhs) } } // Compare binops handles by `codegen_binop`. @@ -279,22 +273,15 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( } } BinOp::Shl => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let val = fx.bcx.ins().ishl(lhs, masked_shift); + let val = fx.bcx.ins().ishl(lhs, rhs); let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); (val, has_overflow) } BinOp::Shr => { - let lhs_ty = fx.bcx.func.dfg.value_type(lhs); - let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); - let val = if !signed { - fx.bcx.ins().ushr(lhs, masked_shift) - } else { - fx.bcx.ins().sshr(lhs, masked_shift) - }; + let val = + if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) }; let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); From 48c45c481c53e615637788e3dad1b7dcb993bdc3 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 23 Aug 2022 11:42:35 +0100 Subject: [PATCH 087/100] Use native scalar `fma` instruction (#1267) Cranelift 0.87 now supports lowering `fma` as a libcall on x86 [0]. With 0.88 enabling the native x86 instruction under the `has_fma` flag. aarch64 and s390x already support this as a native instruction, so it's nice that we emit it for those. We can't lower the SIMD version using the `fma` instruction since the lowering can fail if the x86 `has_fma` flag is not enabled. Cranelift doesn't yet know how to fallback for these cases [0]: https://github.com/bytecodealliance/wasmtime/commit/709716bb8e6adaf7e65f3497168af23ce0cf09ef --- src/intrinsics/mod.rs | 6 ++++++ src/intrinsics/simd.rs | 18 ++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index cb620822f2d61..ef3d5ccea8a24 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -303,6 +303,12 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { + sym::fmaf32 | sym::fmaf64 => { + let a = args[0].load_scalar(fx); + let b = args[1].load_scalar(fx); + let c = args[2].load_scalar(fx); + CValue::by_val(fx.bcx.ins().fma(a, b, c), layout) + } sym::copysignf32 | sym::copysignf64 => { let a = args[0].load_scalar(fx); let b = args[1].load_scalar(fx); diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index c7efdb392b75e..a32b413d45f93 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -397,21 +397,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let layout = a.layout(); let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let res_lane_layout = fx.layout_of(lane_ty); for lane in 0..lane_count { - let a_lane = a.value_lane(fx, lane); - let b_lane = b.value_lane(fx, lane); - let c_lane = c.value_lane(fx, lane); + let a_lane = a.value_lane(fx, lane).load_scalar(fx); + let b_lane = b.value_lane(fx, lane).load_scalar(fx); + let c_lane = c.value_lane(fx, lane).load_scalar(fx); - let res_lane = match lane_ty.kind() { - ty::Float(FloatTy::F32) => { - fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty) - } - ty::Float(FloatTy::F64) => { - fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty) - } - _ => unreachable!(), - }; + let res_lane = fx.bcx.ins().fma(a_lane, b_lane, c_lane); + let res_lane = CValue::by_val(res_lane, res_lane_layout); ret.place_lane(fx, lane).write_cvalue(fx, res_lane); } From b1e9d2e1a21f91fee0013b03555f723358890864 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 11:10:44 +0000 Subject: [PATCH 088/100] Revert "Avoid masking shift amounts (#1268)" This reverts commit 156bda8bc708cca60e9de18743d833c8d97dd7ff. This breaks the mir_overflow_off rustc test: https://github.com/bjorn3/rustc_codegen_cranelift/runs/7971362755?check_suite_focus=true#step:7:2904 --- src/num.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/num.rs b/src/num.rs index 679974710df97..4ce8adb182e0f 100644 --- a/src/num.rs +++ b/src/num.rs @@ -150,12 +150,18 @@ pub(crate) fn codegen_int_binop<'tcx>( BinOp::BitXor => b.bxor(lhs, rhs), BinOp::BitAnd => b.band(lhs, rhs), BinOp::BitOr => b.bor(lhs, rhs), - BinOp::Shl => b.ishl(lhs, rhs), + BinOp::Shl => { + let lhs_ty = fx.bcx.func.dfg.value_type(lhs); + let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); + fx.bcx.ins().ishl(lhs, actual_shift) + } BinOp::Shr => { + let lhs_ty = fx.bcx.func.dfg.value_type(lhs); + let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); if signed { - b.sshr(lhs, rhs) + fx.bcx.ins().sshr(lhs, actual_shift) } else { - b.ushr(lhs, rhs) + fx.bcx.ins().ushr(lhs, actual_shift) } } // Compare binops handles by `codegen_binop`. @@ -273,15 +279,22 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( } } BinOp::Shl => { - let val = fx.bcx.ins().ishl(lhs, rhs); + let lhs_ty = fx.bcx.func.dfg.value_type(lhs); + let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); + let val = fx.bcx.ins().ishl(lhs, masked_shift); let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); (val, has_overflow) } BinOp::Shr => { - let val = - if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) }; + let lhs_ty = fx.bcx.func.dfg.value_type(lhs); + let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); + let val = if !signed { + fx.bcx.ins().ushr(lhs, masked_shift) + } else { + fx.bcx.ins().sshr(lhs, masked_shift) + }; let ty = fx.bcx.func.dfg.value_type(val); let max_shift = i64::from(ty.bits()) - 1; let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift); From 5896e5cdfaab217e7948a3d91a39d2644e866e85 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 19 Aug 2022 10:27:00 +0000 Subject: [PATCH 089/100] Store symbol name as owned string --- src/base.rs | 24 ++++++++++++------------ src/common.rs | 3 +-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/base.rs b/src/base.rs index 3a4c2b8454958..492e488265194 100644 --- a/src/base.rs +++ b/src/base.rs @@ -5,15 +5,14 @@ use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::SymbolName; use crate::constant::ConstantCx; use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; use crate::pretty_clif::CommentWriter; -struct CodegenedFunction<'tcx> { - symbol_name: SymbolName<'tcx>, +struct CodegenedFunction { + symbol_name: String, func_id: FuncId, func: Function, clif_comments: CommentWriter, @@ -42,7 +41,7 @@ fn codegen_fn<'tcx>( cached_func: Function, module: &mut dyn Module, instance: Instance<'tcx>, -) -> CodegenedFunction<'tcx> { +) -> CodegenedFunction { debug_assert!(!instance.substs.needs_infer()); let mir = tcx.instance_mir(instance.def); @@ -56,9 +55,9 @@ fn codegen_fn<'tcx>( }); // Declare function - let symbol_name = tcx.symbol_name(instance); + let symbol_name = tcx.symbol_name(instance).name.to_string(); let sig = get_function_sig(tcx, module.isa().triple(), instance); - let func_id = module.declare_function(symbol_name.name, Linkage::Local, &sig).unwrap(); + let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap(); // Make the FunctionBuilder let mut func_ctx = FunctionBuilderContext::new(); @@ -81,7 +80,7 @@ fn codegen_fn<'tcx>( let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context { - Some(debug_context.define_function(tcx, symbol_name.name, mir.span)) + Some(debug_context.define_function(tcx, &symbol_name, mir.span)) } else { None }; @@ -113,6 +112,7 @@ fn codegen_fn<'tcx>( tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block)); // Recover all necessary data from fx, before accessing func will prevent future access to it. + let symbol_name = fx.symbol_name; let clif_comments = fx.clif_comments; let func_debug_cx = fx.func_debug_cx; @@ -121,7 +121,7 @@ fn codegen_fn<'tcx>( if cx.should_write_ir { crate::pretty_clif::write_clif_file( tcx.output_filenames(()), - symbol_name.name, + &symbol_name, "unopt", module.isa(), &func, @@ -135,11 +135,11 @@ fn codegen_fn<'tcx>( CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx } } -fn compile_fn<'tcx>( +fn compile_fn( cx: &mut crate::CodegenCx, cached_context: &mut Context, module: &mut dyn Module, - codegened_func: CodegenedFunction<'tcx>, + codegened_func: CodegenedFunction, ) { let clif_comments = codegened_func.clif_comments; @@ -195,7 +195,7 @@ fn compile_fn<'tcx>( // Write optimized function to file for debugging crate::pretty_clif::write_clif_file( &cx.output_filenames, - codegened_func.symbol_name.name, + &codegened_func.symbol_name, "opt", module.isa(), &context.func, @@ -205,7 +205,7 @@ fn compile_fn<'tcx>( if let Some(disasm) = &context.compiled_code().unwrap().disasm { crate::pretty_clif::write_ir_file( &cx.output_filenames, - &format!("{}.vcode", codegened_func.symbol_name.name), + &format!("{}.vcode", codegened_func.symbol_name), |file| file.write_all(disasm.as_bytes()), ) } diff --git a/src/common.rs b/src/common.rs index 4a80b79a9dc1b..589594465783e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -6,7 +6,6 @@ use rustc_index::vec::IndexVec; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::SymbolName; use rustc_span::SourceFile; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Integer, Primitive}; @@ -246,7 +245,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) func_debug_cx: Option, pub(crate) instance: Instance<'tcx>, - pub(crate) symbol_name: SymbolName<'tcx>, + pub(crate) symbol_name: String, pub(crate) mir: &'tcx Body<'tcx>, pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>, From 1a0dfb399cb803ca2e36688fb32f8a74bc903d8e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 15:44:39 +0000 Subject: [PATCH 090/100] Add a jobserver based concurrency limiter --- src/concurrency_limiter.rs | 153 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + 2 files changed, 155 insertions(+) create mode 100644 src/concurrency_limiter.rs diff --git a/src/concurrency_limiter.rs b/src/concurrency_limiter.rs new file mode 100644 index 0000000000000..eaf3a61f40394 --- /dev/null +++ b/src/concurrency_limiter.rs @@ -0,0 +1,153 @@ +use std::sync::{Arc, Condvar, Mutex}; + +use rustc_session::Session; + +use jobserver::HelperThread; + +pub(super) struct ConcurrencyLimiter { + helper_thread: Option, + state: Arc>, + available_token_condvar: Arc, +} + +impl ConcurrencyLimiter { + pub(super) fn new(sess: &Session, pending_jobs: usize) -> Self { + let state = Arc::new(Mutex::new(state::ConcurrencyLimiterState::new(pending_jobs))); + let available_token_condvar = Arc::new(Condvar::new()); + + let state_helper = state.clone(); + let available_token_condvar_helper = available_token_condvar.clone(); + let helper_thread = sess + .jobserver + .clone() + .into_helper_thread(move |token| { + let mut state = state_helper.lock().unwrap(); + state.add_new_token(token.unwrap()); + available_token_condvar_helper.notify_one(); + }) + .unwrap(); + ConcurrencyLimiter { + helper_thread: Some(helper_thread), + state, + available_token_condvar: Arc::new(Condvar::new()), + } + } + + pub(super) fn acquire(&mut self) -> ConcurrencyLimiterToken { + let mut state = self.state.lock().unwrap(); + loop { + state.assert_invariants(); + + if state.try_start_job() { + return ConcurrencyLimiterToken { + state: self.state.clone(), + available_token_condvar: self.available_token_condvar.clone(), + }; + } + + self.helper_thread.as_mut().unwrap().request_token(); + state = self.available_token_condvar.wait(state).unwrap(); + } + } +} + +impl Drop for ConcurrencyLimiter { + fn drop(&mut self) { + // + self.helper_thread.take(); + + // Assert that all jobs have finished + let state = Mutex::get_mut(Arc::get_mut(&mut self.state).unwrap()).unwrap(); + state.assert_done(); + } +} + +#[derive(Debug)] +pub(super) struct ConcurrencyLimiterToken { + state: Arc>, + available_token_condvar: Arc, +} + +impl Drop for ConcurrencyLimiterToken { + fn drop(&mut self) { + let mut state = self.state.lock().unwrap(); + state.job_finished(); + self.available_token_condvar.notify_one(); + } +} + +mod state { + use jobserver::Acquired; + + #[derive(Debug)] + pub(super) struct ConcurrencyLimiterState { + pending_jobs: usize, + active_jobs: usize, + + // None is used to represent the implicit token, Some to represent explicit tokens + tokens: Vec>, + } + + impl ConcurrencyLimiterState { + pub(super) fn new(pending_jobs: usize) -> Self { + ConcurrencyLimiterState { pending_jobs, active_jobs: 0, tokens: vec![None] } + } + + pub(super) fn assert_invariants(&self) { + // There must be no excess active jobs + assert!(self.active_jobs <= self.pending_jobs); + + // There may not be more active jobs than there are tokens + assert!(self.active_jobs <= self.tokens.len()); + } + + pub(super) fn assert_done(&self) { + assert_eq!(self.pending_jobs, 0); + assert_eq!(self.active_jobs, 0); + } + + pub(super) fn add_new_token(&mut self, token: Acquired) { + self.tokens.push(Some(token)); + self.drop_excess_capacity(); + } + + pub(super) fn try_start_job(&mut self) -> bool { + if self.active_jobs < self.tokens.len() { + // Using existing token + self.job_started(); + return true; + } + + false + } + + pub(super) fn job_started(&mut self) { + self.assert_invariants(); + self.active_jobs += 1; + self.drop_excess_capacity(); + self.assert_invariants(); + } + + pub(super) fn job_finished(&mut self) { + self.assert_invariants(); + self.pending_jobs -= 1; + self.active_jobs -= 1; + self.assert_invariants(); + self.drop_excess_capacity(); + self.assert_invariants(); + } + + fn drop_excess_capacity(&mut self) { + self.assert_invariants(); + if self.active_jobs == self.pending_jobs { + // Drop all excess tokens + self.tokens.truncate(std::cmp::max(self.active_jobs, 1)); + } else { + // Keep some excess tokens to satisfy requests faster + const MAX_EXTRA_CAPACITY: usize = 2; + self.tokens.truncate(std::cmp::max(self.active_jobs + MAX_EXTRA_CAPACITY, 1)); + } + self.assert_invariants(); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 40dab58523c20..913414e761821 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![warn(unused_lifetimes)] #![warn(unreachable_pub)] +extern crate jobserver; #[macro_use] extern crate rustc_middle; extern crate rustc_ast; @@ -53,6 +54,7 @@ mod cast; mod codegen_i128; mod common; mod compiler_builtins; +mod concurrency_limiter; mod config; mod constant; mod debuginfo; From f9d60cf55154272656bb2bdba8c4fd419ec814e6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 16:05:29 +0000 Subject: [PATCH 091/100] Do asm compilation and object file emission in parallel --- src/driver/aot.rs | 80 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3220d16f72539..224756bc6c712 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -4,6 +4,7 @@ use std::fs::File; use std::path::PathBuf; use std::sync::Arc; +use std::thread::JoinHandle; use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; @@ -18,6 +19,7 @@ use rustc_session::Session; use cranelift_object::{ObjectBuilder, ObjectModule}; +use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken}; use crate::global_asm::GlobalAsmConfig; use crate::{prelude::*, BackendConfig}; @@ -27,18 +29,24 @@ struct ModuleCodegenResult { existing_work_product: Option<(WorkProductId, WorkProduct)>, } -impl HashStable for ModuleCodegenResult { +enum OngoingModuleCodegen { + Sync(Result), + Async(JoinHandle>), +} + +impl HashStable for OngoingModuleCodegen { fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) { // do nothing } } pub(crate) struct OngoingCodegen { - modules: Vec>, + modules: Vec, allocator_module: Option, metadata_module: Option, metadata: EncodedMetadata, crate_info: CrateInfo, + concurrency_limiter: ConcurrencyLimiter, } impl OngoingCodegen { @@ -50,7 +58,15 @@ impl OngoingCodegen { let mut work_products = FxHashMap::default(); let mut modules = vec![]; - for module_codegen_result in self.modules { + for module_codegen in self.modules { + let module_codegen_result = match module_codegen { + OngoingModuleCodegen::Sync(module_codegen_result) => module_codegen_result, + OngoingModuleCodegen::Async(join_handle) => match join_handle.join() { + Ok(module_codegen_result) => module_codegen_result, + Err(panic) => std::panic::resume_unwind(panic), + }, + }; + let module_codegen_result = match module_codegen_result { Ok(module_codegen_result) => module_codegen_result, Err(err) => sess.fatal(&err), @@ -90,6 +106,8 @@ impl OngoingCodegen { } } + drop(self.concurrency_limiter); + ( CodegenResults { modules, @@ -233,12 +251,13 @@ fn reuse_workproduct_for_cgu( fn module_codegen( tcx: TyCtxt<'_>, - (backend_config, global_asm_config, cgu_name): ( + (backend_config, global_asm_config, cgu_name, token): ( BackendConfig, Arc, rustc_span::Symbol, + ConcurrencyLimiterToken, ), -) -> Result { +) -> OngoingModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); let mono_items = cgu.items_in_deterministic_order(tcx); @@ -280,23 +299,26 @@ fn module_codegen( cgu.is_primary(), ); - let global_asm_object_file = crate::global_asm::compile_global_asm( - &global_asm_config, - cgu.name().as_str(), - &cx.global_asm, - )?; - - tcx.sess.time("write object file", || { - emit_cgu( - &global_asm_config.output_filenames, - &cx.profiler, - cgu.name().as_str().to_string(), - module, - cx.debug_context, - cx.unwind_context, - global_asm_object_file, - ) - }) + let cgu_name = cgu.name().as_str().to_owned(); + + OngoingModuleCodegen::Async(std::thread::spawn(move || { + let global_asm_object_file = + crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)?; + + let codegen_result = cx.profiler.verbose_generic_activity("write object file").run(|| { + emit_cgu( + &global_asm_config.output_filenames, + &cx.profiler, + cgu_name, + module, + cx.debug_context, + cx.unwind_context, + global_asm_object_file, + ) + }); + std::mem::drop(token); + codegen_result + })) } pub(crate) fn run_aot( @@ -321,6 +343,8 @@ pub(crate) fn run_aot( let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx)); + let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len()); + let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { cgus.iter() .map(|cgu| { @@ -338,13 +362,20 @@ pub(crate) fn run_aot( .with_task( dep_node, tcx, - (backend_config.clone(), global_asm_config.clone(), cgu.name()), + ( + backend_config.clone(), + global_asm_config.clone(), + cgu.name(), + concurrency_limiter.acquire(), + ), module_codegen, Some(rustc_middle::dep_graph::hash_result), ) .0 } - CguReuse::PreLto => reuse_workproduct_for_cgu(tcx, &*cgu), + CguReuse::PreLto => { + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu)) + } CguReuse::PostLto => unreachable!(), } }) @@ -424,6 +455,7 @@ pub(crate) fn run_aot( metadata_module, metadata, crate_info: CrateInfo::new(tcx, target_cpu), + concurrency_limiter, }) } From 1a6323313b7b33afe7aafa93a689e43a2c4ac768 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 16:06:01 +0000 Subject: [PATCH 092/100] Use correct CguReuse variant --- src/driver/aot.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 224756bc6c712..b8b325be71bcb 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -373,10 +373,10 @@ pub(crate) fn run_aot( ) .0 } - CguReuse::PreLto => { + CguReuse::PreLto => unreachable!(), + CguReuse::PostLto => { OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu)) } - CguReuse::PostLto => unreachable!(), } }) .collect::>() @@ -485,5 +485,5 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR cgu.name() ); - if tcx.try_mark_green(&dep_node) { CguReuse::PreLto } else { CguReuse::No } + if tcx.try_mark_green(&dep_node) { CguReuse::PostLto } else { CguReuse::No } } From d081c20273cfafab0c896f66485495fa906a1f84 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 16:09:08 +0000 Subject: [PATCH 093/100] Compile functions from clif ir to object code in parallel --- src/base.rs | 7 ++++--- src/driver/aot.rs | 17 +++++++++-------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/base.rs b/src/base.rs index 492e488265194..44c34d6c8cb79 100644 --- a/src/base.rs +++ b/src/base.rs @@ -11,7 +11,7 @@ use crate::debuginfo::FunctionDebugContext; use crate::prelude::*; use crate::pretty_clif::CommentWriter; -struct CodegenedFunction { +pub(crate) struct CodegenedFunction { symbol_name: String, func_id: FuncId, func: Function, @@ -19,6 +19,7 @@ struct CodegenedFunction { func_debug_cx: Option, } +#[cfg_attr(not(feature = "jit"), allow(dead_code))] pub(crate) fn codegen_and_compile_fn<'tcx>( tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx, @@ -35,7 +36,7 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( compile_fn(cx, cached_context, module, codegened_func); } -fn codegen_fn<'tcx>( +pub(crate) fn codegen_fn<'tcx>( tcx: TyCtxt<'tcx>, cx: &mut crate::CodegenCx, cached_func: Function, @@ -135,7 +136,7 @@ fn codegen_fn<'tcx>( CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx } } -fn compile_fn( +pub(crate) fn compile_fn( cx: &mut crate::CodegenCx, cached_context: &mut Context, module: &mut dyn Module, diff --git a/src/driver/aot.rs b/src/driver/aot.rs index b8b325be71bcb..5a63786f070b4 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -271,18 +271,14 @@ fn module_codegen( cgu_name, ); super::predefine_mono_items(tcx, &mut module, &mono_items); - let mut cached_context = Context::new(); + let mut codegened_functions = vec![]; for (mono_item, _) in mono_items { match mono_item { MonoItem::Fn(inst) => { tcx.sess.time("codegen fn", || { - crate::base::codegen_and_compile_fn( - tcx, - &mut cx, - &mut cached_context, - &mut module, - inst, - ) + let codegened_function = + crate::base::codegen_fn(tcx, &mut cx, Function::new(), &mut module, inst); + codegened_functions.push(codegened_function); }); } MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), @@ -302,6 +298,11 @@ fn module_codegen( let cgu_name = cgu.name().as_str().to_owned(); OngoingModuleCodegen::Async(std::thread::spawn(move || { + let mut cached_context = Context::new(); + for codegened_func in codegened_functions { + crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func); + } + let global_asm_object_file = crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)?; From 5b4195669ebb2e7065b00258316d375b1be9b1b0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 16:11:12 +0000 Subject: [PATCH 094/100] Add some self profiler calls --- src/driver/aot.rs | 95 +++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 5a63786f070b4..67ac52f2d030c 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -258,53 +258,68 @@ fn module_codegen( ConcurrencyLimiterToken, ), ) -> OngoingModuleCodegen { - let cgu = tcx.codegen_unit(cgu_name); - let mono_items = cgu.items_in_deterministic_order(tcx); - - let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); - - let mut cx = crate::CodegenCx::new( - tcx, - backend_config.clone(), - module.isa(), - tcx.sess.opts.debuginfo != DebugInfo::None, - cgu_name, - ); - super::predefine_mono_items(tcx, &mut module, &mono_items); - let mut codegened_functions = vec![]; - for (mono_item, _) in mono_items { - match mono_item { - MonoItem::Fn(inst) => { - tcx.sess.time("codegen fn", || { - let codegened_function = - crate::base::codegen_fn(tcx, &mut cx, Function::new(), &mut module, inst); - codegened_functions.push(codegened_function); - }); - } - MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id), - MonoItem::GlobalAsm(item_id) => { - crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); + let (cgu_name, mut cx, mut module, codegened_functions) = tcx.sess.time("codegen cgu", || { + let cgu = tcx.codegen_unit(cgu_name); + let mono_items = cgu.items_in_deterministic_order(tcx); + + let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string()); + + let mut cx = crate::CodegenCx::new( + tcx, + backend_config.clone(), + module.isa(), + tcx.sess.opts.debuginfo != DebugInfo::None, + cgu_name, + ); + super::predefine_mono_items(tcx, &mut module, &mono_items); + let mut codegened_functions = vec![]; + for (mono_item, _) in mono_items { + match mono_item { + MonoItem::Fn(inst) => { + tcx.sess.time("codegen fn", || { + let codegened_function = crate::base::codegen_fn( + tcx, + &mut cx, + Function::new(), + &mut module, + inst, + ); + codegened_functions.push(codegened_function); + }); + } + MonoItem::Static(def_id) => { + crate::constant::codegen_static(tcx, &mut module, def_id) + } + MonoItem::GlobalAsm(item_id) => { + crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id); + } } } - } - crate::main_shim::maybe_create_entry_wrapper( - tcx, - &mut module, - &mut cx.unwind_context, - false, - cgu.is_primary(), - ); + crate::main_shim::maybe_create_entry_wrapper( + tcx, + &mut module, + &mut cx.unwind_context, + false, + cgu.is_primary(), + ); - let cgu_name = cgu.name().as_str().to_owned(); + let cgu_name = cgu.name().as_str().to_owned(); + + (cgu_name, cx, module, codegened_functions) + }); OngoingModuleCodegen::Async(std::thread::spawn(move || { - let mut cached_context = Context::new(); - for codegened_func in codegened_functions { - crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func); - } + cx.profiler.clone().verbose_generic_activity("compile functions").run(|| { + let mut cached_context = Context::new(); + for codegened_func in codegened_functions { + crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func); + } + }); let global_asm_object_file = - crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)?; + cx.profiler.verbose_generic_activity("compile assembly").run(|| { + crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) + })?; let codegen_result = cx.profiler.verbose_generic_activity("write object file").run(|| { emit_cgu( From f71c54574687681d0ea61175e3b78a823bfb5dee Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 23 Aug 2022 16:51:06 +0000 Subject: [PATCH 095/100] Make sure to count reused cgus towards the count of jobs done --- src/concurrency_limiter.rs | 13 +++++++++++++ src/driver/aot.rs | 1 + 2 files changed, 14 insertions(+) diff --git a/src/concurrency_limiter.rs b/src/concurrency_limiter.rs index eaf3a61f40394..d966ea323eb16 100644 --- a/src/concurrency_limiter.rs +++ b/src/concurrency_limiter.rs @@ -49,6 +49,11 @@ impl ConcurrencyLimiter { state = self.available_token_condvar.wait(state).unwrap(); } } + + pub(super) fn job_already_done(&mut self) { + let mut state = self.state.lock().unwrap(); + state.job_already_done(); + } } impl Drop for ConcurrencyLimiter { @@ -137,6 +142,14 @@ mod state { self.assert_invariants(); } + pub(super) fn job_already_done(&mut self) { + self.assert_invariants(); + self.pending_jobs -= 1; + self.assert_invariants(); + self.drop_excess_capacity(); + self.assert_invariants(); + } + fn drop_excess_capacity(&mut self) { self.assert_invariants(); if self.active_jobs == self.pending_jobs { diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 67ac52f2d030c..8eabe1cbcb150 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -391,6 +391,7 @@ pub(crate) fn run_aot( } CguReuse::PreLto => unreachable!(), CguReuse::PostLto => { + concurrency_limiter.job_already_done(); OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, &*cgu)) } } From 293223d0cf504c6bf0f314dcdabced1e828906dd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 24 Aug 2022 12:22:01 +0200 Subject: [PATCH 096/100] Tune drop_excess_capacity --- src/concurrency_limiter.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/concurrency_limiter.rs b/src/concurrency_limiter.rs index d966ea323eb16..ba9e82447dd2a 100644 --- a/src/concurrency_limiter.rs +++ b/src/concurrency_limiter.rs @@ -152,14 +152,14 @@ mod state { fn drop_excess_capacity(&mut self) { self.assert_invariants(); - if self.active_jobs == self.pending_jobs { - // Drop all excess tokens - self.tokens.truncate(std::cmp::max(self.active_jobs, 1)); - } else { - // Keep some excess tokens to satisfy requests faster - const MAX_EXTRA_CAPACITY: usize = 2; - self.tokens.truncate(std::cmp::max(self.active_jobs + MAX_EXTRA_CAPACITY, 1)); - } + + // Drop all tokens that can never be used anymore + self.tokens.truncate(std::cmp::max(self.pending_jobs, 1)); + + // Keep some excess tokens to satisfy requests faster + const MAX_EXTRA_CAPACITY: usize = 2; + self.tokens.truncate(std::cmp::max(self.active_jobs + MAX_EXTRA_CAPACITY, 1)); + self.assert_invariants(); } } From 072fd2b0b14e6da232cf51b991766a32456632e0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 24 Aug 2022 14:28:40 +0000 Subject: [PATCH 097/100] Add fixme --- src/concurrency_limiter.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/concurrency_limiter.rs b/src/concurrency_limiter.rs index ba9e82447dd2a..dfde97920461e 100644 --- a/src/concurrency_limiter.rs +++ b/src/concurrency_limiter.rs @@ -4,6 +4,8 @@ use rustc_session::Session; use jobserver::HelperThread; +// FIXME don't panic when a worker thread panics + pub(super) struct ConcurrencyLimiter { helper_thread: Option, state: Arc>, From e9d1a0a7b0b28dd422f1a790ccde532acafbf193 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 24 Aug 2022 18:37:37 +0200 Subject: [PATCH 098/100] Rustup to rustc 1.65.0-nightly (060e47f74 2022-08-23) --- build_sysroot/Cargo.lock | 12 ++++++------ rust-toolchain | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build_sysroot/Cargo.lock b/build_sysroot/Cargo.lock index 9713f13ccb33a..6c5043bb6f8e1 100644 --- a/build_sysroot/Cargo.lock +++ b/build_sysroot/Cargo.lock @@ -69,9 +69,9 @@ version = "0.0.0" [[package]] name = "dlmalloc" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e" +checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a" dependencies = [ "compiler_builtins", "libc", @@ -80,9 +80,9 @@ dependencies = [ [[package]] name = "fortanix-sgx-abi" -version = "0.3.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56c422ef86062869b2d57ae87270608dc5929969dd130a6e248979cf4fb6ca6" +checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.131" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" dependencies = [ "rustc-std-workspace-core", ] diff --git a/rust-toolchain b/rust-toolchain index 1405265959db1..14f2746ecb19f 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-08-15" +channel = "nightly-2022-08-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 716101c01db55a8c12c3aa48848751458229d73a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:06:37 +0000 Subject: [PATCH 099/100] Add new allowed deps --- src/tools/tidy/src/deps.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 333f85f6d62b8..7f8d6ad12888c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -300,6 +300,12 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "winapi", "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", + "windows-sys", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", ]; const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[ From e62e1d4347198e17cfb1fe6fec531cac3b223019 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:06:47 +0000 Subject: [PATCH 100/100] Rustfmt --- compiler/rustc_codegen_cranelift/build_system/tests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index dc83b10958e01..e21397cece8b3 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -465,7 +465,8 @@ impl TestRunner { out_dir.push("out"); let is_native = host_triple == target_triple; - let jit_supported = target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); + let jit_supported = + target_triple.contains("x86_64") && is_native && !host_triple.contains("windows"); let mut rust_flags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string()); let mut run_wrapper = Vec::new();