summary refs log tree commit diff
path: root/compiler/rustc_codegen_gcc/src
diff options
context:
space:
mode:
authorAntoni Boucher <bouanto@zoho.com>2021-09-28 09:19:11 -0400
committerAntoni Boucher <bouanto@zoho.com>2021-09-28 09:19:11 -0400
commit7f32dd546f23f122a6c5e87db50e404261b75722 (patch)
tree615d2a69a0c7a6209f32bbfe7a36248b68578a17 /compiler/rustc_codegen_gcc/src
parentdf487317d08eb1bf194e87aa7c193bb738ed7546 (diff)
parent9809f5d21990d9e24b3e9876ea7da756fd4e9def (diff)
downloadrust-7f32dd546f23f122a6c5e87db50e404261b75722.tar.gz
rust-7f32dd546f23f122a6c5e87db50e404261b75722.zip
Merge commit '9809f5d21990d9e24b3e9876ea7da756fd4e9def' into libgccjit-codegen
Diffstat (limited to 'compiler/rustc_codegen_gcc/src')
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs41
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs15
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs46
-rw-r--r--compiler/rustc_codegen_gcc/src/callee.rs11
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs70
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs89
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs86
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs25
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs85
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs356
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs27
-rw-r--r--compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs12
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs4
14 files changed, 405 insertions, 466 deletions
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index a684c34b644..3b77097e9ad 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods,
 
 use rustc_hir::LlvmInlineAsmInner;
 use rustc_middle::{bug, ty::Instance};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 use rustc_target::asm::*;
 
 use std::borrow::Cow;
@@ -173,7 +173,20 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                             continue
                         },
                         (Register(reg_name), None) => {
-                            clobbers.push(reg_name);
+                            // `clobber_abi` can add lots of clobbers that are not supported by the target,
+                            // such as AVX-512 registers, so we just ignore unsupported registers
+                            let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
+                                .any(|&(_, feature)| {
+                                    if let Some(feature) = feature {
+                                        self.tcx.sess.target_features.contains(&Symbol::intern(feature))
+                                    } else {
+                                        true // Register class is unconditionally supported
+                                    }
+                                });
+
+                            if is_target_supported && !clobbers.contains(&reg_name) {
+                                clobbers.push(reg_name);
+                            }
                             continue
                         }
                     };
