This is an archive of the discontinued LLVM Phabricator instance.

  • -
    clang/
  • -
    lib/
  • -
    Basic/
  • -
    Targets.cpp
  • -
    Targets/
  • -
    OSTargets.h
  • -
    X86.h
  • -
    Driver/
  • -
    CMakeLists.txt
  • -
    Driver.cpp
  • -
    ToolChains/
  • 1/1
    UEFI.h
  • 3/3
    UEFI.cpp
  • -
    test/Driver/
  • -
    Driver/
  • 1/1
    uefi.c

[UEFI] X86_64 UEFI Clang Driver
Needs ReviewPublic

Authored by Prabhuk on Sep 21 2023, 1:42 PM.

Details

Reviewers
Summary

Introduce changes necessary for UEFI X86_64 target Clang driver.

Event Timeline

Prabhuk created this revision.Sep 21 2023, 1:42 PM
Herald added a project: Restricted Project. · View Herald Transcript Sep 21 2023, 1:42 PM
Herald added a subscriber: pengfei. · View Herald Transcript
Prabhuk requested review of this revision.Sep 21 2023, 1:42 PM
Herald added a project: Restricted Project. · View Herald Transcript Sep 21 2023, 1:42 PM
Prabhuk added a reviewer: brad .Sep 21 2023, 1:59 PM
phosek added inline comments.Sep 21 2023, 11:46 PM
clang/lib/Driver/ToolChains/UEFI.cpp
59–60
63–65
Prabhuk updated this revision to Diff 557227.Sep 22 2023, 12:39 AM

Addressed review comments about the inline comments.

Prabhuk marked 2 inline comments as done.Sep 22 2023, 12:39 AM
brad added inline comments.Sep 22 2023, 10:39 AM
clang/lib/Driver/ToolChains/UEFI.h
47

Remove the IsIntegratedAssemblerDefault entry.

Prabhuk updated this revision to Diff 557372.Sep 26 2023, 1:06 PM

Removed IsIntegratedAssemblerDefault.

Prabhuk marked an inline comment as done.Sep 26 2023, 1:07 PM
phosek accepted this revision.Sep 29 2023, 4:33 PM

LGTM

This revision is now accepted and ready to land.Sep 29 2023, 4:33 PM
MaskRay requested changes to this revision.Sep 29 2023, 11:01 PM
MaskRay added inline comments.
clang/lib/Driver/ToolChains/UEFI.cpp
69

These options are not tested.

clang/test/Driver/uefi.c
5

This RUN line is not needed. If you want to check that x86_64-uefi normalizes to unknown, you can add a unittest instead.

This revision now requires changes to proceed.Sep 29 2023, 11:01 PM
brad added a comment.EditedMon, Nov 27, 12:56 PM

Is this still being worked on?

Prabhuk added a comment.Fri, Dec 1, 10:24 AM

Is this still being worked on?

Hi Brad! Yes. I am picking this up this week and expect to send out a patch in the next couple of days to address the comment.

Prabhuk updated this revision to Diff 558209.Mon, Dec 4, 9:48 AM

Updated the Driver test to address review comments.

Prabhuk marked 2 inline comments as done.Mon, Dec 4, 9:49 AM

Revision Contents

PathSize
clang/
lib/
Basic/
3 lines
Targets/
15 lines
37 lines
Driver/
1 line
4 lines
ToolChains/
61 lines
115 lines
test/
Driver/
11 lines
DiffIDBaseDescriptionCreatedLintUnit
Base Base
Diff 1557200 720fc11Sep 21 2023, 1:42 PM
Diff 2557227 cce062d Addressed review comments about the inline comments.Sep 22 2023, 12:39 AM
Diff 3557372 cce062d Removed IsIntegratedAssemblerDefault.Sep 26 2023, 1:06 PM
Diff 4558209 74e59e7 Updated the Driver test to address review comments.Mon, Dec 4, 9:48 AM
CommitTreeParentsAuthorSummaryDate
8f4f9c3d0147d03881a2878174e59e7752ac prabhukr
[UEFI] X86_64 UEFI Clang Driver (Show More...)
Mon, Dec 4, 8:54 AM

Diff 558209

clang/lib/Basic/Targets.cpp

