https://github.com/zyedidia created 
https://github.com/llvm/llvm-project/pull/172906

This PR adds the following:

* `MCLFIRewriter` class, which will be used to perform LFI rewrites on a 
per-architecture basis. Each architecture where LFI is supported will implement 
a subclass (for example, 
`Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp`) that will implement the 
`rewriteInst` function to perform the actual rewriting (the AArch64 version 
will be added in the next PR). The generic rewriter class provides some 
instruction info utilities (`mayLoad`, `mayStore`) and is used to call 
`rewriteInst` during instruction emission.
* LFI streamer initialization that marks object files with a NOTE section to 
indicate that the object file is using LFI.
* A basic LFI assembly parser that introduces the `.lfi_rewrite_disable` and 
`.lfi_rewrite_enable` directives that can be used to control whether rewriting 
is enabled or not in hand-written assembly.

The rewriter infrastructure could be useful beyond just LFI, for any kind of 
MC-level rewriting (maybe Spectre mitigations?). We could use a more generic 
name (`MCRewriter`) to reflect that. In that case, the AsmParser would also 
need to be more generic and it would probably make more sense to name the 
directives `.rewrite_disable`/`.rewrite_enable`, or something like that. Let me 
know if you think we should use a more generic name.

>From c1102064630e7b3568b0192f563c124c05b81722 Mon Sep 17 00:00:00 2001
From: Zachary Yedidia <[email protected]>
Date: Thu, 18 Dec 2025 21:06:01 +0000
Subject: [PATCH] [LFI] Add MCLFIRewriter infrastructure

---
 clang/tools/driver/cc1as_main.cpp             |  3 +
 llvm/include/llvm/MC/MCLFI.h                  | 22 ++++++
 llvm/include/llvm/MC/MCLFIRewriter.h          | 64 ++++++++++++++++
 .../llvm/MC/MCParser/MCAsmParserExtension.h   |  2 +
 llvm/include/llvm/MC/MCStreamer.h             |  7 ++
 llvm/include/llvm/MC/TargetRegistry.h         | 21 +++++
 llvm/lib/MC/CMakeLists.txt                    |  2 +
 llvm/lib/MC/MCAsmStreamer.cpp                 |  4 +
 llvm/lib/MC/MCLFI.cpp                         | 76 +++++++++++++++++++
 llvm/lib/MC/MCLFIRewriter.cpp                 | 61 +++++++++++++++
 llvm/lib/MC/MCObjectStreamer.cpp              |  4 +
 llvm/lib/MC/MCParser/AsmParser.cpp            |  9 ++-
 llvm/lib/MC/MCParser/CMakeLists.txt           |  1 +
 llvm/lib/MC/MCParser/LFIAsmParser.cpp         | 67 ++++++++++++++++
 llvm/tools/llvm-mc/llvm-mc.cpp                | 14 ++++
 15 files changed, 355 insertions(+), 2 deletions(-)
 create mode 100644 llvm/include/llvm/MC/MCLFI.h
 create mode 100644 llvm/include/llvm/MC/MCLFIRewriter.h
 create mode 100644 llvm/lib/MC/MCLFI.cpp
 create mode 100644 llvm/lib/MC/MCLFIRewriter.cpp
 create mode 100644 llvm/lib/MC/MCParser/LFIAsmParser.cpp

diff --git a/clang/tools/driver/cc1as_main.cpp 
b/clang/tools/driver/cc1as_main.cpp
index dfff194f83106..78a1226577be7 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -28,6 +28,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCLFI.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCParser/MCAsmParser.h"
@@ -588,6 +589,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
     Triple T(Opts.Triple);
     Str.reset(TheTarget->createMCObjectStreamer(
         T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));
