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