From 8df7c85b896aefd774014cb0387c4e99b6e49f20 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 21 Jun 2025 20:50:43 -0700 Subject: [PATCH 1/8] LFI external support patch --- clang/lib/Basic/Targets/AArch64.cpp | 4 + clang/lib/Basic/Targets/X86.cpp | 4 + clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 3 + clang/lib/Driver/ToolChains/LFILinux.cpp | 29 +++ clang/lib/Driver/ToolChains/LFILinux.h | 38 ++++ clang/tools/driver/cc1as_main.cpp | 184 +++++++++++++++--- libunwind/src/DwarfInstructions.hpp | 2 +- lld/ELF/Arch/AArch64.cpp | 52 +++++ lld/ELF/Config.h | 1 + lld/ELF/Driver.cpp | 1 + llvm/include/llvm/CodeGen/AsmPrinter.h | 8 + .../llvm/CodeGen/CodeGenTargetMachineImpl.h | 3 + llvm/include/llvm/Target/TargetMachine.h | 8 + llvm/include/llvm/TargetParser/Triple.h | 15 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 140 ++++++++++++- llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp | 41 +++- llvm/lib/MC/MCAsmStreamer.cpp | 2 + .../Target/AArch64/AArch64RegisterInfo.cpp | 12 ++ llvm/lib/Target/AArch64/AArch64RegisterInfo.h | 2 + .../Target/AArch64/AArch64TargetMachine.cpp | 3 + .../AArch64/AsmParser/AArch64AsmParser.cpp | 11 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 8 + .../MCTargetDesc/AArch64TargetStreamer.h | 3 + llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 2 + llvm/lib/Target/X86/X86ISelLowering.cpp | 7 +- llvm/lib/Target/X86/X86RegisterInfo.cpp | 9 + llvm/lib/Target/X86/X86RegisterInfo.h | 4 + llvm/lib/TargetParser/Triple.cpp | 4 + .../Scalar/TailRecursionElimination.cpp | 6 + 30 files changed, 572 insertions(+), 35 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/LFILinux.cpp create mode 100644 clang/lib/Driver/ToolChains/LFILinux.h diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index cabda0a1323a3..ce164ba26f662 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -413,6 +413,10 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__aarch64__"); } + if (getTriple().isVendorLFI()) { + Builder.defineMacro("__LFI__"); + } + // Inline assembly supports AArch64 flag outputs. Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__"); diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 40ad8fd9a0967..4bfa45ec21d7f 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -557,6 +557,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, DefineStd(Builder, "i386", Opts); } + if (getTriple().isVendorLFI()) { + Builder.defineMacro("__LFI__"); + } + Builder.defineMacro("__SEG_GS"); Builder.defineMacro("__SEG_FS"); Builder.defineMacro("__seg_gs", "__attribute__((address_space(256)))"); diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 5bdb6614389cf..9fd7beb4b29a7 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -64,6 +64,7 @@ add_clang_library(clangDriver ToolChains/Hexagon.cpp ToolChains/HLSL.cpp ToolChains/Hurd.cpp + ToolChains/LFILinux.cpp ToolChains/Linux.cpp ToolChains/MipsLinux.cpp ToolChains/MinGW.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 87855fdb79971..546d23683f0e7 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -28,6 +28,7 @@ #include "ToolChains/Haiku.h" #include "ToolChains/Hexagon.h" #include "ToolChains/Hurd.h" +#include "ToolChains/LFILinux.h" #include "ToolChains/Lanai.h" #include "ToolChains/Linux.h" #include "ToolChains/MSP430.h" @@ -6654,6 +6655,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = std::make_unique(*this, Target, Args); else if (Target.isOHOSFamily()) TC = std::make_unique(*this, Target, Args); + else if (Target.getVendor() == llvm::Triple::LFI) + TC = std::make_unique(*this, Target, Args); else TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/LFILinux.cpp b/clang/lib/Driver/ToolChains/LFILinux.cpp new file mode 100644 index 0000000000000..37510c596b303 --- /dev/null +++ b/clang/lib/Driver/ToolChains/LFILinux.cpp @@ -0,0 +1,29 @@ +//===-- LFILinux.cpp - LFI 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 "LFILinux.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" + +using namespace clang::driver::toolchains; +using namespace llvm::opt; + +void LFILinuxToolChain::AddCXXStdlibLibArgs( + const ArgList &Args, ArgStringList &CmdArgs) const { + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + if (Args.hasArg(options::OPT_fexperimental_library)) + CmdArgs.push_back("-lc++experimental"); + CmdArgs.push_back("-lc++abi"); + break; + case ToolChain::CST_Libstdcxx: + CmdArgs.push_back("-lstdc++"); + break; + } +} diff --git a/clang/lib/Driver/ToolChains/LFILinux.h b/clang/lib/Driver/ToolChains/LFILinux.h new file mode 100644 index 0000000000000..3eb37231a2af8 --- /dev/null +++ b/clang/lib/Driver/ToolChains/LFILinux.h @@ -0,0 +1,38 @@ +//===--- LFILinux.h - LFI 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_LFI_LINUX_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H + +#include "Linux.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY LFILinuxToolChain : public Linux { +public: + LFILinuxToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Linux(D, Triple, Args) { + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("separate-code"); + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("lfi"); + } + + void + AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 7fe97cc6e6ace..9d5f4895a644e 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -57,6 +57,7 @@ #include #include #include +#include using namespace clang; using namespace clang::driver; using namespace clang::driver::options; @@ -539,6 +540,13 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory; MCOptions.ABIName = Opts.TargetABI; + MAI->setPreserveAsmComments(false); + + Expected AsmTemp = + sys::fs::TempFile::create("asm.temp-%%%%%%%.s"); + if (!AsmTemp) + return false; + // FIXME: There is a bit of code duplication with addPassesToEmitFile. if (Opts.OutputType == AssemblerInvocation::FT_Asm) { MCInstPrinter *IP = TheTarget->createMCInstPrinter( @@ -558,31 +566,48 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, } else { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); - if (!FDOS->supportsSeeking()) { - BOS = std::make_unique(*FDOS); - Out = BOS.get(); - } - std::unique_ptr CE( - TheTarget->createMCCodeEmitter(*MCII, Ctx)); - std::unique_ptr MAB( - TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); - assert(MAB && "Unable to create asm backend!"); - - std::unique_ptr OW = - DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS) - : MAB->createObjectWriter(*Out); - - Triple T(Opts.Triple); - Str.reset(TheTarget->createMCObjectStreamer( - T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI)); - Str.get()->initSections(Opts.NoExecStack, *STI); - if (T.isOSBinFormatMachO() && T.isOSDarwin()) { - Triple *TVT = Opts.DarwinTargetVariantTriple - ? &*Opts.DarwinTargetVariantTriple - : nullptr; - Str->emitVersionForTarget(T, VersionTuple(), TVT, - Opts.DarwinTargetVariantSDKVersion); + if (llvm::Triple(Opts.Triple).isVendorLFI()) { + MCInstPrinter *IP = TheTarget->createMCInstPrinter( + llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI); + + std::unique_ptr CE; + if (Opts.ShowEncoding) + CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx)); + std::unique_ptr MAB( + TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); + + raw_fd_ostream* Tmp = new raw_fd_ostream(AsmTemp->FD, false); + auto TempOut = std::make_unique(*Tmp); + Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(TempOut), IP, + std::move(CE), std::move(MAB))); + } else { + if (!FDOS->supportsSeeking()) { + BOS = std::make_unique(*FDOS); + Out = BOS.get(); + } + + std::unique_ptr CE( + TheTarget->createMCCodeEmitter(*MCII, Ctx)); + std::unique_ptr MAB( + TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); + assert(MAB && "Unable to create asm backend!"); + + std::unique_ptr OW = + DwoOS ? MAB->createDwoObjectWriter(*Out, *DwoOS) + : MAB->createObjectWriter(*Out); + + Triple T(Opts.Triple); + Str.reset(TheTarget->createMCObjectStreamer( + T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI)); + Str.get()->initSections(Opts.NoExecStack, *STI); + if (T.isOSBinFormatMachO() && T.isOSDarwin()) { + Triple *TVT = Opts.DarwinTargetVariantTriple + ? &*Opts.DarwinTargetVariantTriple + : nullptr; + Str->emitVersionForTarget(T, VersionTuple(), TVT, + Opts.DarwinTargetVariantSDKVersion); + } } } @@ -622,6 +647,117 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, Failed = Parser->Run(Opts.NoInitialTextSection); } + const auto& triple = llvm::Triple(Opts.Triple); + if (triple.isVendorLFI()) { + Expected RewriteTemp = + sys::fs::TempFile::create("rewrite.temp-%%%%%%%.s"); + if (!RewriteTemp) { + consumeError(AsmTemp->discard()); + return false; + } + + const char* LFIRewriter = std::getenv("LFIREWRITER"); + const char* LFIFlags = ""; + if (triple.isVendorLFIStores()) + LFIFlags = "--sandbox=stores"; + const char* LFIDebug = std::getenv("LFIDEBUG"); + + if (!LFIRewriter) + LFIRewriter = "lfi-rewrite"; + + auto Prog = sys::findProgramByName(std::string(LFIRewriter)); + if (!Prog) { + errs() << "Could not find " << LFIRewriter; + consumeError(RewriteTemp->discard()); + consumeError(AsmTemp->discard()); + return Failed; + } + + std::stringstream SS; + SS << Prog.get() << " " << LFIFlags << " " << "-a " << triple.getArchName().str() << " " << AsmTemp->TmpName << " -o " << RewriteTemp->TmpName << "\n"; + if (LFIDebug) + errs() << SS.str(); + std::string Cmd = SS.str(); + + SmallVector Args = { + "/bin/sh", "-c", Cmd, + }; + + int RC = sys::ExecuteAndWait(Args[0], Args); + if (RC < -1) { + printf("lfi: exited abnormally\n"); + } else if (RC < 0) { + printf("lfi: unable to invoke\n"); + } else if (RC > 0) { + printf("lfi: returned non-zero\n"); + } + + auto EBuf = MemoryBuffer::getFileAsStream(RewriteTemp->TmpName); + if (!EBuf) { + consumeError(RewriteTemp->discard()); + consumeError(AsmTemp->discard()); + return Failed; + } + auto *Buf = EBuf->get(); + std::string Str(Buf->getBufferStart(), Buf->getBufferEnd()); + + std::unique_ptr MBuf; + MBuf = MemoryBuffer::getMemBuffer(Str, RewriteTemp->TmpName); + SourceMgr SrcMgr; + SrcMgr.AddNewSourceBuffer(std::move(MBuf), SMLoc()); + + std::unique_ptr MRI(TheTarget->createMCRegInfo(triple.getTriple())); + if (!MRI) { + errs() << "Unable to create target register info!"; + abort(); + } + + std::unique_ptr MCII(TheTarget->createMCInstrInfo()); + + std::string OutputString; + raw_string_ostream NewOut(OutputString); + auto FOut = std::make_unique(NewOut); + + MCContext *NewCtx = new MCContext(triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, Ctx.getTargetOptions()); + TheTarget->createMCObjectFileInfo(*NewCtx, Ctx.getObjectFileInfo()->isPositionIndependent()); + NewCtx->setObjectFileInfo(Ctx.getObjectFileInfo()); + + std::unique_ptr MCStr; + + NewCtx->setUseNamesOnTempLabels(false); + + MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *NewCtx); + MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions); + MCStr.reset(TheTarget->createMCObjectStreamer( + triple, *NewCtx, std::unique_ptr(MAB), + MAB->createObjectWriter(*Out), std::unique_ptr(CE), + *STI)); + + std::unique_ptr Parser( + createMCAsmParser(SrcMgr, *NewCtx, *MCStr, *MAI)); + + std::unique_ptr MII(TheTarget->createMCInstrInfo()); + assert(MII && "Failed to create instruction info"); + std::unique_ptr NewTAP(TheTarget->createMCAsmParser( + TAP->getSTI(), *Parser, *MII, MCOptions)); + if (!NewTAP) + report_fatal_error("External rewriting not supported by this streamer because" + " we don't have an asm parser for this target\n"); + if (!triple.isAArch64()) { + NewTAP->setAvailableFeatures(TAP->getAvailableFeatures()); + } + + Parser->setTargetParser(*NewTAP); + + if (Parser->Run(/*NoInitialTextSection*/ false, /*NoFinalize*/ false)) + Failed = true; + + consumeError(RewriteTemp->discard()); + } + consumeError(AsmTemp->discard()); + + return Failed; + return Failed; } diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index e7be0d6d5d635..e2b917df13117 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -224,7 +224,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // __unw_step_stage2 is not used for cross unwinding, so we use // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are // building for AArch64 natively. -#if defined(__aarch64__) +#if defined(__aarch64__) && !defined(__LFI__) if (stage2 && cieInfo.mteTaggedFrame) { pint_t sp = registers.getSP(); pint_t p = sp; diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 9538dd4a70bae..f0e28380b6759 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -88,6 +88,10 @@ class AArch64 : public TargetInfo { void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const; void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; + + void writePltHeaderLfi(uint8_t *buf) const;Add commentMore actions + void writePltLfi(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const; }; struct AArch64Relaxer { @@ -377,6 +381,11 @@ void AArch64::writeIgotPlt(uint8_t *buf, const Symbol &s) const { } void AArch64::writePltHeader(uint8_t *buf) const { + if (ctx.arg.zLFI) { + writePltHeaderLfi(buf); + return; + } + const uint8_t pltData[] = { 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[2])) @@ -399,6 +408,11 @@ void AArch64::writePltHeader(uint8_t *buf) const { void AArch64::writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const { + if (ctx.arg.zLFI) { + writePltLfi(buf, sym, pltEntryAddr); + return; + } + const uint8_t inst[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[n])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.got.plt[n]))] @@ -414,6 +428,44 @@ void AArch64::writePlt(uint8_t *buf, const Symbol &sym, relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); } +void AArch64::writePltHeaderLfi(uint8_t *buf) const { + const uint8_t pltData[] = { + 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! + 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[2])) + 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.got.plt[2])) + 0xb1, 0x4a, 0x70, 0xf8, // ldr x17, [x21, w16, uxtw] + 0xb2, 0x42, 0x31, 0x8b, // add x18, x21, w17, uxtw + 0x40, 0x02, 0x1f, 0xd6, // br x18 + 0x1f, 0x20, 0x03, 0xd5, // nop + 0x1f, 0x20, 0x03, 0xd5 // nop + }; + memcpy(buf, pltData, sizeof(pltData)); + + uint64_t got = ctx.in.gotPlt->getVA(); + uint64_t plt = ctx.in.plt->getVA(); + relocateNoSym(buf + 4, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(got + 16) - getAArch64Page(plt + 4)); + relocateNoSym(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, got + 16); +} + +void AArch64::writePltLfi(uint8_t *buf, const Symbol &sym, + uint64_t pltEntryAddr) const { + const uint8_t inst[] = { + 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.got.plt[n])) + 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.got.plt[n])) + 0xb1, 0x4a, 0x70, 0xf8, // ldr x17, [x21, w16, uxtw] + 0x00, 0x00, 0x00, 0x14 // b Offset(&(.plt[0])+20) + }; + memcpy(buf, inst, sizeof(inst)); + + uint64_t gotPltEntryAddr = sym.getGotPltVA(ctx); + uint64_t plt = ctx.in.plt->getVA(); + relocateNoSym(buf, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr)); + relocateNoSym(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); + relocateNoSym(buf + 12, R_AARCH64_JUMP26, (plt + 16) - (pltEntryAddr + 12)); +} + bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file, uint64_t branchAddr, const Symbol &s, int64_t a) const { diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 9826ed0517337..82cf9ca63096b 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -360,6 +360,7 @@ struct Config { bool zInitfirst; bool zInterpose; bool zKeepTextSectionPrefix; + bool zLFI; bool zLrodataAfterBss; bool zNoBtCfi; bool zNodefaultlib; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index a1e9ecae08557..2cd2e954fe501 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1511,6 +1511,7 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) { ctx.arg.zInterpose = hasZOption(args, "interpose"); ctx.arg.zKeepTextSectionPrefix = getZFlag( args, "keep-text-section-prefix", "nokeep-text-section-prefix", false); + ctx.arg.zLFI = hasZOption(args, "lfi"); ctx.arg.zLrodataAfterBss = getZFlag(args, "lrodata-after-bss", "nolrodata-after-bss", false); ctx.arg.zNoBtCfi = hasZOption(args, "nobtcfi"); diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index 3da63af5ba571..08d70191baa8a 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/StackMaps.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -152,6 +153,11 @@ class AsmPrinter : public MachineFunctionPass { Debug = 2 ///< Emit .debug_frame }; + struct { + std::string File; // File containing dumped .s + raw_pwrite_stream *Out = nullptr; // Output stream to write object to + } ExtAsm; + private: MCSymbol *CurrentFnEnd = nullptr; @@ -273,6 +279,8 @@ class AsmPrinter : public MachineFunctionPass { // given basic block. MCSymbol *getMBBExceptionSym(const MachineBasicBlock &MBB); + bool doExtAsm(); + /// Return the symbol to be used for the specified basic block when its /// address is taken. This cannot be its normal LBB label because the block /// may be accessed outside its containing function. diff --git a/llvm/include/llvm/CodeGen/CodeGenTargetMachineImpl.h b/llvm/include/llvm/CodeGen/CodeGenTargetMachineImpl.h index 7bb4420e555fb..13b14a624ec1a 100644 --- a/llvm/include/llvm/CodeGen/CodeGenTargetMachineImpl.h +++ b/llvm/include/llvm/CodeGen/CodeGenTargetMachineImpl.h @@ -66,6 +66,9 @@ class CodeGenTargetMachineImpl : public TargetMachine { bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType, MCContext &Context) override; + bool addAsmPrinterLFI(PassManagerBase &PM, raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, CodeGenFileType FileType, + MCContext &Context) override; Expected> createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 9bdb110bd3683..b8f082c70ec00 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -463,6 +463,14 @@ class TargetMachine { return false; } + /// Adds an AsmPrinter pass to the pipeline that prints assembly or + /// machine code from the MI representation. + virtual bool addAsmPrinterLFI(PassManagerBase &PM, raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, CodeGenFileType FileType, + MCContext &Context) { + return false; + } + virtual Expected> createMCStreamer(raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType, MCContext &Ctx) { diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index 7d67966d17256..286b3117d67cb 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -194,7 +194,9 @@ class Triple { SUSE, OpenEmbedded, Intel, - LastVendorType = Intel + LFI, + LFIStores, + LastVendorType = LFIStores }; enum OSType { UnknownOS, @@ -846,6 +848,17 @@ class Triple { bool isVulkanOS() const { return getOS() == Triple::Vulkan; } + /// Tests whether the vendor is LFI + bool isVendorLFI() const { + return getVendor() == Triple::LFI || getVendor() == Triple::LFIStores; + } + bool isVendorLFIFull() const { + return getVendor() == Triple::LFI; + } + bool isVendorLFIStores() const { + return getVendor() == Triple::LFIStores; + } + bool isShaderStageEnvironment() const { EnvironmentType Env = getEnvironment(); return Env == Triple::Pixel || Env == Triple::Vertex || diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index e77abf429e6b4..73e213c26d510 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -86,12 +86,16 @@ #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/IR/ValueHandle.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSchedule.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" @@ -104,6 +108,9 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Pass.h" #include "llvm/Remarks/RemarkStreamer.h" @@ -115,7 +122,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/VCSRevision.h" +#include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" @@ -131,6 +140,7 @@ #include #include #include +#include using namespace llvm; @@ -2689,17 +2699,138 @@ bool AsmPrinter::doFinalization(Module &M) { // after everything else has gone out. emitEndOfAsmFile(M); + OutStreamer->finish(); + OutStreamer->reset(); + + if (ExtAsm.Out) { + if (doExtAsm()) + std::exit(1); // HACK (how do I return a failure from this function?) + } + MMI = nullptr; AddrLabelSymbols = nullptr; - OutStreamer->finish(); - OutStreamer->reset(); OwnedMLI.reset(); OwnedMDT.reset(); return false; } +bool AsmPrinter::doExtAsm() { + Expected Temp = + sys::fs::TempFile::create("rewrite.temp-%%%%%%%.s"); + if (!Temp) { + sys::fs::remove(ExtAsm.File); + return true; + } + + const char* LFIRewriter = std::getenv("LFIREWRITER"); + const char* LFIFlags = ""; + if (TM.getTargetTriple().isVendorLFIStores()) + LFIFlags = "--sandbox=stores"; + const char* LFIDebug = std::getenv("LFIDEBUG"); + + if (!LFIRewriter) + LFIRewriter = "lfi-rewrite"; + + auto Prog = sys::findProgramByName(std::string(LFIRewriter)); + if (!Prog) { + errs() << "Could not find " << LFIRewriter; + sys::fs::remove(ExtAsm.File); + consumeError(Temp->discard()); + return true; + } + + std::stringstream SS; + SS << Prog.get() << " " << LFIFlags << " " << "-a " << TM.getTargetTriple().getArchName().str() << " " << ExtAsm.File << " -o " << Temp->TmpName << "\n"; + if (LFIDebug) + errs() << SS.str(); + std::string Cmd = SS.str(); + + SmallVector Args = { + "/bin/sh", "-c", Cmd, + }; + + int RC = sys::ExecuteAndWait(Args[0], Args); + if (RC < -1) { + printf("lfi: exited abnormally\n"); + } else if (RC < 0) { + printf("lfi: unable to invoke\n"); + } else if (RC > 0) { + printf("lfi: returned non-zero\n"); + } + + auto EBuf = MemoryBuffer::getFileAsStream(Temp->TmpName); + if (!EBuf) { + sys::fs::remove(ExtAsm.File); + consumeError(Temp->discard()); + return true; + } + auto *Buf = EBuf->get(); + std::string Str(Buf->getBufferStart(), Buf->getBufferEnd()); + + std::unique_ptr MBuf; + MBuf = MemoryBuffer::getMemBuffer(Str, Temp->TmpName); + auto &MCOptions = TM.Options.MCOptions; + SourceMgr SrcMgr; + SrcMgr.AddNewSourceBuffer(std::move(MBuf), SMLoc()); + + std::unique_ptr MRI(TM.getTarget().createMCRegInfo(TM.getTargetTriple().getTriple())); + if (!MRI) { + errs() << "Unable to create target register info!"; + abort(); + } + + std::unique_ptr MCII(TM.getTarget().createMCInstrInfo()); + + std::string OutputString; + raw_string_ostream Out(OutputString); + auto FOut = std::make_unique(Out); + + MCContext *Ctx = new MCContext(TM.getTargetTriple(), MAI, MRI.get(), TM.getMCSubtargetInfo(), &SrcMgr, OutContext.getTargetOptions()); + TM.getTarget().createMCObjectFileInfo(*Ctx, OutContext.getObjectFileInfo()->isPositionIndependent()); + Ctx->setObjectFileInfo(OutContext.getObjectFileInfo()); + + std::unique_ptr MCStr; + + // The following code can be used to output assembly instead of an object file. + // const unsigned OutputAsmVariant = 0; + // MCInstPrinter *IP = TM.getTarget().createMCInstPrinter(TM.getTargetTriple(), OutputAsmVariant, + // *MAI, *MCII, *MRI); + // std::unique_ptr CE = nullptr; + // std::unique_ptr MAB = nullptr; + // MCStr.reset(TM.getTarget().createAsmStreamer(Ctx, std::move(FOut), IP, std::move(CE), std::move(MAB))); + + Ctx->setUseNamesOnTempLabels(false); + + MCCodeEmitter *CE = TM.getTarget().createMCCodeEmitter(*MCII, *Ctx); + MCAsmBackend *MAB = TM.getTarget().createMCAsmBackend(*TM.getMCSubtargetInfo(), *MRI, MCOptions); + MCStr.reset(TM.getTarget().createMCObjectStreamer( + TM.getTargetTriple(), *Ctx, std::unique_ptr(MAB), + MAB->createObjectWriter(*ExtAsm.Out), std::unique_ptr(CE), + *TM.getMCSubtargetInfo())); + + std::unique_ptr Parser( + createMCAsmParser(SrcMgr, *Ctx, *MCStr, *MAI)); + + std::unique_ptr MII(TM.getTarget().createMCInstrInfo()); + assert(MII && "Failed to create instruction info"); + std::unique_ptr TAP(TM.getTarget().createMCAsmParser( + *TM.getMCSubtargetInfo(), *Parser, *MII, MCOptions)); + if (!TAP) + report_fatal_error("External rewriting not supported by this streamer because" + " we don't have an asm parser for this target\n"); + + Parser->setTargetParser(*TAP); + + bool Failed = Parser->Run(/*NoInitialTextSection*/ false, /*NoFinalize*/ false); + + sys::fs::remove(ExtAsm.File); + consumeError(Temp->discard()); + + return Failed; +} + MCSymbol *AsmPrinter::getMBBExceptionSym(const MachineBasicBlock &MBB) { auto Res = MBBSectionExceptionSyms.try_emplace(MBB.getSectionID()); if (Res.second) @@ -2711,6 +2842,11 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { this->MF = &MF; const Function &F = MF.getFunction(); + if (TM.getTargetTriple().isVendorLFI() && TM.getTargetTriple().isX86()) + for (auto &MBB : MF) + if (shouldEmitLabelForBasicBlock(MBB)) + MBB.setAlignment(Align(32)); + // Record that there are split-stack functions, so we will emit a special // section to tell the linker. if (MF.shouldSplitStack()) { diff --git a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp index 5757ca1b3adf8..59bf192ba0266 100644 --- a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp +++ b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp @@ -29,6 +29,7 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -125,6 +126,33 @@ addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, PassManagerBase &PM, return PassConfig; } +bool CodeGenTargetMachineImpl::addAsmPrinterLFI(PassManagerBase &PM, + raw_pwrite_stream &Out, + raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, + MCContext &Context) { + int FD; + SmallVector Path; + sys::fs::createTemporaryFile("asm.temp", "s", FD, Path); + raw_fd_ostream* Tmp = new raw_fd_ostream(FD, false); + + Expected> MCStreamerOrErr = + createMCStreamer(*Tmp, nullptr, CodeGenFileType::AssemblyFile, Context); + if (auto Err = MCStreamerOrErr.takeError()) + return true; + + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + AsmPrinter *Printer = + getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr)); + if (!Printer) + return true; + Printer->ExtAsm.File = Twine(Path).str(); + Printer->ExtAsm.Out = &Out; + + PM.add(Printer); + return false; +} + bool CodeGenTargetMachineImpl::addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, @@ -136,10 +164,11 @@ bool CodeGenTargetMachineImpl::addAsmPrinter(PassManagerBase &PM, return true; // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. - FunctionPass *Printer = + AsmPrinter *Printer = getTarget().createAsmPrinter(*this, std::move(*MCStreamerOrErr)); if (!Printer) return true; + Printer->ExtAsm.Out = nullptr; PM.add(Printer); return false; @@ -221,8 +250,14 @@ bool CodeGenTargetMachineImpl::addPassesToEmitFile( return true; if (TargetPassConfig::willCompleteCodeGenPipeline()) { - if (addAsmPrinter(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext())) - return true; + const Triple &T = getTargetTriple(); + if (T.isVendorLFI() && FileType == CodeGenFileType::ObjectFile) { + if (addAsmPrinterLFI(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext())) + return true; + } else { + if (addAsmPrinter(PM, Out, DwoOut, FileType, MMIWP->getMMI().getContext())) + return true; + } } else { // MIR printing is redundant with -filetype=null. if (FileType != CodeGenFileType::Null) diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index dd8058c6d5cd8..d15db54e3bb7a 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -2572,6 +2572,8 @@ void MCAsmStreamer::finishImpl() { emitLabel(Label); } } + + OS.flush(); } void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) { diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index 367f6b626b420..7084c1727100f 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -42,6 +42,7 @@ using namespace llvm; AArch64RegisterInfo::AArch64RegisterInfo(const Triple &TT, unsigned HwMode) : AArch64GenRegisterInfo(AArch64::LR, 0, 0, 0, HwMode), TT(TT) { AArch64_MC::initLLVMToCVRegMapping(this); + IsLFI = TT.isVendorLFI(); } /// Return whether the register needs a CFI entry. Not all unwinders may know @@ -433,6 +434,17 @@ AArch64RegisterInfo::getStrictlyReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, AArch64::WSP); markSuperRegs(Reserved, AArch64::WZR); + if (IsLFI) { + markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(21)); // x21 + markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(18)); // x18 + markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(22)); // x22 + if (!MF.getProperties().hasProperty( + MachineFunctionProperties::Property::NoVRegs)) { + markSuperRegs(Reserved, AArch64::LR); // x30 + markSuperRegs(Reserved, AArch64::W30); // w30 + } + } + if (TFI->hasFP(MF) || TT.isOSDarwin()) markSuperRegs(Reserved, AArch64::W29); diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h index 898a509f75908..db1eb75bd0063 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -152,6 +152,8 @@ class AArch64RegisterInfo final : public AArch64GenRegisterInfo { SmallVectorImpl &Ops) const override; bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const override; + + bool IsLFI; }; } // end namespace llvm diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 07f072446081a..9bdef0fefc8eb 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -369,6 +369,9 @@ AArch64TargetMachine::AArch64TargetMachine(const Target &T, const Triple &TT, this->Options.NoTrapAfterNoreturn = true; } + if (TT.isVendorLFI()) + EnableCompressJumpTables = false; + if (getMCAsmInfo()->usesWindowsCFI()) { // Unwinding can get confused if the last instruction in an // exception-handling region (function, funclet, try block, etc.) diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 43f07be15e9d1..4054e1d88344b 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -7159,9 +7159,9 @@ static SMLoc incrementLoc(SMLoc L, int Offset) { bool AArch64AsmParser::parseDirectiveArch(SMLoc L) { SMLoc CurLoc = getLoc(); + StringRef Name = getParser().parseStringToEndOfStatement().trim(); StringRef Arch, ExtensionString; - std::tie(Arch, ExtensionString) = - getParser().parseStringToEndOfStatement().trim().split('+'); + std::tie(Arch, ExtensionString) = Name.split('+'); const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch); if (!ArchInfo) @@ -7208,6 +7208,8 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) { } FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits()); setAvailableFeatures(Features); + + getTargetStreamer().emitDirectiveArch(Name); return false; } @@ -7216,12 +7218,13 @@ bool AArch64AsmParser::parseDirectiveArch(SMLoc L) { bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) { SMLoc ExtLoc = getLoc(); - StringRef Name = getParser().parseStringToEndOfStatement().trim(); + StringRef FullName = getParser().parseStringToEndOfStatement().trim(); if (parseEOL()) return true; bool EnableFeature = true; + StringRef Name = FullName; if (Name.starts_with_insensitive("no")) { EnableFeature = false; Name = Name.substr(2); @@ -7241,6 +7244,8 @@ bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) { STI.ClearFeatureBitsTransitively(It->Features); FeatureBitset Features = ComputeAvailableFeatures(STI.getFeatureBits()); setAvailableFeatures(Features); + + getTargetStreamer().emitDirectiveArchExtension(FullName); return false; } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index 6b5c5f36cbd4b..471575eb8ea8e 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -54,6 +54,14 @@ class AArch64TargetAsmStreamer : public AArch64TargetStreamer { OS << "\t.variant_pcs\t" << Symbol->getName() << "\n"; } + void emitDirectiveArch(StringRef Name) override { + OS << "\t.arch\t" << Name << "\n"; + } + + void emitDirectiveArchExtension(StringRef Name) override { + OS << "\t.arch_extension\t" << Name << "\n"; + } + void emitARM64WinCFIAllocStack(unsigned Size) override { OS << "\t.seh_stackalloc\t" << Size << "\n"; } diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h index a33f0bc78c213..12652715758ab 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h @@ -55,6 +55,9 @@ class AArch64TargetStreamer : public MCTargetStreamer { /// Callback used to implement the .variant_pcs directive. virtual void emitDirectiveVariantPCS(MCSymbol *Symbol) {}; + virtual void emitDirectiveArch(StringRef Name) {}; + virtual void emitDirectiveArchExtension(StringRef Name) {}; + virtual void emitARM64WinCFIAllocStack(unsigned Size) {} virtual void emitARM64WinCFISaveR19R20X(int Offset) {} virtual void emitARM64WinCFISaveFPLR(int Offset) {} diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 84bcdae520885..2ba13dae527b6 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -181,6 +181,8 @@ namespace { Subtarget = &MF.getSubtarget(); IndirectTlsSegRefs = MF.getFunction().hasFnAttribute( "indirect-tls-seg-refs"); + if (Subtarget->getTargetTriple().isVendorLFI()) + IndirectTlsSegRefs = true; // OptFor[Min]Size are used in pattern predicates that isel is matching. OptForMinSize = MF.getFunction().hasMinSize(); diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 4413fbb77f415..ba62ab3eebfc0 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2724,7 +2724,12 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, // but a conditional move could be stalled by an expensive earlier operation. PredictableSelectIsExpensive = Subtarget.getSchedModel().isOutOfOrder(); EnableExtLdPromotion = true; - setPrefFunctionAlignment(Align(16)); + if (Subtarget.getTargetTriple().isVendorLFI()) { + setMinFunctionAlignment(Align(32)); + setPrefFunctionAlignment(Align(32)); + } else { + setPrefFunctionAlignment(Align(16)); + } verifyIntrinsicTables(); diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp index 4faf8bca4f9e0..b744f8ce8a417 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/TargetParser/Triple.h" using namespace llvm; @@ -60,6 +61,7 @@ X86RegisterInfo::X86RegisterInfo(const Triple &TT) // Cache some information. Is64Bit = TT.isArch64Bit(); IsWin64 = Is64Bit && TT.isOSWindows(); + IsLFI = TT.isVendorLFI(); // Use a callee-saved register as the base pointer. These registers must // not conflict with any ABI requirements. For example, in 32-bit mode PIC @@ -557,6 +559,13 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { // Set the SIMD floating point control register as reserved. Reserved.set(X86::MXCSR); + if (IsLFI) { + for (const MCPhysReg &SubReg : subregs_inclusive(X86::R11)) // scratch + Reserved.set(SubReg); + for (const MCPhysReg &SubReg : subregs_inclusive(X86::R14)) // base + Reserved.set(SubReg); + } + // Set the stack-pointer register and its aliases as reserved. for (const MCPhysReg &SubReg : subregs_inclusive(X86::RSP)) Reserved.set(SubReg); diff --git a/llvm/lib/Target/X86/X86RegisterInfo.h b/llvm/lib/Target/X86/X86RegisterInfo.h index 68ee372f27b14..5442e1cfe64a0 100644 --- a/llvm/lib/Target/X86/X86RegisterInfo.h +++ b/llvm/lib/Target/X86/X86RegisterInfo.h @@ -31,6 +31,10 @@ class X86RegisterInfo final : public X86GenRegisterInfo { /// bool IsWin64; + /// IsLFI - Is the target LFI + /// + bool IsLFI; + /// SlotSize - Stack slot size in bytes. /// unsigned SlotSize; diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index e9e6f130f757c..fbc78b1d53c18 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -270,6 +270,8 @@ StringRef Triple::getVendorTypeName(VendorType Kind) { case PC: return "pc"; case SCEI: return "scei"; case SUSE: return "suse"; + case LFI: return "lfi"; + case LFIStores: return "lfi_stores"; } llvm_unreachable("Invalid VendorType!"); @@ -664,6 +666,8 @@ static Triple::VendorType parseVendor(StringRef VendorName) { .Case("suse", Triple::SUSE) .Case("oe", Triple::OpenEmbedded) .Case("intel", Triple::Intel) + .Case("lfi", Triple::LFI) + .Case("lfi_stores", Triple::LFIStores) .Default(Triple::UnknownVendor); } diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 3f27166080d5a..74aa311c8925d 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -77,6 +77,7 @@ #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" using namespace llvm; @@ -256,6 +257,11 @@ static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { {LLVMContext::OB_clang_arc_attachedcall, LLVMContext::OB_ptrauth, LLVMContext::OB_kcfi}); + // LFI: the CI->getNumOperands() >= 6 is needed because we reserve %r11 + // on x86-64. See https://issuetracker.google.com/issues/42403689?pli=1 + if (llvm::Triple(CI->getModule()->getTargetTriple()).isVendorLFI() && CI->getNumOperands() >= 6) + IsNoTail = true; + if (!IsNoTail && CI->doesNotAccessMemory()) { // A call to a readnone function whose arguments are all things computed // outside this function can be marked tail. Even if you stored the From 538c3bb05a90e2ecbcf9106d2775bc7f8a1508a5 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 21 Jun 2025 21:08:49 -0700 Subject: [PATCH 2/8] Fix GH paste issue --- lld/ELF/Arch/AArch64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index f0e28380b6759..dcd926f346e39 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -89,7 +89,7 @@ class AArch64 : public TargetInfo { void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) const; void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const; - void writePltHeaderLfi(uint8_t *buf) const;Add commentMore actions + void writePltHeaderLfi(uint8_t *buf) const; void writePltLfi(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const; }; From 22f4e404f1726bf2866d920d74870093fb8382cf Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 21 Jun 2025 21:19:42 -0700 Subject: [PATCH 3/8] Fix filltrap --- lld/ELF/Writer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 0db922b07aabf..39848de8755a4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2901,7 +2901,7 @@ template void Writer::writeTrapInstr() { if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) fillTrap( ctx.target->trapInstr, - ctx.bufferStart + alignDown(p->firstSec->offset + p->p_filesz, 4), + ctx.bufferStart + p->firstSec->offset, ctx.bufferStart + alignToPowerOf2(p->firstSec->offset + p->p_filesz, ctx.arg.maxPageSize)); From 7f1a2a6ac67fd751152476c23598d4148b317550 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 12 Jul 2025 12:03:04 -0700 Subject: [PATCH 4/8] Disable dwarf gen for .S files --- clang/tools/driver/cc1as_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 9d5f4895a644e..27289752278ce 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -568,6 +568,10 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, "Invalid file type!"); if (llvm::Triple(Opts.Triple).isVendorLFI()) { + // When compiling .S files, LLVM generates debug info that cannot be + // assembled unless we turn this off here. Encountered when compiling + // sanitizers (asan_interceptors_vfork.S). + Ctx.setGenDwarfForAssembly(false); MCInstPrinter *IP = TheTarget->createMCInstPrinter( llvm::Triple(Opts.Triple), Opts.OutputAsmVariant, *MAI, *MCII, *MRI); From 8026c8ea726fb73c48eb1f1f7251907cc7914fe1 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 12 Jul 2025 18:23:30 -0700 Subject: [PATCH 5/8] Add RISCV support --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 4 ++++ llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 14 ++++++++++++-- llvm/lib/Target/RISCV/RISCVRegisterInfo.h | 4 +++- llvm/lib/Target/RISCV/RISCVSubtarget.cpp | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 6935904a24edb..9be1bf822487c 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -325,6 +325,8 @@ std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args, else if (MABI.starts_with_insensitive("lp64")) { if (Triple.isAndroid()) return "rv64imafdcv_zba_zbb_zbs"; + if (Triple.isVendorLFI()) + return "rv64imafdc_zba_zbb"; return "rv64imafdc"; } @@ -345,6 +347,8 @@ std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args, return "rv64imac"; else if (Triple.isAndroid()) return "rv64imafdcv_zba_zbb_zbs"; + else if (Triple.isVendorLFI()) + return "rv64imafdc_zba_zbb"; else return "rv64imafdc"; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index b0a52698c1e9f..d19c2c36adbcf 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -51,9 +51,11 @@ static_assert(RISCV::F31_D == RISCV::F0_D + 31, static_assert(RISCV::V1 == RISCV::V0 + 1, "Register list not consecutive"); static_assert(RISCV::V31 == RISCV::V0 + 31, "Register list not consecutive"); -RISCVRegisterInfo::RISCVRegisterInfo(unsigned HwMode) +RISCVRegisterInfo::RISCVRegisterInfo(const Triple &TT, unsigned HwMode) : RISCVGenRegisterInfo(RISCV::X1, /*DwarfFlavour*/0, /*EHFlavor*/0, - /*PC*/0, HwMode) {} + /*PC*/0, HwMode) { + IsLFI = TT.isVendorLFI(); +} const MCPhysReg * RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { @@ -113,6 +115,14 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { markSuperRegs(Reserved, Reg); } + if (IsLFI) { + markSuperRegs(Reserved, RISCV::X27_H); // s11 + markSuperRegs(Reserved, RISCV::X26_H); // s10 + markSuperRegs(Reserved, RISCV::X25_H); // s9 + markSuperRegs(Reserved, RISCV::X24_H); // s8 + markSuperRegs(Reserved, RISCV::X1_H); // ra + } + // Use markSuperRegs to ensure any register aliases are also reserved markSuperRegs(Reserved, RISCV::X2_H); // sp markSuperRegs(Reserved, RISCV::X3_H); // gp diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h index 3ab79694e175c..2ee4caf127efc 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h @@ -55,7 +55,7 @@ static inline unsigned getNF(uint64_t TSFlags) { struct RISCVRegisterInfo : public RISCVGenRegisterInfo { - RISCVRegisterInfo(unsigned HwMode); + RISCVRegisterInfo(const Triple &TT, unsigned HwMode); const uint32_t *getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override; @@ -144,6 +144,8 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo { static bool isRVVRegClass(const TargetRegisterClass *RC) { return RISCVRI::isVRegClass(RC->TSFlags); } + + bool IsLFI; }; } // namespace llvm diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp index 1b54c278820fc..c1199b1b67f03 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -106,7 +106,7 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax), FrameLowering( initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), - InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { + InstrInfo(*this), RegInfo(TT, getHwMode()), TLInfo(TM, *this) { TSInfo = std::make_unique(); } From 4a9e87e7e61ba3304ac2fd7c8bfad673689c173f Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sun, 13 Jul 2025 20:10:35 -0700 Subject: [PATCH 6/8] Hacks to get riscv working --- clang/tools/driver/cc1as_main.cpp | 20 +++++++++----------- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 15 +++++++-------- llvm/lib/TargetParser/RISCVISAInfo.cpp | 3 ++- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 27289752278ce..c342fdf038ee7 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -707,7 +707,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr MBuf; MBuf = MemoryBuffer::getMemBuffer(Str, RewriteTemp->TmpName); - SourceMgr SrcMgr; + // SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(MBuf), SMLoc()); std::unique_ptr MRI(TheTarget->createMCRegInfo(triple.getTriple())); @@ -716,15 +716,15 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, abort(); } - std::unique_ptr MCII(TheTarget->createMCInstrInfo()); + // std::unique_ptr MCII(TheTarget->createMCInstrInfo()); std::string OutputString; raw_string_ostream NewOut(OutputString); auto FOut = std::make_unique(NewOut); - MCContext *NewCtx = new MCContext(triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, Ctx.getTargetOptions()); - TheTarget->createMCObjectFileInfo(*NewCtx, Ctx.getObjectFileInfo()->isPositionIndependent()); - NewCtx->setObjectFileInfo(Ctx.getObjectFileInfo()); + MCContext *NewCtx = new MCContext(triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, &MCOptions); + std::unique_ptr MOFI(TheTarget->createMCObjectFileInfo(*NewCtx, Ctx.getObjectFileInfo()->isPositionIndependent())); + NewCtx->setObjectFileInfo(MOFI.get()); std::unique_ptr MCStr; @@ -736,14 +736,14 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, triple, *NewCtx, std::unique_ptr(MAB), MAB->createObjectWriter(*Out), std::unique_ptr(CE), *STI)); + MCStr.get()->initSections(Opts.NoExecStack, *STI); + Ctx.reset(); std::unique_ptr Parser( - createMCAsmParser(SrcMgr, *NewCtx, *MCStr, *MAI)); + createMCAsmParser(SrcMgr, Ctx, *MCStr, *MAI)); - std::unique_ptr MII(TheTarget->createMCInstrInfo()); - assert(MII && "Failed to create instruction info"); std::unique_ptr NewTAP(TheTarget->createMCAsmParser( - TAP->getSTI(), *Parser, *MII, MCOptions)); + *STI, *Parser, *MCII, MCOptions)); if (!NewTAP) report_fatal_error("External rewriting not supported by this streamer because" " we don't have an asm parser for this target\n"); @@ -761,8 +761,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, consumeError(AsmTemp->discard()); return Failed; - - return Failed; } static bool ExecuteAssembler(AssemblerInvocation &Opts, diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 73e213c26d510..fe90b03fb8c06 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2787,7 +2787,7 @@ bool AsmPrinter::doExtAsm() { raw_string_ostream Out(OutputString); auto FOut = std::make_unique(Out); - MCContext *Ctx = new MCContext(TM.getTargetTriple(), MAI, MRI.get(), TM.getMCSubtargetInfo(), &SrcMgr, OutContext.getTargetOptions()); + MCContext *Ctx = new MCContext(TM.getTargetTriple(), MAI, MRI.get(), OutContext.getSubtargetInfo(), &SrcMgr, OutContext.getTargetOptions()); TM.getTarget().createMCObjectFileInfo(*Ctx, OutContext.getObjectFileInfo()->isPositionIndependent()); Ctx->setObjectFileInfo(OutContext.getObjectFileInfo()); @@ -2803,20 +2803,19 @@ bool AsmPrinter::doExtAsm() { Ctx->setUseNamesOnTempLabels(false); - MCCodeEmitter *CE = TM.getTarget().createMCCodeEmitter(*MCII, *Ctx); - MCAsmBackend *MAB = TM.getTarget().createMCAsmBackend(*TM.getMCSubtargetInfo(), *MRI, MCOptions); + MCCodeEmitter *CE = TM.getTarget().createMCCodeEmitter(*MCII, OutContext); + MCAsmBackend *MAB = TM.getTarget().createMCAsmBackend(*OutContext.getSubtargetInfo(), *MRI, MCOptions); MCStr.reset(TM.getTarget().createMCObjectStreamer( - TM.getTargetTriple(), *Ctx, std::unique_ptr(MAB), + TM.getTargetTriple(), OutContext, std::unique_ptr(MAB), MAB->createObjectWriter(*ExtAsm.Out), std::unique_ptr(CE), - *TM.getMCSubtargetInfo())); + *OutContext.getSubtargetInfo())); + MCStr.get()->initSections(true, *TM.getMCSubtargetInfo()); std::unique_ptr Parser( createMCAsmParser(SrcMgr, *Ctx, *MCStr, *MAI)); - std::unique_ptr MII(TM.getTarget().createMCInstrInfo()); - assert(MII && "Failed to create instruction info"); std::unique_ptr TAP(TM.getTarget().createMCAsmParser( - *TM.getMCSubtargetInfo(), *Parser, *MII, MCOptions)); + *TM.getMCSubtargetInfo(), *Parser, *MCII, MCOptions)); if (!TAP) report_fatal_error("External rewriting not supported by this streamer because" " we don't have an asm parser for this target\n"); diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 64ec411cb06e1..3437b8688a377 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -981,7 +981,8 @@ StringRef RISCVISAInfo::computeDefaultABI() const { return "lp64d"; if (Exts.count("f")) return "lp64f"; - return "lp64"; + // HACK for LFI reassembler: lp64 -> lp64d + return "lp64d"; } llvm_unreachable("Invalid XLEN"); } From 58b2fe3ad138fb21050fae3276007b5cdd6af948 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 14 Jul 2025 10:55:03 -0700 Subject: [PATCH 7/8] Undo change to cc1as_main --- clang/tools/driver/cc1as_main.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index c342fdf038ee7..b72b31b8d825c 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -707,7 +707,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr MBuf; MBuf = MemoryBuffer::getMemBuffer(Str, RewriteTemp->TmpName); - // SourceMgr SrcMgr; + SourceMgr SrcMgr; SrcMgr.AddNewSourceBuffer(std::move(MBuf), SMLoc()); std::unique_ptr MRI(TheTarget->createMCRegInfo(triple.getTriple())); @@ -716,15 +716,15 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, abort(); } - // std::unique_ptr MCII(TheTarget->createMCInstrInfo()); + std::unique_ptr MCII(TheTarget->createMCInstrInfo()); std::string OutputString; raw_string_ostream NewOut(OutputString); auto FOut = std::make_unique(NewOut); - MCContext *NewCtx = new MCContext(triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, &MCOptions); - std::unique_ptr MOFI(TheTarget->createMCObjectFileInfo(*NewCtx, Ctx.getObjectFileInfo()->isPositionIndependent())); - NewCtx->setObjectFileInfo(MOFI.get()); + MCContext *NewCtx = new MCContext(triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr, Ctx.getTargetOptions()); + TheTarget->createMCObjectFileInfo(*NewCtx, Ctx.getObjectFileInfo()->isPositionIndependent()); + NewCtx->setObjectFileInfo(Ctx.getObjectFileInfo()); std::unique_ptr MCStr; @@ -738,12 +738,13 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, *STI)); MCStr.get()->initSections(Opts.NoExecStack, *STI); - Ctx.reset(); std::unique_ptr Parser( - createMCAsmParser(SrcMgr, Ctx, *MCStr, *MAI)); + createMCAsmParser(SrcMgr, *NewCtx, *MCStr, *MAI)); + std::unique_ptr MII(TheTarget->createMCInstrInfo()); + assert(MII && "Failed to create instruction info"); std::unique_ptr NewTAP(TheTarget->createMCAsmParser( - *STI, *Parser, *MCII, MCOptions)); + TAP->getSTI(), *Parser, *MII, MCOptions)); if (!NewTAP) report_fatal_error("External rewriting not supported by this streamer because" " we don't have an asm parser for this target\n"); @@ -761,6 +762,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, consumeError(AsmTemp->discard()); return Failed; + + return Failed; } static bool ExecuteAssembler(AssemblerInvocation &Opts, From 7e0f4d19baebc70ceb829a99f12604335a84bad0 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Thu, 31 Jul 2025 12:47:04 -0700 Subject: [PATCH 8/8] Set label alignment to 4 --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index fe90b03fb8c06..2580d0bab7034 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2845,6 +2845,10 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { for (auto &MBB : MF) if (shouldEmitLabelForBasicBlock(MBB)) MBB.setAlignment(Align(32)); + if (TM.getTargetTriple().isVendorLFI() && TM.getTargetTriple().isRISCV()) + for (auto &MBB : MF) + if (shouldEmitLabelForBasicBlock(MBB)) + MBB.setAlignment(Align(4)); // Record that there are split-stack functions, so we will emit a special // section to tell the linker. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index d4eaf06f857be..3d703036e0a8f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1500,6 +1500,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, const Align FunctionAlignment(Subtarget.hasStdExtCOrZca() ? 2 : 4); setMinFunctionAlignment(FunctionAlignment); // Set preferred alignments. + if (Subtarget.getTargetTriple().isVendorLFI()) { + setMinFunctionAlignment(Align(4)); + } setPrefFunctionAlignment(Subtarget.getPrefFunctionAlignment()); setPrefLoopAlignment(Subtarget.getPrefLoopAlignment());