diff --git a/llvm/include/llvm/MC/TargetRegistry.h b/llvm/include/llvm/MC/TargetRegistry.h --- a/llvm/include/llvm/MC/TargetRegistry.h +++ b/llvm/include/llvm/MC/TargetRegistry.h @@ -564,7 +564,8 @@ case Triple::UnknownObjectFormat: llvm_unreachable("Unknown object format"); case Triple::COFF: - assert(T.isOSWindows() && "only Windows COFF is supported"); + assert((T.isOSWindows() || T.isUEFI()) && + "only Windows and UEFI COFF are supported"); S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), std::move(Emitter), RelaxAll, IncrementalLinkerCompatible); diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -199,6 +199,7 @@ NetBSD, OpenBSD, Solaris, + UEFI, Win32, ZOS, Haiku, @@ -580,6 +581,11 @@ return getOS() == Triple::Haiku; } + /// Tests whether the OS is UEFI. + bool isUEFI() const { + return getOS() == Triple::UEFI; + } + /// Tests whether the OS is Windows. bool isOSWindows() const { return getOS() == Triple::Win32; diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -85,7 +85,7 @@ Env = IsMachO; break; case Triple::COFF: - if (!TheTriple.isOSWindows()) + if (!TheTriple.isOSWindows() && !TheTriple.isUEFI()) report_fatal_error( "Cannot initialize MC for non-Windows COFF object files."); diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -1516,6 +1516,12 @@ if (TheTriple.isOSWindows() && TheTriple.isOSBinFormatCOFF()) return new WindowsX86AsmBackend(T, true, STI); + if (TheTriple.isUEFI()) { + assert(TheTriple.isOSBinFormatCOFF() && + "Only COFF format is supported in UEFI environment."); + return new WindowsX86AsmBackend(T, true, STI); + } + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); if (TheTriple.isX32()) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp @@ -153,7 +153,8 @@ void X86MCAsmInfoGNUCOFF::anchor() { } X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) { - assert(Triple.isOSWindows() && "Windows is the only supported COFF target"); + assert((Triple.isOSWindows() || Triple.isUEFI()) && + "Windows and UEFI are the only supported COFF targets"); if (Triple.getArch() == Triple::x86_64) { PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp @@ -441,6 +441,8 @@ } else if (TheTriple.isOSCygMing() || TheTriple.isWindowsItaniumEnvironment()) { MAI = new X86MCAsmInfoGNUCOFF(TheTriple); + } else if (TheTriple.isUEFI()) { + MAI = new X86MCAsmInfoGNUCOFF(TheTriple); } else { // The default is ELF. MAI = new X86ELFMCAsmInfo(TheTriple); diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1555,7 +1555,8 @@ void X86AsmPrinter::EmitSEHInstruction(const MachineInstr *MI) { assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?"); - assert(getSubtarget().isOSWindows() && "SEH_ instruction Windows only"); + assert((getSubtarget().isOSWindows() || TM.getTargetTriple().isUEFI()) && + "SEH_ instruction Windows and UEFI only"); // Use the .cv_fpo directives if we're emitting CodeView on 32-bit x86. if (EmitFPOData) { diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -238,6 +238,7 @@ case RTEMS: return "rtems"; case Solaris: return "solaris"; case TvOS: return "tvos"; + case UEFI: return "uefi"; case WASI: return "wasi"; case WatchOS: return "watchos"; case Win32: return "windows"; @@ -588,6 +589,7 @@ .StartsWith("netbsd", Triple::NetBSD) .StartsWith("openbsd", Triple::OpenBSD) .StartsWith("solaris", Triple::Solaris) + .StartsWith("uefi", Triple::UEFI) .StartsWith("win32", Triple::Win32) .StartsWith("windows", Triple::Win32) .StartsWith("zos", Triple::ZOS) diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -349,6 +349,12 @@ EXPECT_EQ(Triple::HermitCore, T.getOS()); EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("x86_64-unknown-uefi"); + EXPECT_EQ(Triple::x86_64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UEFI, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("wasm32-unknown-unknown"); EXPECT_EQ(Triple::wasm32, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor());