diff options
| author | bors <bors@rust-lang.org> | 2024-03-06 18:51:11 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-06 18:51:11 +0000 |
| commit | 305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd (patch) | |
| tree | e8c9415143a6307f929727db3da941edda124d78 /compiler/rustc_codegen_ssa/src | |
| parent | 033c1e00b0fda6616c1442ecf40bb79da8c5db20 (diff) | |
| parent | 3c2318c0b21e2f4473c2465a4d9481ccd21906dd (diff) | |
| download | rust-305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd.tar.gz rust-305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd.zip | |
Auto merge of #3363 - RalfJung:rustup, r=RalfJung
Rustup This should finally work again :)
Diffstat (limited to 'compiler/rustc_codegen_ssa/src')
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/assert_module_sources.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/link.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/linker.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/metadata.rs | 87 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/back/write.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/block.rs | 59 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/operand.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/place.rs | 41 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/builder.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/traits/type_.rs | 3 |
13 files changed, 141 insertions, 118 deletions
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index cbee4877122..7ecc3864347 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -176,7 +176,7 @@ impl<'tcx> AssertModuleSource<'tcx> { /// Scan for a `cfg="foo"` attribute and check whether we have a /// cfg flag called `foo`. fn check_config(&self, attr: &ast::Attribute) -> bool { - let config = &self.tcx.sess.parse_sess.config; + let config = &self.tcx.sess.psess.config; let value = self.field(attr, sym::cfg); debug!("check_config(config={:?}, value={:?})", config, value); if config.iter().any(|&(name, _)| name == value) { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e4a050dcfc9..fcb3602b734 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -315,8 +315,11 @@ fn link_rlib<'a>( let trailing_metadata = match flavor { RlibFlavor::Normal => { - let (metadata, metadata_position) = - create_wrapper_file(sess, b".rmeta".to_vec(), codegen_results.metadata.raw_data()); + let (metadata, metadata_position) = create_wrapper_file( + sess, + ".rmeta".to_string(), + codegen_results.metadata.raw_data(), + ); let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME); match metadata_position { MetadataPosition::First => { @@ -384,7 +387,7 @@ fn link_rlib<'a>( let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess); let src = read(path) .map_err(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e }))?; - let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src); + let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src); let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); packed_bundled_libs.push(wrapper_file); } else { @@ -1218,6 +1221,9 @@ fn add_sanitizer_libraries( if sanitizer.contains(SanitizerSet::ADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "asan"); } + if sanitizer.contains(SanitizerSet::DATAFLOW) { + link_sanitizer_runtime(sess, flavor, linker, "dfsan"); + } if sanitizer.contains(SanitizerSet::LEAK) { link_sanitizer_runtime(sess, flavor, linker, "lsan"); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 1f3383815e2..e52efd86955 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1631,7 +1631,9 @@ impl<'a> Linker for AixLinker<'a> { fn optimize(&mut self) {} - fn pgo_gen(&mut self) {} + fn pgo_gen(&mut self) { + self.cmd.arg("-bdbg:namedsects:ss"); + } fn control_flow_guard(&mut self) {} diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index c6b04431fab..158b8fb8727 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -1,5 +1,6 @@ //! Reading of the rustc metadata for rlibs and dylibs +use std::borrow::Cow; use std::fs::File; use std::io::Write; use std::path::Path; @@ -15,7 +16,6 @@ use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice}; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::fs::METADATA_FILENAME; use rustc_metadata::EncodedMetadata; -use rustc_serialize::leb128; use rustc_session::Session; use rustc_span::sym; use rustc_target::abi::Endian; @@ -434,12 +434,15 @@ pub enum MetadataPosition { /// automatically removed from the final output. pub fn create_wrapper_file( sess: &Session, - section_name: Vec<u8>, + section_name: String, data: &[u8], ) -> (Vec<u8>, MetadataPosition) { let Some(mut file) = create_object_file(sess) else { if sess.target.is_like_wasm { - return (create_metadata_file_for_wasm(data, §ion_name), MetadataPosition::First); + return ( + create_metadata_file_for_wasm(sess, data, §ion_name), + MetadataPosition::First, + ); } // Targets using this branch don't have support implemented here yet or @@ -452,7 +455,7 @@ pub fn create_wrapper_file( } else { file.add_section( file.segment_name(StandardSegment::Debug).to_vec(), - section_name, + section_name.into_bytes(), SectionKind::Debug, ) }; @@ -524,7 +527,7 @@ pub fn create_compressed_metadata_file( let Some(mut file) = create_object_file(sess) else { if sess.target.is_like_wasm { - return create_metadata_file_for_wasm(&packed_metadata, b".rustc"); + return create_metadata_file_for_wasm(sess, &packed_metadata, ".rustc"); } return packed_metadata.to_vec(); }; @@ -624,51 +627,41 @@ pub fn create_compressed_metadata_file_for_xcoff( /// `data`. /// /// NB: the `object` crate does not yet have support for writing the wasm -/// object file format. The format is simple enough that for now an extra crate -/// from crates.io (such as `wasm-encoder`). The file format is: +/// object file format. In lieu of that the `wasm-encoder` crate is used to +/// build a wasm file by hand. /// -/// * 4-byte header "\0asm" -/// * 4-byte version number - 1u32 in little-endian format -/// * concatenated sections, which for this object is always "custom sections" -/// -/// Custom sections are then defined by: -/// * 1-byte section identifier - 0 for a custom section -/// * leb-encoded section length (size of the contents beneath this bullet) -/// * leb-encoded custom section name length -/// * custom section name -/// * section contents -/// -/// One custom section, `linking`, is added here in accordance with +/// The wasm object file format is defined at /// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md> -/// which is required to inform LLD that this is an object file but it should -/// otherwise basically ignore it if it otherwise looks at it. The linking -/// section currently is defined by a single version byte (2) and then further -/// sections, but we have no more sections, so it's just the byte "2". +/// and mainly consists of a `linking` custom section. In this case the custom +/// section there is empty except for a version marker indicating what format +/// it's in. /// -/// The next custom section is the one we're interested in. -pub fn create_metadata_file_for_wasm(data: &[u8], section_name: &[u8]) -> Vec<u8> { - let mut bytes = b"\0asm\x01\0\0\0".to_vec(); - - let mut append_custom_section = |section_name: &[u8], data: &[u8]| { - let mut section_name_len = [0; leb128::max_leb128_len::<usize>()]; - let off = leb128::write_usize_leb128(&mut section_name_len, section_name.len()); - let section_name_len = §ion_name_len[..off]; - - let mut section_len = [0; leb128::max_leb128_len::<usize>()]; - let off = leb128::write_usize_leb128( - &mut section_len, - data.len() + section_name_len.len() + section_name.len(), +/// The main purpose of this is to contain a custom section with `section_name`, +/// which is then appended after `linking`. +/// +/// As a further detail the object needs to have a 64-bit memory if `wasm64` is +/// the target or otherwise it's interpreted as a 32-bit object which is +/// incompatible with 64-bit ones. +pub fn create_metadata_file_for_wasm(sess: &Session, data: &[u8], section_name: &str) -> Vec<u8> { + assert!(sess.target.is_like_wasm); + let mut module = wasm_encoder::Module::new(); + let mut imports = wasm_encoder::ImportSection::new(); + + if sess.target.pointer_width == 64 { + imports.import( + "env", + "__linear_memory", + wasm_encoder::MemoryType { minimum: 0, maximum: None, memory64: true, shared: false }, ); - let section_len = §ion_len[..off]; - - bytes.push(0u8); - bytes.extend_from_slice(section_len); - bytes.extend_from_slice(section_name_len); - bytes.extend_from_slice(section_name); - bytes.extend_from_slice(data); - }; + } - append_custom_section(b"linking", &[2]); - append_custom_section(section_name, data); - bytes + if imports.len() > 0 { + module.section(&imports); + } + module.section(&wasm_encoder::CustomSection { + name: "linking".into(), + data: Cow::Borrowed(&[2]), + }); + module.section(&wasm_encoder::CustomSection { name: section_name.into(), data: data.into() }); + module.finish() } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 2dba04e0bb7..bff7e43b8e4 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -81,6 +81,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S return library.kind.is_statically_included().then_some(def_id); } + if tcx.intrinsic(def_id).is_some_and(|i| i.must_be_overridden) { + return None; + } + // Only consider nodes that actually have exported symbols. match tcx.def_kind(def_id) { DefKind::Fn | DefKind::Static(_) => {} diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 97089dff31b..bbb04652119 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -16,8 +16,8 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; use rustc_errors::translation::Translate; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagnosticMessage, ErrCode, FatalError, FluentBundle, Level, - MultiSpan, Style, + Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, FluentBundle, Level, MultiSpan, + Style, }; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -95,6 +95,7 @@ pub struct ModuleConfig { pub sanitizer: SanitizerSet, pub sanitizer_recover: SanitizerSet, + pub sanitizer_dataflow_abilist: Vec<String>, pub sanitizer_memory_track_origins: usize, // Flags indicating which outputs to produce. @@ -197,6 +198,10 @@ impl ModuleConfig { ), sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()), + sanitizer_dataflow_abilist: if_regular!( + sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(), + Vec::new() + ), sanitizer_recover: if_regular!( sess.opts.unstable_opts.sanitizer_recover, SanitizerSet::empty() @@ -999,9 +1004,9 @@ pub(crate) enum Message<B: WriteBackendMethods> { /// process another codegen unit. pub struct CguMessage; -// A cut-down version of `rustc_errors::Diagnostic` that impls `Send`, which +// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which // can be used to send diagnostics from codegen threads to the main thread. -// It's missing the following fields from `rustc_errors::Diagnostic`. +// It's missing the following fields from `rustc_errors::DiagInner`. // - `span`: it doesn't impl `Send`. // - `suggestions`: it doesn't impl `Send`, and isn't used for codegen // diagnostics. @@ -1010,18 +1015,18 @@ pub struct CguMessage; // - `emitted_at`: not used for codegen diagnostics. struct Diagnostic { level: Level, - messages: Vec<(DiagnosticMessage, Style)>, + messages: Vec<(DiagMessage, Style)>, code: Option<ErrCode>, children: Vec<Subdiagnostic>, args: DiagArgMap, } -// A cut-down version of `rustc_errors::SubDiagnostic` that impls `Send`. It's -// missing the following fields from `rustc_errors::SubDiagnostic`. +// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's +// missing the following fields from `rustc_errors::Subdiag`. // - `span`: it doesn't impl `Send`. pub struct Subdiagnostic { level: Level, - messages: Vec<(DiagnosticMessage, Style)>, + messages: Vec<(DiagMessage, Style)>, } #[derive(PartialEq, Clone, Copy, Debug)] diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 9e23757fcee..9c9e134f033 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -441,7 +441,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .map_err(|msg| { struct_span_code_err!( tcx.dcx(), - attr.span, + literal.span, E0589, "invalid `repr(align)` attribute: {}", msg diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 9c7aadb81f8..b0efb646ef3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,12 +12,12 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{self, AssertKind, SwitchTargets, UnwindTerminateReason}; +use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_session::config::OptLevel; -use rustc_span::{source_map::Spanned, sym, Span, Symbol}; +use rustc_span::{source_map::Spanned, sym, Span}; use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; @@ -680,7 +680,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, helper: &TerminatorCodegenHelper<'tcx>, bx: &mut Bx, - intrinsic: Option<Symbol>, + intrinsic: Option<ty::IntrinsicDef>, instance: Option<Instance<'tcx>>, source_info: mir::SourceInfo, target: Option<mir::BasicBlock>, @@ -690,7 +690,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. - let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s)); + let panic_intrinsic = intrinsic.and_then(|i| ValidityRequirement::from_intrinsic(i.name)); if let Some(requirement) = panic_intrinsic { let ty = instance.unwrap().args.type_at(0); @@ -826,14 +826,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The arguments we'll be passing. Plus one to account for outptr, if used. let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; - if intrinsic == Some(sym::caller_location) { + if matches!(intrinsic, Some(ty::IntrinsicDef { name: sym::caller_location, .. })) { return if let Some(target) = target { let location = self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); let mut llargs = Vec::with_capacity(arg_count); - let ret_dest = - self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, true, true); + let ret_dest = self.make_return_dest( + bx, + destination, + &fn_abi.ret, + &mut llargs, + intrinsic, + Some(target), + ); assert_eq!(llargs, []); if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { location.val.store(bx, tmp); @@ -846,7 +852,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let instance = match intrinsic { - None | Some(sym::drop_in_place) => instance, + None => instance, Some(intrinsic) => { let mut llargs = Vec::with_capacity(1); let ret_dest = self.make_return_dest( @@ -854,8 +860,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { destination, &fn_abi.ret, &mut llargs, - true, - target.is_some(), + Some(intrinsic), + target, ); let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], @@ -873,7 +879,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // The indices passed to simd_shuffle in the // third argument must be constant. This is // checked by the type-checker. - if i == 2 && intrinsic == sym::simd_shuffle { + if i == 2 && intrinsic.name == sym::simd_shuffle { if let mir::Operand::Constant(constant) = &arg.node { let (llval, ty) = self.simd_shuffle_indices(bx, constant); return OperandRef { @@ -903,14 +909,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MergingSucc::False }; } - Err(instance) => Some(instance), + Err(instance) => { + if intrinsic.must_be_overridden { + span_bug!( + span, + "intrinsic {} must be overridden by codegen backend, but isn't", + intrinsic.name, + ); + } + Some(instance) + } } } }; let mut llargs = Vec::with_capacity(arg_count); let destination = target.as_ref().map(|&target| { - (self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, false, true), target) + ( + self.make_return_dest( + bx, + destination, + &fn_abi.ret, + &mut llargs, + None, + Some(target), + ), + target, + ) }); // Split the rust-call tupled arguments off. @@ -1643,10 +1668,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { dest: mir::Place<'tcx>, fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec<Bx::Value>, - is_intrinsic: bool, - has_target: bool, + intrinsic: Option<ty::IntrinsicDef>, + target: Option<BasicBlock>, ) -> ReturnDest<'tcx, Bx::Value> { - if !has_target { + if target.is_none() { return ReturnDest::Nothing; } // If the return is ignored, we can just return a do-nothing `ReturnDest`. @@ -1667,7 +1692,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { tmp.storage_live(bx); llargs.push(tmp.llval); ReturnDest::IndirectOperand(tmp, index) - } else if is_intrinsic { + } else if intrinsic.is_some() { // Currently, intrinsics always need a location to store // the result, so we create a temporary `alloca` for the // result. diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 6f6f010422f..932926976b5 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -204,6 +204,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> { if self.layout.ty.is_box() { + // Derefer should have removed all Box derefs bug!("dereferencing {:?} in codegen", self.layout.ty); } @@ -437,8 +438,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { let align = dest.align; bx.store_with_flags(val, dest.llval, align, flags); - let llptr = - bx.inbounds_gep(bx.type_i8(), dest.llval, &[bx.const_usize(b_offset.bytes())]); + let llptr = bx.inbounds_ptradd(dest.llval, bx.const_usize(b_offset.bytes())); let val = bx.from_immediate(b); let align = dest.align.restrict_for_offset(b_offset); bx.store_with_flags(val, llptr, align, flags); @@ -476,7 +476,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> { let address = bx.ptrtoint(alloca, bx.type_isize()); let neg_address = bx.neg(address); let offset = bx.and(neg_address, align_minus_1); - let dst = bx.inbounds_gep(bx.type_i8(), alloca, &[offset]); + let dst = bx.inbounds_ptradd(alloca, offset); bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty()); // Store the allocated region and the extra to the indirect place. diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 73c08e2ca61..725d3bf4431 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -9,7 +9,7 @@ use rustc_middle::mir; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::{Abi, Align, FieldsShape, Int, Pointer, TagEncoding}; +use rustc_target::abi::{Align, FieldsShape, Int, Pointer, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; #[derive(Copy, Clone, Debug)] @@ -102,34 +102,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // `simple` is called when we don't need to adjust the offset to // the dynamic alignment of the field. let mut simple = || { - let llval = match self.layout.abi { - _ if offset.bytes() == 0 => { - // Unions and newtypes only use an offset of 0. - // Also handles the first field of Scalar, ScalarPair, and Vector layouts. - self.llval - } - Abi::ScalarPair(..) => { - // FIXME(nikic): Generate this for all ABIs. - bx.inbounds_gep(bx.type_i8(), self.llval, &[bx.const_usize(offset.bytes())]) - } - Abi::Scalar(_) | Abi::Vector { .. } if field.is_zst() => { - // ZST fields (even some that require alignment) are not included in Scalar, - // ScalarPair, and Vector layouts, so manually offset the pointer. - bx.gep(bx.cx().type_i8(), self.llval, &[bx.const_usize(offset.bytes())]) - } - Abi::Scalar(_) => { - // All fields of Scalar layouts must have been handled by this point. - // Vector layouts have additional fields for each element of the vector, so don't panic in that case. - bug!( - "offset of non-ZST field `{:?}` does not match layout `{:#?}`", - field, - self.layout - ); - } - _ => { - let ty = bx.backend_type(self.layout); - bx.struct_gep(ty, self.llval, bx.cx().backend_field_index(self.layout, ix)) - } + let llval = if offset.bytes() == 0 { + self.llval + } else if field.is_zst() { + // FIXME(erikdesjardins): it should be fine to use inbounds for ZSTs too; + // keeping this logic for now to preserve previous behavior. + bx.ptradd(self.llval, bx.const_usize(offset.bytes())) + } else { + bx.inbounds_ptradd(self.llval, bx.const_usize(offset.bytes())) }; PlaceRef { llval, @@ -188,7 +168,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { debug!("struct_field_ptr: DST field offset: {:?}", offset); // Adjust pointer. - let ptr = bx.gep(bx.cx().type_i8(), self.llval, &[offset]); + // FIXME(erikdesjardins): should be able to use inbounds here too. + let ptr = bx.ptradd(self.llval, offset); PlaceRef { llval: ptr, llextra: self.llextra, layout: field, align: effective_field_align } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 5c6060a7159..9ae82d4845e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -94,8 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if let OperandValue::Immediate(v) = cg_elem.val { - let zero = bx.const_usize(0); - let start = dest.project_index(bx, zero).llval; + let start = dest.llval; let size = bx.const_usize(dest.layout.size.bytes()); // Use llvm.memset.p0i8.* to initialize all zero arrays @@ -303,15 +302,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { - (Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty), + (Int(..) | F16 | F32 | F64 | F128, Int(..) | F16 | F32 | F64 | F128) => { + bx.bitcast(imm, to_backend_ty) + } (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), (Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty), (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), - (F32 | F64, Pointer(..)) => { + (F16 | F32 | F64 | F128, Pointer(..)) => { let int_imm = bx.bitcast(imm, bx.cx().type_isize()); bx.inttoptr(int_imm, to_backend_ty) } - (Pointer(..), F32 | F64) => { + (Pointer(..), F16 | F32 | F64 | F128) => { let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); bx.bitcast(int_imm, to_backend_ty) } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 86d3d1260c3..36f37e3791b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -190,7 +190,12 @@ pub trait BuilderMethods<'a, 'tcx>: ptr: Self::Value, indices: &[Self::Value], ) -> Self::Value; - fn struct_gep(&mut self, ty: Self::Type, ptr: Self::Value, idx: u64) -> Self::Value; + fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value { + self.gep(self.cx().type_i8(), ptr, &[offset]) + } + fn inbounds_ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value { + self.inbounds_gep(self.cx().type_i8(), ptr, &[offset]) + } fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index b1fde8e4d86..72cce43a3fa 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -19,8 +19,10 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn type_i128(&self) -> Self::Type; fn type_isize(&self) -> Self::Type; + fn type_f16(&self) -> Self::Type; fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; + fn type_f128(&self) -> Self::Type; fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type; fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type; @@ -111,7 +113,6 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool; fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool; - fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64; fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, |
