================ @@ -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()) { + continue; + } + + llvm::StringRef FuncName{}; + if (auto *SP = F.getSubprogram(); SP != nullptr) { ---------------- sivadeilra wrote:
Ahh, I think this is incorrect. I just need the mangled name of the symbol, and at one point this was the only way I could get it. I think this can simply be `F.getName()`; I'll verify and update. 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