Skip to content

Commit

Permalink
Use LLVM's UEFI targets
Browse files Browse the repository at this point in the history
The UEFI targets previously passed Windows targets to LLVM, because
that's what they're the most similar to.

That's not ideal though (part of this problem was analyzed in 21e062d),
but it seems like LLVM has since the introduction of these targets
gained support for UEFI in-tree, so we should just use that:
https://discourse.llvm.org/t/rfc-uefi-driver-support-uefi-target/73261
  • Loading branch information
madsmtm committed Nov 3, 2024
1 parent 705cfe0 commit dcd0c86
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target {
base.features = "+v8a".into();

Target {
llvm_target: "aarch64-unknown-windows".into(),
llvm_target: "aarch64-unknown-uefi".into(),
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 UEFI".into()),
tier: Some(2),
Expand Down
58 changes: 2 additions & 56 deletions compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// UEFI systems always run in protected-mode, have the interrupt-controller pre-configured and
// force a single-CPU execution.
// The cdecl ABI is used. It differs from the stdcall or fastcall ABI.
// "i686-unknown-windows" is used to get the minimal subset of windows-specific features.

use crate::spec::{Target, base};

Expand All @@ -23,61 +22,8 @@ pub(crate) fn target() -> Target {
// arguments, thus giving you access to full MMX/SSE acceleration.
base.features = "-mmx,-sse,+soft-float".into();

// Use -GNU here, because of the reason below:
// Background and Problem:
// If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic
// _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol.
// A real issue is __aulldiv() is referred by __udivdi3() - udivmod_inner!(), from
// https://github.com/rust-lang-nursery/compiler-builtins.
// As result, rust-lld generates link error finally.
// Root-cause:
// In rust\src\llvm-project\llvm\lib\Target\X86\X86ISelLowering.cpp,
// we have below code to use MSVC intrinsics. It assumes MSVC target
// will link MSVC library. But that is NOT true in UEFI environment.
// UEFI does not link any MSVC or GCC standard library.
// if (Subtarget.isTargetKnownWindowsMSVC() ||
// Subtarget.isTargetWindowsItanium()) {
// // Setup Windows compiler runtime calls.
// setLibcallName(RTLIB::SDIV_I64, "_alldiv");
// setLibcallName(RTLIB::UDIV_I64, "_aulldiv");
// setLibcallName(RTLIB::SREM_I64, "_allrem");
// setLibcallName(RTLIB::UREM_I64, "_aullrem");
// setLibcallName(RTLIB::MUL_I64, "_allmul");
// setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::X86_StdCall);
// setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::X86_StdCall);
// setLibcallCallingConv(RTLIB::SREM_I64, CallingConv::X86_StdCall);
// setLibcallCallingConv(RTLIB::UREM_I64, CallingConv::X86_StdCall);
// setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::X86_StdCall);
// }
// The compiler intrinsics should be implemented by compiler-builtins.
// Unfortunately, compiler-builtins has not provided those intrinsics yet. Such as:
// i386/divdi3.S
// i386/lshrdi3.S
// i386/moddi3.S
// i386/muldi3.S
// i386/udivdi3.S
// i386/umoddi3.S
// Possible solution:
// 1. Eliminate Intrinsics generation.
// 1.1 Choose different target to bypass isTargetKnownWindowsMSVC().
// 1.2 Remove the "Setup Windows compiler runtime calls" in LLVM
// 2. Implement Intrinsics.
// We evaluated all options.
// #2 is hard because we need implement the intrinsics (_aulldiv) generated
// from the other intrinsics (__udivdi3) implementation with the same
// functionality (udivmod_inner). If we let _aulldiv() call udivmod_inner!(),
// then we are in loop. We may have to find another way to implement udivmod_inner!().
// #1.2 may break the existing usage.
// #1.1 seems the simplest solution today.
// The IA32 -gnu calling convention is same as the one defined in UEFI specification.
// It uses cdecl, EAX/ECX/EDX as volatile register, and EAX/EDX as return value.
// We also checked the LLVM X86TargetLowering, the differences between -gnu and -msvc
// is fmodf(f32), longjmp() and TLS. None of them impacts the UEFI code.
// As a result, we choose -gnu for i686 version before those intrinsics are implemented in
// compiler-builtins. After compiler-builtins implements all required intrinsics, we may
// remove -gnu and use the default one.
Target {
llvm_target: "i686-unknown-windows-gnu".into(),
llvm_target: "i686-unknown-uefi".into(),
metadata: crate::spec::TargetMetadata {
description: Some("32-bit UEFI".into()),
tier: Some(2),
Expand All @@ -86,7 +32,7 @@ pub(crate) fn target() -> Target {
},
pointer_width: 32,
data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
i128:128-f64:32:64-f80:32-n8:16:32-S128"
.into(),
arch: "x86".into(),

Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// uefi-base module for generic UEFI options. On x86_64 systems (mostly called "x64" in the spec)
// UEFI systems always run in long-mode, have the interrupt-controller pre-configured and force a
// single-CPU execution.
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
// The win64 ABI is used. It differs from the sysv64 ABI.

use crate::abi::call::Conv;
use crate::spec::{Target, base};
Expand All @@ -28,7 +27,7 @@ pub(crate) fn target() -> Target {
base.features = "-mmx,-sse,+soft-float".into();

Target {
llvm_target: "x86_64-unknown-windows".into(),
llvm_target: "x86_64-unknown-uefi".into(),
metadata: crate::spec::TargetMetadata {
description: Some("64-bit UEFI".into()),
tier: Some(2),
Expand Down

0 comments on commit dcd0c86

Please sign in to comment.