about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-06 18:51:11 +0000
committerbors <bors@rust-lang.org>2024-03-06 18:51:11 +0000
commit305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd (patch)
treee8c9415143a6307f929727db3da941edda124d78 /compiler/rustc_codegen_ssa/src
parent033c1e00b0fda6616c1442ecf40bb79da8c5db20 (diff)
parent3c2318c0b21e2f4473c2465a4d9481ccd21906dd (diff)
downloadrust-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.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs87
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs59
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs41
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs3
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, &section_name), MetadataPosition::First);
+            return (
+                create_metadata_file_for_wasm(sess, data, &section_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 = &section_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 = &section_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>,