Importing rustc-1.58.0 Bug: 213921092 Test: ./build.py --lto=thin Change-Id: Icc9fe2d5bc3327afd20177fc973a6e44941f787f
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index a6a553b..5f3f533 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@ bitflags = "1.0" cstr = "0.2" libc = "0.2" -measureme = "9.1.0" +measureme = "10.0.0" snap = "1" tracing = "0.1" rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index dca9c1f..07adfff 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -1,7 +1,6 @@ use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, AttributePlace}; -use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -53,15 +52,10 @@ } fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool { - // LLVM prior to version 12 has known miscompiles in the presence of - // noalias attributes (see #54878). Only enable mutable noalias by - // default for versions we believe to be safe. - cx.tcx - .sess - .opts - .debugging_opts - .mutable_noalias - .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0)) + // LLVM prior to version 12 had known miscompiles in the presence of + // noalias attributes (see #54878), but we don't support earlier + // versions at all anymore. We now enable mutable noalias by default. + cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(true) } impl ArgAttributesExt for ArgAttributes { @@ -613,7 +607,7 @@ fn_abi.apply_attrs_callsite(self, callsite) } - fn get_param(&self, index: usize) -> Self::Value { + fn get_param(&mut self, index: usize) -> Self::Value { llvm::get_param(self.llfn(), index as c_uint) } }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 341a888..02096f4 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::{bug, span_bug}; +use rustc_middle::{bug, span_bug, ty::Instance}; use rustc_span::{Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -120,6 +120,7 @@ operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, line_spans: &[Span], + instance: Instance<'_>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -135,7 +136,10 @@ let is_target_supported = |reg_class: InlineAsmRegClass| { for &(_, feature) in reg_class.supported_types(asm_arch) { if let Some(feature) = feature { - if self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id()); + let feature_name = Symbol::intern(feature); + if self.tcx.sess.target_features.contains(&feature_name) + || codegen_fn_attrs.target_features.contains(&feature_name) { return true; } @@ -316,7 +320,7 @@ InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::S390x => {} InlineAsmArch::SpirV => {} - InlineAsmArch::Wasm32 => {} + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {} InlineAsmArch::Bpf => {} } }
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 659cf9e..8e6329a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -12,7 +12,7 @@ use rustc_session::config::OptLevel; use rustc_session::Session; use rustc_target::spec::abi::Abi; -use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType}; +use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use crate::attributes; use crate::llvm::AttributePlace::Function; @@ -161,6 +161,17 @@ } } +fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { + let sspattr = match cx.sess().stack_protector() { + StackProtector::None => return, + StackProtector::All => Attribute::StackProtectReq, + StackProtector::Strong => Attribute::StackProtectStrong, + StackProtector::Basic => Attribute::StackProtect, + }; + + sspattr.apply_llfn(Function, llfn) +} + pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( @@ -271,6 +282,7 @@ set_frame_pointer_type(cx, llfn); set_instrument_function(cx, llfn); set_probestack(cx, llfn); + set_stackprotector(cx, llfn); if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { Attribute::Cold.apply_llfn(Function, llfn);
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index b6d682f..6d2ad70 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -17,6 +17,7 @@ }; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; @@ -53,6 +54,7 @@ output: &Path, dwo_output: Option<&Path>, file_type: llvm::FileType, + self_profiler_ref: &SelfProfilerRef, ) -> Result<(), FatalError> { unsafe { let output_c = path_to_c_string(output); @@ -76,6 +78,19 @@ file_type, ) }; + + // Record artifact sizes for self-profiling + if result == llvm::LLVMRustResult::Success { + let artifact_kind = match file_type { + llvm::FileType::ObjectFile => "object_file", + llvm::FileType::AssemblyFile => "assembly_file", + }; + record_artifact_size(self_profiler_ref, artifact_kind, output); + if let Some(dwo_file) = dwo_output { + record_artifact_size(self_profiler_ref, "dwo_file", dwo_file); + } + } + result.into_result().map_err(|()| { let msg = format!("could not write output to {}", output.display()); llvm_err(handler, &msg) @@ -161,6 +176,7 @@ let ffunction_sections = sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.function_sections); let fdata_sections = ffunction_sections; + let funique_section_names = !sess.opts.debugging_opts.no_unique_section_names; let code_model = to_llvm_code_model(sess.code_model()); @@ -205,6 +221,7 @@ use_softfp, ffunction_sections, fdata_sections, + funique_section_names, trap_unreachable, singlethread, asm_comments, @@ -284,7 +301,7 @@ cookie = 0; } let level = match level { - llvm::DiagnosticLevel::Error => Level::Error, + llvm::DiagnosticLevel::Error => Level::Error { lint: false }, llvm::DiagnosticLevel::Warning => Level::Warning, llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; @@ -746,6 +763,14 @@ let thin = ThinBuffer::new(llmod); let data = thin.data(); + if let Some(bitcode_filename) = bc_out.file_name() { + cgcx.prof.artifact_size( + "llvm_bitcode", + bitcode_filename.to_string_lossy(), + data.len() as u64, + ); + } + if config.emit_bc || config.emit_obj == EmitObj::Bitcode { let _timer = cgcx.prof.generic_activity_with_arg( "LLVM_module_codegen_emit_bitcode", @@ -806,6 +831,11 @@ } let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback); + + if result == llvm::LLVMRustResult::Success { + record_artifact_size(&cgcx.prof, "llvm_ir", &out); + } + result.into_result().map_err(|()| { let msg = format!("failed to write LLVM IR to {}", out.display()); llvm_err(diag_handler, &msg) @@ -836,6 +866,7 @@ &path, None, llvm::FileType::AssemblyFile, + &cgcx.prof, ) })?; } @@ -869,6 +900,7 @@ &obj_out, dwo_out, llvm::FileType::ObjectFile, + &cgcx.prof, ) })?; } @@ -1125,3 +1157,19 @@ symbol_name.starts_with(b"__llvm_profile_") } } + +fn record_artifact_size( + self_profiler_ref: &SelfProfilerRef, + artifact_kind: &'static str, + path: &Path, +) { + // Don't stat the file if we are not going to record its size. + if !self_profiler_ref.enabled() { + return; + } + + if let Some(artifact_name) = path.file_name() { + let file_size = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0); + self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size); + } +}
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 3026c2f..8766cae 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -113,8 +113,13 @@ let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); - let (module, _) = - tcx.dep_graph.with_task(dep_node, tcx, cgu_name, module_codegen, dep_graph::hash_result); + let (module, _) = tcx.dep_graph.with_task( + dep_node, + tcx, + cgu_name, + module_codegen, + Some(dep_graph::hash_result), + ); let time_to_codegen = start_time.elapsed(); // We assume that the cost to run LLVM on a CGU is proportional to
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index d5deacf..ff88302 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -604,6 +604,32 @@ } } + fn type_metadata(&mut self, function: &'ll Value, typeid: String) { + let typeid_metadata = self.typeid_metadata(typeid); + let v = [self.const_usize(0), typeid_metadata]; + unsafe { + llvm::LLVMGlobalSetMetadata( + function, + llvm::MD_type as c_uint, + llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext( + self.cx.llcx, + v.as_ptr(), + v.len() as c_uint, + )), + ) + } + } + + fn typeid_metadata(&mut self, typeid: String) -> Self::Value { + unsafe { + llvm::LLVMMDStringInContext( + self.cx.llcx, + typeid.as_ptr() as *const c_char, + typeid.as_bytes().len() as c_uint, + ) + } + } + fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } @@ -705,7 +731,7 @@ } fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { + if !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); @@ -717,7 +743,7 @@ } fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> { - if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() { + if !self.fptoint_sat_broken_in_llvm() { let src_ty = self.cx.val_ty(val); let float_width = self.cx.float_width(src_ty); let int_width = self.cx.int_width(dest_ty); @@ -743,7 +769,7 @@ // we like. To ensure that LLVM picks the right instruction we choose // the raw wasm intrinsic functions which avoid LLVM inserting all the // other control flow automatically. - if self.sess().target.arch == "wasm32" { + if self.sess().target.is_like_wasm { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -765,7 +791,7 @@ fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { // see `fptoui` above for why wasm is different here - if self.sess().target.arch == "wasm32" { + if self.sess().target.is_like_wasm { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 1afa6f0..b154ced 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -490,7 +490,7 @@ // Wasm statics with custom link sections get special treatment as they // go into custom sections of the wasm executable. - if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if self.tcx.sess.target.is_like_wasm { if let Some(section) = attrs.link_section { let section = llvm::LLVMMDStringInContext( self.llcx,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 257a0ac..613a8df 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -134,9 +134,6 @@ let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let mut target_data_layout = sess.target.data_layout.clone(); - if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" { - target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", ""); - } if llvm_util::get_version() < (13, 0, 0) { if sess.target.arch == "powerpc64" { target_data_layout = target_data_layout.replace("-S128", ""); @@ -221,6 +218,15 @@ llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1); } + if sess.is_sanitizer_cfi_enabled() { + // FIXME(rcvalle): Add support for non canonical jump tables. + let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast(); + // FIXME(rcvalle): Add it with Override behavior flag--LLVMRustAddModuleFlag adds it with + // Warning behavior flag. Add support for specifying the behavior flag to + // LLVMRustAddModuleFlag. + llvm::LLVMRustAddModuleFlag(llmod, canonical_jump_tables, 1); + } + // Control Flow Guard is currently only supported by the MSVC linker on Windows. if sess.target.is_like_msvc { match sess.opts.cg.control_flow_guard { @@ -591,7 +597,6 @@ ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); - ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); @@ -779,6 +784,8 @@ ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void); } + ifn!("llvm.type.test", fn(i8p, self.type_metadata()) -> i1); + if self.sess().opts.debuginfo != DebugInfo::None { ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void); ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 1f1bd73..2a6bf7d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -322,7 +322,7 @@ type_names::push_item_name(self.tcx(), def_id, false, &mut name); // Find the enclosing function, in case this is a closure. - let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id); + let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id); // Get_template_parameters() will append a `<...>` clause to the function // name if necessary.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c43141c..a7e34b0 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; -use rustc_target::abi::{self, HasDataLayout, Primitive}; +use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; @@ -392,13 +392,12 @@ self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)]) } - fn sideeffect(&mut self) { - // This kind of check would make a ton of sense in the caller, but currently the only - // caller of this function is in `rustc_codegen_ssa`, which is agnostic to whether LLVM - // codegen backend being used, and so is unable to check the LLVM version. - if unsafe { llvm::LLVMRustVersionMajor() } < 12 { - self.call_intrinsic("llvm.sideeffect", &[]); - } + fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value { + // Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time + // optimization pass replaces calls to this intrinsic with code to test type membership. + let i8p_ty = self.type_i8p(); + let bitcast = self.bitcast(pointer, i8p_ty); + self.call_intrinsic("llvm.type.test", &[bitcast, typeid]) } fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value { @@ -849,28 +848,39 @@ let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - let in_ty = arg_tys[0]; - let m_len = match in_ty.kind() { - // Note that this `.unwrap()` crashes for isize/usize, that's sort - // of intentional as there's not currently a use case for that. - ty::Int(i) => i.bit_width().unwrap(), - ty::Uint(i) => i.bit_width().unwrap(), - _ => return_error!("`{}` is not an integral type", in_ty), - }; require_simd!(arg_tys[1], "argument"); - let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); - require!( - // Allow masks for vectors with fewer than 8 elements to be - // represented with a u8 or i8. - m_len == v_len || (m_len == 8 && v_len < 8), - "mismatched lengths: mask length `{}` != other vector length `{}`", - m_len, - v_len - ); + let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); + + let expected_int_bits = (len.max(8) - 1).next_power_of_two(); + let expected_bytes = len / 8 + ((len % 8 > 0) as u64); + + let mask_ty = arg_tys[0]; + let mask = match mask_ty.kind() { + ty::Int(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(), + ty::Array(elem, len) + if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all()) + == Some(expected_bytes) => + { + let place = PlaceRef::alloca(bx, args[0].layout); + args[0].val.store(bx, place); + let int_ty = bx.type_ix(expected_bytes * 8); + let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); + bx.load(int_ty, ptr, Align::ONE) + } + _ => return_error!( + "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`", + mask_ty, + expected_int_bits, + expected_bytes + ), + }; + let i1 = bx.type_i1(); - let im = bx.type_ix(v_len); - let i1xn = bx.type_vector(i1, v_len); - let m_im = bx.trunc(args[0].immediate(), im); + let im = bx.type_ix(len); + let i1xn = bx.type_vector(i1, len); + let m_im = bx.trunc(mask, im); let m_i1s = bx.bitcast(m_im, i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } @@ -1048,16 +1058,16 @@ if name == sym::simd_bitmask { // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a - // vector mask and returns an unsigned integer containing the most - // significant bit (MSB) of each lane. - - // If the vector has less than 8 lanes, a u8 is returned with zeroed - // trailing bits. + // vector mask and returns the most significant bit (MSB) of each lane in the form + // of either: + // * an unsigned integer + // * an array of `u8` + // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits. + // + // The bit order of the result depends on the byte endianness, LSB-first for little + // endian and MSB-first for big endian. let expected_int_bits = in_len.max(8); - match ret_ty.kind() { - ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (), - _ => return_error!("bitmask `{}`, expected `u{}`", ret_ty, expected_int_bits), - } + let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64); // Integer vector <i{in_bitwidth} x in_len>: let (i_xn, in_elem_bitwidth) = match in_elem.kind() { @@ -1087,8 +1097,34 @@ let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len)); // Bitcast <i1 x N> to iN: let i_ = bx.bitcast(i1xn, bx.type_ix(in_len)); - // Zero-extend iN to the bitmask type: - return Ok(bx.zext(i_, bx.type_ix(expected_int_bits))); + + match ret_ty.kind() { + ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => { + // Zero-extend iN to the bitmask type: + return Ok(bx.zext(i_, bx.type_ix(expected_int_bits))); + } + ty::Array(elem, len) + if matches!(elem.kind(), ty::Uint(ty::UintTy::U8)) + && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all()) + == Some(expected_bytes) => + { + // Zero-extend iN to the array lengh: + let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8)); + + // Convert the integer to a byte array + let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE); + bx.store(ze, ptr, Align::ONE); + let array_ty = bx.type_array(bx.type_i8(), expected_bytes); + let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty)); + return Ok(bx.load(array_ty, ptr, Align::ONE)); + } + _ => return_error!( + "cannot return `{}`, expected `u{}` or `[u8; {}]`", + ret_ty, + expected_int_bits, + expected_bytes + ), + } } fn simd_simple_float_intrinsic(
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 8f4d79e..c66d7d8 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -76,6 +76,27 @@ #[derive(Clone)] pub struct LlvmCodegenBackend(()); +struct TimeTraceProfiler { + enabled: bool, +} + +impl TimeTraceProfiler { + fn new(enabled: bool) -> Self { + if enabled { + unsafe { llvm::LLVMTimeTraceProfilerInitialize() } + } + TimeTraceProfiler { enabled } + } +} + +impl Drop for TimeTraceProfiler { + fn drop(&mut self) { + if self.enabled { + unsafe { llvm::LLVMTimeTraceProfilerFinishThread() } + } + } +} + impl ExtraBackendMethods for LlvmCodegenBackend { fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm { ModuleLlvm::new_metadata(tcx, mod_name) @@ -119,6 +140,34 @@ fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> { llvm_util::tune_cpu(sess) } + + fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + std::thread::spawn(move || { + let _profiler = TimeTraceProfiler::new(time_trace); + f() + }) + } + + fn spawn_named_thread<F, T>( + time_trace: bool, + name: String, + f: F, + ) -> std::io::Result<std::thread::JoinHandle<T>> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + std::thread::Builder::new().name(name).spawn(move || { + let _profiler = TimeTraceProfiler::new(time_trace); + f() + }) + } } impl WriteBackendMethods for LlvmCodegenBackend { @@ -239,6 +288,31 @@ } println!(); } + PrintRequest::StackProtectorStrategies => { + println!( + r#"Available stack protector strategies: + all + Generate stack canaries in all functions. + + strong + Generate stack canaries in a function if it either: + - has a local variable of `[T; N]` type, regardless of `T` and `N` + - takes the address of a local variable. + + (Note that a local variable being borrowed is not equivalent to its + address being taken: e.g. some borrows may be removed by optimization, + while by-value argument passing may be implemented with reference to a + local stack variable in the ABI.) + + basic + Generate stack canaries in functions with: + - local variables of `[T; N]` type, where `T` is byte-sized and `N` > 8. + + none + Do not generate stack canaries. +"# + ); + } req => llvm_util::print(req, sess), } }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4c9ae4f..1d255c0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -166,6 +166,9 @@ InaccessibleMemOnly = 27, SanitizeHWAddress = 28, WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, } /// LLVMIntPredicate @@ -416,6 +419,7 @@ MD_nontemporal = 9, MD_mem_parallel_loop_access = 10, MD_nonnull = 11, + MD_type = 19, } /// LLVMRustAsmDialect @@ -1002,6 +1006,8 @@ pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); + pub fn LLVMGlobalSetMetadata(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); + pub fn LLVMValueAsMetadata(Node: &'a Value) -> &Metadata; // Operations on constants of any type pub fn LLVMConstNull(Ty: &Type) -> &Value; @@ -1734,6 +1740,8 @@ pub fn LLVMTimeTraceProfilerInitialize(); + pub fn LLVMTimeTraceProfilerFinishThread(); + pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char); pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>); @@ -1770,7 +1778,7 @@ pub fn LLVMDisposeMessage(message: *mut c_char); - pub fn LLVMStartMultithreaded() -> Bool; + pub fn LLVMIsMultithreaded() -> Bool; /// Returns a string describing the last error caused by an LLVMRust* call. pub fn LLVMRustGetLastError() -> *const c_char; @@ -2187,6 +2195,7 @@ UseSoftFP: bool, FunctionSections: bool, DataSections: bool, + UniqueSectionNames: bool, TrapUnreachable: bool, Singlethread: bool, AsmComments: bool,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c2136f1..3393c9b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -17,35 +17,25 @@ use std::ptr; use std::slice; use std::str; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; -static POISONED: AtomicBool = AtomicBool::new(false); static INIT: Once = Once::new(); pub(crate) fn init(sess: &Session) { unsafe { // Before we touch LLVM, make sure that multithreading is enabled. + if llvm::LLVMIsMultithreaded() != 1 { + bug!("LLVM compiled without support for threads"); + } INIT.call_once(|| { - if llvm::LLVMStartMultithreaded() != 1 { - // use an extra bool to make sure that all future usage of LLVM - // cannot proceed despite the Once not running more than once. - POISONED.store(true, Ordering::SeqCst); - } - configure_llvm(sess); }); - - if POISONED.load(Ordering::SeqCst) { - bug!("couldn't enable multi-threaded LLVM"); - } } } fn require_inited() { - INIT.call_once(|| bug!("llvm is not initialized")); - if POISONED.load(Ordering::SeqCst) { - bug!("couldn't enable multi-threaded LLVM"); + if !INIT.is_completed() { + bug!("LLVM is not initialized"); } } @@ -85,7 +75,9 @@ if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - if !sess.opts.debugging_opts.no_generate_arange_section { + if sess.target.generate_arange_section + && !sess.opts.debugging_opts.no_generate_arange_section + { add("-generate-arange-section", false); } @@ -95,8 +87,7 @@ // Ref: // - https://github.com/rust-lang/rust/issues/85351 // - https://reviews.llvm.org/D103167 - let llvm_version = llvm_util::get_version(); - if llvm_version >= (11, 0, 0) && llvm_version < (13, 0, 0) { + if llvm_util::get_version() < (13, 0, 0) { add("-enable-machine-outliner=never", false); } @@ -124,11 +115,6 @@ } if sess.opts.debugging_opts.llvm_time_trace { - // time-trace is not thread safe and running it in parallel will cause seg faults. - if !sess.opts.debugging_opts.no_parallel_llvm { - bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm") - } - llvm::LLVMTimeTraceProfilerInitialize(); } @@ -191,6 +177,7 @@ ("aarch64", "dpb2") => vec!["ccdp"], ("aarch64", "frintts") => vec!["fptoint"], ("aarch64", "fcma") => vec!["complxnum"], + ("aarch64", "pmuv3") => vec!["perfmon"], (_, s) => vec![s], } } @@ -416,14 +403,6 @@ // -Ctarget-features features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter)); - // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12. - if get_version() >= (12, 0, 0) - && sess.target.llvm_target.contains("aarch64-unknown-linux") - && sess.target.llvm_target != "aarch64-unknown-linux-musl" - { - features.push("+outline-atomics".to_string()); - } - features }