From 0fed1a5f57fc8ffba7dccfddbfffeb77282888b9 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 1 Jul 2022 13:01:41 -0700 Subject: [PATCH 001/115] 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 0812f930b5d..f3f3628fcee 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/115] Merge commit 'd3a2366ee877075c59b38bd8ced55f224fc7ef51' into sync_cg_clif-2022-07-26 --- src/intrinsics/llvm.rs | 145 +++++----- src/intrinsics/mod.rs | 622 ++++++++++++++++++++++++----------------- src/intrinsics/simd.rs | 387 +++++++++++++++---------- 3 files changed, 699 insertions(+), 455 deletions(-) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index 77ac46540a9..869670c8cfa 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 8d8db1da581..b2a83e1d4eb 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 d1ca9edf2e0..30e3d112594 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), + 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::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::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::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), + (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!(), + _ => 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/115] 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 3ab395d89d5..ca1813a6ed0 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/115] 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 c92c1051139..9d39b4aa661 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/115] 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 9d39b4aa661..e28c3813d3f 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/115] 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 e28c3813d3f..b4c79096170 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 568bb20a3f4..bb0793b1deb 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/115] 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 532049c858d..352fd39a308 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 61e977e3e69..3f343a49e0c 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 6c10baa53d4..2f8c697bd1e 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 f9dc1b5169e..fc4953cea6f 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 b2a83e1d4eb..f552c13958d 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 45ae2bd8f07..e48d095d139 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/115] Add Windows build artifacts to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5aeaf3a1788..38dd5b26063 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/115] 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 61da6a2491c..732edd66196 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 aa556a21bf8..a36c570ddc8 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 48faec8bc4b..04f8be6f820 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 16cce83dd9c..dddd5a673c5 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 b897b7fbacf..d1f8ad3e817 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 8bb00352d3f..7e0fd182d98 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 00000000000..74e4b51095f --- /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 12b5d70fad8..2d2778d2fc0 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 b14db27d620..5e4d230776d 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 9b5ffa40960..00000000000 --- 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 a10924628bb..00000000000 --- 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/115] 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 a36c570ddc8..1a947d3551c 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/115] 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 04f8be6f820..ddc099b5388 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 d1f8ad3e817..af75cef04e0 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 74e4b51095f..f2166b20fcb 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/115] 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 dddd5a673c5..14e82a77f86 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 af75cef04e0..0124d47de75 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 7e0fd182d98..4580c4b6549 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 9206bb02bd3..f9689eb2a8c 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/115] 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 14e82a77f86..cd3216cd624 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 f9689eb2a8c..63e1d16ead6 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 f2166b20fcb..20d600effd3 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 02443552c56c0b5d909ba3ddc653e686dff09d9c Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 00:02:47 +0800 Subject: [PATCH 014/115] break out to one scope higher for let-else --- compiler/rustc_mir_build/src/build/block.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6875600129a..c52a7b187d5 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -1,6 +1,7 @@ use crate::build::matches::ArmHasGuard; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; +use rustc_middle::middle::region::Scope; use rustc_middle::thir::*; use rustc_middle::{mir::*, ty}; use rustc_span::Span; @@ -34,10 +35,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &stmts, expr, safety_mode, + region_scope, )) }) } else { - this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode) + this.ast_block_stmts( + destination, + block, + span, + &stmts, + expr, + safety_mode, + region_scope, + ) } }) }) @@ -51,6 +61,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { stmts: &[StmtId], expr: Option<&Expr<'tcx>>, safety_mode: BlockSafety, + region_scope: Scope, ) -> BlockAnd<()> { let this = self; @@ -73,6 +84,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; + // This scope information is kept for breaking out of the current block in case + // one let-else pattern matching fails. + let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); @@ -132,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { initializer_span, else_block, visibility_scope, - *remainder_scope, + last_remainder_scope, remainder_span, pattern, ) @@ -178,6 +192,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(source_scope) = visibility_scope { this.source_scope = source_scope; } + last_remainder_scope = *remainder_scope; } } From aa2f4072f60c5c129a5597cc59ad908aa502868e Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Sat, 30 Jul 2022 15:40:44 +0100 Subject: [PATCH 015/115] 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 1a947d3551c..832572bcf35 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 016/115] 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 20d600effd3..22c8c8a4605 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 017/115] 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 22c8c8a4605..5c69beeaab5 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 018/115] 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 cd3216cd624..ed1c04808c5 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 5c69beeaab5..bc13066b020 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 019/115] 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 bc13066b020..e4a776259c0 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 020/115] 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 832572bcf35..a75c4f97529 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 021/115] 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 a75c4f97529..832572bcf35 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 e4a776259c0..2c96c5cc175 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 022/115] 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 ddc099b5388..48faec8bc4b 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 0124d47de75..3a6d58a2a6d 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 4580c4b6549..b499aaa703c 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 023/115] 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 832572bcf35..e8897e9ae81 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 024/115] 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 ed1c04808c5..6e4b57cf4d3 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 3a6d58a2a6d..4772a5a7778 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 b499aaa703c..7e0fd182d98 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 63e1d16ead6..913b589afcc 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 2c96c5cc175..2b4ae39a75e 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 025/115] 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 2b4ae39a75e..f6f3f4831e1 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 026/115] 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 6e4b57cf4d3..7e205b0fd0b 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 4772a5a7778..8c7d05993a5 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 f6f3f4831e1..3f225b4efa2 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 2d2778d2fc0..3282778e254 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 e26285603ca8b83b9d06e56f74e10e3d410553ff Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:31:53 +0800 Subject: [PATCH 027/115] add test for earlier drop despite extend lifetime --- src/test/ui/let-else/let-else-temporary-lifetime.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/ui/let-else/let-else-temporary-lifetime.rs b/src/test/ui/let-else/let-else-temporary-lifetime.rs index 9c86901b97f..07fcc16e7bb 100644 --- a/src/test/ui/let-else/let-else-temporary-lifetime.rs +++ b/src/test/ui/let-else/let-else-temporary-lifetime.rs @@ -74,6 +74,17 @@ fn main() { }; } } + { + fn must_pass() { + let rc = Rc::new(()); + let &None = &Some(Rc::clone(&rc)) else { + Rc::try_unwrap(rc).unwrap(); + return; + }; + unreachable!(); + } + must_pass(); + } { // test let-else drops temps before else block // NOTE: this test has to be the last block in the `main` From 8467a7b33ebdb0c8641e80c9c36bb098a93a7547 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sun, 31 Jul 2022 20:37:30 +0800 Subject: [PATCH 028/115] provide a clearer explanation of scope breaking --- compiler/rustc_mir_build/src/build/block.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index c52a7b187d5..280b6aad12c 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -84,8 +84,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut let_scope_stack = Vec::with_capacity(8); let outer_source_scope = this.source_scope; let outer_in_scope_unsafe = this.in_scope_unsafe; - // This scope information is kept for breaking out of the current block in case + // This scope information is kept for breaking out of the parent remainder scope in case // one let-else pattern matching fails. + // By doing so, we can be sure that even temporaries that receive extended lifetime + // assignments are dropped, too. let mut last_remainder_scope = region_scope; this.update_source_scope_for_safety_mode(span, safety_mode); From 46fa744e6914bb4f09bc250f059e1879b65a7160 Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Mon, 1 Aug 2022 09:49:54 +0100 Subject: [PATCH 029/115] 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 3f225b4efa2..dc83b10958e 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 030/115] 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 8b6042a3d66..f0e85ca478e 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 031/115] 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 f0e85ca478e..42f8aa50ba1 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 aa1f239bae2..412320997d5 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 032/115] 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 412320997d5..7e9cbe1bba5 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 033/115] 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 f552c13958d..77caf741acf 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 034/115] Update dependencies --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 352fd39a308..069f8cda1fa 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 035/115] 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 00000000000..3d929a1d50c --- /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 036/115] 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 48faec8bc4b..cf04967222f 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 8c7d05993a5..88c4150dbba 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 3282778e254..bdf8f8ecd99 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 037/115] 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 cf04967222f..9e59b8199b4 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 038/115] 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 38dd5b26063..6fd3e4443de 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 00000000000..1aff4acc21b --- /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 88c4150dbba..c5b3e6619b7 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 7e0fd182d98..12aafdc1fb3 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 039/115] 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 e8897e9ae81..0b259369e61 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 040/115] 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 ea1f8c1e892..62e52bd1958 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 041/115] Pass all pairs to abi-checker --- build_system/abi_checker.rs | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/build_system/abi_checker.rs b/build_system/abi_checker.rs index 1aff4acc21b..21d9afc8231 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.args(pairs); + cmd.arg("--add-rustc-codegen-backend"); + cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display())); - 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()); - 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); - } + // 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 042/115] Move abi-checker to y.rs test --- .github/workflows/main.yml | 5 ----- build_system/abi_checker.rs | 14 ++++++++++---- build_system/mod.rs | 24 +++++++++--------------- config.txt | 2 ++ 4 files changed, 21 insertions(+), 24 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0b259369e61..e8897e9ae81 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 21d9afc8231..b6dc0fa6922 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 c5b3e6619b7..c3706dc6f82 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,6 +142,15 @@ pub fn main() { &host_triple, &target_triple, ); + + abi_checker::run( + channel, + sysroot_kind, + &target_dir, + &cg_clif_build_dir, + &host_triple, + &target_triple, + ); } Command::Build => { build_sysroot::build_sysroot( @@ -158,15 +162,5 @@ 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/config.txt b/config.txt index 5e4d230776d..2264d301d59 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 043/115] 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 052ca0a082b..dd9d891ddbd 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 044/115] 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 532049c858d..402fbb16f97 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 045/115] 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 7b2cdd27336..e9bd9167acd 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 ca1813a6ed0..9b9ed85f6c7 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 046/115] 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 122e103ff62..2c04cf47268 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 f619bb5ed5e..e41ae1fbdba 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 241de5e3653..7b1a39c675c 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 d02dfd93c3e..5120b89c4e8 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 869670c8cfa..a799dca938e 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 77caf741acf..cb620822f2d 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 30e3d112594..c7efdb392b7 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 923269c4de9..82a2ec57954 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 047/115] 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 2c04cf47268..439b636031b 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 048/115] 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 439b636031b..8e3f905166b 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 3cd1ef5639e..802e8ebd6f6 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 a56a9100059..a7ea2b182ab 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 049/115] 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 8e3f905166b..c68d33465bc 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 802e8ebd6f6..6aa28637943 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 a7ea2b182ab..1b046d7ec6e 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 bb0793b1deb..a3f8cc4dfa3 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 050/115] 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 6aa28637943..6f1732f9707 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 051/115] 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 6f1732f9707..c417de04ab4 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 a3f8cc4dfa3..49d10012c4f 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 052/115] 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 c417de04ab4..6482dce2746 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 00000000000..5962a86a686 --- /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 49d10012c4f..6ea160d26ce 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 053/115] 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 6482dce2746..0816ebc4599 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 5962a86a686..5cd7abfdfb5 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 f86236ef3ea..b6b465e1f4e 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 054/115] 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 e48d095d139..9e945d83621 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 055/115] 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 0816ebc4599..0ca634affb4 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 5cd7abfdfb5..14288e99242 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 056/115] 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 50ef0bd9418..f3cd7ee77e2 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 057/115] 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 0ca634affb4..4122ce18224 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 14288e99242..8e711988f81 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 058/115] 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 8a2db5a43ec..1e84c7fa365 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 7e9cbe1bba5..e83be3a3df5 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 8e711988f81..917a6fff727 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 059/115] 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 4122ce18224..3bbd286b3d7 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 060/115] 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 3bbd286b3d7..ee89d0701aa 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 061/115] 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 ee89d0701aa..415631ba3e6 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 062/115] 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 415631ba3e6..ff6310bd8af 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 063/115] 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 ff6310bd8af..7e5e3453834 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 6ea160d26ce..909f4f00f1e 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 064/115] 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 b6dc0fa6922..67dbd0a38a4 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 12aafdc1fb3..24a233d3806 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 065/115] 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 24a233d3806..d23b7f00dcf 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 00000000000..526366a7598 --- /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 066/115] 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 067/115] 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 7e5e3453834..817ce7f7e6d 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 068/115] 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 817ce7f7e6d..9d819e3995b 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 917a6fff727..dcbcaba30fe 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 069/115] 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 7b1a39c675c..9221abb8225 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 070/115] 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 e9bd9167acd..9713f13ccb3 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 9b9ed85f6c7..1405265959d 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 071/115] 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 c68d33465bc..2603da19182 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 d1f89adb3bb..0df7e82294b 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 072/115] 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 2603da19182..85cdc6824a6 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 1d1ec21680e..0081ec842eb 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 073/115] Remove TyCtxt field from CodegenCx --- src/base.rs | 64 ++++++++++++++++++++++++---------------------- src/driver/aot.rs | 3 ++- src/driver/jit.rs | 10 ++++---- src/lib.rs | 7 +++-- src/pretty_clif.rs | 59 +++++++++++++++++++----------------------- 5 files changed, 72 insertions(+), 71 deletions(-) diff --git a/src/base.rs b/src/base.rs index 85cdc6824a6..6a276df40ba 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 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( - tcx, - || format!("{}.vcode", codegened_func.symbol_name.name), - |file| file.write_all(disasm.as_bytes()), - ) + 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 9d819e3995b..b2ad3cc4c4c 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 1b046d7ec6e..de71b76da4e 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 909f4f00f1e..1e851e31ac3 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 0081ec842eb..a7af162687c 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 074/115] 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 2f8c697bd1e..3192575b8ad 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 075/115] 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 6a276df40ba..a7c7f66e166 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 1e851e31ac3..f4ffbbcf86e 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 076/115] 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 de71b76da4e..00e7263446b 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 077/115] 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 a7c7f66e166..fe04567af66 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 693092ba543..7a330ff7d35 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 078/115] 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 fe04567af66..b35f02e2d2d 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 7a330ff7d35..9a0787508b7 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 079/115] 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 b35f02e2d2d..b2026f30d17 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 fc4953cea6f..1adb64da8bd 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 589910ede96..9583cd2ec60 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 bbcb9591373..de402a4c713 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 9a0787508b7..3e42905c840 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 b2ad3cc4c4c..971e5eeea87 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 00e7263446b..0e77e4004c0 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 f4ffbbcf86e..40dab58523c 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 080/115] 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 de402a4c713..eb136516771 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()) + }; -pub(crate) fn make_file_info(hash: SourceFileHash) -> Option { + 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 { 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 081/115] 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 b2026f30d17..73af2ea33be 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 3e42905c840..0726807000d 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 } + } +} - self.unit_range_list.0.push(Range::StartLength { +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, + ); + + 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 082/115] 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 73af2ea33be..34dbf96be7d 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 1adb64da8bd..655ceacf729 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 083/115] 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 34dbf96be7d..8440a03335a 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 eb136516771..5a13b9681c0 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 0726807000d..169b7d1ef4c 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 084/115] Make line_program_add_file a DebugContext method --- src/debuginfo/line_info.rs | 99 +++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index 5a13b9681c0..4fdaaf4ffe0 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); +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; - 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); + 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 info = make_file_info(file.src_hash); + 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); - 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) + 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 085/115] 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 8440a03335a..5f6d9f374fd 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 655ceacf729..4a80b79a9dc 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 4fdaaf4ffe0..ff6a21eef0d 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 create_row_for_span = + |debug_context: &mut DebugContext, source_loc: (FileId, u64, u64)| { + let (file_id, line, col) = source_loc; - 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. - 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 169b7d1ef4c..c55db2017ee 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 086/115] 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 971e5eeea87..3220d16f725 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 087/115] 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 cf95c89bc31..50261c19397 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 e4403ae9ff9ca9912fe80a5401c57c48fb979e5f Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 20 Aug 2022 18:30:49 +0200 Subject: [PATCH 088/115] Move existing diagnostic struct to a new errors module --- compiler/rustc_interface/src/errors.rs | 19 +++++++++++++++++++ compiler/rustc_interface/src/lib.rs | 1 + compiler/rustc_interface/src/passes.rs | 21 ++------------------- 3 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 compiler/rustc_interface/src/errors.rs diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs new file mode 100644 index 00000000000..62456d76d71 --- /dev/null +++ b/compiler/rustc_interface/src/errors.rs @@ -0,0 +1,19 @@ +use rustc_macros::SessionDiagnostic; +use rustc_span::{Span, Symbol}; + +#[derive(SessionDiagnostic)] +#[diag(interface::ferris_identifier)] +pub struct FerrisIdentifier { + #[primary_span] + pub spans: Vec, + #[suggestion(code = "ferris", applicability = "maybe-incorrect")] + pub first_span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::emoji_identifier)] +pub struct EmojiIdentifier { + #[primary_span] + pub spans: Vec, + pub ident: Symbol, +} diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index d443057eb79..5ff1a952aef 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -7,6 +7,7 @@ #![allow(rustc::potential_query_instability)] mod callbacks; +mod errors; pub mod interface; mod passes; mod proc_macro_decls; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 014cf88389e..759f9e0f0c9 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,3 +1,4 @@ +use crate::errors::{EmojiIdentifier, FerrisIdentifier}; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; @@ -13,7 +14,6 @@ use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; use rustc_hir::def_id::StableCrateId; use rustc_hir::definitions::Definitions; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; -use rustc_macros::SessionDiagnostic; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -31,7 +31,7 @@ use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{FileName, Span}; +use rustc_span::FileName; use rustc_trait_selection::traits; use rustc_typeck as typeck; use tracing::{info, warn}; @@ -264,23 +264,6 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { } } -#[derive(SessionDiagnostic)] -#[diag(interface::ferris_identifier)] -struct FerrisIdentifier { - #[primary_span] - spans: Vec, - #[suggestion(code = "ferris", applicability = "maybe-incorrect")] - first_span: Span, -} - -#[derive(SessionDiagnostic)] -#[diag(interface::emoji_identifier)] -struct EmojiIdentifier { - #[primary_span] - spans: Vec, - ident: Symbol, -} - /// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins, /// syntax expansion, secondary `cfg` expansion, synthesis of a test /// harness if one is to be provided, injection of a dependency on the From b411adec2aff3d57928e42017aa267fbed6e05f5 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 20 Aug 2022 18:33:02 +0200 Subject: [PATCH 089/115] Move rustc_interface diagnostics to struct SessionDiagnostic derives --- .../locales/en-US/interface.ftl | 37 ++++++++++ compiler/rustc_interface/src/errors.rs | 68 +++++++++++++++++++ compiler/rustc_interface/src/passes.rs | 54 +++++++-------- compiler/rustc_interface/src/queries.rs | 18 ++--- 4 files changed, 137 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index 2c05abd8c09..47419537311 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -4,3 +4,40 @@ interface_ferris_identifier = interface_emoji_identifier = identifiers cannot contain emoji: `{$ident}` + +mixed_bin_crate = + cannot mix `bin` crate type with others + +mixed_proc_macro_crate = + cannot mix `proc-macro` crate type with others + +proc_macro_doc_without_arg = + Trying to document proc macro crate without passing '--crate-type proc-macro to rustdoc + .warn = The generated documentation may be incorrect + +error_writing_dependencies = + error writing dependencies to `{$path}`: {$error} + +input_file_would_be_overwritten = + the input file "{$path}" would be overwritten by the generated executable + +generated_file_conflicts_with_directory = + the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}" + +temps_dir_error = + failed to find or create the directory specified by `--temps-dir` + +out_dir_error = + failed to find or create the directory specified by `--out-dir` + +cant_emit_mir = + could not emit MIR: {$error} + +rustc_error_fatal = + fatal error triggered by #[rustc_error] + +rustc_error_unexpected_annotation = + unexpected annotation used with `#[rustc_error(...)]! + +failed_writing_file = + failed to write file {$path}: {$error}" diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index 62456d76d71..a72134e31f1 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,3 +1,4 @@ +use rustc_errors::DiagnosticArgFromDisplay; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; @@ -17,3 +18,70 @@ pub struct EmojiIdentifier { pub spans: Vec, pub ident: Symbol, } + +#[derive(SessionDiagnostic)] +#[diag(interface::mixed_bin_crate)] +pub struct MixedBinCrate; + +#[derive(SessionDiagnostic)] +#[diag(interface::mixed_proc_macro_crate)] +pub struct MixedProcMacroCrate; + +#[derive(SessionDiagnostic)] +#[diag(interface::proc_macro_doc_without_arg)] +pub struct ProcMacroDocWithoutArg; + +#[derive(SessionDiagnostic)] +#[diag(interface::error_writing_dependencies)] +pub struct ErrorWritingDependencies<'a> { + pub path: DiagnosticArgFromDisplay<'a>, + pub error: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::input_file_would_be_overwritten)] +pub struct InputFileWouldBeOverWritten<'a> { + pub path: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::generated_file_conflicts_with_directory)] +pub struct GeneratedFileConflictsWithDirectory<'a> { + pub input_path: DiagnosticArgFromDisplay<'a>, + pub dir_path: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::temps_dir_error)] +pub struct TempsDirError; + +#[derive(SessionDiagnostic)] +#[diag(interface::out_dir_error)] +pub struct OutDirError; + +#[derive(SessionDiagnostic)] +#[diag(interface::cant_emit_mir)] +pub struct CantEmitMIR<'a> { + pub error: DiagnosticArgFromDisplay<'a>, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::rustc_error_fatal)] +pub struct RustcErrorFatal { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::rustc_error_unexpected_annotation)] +pub struct RustcErrorUnexpectedAnnotation { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(interface::failed_writing_file)] +pub struct FailedWritingFile<'a> { + pub path: DiagnosticArgFromDisplay<'a>, + pub error: DiagnosticArgFromDisplay<'a>, +} diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 759f9e0f0c9..b58fd7b338c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,4 +1,8 @@ -use crate::errors::{EmojiIdentifier, FerrisIdentifier}; +use crate::errors::{ + CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, + GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, + MixedProcMacroCrate, OutDirError, ProcMacroDocWithoutArg, TempsDirError, +}; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; @@ -375,10 +379,10 @@ pub fn configure_and_expand( if crate_types.len() > 1 { if is_executable_crate { - sess.err("cannot mix `bin` crate type with others"); + sess.emit_err(MixedBinCrate); } if is_proc_macro_crate { - sess.err("cannot mix `proc-macro` crate type with others"); + sess.emit_err(MixedProcMacroCrate); } } @@ -389,13 +393,7 @@ pub fn configure_and_expand( // However, we do emit a warning, to let such users know that they should // start passing '--crate-type proc-macro' if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { - let mut msg = sess.diagnostic().struct_warn( - "Trying to document proc macro crate \ - without passing '--crate-type proc-macro to rustdoc", - ); - - msg.warn("The generated documentation may be incorrect"); - msg.emit(); + sess.emit_warning(ProcMacroDocWithoutArg); } else { krate = sess.time("maybe_create_a_macro_crate", || { let is_test_crate = sess.opts.test; @@ -649,11 +647,12 @@ fn write_out_deps( .emit_artifact_notification(&deps_filename, "dep-info"); } } - Err(e) => sess.fatal(&format!( - "error writing dependencies to `{}`: {}", - deps_filename.display(), - e - )), + Err(e) => { + sess.emit_fatal(ErrorWritingDependencies { + path: (&deps_filename.display()).into(), + error: (&e).into(), + }); + } } } @@ -683,20 +682,15 @@ pub fn prepare_outputs( if let Some(ref input_path) = compiler.input_path { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { - let reported = sess.err(&format!( - "the input file \"{}\" would be overwritten by the generated \ - executable", - input_path.display() - )); + let reported = sess + .emit_err(InputFileWouldBeOverWritten { path: (&input_path.display()).into() }); return Err(reported); } if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { - let reported = sess.err(&format!( - "the generated executable for the input file \"{}\" conflicts with the \ - existing directory \"{}\"", - input_path.display(), - dir_path.display() - )); + let reported = sess.emit_err(GeneratedFileConflictsWithDirectory { + input_path: (&input_path.display()).into(), + dir_path: (&dir_path.display()).into(), + }); return Err(reported); } } @@ -704,8 +698,7 @@ pub fn prepare_outputs( if let Some(ref dir) = compiler.temps_dir { if fs::create_dir_all(dir).is_err() { - let reported = - sess.err("failed to find or create the directory specified by `--temps-dir`"); + let reported = sess.emit_err(TempsDirError); return Err(reported); } } @@ -718,8 +711,7 @@ pub fn prepare_outputs( if !only_dep_info { if let Some(ref dir) = compiler.output_dir { if fs::create_dir_all(dir).is_err() { - let reported = - sess.err("failed to find or create the directory specified by `--out-dir`"); + let reported = sess.emit_err(OutDirError); return Err(reported); } } @@ -1003,7 +995,7 @@ pub fn start_codegen<'tcx>( if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { if let Err(e) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { - tcx.sess.err(&format!("could not emit MIR: {}", e)); + tcx.sess.emit_err(CantEmitMIR { error: (&e).into() }); tcx.sess.abort_if_errors(); } } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 73402ae0842..e0e8752036e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -1,3 +1,4 @@ +use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation}; use crate::interface::{Compiler, Result}; use crate::passes::{self, BoxedResolver, QueryContext}; @@ -274,18 +275,14 @@ impl<'tcx> Queries<'tcx> { // Bare `#[rustc_error]`. None => { - tcx.sess.span_fatal( - tcx.def_span(def_id), - "fatal error triggered by #[rustc_error]", - ); + tcx.sess.emit_fatal(RustcErrorFatal { span: tcx.def_span(def_id) }); } // Some other attribute. Some(_) => { - tcx.sess.span_warn( - tcx.def_span(def_id), - "unexpected annotation used with `#[rustc_error(...)]!", - ); + tcx.sess.emit_warning(RustcErrorUnexpectedAnnotation { + span: tcx.def_span(def_id), + }); } } } @@ -361,7 +358,10 @@ impl Linker { let encoded = CodegenResults::serialize_rlink(&codegen_results); let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); std::fs::write(&rlink_file, encoded).map_err(|err| { - sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err)); + sess.emit_fatal(FailedWritingFile { + path: (&rlink_file.display()).into(), + error: (&err).into(), + }) })?; return Ok(()); } From ccc1a4b7a184127e2e6b60000009828b2d4110d3 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Sat, 20 Aug 2022 18:33:35 +0200 Subject: [PATCH 090/115] Deny diagnostic lints in rustc_interface --- compiler/rustc_interface/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 5ff1a952aef..258e38c3bdb 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -5,6 +5,8 @@ #![feature(once_cell)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] mod callbacks; mod errors; From 217a11bdb1d95fbed608636025e9eee9b9daaeb4 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 22 Aug 2022 14:59:41 +0200 Subject: [PATCH 091/115] Prefix fluent resources with interface_ --- .../locales/en-US/interface.ftl | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_error_messages/locales/en-US/interface.ftl index 47419537311..bbcb8fc28cf 100644 --- a/compiler/rustc_error_messages/locales/en-US/interface.ftl +++ b/compiler/rustc_error_messages/locales/en-US/interface.ftl @@ -5,39 +5,39 @@ interface_ferris_identifier = interface_emoji_identifier = identifiers cannot contain emoji: `{$ident}` -mixed_bin_crate = +interface_mixed_bin_crate = cannot mix `bin` crate type with others -mixed_proc_macro_crate = +interface_mixed_proc_macro_crate = cannot mix `proc-macro` crate type with others -proc_macro_doc_without_arg = +interface_proc_macro_doc_without_arg = Trying to document proc macro crate without passing '--crate-type proc-macro to rustdoc .warn = The generated documentation may be incorrect -error_writing_dependencies = +interface_error_writing_dependencies = error writing dependencies to `{$path}`: {$error} -input_file_would_be_overwritten = +interface_input_file_would_be_overwritten = the input file "{$path}" would be overwritten by the generated executable -generated_file_conflicts_with_directory = +interface_generated_file_conflicts_with_directory = the generated executable for the input file "{$input_path}" conflicts with the existing directory "{$dir_path}" -temps_dir_error = +interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` -out_dir_error = +interface_out_dir_error = failed to find or create the directory specified by `--out-dir` -cant_emit_mir = +interface_cant_emit_mir = could not emit MIR: {$error} -rustc_error_fatal = +interface_rustc_error_fatal = fatal error triggered by #[rustc_error] -rustc_error_unexpected_annotation = +interface_rustc_error_unexpected_annotation = unexpected annotation used with `#[rustc_error(...)]! -failed_writing_file = +interface_failed_writing_file = failed to write file {$path}: {$error}" From 0d80ee705f8a7acb65b5ecb05ae0e6deaa97bb53 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 19 Aug 2022 14:45:54 +0100 Subject: [PATCH 092/115] errors: `IntoDiagnosticArg` for `io::Error`/paths Add impls of `IntoDiagnosticArg` for `std::io::Error`, `std::path::Path` and `std::path::PathBuf`. Signed-off-by: David Wood --- compiler/rustc_errors/src/diagnostic.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 356f9dfdb3b..506198df4d8 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -13,6 +13,7 @@ use rustc_span::{edition::Edition, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; +use std::path::{Path, PathBuf}; /// Error type for `Diagnostic`'s `suggestions` field, indicating that /// `.disable_suggestions()` was called on the `Diagnostic`. @@ -83,6 +84,7 @@ into_diagnostic_arg_using_display!( u64, i128, u128, + std::io::Error, std::num::NonZeroU32, hir::Target, Edition, @@ -124,6 +126,18 @@ impl IntoDiagnosticArg for String { } } +impl<'a> IntoDiagnosticArg for &'a Path { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) + } +} + +impl IntoDiagnosticArg for PathBuf { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) + } +} + impl IntoDiagnosticArg for usize { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Number(self) From 645de5b825987473f02b6ac62cfe915602be4c28 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 22 Aug 2022 15:58:26 +0200 Subject: [PATCH 093/115] Remove use of DiagnosticArgFromDisplay --- compiler/rustc_interface/src/errors.rs | 22 ++++++++++++---------- compiler/rustc_interface/src/passes.rs | 22 ++++++++-------------- compiler/rustc_interface/src/queries.rs | 8 ++------ 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index a72134e31f1..6a497aed4ab 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,7 +1,9 @@ -use rustc_errors::DiagnosticArgFromDisplay; use rustc_macros::SessionDiagnostic; use rustc_span::{Span, Symbol}; +use std::io; +use std::path::Path; + #[derive(SessionDiagnostic)] #[diag(interface::ferris_identifier)] pub struct FerrisIdentifier { @@ -34,21 +36,21 @@ pub struct ProcMacroDocWithoutArg; #[derive(SessionDiagnostic)] #[diag(interface::error_writing_dependencies)] pub struct ErrorWritingDependencies<'a> { - pub path: DiagnosticArgFromDisplay<'a>, - pub error: DiagnosticArgFromDisplay<'a>, + pub path: &'a Path, + pub error: io::Error, } #[derive(SessionDiagnostic)] #[diag(interface::input_file_would_be_overwritten)] pub struct InputFileWouldBeOverWritten<'a> { - pub path: DiagnosticArgFromDisplay<'a>, + pub path: &'a Path, } #[derive(SessionDiagnostic)] #[diag(interface::generated_file_conflicts_with_directory)] pub struct GeneratedFileConflictsWithDirectory<'a> { - pub input_path: DiagnosticArgFromDisplay<'a>, - pub dir_path: DiagnosticArgFromDisplay<'a>, + pub input_path: &'a Path, + pub dir_path: &'a Path, } #[derive(SessionDiagnostic)] @@ -61,8 +63,8 @@ pub struct OutDirError; #[derive(SessionDiagnostic)] #[diag(interface::cant_emit_mir)] -pub struct CantEmitMIR<'a> { - pub error: DiagnosticArgFromDisplay<'a>, +pub struct CantEmitMIR { + pub error: io::Error, } #[derive(SessionDiagnostic)] @@ -82,6 +84,6 @@ pub struct RustcErrorUnexpectedAnnotation { #[derive(SessionDiagnostic)] #[diag(interface::failed_writing_file)] pub struct FailedWritingFile<'a> { - pub path: DiagnosticArgFromDisplay<'a>, - pub error: DiagnosticArgFromDisplay<'a>, + pub path: &'a Path, + pub error: io::Error, } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b58fd7b338c..269d4c3795a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -647,11 +647,8 @@ fn write_out_deps( .emit_artifact_notification(&deps_filename, "dep-info"); } } - Err(e) => { - sess.emit_fatal(ErrorWritingDependencies { - path: (&deps_filename.display()).into(), - error: (&e).into(), - }); + Err(error) => { + sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error }); } } } @@ -682,15 +679,12 @@ pub fn prepare_outputs( if let Some(ref input_path) = compiler.input_path { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { - let reported = sess - .emit_err(InputFileWouldBeOverWritten { path: (&input_path.display()).into() }); + let reported = sess.emit_err(InputFileWouldBeOverWritten { path: input_path }); return Err(reported); } - if let Some(dir_path) = output_conflicts_with_dir(&output_paths) { - let reported = sess.emit_err(GeneratedFileConflictsWithDirectory { - input_path: (&input_path.display()).into(), - dir_path: (&dir_path.display()).into(), - }); + if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { + let reported = + sess.emit_err(GeneratedFileConflictsWithDirectory { input_path, dir_path }); return Err(reported); } } @@ -994,8 +988,8 @@ pub fn start_codegen<'tcx>( info!("Post-codegen\n{:?}", tcx.debug_stats()); if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(e) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { - tcx.sess.emit_err(CantEmitMIR { error: (&e).into() }); + if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) { + tcx.sess.emit_err(CantEmitMIR { error }); tcx.sess.abort_if_errors(); } } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index e0e8752036e..65fa8d7495a 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -357,12 +357,8 @@ impl Linker { if sess.opts.unstable_opts.no_link { let encoded = CodegenResults::serialize_rlink(&codegen_results); let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT); - std::fs::write(&rlink_file, encoded).map_err(|err| { - sess.emit_fatal(FailedWritingFile { - path: (&rlink_file.display()).into(), - error: (&err).into(), - }) - })?; + std::fs::write(&rlink_file, encoded) + .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?; return Ok(()); } 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 094/115] Update to Cranelift 0.87.0 --- Cargo.lock | 64 +++++++++++++++++--------------------- 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, 42 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea7e8f45db3..edae7e47157 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", @@ -205,20 +205,14 @@ dependencies = [ "indexmap", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "indexmap" @@ -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 3f343a49e0c..e7c34274854 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 3192575b8ad..f4ad76b3bab 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 5f6d9f374fd..3a4c2b84549 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 ff6a21eef0d..3ad0c420eaf 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 9221abb8225..8b3d475cb18 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 9e945d83621..2ee98546c99 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 351acc87f57d05847e95b1863a9c5c7e953e162c Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 23 Aug 2022 17:02:40 +0800 Subject: [PATCH 095/115] parser will not give wrong help message for 'public' --- .../rustc_parse/src/parser/diagnostics.rs | 24 +++++++++++-------- compiler/rustc_span/src/symbol.rs | 1 + .../ui/parser/public-instead-of-pub-1.fixed | 11 +++++++++ src/test/ui/parser/public-instead-of-pub-1.rs | 11 +++++++++ .../ui/parser/public-instead-of-pub-1.stderr | 13 ++++++++++ src/test/ui/parser/public-instead-of-pub-2.rs | 7 ++++++ .../ui/parser/public-instead-of-pub-2.stderr | 8 +++++++ 7 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/parser/public-instead-of-pub-1.fixed create mode 100644 src/test/ui/parser/public-instead-of-pub-1.rs create mode 100644 src/test/ui/parser/public-instead-of-pub-1.stderr create mode 100644 src/test/ui/parser/public-instead-of-pub-2.rs create mode 100644 src/test/ui/parser/public-instead-of-pub-2.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index b8884dd32d6..f2d79ce756c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -22,7 +22,7 @@ use rustc_errors::{ use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_span::source_map::Spanned; -use rustc_span::symbol::{kw, Ident}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; use std::ops::{Deref, DerefMut}; @@ -977,15 +977,6 @@ impl<'a> Parser<'a> { let mut err = self.struct_span_err(self.token.span, &msg_exp); if let TokenKind::Ident(symbol, _) = &self.prev_token.kind { - if symbol.as_str() == "public" { - err.span_suggestion_short( - self.prev_token.span, - "write `pub` instead of `public` to make the item public", - "pub", - appl, - ); - } - if ["def", "fun", "func", "function"].contains(&symbol.as_str()) { err.span_suggestion_short( self.prev_token.span, @@ -996,6 +987,19 @@ impl<'a> Parser<'a> { } } + // `pub` may be used for an item or `pub(crate)` + if self.prev_token.is_ident_named(sym::public) + && (self.token.can_begin_item() + || self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) + { + err.span_suggestion_short( + self.prev_token.span, + "write `pub` instead of `public` to make the item public", + "pub", + appl, + ); + } + // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens // there are unclosed angle brackets if self.unmatched_angle_bracket_count > 0 diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 156f53ac486..4fac74278de 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1118,6 +1118,7 @@ symbols! { ptr_offset_from_unsigned, pub_macro_rules, pub_restricted, + public, pure, pushpop_unsafe, qreg, diff --git a/src/test/ui/parser/public-instead-of-pub-1.fixed b/src/test/ui/parser/public-instead-of-pub-1.fixed new file mode 100644 index 00000000000..a4fa68ba5cc --- /dev/null +++ b/src/test/ui/parser/public-instead-of-pub-1.fixed @@ -0,0 +1,11 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// run-rustfix + +pub enum Test { + //~^ ERROR expected one of `!` or `::`, found keyword `enum` + //~^^ HELP write `pub` instead of `public` to make the item public + A, + B, +} + +fn main() { } diff --git a/src/test/ui/parser/public-instead-of-pub-1.rs b/src/test/ui/parser/public-instead-of-pub-1.rs new file mode 100644 index 00000000000..43565c9b1d2 --- /dev/null +++ b/src/test/ui/parser/public-instead-of-pub-1.rs @@ -0,0 +1,11 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// run-rustfix + +public enum Test { + //~^ ERROR expected one of `!` or `::`, found keyword `enum` + //~^^ HELP write `pub` instead of `public` to make the item public + A, + B, +} + +fn main() { } diff --git a/src/test/ui/parser/public-instead-of-pub-1.stderr b/src/test/ui/parser/public-instead-of-pub-1.stderr new file mode 100644 index 00000000000..795a5bcf5df --- /dev/null +++ b/src/test/ui/parser/public-instead-of-pub-1.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found keyword `enum` + --> $DIR/public-instead-of-pub-1.rs:4:8 + | +LL | public enum Test { + | ^^^^ expected one of `!` or `::` + | +help: write `pub` instead of `public` to make the item public + | +LL | pub enum Test { + | ~~~ + +error: aborting due to previous error + diff --git a/src/test/ui/parser/public-instead-of-pub-2.rs b/src/test/ui/parser/public-instead-of-pub-2.rs new file mode 100644 index 00000000000..8a43c361e05 --- /dev/null +++ b/src/test/ui/parser/public-instead-of-pub-2.rs @@ -0,0 +1,7 @@ +// Checks what happens when `public` is used instead of the correct, `pub` +// Won't give help message for this case + +public let x = 1; +//~^ ERROR expected one of `!` or `::`, found keyword `let` + +fn main() { } diff --git a/src/test/ui/parser/public-instead-of-pub-2.stderr b/src/test/ui/parser/public-instead-of-pub-2.stderr new file mode 100644 index 00000000000..efe225656fd --- /dev/null +++ b/src/test/ui/parser/public-instead-of-pub-2.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `let` + --> $DIR/public-instead-of-pub-2.rs:4:8 + | +LL | public let x = 1; + | ^^^ expected one of `!` or `::` + +error: aborting due to previous error + From 156bda8bc708cca60e9de18743d833c8d97dd7ff Mon Sep 17 00:00:00 2001 From: Afonso Bordado Date: Tue, 23 Aug 2022 11:42:24 +0100 Subject: [PATCH 096/115] 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 4ce8adb182e..679974710df 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 097/115] 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 cb620822f2d..ef3d5ccea8a 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 c7efdb392b7..a32b413d45f 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 098/115] 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 679974710df..4ce8adb182e 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 099/115] 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 3a4c2b84549..492e4882651 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 4a80b79a9dc..58959446578 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 100/115] 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 00000000000..eaf3a61f403 --- /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 40dab58523c..913414e7618 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 101/115] Do asm compilation and object file emission in parallel --- src/driver/aot.rs | 78 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 3220d16f725..224756bc6c7 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, - )?; + let cgu_name = cgu.name().as_str().to_owned(); - 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, - ) - }) + 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 eb2fdd917ef05184c7ef2eab707183b07d68ff5e Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 23 Aug 2022 16:15:09 +0000 Subject: [PATCH 102/115] Add a warning about `Option/Result::and()` being eagerly evaluated Copied from `or()`. --- library/core/src/option.rs | 6 ++++++ library/core/src/result.rs | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index bca73cb770f..93417586363 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1189,6 +1189,12 @@ impl Option { /// Returns [`None`] if the option is [`None`], otherwise returns `optb`. /// + /// Arguments passed to `and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`and_then`], which is + /// lazily evaluated. + /// + /// [`and_then`]: Option::and_then + /// /// # Examples /// /// ``` diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 45b052c824d..75dcb4cdba9 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1285,6 +1285,11 @@ impl Result { /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. /// + /// Arguments passed to `and` are eagerly evaluated; if you are passing the + /// result of a function call, it is recommended to use [`and_then`], which is + /// lazily evaluated. + /// + /// [`and_then`]: Result::and_then /// /// # Examples /// 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 103/115] 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 224756bc6c7..b8b325be71b 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 104/115] 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 492e4882651..44c34d6c8cb 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 b8b325be71b..5a63786f070 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 105/115] Add some self profiler calls --- src/driver/aot.rs | 91 +++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 5a63786f070..67ac52f2d03 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 (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 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 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 106/115] 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 eaf3a61f403..d966ea323eb 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 67ac52f2d03..8eabe1cbcb1 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 9b95eef6ea3fc8a371241277698be881d4ec4bb7 Mon Sep 17 00:00:00 2001 From: Wonchul Lee Date: Sat, 20 Aug 2022 06:40:31 +0900 Subject: [PATCH 107/115] save_analysis: Migrate diagnostics --- Cargo.lock | 2 ++ .../locales/en-US/save_analysis.ftl | 1 + compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_save_analysis/Cargo.toml | 2 ++ compiler/rustc_save_analysis/src/errors.rs | 10 ++++++++++ compiler/rustc_save_analysis/src/lib.rs | 6 +++++- 6 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/save_analysis.ftl create mode 100644 compiler/rustc_save_analysis/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index 9d91dcde9b4..9e88b908917 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4421,9 +4421,11 @@ dependencies = [ "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", + "rustc_errors", "rustc_hir", "rustc_hir_pretty", "rustc_lexer", + "rustc_macros", "rustc_middle", "rustc_session", "rustc_span", diff --git a/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl new file mode 100644 index 00000000000..36c2ff46823 --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl @@ -0,0 +1 @@ +save_analysis_could_not_open = Could not open `{$file_name}`: `{$err}` diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3e66d12bb37..2d001d445be 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -43,6 +43,7 @@ fluent_messages! { passes => "../locales/en-US/passes.ftl", plugin_impl => "../locales/en-US/plugin_impl.ftl", privacy => "../locales/en-US/privacy.ftl", + save_analysis => "../locales/en-US/save_analysis.ftl", typeck => "../locales/en-US/typeck.ftl", } diff --git a/compiler/rustc_save_analysis/Cargo.toml b/compiler/rustc_save_analysis/Cargo.toml index 15a89d82fa6..181e27f334b 100644 --- a/compiler/rustc_save_analysis/Cargo.toml +++ b/compiler/rustc_save_analysis/Cargo.toml @@ -9,9 +9,11 @@ rustc_middle = { path = "../rustc_middle" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_lexer = { path = "../rustc_lexer" } +rustc_macros = { path = "../rustc_macros" } serde_json = "1" rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_save_analysis/src/errors.rs b/compiler/rustc_save_analysis/src/errors.rs new file mode 100644 index 00000000000..f0ce41d02a6 --- /dev/null +++ b/compiler/rustc_save_analysis/src/errors.rs @@ -0,0 +1,10 @@ +use rustc_macros::SessionDiagnostic; + +use std::path::Path; + +#[derive(SessionDiagnostic)] +#[diag(save_analysis::could_not_open)] +pub(crate) struct CouldNotOpen<'a> { + pub file_name: &'a Path, + pub err: std::io::Error, +} diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index a1a2040bbca..619e083d89a 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -3,11 +3,15 @@ #![feature(let_else)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] +#![feature(never_type)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] mod dump_visitor; mod dumper; #[macro_use] mod span_utils; +mod errors; mod sig; use rustc_ast as ast; @@ -928,7 +932,7 @@ impl<'a> DumpHandler<'a> { info!("Writing output to {}", file_name.display()); let output_file = BufWriter::new(File::create(&file_name).unwrap_or_else(|e| { - sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)) + sess.emit_fatal(errors::CouldNotOpen { file_name: file_name.as_path(), err: e }) })); (output_file, file_name) From c18503f3ff9f81ed3b368246ade73e79dbd53282 Mon Sep 17 00:00:00 2001 From: David Wood Date: Fri, 19 Aug 2022 14:45:54 +0100 Subject: [PATCH 108/115] errors: `IntoDiagnosticArg` for `io::Error`/paths Add impls of `IntoDiagnosticArg` for `std::io::Error`, `std::path::Path` and `std::path::PathBuf`. Signed-off-by: David Wood --- compiler/rustc_errors/src/diagnostic.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 356f9dfdb3b..506198df4d8 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -13,6 +13,7 @@ use rustc_span::{edition::Edition, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; +use std::path::{Path, PathBuf}; /// Error type for `Diagnostic`'s `suggestions` field, indicating that /// `.disable_suggestions()` was called on the `Diagnostic`. @@ -83,6 +84,7 @@ into_diagnostic_arg_using_display!( u64, i128, u128, + std::io::Error, std::num::NonZeroU32, hir::Target, Edition, @@ -124,6 +126,18 @@ impl IntoDiagnosticArg for String { } } +impl<'a> IntoDiagnosticArg for &'a Path { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) + } +} + +impl IntoDiagnosticArg for PathBuf { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Owned(self.display().to_string())) + } +} + impl IntoDiagnosticArg for usize { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Number(self) From 31e39446ec2f251efbcaf9eb22c80e93021f9bbc Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 14 Jul 2022 08:30:38 -0500 Subject: [PATCH 109/115] Stabilize `#![feature(label_break_value)]` # Stabilization proposal The feature was implemented in https://github.com/rust-lang/rust/pull/50045 by est31 and has been in nightly since 2018-05-16 (over 4 years now). There are [no open issues][issue-label] other than the tracking issue. There is a strong consensus that `break` is the right keyword and we should not use `return`. There have been several concerns raised about this feature on the tracking issue (other than the one about tests, which has been fixed, and an interaction with try blocks, which has been fixed). 1. nrc's original comment about cost-benefit analysis: https://github.com/rust-lang/rust/issues/48594#issuecomment-422235234 2. joshtriplett's comments about seeing use cases: https://github.com/rust-lang/rust/issues/48594#issuecomment-422281176 3. withoutboats's comments that Rust does not need more control flow constructs: https://github.com/rust-lang/rust/issues/48594#issuecomment-450050630 Many different examples of code that's simpler using this feature have been provided: - A lexer by rpjohnst which must repeat code without label-break-value: https://github.com/rust-lang/rust/issues/48594#issuecomment-422502014 - A snippet by SergioBenitez which avoids using a new function and adding several new return points to a function: https://github.com/rust-lang/rust/issues/48594#issuecomment-427628251. This particular case would also work if `try` blocks were stabilized (at the cost of making the code harder to optimize). - Several examples by JohnBSmith: https://github.com/rust-lang/rust/issues/48594#issuecomment-434651395 - Several examples by Centril: https://github.com/rust-lang/rust/issues/48594#issuecomment-440154733 - An example by petrochenkov where this is used in the compiler itself to avoid duplicating error checking code: https://github.com/rust-lang/rust/issues/48594#issuecomment-443557569 - Amanieu recently provided another example related to complex conditions, where try blocks would not have helped: https://github.com/rust-lang/rust/issues/48594#issuecomment-1184213006 Additionally, petrochenkov notes that this is strictly more powerful than labelled loops due to macros which accidentally exit a loop instead of being consumed by the macro matchers: https://github.com/rust-lang/rust/issues/48594#issuecomment-450246249 nrc later resolved their concern, mostly because of the aforementioned macro problems. joshtriplett suggested that macros could be able to generate IR directly (https://github.com/rust-lang/rust/issues/48594#issuecomment-451685983) but there are no open RFCs, and the design space seems rather speculative. joshtriplett later resolved his concerns, due to a symmetry between this feature and existing labelled break: https://github.com/rust-lang/rust/issues/48594#issuecomment-632960804 withoutboats has regrettably left the language team. joshtriplett later posted that the lang team would consider starting an FCP given a stabilization report: https://github.com/rust-lang/rust/issues/48594#issuecomment-1111269353 [issue-label]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AF-label_break_value+ ## Report + Feature gate: - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/src/test/ui/feature-gates/feature-gate-label_break_value.rs + Diagnostics: - https://github.com/rust-lang/rust/blob/6b2d3d5f3cd1e553d87b5496632132565b6779d3/compiler/rustc_parse/src/parser/diagnostics.rs#L2629 - https://github.com/rust-lang/rust/blob/f65bf0b2bb1a99f73095c01a118f3c37d3ee614c/compiler/rustc_resolve/src/diagnostics.rs#L749 - https://github.com/rust-lang/rust/blob/f65bf0b2bb1a99f73095c01a118f3c37d3ee614c/compiler/rustc_resolve/src/diagnostics.rs#L1001 - https://github.com/rust-lang/rust/blob/111df9e6eda1d752233482c1309d00d20a4bbf98/compiler/rustc_passes/src/loops.rs#L254 - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/compiler/rustc_parse/src/parser/expr.rs#L2079 - https://github.com/rust-lang/rust/blob/d695a497bbf4b20d2580b75075faa80230d41667/compiler/rustc_parse/src/parser/expr.rs#L1569 + Tests: - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_continue.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_unlabeled_break.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_illegal_uses.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/lint/unused_labels.rs - https://github.com/rust-lang/rust/blob/master/src/test/ui/run-pass/for-loop-while/label_break_value.rs ## Interactions with other features Labels follow the hygiene of local variables. label-break-value is permitted within `try` blocks: ```rust let _: Result<(), ()> = try { 'foo: { Err(())?; break 'foo; } }; ``` label-break-value is disallowed within closures, generators, and async blocks: ```rust 'a: { || break 'a //~^ ERROR use of unreachable label `'a` //~| ERROR `break` inside of a closure } ``` label-break-value is disallowed on [_BlockExpression_]; it can only occur as a [_LoopExpression_]: ```rust fn labeled_match() { match false 'b: { //~ ERROR block label not supported here _ => {} } } macro_rules! m { ($b:block) => { 'lab: $b; //~ ERROR cannot use a `block` macro fragment here unsafe $b; //~ ERROR cannot use a `block` macro fragment here |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here } } fn foo() { m!({}); } ``` [_BlockExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/block-expr.html [_LoopExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/loop-expr.html --- compiler/rustc_ast/src/lib.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 9 --------- .../src/error_codes/E0695.md | 3 --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/active.rs | 2 -- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 4 ---- compiler/rustc_trait_selection/src/lib.rs | 2 +- compiler/rustc_typeck/src/lib.rs | 2 +- library/std/src/lib.rs | 2 +- .../feature-gate-label_break_value.rs | 5 ----- .../feature-gate-label_break_value.stderr | 12 ----------- .../ui/for-loop-while/label_break_value.rs | 1 - .../label_break_value_invalid.rs | 1 - .../label_break_value_invalid.stderr | 6 +++--- src/test/ui/issues/issue-62480.rs | 2 -- src/test/ui/issues/issue-62480.stderr | 4 ++-- .../ui/label/label_break_value_continue.rs | 1 - .../label/label_break_value_continue.stderr | 6 +++--- .../label_break_value_desugared_break.rs | 9 ++++++++- .../label_break_value_illegal_uses.fixed | 1 - .../label/label_break_value_illegal_uses.rs | 1 - .../label_break_value_illegal_uses.stderr | 8 ++++---- .../label_break_value_unlabeled_break.rs | 1 - .../label_break_value_unlabeled_break.stderr | 4 ++-- src/test/ui/lint/unused_labels.rs | 1 - src/test/ui/lint/unused_labels.stderr | 20 +++++++++---------- src/test/ui/macros/stringify.rs | 1 - src/test/ui/parser/bad-interpolated-block.rs | 2 -- .../ui/parser/bad-interpolated-block.stderr | 6 +++--- src/test/ui/parser/labeled-no-colon-expr.rs | 2 -- .../ui/parser/labeled-no-colon-expr.stderr | 16 +++++++-------- .../recover-labeled-non-block-expr.fixed | 1 - .../parser/recover-labeled-non-block-expr.rs | 1 - .../recover-labeled-non-block-expr.stderr | 12 +++++------ .../tests/ui/semicolon_if_nothing_returned.rs | 1 - .../ui/semicolon_if_nothing_returned.stderr | 10 +++++----- src/tools/rustfmt/tests/source/issue-3217.rs | 2 -- src/tools/rustfmt/tests/target/issue-3217.rs | 2 -- 39 files changed, 61 insertions(+), 108 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-label_break_value.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-label_break_value.stderr diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 2426a0cb7dd..f9b4d76f28f 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -13,7 +13,7 @@ #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(if_let_guard)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(slice_internals)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 68fca081018..4ac96ec8b60 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -647,14 +647,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } - ast::ExprKind::Block(_, Some(label)) => { - gate_feature_post!( - &self, - label_break_value, - label.ident.span, - "labels on blocks are unstable" - ); - } _ => {} } visit::walk_expr(self, e) @@ -823,7 +815,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(box_patterns, "box pattern syntax is experimental"); gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental"); gate_all!(try_blocks, "`try` blocks are unstable"); - gate_all!(label_break_value, "labels on blocks are unstable"); gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead"); gate_all!(type_ascription, "type ascription is experimental"); diff --git a/compiler/rustc_error_codes/src/error_codes/E0695.md b/compiler/rustc_error_codes/src/error_codes/E0695.md index 5013e83ca03..577f42ef301 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0695.md +++ b/compiler/rustc_error_codes/src/error_codes/E0695.md @@ -3,7 +3,6 @@ A `break` statement without a label appeared inside a labeled block. Erroneous code example: ```compile_fail,E0695 -# #![feature(label_break_value)] loop { 'a: { break; @@ -14,7 +13,6 @@ loop { Make sure to always label the `break`: ``` -# #![feature(label_break_value)] 'l: loop { 'a: { break 'l; @@ -25,7 +23,6 @@ Make sure to always label the `break`: Or if you want to `break` the labeled block: ``` -# #![feature(label_break_value)] loop { 'a: { break 'a; diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 2d24101b2d5..37b2b0ecad7 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -186,6 +186,8 @@ declare_features! ( /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), + /// Allows `'a: { break 'a; }`. + (accepted, label_break_value, "1.65.0", Some(48594), None), /// Allows `if/while p && let q = r && ...` chains. (accepted, let_chains, "1.64.0", Some(53667), None), /// Allows `break {expr}` with a value inside `loop`s. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1018facebae..22178dd2123 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -420,8 +420,6 @@ declare_features! ( (active, intra_doc_pointers, "1.51.0", Some(80896), None), /// Allows `#[instruction_set(_)]` attribute (active, isa_attribute, "1.48.0", Some(74727), None), - /// Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), /// Allows `let...else` statements. diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 1c515f5ee57..8f02a6cc4a1 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,7 +17,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extend_one)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index df092f55bfa..94923d8ca76 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2075,10 +2075,6 @@ impl<'a> Parser<'a> { } } - if let Some(label) = opt_label { - self.sess.gated_spans.gate(sym::label_break_value, label.ident.span); - } - if self.token.is_whole_block() { self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here") .span_label(lo.to(self.token.span), "the `block` fragment is within this context") diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 9c252fcfe1c..059feb95643 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,7 +16,7 @@ #![feature(control_flow_enum)] #![feature(drain_filter)] #![feature(hash_drain_filter)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(if_let_guard)] #![feature(never_type)] diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 8c6fb6a7718..ffcd74858d3 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -64,7 +64,7 @@ This API is completely unstable and subject to change. #![feature(if_let_guard)] #![feature(is_sorted)] #![feature(iter_intersperse)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5029023121f..5047a58369e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -252,7 +252,7 @@ #![feature(dropck_eyepatch)] #![feature(exhaustive_patterns)] #![feature(intra_doc_pointers)] -#![feature(label_break_value)] +#![cfg_attr(bootstrap, feature(label_break_value))] #![feature(lang_items)] #![feature(let_else)] #![feature(linkage)] diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.rs b/src/test/ui/feature-gates/feature-gate-label_break_value.rs deleted file mode 100644 index 6fc38f45517..00000000000 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn main() { - 'a: { //~ ERROR labels on blocks are unstable - break 'a; - } -} diff --git a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr b/src/test/ui/feature-gates/feature-gate-label_break_value.stderr deleted file mode 100644 index 4b43fdc593f..00000000000 --- a/src/test/ui/feature-gates/feature-gate-label_break_value.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: labels on blocks are unstable - --> $DIR/feature-gate-label_break_value.rs:2:5 - | -LL | 'a: { - | ^^ - | - = note: see issue #48594 for more information - = help: add `#![feature(label_break_value)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/for-loop-while/label_break_value.rs b/src/test/ui/for-loop-while/label_break_value.rs index ca9d71a7a8b..10992c50597 100644 --- a/src/test/ui/for-loop-while/label_break_value.rs +++ b/src/test/ui/for-loop-while/label_break_value.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] #![allow(unused_assignments)] -#![feature(label_break_value)] // Test control flow to follow label_break_value semantics fn label_break(a: bool, b: bool) -> u32 { diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.rs b/src/test/ui/for-loop-while/label_break_value_invalid.rs index 149bf17b83c..fcf2e0f294e 100644 --- a/src/test/ui/for-loop-while/label_break_value_invalid.rs +++ b/src/test/ui/for-loop-while/label_break_value_invalid.rs @@ -1,5 +1,4 @@ #![crate_type = "lib"] -#![feature(label_break_value)] fn lbv_macro_test_hygiene_respected() { macro_rules! mac2 { diff --git a/src/test/ui/for-loop-while/label_break_value_invalid.stderr b/src/test/ui/for-loop-while/label_break_value_invalid.stderr index 7182b8f598f..f6999c4ab11 100644 --- a/src/test/ui/for-loop-while/label_break_value_invalid.stderr +++ b/src/test/ui/for-loop-while/label_break_value_invalid.stderr @@ -1,5 +1,5 @@ error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:7:19 + --> $DIR/label_break_value_invalid.rs:6:19 | LL | break 'a $val; | ^^ undeclared label `'a` @@ -10,7 +10,7 @@ LL | mac2!(2); = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:29:19 + --> $DIR/label_break_value_invalid.rs:28:19 | LL | let x: u8 = mac3!('b: { | -- a label with a similar name is reachable @@ -22,7 +22,7 @@ LL | break 'a 3; | help: try using similarly named label: `'b` error[E0426]: use of undeclared label `'a` - --> $DIR/label_break_value_invalid.rs:34:29 + --> $DIR/label_break_value_invalid.rs:33:29 | LL | let x: u8 = mac3!(break 'a 4); | ^^ undeclared label `'a` diff --git a/src/test/ui/issues/issue-62480.rs b/src/test/ui/issues/issue-62480.rs index 5c3be3e64ee..94a9c2ab8be 100644 --- a/src/test/ui/issues/issue-62480.rs +++ b/src/test/ui/issues/issue-62480.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { // This used to ICE during liveness check because `target_id` passed to // `propagate_through_expr` would be the closure and not the `loop`, which wouldn't be found in diff --git a/src/test/ui/issues/issue-62480.stderr b/src/test/ui/issues/issue-62480.stderr index 17085ef908b..db230537037 100644 --- a/src/test/ui/issues/issue-62480.stderr +++ b/src/test/ui/issues/issue-62480.stderr @@ -1,5 +1,5 @@ error[E0767]: use of unreachable label `'a` - --> $DIR/issue-62480.rs:8:18 + --> $DIR/issue-62480.rs:6:18 | LL | 'a: { | -- unreachable label defined here @@ -9,7 +9,7 @@ LL | || break 'a = note: labels are unreachable through functions, closures, async blocks and modules error[E0267]: `break` inside of a closure - --> $DIR/issue-62480.rs:8:12 + --> $DIR/issue-62480.rs:6:12 | LL | || break 'a | -- ^^^^^^^^ cannot `break` inside of a closure diff --git a/src/test/ui/label/label_break_value_continue.rs b/src/test/ui/label/label_break_value_continue.rs index e0deb30c950..22172f4fd2e 100644 --- a/src/test/ui/label/label_break_value_continue.rs +++ b/src/test/ui/label/label_break_value_continue.rs @@ -1,4 +1,3 @@ -#![feature(label_break_value)] #![allow(unused_labels)] // Simple continue pointing to an unlabeled break should yield in an error diff --git a/src/test/ui/label/label_break_value_continue.stderr b/src/test/ui/label/label_break_value_continue.stderr index 9b8693dc584..284d213d65e 100644 --- a/src/test/ui/label/label_break_value_continue.stderr +++ b/src/test/ui/label/label_break_value_continue.stderr @@ -1,11 +1,11 @@ error[E0695]: unlabeled `continue` inside of a labeled block - --> $DIR/label_break_value_continue.rs:7:9 + --> $DIR/label_break_value_continue.rs:6:9 | LL | continue; | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label error[E0696]: `continue` pointing to a labeled block - --> $DIR/label_break_value_continue.rs:14:9 + --> $DIR/label_break_value_continue.rs:13:9 | LL | / 'b: { LL | | continue 'b; @@ -14,7 +14,7 @@ LL | | } | |_____- labeled block the `continue` points to error[E0695]: unlabeled `continue` inside of a labeled block - --> $DIR/label_break_value_continue.rs:22:13 + --> $DIR/label_break_value_continue.rs:21:13 | LL | continue; | ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label diff --git a/src/test/ui/label/label_break_value_desugared_break.rs b/src/test/ui/label/label_break_value_desugared_break.rs index de883b61111..70227d86933 100644 --- a/src/test/ui/label/label_break_value_desugared_break.rs +++ b/src/test/ui/label/label_break_value_desugared_break.rs @@ -1,5 +1,5 @@ // compile-flags: --edition 2018 -#![feature(label_break_value, try_blocks)] +#![feature(try_blocks)] // run-pass fn main() { @@ -9,4 +9,11 @@ fn main() { break 'foo; } }; + + 'foo: { + let _: Result<(), ()> = try { + Err(())?; + break 'foo; + }; + } } diff --git a/src/test/ui/label/label_break_value_illegal_uses.fixed b/src/test/ui/label/label_break_value_illegal_uses.fixed index c1d2023a216..fb75276b4f4 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.fixed +++ b/src/test/ui/label/label_break_value_illegal_uses.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] // These are forbidden occurrences of label-break-value diff --git a/src/test/ui/label/label_break_value_illegal_uses.rs b/src/test/ui/label/label_break_value_illegal_uses.rs index 5b20c95e581..3cbf41380e6 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.rs +++ b/src/test/ui/label/label_break_value_illegal_uses.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] // These are forbidden occurrences of label-break-value diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr index 24b733fec53..15016ffd54a 100644 --- a/src/test/ui/label/label_break_value_illegal_uses.stderr +++ b/src/test/ui/label/label_break_value_illegal_uses.stderr @@ -1,23 +1,23 @@ error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:8:12 + --> $DIR/label_break_value_illegal_uses.rs:7:12 | LL | unsafe 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:12:13 + --> $DIR/label_break_value_illegal_uses.rs:11:13 | LL | if true 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:16:21 + --> $DIR/label_break_value_illegal_uses.rs:15:21 | LL | if true {} else 'b: {} | ^^^ not supported here error: block label not supported here - --> $DIR/label_break_value_illegal_uses.rs:20:17 + --> $DIR/label_break_value_illegal_uses.rs:19:17 | LL | match false 'b: { | ^^^ not supported here diff --git a/src/test/ui/label/label_break_value_unlabeled_break.rs b/src/test/ui/label/label_break_value_unlabeled_break.rs index fa0c70edc78..2a4f5d57493 100644 --- a/src/test/ui/label/label_break_value_unlabeled_break.rs +++ b/src/test/ui/label/label_break_value_unlabeled_break.rs @@ -1,4 +1,3 @@ -#![feature(label_break_value)] #![allow(unused_labels)] // Simple unlabeled break should yield in an error diff --git a/src/test/ui/label/label_break_value_unlabeled_break.stderr b/src/test/ui/label/label_break_value_unlabeled_break.stderr index 0c4f573d27d..a2ccd27b836 100644 --- a/src/test/ui/label/label_break_value_unlabeled_break.stderr +++ b/src/test/ui/label/label_break_value_unlabeled_break.stderr @@ -1,11 +1,11 @@ error[E0695]: unlabeled `break` inside of a labeled block - --> $DIR/label_break_value_unlabeled_break.rs:7:9 + --> $DIR/label_break_value_unlabeled_break.rs:6:9 | LL | break; | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label error[E0695]: unlabeled `break` inside of a labeled block - --> $DIR/label_break_value_unlabeled_break.rs:15:13 + --> $DIR/label_break_value_unlabeled_break.rs:14:13 | LL | break; | ^^^^^ `break` statements that would diverge to or through a labeled block need to bear a label diff --git a/src/test/ui/lint/unused_labels.rs b/src/test/ui/lint/unused_labels.rs index 8a3568f65f6..87a5392fd30 100644 --- a/src/test/ui/lint/unused_labels.rs +++ b/src/test/ui/lint/unused_labels.rs @@ -4,7 +4,6 @@ // check-pass -#![feature(label_break_value)] #![warn(unused_labels)] fn main() { diff --git a/src/test/ui/lint/unused_labels.stderr b/src/test/ui/lint/unused_labels.stderr index 85adc9ab3bf..846da792bed 100644 --- a/src/test/ui/lint/unused_labels.stderr +++ b/src/test/ui/lint/unused_labels.stderr @@ -1,5 +1,5 @@ warning: label name `'many_used_shadowed` shadows a label name that is already in scope - --> $DIR/unused_labels.rs:62:9 + --> $DIR/unused_labels.rs:61:9 | LL | 'many_used_shadowed: for _ in 0..10 { | ------------------- first declared here @@ -8,55 +8,55 @@ LL | 'many_used_shadowed: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope warning: unused label - --> $DIR/unused_labels.rs:11:5 + --> $DIR/unused_labels.rs:10:5 | LL | 'unused_while_label: while 0 == 0 { | ^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/unused_labels.rs:8:9 + --> $DIR/unused_labels.rs:7:9 | LL | #![warn(unused_labels)] | ^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:16:5 + --> $DIR/unused_labels.rs:15:5 | LL | 'unused_while_let_label: while let Some(_) = opt { | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:20:5 + --> $DIR/unused_labels.rs:19:5 | LL | 'unused_for_label: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:36:9 + --> $DIR/unused_labels.rs:35:9 | LL | 'unused_loop_label_inner_2: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:42:5 + --> $DIR/unused_labels.rs:41:5 | LL | 'unused_loop_label_outer_3: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:60:5 + --> $DIR/unused_labels.rs:59:5 | LL | 'many_used_shadowed: for _ in 0..10 { | ^^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:72:5 + --> $DIR/unused_labels.rs:71:5 | LL | 'unused_loop_label: loop { | ^^^^^^^^^^^^^^^^^^ warning: unused label - --> $DIR/unused_labels.rs:78:5 + --> $DIR/unused_labels.rs:77:5 | LL | 'unused_block_label: { | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index 082c1abb8f2..dd159cb5b6e 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -9,7 +9,6 @@ #![feature(decl_macro)] #![feature(generators)] #![feature(half_open_range_patterns)] -#![feature(label_break_value)] #![feature(more_qualified_paths)] #![feature(raw_ref_op)] #![feature(trait_alias)] diff --git a/src/test/ui/parser/bad-interpolated-block.rs b/src/test/ui/parser/bad-interpolated-block.rs index 38d53a14bc0..c6d7ae383b2 100644 --- a/src/test/ui/parser/bad-interpolated-block.rs +++ b/src/test/ui/parser/bad-interpolated-block.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() {} macro_rules! m { diff --git a/src/test/ui/parser/bad-interpolated-block.stderr b/src/test/ui/parser/bad-interpolated-block.stderr index 77933b1bcec..2a0999afdfa 100644 --- a/src/test/ui/parser/bad-interpolated-block.stderr +++ b/src/test/ui/parser/bad-interpolated-block.stderr @@ -1,5 +1,5 @@ error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:7:15 + --> $DIR/bad-interpolated-block.rs:5:15 | LL | 'lab: $b; | ------^^ @@ -12,7 +12,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:8:16 + --> $DIR/bad-interpolated-block.rs:6:16 | LL | unsafe $b; | -------^^ @@ -25,7 +25,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use a `block` macro fragment here - --> $DIR/bad-interpolated-block.rs:9:23 + --> $DIR/bad-interpolated-block.rs:7:23 | LL | |x: u8| -> () $b; | ^^ the `block` fragment is within this context diff --git a/src/test/ui/parser/labeled-no-colon-expr.rs b/src/test/ui/parser/labeled-no-colon-expr.rs index db9ef52c1ae..d9ebd7473bc 100644 --- a/src/test/ui/parser/labeled-no-colon-expr.rs +++ b/src/test/ui/parser/labeled-no-colon-expr.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { 'l0 while false {} //~ ERROR labeled expression must be followed by `:` 'l1 for _ in 0..1 {} //~ ERROR labeled expression must be followed by `:` diff --git a/src/test/ui/parser/labeled-no-colon-expr.stderr b/src/test/ui/parser/labeled-no-colon-expr.stderr index a258bd3ccde..62288fe152d 100644 --- a/src/test/ui/parser/labeled-no-colon-expr.stderr +++ b/src/test/ui/parser/labeled-no-colon-expr.stderr @@ -1,5 +1,5 @@ error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:4:5 + --> $DIR/labeled-no-colon-expr.rs:2:5 | LL | 'l0 while false {} | ----^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | 'l0 while false {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:5:5 + --> $DIR/labeled-no-colon-expr.rs:3:5 | LL | 'l1 for _ in 0..1 {} | ----^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL | 'l1 for _ in 0..1 {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:6:5 + --> $DIR/labeled-no-colon-expr.rs:4:5 | LL | 'l2 loop {} | ----^^^^^^^ @@ -32,7 +32,7 @@ LL | 'l2 loop {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:7:5 + --> $DIR/labeled-no-colon-expr.rs:5:5 | LL | 'l3 {} | ----^^ @@ -43,7 +43,7 @@ LL | 'l3 {} = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/labeled-no-colon-expr.rs:8:9 + --> $DIR/labeled-no-colon-expr.rs:6:9 | LL | 'l4 0; | ^ expected `while`, `for`, `loop` or `{` after a label @@ -55,7 +55,7 @@ LL + 0; | error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:8:9 + --> $DIR/labeled-no-colon-expr.rs:6:9 | LL | 'l4 0; | ----^ @@ -66,7 +66,7 @@ LL | 'l4 0; = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them error: cannot use a `block` macro fragment here - --> $DIR/labeled-no-colon-expr.rs:13:17 + --> $DIR/labeled-no-colon-expr.rs:11:17 | LL | 'l5 $b; | ----^^ @@ -79,7 +79,7 @@ LL | m!({}); = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: labeled expression must be followed by `:` - --> $DIR/labeled-no-colon-expr.rs:16:8 + --> $DIR/labeled-no-colon-expr.rs:14:8 | LL | 'l5 $b; | ---- help: add `:` after the label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.fixed b/src/test/ui/parser/recover-labeled-non-block-expr.fixed index fe546a71971..c2e76444d11 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.fixed +++ b/src/test/ui/parser/recover-labeled-non-block-expr.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] fn main() { let _ = 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.rs b/src/test/ui/parser/recover-labeled-non-block-expr.rs index 35862e2eef9..fc11c646a8c 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.rs +++ b/src/test/ui/parser/recover-labeled-non-block-expr.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(label_break_value)] fn main() { let _ = 'label: 1 + 1; //~ ERROR expected `while`, `for`, `loop` or `{` after a label diff --git a/src/test/ui/parser/recover-labeled-non-block-expr.stderr b/src/test/ui/parser/recover-labeled-non-block-expr.stderr index 04fc1203e90..d66ce695090 100644 --- a/src/test/ui/parser/recover-labeled-non-block-expr.stderr +++ b/src/test/ui/parser/recover-labeled-non-block-expr.stderr @@ -1,5 +1,5 @@ error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:4:21 + --> $DIR/recover-labeled-non-block-expr.rs:3:21 | LL | let _ = 'label: 1 + 1; | ^ expected `while`, `for`, `loop` or `{` after a label @@ -11,7 +11,7 @@ LL + let _ = 1 + 1; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:6:13 + --> $DIR/recover-labeled-non-block-expr.rs:5:13 | LL | 'label: match () { () => {}, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -23,7 +23,7 @@ LL + match () { () => {}, }; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:7:13 + --> $DIR/recover-labeled-non-block-expr.rs:6:13 | LL | 'label: match () { () => break 'label, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -34,7 +34,7 @@ LL | 'label: { match () { () => break 'label, } }; | + + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:9:13 + --> $DIR/recover-labeled-non-block-expr.rs:8:13 | LL | 'label: match () { () => 'lp: loop { break 'lp 0 }, }; | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -45,7 +45,7 @@ LL | 'label: { match () { () => 'lp: loop { break 'lp 0 }, } }; | + + error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:12:22 + --> $DIR/recover-labeled-non-block-expr.rs:11:22 | LL | let _i = 'label: match x { | ^^^^^ expected `while`, `for`, `loop` or `{` after a label @@ -60,7 +60,7 @@ LL ~ } }; | error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/recover-labeled-non-block-expr.rs:26:24 + --> $DIR/recover-labeled-non-block-expr.rs:25:24 | LL | let _val = 'label: (1, if other == 3 { break 'label (2, 3) } else { other }); | ^ expected `while`, `for`, `loop` or `{` after a label diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs index 91916e7480f..c3235f06779 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs @@ -1,6 +1,5 @@ #![warn(clippy::semicolon_if_nothing_returned)] #![allow(clippy::redundant_closure)] -#![feature(label_break_value)] #![feature(let_else)] fn get_unit() {} diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr index 41d2c1cfb87..78813e7cc1c 100644 --- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr +++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr @@ -1,5 +1,5 @@ error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:10:5 + --> $DIR/semicolon_if_nothing_returned.rs:9:5 | LL | println!("Hello") | ^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("Hello");` @@ -7,25 +7,25 @@ LL | println!("Hello") = note: `-D clippy::semicolon-if-nothing-returned` implied by `-D warnings` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:14:5 + --> $DIR/semicolon_if_nothing_returned.rs:13:5 | LL | get_unit() | ^^^^^^^^^^ help: add a `;` here: `get_unit();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:19:5 + --> $DIR/semicolon_if_nothing_returned.rs:18:5 | LL | y = x + 1 | ^^^^^^^^^ help: add a `;` here: `y = x + 1;` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:25:9 + --> $DIR/semicolon_if_nothing_returned.rs:24:9 | LL | hello() | ^^^^^^^ help: add a `;` here: `hello();` error: consider adding a `;` to the last statement for consistent formatting - --> $DIR/semicolon_if_nothing_returned.rs:36:9 + --> $DIR/semicolon_if_nothing_returned.rs:35:9 | LL | ptr::drop_in_place(s.as_mut_ptr()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());` diff --git a/src/tools/rustfmt/tests/source/issue-3217.rs b/src/tools/rustfmt/tests/source/issue-3217.rs index 176c702002a..e68ca2c5907 100644 --- a/src/tools/rustfmt/tests/source/issue-3217.rs +++ b/src/tools/rustfmt/tests/source/issue-3217.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { let mut res = 0; 's_39: { if res == 0i32 { println!("Hello, world!"); } } diff --git a/src/tools/rustfmt/tests/target/issue-3217.rs b/src/tools/rustfmt/tests/target/issue-3217.rs index 5121320a097..403bf4c340a 100644 --- a/src/tools/rustfmt/tests/target/issue-3217.rs +++ b/src/tools/rustfmt/tests/target/issue-3217.rs @@ -1,5 +1,3 @@ -#![feature(label_break_value)] - fn main() { let mut res = 0; 's_39: { 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 110/115] 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 d966ea323eb..ba9e82447dd 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 111/115] 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 ba9e82447dd..dfde9792046 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 112/115] 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 9713f13ccb3..6c5043bb6f8 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 1405265959d..14f2746ecb1 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 113/115] 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 333f85f6d62..7f8d6ad1288 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 114/115] 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 dc83b10958e..e21397cece8 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(); From 5bac3d71d34813286d51e319f3c8ed95f19d4dc7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 24 Aug 2022 09:01:35 -0700 Subject: [PATCH 115/115] rustdoc: ayu code color selector more specific According to https://github.com/rust-lang/rust/pull/100960#issuecomment-1225970579, this selector is only really intended to apply to item info. However, it's so broad that it's hard to tell when it deliberately applies vs where it accidentally applies. --- src/librustdoc/html/static/css/themes/ayu.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index e7ccd402dd0..63009006b3f 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -47,7 +47,7 @@ h4 { .docblock pre > code, pre > code { color: #e6e1cf; } -span code { +.item-info code { color: #e6e1cf; } .docblock a > code {