114 lines · cpp
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-exception6//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(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(options::OPT_nostdinc))36 return;37 38 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {39 SmallString<128> Dir(getDriver().ResourceDir);40 llvm::sys::path::append(Dir, "include");41 addSystemInclude(DriverArgs, CC1Args, Dir.str());42 }43 44 if (DriverArgs.hasArg(options::OPT_nostdlibinc))45 return;46 47 if (std::optional<std::string> Path = getStdlibIncludePath())48 addSystemInclude(DriverArgs, CC1Args, *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 Args.MakeArgString(std::string("/out:") + Output.getFilename()));63 64 CmdArgs.push_back("/nologo");65 66 // Default entry function name according to the TianoCore reference67 // implementation is EfiMain. -Wl,/subsystem:... or -Wl,/entry:... can68 // override these since they will be added later in AddLinkerInputs.69 CmdArgs.push_back("/subsystem:efi_application");70 CmdArgs.push_back("/entry:EfiMain");71 72 // "Terminal Service Aware" flag is not needed for UEFI applications.73 CmdArgs.push_back("/tsaware:no");74 75 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))76 CmdArgs.push_back("/debug");77 78 Args.AddAllArgValues(CmdArgs, 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(options::OPT_nolibc);84 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,85 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 need101 // to special case some linker paths. In the case of lld, we need to102 // translate 'lld' into 'lld-link'.103 StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ,104 TC.getDriver().getPreferredLinker());105 if (Linker.empty() || Linker == "lld")106 Linker = "lld-link";107 108 auto LinkerPath = TC.GetProgramPath(Linker.str().c_str());109 auto LinkCmd = std::make_unique<Command>(110 JA, *this, ResponseFileSupport::AtFileUTF16(),111 Args.MakeArgString(LinkerPath), CmdArgs, Inputs, Output);112 C.addCommand(std::move(LinkCmd));113}114