xref: /llvm-project/clang/lib/Driver/ToolChains/UEFI.cpp (revision dce2245ba49fad419e551b0143f41431ec8e7f03)
1 //===--- UEFI.cpp - UEFI ToolChain Implementations -----------------------===//
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 
36 Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); }
37 
38 void UEFI::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
39                                      ArgStringList &CC1Args) const {
40   if (DriverArgs.hasArg(options::OPT_nostdinc))
41     return;
42 
43   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
44     SmallString<128> Dir(getDriver().ResourceDir);
45     llvm::sys::path::append(Dir, "include");
46     addSystemInclude(DriverArgs, CC1Args, Dir.str());
47   }
48 
49   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
50     return;
51 
52   if (std::optional<std::string> Path = getStdlibIncludePath())
53     addSystemInclude(DriverArgs, CC1Args, *Path);
54 }
55 
56 void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
57                                        const InputInfo &Output,
58                                        const InputInfoList &Inputs,
59                                        const ArgList &Args,
60                                        const char *LinkingOutput) const {
61   ArgStringList CmdArgs;
62   auto &TC = static_cast<const toolchains::UEFI &>(getToolChain());
63 
64   assert((Output.isFilename() || Output.isNothing()) && "invalid output");
65   if (Output.isFilename())
66     CmdArgs.push_back(
67         Args.MakeArgString(std::string("-out:") + Output.getFilename()));
68 
69   CmdArgs.push_back("-nologo");
70 
71   // TODO: Other UEFI binary subsystems that are currently unsupported:
72   // efi_boot_service_driver, efi_rom, efi_runtime_driver.
73   CmdArgs.push_back("-subsystem:efi_application");
74 
75   // Default entry function name according to the TianoCore reference
76   // implementation is EfiMain.
77   // TODO: Provide a flag to override the entry function name.
78   CmdArgs.push_back("-entry:EfiMain");
79 
80   // "Terminal Service Aware" flag is not needed for UEFI applications.
81   CmdArgs.push_back("-tsaware:no");
82 
83   // EFI_APPLICATION to be linked as DLL by default.
84   CmdArgs.push_back("-dll");
85 
86   if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
87     CmdArgs.push_back("-debug");
88 
89   Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
90 
91   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
92 
93   // This should ideally be handled by ToolChain::GetLinkerPath but we need
94   // to special case some linker paths. In the case of lld, we need to
95   // translate 'lld' into 'lld-link'.
96   StringRef Linker =
97       Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
98   if (Linker.empty() || Linker == "lld")
99     Linker = "lld-link";
100 
101   auto LinkerPath = TC.GetProgramPath(Linker.str().c_str());
102   auto LinkCmd = std::make_unique<Command>(
103       JA, *this, ResponseFileSupport::AtFileUTF16(),
104       Args.MakeArgString(LinkerPath), CmdArgs, Inputs, Output);
105   C.addCommand(std::move(LinkCmd));
106 }
107