================
@@ -0,0 +1,251 @@
+//===------ WindowsHotPatch.cpp - Support for Windows hotpatching 
---------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Marks functions with the `marked_for_windows_hot_patching` attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "windows-hot-patch"
+
+// A file containing list of mangled function names to mark for hot patching.
+static cl::opt<std::string> LLVMMSHotPatchFunctionsFile(
+    "ms-hotpatch-functions-file", cl::value_desc("filename"),
+    cl::desc("A file containing list of mangled function names to mark for hot 
"
+             "patching"));
+
+// A list of mangled function names to mark for hot patching.
+static cl::list<std::string> LLVMMSHotPatchFunctionsList(
+    "ms-hotpatch-functions-list", cl::value_desc("list"),
+    cl::desc("A list of mangled function names to mark for hot patching"),
+    cl::CommaSeparated);
+
+namespace {
+
+class WindowsHotPatch : public ModulePass {
+  struct GlobalVariableUse {
+    GlobalVariable *GV;
+    Instruction *User;
+    unsigned Op;
+  };
+
+public:
+  static char ID;
+
+  WindowsHotPatch() : ModulePass(ID) {
+    initializeWindowsHotPatchPass(*PassRegistry::getPassRegistry());
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+  }
+
+  bool runOnModule(Module &M) override;
+
+private:
+  bool
+  runOnFunction(Function &F,
+                SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping);
+  void replaceGlobalVariableUses(
+      Function &F, SmallVectorImpl<GlobalVariableUse> &GVUses,
+      SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping,
+      DIBuilder &DebugInfo);
+};
+
+} // end anonymous namespace
+
+char WindowsHotPatch::ID = 0;
+
+INITIALIZE_PASS(WindowsHotPatch, "windows-hot-patch",
+                "Mark functions for Windows hot patch support", false, false)
+ModulePass *llvm::createWindowsHotPatch() { return new WindowsHotPatch(); }
+
+// Find functions marked with Attribute::MarkedForWindowsHotPatching and modify
+// their code (if necessary) to account for accesses to global variables.
+bool WindowsHotPatch::runOnModule(Module &M) {
+  // The front end may have already marked functions for hot-patching. However,
+  // we also allow marking functions by passing -ms-hotpatch-functions-file or
+  // -ms-hotpatch-functions-list directly to LLVM. This allows hot-patching to
+  // work with languages that have not yet updated their front-ends.
+  if (!LLVMMSHotPatchFunctionsFile.empty() ||
+      !LLVMMSHotPatchFunctionsList.empty()) {
+    std::vector<std::string> HotPatchFunctionsList;
+
+    if (!LLVMMSHotPatchFunctionsFile.empty()) {
+      auto BufOrErr = llvm::MemoryBuffer::getFile(LLVMMSHotPatchFunctionsFile);
+      if (BufOrErr) {
+        const llvm::MemoryBuffer &FileBuffer = **BufOrErr;
+        for (llvm::line_iterator I(FileBuffer.getMemBufferRef(), true), E;
+             I != E; ++I) {
+          HotPatchFunctionsList.push_back(std::string{*I});
+        }
+      } else {
+        M.getContext().diagnose(llvm::DiagnosticInfoGeneric{
+            llvm::Twine("failed to open hotpatch functions file "
+                        "(--ms-hotpatch-functions-file): ") +
+            LLVMMSHotPatchFunctionsFile + llvm::Twine(" : ") +
+            BufOrErr.getError().message()});
+      }
+    }
+
+    if (!LLVMMSHotPatchFunctionsList.empty()) {
+      for (const auto &FuncName : LLVMMSHotPatchFunctionsList) {
+        HotPatchFunctionsList.push_back(FuncName);
+      }
+    }
+
+    // Build a set for quick lookups. This points into HotPatchFunctionsList, 
so
+    // HotPatchFunctionsList must live longer than HotPatchFunctionsSet.
+    llvm::SmallSet<llvm::StringRef, 16> HotPatchFunctionsSet;
+    for (const auto &FuncName : HotPatchFunctionsList) {
+      HotPatchFunctionsSet.insert(llvm::StringRef{FuncName});
+    }
+
+    // Iterate through all of the functions and check whether they need to be
+    // marked for hotpatching using the list provided directly to LLVM.
+    for (auto &F : M.functions()) {
+      // Ignore declarations that are not definitions.
+      if (F.isDeclarationForLinker()) {
----------------
dpaoliello wrote:

> Furthermore, you mentioned the experience using MSVC - are you referring to 
> Edit & Continue or something else?

This is not for Edit-and-Continue, this is for hot-patching deployed Windows 
machines running retail bits: 
https://www.microsoft.com/en-us/windows-server/blog/2025/04/24/tired-of-all-the-restarts-get-hotpatching-for-windows-server/?msockid=19a6f8f09bd160ac0b18ed449afc614b

> There are hot-patch tools that can deal with symbols with internal linkage 
> just fine ([Live++](https://liveplusplus.tech/)), and it doesn't require 
> developers to do any "homework" at all.

True, but tools like that have their own restrictions. From their own docs:
>Linker -> Optimization -> References must be set to No (/OPT:NOREF)
>Linker -> Optimization -> Enable COMDAT Folding must be set to No (/OPT:NOICF)

For Windows hot-patching one of the goals was to enable its use with 
fully-optimized binaries, the downside of this (as Eli called out) that that 
the optimizer can do lots of things that mess with the resulting symbols and 
binaries, hence why there is some "homework" required (i.e., we'd rather have 
Microsoft devs spend time to craft hot-patching changes that meet these 
requirements rather than deploy suboptimal binaries to customers).

https://github.com/llvm/llvm-project/pull/138972
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to