Prabhuk updated this revision to Diff 557153.
Prabhuk added a comment.

Update X86 backend to use Microsoft ABI for UEFI target.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152206/new/

https://reviews.llvm.org/D152206

Files:
  clang/lib/Basic/Targets.cpp
  clang/lib/Basic/Targets/OSTargets.h
  clang/lib/Basic/Targets/X86.h
  clang/lib/Driver/CMakeLists.txt
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/UEFI.cpp
  clang/lib/Driver/ToolChains/UEFI.h
  clang/test/Driver/uefi.c
  llvm/lib/IR/DataLayout.cpp
  llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
  llvm/lib/Target/X86/X86RegisterInfo.cpp
  llvm/lib/Target/X86/X86RegisterInfo.h
  llvm/lib/Target/X86/X86Subtarget.h
  llvm/lib/TargetParser/Triple.cpp
  llvm/unittests/TargetParser/TripleTest.cpp

Index: llvm/unittests/TargetParser/TripleTest.cpp
===================================================================
--- llvm/unittests/TargetParser/TripleTest.cpp
+++ llvm/unittests/TargetParser/TripleTest.cpp
@@ -462,6 +462,7 @@
   EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
   EXPECT_EQ(Triple::UEFI, T.getOS());
   EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+  EXPECT_EQ(Triple::COFF, T.getObjectFormat());
 
   T = Triple("wasm32-unknown-unknown");
   EXPECT_EQ(Triple::wasm32, T.getArch());
Index: llvm/lib/TargetParser/Triple.cpp
===================================================================
--- llvm/lib/TargetParser/Triple.cpp
+++ llvm/lib/TargetParser/Triple.cpp
@@ -799,6 +799,8 @@
   case Triple::x86_64:
     if (T.isOSWindows())
       return Triple::COFF;
+    else if (T.isUEFI())
+      return Triple::COFF;
     return Triple::ELF;
 
   case Triple::aarch64_be:
Index: llvm/lib/Target/X86/X86Subtarget.h
===================================================================
--- llvm/lib/Target/X86/X86Subtarget.h
+++ llvm/lib/Target/X86/X86Subtarget.h
@@ -332,9 +332,14 @@
 
   bool isTargetCygMing() const { return TargetTriple.isOSCygMing(); }
 
+  // bool isOSWindows() const { return (TargetTriple.isOSWindows() ||
+  // TargetTriple.isUEFI()); }
+
   bool isOSWindows() const { return TargetTriple.isOSWindows(); }
 
-  bool isTargetWin64() const { return Is64Bit && isOSWindows(); }
+  bool isTargetWin64() const {
+    return Is64Bit && (isOSWindows() || TargetTriple.isUEFI());
+  }
 
   bool isTargetWin32() const { return !Is64Bit && isOSWindows(); }
 
@@ -360,9 +365,11 @@
     case CallingConv::X86_ThisCall:
     case CallingConv::X86_VectorCall:
     case CallingConv::Intel_OCL_BI:
+      llvm::outs() << "RETURNING TRUE FOR CALLING CONVENTION PRABPRAB \n";
       return isTargetWin64();
     // This convention allows using the Win64 convention on other targets.
     case CallingConv::Win64:
+      llvm::outs() << "RETURNING TRUE FOR CALLING CONVENTION PRABPRAB \n";
       return true;
     // This convention allows using the SysV convention on Windows targets.
     case CallingConv::X86_64_SysV:
Index: llvm/lib/Target/X86/X86RegisterInfo.h
===================================================================
--- llvm/lib/Target/X86/X86RegisterInfo.h
+++ llvm/lib/Target/X86/X86RegisterInfo.h
@@ -27,7 +27,7 @@
   ///
   bool Is64Bit;
 
-  /// IsWin64 - Is the target on of win64 flavours
+  /// IsWin64 - Is the target one of win64 flavours
   ///
   bool IsWin64;
 
Index: llvm/lib/Target/X86/X86RegisterInfo.cpp
===================================================================
--- llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -54,7 +54,7 @@
 
   // Cache some information.
   Is64Bit = TT.isArch64Bit();
-  IsWin64 = Is64Bit && TT.isOSWindows();
+  IsWin64 = Is64Bit && (TT.isOSWindows() || TT.isUEFI());
 
   // Use a callee-saved register as the base pointer.  These registers must
   // not conflict with any ABI requirements.  For example, in 32-bit mode PIC