+    if (T.isLFI())
+      initializeLFIMCStreamer(*Str.get(), Ctx, T);
     if (T.isOSBinFormatMachO() && T.isOSDarwin()) {
       Triple *TVT = Opts.DarwinTargetVariantTriple
                         ? &*Opts.DarwinTargetVariantTriple
diff --git a/llvm/include/llvm/MC/MCLFI.h b/llvm/include/llvm/MC/MCLFI.h
new file mode 100644
index 0000000000000..f5f638cd47cbb
--- /dev/null
+++ b/llvm/include/llvm/MC/MCLFI.h
@@ -0,0 +1,22 @@
+//===- MCLFI.h - LFI-specific code for MC -----------------------*- 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
+//
+// This file was written by the LFI and Native Client authors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+
+class MCContext;
+class MCStreamer;
+class Triple;
+
+void initializeLFIMCStreamer(MCStreamer &Streamer, MCContext &Ctx,
+                             const Triple &TheTriple);
+
+} // namespace llvm
diff --git a/llvm/include/llvm/MC/MCLFIRewriter.h 
b/llvm/include/llvm/MC/MCLFIRewriter.h
new file mode 100644
index 0000000000000..d78240c7819c4
--- /dev/null
+++ b/llvm/include/llvm/MC/MCLFIRewriter.h
@@ -0,0 +1,64 @@
+//===- llvm/MC/MCLFIRewriter.h ----------------------------------*- 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
+//
+// This file was written by the LFI and Native Client authors.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the MCLFIRewriter class. This is an abstract
+// class that encapsulates the rewriting logic for MCInsts.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCLFIREWRITER_H
+#define LLVM_MC_MCLFIREWRITER_H
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+
+namespace llvm {
+class MCInst;
+class MCSubtargetInfo;
+class MCStreamer;
+
+class MCLFIRewriter {
+private:
+  MCContext &Ctx;
+  bool Enabled = true;
+
+protected:
+  std::unique_ptr<MCInstrInfo> InstInfo;
+  std::unique_ptr<MCRegisterInfo> RegInfo;
+
+public:
+  MCLFIRewriter(MCContext &Ctx, std::unique_ptr<MCRegisterInfo> &&RI,
+                std::unique_ptr<MCInstrInfo> &&II)
+      : Ctx(Ctx), InstInfo(std::move(II)), RegInfo(std::move(RI)) {}
+
+  void error(const MCInst &Inst, const char Msg[]);
+
+  void disable();
+  void enable();
+  bool isEnabled();
+
+  bool isCall(const MCInst &Inst) const;
+  bool isBranch(const MCInst &Inst) const;
+  bool isIndirectBranch(const MCInst &Inst) const;
+  bool isReturn(const MCInst &Inst) const;
+
+  bool mayLoad(const MCInst &Inst) const;
+  bool mayStore(const MCInst &Inst) const;
+
+  bool mayModifyRegister(const MCInst &Inst, MCRegister Reg) const;
+
+  virtual ~MCLFIRewriter() = default;
+  virtual bool rewriteInst(const MCInst &Inst, MCStreamer &Out,
+                           const MCSubtargetInfo &STI) = 0;
+};
+
+} // namespace llvm
+#endif
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h 
b/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
index 66fd28827065b..a32982ea315a8 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCLFIRewriter.h"
 #include "llvm/MC/MCParser/MCAsmParser.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/SMLoc.h"
@@ -127,6 +128,7 @@ MCAsmParserExtension *createCOFFMasmParser();
 MCAsmParserExtension *createGOFFAsmParser();
 MCAsmParserExtension *createXCOFFAsmParser();
 MCAsmParserExtension *createWasmAsmParser();
+MCAsmParserExtension *createLFIAsmParser(MCLFIRewriter *Exp);
 
 } // end namespace llvm
 
diff --git a/llvm/include/llvm/MC/MCStreamer.h 
b/llvm/include/llvm/MC/MCStreamer.h
index 79c715e3820a6..aa7a457c3487c 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -20,6 +20,7 @@
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCLinkerOptimizationHint.h"
+#include "llvm/MC/MCLFIRewriter.h"
 #include "llvm/MC/MCPseudoProbe.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCWinEH.h"