@@ -526,16 +539,20 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
     let constraint = match reg {
         // For vector registers LLVM wants the register name to match the type size.
         InlineAsmRegOrRegClass::Reg(reg) => {
-            // TODO(antoyo): add support for vector register.
-            match reg.name() {
-                "ax" => "a",
-                "bx" => "b",
-                "cx" => "c",
-                "dx" => "d",
-                "si" => "S",
-                "di" => "D",
-                // For registers like r11, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
-                name => return ConstraintOrRegister::Register(name), 
+            match reg {
+                InlineAsmReg::X86(_) => {
+                    // TODO(antoyo): add support for vector register.
+                    //
+                    // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
+                    return ConstraintOrRegister::Register(match reg.name() {
+                        // Some of registers' names does not map 1-1 from rust to gcc
+                        "st(0)" => "st",
+
+                        name => name,
+                    });
+                }
+
+                _ => unimplemented!(),
             }
         },
         InlineAsmRegOrRegClass::RegClass(reg) => match reg {
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 2963a3d49a2..9fd043607fc 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -1,5 +1,4 @@
 use std::env;
-use std::sync::Once;
 use std::time::Instant;
 
 use gccjit::{
@@ -7,7 +6,6 @@ use gccjit::{
     FunctionType,
     GlobalKind,
 };
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::dep_graph;
 use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::middle::exported_symbols;
@@ -20,7 +18,7 @@ use rustc_codegen_ssa::traits::DebugInfoMethods;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
 
-use crate::{GccContext, create_function_calling_initializers};
+use crate::GccContext;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 
@@ -97,15 +95,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
         {
             let cx = CodegenCx::new(&context, cgu, tcx);
 
-            static START: Once = Once::new();
-            START.call_once(|| {
-                let initializer_name = format!("__gccGlobalCrateInit{}", tcx.crate_name(LOCAL_CRATE));
-                let func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[], initializer_name, false);
-                let block = func.new_block("initial");
-                create_function_calling_initializers(tcx, &context, block);
-                block.end_with_void_return(None);
-            });
-
             let mono_items = cgu.items_in_deterministic_order(tcx);
             for &(mono_item, (linkage, visibility)) in &mono_items {
                 mono_item.predefine::<Builder<'_, '_, '_>>(&cx, linkage, visibility);
@@ -124,8 +113,6 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
             if cx.sess().opts.debuginfo != DebugInfo::None {
                 cx.debuginfo_finalize();
             }
-
-            cx.global_init_block.end_with_void_return(None);
         }
 
         ModuleCodegen {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 5d06d71953c..ac908418ee4 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -31,11 +31,12 @@ use rustc_codegen_ssa::traits::{
     StaticBuilderMethods,
 };
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_span::Span;
 use rustc_span::def_id::DefId;
 use rustc_target::abi::{
     self,
+    call::FnAbi,
     Align,
     HasDataLayout,
     Size,
@@ -347,6 +348,20 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
     }
 }
 
+impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        self.cx.handle_fn_abi_err(err, span, fn_abi_request)
+    }
+}
+
 impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
     type Target = CodegenCx<'gcc, 'tcx>;
 
@@ -505,7 +520,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
         // should be the same.
         let typ = a.get_type().to_signed(self);
-        let a = self.context.new_cast(None, a, typ);
         let b = self.context.new_cast(None, b, typ);
         a / b
     }
@@ -1052,11 +1066,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     /* Comparisons */
-    fn icmp(&mut self, op: IntPredicate, lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
-        if lhs.get_type() != rhs.get_type() {
+    fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
+        let left_type = lhs.get_type();
+        let right_type = rhs.get_type();
+        if left_type != right_type {
+            // NOTE: because libgccjit cannot compare function pointers.
+            if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() {
+                lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
+                rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
+            }
             // NOTE: hack because we try to cast a vector type to the same vector type.
-            if format!("{:?}", lhs.get_type()) != format!("{:?}", rhs.get_type()) {
-                rhs = self.context.new_cast(None, rhs, lhs.get_type());
+            else if format!("{:?}", left_type) != format!("{:?}", right_type) {
+                rhs = self.context.new_cast(None, rhs, left_type);
             }
         }
         self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
@@ -1210,6 +1231,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             else {
                 panic!("Unexpected type {:?}", value_type);
             };
+
+        let lvalue_type = lvalue.to_rvalue().get_type();
+        let value =
+            // NOTE: sometimes, rustc will create a value with the wrong type.
+            if lvalue_type != value.get_type() {
+                self.context.new_cast(None, value, lvalue_type)
+            }
+            else {
+                value
+            };
+
         self.llbb().add_assignment(None, lvalue, value);
 
         aggregate_value
@@ -1413,7 +1445,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
         // Forward to the `get_static` method of `CodegenCx`
-        self.cx().get_static(def_id)
+        self.cx().get_static(def_id).get_address(None)
     }
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index e402e0e91f1..76419b103d0 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -1,8 +1,7 @@
 use gccjit::{FunctionType, RValue};
 use rustc_codegen_ssa::traits::BaseTypeMethods;
-use rustc_middle::ty::{Instance, TypeFoldable};
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
-use rustc_target::abi::call::FnAbi;
+use rustc_middle::ty::{self, Instance, TypeFoldable};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
 
 use crate::abi::FnAbiGccExt;
 use crate::context::CodegenCx;
@@ -20,13 +19,13 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
     assert!(!instance.substs.needs_infer());
     assert!(!instance.substs.has_escaping_bound_vars());
 
-    if let Some(&func) = cx.instances.borrow().get(&instance) {
+    if let Some(&func) = cx.function_instances.borrow().get(&instance) {
         return func;
     }
 
     let sym = tcx.symbol_name(instance).name;
 
-    let fn_abi = FnAbi::of_instance(cx, instance, &[]);
+    let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
 
     let func =
         if let Some(func) = cx.get_declared_value(&sym) {
@@ -72,7 +71,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
             func
         };
 
-    cx.instances.borrow_mut().insert(instance, func);
+    cx.function_instances.borrow_mut().insert(instance, func);
 
     func
 }
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index a24fe0df911..bda08b653f0 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,6 +1,7 @@
 use std::convert::TryFrom;
 use std::convert::TryInto;
 
+use gccjit::LValue;
 use gccjit::{Block, CType, RValue, Type, ToRValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{
@@ -10,7 +11,6 @@ use rustc_codegen_ssa::traits::{
     MiscMethods,
     StaticMethods,
 };
-use rustc_middle::bug;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::ScalarInt;
 use rustc_middle::ty::layout::{TyAndLayout, LayoutOf};
@@ -27,28 +27,25 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         bytes_in_context(self, bytes)
     }
 
-    fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> RValue<'gcc> {
+    fn const_cstr(&self, symbol: Symbol, _null_terminated: bool) -> LValue<'gcc> {
         // TODO(antoyo): handle null_terminated.
         if let Some(&value) = self.const_cstr_cache.borrow().get(&symbol) {
-            return value.to_rvalue();
+            return value;
         }
 
         let global = self.global_string(&*symbol.as_str());
 
-        self.const_cstr_cache.borrow_mut().insert(symbol, global.dereference(None));
+        self.const_cstr_cache.borrow_mut().insert(symbol, global);
         global
     }
 
-    fn global_string(&self, string: &str) -> RValue<'gcc> {
+    fn global_string(&self, string: &str) -> LValue<'gcc> {
         // TODO(antoyo): handle non-null-terminated strings.
         let string = self.context.new_string_literal(&*string);
         let sym = self.generate_local_symbol_name("str");
-        // NOTE: TLS is always off for a string litteral.
-        // NOTE: string litterals do not have a link section.
-        let global = self.define_global(&sym, self.val_ty(string), false, None)
-            .unwrap_or_else(|| bug!("symbol `{}` is already defined", sym));
-        self.global_init_block.add_assignment(None, global.dereference(None), string);
-        global.to_rvalue()
+        let global = self.declare_private_global(&sym, self.val_ty(string));
+        global.global_set_initializer_value(string);
+        global
         // TODO(antoyo): set linkage.
     }
 
@@ -76,10 +73,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 
 pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
     let context = &cx.context;
-    let typ = context.new_array_type(None, context.new_type::<u8>(), bytes.len() as i32);
-    let global = cx.declare_unnamed_global(typ);
-    global.global_set_initializer(bytes);
-    global.to_rvalue()
+    let byte_type = context.new_type::<u8>();
+    let typ = context.new_array_type(None, byte_type, bytes.len() as i32);
+    let elements: Vec<_> =
+        bytes.iter()
+        .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
+        .collect();
+    context.new_rvalue_from_array(None, typ, &elements)
 }
 
 pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool {
@@ -180,7 +180,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
     fn const_str(&self, s: Symbol) -> (RValue<'gcc>, RValue<'gcc>) {
         let len = s.as_str().len();
-        let cs = self.const_ptrcast(self.const_cstr(s, false),
+        let cs = self.const_ptrcast(self.const_cstr(s, false).get_address(None),
             self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)),
         );
         (cs, self.const_usize(len as u64))
@@ -191,16 +191,9 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             .map(|value| value.get_type())
             .collect();
         // TODO(antoyo): cache the type? It's anonymous, so probably not.
-        let name = fields.iter().map(|typ| format!("{:?}", typ)).collect::<Vec<_>>().join("_");
         let typ = self.type_struct(&fields, packed);
-        let structure = self.global_init_func.new_local(None, typ, &name);
         let struct_type = typ.is_struct().expect("struct type");
-        for (index, value) in values.iter().enumerate() {
-            let field = struct_type.get_field(index as i32);
-            let field_lvalue = structure.access_field(None, field);
-            self.global_init_block.add_assignment(None, field_lvalue, *value);
-        }
-        self.lvalue_to_rvalue(structure)
+        self.context.new_rvalue_from_struct(None, struct_type, values)
     }
 
     fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {
@@ -260,19 +253,18 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                         },
                         GlobalAlloc::Static(def_id) => {
                             assert!(self.tcx.is_static(def_id));
-                            self.get_static(def_id)
+                            self.get_static(def_id).get_address(None)
                         },
                     };
                 let ptr_type = base_addr.get_type();
                 let base_addr = self.const_bitcast(base_addr, self.usize_type);
                 let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
                 let ptr = self.const_bitcast(base_addr + offset, ptr_type);