Index: llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
===================================================================
--- llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -445,7 +445,7 @@
     // Force the use of an ELF container.
     MAI = new X86ELFMCAsmInfo(TheTriple);
   } else if (TheTriple.isWindowsMSVCEnvironment() ||
-             TheTriple.isWindowsCoreCLREnvironment()) {
+             TheTriple.isWindowsCoreCLREnvironment() || TheTriple.isUEFI()) {
     if (Options.getAssemblyLanguage().equals_insensitive("masm"))
       MAI = new X86MCAsmInfoMicrosoftMASM(TheTriple);
     else
@@ -453,8 +453,6 @@
   } 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);
Index: llvm/lib/IR/DataLayout.cpp
===================================================================
--- llvm/lib/IR/DataLayout.cpp
+++ llvm/lib/IR/DataLayout.cpp
@@ -171,7 +171,7 @@
     return "-m:l";
   if (T.isOSBinFormatMachO())
     return "-m:o";
-  if (T.isOSWindows() && T.isOSBinFormatCOFF())
+  if ((T.isOSWindows() || T.isUEFI()) && T.isOSBinFormatCOFF())
     return T.getArch() == Triple::x86 ? "-m:x" : "-m:w";
   if (T.isOSBinFormatXCOFF())
     return "-m:a";
Index: clang/test/Driver/uefi.c
===================================================================
--- /dev/null
+++ clang/test/Driver/uefi.c
@@ -0,0 +1,10 @@
+// RUN: %clang -### %s --target=x86_64-unknown-uefi \
+// RUN:     --sysroot=%S/platform -fuse-ld=lld 2>&1 \
+// RUN:     | FileCheck -check-prefixes=CHECK %s
+// RUN: %clang -### %s --target=x86_64-uefi \
+// RUN:     --sysroot=%S/platform -fuse-ld=lld 2>&1 \
+// RUN:     | FileCheck -check-prefixes=CHECK %s
+// CHECK: "-cc1"
+// CHECK-SAME: "-triple" "x86_64-unknown-uefi"
+// CHECK-SAME: "-mrelocation-model" "pic" "-pic-level" "2"
+// CHECK-SAME: "-mframe-pointer=all"
Index: clang/lib/Driver/ToolChains/UEFI.h
===================================================================
--- /dev/null
+++ clang/lib/Driver/ToolChains/UEFI.h
@@ -0,0 +1,62 @@
+//===--- 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/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace uefi {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+  Linker(const ToolChain &TC) : Tool("uefi::Linker", "lld-link", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+  bool isLinkJob() const override { return true; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+                    const InputInfo &Output, const InputInfoList &Inputs,
+                    const llvm::opt::ArgList &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+} // end namespace uefi
+} // end namespace tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY UEFI : public ToolChain {
+public:
+  UEFI(const Driver &D, const llvm::Triple &Triple,
+       const llvm::opt::ArgList &Args);
+
+protected:
+  Tool *buildLinker() const override;
+
+public:
+  bool HasNativeLLVMSupport() const override { return true; }
+  bool IsIntegratedAssemblerDefault() const override { return true; }
+  UnwindTableLevel
+  getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
+    return UnwindTableLevel::Asynchronous;
+  }
+  bool isPICDefault() const override { return true; }
+  bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+    return false;
+  }
+  bool isPICDefaultForced() const override { return true; }
+};
+
+} // namespace toolchains
+} // namespace driver
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
Index: clang/lib/Driver/ToolChains/UEFI.cpp
===================================================================
--- /dev/null
+++ clang/lib/Driver/ToolChains/UEFI.cpp
@@ -0,0 +1,115 @@
+//===--- 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/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/Host.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);
+}
+
+Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); }
+
+void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                                       const InputInfo &Output,
+                                       const InputInfoList &Inputs,
+                                       const ArgList &Args,
+                                       const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  auto &TC = static_cast<const toolchains::UEFI &>(getToolChain());
+
+  assert((Output.isFilename() || Output.isNothing()) && "invalid output");
+  if (Output.isFilename())
+    CmdArgs.push_back(
+        Args.MakeArgString(std::string("-out:") + Output.getFilename()));
+
+  CmdArgs.push_back("-nologo");
+
+  // Other UEFI binary subsystems that are currently unsupported:
+  // efi_boot_service_driver, efi_rom, efi_runtime_driver.
+  CmdArgs.push_back("-subsystem:efi_application");
+
+  // Default entry function name according to the TianaCore reference
+  // implementation is EfiMain. In the future we will add a flag to override the
+  // entry function name.
+  CmdArgs.push_back("-entry:EfiMain");
+
+  // "Terminal Service Aware" flag is not needed for UEFI applications.
+  CmdArgs.push_back("-tsaware:no");
+
+  // EFI_APPLICATION to be linked as DLL by default.
+  CmdArgs.push_back("-dll");
+
+  if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
+    CmdArgs.push_back("-debug");
+
+  Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
+
+  // Add filenames, libraries, and other linker inputs.
+  for (const auto &Input : Inputs) {
+    if (Input.isFilename()) {
+      CmdArgs.push_back(Input.getFilename());
+      continue;
+    }
+
+    const Arg &A = Input.getInputArg();
+    if (A.getOption().matches(options::OPT_l)) {
+      StringRef Lib = A.getValue();
+      const char *LinkLibArg;
+      if (Lib.endswith(".lib"))
+        LinkLibArg = Args.MakeArgString(Lib);
+      else
+        LinkLibArg = Args.MakeArgString(Lib + ".lib");
+      CmdArgs.push_back(LinkLibArg);
+      continue;
+    }
+
+    // Otherwise, this is some other kind of linker input option like -Wl, -z,
+    // or -L.
+    A.renderAsInput(Args, CmdArgs);
+  }
+
+  // This should ideally be handled by ToolChain::GetLinkerPath but we need
+  // to special case some linker paths. In the case of lld, we need to
+  // translate 'lld' into 'lld-link'.
+  StringRef Linker =
+      Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
+  if (Linker.empty() || Linker.equals_insensitive("lld"))
+    Linker = "lld-link";
+
+  auto LinkerPath = TC.GetProgramPath(Linker.str().c_str());
+  auto LinkCmd = std::make_unique<Command>(
+      JA, *this, ResponseFileSupport::AtFileUTF16(),
+      Args.MakeArgString(LinkerPath), CmdArgs, Inputs, Output);
+  C.addCommand(std::move(LinkCmd));
+}
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -45,6 +45,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"
@@ -6239,6 +6240,9 @@
     case llvm::Triple::Mesa3D:
       TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
       break;
