Importing rustc-1.58.0
Bug: 213921092
Test: ./build.py --lto=thin
Change-Id: Icc9fe2d5bc3327afd20177fc973a6e44941f787f
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
}