-                let value = ptr.dereference(None);
                 if layout.value != Pointer {
-                    self.const_bitcast(value.to_rvalue(), ty)
+                    self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
                 }
                 else {
-                    self.const_bitcast(value.get_address(None), ty)
+                    self.const_bitcast(ptr, ty)
                 }
             }
         }
@@ -310,6 +302,7 @@ pub trait SignType<'gcc, 'tcx> {
     fn is_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
     fn is_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
     fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
+    fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
 }
 
 impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
@@ -341,6 +334,27 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
             self.clone()
         }
     }
+
+    fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
+        if self.is_i8(cx) {
+            cx.u8_type
+        }
+        else if self.is_i16(cx) {
+            cx.u16_type
+        }
+        else if self.is_i32(cx) {
+            cx.u32_type
+        }
+        else if self.is_i64(cx) {
+            cx.u64_type
+        }
+        else if self.is_i128(cx) {
+            cx.u128_type
+        }
+        else {
+            self.clone()
+        }
+    }
 }
 
 pub trait TypeReflection<'gcc, 'tcx>  {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index df13fa79f06..205498acc31 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,4 +1,4 @@
-use gccjit::{RValue, Type};
+use gccjit::{LValue, RValue, ToRValue, Type};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
 use rustc_hir as hir;
 use rustc_hir::Node;
@@ -14,7 +14,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan
 
 use crate::base;
 use crate::context::CodegenCx;
-use crate::mangled_std_symbols::{ARGC, ARGV, ARGV_INIT_ARRAY};
 use crate::type_of::LayoutGccExt;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -45,17 +44,13 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
     fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
         let attrs = self.tcx.codegen_fn_attrs(def_id);
 
-        let instance = Instance::mono(self.tcx, def_id);
-        let name = &*self.tcx.symbol_name(instance).name;
-
-        let (value, alloc) =
+        let value =
             match codegen_static_initializer(&self, def_id) {
-                Ok(value) => value,
+                Ok((value, _)) => value,
                 // Error has already been reported
                 Err(_) => return,
             };
 
-        let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
         let global = self.get_static(def_id);
 
         // boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -73,45 +68,16 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
         let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
         let gcc_type = self.layout_of(ty).gcc_type(self, true);
 
-        let global =
-            if val_llty == gcc_type {
-                global
+        // TODO(antoyo): set alignment.
+
+        let value =
+            if value.get_type() != gcc_type {
+                self.context.new_bitcast(None, value, gcc_type)
             }
             else {
-                // If we created the global with the wrong type,
-                // correct the type.
-                // TODO(antoyo): set value name, linkage and visibility.
-
-                let new_global = self.get_or_insert_global(&name, val_llty, is_tls, attrs.link_section);
-
-                // To avoid breaking any invariants, we leave around the old
-                // global for the moment; we'll replace all references to it
-                // with the new global later. (See base::codegen_backend.)
-                //self.statics_to_rauw.borrow_mut().push((global, new_global));
-                new_global
+                value
             };
-        // TODO(antoyo): set alignment and initializer.
-        let value = self.rvalue_as_lvalue(value);
-        let value = value.get_address(None);
-        let dest_typ = global.get_type();
-        let value = self.context.new_cast(None, value, dest_typ);
-
-        // NOTE: do not init the variables related to argc/argv because it seems we cannot
-        // overwrite those variables.
-        // FIXME(antoyo): correctly support global variable initialization.
-        let skip_init = [
-            ARGV_INIT_ARRAY,
-            ARGC,
-            ARGV,
-        ];
-        if !skip_init.iter().any(|symbol_name| name.starts_with(symbol_name)) {
-            // TODO(antoyo): switch to set_initializer when libgccjit supports that.
-            let memcpy = self.context.get_builtin_function("memcpy");
-            let dst = self.context.new_cast(None, global, self.type_i8p());
-            let src = self.context.new_cast(None, value, self.type_ptr_to(self.type_void()));
-            let size = self.context.new_rvalue_from_long(self.sizet_type, alloc.size().bytes() as i64);
-            self.global_init_block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
-        }
+        global.global_set_initializer_value(value);
 
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
@@ -175,7 +141,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
         }
 
         if attrs.flags.contains(CodegenFnAttrFlags::USED) {
-            self.add_used_global(global);
+            self.add_used_global(global.to_rvalue());
         }
     }
 
@@ -191,38 +157,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
-        let (name, gv) =
+        let global =
             match kind {
                 Some(kind) if !self.tcx.sess.fewer_names() => {
                     let name = self.generate_local_symbol_name(kind);
                     // TODO(antoyo): check if it's okay that TLS is off here.
                     // TODO(antoyo): check if it's okay that link_section is None here.
                     // TODO(antoyo): set alignment here as well.
-                    let gv = self.define_global(&name[..], self.val_ty(cv), false, None).unwrap_or_else(|| {
-                        bug!("symbol `{}` is already defined", name);
-                    });
+                    let global = self.define_global(&name[..], self.val_ty(cv), false, None);
                     // TODO(antoyo): set linkage.
-                    (name, gv)
+                    global
                 }
                 _ => {
-                    let index = self.global_gen_sym_counter.get();
-                    let name = format!("global_{}_{}", index, self.codegen_unit.name());
                     let typ = self.val_ty(cv).get_aligned(align.bytes());
-                    let global = self.define_private_global(typ);
-                    (name, global)
+                    let global = self.declare_unnamed_global(typ);
+                    global
                 },
             };
         // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used
         // globally.
