diff options
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/linker.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 92 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mono_item.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/size_of_val.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/builder.rs | 48 |
12 files changed, 152 insertions, 102 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8fb831471a9..e3ace01c1eb 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -410,7 +410,7 @@ impl<'a> GccLinker<'a> { let opt_level = match self.sess.opts.optimize { config::OptLevel::No => "O0", config::OptLevel::Less => "O1", - config::OptLevel::Default | config::OptLevel::Size | config::OptLevel::SizeMin => "O2", + config::OptLevel::More | config::OptLevel::Size | config::OptLevel::SizeMin => "O2", config::OptLevel::Aggressive => "O3", }; @@ -685,7 +685,7 @@ impl<'a> Linker for GccLinker<'a> { // GNU-style linkers support optimization with -O. GNU ld doesn't // need a numeric argument, but other linkers do. - if self.sess.opts.optimize == config::OptLevel::Default + if self.sess.opts.optimize == config::OptLevel::More || self.sess.opts.optimize == config::OptLevel::Aggressive { self.link_arg("-O1"); @@ -1213,7 +1213,7 @@ impl<'a> Linker for EmLinker<'a> { self.cc_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", @@ -1384,7 +1384,7 @@ impl<'a> Linker for WasmLd<'a> { self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2` // instead. @@ -1451,7 +1451,7 @@ impl<'a> WasmLd<'a> { let opt_level = match self.sess.opts.optimize { config::OptLevel::No => "O0", config::OptLevel::Less => "O1", - config::OptLevel::Default => "O2", + config::OptLevel::More => "O2", config::OptLevel::Aggressive => "O3", // wasm-ld only handles integer LTO opt levels. Use O2 config::OptLevel::Size | config::OptLevel::SizeMin => "O2", @@ -1525,7 +1525,7 @@ impl<'a> Linker for L4Bender<'a> { fn optimize(&mut self) { // GNU-style linkers support optimization with -O. GNU ld doesn't // need a numeric argument, but other linkers do. - if self.sess.opts.optimize == config::OptLevel::Default + if self.sess.opts.optimize == config::OptLevel::More || self.sess.opts.optimize == config::OptLevel::Aggressive { self.link_arg("-O1"); @@ -1776,6 +1776,7 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) - symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate( tcx, symbol, cnum, )); + symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum); } }); @@ -1929,7 +1930,7 @@ impl<'a> Linker for LlbcLinker<'a> { match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", @@ -2006,7 +2007,7 @@ impl<'a> Linker for BpfLinker<'a> { self.link_arg(match self.sess.opts.optimize { OptLevel::No => "-O0", OptLevel::Less => "-O1", - OptLevel::Default => "-O2", + OptLevel::More => "-O2", OptLevel::Aggressive => "-O3", OptLevel::Size => "-Os", OptLevel::SizeMin => "-Oz", diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 1dbaffaa577..12ee872d531 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -10,9 +10,10 @@ use rustc_middle::middle::exported_symbols::{ ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, metadata_symbol_name, }; use rustc_middle::query::LocalCrate; -use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, TyCtxt}; +use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; +use rustc_target::callconv::Conv; use rustc_target::spec::{SanitizerSet, TlsModel}; use tracing::debug; @@ -584,6 +585,42 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( } } +fn calling_convention_for_symbol<'tcx>( + tcx: TyCtxt<'tcx>, + symbol: ExportedSymbol<'tcx>, +) -> (Conv, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) { + let instance = match symbol { + ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) + if tcx.is_static(def_id) => + { + None + } + ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), + ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)), + // DropGlue always use the Rust calling convention and thus follow the target's default + // symbol decoration scheme. + ExportedSymbol::DropGlue(..) => None, + // AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the + // target's default symbol decoration scheme. + ExportedSymbol::AsyncDropGlueCtorShim(..) => None, + // NoDefId always follow the target's default symbol decoration scheme. + ExportedSymbol::NoDefId(..) => None, + // ThreadLocalShim always follow the target's default symbol decoration scheme. + ExportedSymbol::ThreadLocalShim(..) => None, + }; + + instance + .map(|i| { + tcx.fn_abi_of_instance( + ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())), + ) + .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) + }) + .map(|fnabi| (fnabi.conv, &fnabi.args[..])) + // FIXME(workingjubilee): why don't we know the convention here? + .unwrap_or((Conv::Rust, &[])) +} + /// This is the symbol name of the given instance as seen by the linker. /// /// On 32-bit Windows symbols are decorated according to their calling conventions. @@ -592,8 +629,6 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, ) -> String { - use rustc_target::callconv::Conv; - let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); // thread local will not be a function call, @@ -617,35 +652,7 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( _ => return undecorated, }; - let instance = match symbol { - ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) - if tcx.is_static(def_id) => - { - None - } - ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), - ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)), - // DropGlue always use the Rust calling convention and thus follow the target's default - // symbol decoration scheme. - ExportedSymbol::DropGlue(..) => None, - // AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the - // target's default symbol decoration scheme. - ExportedSymbol::AsyncDropGlueCtorShim(..) => None, - // NoDefId always follow the target's default symbol decoration scheme. - ExportedSymbol::NoDefId(..) => None, - // ThreadLocalShim always follow the target's default symbol decoration scheme. - ExportedSymbol::ThreadLocalShim(..) => None, - }; - - let (conv, args) = instance - .map(|i| { - tcx.fn_abi_of_instance( - ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())), - ) - .unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) - }) - .map(|fnabi| (fnabi.conv, &fnabi.args[..])) - .unwrap_or((Conv::Rust, &[])); + let (conv, args) = calling_convention_for_symbol(tcx, symbol); // Decorate symbols with prefixes, suffixes and total number of bytes of arguments. // Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170 @@ -677,6 +684,27 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>( maybe_emutls_symbol_name(tcx, symbol, &undecorated).unwrap_or(undecorated) } +/// On amdhsa, `gpu-kernel` functions have an associated metadata object with a `.kd` suffix. +/// Add it to the symbols list for all kernel functions, so that it is exported in the linked +/// object. +pub(crate) fn extend_exported_symbols<'tcx>( + symbols: &mut Vec<String>, + tcx: TyCtxt<'tcx>, + symbol: ExportedSymbol<'tcx>, + instantiating_crate: CrateNum, +) { + let (conv, _) = calling_convention_for_symbol(tcx, symbol); + + if conv != Conv::GpuKernel || tcx.sess.target.os != "amdhsa" { + return; + } + + let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); + + // Add the symbol for the kernel descriptor (with .kd suffix) + symbols.push(format!("{undecorated}.kd")); +} + fn maybe_emutls_symbol_name<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index ce2161a07eb..f029c08a808 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -236,7 +236,7 @@ impl ModuleConfig { // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. vectorize_loop: !sess.opts.cg.no_vectorize_loops - && (sess.opts.optimize == config::OptLevel::Default + && (sess.opts.optimize == config::OptLevel::More || sess.opts.optimize == config::OptLevel::Aggressive), vectorize_slp: !sess.opts.cg.no_vectorize_slp && sess.opts.optimize == config::OptLevel::Aggressive, @@ -260,7 +260,7 @@ impl ModuleConfig { MergeFunctions::Trampolines | MergeFunctions::Aliases => { use config::OptLevel::*; match sess.opts.optimize { - Aggressive | Default | SizeMin | Size => true, + Aggressive | More | SizeMin | Size => true, Less | No => false, } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index d9fbf539fd3..e800492dad0 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1054,12 +1054,12 @@ pub(crate) fn provide(providers: &mut Providers) { config::OptLevel::No => return config::OptLevel::No, // If globally optimise-speed is already specified, just use that level. config::OptLevel::Less => return config::OptLevel::Less, - config::OptLevel::Default => return config::OptLevel::Default, + config::OptLevel::More => return config::OptLevel::More, config::OptLevel::Aggressive => return config::OptLevel::Aggressive, // If globally optimize-for-size has been requested, use -O2 instead (if optimize(size) // are present). - config::OptLevel::Size => config::OptLevel::Default, - config::OptLevel::SizeMin => config::OptLevel::Default, + config::OptLevel::Size => config::OptLevel::More, + config::OptLevel::SizeMin => config::OptLevel::More, }; let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items; diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7acdbd19993..3e9dfcea58b 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use rustc_abi::ExternAbi; use rustc_ast::attr::list_contains_name; use rustc_ast::expand::autodiff_attrs::{ AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity, @@ -23,7 +24,7 @@ use rustc_middle::ty::{self as ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_session::{Session, lint}; use rustc_span::{Ident, Span, sym}; -use rustc_target::spec::{SanitizerSet, abi}; +use rustc_target::spec::SanitizerSet; use tracing::debug; use crate::errors; @@ -219,7 +220,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if !is_closure && let Some(fn_sig) = fn_sig() - && fn_sig.skip_binder().abi() != abi::Abi::Rust + && fn_sig.skip_binder().abi() != ExternAbi::Rust { struct_span_code_err!( tcx.dcx(), @@ -271,10 +272,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if safe_target_features { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on - // WebAssembly targets on all functions, including safe - // ones. Other targets require that `#[target_feature]` is - // only applied to unsafe functions (pending the - // `target_feature_11` feature) because on most targets + // WebAssembly targets on all functions. Prior to stabilizing + // the `target_feature_11` feature, `#[target_feature]` was + // only permitted on unsafe functions because on most targets // execution of instructions that are not supported is // considered undefined behavior. For WebAssembly which is a // 100% safe target at execution time it's not possible to @@ -288,17 +288,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // if a target is documenting some wasm-specific code then // it's not spuriously denied. // - // This exception needs to be kept in sync with allowing - // `#[target_feature]` on `main` and `start`. - } else if !tcx.features().target_feature_11() { - feature_err( - &tcx.sess, - sym::target_feature_11, - attr.span, - "`#[target_feature(..)]` can only be applied to `unsafe` functions", - ) - .with_span_label(tcx.def_span(did), "not an `unsafe` function") - .emit(); + // Now that `#[target_feature]` is permitted on safe functions, + // this exception must still exist for allowing the attribute on + // `main`, `start`, and other functions that are not usually + // allowed. } else { check_target_feature_trait_unsafe(tcx, did, attr.span); } @@ -627,10 +620,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // its parent function, which effectively inherits the features anyway. Boxing this closure // would result in this closure being compiled without the inherited target features, but this // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute. - if tcx.features().target_feature_11() - && tcx.is_closure_like(did.to_def_id()) - && !codegen_fn_attrs.inline.always() - { + if tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always { let owner_id = tcx.parent(did.to_def_id()); if tcx.def_kind(owner_id).has_codegen_attrs() { codegen_fn_attrs @@ -914,8 +904,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> { let mode = match mode.as_str() { "Forward" => DiffMode::Forward, "Reverse" => DiffMode::Reverse, - "ForwardFirst" => DiffMode::ForwardFirst, - "ReverseFirst" => DiffMode::ReverseFirst, _ => { span_bug!(mode.span, "rustc_autodiff attribute contains invalid mode"); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 05175371591..53953b089c6 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -367,9 +367,7 @@ fn push_debuginfo_type_name<'tcx>( output.push_str(sig.safety.prefix_str()); if sig.abi != rustc_abi::ExternAbi::Rust { - output.push_str("extern \""); - output.push_str(sig.abi.name()); - output.push_str("\" "); + let _ = write!(output, "extern {} ", sig.abi); } output.push_str("fn("); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 8c571558717..4630ed48c52 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1013,7 +1013,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // // This is also relevant for `Pin<&mut Self>`, where we need to peel the // `Pin`. - while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_ref() { + while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() { let (idx, _) = op.layout.non_1zst_field(bx).expect( "not exactly one non-1-ZST field in a `DispatchFromDyn` type", ); @@ -1045,7 +1045,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } Immediate(_) => { // See comment above explaining why we peel these newtypes - while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_ref() { + while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() { let (idx, _) = op.layout.non_1zst_field(bx).expect( "not exactly one non-1-ZST field in a `DispatchFromDyn` type", ); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 6e7fbe62c8d..b34e966ba6c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -367,7 +367,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.sess().dcx().emit_fatal(errors::AtomicCompareExchange); }; let ty = fn_args.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { + if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() { let weak = instruction == "cxchgweak"; let dst = args[0].immediate(); let cmp = args[1].immediate(); @@ -395,7 +395,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "load" => { let ty = fn_args.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { + if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() { let layout = bx.layout_of(ty); let size = layout.size; let source = args[0].immediate(); @@ -413,7 +413,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "store" => { let ty = fn_args.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { + if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() { let size = bx.layout_of(ty).size; let val = args[1].immediate(); let ptr = args[0].immediate(); @@ -458,7 +458,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let ty = fn_args.type_at(0); - if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { + if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() { let ptr = args[0].immediate(); let val = args[1].immediate(); bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering)) diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 27cb7883b9a..4c5b183cfe9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -435,18 +435,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scalar: abi::Scalar, backend_ty: Bx::Type, ) { - if matches!(self.cx.sess().opts.optimize, OptLevel::No) - // For now, the critical niches are all over `Int`eger values. - // Should floating-point values or pointers ever get more complex - // niches, then this code will probably want to handle them too. - || !matches!(scalar.primitive(), abi::Primitive::Int(..)) - || scalar.is_always_valid(self.cx) - { + if matches!(self.cx.sess().opts.optimize, OptLevel::No) || scalar.is_always_valid(self.cx) { return; } - let range = scalar.valid_range(self.cx); - bx.assume_integer_range(imm, backend_ty, range); + match scalar.primitive() { + abi::Primitive::Int(..) => { + let range = scalar.valid_range(self.cx); + bx.assume_integer_range(imm, backend_ty, range); + } + abi::Primitive::Pointer(abi::AddressSpace::DATA) + if !scalar.valid_range(self.cx).contains(0) => + { + bx.assume_nonnull(imm); + } + abi::Primitive::Pointer(..) | abi::Primitive::Float(..) => {} + } } pub(crate) fn codegen_rvalue_unsized( @@ -689,7 +693,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (OperandValue::Immediate(llval), operand.layout) } mir::UnOp::PtrMetadata => { - assert!(operand.layout.ty.is_unsafe_ptr() || operand.layout.ty.is_ref(),); + assert!(operand.layout.ty.is_raw_ptr() || operand.layout.ty.is_ref(),); let (_, meta) = operand.val.pointer_parts(); assert_eq!(operand.layout.fields.count() > 1, meta.is_some()); if let Some(meta) = meta { diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 6749bc63327..5f95b6615bd 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { cx.codegen_static(def_id); } MonoItem::GlobalAsm(item_id) => { - let item = cx.tcx().hir().item(item_id); + let item = cx.tcx().hir_item(item_id); if let hir::ItemKind::GlobalAsm(asm) = item.kind { let operands: Vec<_> = asm .operands diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index 71a2f916db5..ac2366340fb 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -45,14 +45,9 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // The info in this case is the length of the str, so the size is that // times the unit size. ( - // All slice sizes must fit into `isize`, so this multiplication cannot (signed) - // wrap. - // NOTE: ideally, we want the effects of both `unchecked_smul` and `unchecked_umul` - // (resulting in `mul nsw nuw` in LLVM IR), since we know that the multiplication - // cannot signed wrap, and that both operands are non-negative. But at the time of - // writing, the `LLVM-C` binding can't do this, and it doesn't seem to enable any - // further optimizations. - bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())), + // All slice sizes must fit into `isize`, so this multiplication cannot + // wrap -- neither signed nor unsigned. + bx.unchecked_sumul(info.unwrap(), bx.const_usize(unit.size.bytes())), bx.const_usize(unit.align.abi.bytes()), ) } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index b7dcf16fa2b..2c843e2f5e4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -159,12 +159,35 @@ pub trait BuilderMethods<'a, 'tcx>: /// must be interpreted as unsigned and can be assumed to be less than the size of the left /// operand. fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; - fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; + fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.add(lhs, rhs) + } + fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.add(lhs, rhs) + } + fn unchecked_suadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.unchecked_sadd(lhs, rhs) + } + fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.sub(lhs, rhs) + } + fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.sub(lhs, rhs) + } + fn unchecked_susub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.unchecked_ssub(lhs, rhs) + } + fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.mul(lhs, rhs) + } + fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.mul(lhs, rhs) + } + fn unchecked_sumul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + // Which to default to is a fairly arbitrary choice, + // but this is what slice layout was using before. + self.unchecked_smul(lhs, rhs) + } fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value; /// Defaults to [`Self::or`], but guarantees `(lhs & rhs) == 0` so some backends @@ -243,6 +266,19 @@ pub trait BuilderMethods<'a, 'tcx>: self.assume(cmp); } + /// Emits an `assume` that the `val` of pointer type is non-null. + /// + /// You may want to check the optimization level before bothering calling this. + fn assume_nonnull(&mut self, val: Self::Value) { + // Arguably in LLVM it'd be better to emit an assume operand bundle instead + // <https://llvm.org/docs/LangRef.html#assume-operand-bundles> + // but this works fine for all backends. + + let null = self.const_null(self.type_ptr()); + let is_null = self.icmp(IntPredicate::IntNE, val, null); + self.assume(is_null); + } + fn range_metadata(&mut self, load: Self::Value, range: WrappingRange); fn nonnull_metadata(&mut self, load: Self::Value); |