+    case llvm::Triple::UEFI:
+      TC = std::make_unique<toolchains::UEFI>(*this, Target, Args);
+      break;
     case llvm::Triple::Win32:
       switch (Target.getEnvironment()) {
       default:
Index: clang/lib/Driver/CMakeLists.txt
===================================================================
--- clang/lib/Driver/CMakeLists.txt
+++ clang/lib/Driver/CMakeLists.txt
@@ -78,6 +78,7 @@
   ToolChains/Solaris.cpp
   ToolChains/SPIRV.cpp
   ToolChains/TCE.cpp
+  ToolChains/UEFI.cpp
   ToolChains/VEToolchain.cpp
   ToolChains/WebAssembly.cpp
   ToolChains/XCore.cpp
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -810,6 +810,43 @@
   }
 };
 
+// x86-64 UEFI target
+class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo
+    : public UEFITargetInfo<X86_64TargetInfo> {
+public:
+  UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : UEFITargetInfo<X86_64TargetInfo>(Triple, Opts) {
+    this->TheCXXABI.set(TargetCXXABI::Microsoft);
+    this->MaxTLSAlign = 8192u * this->getCharWidth();
+    this->resetDataLayout("e-m:w-p270:32:32-p271:32:32-p272:64:"
+                          "64-i64:64-f80:128-n8:16:32:64-S128");
+  }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override {
+    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<X86_64TargetInfo> {
Index: clang/lib/Basic/Targets/OSTargets.h
===================================================================
--- clang/lib/Basic/Targets/OSTargets.h
+++ clang/lib/Basic/Targets/OSTargets.h
@@ -760,6 +760,21 @@
   }
 };
 
+// UEFI target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY UEFITargetInfo : public OSTargetInfo<Target> {
+protected:
+  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+                    MacroBuilder &Builder) const override {}
+
+public:
+  UEFITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : OSTargetInfo<Target>(Triple, Opts) {
+    this->WCharType = TargetInfo::UnsignedShort;
+    this->WIntType = TargetInfo::UnsignedShort;
+  }
+};
+
 void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
                        MacroBuilder &Builder);
 
Index: clang/lib/Basic/Targets.cpp
===================================================================
--- clang/lib/Basic/Targets.cpp
+++ clang/lib/Basic/Targets.cpp
@@ -630,6 +630,9 @@
     case llvm::Triple::Solaris:
       return std::make_unique<SolarisTargetInfo<X86_64TargetInfo>>(Triple,
                                                                    Opts);
+    case llvm::Triple::UEFI:
+      return std::make_unique<UEFIX86_64TargetInfo>(Triple, Opts);
+
     case llvm::Triple::Win32: {
       switch (Triple.getEnvironment()) {
       case llvm::Triple::Cygnus:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D15... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Petr Hosek via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Petr Hosek via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Prabhu Karthikeyan Rajasekaran via Phabricator via cfe-commits
    • [PATCH... Petr Hosek via Phabricator via cfe-commits
    • [PATCH... Fangrui Song via Phabricator via cfe-commits

Reply via email to