-        // NOTE: global seems to only be global in a module. So save the name instead of the value
-        // to import it later.
-        self.global_names.borrow_mut().insert(cv, name);
-        self.global_init_block.add_assignment(None, gv.dereference(None), cv);
+        global.global_set_initializer_value(cv);
         // TODO(antoyo): set unnamed address.
-        gv
+        global.get_address(None)
     }
 
-    pub fn get_static(&self, def_id: DefId) -> RValue<'gcc> {
+    pub fn get_static(&self, def_id: DefId) -> LValue<'gcc> {
         let instance = Instance::mono(self.tcx, def_id);
         let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
         if let Some(&global) = self.instances.borrow().get(&instance) {
@@ -380,7 +339,7 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
     Ok((const_alloc_to_gcc(cx, alloc), alloc))
 }
 
-fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> RValue<'gcc> {
+fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str, span: Span) -> LValue<'gcc> {
     let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
     let llty = cx.layout_of(ty).gcc_type(cx, true);
     if let Some(linkage) = attrs.linkage {
@@ -410,13 +369,9 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
         // zero.
         let mut real_name = "_rust_extern_with_linkage_".to_string();
         real_name.push_str(&sym);
-        let global2 =
-            cx.define_global(&real_name, llty, is_tls, attrs.link_section).unwrap_or_else(|| {
-                cx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym))
-            });
+        let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section);
         // TODO(antoyo): set linkage.
-        let lvalue = global2.dereference(None);
-        cx.global_init_block.add_assignment(None, lvalue, global1);
+        global2.global_set_initializer_value(global1.get_address(None));
         // TODO(antoyo): use global_set_initializer() when it will work.
         global2
     }
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index ef687dd22c6..7677ade7314 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -21,10 +21,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_middle::span_bug;
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
+use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
 use rustc_session::Session;
 use rustc_span::{Span, Symbol};
-use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
 
 use crate::callee::get_fn;
@@ -46,10 +46,6 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub current_func: RefCell<Option<Function<'gcc>>>,
     pub normal_function_addresses: RefCell<FxHashSet<RValue<'gcc>>>,
 
-    /// The function where globals are initialized.
-    pub global_init_func: Function<'gcc>,
-    pub global_init_block: Block<'gcc>,
-
     pub functions: RefCell<FxHashMap<String, Function<'gcc>>>,
 
     pub tls_model: gccjit::TlsModel,
@@ -89,23 +85,20 @@ pub struct CodegenCx<'gcc, 'tcx> {
     pub types_with_fields_to_set: RefCell<FxHashMap<Type<'gcc>, (Struct<'gcc>, TyAndLayout<'tcx>)>>,
 
     /// Cache instances of monomorphic and polymorphic items
-    pub instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>,
+    pub instances: RefCell<FxHashMap<Instance<'tcx>, LValue<'gcc>>>,
+    /// Cache function instances of monomorphic and polymorphic items
+    pub function_instances: RefCell<FxHashMap<Instance<'tcx>, RValue<'gcc>>>,
     /// Cache generated vtables
     pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
 
     /// Cache of emitted const globals (value -> global)
     pub const_globals: RefCell<FxHashMap<RValue<'gcc>, RValue<'gcc>>>,
 
-    pub init_argv_var: RefCell<String>,
-    pub argv_initialized: Cell<bool>,
-
     /// Cache of constant strings,
     pub const_cstr_cache: RefCell<FxHashMap<Symbol, LValue<'gcc>>>,
 
     /// Cache of globals.
     pub globals: RefCell<FxHashMap<String, RValue<'gcc>>>,
-    // TODO(antoyo): remove global_names.
-    pub global_names: RefCell<FxHashMap<RValue<'gcc>, String>>,
 
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
@@ -118,16 +111,9 @@ pub struct CodegenCx<'gcc, 'tcx> {
     /// NOTE: a hack is used because the rustc API is not suitable to libgccjit and as such,
     /// `const_undef()` returns struct as pointer so that they can later be assigned a value.
     /// As such, this set remembers which of these pointers were returned by this function so that
-    /// they can be derefered later.
+    /// they can be deferenced later.
     /// FIXME(antoyo): fix the rustc API to avoid having this hack.
     pub structs_as_pointer: RefCell<FxHashSet<RValue<'gcc>>>,
-
-    /// Store the pointer of different types for safety.
-    /// When casting the values back to their original types, check that they are indeed that type
-    /// with these sets.
-    /// FIXME(antoyo): remove when the API supports more types.
-    #[cfg(debug_assertions)]
-    lvalues: RefCell<FxHashSet<LValue<'gcc>>>,
 }
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -180,10 +166,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             functions.insert(builtin.to_string(), context.get_builtin_function(builtin));
         }
 
-        let global_init_func = context.new_function(None, FunctionType::Exported, context.new_type::<()>(), &[],
-            &format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false);
-        let global_init_block = global_init_func.new_block("initial");
-
         Self {
             check_overflow,
             codegen_unit,
@@ -192,8 +174,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             current_func: RefCell::new(None),
             normal_function_addresses: Default::default(),
             functions: RefCell::new(functions),
-            global_init_func,
-            global_init_block,
 
             tls_model,
 
@@ -221,15 +201,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             double_type,
 
             linkage: Cell::new(FunctionType::Internal),
-            #[cfg(debug_assertions)]
-            lvalues: Default::default(),
             instances: Default::default(),
+            function_instances: Default::default(),
             vtables: Default::default(),
             const_globals: Default::default(),
-            init_argv_var: RefCell::new(String::new()),
-            argv_initialized: Cell::new(false),
             const_cstr_cache: Default::default(),
-            global_names: Default::default(),
             globals: Default::default(),
             scalar_types: Default::default(),
             types: Default::default(),
@@ -244,12 +220,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         }
     }
 
