Skip to content

Commit dea3d41

Browse files
committed
[UEFI] X86_64 UEFI Clang Driver
Introduce changes necessary for UEFI X86_64 target Clang driver. Reviewed By: phosek Differential Revision: https://reviews.llvm.org/D159541
1 parent c63e68b commit dea3d41

File tree

9 files changed

+229
-0
lines changed

9 files changed

+229
-0
lines changed

clang/lib/Basic/Targets.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
625625
case llvm::Triple::Solaris:
626626
return std::make_unique<SolarisTargetInfo<X86_64TargetInfo>>(Triple,
627627
Opts);
628+
case llvm::Triple::UEFI:
629+
return std::make_unique<UEFIX86_64TargetInfo>(Triple, Opts);
630+
628631
case llvm::Triple::Win32: {
629632
switch (Triple.getEnvironment()) {
630633
case llvm::Triple::Cygnus:

clang/lib/Basic/Targets/OSTargets.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,21 @@ class LLVM_LIBRARY_VISIBILITY ZOSTargetInfo : public OSTargetInfo<Target> {
778778
}
779779
};
780780

781+
// UEFI target
782+
template <typename Target>
783+
class LLVM_LIBRARY_VISIBILITY UEFITargetInfo : public OSTargetInfo<Target> {
784+
protected:
785+
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
786+
MacroBuilder &Builder) const override {}
787+
788+
public:
789+
UEFITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
790+
: OSTargetInfo<Target>(Triple, Opts) {
791+
this->WCharType = TargetInfo::UnsignedShort;
792+
this->WIntType = TargetInfo::UnsignedShort;
793+
}
794+
};
795+
781796
void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
782797
MacroBuilder &Builder);
783798

clang/lib/Basic/Targets/X86.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,43 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
825825
}
826826
};
827827

