diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -641,6 +641,9 @@ case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); + case llvm::Triple::UEFI: + return std::make_unique(Triple, Opts); + case llvm::Triple::Win32: { switch (Triple.getEnvironment()) { case llvm::Triple::Cygnus: diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -843,6 +843,23 @@ } }; +// UEFI target +template +class LLVM_LIBRARY_VISIBILITY UEFITargetInfo : public OSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + Builder.defineMacro("__UEFI__"); + } + +public: + UEFITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo(Triple, Opts) { + this->WCharType = TargetInfo::UnsignedShort; + this->WIntType = TargetInfo::UnsignedShort; + } +}; + void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, MacroBuilder &Builder); diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -808,6 +808,50 @@ } }; +// x86-64 UEFI target +class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo + : public UEFITargetInfo { +public: + UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : UEFITargetInfo(Triple, Opts) { + LongWidth = LongAlign = 32; + DoubleAlign = LongLongAlign = 64; + IntMaxType = SignedLongLong; + Int64Type = SignedLongLong; + SizeType = UnsignedLongLong; + PtrDiffType = SignedLongLong; + IntPtrType = SignedLongLong; + LongDoubleWidth = LongDoubleAlign = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override { + Builder.defineMacro("_M_X64", "100"); + Builder.defineMacro("_M_AMD64", "100"); + getOSDefines(Opts, X86TargetInfo::getTriple(), Builder); + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::CharPtrBuiltinVaList; + } + + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override { + switch (CC) { + case CC_C: + case CC_Win64: + return CCCR_OK; + default: + return CCCR_Warning; + } + } + + TargetInfo::CallingConvKind + getCallingConvKind(bool ClangABICompat4) const override { + return CCK_MicrosoftWin64; + } +}; + // x86-64 Windows target class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo : public WindowsTargetInfo { diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -83,6 +83,7 @@ ToolChains/Solaris.cpp ToolChains/SPIRV.cpp ToolChains/TCE.cpp + ToolChains/UEFI.cpp ToolChains/VEToolchain.cpp ToolChains/WebAssembly.cpp ToolChains/XCore.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -50,6 +50,7 @@ #include "ToolChains/SPIRV.h" #include "ToolChains/Solaris.h" #include "ToolChains/TCE.h" +#include "ToolChains/UEFI.h" #include "ToolChains/VEToolchain.h" #include "ToolChains/WebAssembly.h" #include "ToolChains/XCore.h" @@ -700,6 +701,11 @@ } } + // If target is UEFI set default object format + if (Target.isUEFI()) { + Target.setObjectFormat(llvm::Triple::COFF); + } + return Target; } @@ -6147,6 +6153,9 @@ case llvm::Triple::Mesa3D: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::UEFI: + TC = std::make_unique(*this, Target, Args); + break; case llvm::Triple::Win32: switch (Target.getEnvironment()) { default: diff --git a/clang/lib/Driver/ToolChains/UEFI.h b/clang/lib/Driver/ToolChains/UEFI.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/UEFI.h @@ -0,0 +1,32 @@ +//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY UEFI : public ToolChain { +public: + UEFI(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool IsIntegratedAssemblerDefault() const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool isPICDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; + bool isPICDefaultForced() const override; +}; +} // namespace toolchains +} // namespace driver +} // namespace clang +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H diff --git a/clang/lib/Driver/ToolChains/UEFI.cpp b/clang/lib/Driver/ToolChains/UEFI.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/UEFI.cpp @@ -0,0 +1,59 @@ +//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UEFI.h" +#include "CommonArgs.h" +#include "Darwin.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +UEFI::UEFI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : ToolChain(D, Triple, Args) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + getProgramPaths().push_back(getDriver().Dir); +} + +bool UEFI::IsUnwindTablesDefault(const ArgList &Args) const { + // TODO(prabhukr):: What about x86_32? + return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || + getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64; +} + +bool UEFI::isPICDefault() const { + return getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::aarch64; +} + +bool UEFI::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; } + +bool UEFI::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::aarch64; +} + +bool UEFI::IsIntegratedAssemblerDefault() const { return true; } \ No newline at end of file diff --git a/clang/test/Driver/windows-thumbv7em.cpp b/clang/test/Driver/windows-thumbv7em.cpp --- a/clang/test/Driver/windows-thumbv7em.cpp +++ b/clang/test/Driver/windows-thumbv7em.cpp @@ -6,3 +6,11 @@ // RUN: | FileCheck %s --check-prefix CHECK-V6 // CHECK-V6: error: the target architecture 'thumbv6m' is not supported by the target 'thumbv6m-none-windows-eabihf' +// RUN: %clang -target thumb-unknown-eabi-coff -mcpu=cortex-m7 -### -c %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix CHECK-V7 +// CHECK-V7-NOT: error: the target architecture 'thumbv7em' is not supported by the target 'thumbv7em-unknown-eabihf' + +// RUN: %clang -target thumb-unknown-eabi-coff -mcpu=cortex-m1 -### -c %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix CHECK-V6 +// CHECK-V6: error: the target architecture 'thumbv6m' is not supported by the target 'thumbv6m-unknown-eabihf' + diff --git a/llvm/include/llvm/MC/TargetRegistry.h b/llvm/include/llvm/MC/TargetRegistry.h --- a/llvm/include/llvm/MC/TargetRegistry.h +++ b/llvm/include/llvm/MC/TargetRegistry.h @@ -564,7 +564,8 @@ case Triple::UnknownObjectFormat: llvm_unreachable("Unknown object format"); case Triple::COFF: - assert(T.isOSWindows() && "only Windows COFF is supported"); + assert((T.isOSWindows() || T.isUEFI()) && + "only Windows and UEFI COFF are supported"); S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), std::move(Emitter), RelaxAll, IncrementalLinkerCompatible); diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -199,6 +199,7 @@ NetBSD, OpenBSD, Solaris, + UEFI, Win32, ZOS, Haiku, @@ -580,6 +581,11 @@ return getOS() == Triple::Haiku; } + /// Tests whether the OS is UEFI. + bool isUEFI() const { + return getOS() == Triple::UEFI; + } + /// Tests whether the OS is Windows. bool isOSWindows() const { return getOS() == Triple::Win32; diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -85,7 +85,7 @@ Env = IsMachO; break; case Triple::COFF: - if (!TheTriple.isOSWindows()) + if (!TheTriple.isOSWindows() && !TheTriple.isUEFI()) report_fatal_error( "Cannot initialize MC for non-Windows COFF object files."); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1520,6 +1520,13 @@ if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF()) return new WindowsX86AsmBackend(T, false, STI); + if (TheTriple.isUEFI()) { + assert(TheTriple.isOSBinFormatCOFF() && + "Only COFF format is supported in UEFI environment."); + // $TODO(prabhukr): Create a new UEFIX86AsmBackend + return new WindowsX86AsmBackend(T, false, STI); + } + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); if (TheTriple.isOSIAMCU()) @@ -1539,6 +1546,13 @@ if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF()) return new WindowsX86AsmBackend(T, true, STI); + if (TheTriple.isUEFI()) { + assert(TheTriple.isOSBinFormatCOFF() && + "Only COFF format is supported in UEFI environment."); + // $TODO(prabhukr): Create a new UEFIX86AsmBackend + return new WindowsX86AsmBackend(T, true, STI); + } + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); if (TheTriple.isX32()) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -153,7 +153,8 @@ void X86MCAsmInfoGNUCOFF::anchor() { } X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) { - assert(Triple.isOSWindows() && "Windows is the only supported COFF target"); + assert((Triple.isOSWindows() || Triple.isUEFI()) && + "Windows and UEFI are the only supported COFF targets"); if (Triple.getArch() == Triple::x86_64) { PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -441,6 +441,8 @@ } else if (TheTriple.isOSCygMing() || TheTriple.isWindowsItaniumEnvironment()) { MAI = new X86MCAsmInfoGNUCOFF(TheTriple); + } else if (TheTriple.isUEFI()) { + MAI = new X86MCAsmInfoGNUCOFF(TheTriple); } else { // The default is ELF. MAI = new X86ELFMCAsmInfo(TheTriple); diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1947,7 +1947,8 @@ void X86AsmPrinter::EmitSEHInstruction(const MachineInstr *MI) { assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?"); - assert(getSubtarget().isOSWindows() && "SEH_ instruction Windows only"); + assert((getSubtarget().isOSWindows() || TM.getTargetTriple().isUEFI()) && + "SEH_ instruction Windows and UEFI only"); // Use the .cv_fpo directives if we're emitting CodeView on 32-bit x86. if (EmitFPOData) { diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -238,6 +238,7 @@ case RTEMS: return "rtems"; case Solaris: return "solaris"; case TvOS: return "tvos"; + case UEFI: return "uefi"; case WASI: return "wasi"; case WatchOS: return "watchos"; case Win32: return "windows"; @@ -588,6 +589,7 @@ .StartsWith("netbsd", Triple::NetBSD) .StartsWith("openbsd", Triple::OpenBSD) .StartsWith("solaris", Triple::Solaris) + .StartsWith("uefi", Triple::UEFI) .StartsWith("win32", Triple::Win32) .StartsWith("windows", Triple::Win32) .StartsWith("zos", Triple::ZOS) diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/X86/coff-alignment.ll b/llvm/test/ExecutionEngine/RuntimeDyld/X86/coff-alignment.ll --- a/llvm/test/ExecutionEngine/RuntimeDyld/X86/coff-alignment.ll +++ b/llvm/test/ExecutionEngine/RuntimeDyld/X86/coff-alignment.ll @@ -1,6 +1,7 @@ ; XFAIL: target=aarch64-pc-windows-{{.*}} ; REQUIRES: system-windows ; RUN: opt -mtriple=x86_64-pc-win32-coff %s -o - | lli +; RUN: opt -mtriple=x86_64-unknown-coff %s -o - | lli @o = common global i32 0, align 4 diff --git a/llvm/test/Instrumentation/InstrProfiling/profiling.ll b/llvm/test/Instrumentation/InstrProfiling/profiling.ll --- a/llvm/test/Instrumentation/InstrProfiling/profiling.ll +++ b/llvm/test/Instrumentation/InstrProfiling/profiling.ll @@ -7,6 +7,7 @@ ; RUN: opt < %s -mtriple=x86_64-scei-ps4 -passes=instrprof -S | FileCheck %s --check-prefixes=ELF,PS ; RUN: opt < %s -mtriple=x86_64-sie-ps5 -passes=instrprof -S | FileCheck %s --check-prefixes=ELF,PS ; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF +; RUN: opt < %s -mtriple=x86_64-unknown-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF ; RUN: opt < %s -mtriple=powerpc64-ibm-aix-xcoff -passes=instrprof -S | FileCheck %s --check-prefixes=XCOFF ; RUN: opt < %s -mtriple=x86_64-pc-freebsd13 -passes=instrprof -S | FileCheck %s --check-prefixes=ELF diff --git a/llvm/test/Transforms/PGOProfile/comdat_rename.ll b/llvm/test/Transforms/PGOProfile/comdat_rename.ll --- a/llvm/test/Transforms/PGOProfile/comdat_rename.ll +++ b/llvm/test/Transforms/PGOProfile/comdat_rename.ll @@ -1,5 +1,6 @@ ; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s ; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-unknown-coff -passes=pgo-instr-gen -do-comdat-renaming=true -S | FileCheck %s ; Rename Comdat group and its function. $f = comdat any