-    pub fn lvalue_to_rvalue(&self, value: LValue<'gcc>) -> RValue<'gcc> {
-        #[cfg(debug_assertions)]
-        self.lvalues.borrow_mut().insert(value);
-        unsafe { std::mem::transmute(value) }
-    }
-
     pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
         let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
         debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(),
@@ -257,11 +227,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         function
     }
 
-    pub fn rvalue_as_lvalue(&self, value: RValue<'gcc>) -> LValue<'gcc> {
-        let lvalue: LValue<'gcc> = unsafe { std::mem::transmute(value) };
-        lvalue
-    }
-
     pub fn sess(&self) -> &Session {
         &self.tcx.sess
     }
@@ -436,6 +401,43 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 }
 
+impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+            self.sess().span_fatal(span, &err.to_string())
+        } else {
+            match fn_abi_request {
+                FnAbiRequest::OfFnPtr { sig, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+                        sig,
+                        extra_args,
+                        err
+                    );
+                }
+                FnAbiRequest::OfInstance { instance, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_instance({}, {:?})` failed: {}",
+                        instance,
+                        extra_args,
+                        err
+                    );
+                }
+            }
+        }
+    }
+}
+
 impl<'tcx, 'gcc> HasParamEnv<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn param_env(&self) -> ParamEnv<'tcx> {
         ParamEnv::reveal_all()
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 8661532a359..4d3b4f04bad 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,11 +1,9 @@
-use gccjit::{FunctionType, RValue};
+use gccjit::RValue;
 use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
-use rustc_codegen_ssa::traits::{BuilderMethods, DebugInfoBuilderMethods, DebugInfoMethods};
-use rustc_middle::middle::cstore::CrateDepKind;
+use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
 use rustc_middle::mir;
 use rustc_middle::ty::{Instance, Ty};
 use rustc_span::{SourceFile, Span, Symbol};
-use rustc_span::def_id::LOCAL_CRATE;
 use rustc_target::abi::Size;
 use rustc_target::abi::call::FnAbi;
 
@@ -20,25 +18,6 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
-        // TODO(antoyo): replace with gcc_jit_context_new_global_with_initializer() if it's added:
-        // https://gcc.gnu.org/pipermail/jit/2020q3/001225.html
-        //
-        // Call the function to initialize global values here.
-        // We assume this is only called for the main function.
-        use std::iter;
-
-        for crate_num in self.cx.tcx.crates(()).iter().copied().chain(iter::once(LOCAL_CRATE)) {
-            // FIXME(antoyo): better way to find if a crate is of proc-macro type?
-            if crate_num == LOCAL_CRATE || self.cx.tcx.dep_kind(crate_num) != CrateDepKind::MacrosOnly {
-                // NOTE: proc-macro crates are not included in the executable, so don't call their
-                // initialization routine.
-                let initializer_name = format!("__gccGlobalCrateInit{}", self.cx.tcx.crate_name(crate_num));
-                let codegen_init_func = self.context.new_function(None, FunctionType::Extern, self.context.new_type::<()>(), &[],
-                initializer_name, false);
-                self.llbb().add_eval(None, self.context.new_call(None, codegen_init_func, &[]));
-            }
-        }
-
         // TODO(antoyo): insert reference to gdb debug scripts section global.
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index c1382bf2f4a..b43f68f878d 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -7,10 +7,9 @@ use rustc_target::abi::call::FnAbi;
 use crate::abi::FnAbiGccExt;
 use crate::context::{CodegenCx, unit_name};
 use crate::intrinsic::llvm;
-use crate::mangled_std_symbols::{ARGV_INIT_ARRAY, ARGV_INIT_WRAPPER};
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> RValue<'gcc> {
+    pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
         if self.globals.borrow().contains_key(name) {
             let typ = self.globals.borrow().get(name).expect("global").get_type();
             let global = self.context.new_global(None, GlobalKind::Imported, typ, name);
@@ -20,7 +19,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             if let Some(link_section) = link_section {
                 global.set_link_section(&link_section.as_str());
             }
-            global.get_address(None)
+            global
         }
         else {
             self.declare_global(name, ty, is_tls, link_section)
@@ -34,13 +33,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.context.new_global(None, GlobalKind::Exported, ty, &name)
     }
 
-    pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> RValue<'gcc> {
-        let global = self.context.new_global(None, linkage, ty, name)
-            .get_address(None);
-        self.globals.borrow_mut().insert(name.to_string(), global);
-        // NOTE: global seems to only be global in a module. So save the name instead of the value
-        // to import it later.
-        self.global_names.borrow_mut().insert(global, name.to_string());
+    pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> {
+        let global = self.context.new_global(None, linkage, ty, name);
+        let global_address = global.get_address(None);
+        self.globals.borrow_mut().insert(name.to_string(), global_address);
         global
     }
 
@@ -51,19 +47,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         unsafe { std::mem::transmute(func) }
     }
 
-    pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> RValue<'gcc> {
-        // FIXME(antoyo): correctly support global variable initialization.
-        if name.starts_with(ARGV_INIT_ARRAY) {
-            // NOTE: hack to avoid having to update the names in mangled_std_symbols: we save the
-            // name of the variable now to actually declare it later.
-            *self.init_argv_var.borrow_mut() = name.to_string();
-
-            let global = self.context.new_global(None, GlobalKind::Imported, ty, name);
-            if let Some(link_section) = link_section {
-                global.set_link_section(&link_section.as_str());
-            }
-            return global.get_address(None);
-        }
+    pub fn declare_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
         let global = self.context.new_global(None, GlobalKind::Exported, ty, name);
         if is_tls {
             global.set_tls_model(self.tls_model);
@@ -71,11 +55,15 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         if let Some(link_section) = link_section {
             global.set_link_section(&link_section.as_str());
         }
-        let global = global.get_address(None);
-        self.globals.borrow_mut().insert(name.to_string(), global);
-        // NOTE: global seems to only be global in a module. So save the name instead of the value
-        // to import it later.
-        self.global_names.borrow_mut().insert(global, name.to_string());
+        let global_address = global.get_address(None);
+        self.globals.borrow_mut().insert(name.to_string(), global_address);
+        global
+    }
+
+    pub fn declare_private_global(&self, name: &str, ty: Type<'gcc>) -> LValue<'gcc> {
+        let global = self.context.new_global(None, GlobalKind::Internal, ty, name);
+        let global_address = global.get_address(None);
+        self.globals.borrow_mut().insert(name.to_string(), global_address);
         global
     }
 
@@ -94,51 +82,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> RValue<'gcc> {
-        // NOTE: hack to avoid having to update the names in mangled_std_symbols: we found the name
-        // of the variable earlier, so we declare it now.
-        // Since we don't correctly support initializers yet, we initialize this variable manually
-        // for now.
-        if name.starts_with(ARGV_INIT_WRAPPER) && !self.argv_initialized.get() {
-            let global_name = &*self.init_argv_var.borrow();
-            let return_type = self.type_void();
-            let params = [
-                self.context.new_parameter(None, self.int_type, "argc"),
-                self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "argv"),
-                self.context.new_parameter(None, self.u8_type.make_pointer().make_pointer(), "envp"),
-            ];
-            let function = self.context.new_function(None, FunctionType::Extern, return_type, &params, name, false);
-            let initializer = function.get_address(None);
-
-            let param_types = [
-                self.int_type,
-                self.u8_type.make_pointer().make_pointer(),
-                self.u8_type.make_pointer().make_pointer(),
-            ];
-            let ty = self.context.new_function_pointer_type(None, return_type, &param_types, false);
-
-            let global = self.context.new_global(None, GlobalKind::Exported, ty, global_name);
-            global.set_link_section(".init_array.00099");
-            global.global_set_initializer_value(initializer);
-            let global = global.get_address(None);
-            self.globals.borrow_mut().insert(global_name.to_string(), global);
-            // NOTE: global seems to only be global in a module. So save the name instead of the value
-            // to import it later.
-            self.global_names.borrow_mut().insert(global, global_name.to_string());
-            self.argv_initialized.set(true);
-        }
         let (return_type, params, variadic) = fn_abi.gcc_type(self);
         let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &params, variadic);
         // FIXME(antoyo): this is a wrong cast. That requires changing the compiler API.
         unsafe { std::mem::transmute(func) }
     }
 
-    pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> Option<RValue<'gcc>> {
-        Some(self.get_or_insert_global(name, ty, is_tls, link_section))
-    }
-
-    pub fn define_private_global(&self, ty: Type<'gcc>) -> RValue<'gcc> {
-        let global = self.declare_unnamed_global(ty);
-        global.get_address(None)
+    pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
+        self.get_or_insert_global(name, ty, is_tls, link_section)
     }
 
     pub fn get_declared_value(&self, name: &str) -> Option<RValue<'gcc>> {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 3dc4f61a7ac..45978e14090 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -18,7 +18,7 @@ use rustc_target::spec::PanicStrategy;
 
 use crate::abi::GccType;
 use crate::builder::Builder;
-use crate::common::TypeReflection;
+use crate::common::{SignType, TypeReflection};
 use crate::context::CodegenCx;
 use crate::type_of::LayoutGccExt;
 use crate::intrinsic::simd::generic_simd_intrinsic;
@@ -520,163 +520,176 @@ fn int_type_width_signed<'gcc, 'tcx>(ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>) -
 
 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> {
-        let typ = value.get_type();
+        let result_type = value.get_type();
+        let typ = result_type.to_unsigned(self.cx);
+
+        let value =
+            if result_type.is_signed(self.cx) {
+                self.context.new_bitcast(None, value, typ)
+            }
+            else {
+                value
+            };
+
         let context = &self.cx.context;
-        match width {
-            8 => {
-                // First step.
-                let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
-                let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
-                let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
-                let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
-                let step1 = self.or(left, right);
-
-                // Second step.
-                let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
-                let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
-                let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
-                let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
-                let step2 = self.or(left, right);
-
-                // Third step.
-                let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
-                let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
-                let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
-                let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
-                let step3 = self.or(left, right);
-
-                step3
-            },
-            16 => {
-                // First step.
-                let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
-                let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
-                let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
-                let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
-                let step1 = self.or(left, right);
-
-                // Second step.
-                let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
-                let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
-                let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
-                let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
-                let step2 = self.or(left, right);
-
-                // Third step.
-                let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
-                let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
-                let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
-                let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
-                let step3 = self.or(left, right);
-
-                // Fourth step.
-                let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
-                let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
-                let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
-                let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
-                let step4 = self.or(left, right);
-
-                step4
-            },
-            32 => {
-                // TODO(antoyo): Refactor with other implementations.
-                // First step.
-                let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
-                let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
-                let step1 = self.or(left, right);
-
-                // Second step.
-                let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
-                let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
-                let step2 = self.or(left, right);
-
-                // Third step.
-                let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
-                let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
-                let step3 = self.or(left, right);
-
-                // Fourth step.
-                let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
-                let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
-                let step4 = self.or(left, right);
-
-                // Fifth step.
-                let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
-                let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
-                let step5 = self.or(left, right);
-
-                step5
-            },
-            64 => {
-                // First step.
-                let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
-                let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
-                let step1 = self.or(left, right);
-
-                // Second step.
-                let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
-                let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
-                let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
-                let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
-                let step2 = self.or(left, right);
-
-                // Third step.
-                let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
-                let left = self.xor(step2, left);
-                let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
-
-                let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
-                let left = self.or(temp, left);
-                let step3 = self.xor(left, step2);
-
-                // Fourth step.
-                let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
-                let left = self.xor(step3, left);
-                let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
-
-                let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
-                let left = self.or(temp, left);
-                let step4 = self.xor(left, step3);
-
-                // Fifth step.
-                let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
-                let left = self.xor(step4, left);
-                let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
-
-                let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
-                let left = self.or(temp, left);
-                let step5 = self.xor(left, step4);
-
-                step5
-            },
-            128 => {
-                // TODO(antoyo): find a more efficient implementation?
-                let sixty_four = self.context.new_rvalue_from_long(typ, 64);
-                let high = self.context.new_cast(None, value >> sixty_four, self.u64_type);
-                let low = self.context.new_cast(None, value, self.u64_type);
+        let result =
+            match width {
+                8 => {
+                    // First step.
+                    let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
+                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
+                    let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
+                    let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
+                    let step1 = self.or(left, right);
+
+                    // Second step.
+                    let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
+                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
+                    let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
+                    let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
+                    let step2 = self.or(left, right);
+
+                    // Third step.
+                    let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
+                    let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
+                    let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
+                    let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
+                    let step3 = self.or(left, right);
+
+                    step3
+                },
+                16 => {
+                    // First step.
+                    let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
+                    let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
+                    let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
+                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
+                    let step1 = self.or(left, right);
+
+                    // Second step.
+                    let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
+                    let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
+                    let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
+                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
+                    let step2 = self.or(left, right);
+
+                    // Third step.
+                    let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
+                    let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
+                    let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
+                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
+                    let step3 = self.or(left, right);
+
+                    // Fourth step.
+                    let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
+                    let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
+                    let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
+                    let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
+                    let step4 = self.or(left, right);
+
+                    step4
+                },
+                32 => {
+                    // TODO(antoyo): Refactor with other implementations.
+                    // First step.
+                    let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
+                    let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
+                    let step1 = self.or(left, right);
+
+                    // Second step.
+                    let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
+                    let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
+                    let step2 = self.or(left, right);
+
+                    // Third step.
+                    let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
+                    let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
+                    let step3 = self.or(left, right);
+
+                    // Fourth step.
+                    let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
+                    let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
+                    let step4 = self.or(left, right);
+
+                    // Fifth step.
+                    let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
+                    let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
+                    let step5 = self.or(left, right);
+
+                    step5
+                },
+                64 => {
+                    // First step.
+                    let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
+                    let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
+                    let step1 = self.or(left, right);
+
+                    // Second step.
+                    let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
+                    let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
+                    let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
+                    let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
+                    let step2 = self.or(left, right);
+
+                    // Third step.
+                    let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
+                    let left = self.xor(step2, left);
+                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
+
+                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
+                    let left = self.or(temp, left);
+                    let step3 = self.xor(left, step2);
+
+                    // Fourth step.
+                    let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
+                    let left = self.xor(step3, left);
+                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
+
+                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
+                    let left = self.or(temp, left);
+                    let step4 = self.xor(left, step3);
+
+                    // Fifth step.
+                    let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
+                    let left = self.xor(step4, left);
+                    let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
+
+                    let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
+                    let left = self.or(temp, left);
+                    let step5 = self.xor(left, step4);
+
+                    step5
+                },
+                128 => {
+                    // TODO(antoyo): find a more efficient implementation?
+                    let sixty_four = self.context.new_rvalue_from_long(typ, 64);
+                    let high = self.context.new_cast(None, value >> sixty_four, self.u64_type);
+                    let low = self.context.new_cast(None, value, self.u64_type);
 
-                let reversed_high = self.bit_reverse(64, high);
-                let reversed_low = self.bit_reverse(64, low);
+                    let reversed_high = self.bit_reverse(64, high);
+                    let reversed_low = self.bit_reverse(64, low);
 
-                let new_low = self.context.new_cast(None, reversed_high, typ);
-                let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four;
+                    let new_low = self.context.new_cast(None, reversed_high, typ);
+                    let new_high = self.context.new_cast(None, reversed_low, typ) << sixty_four;
 
-                new_low | new_high
-            },
-            _ => {
-                panic!("cannot bit reverse with width = {}", width);
-            },
-        }
+                    new_low | new_high
+                },
+                _ => {
+                    panic!("cannot bit reverse with width = {}", width);
+                },
+            };
+
+        self.context.new_bitcast(None, result, result_type)
     }
 
     fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
@@ -746,6 +759,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 
     fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
+        let result_type = arg.get_type();
+        let arg =
+            if result_type.is_signed(self.cx) {
+                let new_type = result_type.to_unsigned(self.cx);
+                self.context.new_bitcast(None, arg, new_type)
+            }
+            else {
+                arg
+            };
         let arg_type = arg.get_type();
         let (count_trailing_zeroes, expected_type) =
             if arg_type.is_uchar(&self.cx) || arg_type.is_ushort(&self.cx) || arg_type.is_uint(&self.cx) {
@@ -796,7 +818,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
                 let res = self.context.new_array_access(None, result, index);
 
-                return self.context.new_cast(None, res, arg_type);
+                return self.context.new_bitcast(None, res, result_type);
             }
             else {
                 unimplemented!("count_trailing_zeroes for {:?}", arg_type);
@@ -810,7 +832,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 arg
             };
         let res = self.context.new_call(None, count_trailing_zeroes, &[arg]);
-        self.context.new_cast(None, res, arg_type)
+        self.context.new_bitcast(None, res, result_type)
     }
 
     fn int_width(&self, typ: Type<'gcc>) -> i64 {
@@ -819,7 +841,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
     fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): use the optimized version with fewer operations.
-        let value_type = value.get_type();
+        let result_type = value.get_type();
+        let value_type = result_type.to_unsigned(self.cx);
+
+        let value =
+            if result_type.is_signed(self.cx) {
+                self.context.new_bitcast(None, value, value_type)
+            }
+            else {
+                value
+            };
 
         if value_type.is_u128(&self.cx) {
             // TODO(antoyo): implement in the normal algorithm below to have a more efficient
@@ -830,7 +861,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let high = self.context.new_call(None, popcount, &[high]);
             let low = self.context.new_cast(None, value, self.cx.ulonglong_type);
             let low = self.context.new_call(None, popcount, &[low]);
-            return high + low;
+            let res = high + low;
+            return self.context.new_bitcast(None, res, result_type);
         }
 
         // First step.
@@ -855,7 +887,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let value = left + right;
 
         if value_type.is_u8(&self.cx) {
-            return value;
+            return self.context.new_bitcast(None, value, result_type);
         }
 
         // Fourth step.
@@ -866,7 +898,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let value = left + right;
 
         if value_type.is_u16(&self.cx) {
-            return value;
+            return self.context.new_bitcast(None, value, result_type);
         }
 
         // Fifth step.
@@ -877,7 +909,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let value = left + right;
 
         if value_type.is_u32(&self.cx) {
-            return value;
+            return self.context.new_bitcast(None, value, result_type);
         }
 
         // Sixth step.
@@ -887,7 +919,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let right = shifted & mask;
         let value = left + right;
 
-        value
+        self.context.new_bitcast(None, value, result_type)
     }
 
     // Algorithm from: https://blog.regehr.org/archives/1063
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 793e5c48d0a..f3c02e2634f 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -43,7 +43,6 @@ mod coverageinfo;
 mod debuginfo;
 mod declare;
 mod intrinsic;
-mod mangled_std_symbols;
 mod mono_item;
 mod type_;
 mod type_of;
@@ -51,7 +50,7 @@ mod type_of;
 use std::any::Any;
 use std::sync::Arc;
 
-use gccjit::{Block, Context, FunctionType, OptimizationLevel};
+use gccjit::{Context, OptimizationLevel};
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
 use rustc_codegen_ssa::base::codegen_crate;
@@ -64,13 +63,11 @@ use rustc_errors::{ErrorReported, Handler};
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{CrateType, Lto, OptLevel, OutputFilenames};
+use rustc_session::config::{Lto, OptLevel, OutputFilenames};
 use rustc_session::Session;
 use rustc_span::Symbol;
 use rustc_span::fatal_error::FatalError;
 
-use crate::context::unit_name;
-
 pub struct PrintOnPanic<F: Fn() -> String>(pub F);
 
 impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
@@ -109,16 +106,8 @@ impl CodegenBackend for GccCodegenBackend {
         Ok((codegen_results, work_products))
     }
 
-    fn link(&self, sess: &Session, mut codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> {
+    fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> {
         use rustc_codegen_ssa::back::link::link_binary;
-        if let Some(symbols) = codegen_results.crate_info.exported_symbols.get_mut(&CrateType::Dylib) {
-            // TODO:(antoyo): remove when global initializer work without calling a function at runtime.
-            // HACK: since this codegen add some symbols (e.g. __gccGlobalCrateInit) and the UI
-            // tests load libstd.so as a dynamic library, and rustc use a version-script to specify
-            // the symbols visibility, we add * to export all symbols.
-            // It seems other symbols from libstd/libcore are causing some issues here as well.
-            symbols.push("*".to_string());
-        }
 
         link_binary::<crate::archive::ArArchiveBuilder<'_>>(
             sess,
@@ -203,6 +192,7 @@ impl WriteBackendMethods for GccCodegenBackend {
     fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLTOInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
         // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
         // NOTE: implemented elsewhere.
+        // TODO: what is implemented elsewhere ^ ?
         let module =
             match modules.remove(0) {
                 FatLTOInput::InMemory(module) => module,
@@ -273,15 +263,6 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
     }
 }
 
-fn create_function_calling_initializers<'gcc, 'tcx>(tcx: TyCtxt<'tcx>, context: &Context<'gcc>, block: Block<'gcc>) {
-    let codegen_units = tcx.collect_and_partition_mono_items(()).1;
-    for codegen_unit in codegen_units {
-        let codegen_init_func = context.new_function(None, FunctionType::Extern, context.new_type::<()>(), &[],
-            &format!("__gccGlobalInit{}", unit_name(&codegen_unit)), false);
-        block.add_eval(None, context.new_call(None, codegen_init_func, &[]));
-    }
-}
-
 fn handle_native(name: &str) -> &str {
     if name != "native" {
         return name;
diff --git a/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs b/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs
deleted file mode 100644
index b0c3f214d66..00000000000
--- a/compiler/rustc_codegen_gcc/src/mangled_std_symbols.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub const ARGV_INIT_ARRAY: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY";
-pub const ARGV_INIT_WRAPPER: &str = "_ZN3std3sys4unix4args3imp15ARGV_INIT_ARRAY12init_wrapper";
-pub const ARGC: &str = "_ZN3std3sys4unix4args3imp4ARGC";
-pub const ARGV: &str = "_ZN3std3sys4unix4args3imp4ARGV";
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index cedeb54f60b..e21d40b6c37 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -2,9 +2,8 @@ use rustc_codegen_ssa::traits::PreDefineMethods;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::mono::{Linkage, Visibility};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
 use rustc_span::def_id::DefId;
-use rustc_target::abi::call::FnAbi;
 
 use crate::base;
 use crate::context::CodegenCx;
@@ -18,12 +17,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         let gcc_type = self.layout_of(ty).gcc_type(self, true);
 
         let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
-        let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section).unwrap_or_else(|| {
-            self.sess().span_fatal(
-                self.tcx.def_span(def_id),
-                &format!("symbol `{}` is already defined", symbol_name),
-            )
-        });
+        let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section);
 
         // TODO(antoyo): set linkage and visibility.
         self.instances.borrow_mut().insert(instance, global);
@@ -32,7 +26,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, symbol_name: &str) {
         assert!(!instance.substs.needs_infer());
 
-        let fn_abi = FnAbi::of_instance(self, instance, &[]);
+        let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
         self.linkage.set(base::linkage_to_gcc(linkage));
         let _decl = self.declare_fn(symbol_name, &fn_abi);
         //let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 2ff2ee7b852..9c39c8f91a1 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -4,7 +4,7 @@ use gccjit::{Struct, Type};
 use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
 use rustc_middle::bug;
 use rustc_middle::ty::{self, Ty, TypeFoldable};
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
@@ -160,7 +160,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
                     ty::Adt(def, _) if def.is_box() => {
                         cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx, true))
                     }
-                    ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])),
+                    ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())),
                     _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
                 };
             cx.scalar_types.borrow_mut().insert(self.ty, ty);