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 "clang/Config/config.h"
11#include "clang/Driver/CommonArgs.h"
12#include "clang/Driver/Compilation.h"
13#include "clang/Driver/Driver.h"
14#include "clang/Driver/SanitizerArgs.h"
15#include "clang/Options/Options.h"
16#include "llvm/Option/Arg.h"
17#include "llvm/Option/ArgList.h"
18#include "llvm/Support/VirtualFileSystem.h"
19#include "llvm/TargetParser/Host.h"
20
21using namespace clang::driver;
22using namespace clang::driver::toolchains;
23using namespace clang;
24using namespace llvm::opt;
25
26UEFI::UEFI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
27 : ToolChain(D, Triple, Args) {
28 getProgramPaths().push_back(Elt: getDriver().Dir);
29}
30
31Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); }
32
33void UEFI::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
34 ArgStringList &CC1Args) const {
35 if (DriverArgs.hasArg(Ids: options::OPT_nostdinc))
36 return;
37
38 if (!DriverArgs.hasArg(Ids: options::OPT_nobuiltininc)) {
39 SmallString<128> Dir(getDriver().ResourceDir);
40 llvm::sys::path::append(path&: Dir, a: "include");
41 addSystemInclude(DriverArgs, CC1Args, Path: Dir.str());
42 }
43
44 if (DriverArgs.hasArg(Ids: options::OPT_nostdlibinc))
45 return;
46
47 if (std::optional<std::string> Path = getStdlibIncludePath())
48 addSystemInclude(DriverArgs, CC1Args, Path: *Path);
49}
50
51void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
52 const InputInfo &Output,
53 const InputInfoList &Inputs,
54 const ArgList &Args,
55 const char *LinkingOutput) const {
56 ArgStringList CmdArgs;
57 auto &TC = static_cast<const toolchains::UEFI &>(getToolChain());
58
59 assert((Output.isFilename() || Output.isNothing()) && "invalid output");
60 if (Output.isFilename())
61 CmdArgs.push_back(
62 Elt: Args.MakeArgString(Str: std::string("/out:") + Output.getFilename()));
63
64 CmdArgs.push_back(Elt: "/nologo");
65
66 // Default entry function name according to the TianoCore reference
67 // implementation is EfiMain. -Wl,/subsystem:... or -Wl,/entry:... can
68 // override these since they will be added later in AddLinkerInputs.
69 CmdArgs.push_back(Elt: "/subsystem:efi_application");
70 CmdArgs.push_back(Elt: "/entry:EfiMain");
71
72 // "Terminal Service Aware" flag is not needed for UEFI applications.
73 CmdArgs.push_back(Elt: "/tsaware:no");
74
75 if (Args.hasArg(Ids: options::OPT_g_Group, Ids: options::OPT__SLASH_Z7))
76 CmdArgs.push_back(Elt: "/debug");
77
78 Args.AddAllArgValues(Output&: CmdArgs, Id0: options::OPT__SLASH_link);
79
80 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
81
82 // Sample these options first so they are claimed even under -nostdlib et al.
83 bool NoLibc = Args.hasArg(Ids: options::OPT_nolibc);
84 if (!Args.hasArg(Ids: options::OPT_nostdlib, Ids: options::OPT_nodefaultlibs,
85 Ids: options::OPT_r)) {
86 addSanitizerRuntimes(TC, Args, CmdArgs);
87
88 addXRayRuntime(TC, Args, CmdArgs);
89
90 TC.addProfileRTLibs(Args, CmdArgs);
91
92 // TODO: When compiler-rt/lib/builtins is ready, enable this call:
93 // AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
94
95 if (!NoLibc) {
96 // TODO: When there is a libc ready, add it here.
97 }
98 }
99
100 // This should ideally be handled by ToolChain::GetLinkerPath but we need
101 // to special case some linker paths. In the case of lld, we need to
102 // translate 'lld' into 'lld-link'.
103 StringRef Linker = Args.getLastArgValue(Id: options::OPT_fuse_ld_EQ,
104 Default: TC.getDriver().getPreferredLinker());
105 if (Linker.empty() || Linker == "lld")
106 Linker = "lld-link";
107
108 auto LinkerPath = TC.GetProgramPath(Name: Linker.str().c_str());
109 auto LinkCmd = std::make_unique<Command>(
110 args: JA, args: *this, args: ResponseFileSupport::AtFileUTF16(),
111 args: Args.MakeArgString(Str: LinkerPath), args&: CmdArgs, args: Inputs, args: Output);
112 C.addCommand(C: std::move(LinkCmd));
113}
114