Reland "[Driver] Add toolchain for X86_64 UEFI target" (#109364)
Reverts llvm/llvm-project#109340 Addressing the failed MAC Clang Driver test as part of this reland.
This commit is contained in:
@@ -613,6 +613,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
|
||||
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:
|
||||
|
||||
@@ -778,6 +778,21 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@@ -814,6 +814,43 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// 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-i128:128-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> {
|
||||
|
||||
@@ -78,6 +78,7 @@ add_clang_library(clangDriver
|
||||
ToolChains/Solaris.cpp
|
||||
ToolChains/SPIRV.cpp
|
||||
ToolChains/TCE.cpp
|
||||
ToolChains/UEFI.cpp
|
||||
ToolChains/VEToolchain.cpp
|
||||
ToolChains/WebAssembly.cpp
|
||||
ToolChains/XCore.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"
|
||||
@@ -6422,6 +6423,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
|
||||
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:
|
||||
|
||||
88
clang/lib/Driver/ToolChains/UEFI.cpp
Normal file
88
clang/lib/Driver/ToolChains/UEFI.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//===--- UEFI.cpp - UEFI ToolChain Implementations -----------------------===//
|
||||
//
|
||||
// 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) {}
|
||||
|
||||
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");
|
||||
|
||||
// TODO: 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 TianoCore reference
|
||||
// implementation is EfiMain.
|
||||
// TODO: Provide 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);
|
||||
|
||||
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
|
||||
|
||||
// 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 == "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));
|
||||
}
|
||||
59
clang/lib/Driver/ToolChains/UEFI.h
Normal file
59
clang/lib/Driver/ToolChains/UEFI.h
Normal file
@@ -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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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::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; }
|
||||
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 clang::driver
|
||||
|
||||
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
|
||||
3
clang/test/CodeGen/X86/uefi-data-layout.c
Normal file
3
clang/test/CodeGen/X86/uefi-data-layout.c
Normal file
@@ -0,0 +1,3 @@
|
||||
// RUN: %clang -target x86_64-unknown-uefi -S -emit-llvm -o - %s | \
|
||||
// RUN: FileCheck --check-prefix=X86_64_UEFI %s
|
||||
// X86_64_UEFI: target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||
12
clang/test/Driver/uefi-constructed-args.c
Normal file
12
clang/test/Driver/uefi-constructed-args.c
Normal file
@@ -0,0 +1,12 @@
|
||||
// RUN: %clang_cl -### --target=x86_64-unknown-uefi -g -- %s 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"
|
||||
// CHECK-NEXT: "-nologo"
|
||||
// CHECK-SAME: "-subsystem:efi_application"
|
||||
// CHECK-SAME: "-entry:EfiMain"
|
||||
// CHECK-SAME: "-tsaware:no"
|
||||
// CHECK-SAME: "-dll"
|
||||
// CHECK-SAME: "-debug"
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "clang/Basic/DiagnosticIDs.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/TargetOptions.h"
|
||||
#include "clang/Driver/Compilation.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
@@ -574,6 +575,26 @@ TEST(CompilerInvocation, SplitSwarfSingleCrash) {
|
||||
EXPECT_TRUE(CI); // no-crash
|
||||
}
|
||||
|
||||
TEST(ToolChainTest, UEFICallingConventionTest) {
|
||||
clang::CompilerInstance compiler;
|
||||
compiler.createDiagnostics();
|
||||
|
||||
std::string TrStr = "x86_64-unknown-uefi";
|
||||
llvm::Triple Tr(TrStr);
|
||||
Tr.setOS(llvm::Triple::OSType::UEFI);
|
||||
Tr.setVendor(llvm::Triple::VendorType::UnknownVendor);
|
||||
Tr.setEnvironment(llvm::Triple::EnvironmentType::UnknownEnvironment);
|
||||
Tr.setArch(llvm::Triple::ArchType::x86_64);
|
||||
|
||||
compiler.getTargetOpts().Triple = Tr.getTriple();
|
||||
compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
|
||||
compiler.getDiagnostics(),
|
||||
std::make_shared<clang::TargetOptions>(compiler.getTargetOpts())));
|
||||
|
||||
EXPECT_EQ(compiler.getTarget().getCallingConvKind(true),
|
||||
TargetInfo::CallingConvKind::CCK_MicrosoftWin64);
|
||||
}
|
||||
|
||||
TEST(GetDriverMode, PrefersLastDriverMode) {
|
||||
static constexpr const char *Args[] = {"clang-cl", "--driver-mode=foo",
|
||||
"--driver-mode=bar", "foo.cpp"};
|
||||
|
||||
Reference in New Issue
Block a user