diff options
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/abi.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/callee.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/context.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/declare.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 |
7 files changed, 76 insertions, 32 deletions
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index d478efc863a..a6fd2a7de6b 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -398,23 +398,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } fn llvm_cconv(&self) -> llvm::CallConv { - match self.conv { - Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv, - Conv::RustCold => llvm::ColdCallConv, - Conv::AmdGpuKernel => llvm::AmdGpuKernel, - Conv::AvrInterrupt => llvm::AvrInterrupt, - Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, - Conv::ArmAapcs => llvm::ArmAapcsCallConv, - Conv::Msp430Intr => llvm::Msp430Intr, - Conv::PtxKernel => llvm::PtxKernel, - Conv::X86Fastcall => llvm::X86FastcallCallConv, - Conv::X86Intr => llvm::X86_Intr, - Conv::X86Stdcall => llvm::X86StdcallCallConv, - Conv::X86ThisCall => llvm::X86_ThisCall, - Conv::X86VectorCall => llvm::X86_VectorCall, - Conv::X86_64SysV => llvm::X86_64_SysV, - Conv::X86_64Win64 => llvm::X86_64_Win64, - } + self.conv.into() } fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) { @@ -596,3 +580,25 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { llvm::get_param(self.llfn(), index as c_uint) } } + +impl From<Conv> for llvm::CallConv { + fn from(conv: Conv) -> Self { + match conv { + Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv, + Conv::RustCold => llvm::ColdCallConv, + Conv::AmdGpuKernel => llvm::AmdGpuKernel, + Conv::AvrInterrupt => llvm::AvrInterrupt, + Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, + Conv::ArmAapcs => llvm::ArmAapcsCallConv, + Conv::Msp430Intr => llvm::Msp430Intr, + Conv::PtxKernel => llvm::PtxKernel, + Conv::X86Fastcall => llvm::X86FastcallCallConv, + Conv::X86Intr => llvm::X86_Intr, + Conv::X86Stdcall => llvm::X86StdcallCallConv, + Conv::X86ThisCall => llvm::X86_ThisCall, + Conv::X86VectorCall => llvm::X86_VectorCall, + Conv::X86_64SysV => llvm::X86_64_SysV, + Conv::X86_64Win64 => llvm::X86_64_Win64, + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 6f0d1b7ce84..70ff5c9617b 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -83,7 +83,20 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> let llfn = if tcx.sess.target.arch == "x86" && let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym) { - cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi) + // Fix for https://github.com/rust-lang/rust/issues/104453 + // On x86 Windows, LLVM uses 'L' as the prefix for any private + // global symbols, so when we create an undecorated function symbol + // that begins with an 'L' LLVM misinterprets that as a private + // global symbol that it created and so fails the compilation at a + // later stage since such a symbol must have a definition. + // + // To avoid this, we set the Storage Class to "DllImport" so that + // LLVM will prefix the name with `__imp_`. Ideally, we'd like the + // existing logic below to set the Storage Class, but it has an + // exemption for MinGW for backwards compatability. + let llfn = cx.declare_fn(&common::i686_decorated_name(&dllimport, common::is_mingw_gnu_toolchain(&tcx.sess.target), true), fn_abi); + unsafe { llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport); } + llfn } else { cx.declare_fn(sym, fn_abi) }; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index eaa2ccfc835..4dcc7cd5447 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -576,8 +576,14 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> { - if self.get_declared_value("main").is_none() { - Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type)) + let entry_name = self.sess().target.entry_name.as_ref(); + if self.get_declared_value(entry_name).is_none() { + Some(self.declare_entry_fn( + entry_name, + self.sess().target.entry_abi.into(), + llvm::UnnamedAddr::Global, + fn_type, + )) } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 129e336c7e4..53e8a291d1e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -462,7 +462,7 @@ fn build_variant_names_type_di_node<'ll, 'tcx>( cx, "VariantNames", variant_names_enum_base_type(cx), - variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32() as u64)), + variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())), containing_scope, ) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 14044d0f99b..cb558a50d91 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -91,9 +91,7 @@ fn build_c_style_enum_di_node<'ll, 'tcx>( tag_base_type(cx, enum_type_and_layout), enum_adt_def.discriminants(cx.tcx).map(|(variant_index, discr)| { let name = Cow::from(enum_adt_def.variant(variant_index).name.as_str()); - // Is there anything we can do to support 128-bit C-Style enums? - let value = discr.val as u64; - (name, value) + (name, discr.val) }), containing_scope, ), @@ -147,14 +145,11 @@ fn tag_base_type<'ll, 'tcx>( /// This is a helper function and does not register anything in the type map by itself. /// /// `variants` is an iterator of (discr-value, variant-name). -/// -// NOTE: Handling of discriminant values is somewhat inconsistent. They can appear as u128, -// u64, and i64. Here everything gets mapped to i64 because that's what LLVM's API expects. fn build_enumeration_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, type_name: &str, base_type: Ty<'tcx>, - enumerators: impl Iterator<Item = (Cow<'tcx, str>, u64)>, + enumerators: impl Iterator<Item = (Cow<'tcx, str>, u128)>, containing_scope: &'ll DIType, ) -> &'ll DIType { let is_unsigned = match base_type.kind() { @@ -162,21 +157,22 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( ty::Uint(_) => true, _ => bug!("build_enumeration_type_di_node() called with non-integer tag type."), }; + let (size, align) = cx.size_and_align_of(base_type); let enumerator_di_nodes: SmallVec<Option<&'ll DIType>> = enumerators .map(|(name, value)| unsafe { + let value = [value as u64, (value >> 64) as u64]; Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), name.as_ptr().cast(), name.len(), - value as i64, + value.as_ptr(), + size.bits() as libc::c_uint, is_unsigned, )) }) .collect(); - let (size, align) = cx.size_and_align_of(base_type); - unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index f79ef11720d..dc21a02cec4 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -90,6 +90,28 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) } + /// Declare an entry Function + /// + /// The ABI of this function can change depending on the target (although for now the same as + /// `declare_cfn`) + /// + /// If there’s a value with the same name already declared, the function will + /// update the declaration and return existing Value instead. + pub fn declare_entry_fn( + &self, + name: &str, + callconv: llvm::CallConv, + unnamed: llvm::UnnamedAddr, + fn_type: &'ll Type, + ) -> &'ll Value { + let visibility = if self.tcx.sess.target.default_hidden_visibility { + llvm::Visibility::Hidden + } else { + llvm::Visibility::Default + }; + declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type) + } + /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8f7728da9dd..f4519849730 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2127,7 +2127,8 @@ extern "C" { Builder: &DIBuilder<'a>, Name: *const c_char, NameLen: size_t, - Value: i64, + Value: *const u64, + SizeInBits: c_uint, IsUnsigned: bool, ) -> &'a DIEnumerator; |