Show First 20 LinesShow All 619 Lines▼ Show 20 Lines case llvm::Triple::Fuchsia:
return std::make_unique<FuchsiaTargetInfo<X86_64TargetInfo>>(Triple, return std::make_unique<FuchsiaTargetInfo<X86_64TargetInfo>>(Triple,
Opts); Opts);
case llvm::Triple::KFreeBSD: case llvm::Triple::KFreeBSD:
return std::make_unique<KFreeBSDTargetInfo<X86_64TargetInfo>>(Triple, return std::make_unique<KFreeBSDTargetInfo<X86_64TargetInfo>>(Triple,
Opts); Opts);
case llvm::Triple::Solaris: case llvm::Triple::Solaris:
return std::make_unique<SolarisTargetInfo<X86_64TargetInfo>>(Triple, return std::make_unique<SolarisTargetInfo<X86_64TargetInfo>>(Triple,
Opts); Opts);
case llvm::Triple::UEFI:
return std::make_unique<UEFIX86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Win32: { case llvm::Triple::Win32: {
switch (Triple.getEnvironment()) { switch (Triple.getEnvironment()) {
case llvm::Triple::Cygnus: case llvm::Triple::Cygnus:
return std::make_unique<CygwinX86_64TargetInfo>(Triple, Opts); return std::make_unique<CygwinX86_64TargetInfo>(Triple, Opts);
case llvm::Triple::GNU: case llvm::Triple::GNU:
return std::make_unique<MinGWX86_64TargetInfo>(Triple, Opts); return std::make_unique<MinGWX86_64TargetInfo>(Triple, Opts);
case llvm::Triple::MSVC: case llvm::Triple::MSVC:
default: // Assume MSVC for unknown environments default: // Assume MSVC for unknown environments

clang/lib/Basic/Targets/OSTargets.h

Show First 20 LinesShow All 768 Lines▼ Show 20 Lines ZOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
this->TheCXXABI.set(TargetCXXABI::XL); this->TheCXXABI.set(TargetCXXABI::XL);
} }
bool areDefaultedSMFStillPOD(const LangOptions &) const override { bool areDefaultedSMFStillPOD(const LangOptions &) const override {
return false; return false;
} }
}; };
// UEFI target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY UEFITargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {}
public:
UEFITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort;
this->WIntType = TargetInfo::UnsignedShort;
}
};
void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts, void addWindowsDefines(const llvm::Triple &Triple, const LangOptions &Opts,
MacroBuilder &Builder); MacroBuilder &Builder);
// Windows target // Windows target
template <typename Target> template <typename Target>
class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> { class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> {
protected: protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,

clang/lib/Basic/Targets/X86.h

ArrayRef<Builtin::Info> getTargetBuiltins() const override; ArrayRef<Builtin::Info> getTargetBuiltins() const override;
bool hasBitIntType() const override { return true; } bool hasBitIntType() const override { return true; }
size_t getMaxBitIntWidth() const override { size_t getMaxBitIntWidth() const override {
return llvm::IntegerType::MAX_INT_BITS; return llvm::IntegerType::MAX_INT_BITS;
} }
}; };
// x86-64 UEFI target
class LLVM_LIBRARY_VISIBILITY UEFIX86_64TargetInfo
: public UEFITargetInfo<X86_64TargetInfo> {
public:
UEFIX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: UEFITargetInfo<X86_64TargetInfo>(Triple, Opts) {
this->TheCXXABI.set(TargetCXXABI::Microsoft);
this->MaxTLSAlign = 8192u * this->getCharWidth();
this->resetDataLayout("e-m:w-p270:32:32-p271:32:32-p272:64:"
"64-i64:64-f80:128-n8:16:32:64-S128");
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
getOSDefines(Opts, X86TargetInfo::getTriple(), Builder);
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::CharPtrBuiltinVaList;
}
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
switch (CC) {
case CC_C:
case CC_Win64:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const override {
return CCK_MicrosoftWin64;
}
};
// x86-64 Windows target // x86-64 Windows target
class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo class LLVM_LIBRARY_VISIBILITY WindowsX86_64TargetInfo
: public WindowsTargetInfo<X86_64TargetInfo> { : public WindowsTargetInfo<X86_64TargetInfo> {
public: public:
WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) WindowsX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) { : WindowsTargetInfo<X86_64TargetInfo>(Triple, Opts) {
LongWidth = LongAlign = 32; LongWidth = LongAlign = 32;
DoubleAlign = LongLongAlign = 64; DoubleAlign = LongLongAlign = 64;

clang/lib/Driver/CMakeLists.txt

Show First 20 LinesShow All 72 Lines▼ Show 20 Lines add_clang_library(clangDriver
ToolChains/NetBSD.cpp ToolChains/NetBSD.cpp
ToolChains/OHOS.cpp ToolChains/OHOS.cpp
ToolChains/OpenBSD.cpp ToolChains/OpenBSD.cpp
ToolChains/PS4CPU.cpp ToolChains/PS4CPU.cpp
ToolChains/RISCVToolchain.cpp ToolChains/RISCVToolchain.cpp
ToolChains/Solaris.cpp ToolChains/Solaris.cpp
ToolChains/SPIRV.cpp ToolChains/SPIRV.cpp
ToolChains/TCE.cpp ToolChains/TCE.cpp
ToolChains/UEFI.cpp
ToolChains/VEToolchain.cpp ToolChains/VEToolchain.cpp
ToolChains/WebAssembly.cpp ToolChains/WebAssembly.cpp
ToolChains/XCore.cpp ToolChains/XCore.cpp
ToolChains/PPCLinux.cpp ToolChains/PPCLinux.cpp
ToolChains/PPCFreeBSD.cpp ToolChains/PPCFreeBSD.cpp
ToolChains/InterfaceStubs.cpp ToolChains/InterfaceStubs.cpp
ToolChains/ZOS.cpp ToolChains/ZOS.cpp
Types.cpp Types.cpp

clang/lib/Driver/Driver.cpp

#include "ToolChains/OpenBSD.h" #include "ToolChains/OpenBSD.h"
#include "ToolChains/PPCFreeBSD.h" #include "ToolChains/PPCFreeBSD.h"
#include "ToolChains/PPCLinux.h" #include "ToolChains/PPCLinux.h"
#include "ToolChains/PS4CPU.h" #include "ToolChains/PS4CPU.h"
#include "ToolChains/RISCVToolchain.h" #include "ToolChains/RISCVToolchain.h"
#include "ToolChains/SPIRV.h" #include "ToolChains/SPIRV.h"
#include "ToolChains/Solaris.h" #include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h" #include "ToolChains/TCE.h"
#include "ToolChains/UEFI.h"
#include "ToolChains/VEToolchain.h" #include "ToolChains/VEToolchain.h"
#include "ToolChains/WebAssembly.h" #include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h" #include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h" #include "ToolChains/ZOS.h"
#include "clang/Basic/TargetID.h" #include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h" #include "clang/Basic/Version.h"
#include "clang/Config/config.h" #include "clang/Config/config.h"
#include "clang/Driver/Action.h" #include "clang/Driver/Action.h"
break; break;
case llvm::Triple::AMDHSA: case llvm::Triple::AMDHSA:
TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args); TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args);
break; break;
case llvm::Triple::AMDPAL: case llvm::Triple::AMDPAL:
case llvm::Triple::Mesa3D: case llvm::Triple::Mesa3D:
TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args); TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
break; break;
case llvm::Triple::UEFI:
TC = std::make_unique<toolchains::UEFI>(*this, Target, Args);
break;
case llvm::Triple::Win32: case llvm::Triple::Win32:
switch (Target.getEnvironment()) { switch (Target.getEnvironment()) {
default: default:
if (Target.isOSBinFormatELF()) if (Target.isOSBinFormatELF())
TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args); TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
else if (Target.isOSBinFormatMachO()) else if (Target.isOSBinFormatMachO())
TC = std::make_unique<toolchains::MachO>(*this, Target, Args); TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
else else

clang/lib/Driver/ToolChains/UEFI.h

  • This file was added.
//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
namespace clang {
namespace driver {
namespace tools {
namespace uefi {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
Linker(const ToolChain &TC) : Tool("uefi::Linker", "lld-link", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
} // end namespace uefi
} // end namespace tools
namespace toolchains {
class LLVM_LIBRARY_VISIBILITY UEFI : public ToolChain {
public:
UEFI(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
protected:
Tool *buildLinker() const override;
public:
bool HasNativeLLVMSupport() const override { return true; }
UnwindTableLevel
getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override {
bradUnsubmitted

Remove the IsIntegratedAssemblerDefault entry.

brad: Remove the IsIntegratedAssemblerDefault entry.
return UnwindTableLevel::Asynchronous;
}
bool isPICDefault() const override { return true; }
bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
return false;
}
bool isPICDefaultForced() const override { return true; }
};
} // namespace toolchains
} // namespace driver
} // namespace clang
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_UEFI_H

clang/lib/Driver/ToolChains/UEFI.cpp

  • This file was added.
//===--- UEFI.h - UEFI ToolChain Implementations ----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "UEFI.h"
#include "CommonArgs.h"
#include "Darwin.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/Host.h"
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
UEFI::UEFI(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
Tool *UEFI::buildLinker() const { return new tools::uefi::Linker(*this); }
void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
auto &TC = static_cast<const toolchains::UEFI &>(getToolChain());
assert((Output.isFilename() || Output.isNothing()) && "invalid output");
if (Output.isFilename())
CmdArgs.push_back(
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
CmdArgs.push_back("-nologo");
// TODO: Other UEFI binary subsystems that are currently unsupported:
// efi_boot_service_driver, efi_rom, efi_runtime_driver.
CmdArgs.push_back("-subsystem:efi_application");
phosekUnsubmitted
CmdArgs.push_back("-nologo");
- // Other UEFI binary subsystems that are currently unsupported:
+ // TODO: Other UEFI binary subsystems that are currently unsupported:
// efi_boot_service_driver, efi_rom, efi_runtime_driver.
CmdArgs.push_back("-subsystem:efi_application");
phosek:
// Default entry function name according to the TianoCore reference // implementation is EfiMain. // TODO: Provide a flag to override the entry function name. CmdArgs.push_back("-entry:EfiMain");
phosekUnsubmitted
CmdArgs.push_back("-subsystem:efi_application");
- // Default entry function name according to the TianaCore reference
- // implementation is EfiMain. In the future we will add a flag to override the
- // entry function name.
+ // Default entry function name according to the TianoCore reference
+ // implementation is EfiMain.
+ // TODO: Provide a flag to override the entry function name.
CmdArgs.push_back("-entry:EfiMain");
phosek:
// "Terminal Service Aware" flag is not needed for UEFI applications. CmdArgs.push_back("-tsaware:no");
MaskRayUnsubmitted

These options are not tested.

MaskRay: These options are not tested.
// EFI_APPLICATION to be linked as DLL by default. CmdArgs.push_back("-dll"); if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) CmdArgs.push_back("-debug"); Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); // Add filenames, libraries, and other linker inputs. for (const auto &Input : Inputs) { if (Input.isFilename()) { CmdArgs.push_back(Input.getFilename()); continue; } const Arg &A = Input.getInputArg(); if (A.getOption().matches(options::OPT_l)) { StringRef Lib = A.getValue(); const char *LinkLibArg; if (Lib.endswith(".lib")) LinkLibArg = Args.MakeArgString(Lib); else LinkLibArg = Args.MakeArgString(Lib + ".lib"); CmdArgs.push_back(LinkLibArg); continue; } // Otherwise, this is some other kind of linker input option like -Wl, -z, // or -L. A.renderAsInput(Args, CmdArgs); } // This should ideally be handled by ToolChain::GetLinkerPath but we need // to special case some linker paths. In the case of lld, we need to // translate 'lld' into 'lld-link'. StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); if (Linker.empty() || Linker.equals_insensitive("lld")) Linker = "lld-link"; auto LinkerPath = TC.GetProgramPath(Linker.str().c_str()); auto LinkCmd = std::make_unique<Command>( JA, *this, ResponseFileSupport::AtFileUTF16(), Args.MakeArgString(LinkerPath), CmdArgs, Inputs, Output); C.addCommand(std::move(LinkCmd)); }

clang/test/Driver/uefi.c

  • This file was added.
// RUN: %clang -### %s --target=x86_64-unknown-uefi \
// RUN: --sysroot=%S/platform -fuse-ld=lld 2>&1 \
// RUN: | FileCheck -check-prefixes=CHECK %s
// CHECK: "-cc1"
// CHECK-SAME: "-triple" "x86_64-unknown-uefi"
MaskRayUnsubmitted

This RUN line is not needed. If you want to check that x86_64-uefi normalizes to unknown, you can add a unittest instead.

MaskRay: This RUN line is not needed. If you want to check that x86_64-uefi normalizes to unknown, you...
// CHECK-SAME: "-mrelocation-model" "pic" "-pic-level" "2"
// CHECK-SAME: "-mframe-pointer=all"
// CHECK-NEXT: "-subsystem:efi_application"
// CHECK-SAME: "-entry:EfiMain"
// CHECK-SAME: "-tsaware:no"
// CHECK-SAME: "-dll"

AltStyle によって変換されたページ (->オリジナル) /