@@ -290,6 +291,8 @@ class LLVM_ABI MCStreamer {
   /// Returns true if the .cv_loc directive is in the right section.
   bool checkCVLocSection(unsigned FuncId, unsigned FileNo, SMLoc Loc);
 
+  std::unique_ptr<MCLFIRewriter> LFIRewriter;
+
 public:
   MCStreamer(const MCStreamer &) = delete;
   MCStreamer &operator=(const MCStreamer &) = delete;
@@ -307,6 +310,10 @@ class LLVM_ABI MCStreamer {
     return StartTokLocPtr ? *StartTokLocPtr : SMLoc();
   }
 
+  void setLFIRewriter(MCLFIRewriter *Exp) { LFIRewriter.reset(Exp); }
+
+  MCLFIRewriter *getLFIRewriter() { return LFIRewriter.get(); }
+
   /// State management
   ///
   virtual void reset();
diff --git a/llvm/include/llvm/MC/TargetRegistry.h 
b/llvm/include/llvm/MC/TargetRegistry.h
index 234c587c8e951..70c38da62237c 100644
--- a/llvm/include/llvm/MC/TargetRegistry.h
+++ b/llvm/include/llvm/MC/TargetRegistry.h
@@ -46,6 +46,7 @@ class MCDisassembler;
 class MCInstPrinter;
 class MCInstrAnalysis;
 class MCInstrInfo;
+class MCLFIRewriter;
 class MCObjectWriter;
 class MCRegisterInfo;
 class MCRelocationInfo;
@@ -237,6 +238,10 @@ class Target {
       mca::InstrumentManager *(*)(const MCSubtargetInfo &STI,
                                   const MCInstrInfo &MCII);
 
+  using MCLFIRewriterCtorTy = MCLFIRewriter *(*)(
+      MCStreamer &S, std::unique_ptr<MCRegisterInfo> &&RegInfo,
+      std::unique_ptr<MCInstrInfo> &&InstInfo);
+
 private:
   /// Next - The next registered target in the linked list, maintained by the
   /// TargetRegistry.
@@ -351,6 +356,10 @@ class Target {
   /// InstrumentManager, if registered (default = nullptr).
   InstrumentManagerCtorTy InstrumentManagerCtorFn = nullptr;
 
+  // MCLFIRewriterCtorFn - Construction function for this target's
+  // MCLFIRewriter, if registered (default = nullptr).
+  MCLFIRewriterCtorTy MCLFIRewriterCtorFn = nullptr;
+
 public:
   Target() = default;
 
@@ -592,6 +601,13 @@ class Target {
     return nullptr;
   }
 
+  void createMCLFIRewriter(MCStreamer &S,
+      std::unique_ptr<MCRegisterInfo> &&RegInfo,
+      std::unique_ptr<MCInstrInfo> &&InstInfo) const {
+    if (MCLFIRewriterCtorFn)
+      MCLFIRewriterCtorFn(S, std::move(RegInfo), std::move(InstInfo));
+  }
+
   // TODO(boomanaiden154): Remove this function after LLVM 22 branches.
   [[deprecated("Use overload accepting Triple instead")]]
   MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) const 
{
@@ -1064,6 +1080,11 @@ struct TargetRegistry {
     T.InstrumentManagerCtorFn = Fn;
   }
 
+  static void RegisterMCLFIRewriter(Target &T,
+                                    Target::MCLFIRewriterCtorTy Fn) {
+    T.MCLFIRewriterCtorFn = Fn;
+  }
+
   /// @}
 };
 
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index 70c4577aeec0a..ed19d513ef54f 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -31,6 +31,8 @@ add_llvm_component_library(LLVMMC
   MCInstrAnalysis.cpp
   MCInstrDesc.cpp
   MCInstrInfo.cpp
+  MCLFI.cpp
+  MCLFIRewriter.cpp
   MCLabel.cpp
   MCLinkerOptimizationHint.cpp
   MCMachOStreamer.cpp
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index e2543058394a2..82e72fa26d759 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCLFIRewriter.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCPseudoProbe.h"
@@ -2437,6 +2438,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
 
 void MCAsmStreamer::emitInstruction(const MCInst &Inst,
                                     const MCSubtargetInfo &STI) {
+  if (LFIRewriter && LFIRewriter->isEnabled() && 
LFIRewriter->rewriteInst(Inst, *this, STI))
+    return;
+
   if (CurFrag) {
     MCSection *Sec = getCurrentSectionOnly();
     Sec->setHasInstructions(true);
diff --git a/llvm/lib/MC/MCLFI.cpp b/llvm/lib/MC/MCLFI.cpp
new file mode 100644
index 0000000000000..4e078f5fb6819
--- /dev/null
+++ b/llvm/lib/MC/MCLFI.cpp
@@ -0,0 +1,76 @@
+//===- lib/MC/MCLFI.cpp - LFI-specific MC implementation 
------------------===//
+//
+// 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
+//
+// This file was written by the LFI and Native Client authors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCLFI.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCLFIRewriter.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/TargetParser/Triple.h"
+
+static const char NoteNamespace[] = "LFI";
+
+namespace llvm {
+
+cl::opt<bool> FlagEnableRewriting("lfi-enable-rewriter",
+                              cl::desc("Don't enable rewriting for LFI."),
+                              cl::init(true));
+
+void initializeLFIMCStreamer(MCStreamer &Streamer, MCContext &Ctx,
+                             const Triple &TheTriple) {
+  assert(TheTriple.isLFI());
+  const char *NoteName;
+  const char *NoteArch;
+  switch (TheTriple.getArch()) {
+  case Triple::aarch64:
+    NoteName = ".note.LFI.ABI.aarch64";
+    NoteArch = "aarch64";
+    break;
+  default:
+    report_fatal_error("Unsupported architecture for LFI");
+  }
+
+  std::string Error; // empty
+  const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, Error);
+
+  // Create the Target specific MCLFIRewriter.
+  assert(TheTarget != nullptr);
+  if (FlagEnableRewriting) {
+    TheTarget->createMCLFIRewriter(
+        Streamer,
+        std::unique_ptr<MCRegisterInfo>(
+            TheTarget->createMCRegInfo(TheTriple)),
+        std::unique_ptr<MCInstrInfo>(TheTarget->createMCInstrInfo()));
+  }
+
+  // Emit an ELF Note section in its own COMDAT group which identifies LFI
+  // object files.
+  MCSectionELF *Note = Ctx.getELFSection(NoteName, ELF::SHT_NOTE,
+                                         ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
+                                         NoteName, /*IsComdat=*/true);
+
+  Streamer.pushSection();
+  Streamer.switchSection(Note);
+  Streamer.emitIntValue(strlen(NoteNamespace) + 1, 4);
+  Streamer.emitIntValue(strlen(NoteArch) + 1, 4);
+  Streamer.emitIntValue(ELF::NT_VERSION, 4);
+  Streamer.emitBytes(NoteNamespace);
+  Streamer.emitIntValue(0, 1); // NUL terminator
+  Streamer.emitValueToAlignment(Align(4));
+  Streamer.emitBytes(NoteArch);
+  Streamer.emitIntValue(0, 1); // NUL terminator
+  Streamer.emitValueToAlignment(Align(4));
+  Streamer.popSection();
+}
+
+} // namespace llvm
diff --git a/llvm/lib/MC/MCLFIRewriter.cpp b/llvm/lib/MC/MCLFIRewriter.cpp
new file mode 100644
index 0000000000000..5295a5c3e3771
--- /dev/null
+++ b/llvm/lib/MC/MCLFIRewriter.cpp
@@ -0,0 +1,61 @@
+//===- MCLFIRewriter.cpp ----------------------------------------*- 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
+//
+// This file was written by the LFI and Native Client authors.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MCLFIRewriter class. This is a base
+// class that encapsulates the rewriting logic for MCInsts.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCLFIRewriter.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+
+namespace llvm {
+
+void MCLFIRewriter::error(const MCInst &Inst, const char Msg[]) {
+  Ctx.reportError(Inst.getLoc(), Msg);
+}
+
+void MCLFIRewriter::disable() { Enabled = false; }
+
+void MCLFIRewriter::enable() { Enabled = true; }
+
+bool MCLFIRewriter::isEnabled() { return Enabled; }
+
+bool MCLFIRewriter::isCall(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).isCall();
+}
+
+bool MCLFIRewriter::isBranch(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).isBranch();
+}
+
+bool MCLFIRewriter::isIndirectBranch(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).isIndirectBranch();
+}
+
+bool MCLFIRewriter::isReturn(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).isReturn();
+}
+
+bool MCLFIRewriter::mayLoad(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).mayLoad();
+}
+
+bool MCLFIRewriter::mayStore(const MCInst &Inst) const {
+  return InstInfo->get(Inst.getOpcode()).mayStore();
+}
+
+bool MCLFIRewriter::mayModifyRegister(const MCInst &Inst,
+                                      MCRegister Reg) const {
+  return InstInfo->get(Inst.getOpcode()).hasDefOfPhysReg(Inst, Reg, *RegInfo);
+}
+} // namespace llvm
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 94468140a30b9..eef2baf21f3f4 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -15,6 +15,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCLFIRewriter.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSFrame.h"
@@ -390,6 +391,9 @@ bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) 
const {
 
 void MCObjectStreamer::emitInstruction(const MCInst &Inst,
                                        const MCSubtargetInfo &STI) {
+  if (LFIRewriter && LFIRewriter->isEnabled() && 
LFIRewriter->rewriteInst(Inst, *this, STI))
+    return;
+
   MCStreamer::emitInstruction(Inst, STI);
 
   MCSection *Sec = getCurrentSectionOnly();
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp 
b/llvm/lib/MC/MCParser/AsmParser.cpp
index 429cdae1fa1b6..3d650081dbd82 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -120,6 +120,7 @@ class AsmParser : public MCAsmParser {
   SourceMgr::DiagHandlerTy SavedDiagHandler;
   void *SavedDiagContext;
   std::unique_ptr<MCAsmParserExtension> PlatformParser;
+  std::unique_ptr<MCAsmParserExtension> LFIParser;
   SMLoc StartTokLoc;
   std::optional<SMLoc> CFIStartProcLoc;
 
@@ -743,8 +744,8 @@ extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
 
 AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
                      const MCAsmInfo &MAI, unsigned CB = 0)
-    : MCAsmParser(Ctx, Out, SM, MAI), CurBuffer(CB ? CB : SM.getMainFileID()),
-      MacrosEnabledFlag(true) {
+    : MCAsmParser(Ctx, Out, SM, MAI), LFIParser(nullptr),
+      CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
   HadError = false;
   // Save the old handler.
   SavedDiagHandler = SrcMgr.getDiagHandler();
@@ -786,6 +787,10 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, 
MCStreamer &Out,
   }
 
   PlatformParser->Initialize(*this);
+  if (Out.getLFIRewriter()) {
+    LFIParser.reset(createLFIAsmParser(Out.getLFIRewriter()));
+    LFIParser->Initialize(*this);
+  }
   initializeDirectiveKindMap();
   initializeCVDefRangeTypeMap();
 }
diff --git a/llvm/lib/MC/MCParser/CMakeLists.txt 
b/llvm/lib/MC/MCParser/CMakeLists.txt
index 008a50e9da660..c911874fc6540 100644
--- a/llvm/lib/MC/MCParser/CMakeLists.txt
+++ b/llvm/lib/MC/MCParser/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMMCParser
   GOFFAsmParser.cpp
   DarwinAsmParser.cpp
   ELFAsmParser.cpp
+  LFIAsmParser.cpp
   MCAsmParser.cpp
   MCAsmParserExtension.cpp
   MCTargetAsmParser.cpp
diff --git a/llvm/lib/MC/MCParser/LFIAsmParser.cpp 
b/llvm/lib/MC/MCParser/LFIAsmParser.cpp
new file mode 100644
index 0000000000000..b54c955cd4174
--- /dev/null
+++ b/llvm/lib/MC/MCParser/LFIAsmParser.cpp
@@ -0,0 +1,67 @@
+//===- LFIAsmParser.cpp - LFI Assembly Parser 
-----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file was written by the LFI and Native Client authors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCLFIRewriter.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+class LFIAsmParser : public MCAsmParserExtension {
+  MCLFIRewriter *Rewriter;
+  template <bool (LFIAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+  void addDirectiveHandler(StringRef Directive) {
+    MCAsmParser::ExtensionDirectiveHandler Handler =
+        std::make_pair(this, HandleDirective<LFIAsmParser, HandlerMethod>);
+
+    getParser().addDirectiveHandler(Directive, Handler);
+  }
+
+public:
+  LFIAsmParser(MCLFIRewriter *Exp) : Rewriter(Exp) {}
+  void Initialize(MCAsmParser &Parser) override {
+    // Call the base implementation.
+    MCAsmParserExtension::Initialize(Parser);
+    
addDirectiveHandler<&LFIAsmParser::parseRewriteDisable>(".lfi_rewrite_disable");
+    
addDirectiveHandler<&LFIAsmParser::parseRewriteEnable>(".lfi_rewrite_enable");
+  }
+
+  /// ::= {.lfi_rewrite_disable}
+  bool parseRewriteDisable(StringRef Directive, SMLoc Loc) {
+    getParser().checkForValidSection();
+    if (getLexer().isNot(AsmToken::EndOfStatement))
+      return TokError("unexpected token");
+    Lex();
+
+    Rewriter->disable();
+
+    return false;
+  }
+
+  /// ::= {.lfi_rewrite_enable}
+  bool parseRewriteEnable(StringRef Directive, SMLoc Loc) {
+    getParser().checkForValidSection();
+    if (getLexer().isNot(AsmToken::EndOfStatement))
+      return TokError("unexpected token");
+    Lex();
+
+    Rewriter->enable();
+
+    return false;
+  }
+};
+
+namespace llvm {
+MCAsmParserExtension *createLFIAsmParser(MCLFIRewriter *Exp) {
+  return new LFIAsmParser(Exp);
+}
+} // namespace llvm
diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp
index 3b2d4f8625a4c..f8a8254a79792 100644
--- a/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -21,6 +21,7 @@
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCLFI.h"
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCParser/AsmLexer.h"
@@ -626,6 +627,12 @@ int main(int argc, char **argv) {
     Str.reset(TheTarget->createAsmStreamer(Ctx, std::move(FOut), std::move(IP),
                                            std::move(CE), std::move(MAB)));
 
+    Triple T(TripleName);
+    if (T.isLFI()) {
+      Str->initSections(NoExecStack, *STI);
+      initializeLFIMCStreamer(*Str.get(), Ctx, T);
+    }
+
   } else if (FileType == OFT_Null) {
     Str.reset(TheTarget->createNullStreamer(Ctx));
   } else {
@@ -646,6 +653,13 @@ int main(int argc, char **argv) {
     if (NoExecStack)
       Str->switchSection(
           Ctx.getAsmInfo()->getStackSection(Ctx, /*Exec=*/false));
+
+    Triple T(TripleName);
+    if (T.isLFI()) {
+      Str->initSections(NoExecStack, *STI);
+      initializeLFIMCStreamer(*Str.get(), Ctx, T);
+    }
+
     Str->emitVersionForTarget(TheTriple, VersionTuple(), nullptr,
                               VersionTuple());
   }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to