828+
// x86-64 UEFI target
829+
class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo
830+
: public UEFITargetInfo<X86_64TargetInfo> {
831+
public:
832+
UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
833+
: UEFITargetInfo<X86_64TargetInfo>(Triple, Opts) {
834+
this->TheCXXABI.set(TargetCXXABI::Microsoft);
835+
this->MaxTLSAlign = 8192u * this->getCharWidth();
836+
this->resetDataLayout("e-m:w-p270:32:32-p271:32:32-p272:64:64-"
837+
"i64:64-i128:128-f80:128-n8:16:32:64-S128");
838+
}
839+
840+
void getTargetDefines(const LangOptions &Opts,
841+
MacroBuilder &Builder) const override {
842+
getOSDefines(Opts, X86TargetInfo::getTriple(), Builder);
843+
}
844+
845+
BuiltinVaListKind getBuiltinVaListKind() const override {
846+
return TargetInfo::CharPtrBuiltinVaList;
847+
}
848+
849+
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
850+
switch (CC) {
851+
case CC_C:
852+
case CC_Win64:
853+
return CCCR_OK;
854+
default:
855+
return CCCR_Warning;
856+
}
857+
}
858+
859+
TargetInfo::CallingConvKind
860+
getCallingConvKind(bool ClangABICompat4) const override {
861+
return CCK_MicrosoftWin64;
862+
}
863+
};
864+
828865
// x86-64 Windows target
829866
class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
830867
: public WindowsTargetInfo<X86_64TargetInfo> {

clang/lib/Driver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ add_clang_library(clangDriver
7878
ToolChains/Solaris.cpp
7979
ToolChains/SPIRV.cpp
8080
ToolChains/TCE.cpp
81+
ToolChains/UEFI.cpp
8182
ToolChains/VEToolchain.cpp
8283
ToolChains/WebAssembly.cpp
8384
ToolChains/XCore.cpp

clang/lib/Driver/Driver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "ToolChains/SPIRV.h"
4646
#include "ToolChains/Solaris.h"
4747
#include "ToolChains/TCE.h"
48+
#include "ToolChains/UEFI.h"
4849
#include "ToolChains/VEToolchain.h"
4950
#include "ToolChains/WebAssembly.h"
5051
#include "ToolChains/XCore.h"
@@ -6288,6 +6289,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
62886289
case llvm::Triple::Mesa3D:
62896290
TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
62906291
break;
6292+
case llvm::Triple::UEFI:
6293+
TC = std::make_unique<toolchains::UEFI>(*this, Target, Args);
6294+
break;
62916295
case llvm::Triple::Win32:
62926296
switch (Target.getEnvironment()) {
62936297
default:

clang/lib/Driver/ToolChains/UEFI.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "UEFI.h"
10+
#include "CommonArgs.h"
11+
#include "Darwin.h"
12+
#include "clang/Basic/CharInfo.h"
13+
#include "clang/Basic/Version.h"
14+
#include "clang/Config/config.h"
15+
#include "clang/Driver/Compilation.h"
16+
#include "clang/Driver/Driver.h"
17+
#include "clang/Driver/Options.h"
18+
#include "clang/Driver/SanitizerArgs.h"
19+
#include "llvm/ADT/StringExtras.h"
20+
#include "llvm/ADT/StringSwitch.h"
21+
#include "llvm/Option/Arg.h"
22+
#include "llvm/Option/ArgList.h"
23+
#include "llvm/Support/FileSystem.h"
24+
#include "llvm/Support/MemoryBuffer.h"
25+
#include "llvm/Support/VirtualFileSystem.h"
26+
#include "llvm/TargetParser/Host.h"
27+
28+
using namespace clang::driver;
29+
using namespace clang::driver::toolchains;
30+
using namespace clang;
31+
using namespace llvm::opt;
32+
33+
UEFI::UEFI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
34+
: ToolChain(D, Triple, Args) {
35+
getProgramPaths().push_back(getDriver().getInstalledDir());
36+
if (getDriver().getInstalledDir() != getDriver().Dir)
37+
getProgramPaths().push_back(getDriver().Dir);
38+
}
39+
40+
Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); }
41+
42+
void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
43+
const InputInfo &Output,
44+
const InputInfoList &Inputs,
45+
const ArgList &Args,
46+
const char *LinkingOutput) const {
47+
ArgStringList CmdArgs;
48+
auto &TC = static_cast<const toolchains::UEFI &>(getToolChain());
49+
50+
assert((Output.isFilename() || Output.isNothing()) && "invalid output");
51+
if (Output.isFilename())
52+
CmdArgs.push_back(
53+
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
54+
55+
CmdArgs.push_back("-nologo");
56+
57+
// TODO: Other UEFI binary subsystems that are currently unsupported:
58+
// efi_boot_service_driver, efi_rom, efi_runtime_driver.
59+
CmdArgs.push_back("-subsystem:efi_application");
60+
61+
// Default entry function name according to the TianoCore reference
62+
// implementation is EfiMain.
63+
// TODO: Provide a flag to override the entry function name.
64+
CmdArgs.push_back("-entry:EfiMain");
65+
66+
// "Terminal Service Aware" flag is not needed for UEFI applications.
67+
CmdArgs.push_back("-tsaware:no");
68+
69+
// EFI_APPLICATION to be linked as DLL by default.
70+
CmdArgs.push_back("-dll");
71+
72+
if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
73+
CmdArgs.push_back("-debug");
74+
75+
Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
76+
77+
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
78+
79+
// This should ideally be handled by ToolChain::GetLinkerPath but we need
80+
// to special case some linker paths. In the case of lld, we need to
81+
// translate 'lld' into 'lld-link'.
82+
StringRef Linker =
83+
Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
84+
if (Linker.empty() || Linker.equals("lld"))
85+
Linker = "lld-link";
86+
87+
auto LinkerPath = TC.GetProgramPath(Linker.str().c_str());
88+
auto LinkCmd = std::make_unique<Command>(
89+
JA, *this, ResponseFileSupport::AtFileUTF16(),
90+
Args.MakeArgString(LinkerPath), CmdArgs, Inputs, Output);
91+
C.addCommand(std::move(LinkCmd));
92+
}

clang/lib/Driver/ToolChains/UEFI.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
10+
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
11+
12+
#include "clang/Driver/Tool.h"
13+
#include "clang/Driver/ToolChain.h"
14+
15+
namespace clang {
16+
namespace driver {
17+
namespace tools {
18+
namespace uefi {
19+
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
20+
public:
21+
Linker(const ToolChain &TC) : Tool("uefi::Linker", "lld-link", TC) {}
22+
23+
bool hasIntegratedCPP() const override { return false; }
24+
bool isLinkJob() const override { return true; }
25+
26+
void ConstructJob(Compilation &C, const JobAction &JA,
27+
const InputInfo &Output, const InputInfoList &Inputs,
28+
const llvm::opt::ArgList &TCArgs,
29+
const char *LinkingOutput) const override;
30+
};
31+
} // end namespace uefi
32+
} // end namespace tools
33+
34+
namespace toolchains {
35+
36+
class LLVM_LIBRARY_VISIBILITY UEFI : public ToolChain {
37+
public:
38+
UEFI(const Driver &D, const llvm::Triple &Triple,
39+
const llvm::opt::ArgList &Args);
40+
41+
protected:
42+
Tool *buildLinker() const override;
43+
44+
public:
45+
bool HasNativeLLVMSupport() const override { return true; }
46+
UnwindTableLevel
47+
getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
48+
return UnwindTableLevel::Asynchronous;
49+
}
50+
bool isPICDefault() const override { return true; }
51+
bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
52+
return false;
53+
}
54+
bool isPICDefaultForced() const override { return true; }
55+
};
56+
57+
} // namespace toolchains
58+
} // namespace driver
59+
} // namespace clang
60+
61+
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H

clang/test/CodeGen/target-data.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
// RUN: FileCheck --check-prefix=X86_64 %s
2323
// X86_64: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
2424

25+
// RUN: %clang_cc1 -triple x86_64-unknown-uefi -emit-llvm -o - %s | \
26+
// RUN: FileCheck --check-prefix=X86_64_UEFI %s
27+
// 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"
28+
2529
// RUN: %clang_cc1 -triple xcore-unknown-unknown -emit-llvm -o - %s | \
2630
// RUN: FileCheck --check-prefix=XCORE %s
2731
// XCORE: target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32"

clang/test/Driver/uefi.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang -### %s --target=x86_64-unknown-uefi \
2+
// RUN: --sysroot=%S/platform -fuse-ld=lld -g 2>&1 \
3+
// RUN: | FileCheck -check-prefixes=CHECK %s
4+
// CHECK: "-cc1"
5+
// CHECK-SAME: "-triple" "x86_64-unknown-uefi"
6+
// CHECK-SAME: "-mrelocation-model" "pic" "-pic-level" "2"
7+
// CHECK-SAME: "-mframe-pointer=all"
8+
// CHECK-NEXT: "-subsystem:efi_application"
9+
// CHECK-SAME: "-entry:EfiMain"
10+
// CHECK-SAME: "-tsaware:no"
11+
// CHECK-SAME: "-dll"
12+
// CHECK-SAME: "-debug"

0 commit comments

Comments
 (0)