Auto merge of #77004 - RalfJung:rollup-usac4nv, r=RalfJung
Rollup of 13 pull requests Successful merges: - #76135 (Stabilize some Option methods as const) - #76628 (Add sample defaults for config.toml ) - #76846 (Avoiding unnecesary allocations at rustc_errors) - #76867 (Use intra-doc links in core/src/iter when possible) - #76868 (Finish moving to intra doc links for std::sync) - #76872 (Remove DeclareMethods) - #76936 (Add non-`unsafe` `.get_mut()` for `Unsafecell`) - #76958 (Replace manual as_nanos and as_secs_f64 reimplementations) - #76959 (Replace write_fmt with write!) - #76961 (Add test for issue #34634) - #76962 (Use const_cstr macro in consts.rs) - #76963 (Remove unused static_assert macro) - #77000 (update Miri) Failed merges: r? `@ghost`
This commit is contained in:
commit
956e06c6c8
46 changed files with 594 additions and 506 deletions
|
@ -108,7 +108,7 @@ pub fn compile_codegen_unit(
|
|||
|
||||
// We assume that the cost to run LLVM on a CGU is proportional to
|
||||
// the time we needed for codegenning it.
|
||||
let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
|
||||
let cost = time_to_codegen.as_nanos() as u64;
|
||||
|
||||
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
|
||||
let cgu = tcx.codegen_unit(cgu_name);
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::type_of::LayoutLlvmExt;
|
|||
use crate::value::Value;
|
||||
use libc::c_uint;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::const_cstr;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Node;
|
||||
|
@ -22,8 +23,6 @@ use rustc_span::Span;
|
|||
use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
|
||||
use tracing::debug;
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
|
||||
let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
|
||||
let dl = cx.data_layout();
|
||||
|
@ -454,9 +453,9 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
|||
.all(|&byte| byte == 0);
|
||||
|
||||
let sect_name = if all_bytes_are_zero {
|
||||
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
|
||||
const_cstr!("__DATA,__thread_bss")
|
||||
} else {
|
||||
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
|
||||
const_cstr!("__DATA,__thread_data")
|
||||
};
|
||||
llvm::LLVMSetSection(g, sect_name.as_ptr());
|
||||
}
|
||||
|
|
|
@ -433,6 +433,17 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
llvm::LLVMSetSection(g, section.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
|
||||
if self.get_declared_value("main").is_none() {
|
||||
Some(self.declare_cfn("main", fn_type))
|
||||
} else {
|
||||
// If the symbol already exists, it is an error: for example, the user wrote
|
||||
// #[no_mangle] extern "C" fn main(..) {..}
|
||||
// instead of #[start]
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodegenCx<'b, 'tcx> {
|
||||
|
|
|
@ -51,17 +51,32 @@ fn declare_raw_fn(
|
|||
llfn
|
||||
}
|
||||
|
||||
impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||
impl CodegenCx<'ll, 'tcx> {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// return its Value instead.
|
||||
pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||
debug!("declare_global(name={:?})", name);
|
||||
unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
|
||||
}
|
||||
|
||||
fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
|
||||
/// Declare a C ABI function.
|
||||
///
|
||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||
/// `declare_fn` instead.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
|
||||
declare_raw_fn(self, name, llvm::CCallConv, fn_type)
|
||||
}
|
||||
|
||||
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
|
||||
/// Declare a Rust function.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
|
||||
debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
|
||||
|
||||
let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self));
|
||||
|
@ -69,7 +84,13 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
llfn
|
||||
}
|
||||
|
||||
fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
|
||||
/// Declare a global with an intention to define it.
|
||||
///
|
||||
/// Use this function when you intend to define a global. This function will
|
||||
/// return `None` if the name already has a definition associated with it. In that
|
||||
/// case an error should be reported to the user, because it usually happens due
|
||||
/// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
|
||||
pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
|
||||
if self.get_defined_value(name).is_some() {
|
||||
None
|
||||
} else {
|
||||
|
@ -77,16 +98,22 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
|
||||
/// Declare a private global
|
||||
///
|
||||
/// Use this function when you intend to define a global without a name.
|
||||
pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) }
|
||||
}
|
||||
|
||||
fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
/// Gets declared value by name.
|
||||
pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
debug!("get_declared_value(name={:?})", name);
|
||||
unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
|
||||
}
|
||||
|
||||
fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
/// Gets defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
self.get_declared_value(name).and_then(|val| {
|
||||
let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 };
|
||||
if !declaration { Some(val) } else { None }
|
||||
|
|
|
@ -407,16 +407,18 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// listing.
|
||||
let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap());
|
||||
|
||||
if cx.get_declared_value("main").is_some() {
|
||||
// FIXME: We should be smart and show a better diagnostic here.
|
||||
cx.sess()
|
||||
.struct_span_err(sp, "entry symbol `main` declared multiple times")
|
||||
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
|
||||
.emit();
|
||||
cx.sess().abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
let llfn = cx.declare_cfn("main", llfty);
|
||||
let llfn = match cx.declare_c_main(llfty) {
|
||||
Some(llfn) => llfn,
|
||||
None => {
|
||||
// FIXME: We should be smart and show a better diagnostic here.
|
||||
cx.sess()
|
||||
.struct_span_err(sp, "entry symbol `main` declared multiple times")
|
||||
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
|
||||
.emit();
|
||||
cx.sess().abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
};
|
||||
|
||||
// `main` should respect same config for frame pointer elimination as rest of code
|
||||
cx.set_frame_pointer_elimination(llfn);
|
||||
|
|
|
@ -1,51 +1,7 @@
|
|||
use super::BackendTypes;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::{Instance, Ty};
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
pub trait DeclareMethods<'tcx>: BackendTypes {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// return its Value instead.
|
||||
fn declare_global(&self, name: &str, ty: Self::Type) -> Self::Value;
|
||||
|
||||
/// Declare a C ABI function.
|
||||
///
|
||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||
/// `declare_fn` instead.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function;
|
||||
|
||||
/// Declare a Rust function.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function;
|
||||
|
||||
/// Declare a global with an intention to define it.
|
||||
///
|
||||
/// Use this function when you intend to define a global. This function will
|
||||
/// return `None` if the name already has a definition associated with it. In that
|
||||
/// case an error should be reported to the user, because it usually happens due
|
||||
/// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
|
||||
fn define_global(&self, name: &str, ty: Self::Type) -> Option<Self::Value>;
|
||||
|
||||
/// Declare a private global
|
||||
///
|
||||
/// Use this function when you intend to define a global without a name.
|
||||
fn define_private_global(&self, ty: Self::Type) -> Self::Value;
|
||||
|
||||
/// Gets declared value by name.
|
||||
fn get_declared_value(&self, name: &str) -> Option<Self::Value>;
|
||||
|
||||
/// Gets defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
fn get_defined_value(&self, name: &str) -> Option<Self::Value>;
|
||||
}
|
||||
use rustc_middle::ty::Instance;
|
||||
|
||||
pub trait PreDefineMethods<'tcx>: BackendTypes {
|
||||
fn predefine_static(
|
||||
|
|
|
@ -19,4 +19,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
|||
fn set_frame_pointer_elimination(&self, llfn: Self::Function);
|
||||
fn apply_target_cpu_attr(&self, llfn: Self::Function);
|
||||
fn create_used_variable(&self);
|
||||
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
|
||||
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ pub use self::builder::{BuilderMethods, OverflowOp};
|
|||
pub use self::consts::ConstMethods;
|
||||
pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods};
|
||||
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||
pub use self::declare::{DeclareMethods, PreDefineMethods};
|
||||
pub use self::declare::PreDefineMethods;
|
||||
pub use self::intrinsic::IntrinsicCallMethods;
|
||||
pub use self::misc::MiscMethods;
|
||||
pub use self::statics::{StaticBuilderMethods, StaticMethods};
|
||||
|
@ -60,7 +60,6 @@ pub trait CodegenMethods<'tcx>:
|
|||
+ StaticMethods
|
||||
+ CoverageInfoMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
|
@ -77,7 +76,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
|||
+ StaticMethods
|
||||
+ CoverageInfoMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
/// A simple static assertion macro.
|
||||
#[macro_export]
|
||||
#[allow_internal_unstable(type_ascription)]
|
||||
macro_rules! static_assert {
|
||||
($test:expr) => {
|
||||
// Use the bool to access an array such that if the bool is false, the access
|
||||
// is out-of-bounds.
|
||||
#[allow(dead_code)]
|
||||
const _: () = [()][!($test: bool) as usize];
|
||||
};
|
||||
}
|
||||
|
||||
/// Type size assertion. The first argument is a type and the second argument is its expected size.
|
||||
#[macro_export]
|
||||
macro_rules! static_assert_size {
|
||||
|
|
|
@ -600,10 +600,7 @@ pub fn print_time_passes_entry(do_it: bool, what: &str, dur: Duration) {
|
|||
// Hack up our own formatting for the duration to make it easier for scripts
|
||||
// to parse (always use the same number of decimal places and the same unit).
|
||||
pub fn duration_to_secs_str(dur: std::time::Duration) -> String {
|
||||
const NANOS_PER_SEC: f64 = 1_000_000_000.0;
|
||||
let secs = dur.as_secs() as f64 + dur.subsec_nanos() as f64 / NANOS_PER_SEC;
|
||||
|
||||
format!("{:.3}", secs)
|
||||
format!("{:.3}", dur.as_secs_f64())
|
||||
}
|
||||
|
||||
// Memory reporting
|
||||
|
|
|
@ -1227,18 +1227,14 @@ impl EmitterWriter {
|
|||
}
|
||||
draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
|
||||
if *level != Level::FailureNote {
|
||||
let level_str = level.to_string();
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::MainHeaderMsg);
|
||||
buffer.append(0, ": ", Style::NoStyle);
|
||||
}
|
||||
buffer.append(0, level.to_str(), Style::MainHeaderMsg);
|
||||
buffer.append(0, ": ", Style::NoStyle);
|
||||
}
|
||||
self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
|
||||
} else {
|
||||
let level_str = level.to_string();
|
||||
// The failure note level itself does not provide any useful diagnostic information
|
||||
if *level != Level::FailureNote && !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::Level(*level));
|
||||
if *level != Level::FailureNote {
|
||||
buffer.append(0, level.to_str(), Style::Level(*level));
|
||||
}
|
||||
// only render error codes, not lint codes
|
||||
if let Some(DiagnosticId::Error(ref code)) = *code {
|
||||
|
@ -1246,7 +1242,7 @@ impl EmitterWriter {
|
|||
buffer.append(0, &code, Style::Level(*level));
|
||||
buffer.append(0, "]", Style::Level(*level));
|
||||
}
|
||||
if *level != Level::FailureNote && !level_str.is_empty() {
|
||||
if *level != Level::FailureNote {
|
||||
buffer.append(0, ": ", header_style);
|
||||
}
|
||||
for &(ref text, _) in msg.iter() {
|
||||
|
@ -1548,11 +1544,9 @@ impl EmitterWriter {
|
|||
let mut buffer = StyledBuffer::new();
|
||||
|
||||
// Render the suggestion message
|
||||
let level_str = level.to_string();
|
||||
if !level_str.is_empty() {
|
||||
buffer.append(0, &level_str, Style::Level(*level));
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
}
|
||||
buffer.append(0, level.to_str(), Style::Level(*level));
|
||||
buffer.append(0, ": ", Style::HeaderMsg);
|
||||
|
||||
self.msg_to_buffer(
|
||||
&mut buffer,
|
||||
&[(suggestion.msg.to_owned(), Style::NoStyle)],
|
||||
|
|
|
@ -973,16 +973,14 @@ impl HandlerInner {
|
|||
|
||||
fn panic_if_treat_err_as_bug(&self) {
|
||||
if self.treat_err_as_bug() {
|
||||
let s = match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) {
|
||||
(0, _) => return,
|
||||
(1, 1) => "aborting due to `-Z treat-err-as-bug=1`".to_string(),
|
||||
(1, _) => return,
|
||||
(count, as_bug) => format!(
|
||||
match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) {
|
||||
(1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
|
||||
(0, _) | (1, _) => {}
|
||||
(count, as_bug) => panic!(
|
||||
"aborting after {} errors due to `-Z treat-err-as-bug={}`",
|
||||
count, as_bug,
|
||||
),
|
||||
};
|
||||
panic!(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue