1 //===------ WindowsHotPatch.cpp - Support for Windows hotpatching ---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Provides support for the Windows "Secure Hot-Patching" feature. 10 // 11 // Windows contains technology, called "Secure Hot-Patching" (SHP), for securely 12 // applying hot-patches to a running system. Hot-patches may be applied to the 13 // kernel, kernel-mode components, device drivers, user-mode system services, 14 // etc. 15 // 16 // SHP relies on integration between many tools, including compiler, linker, 17 // hot-patch generation tools, and the Windows kernel. This file implements that 18 // part of the workflow needed in compilers / code generators. 19 // 20 // SHP is not intended for productivity scenarios such as Edit-and-Continue or 21 // interactive development. SHP is intended to minimize downtime during 22 // installation of Windows OS patches. 23 // 24 // In order to work with SHP, LLVM must do all of the following: 25 // 26 // * On some architectures (X86, AMD64), the function prolog must begin with 27 // hot-patchable instructions. This is handled by the MSVC `/hotpatch` option 28 // and the equivalent `-fms-hotpatch` function. This is necessary because we 29 // generally cannot anticipate which functions will need to be patched in the 30 // future. This option ensures that a function can be hot-patched in the 31 // future, but does not actually generate any hot-patch for it. 32 // 33 // * For a selected set of functions that are being hot-patched (which are 34 // identified using command-line options), LLVM must generate the 35 // `S_HOTPATCHFUNC` CodeView record (symbol). This record indicates that a 36 // function was compiled with hot-patching enabled. 37 // 38 // This implementation uses the `MarkedForWindowsHotPatching` attribute to 39 // annotate those functions that were marked for hot-patching by command-line 40 // parameters. The attribute may be specified by a language front-end by 41 // setting an attribute when a function is created in LLVM IR, or it may be 42 // set by passing LLVM arguments. 43 // 44 // * For those functions that are hot-patched, LLVM must rewrite references to 45 // global variables so that they are indirected through a `__ref_*` pointer 46 // variable. For each global variable, that is accessed by a hot-patched 47 // function, e.g. `FOO`, a `__ref_FOO` global pointer variable is created and 48 // all references to the original `FOO` are rewritten as dereferences of the 49 // `__ref_FOO` pointer. 50 // 51 // Some globals do not need `__ref_*` indirection. The pointer indirection 52 // behavior can be disabled for these globals by marking them with the 53 // `AllowDirectAccessInHotPatchFunction`. 54 // 55 // Rewriting references to global variables has some complexity. 56 // 57 // For ordinary instructions that reference GlobalVariables, we rewrite the 58 // operand of the instruction to a Load of the __ref_* variable. 59 // 60 // For constant expressions, we have to convert the constant expression (and 61 // transitively all constant expressions in its parent chain) to non-constant 62 // expressions, i.e. to a sequence of instructions. 63 // 64 // Pass 1: 65 // * Enumerate all instructions in all basic blocks. 66 // 67 // * If an instruction references a GlobalVariable (and it is not marked 68 // as being ignored), then we create (if necessary) the __ref_* variable 69 // for the GlobalVariable reference. However, we do not yet modify the 70 // Instruction. 71 // 72 // * If an instruction has an operand that is a ConstantExpr and the 73 // ConstantExpression tree contains a reference to a GlobalVariable, then 74 // we similarly create __ref_*. Similarly, we do not yet modify the 75 // Instruction or the ConstantExpr tree. 76 // 77 // After Pass 1 completes, we will know whether we found any references to 78 // globals in this pass. If the function does not use any globals (and most 79 // functions do not use any globals), then we return immediately. 80 // 81 // If a function does reference globals, then we iterate the list of globals 82 // used by this function and we generate Load instructions for each (unique) 83 // global. 84 // 85 // Next, we do another pass over all instructions: 86 // 87 // Pass 2: 88 // * Re-visit the instructions that were found in Pass 1. 89 // 90 // * If an instruction operand is a GlobalVariable, then look up the 91 // replacement 92 // __ref_* global variable and the Value that came from the Load instruction 93 // for it. Replace the operand of the GlobalVariable with the Load Value. 94 // 95 // * If an instruction operand is a ConstantExpr, then recursively examine the 96 // operands of all instructions in the ConstantExpr tree. If an operand is 97 // a GlobalVariable, then replace the operand with the result of the load 98 // *and* convert the ConstantExpr to a non-constant instruction. This 99 // instruction will need to be inserted into the BB of the instruction whose 100 // operand is being modified, ideally immediately before the instruction 101 // being modified. 102 // 103 // Limitations 104 // 105 // This feature is not intended to work in every situation. There are many 106 // legitimate code changes (patches) for which it is not possible to generate 107 // a hot-patch. Developers who are writing hot-patches are expected to 108 // understand the limitations. 109 // 110 // Tools which generate hot-patch metadata may also check that certain 111 // variables are upheld, and some of these invariants may be global (may require 112 // whole-program knowledge, not available in any single compiland). However, 113 // such tools are not required to be perfect; they are also best-effort. 114 // 115 // For these reasons, the hot-patching support implemented in this file is 116 // "best effort". It does not recognize every possible code pattern that could 117 // be patched, nor does it generate diagnostics for certain code patterns that 118 // could result in a binary that does not work with hot-patching. For example, 119 // const GlobalVariables that point to other non-const GlobalVariables are not 120 // compatible with hot-patching because they cannot use __ref_*-based 121 // redirection. 122 // 123 // References 124 // 125 // * "Hotpatching on Windows": 126 // https://techcommunity.microsoft.com/blog/windowsosplatform/hotpatching-on-windows/2959541 127 // 128 // * "Hotpatch for Windows client now available": 129 // https://techcommunity.microsoft.com/blog/windows-itpro-blog/hotpatch-for-windows-client-now-available/4399808 130 // 131 // * "Get hotpatching for Windows Server": 132 // https://www.microsoft.com/en-us/windows-server/blog/2025/04/24/tired-of-all-the-restarts-get-hotpatching-for-windows-server/ 133 // 134 //===----------------------------------------------------------------------===// 135 136 #include "llvm/ADT/SmallSet.h" 137 #include "llvm/CodeGen/Passes.h" 138 #include "llvm/IR/Attributes.h" 139 #include "llvm/IR/DIBuilder.h" 140 #include "llvm/IR/DiagnosticInfo.h" 141 #include "llvm/IR/Function.h" 142 #include "llvm/IR/IRBuilder.h" 143 #include "llvm/IR/InstIterator.h" 144 #include "llvm/IR/Module.h" 145 #include "llvm/InitializePasses.h" 146 #include "llvm/Pass.h" 147 #include "llvm/Support/CommandLine.h" 148 #include "llvm/Support/LineIterator.h" 149 #include "llvm/Support/MemoryBuffer.h" 150 151 using namespace llvm; 152 153 #define DEBUG_TYPE "windows-secure-hot-patch" 154 155 // A file containing list of mangled function names to mark for hot patching. 156 static cl::opt<std::string> LLVMMSSecureHotPatchFunctionsFile( 157 "ms-secure-hotpatch-functions-file", cl::value_desc("filename"), 158 cl::desc("A file containing list of mangled function names to mark for " 159 "Windows Secure Hot-Patching")); 160 161 // A list of mangled function names to mark for hot patching. 162 static cl::list<std::string> LLVMMSSecureHotPatchFunctionsList( 163 "ms-secure-hotpatch-functions-list", cl::value_desc("list"), 164 cl::desc("A list of mangled function names to mark for Windows Secure " 165 "Hot-Patching"), 166 cl::CommaSeparated); 167 168 namespace { 169 170 struct GlobalVariableUse { 171 // GlobalVariable *GV; 172 Instruction *User; 173 unsigned Op; 174 }; 175 176 class WindowsSecureHotPatching : public ModulePass { 177 public: 178 static char ID; 179 180 WindowsSecureHotPatching() : ModulePass(ID) { 181 initializeWindowsSecureHotPatchingPass(*PassRegistry::getPassRegistry()); 182 } 183 184 void getAnalysisUsage(AnalysisUsage &AU) const override { 185 AU.setPreservesCFG(); 186 } 187 188 bool doInitialization(Module &) override; 189 bool runOnModule(Module &M) override { return false; } 190 191 private: 192 bool 193 runOnFunction(Function &F, 194 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping); 195 }; 196 197 } // end anonymous namespace 198 199 char WindowsSecureHotPatching::ID = 0; 200 201 INITIALIZE_PASS(WindowsSecureHotPatching, "windows-secure-hot-patch", 202 "Mark functions for Windows hot patch support", false, false) 203 ModulePass *llvm::createWindowsSecureHotPatchingPass() { 204 return new WindowsSecureHotPatching(); 205 } 206 207 // Find functions marked with Attribute::MarkedForWindowsHotPatching and modify 208 // their code (if necessary) to account for accesses to global variables. 209 // 210 // This runs during doInitialization() instead of runOnModule() because it needs 211 // to run before CodeViewDebug::collectGlobalVariableInfo(). 212 bool WindowsSecureHotPatching::doInitialization(Module &M) { 213 // The front end may have already marked functions for hot-patching. However, 214 // we also allow marking functions by passing -ms-hotpatch-functions-file or 215 // -ms-hotpatch-functions-list directly to LLVM. This allows hot-patching to 216 // work with languages that have not yet updated their front-ends. 217 if (!LLVMMSSecureHotPatchFunctionsFile.empty() || 218 !LLVMMSSecureHotPatchFunctionsList.empty()) { 219 std::vector<std::string> HotPatchFunctionsList; 220 221 if (!LLVMMSSecureHotPatchFunctionsFile.empty()) { 222 auto BufOrErr = MemoryBuffer::getFile(LLVMMSSecureHotPatchFunctionsFile); 223 if (BufOrErr) { 224 const MemoryBuffer &FileBuffer = **BufOrErr; 225 for (line_iterator I(FileBuffer.getMemBufferRef(), true), E; I != E; 226 ++I) 227 HotPatchFunctionsList.push_back(std::string{*I}); 228 } else { 229 M.getContext().diagnose(DiagnosticInfoGeneric{ 230 Twine("failed to open hotpatch functions file " 231 "(--ms-hotpatch-functions-file): ") + 232 LLVMMSSecureHotPatchFunctionsFile + Twine(" : ") + 233 BufOrErr.getError().message()}); 234 } 235 } 236 237 if (!LLVMMSSecureHotPatchFunctionsList.empty()) 238 for (const auto &FuncName : LLVMMSSecureHotPatchFunctionsList) 239 HotPatchFunctionsList.push_back(FuncName); 240 241 // Build a set for quick lookups. This points into HotPatchFunctionsList, so 242 // HotPatchFunctionsList must live longer than HotPatchFunctionsSet. 243 SmallSet<StringRef, 16> HotPatchFunctionsSet; 244 for (const auto &FuncName : HotPatchFunctionsList) 245 HotPatchFunctionsSet.insert(StringRef{FuncName}); 246 247 // Iterate through all of the functions and check whether they need to be 248 // marked for hotpatching using the list provided directly to LLVM. 249 for (auto &F : M.functions()) { 250 // Ignore declarations that are not definitions. 251 if (F.isDeclarationForLinker()) 252 continue; 253 254 if (HotPatchFunctionsSet.contains(F.getName())) 255 F.addFnAttr("marked_for_windows_hot_patching"); 256 } 257 } 258 259 SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping; 260 bool MadeChanges = false; 261 for (auto &F : M.functions()) { 262 if (F.hasFnAttribute("marked_for_windows_hot_patching")) { 263 if (runOnFunction(F, RefMapping)) 264 MadeChanges = true; 265 } 266 } 267 return MadeChanges; 268 } 269 270 static bool TypeContainsPointers(Type *ty) { 271 switch (ty->getTypeID()) { 272 case Type::PointerTyID: 273 return true; 274 275 case Type::ArrayTyID: 276 return TypeContainsPointers(ty->getArrayElementType()); 277 278 case Type::StructTyID: { 279 unsigned NumElements = ty->getStructNumElements(); 280 for (unsigned I = 0; I < NumElements; ++I) { 281 if (TypeContainsPointers(ty->getStructElementType(I))) { 282 return true; 283 } 284 } 285 return false; 286 } 287 288 default: 289 return false; 290 } 291 } 292 293 // Returns true if GV needs redirection through a __ref_* variable. 294 static bool globalVariableNeedsRedirect(GlobalVariable *GV) { 295 // If a global variable is explictly marked as allowing access in hot-patched 296 // functions, then do not redirect it. 297 if (GV->hasAttribute("allow_direct_access_in_hot_patch_function")) 298 return false; 299 300 // If the global variable is not a constant, then we want to redirect it. 301 if (!GV->isConstant()) { 302 if (GV->getName().starts_with("??_R")) { 303 // This is the name mangling prefix that MSVC uses for RTTI data. 304 // Clang is currently generating RTTI data that is marked non-constant. 305 // We override that and treat it like it is constant. 306 return false; 307 } 308 309 // In general, if a global variable is not a constant, then redirect it. 310 return true; 311 } 312 313 // If the type of GV cannot contain pointers, then it cannot point to 314 // other global variables. In this case, there is no need for redirects. 315 // For example, string literals do not contain pointers. 316 return TypeContainsPointers(GV->getValueType()); 317 } 318 319 // Get or create a new global variable that points to the old one and whose 320 // name begins with `__ref_`. 321 // 322 // In hot-patched images, the __ref_* variables point to global variables in 323 // the original (unpatched) image. Hot-patched functions in the hot-patch 324 // image use these __ref_* variables to access global variables. This ensures 325 // that all code (both unpatched and patched) is using the same instances of 326 // global variables. 327 // 328 // The Windows hot-patch infrastructure handles modifying these __ref_* 329 // variables. By default, they are initialized with pointers to the equivalent 330 // global variables, so when a hot-patch module is loaded *as* a base image 331 // (such as after a system reboot), hot-patch functions will access the 332 // instances of global variables that are compiled into the hot-patch image. 333 // This is the desired outcome, since in this situation (normal boot) the 334 // hot-patch image *is* the base image. 335 // 336 // When we create the GlobalVariable for the __ref_* variable, we must create 337 // it as a *non-constant* global variable. The __ref_* pointers will not change 338 // during the runtime of the program, so it is tempting to think that they 339 // should be constant. However, they still need to be updateable by the 340 // hot-patching infrastructure. Also, if the GlobalVariable is created as a 341 // constant, then the LLVM optimizer will assume that it can dereference the 342 // definition of the __ref_* variable at compile time, which defeats the 343 // purpose of the indirection (pointer). 344 // 345 // The RefMapping table spans the entire module, not just a single function. 346 static GlobalVariable *getOrCreateRefVariable( 347 Function &F, SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping, 348 GlobalVariable *GV) { 349 GlobalVariable *&ReplaceWithRefGV = RefMapping.try_emplace(GV).first->second; 350 if (ReplaceWithRefGV != nullptr) { 351 // We have already created a __ref_* pointer for this GlobalVariable. 352 return ReplaceWithRefGV; 353 } 354 355 Module *M = F.getParent(); 356 357 const DISubprogram *Subprogram = F.getSubprogram(); 358 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr; 359 DIFile *File = Subprogram != nullptr ? Subprogram->getFile() : nullptr; 360 DIBuilder DebugInfo{*F.getParent(), true, Unit}; 361 362 auto PtrTy = PointerType::get(M->getContext(), 0); 363 364 Constant *AddrOfOldGV = 365 ConstantExpr::getGetElementPtr(PtrTy, GV, ArrayRef<Value *>{}); 366 367 GlobalVariable *RefGV = 368 new GlobalVariable(*M, PtrTy, false, GlobalValue::LinkOnceAnyLinkage, 369 AddrOfOldGV, Twine("__ref_").concat(GV->getName()), 370 nullptr, GlobalVariable::NotThreadLocal); 371 372 // Create debug info for the replacement global variable. 373 DataLayout Layout = M->getDataLayout(); 374 DIType *DebugType = DebugInfo.createPointerType( 375 nullptr, Layout.getTypeSizeInBits(GV->getValueType())); 376 DIGlobalVariableExpression *GVE = DebugInfo.createGlobalVariableExpression( 377 Unit, RefGV->getName(), StringRef{}, File, 378 /*LineNo*/ 0, DebugType, 379 /*IsLocalToUnit*/ false); 380 RefGV->addDebugInfo(GVE); 381 382 // Store the __ref_* in RefMapping so that future calls use the same RefGV. 383 ReplaceWithRefGV = RefGV; 384 385 return RefGV; 386 } 387 388 // Given a ConstantExpr, this searches for GlobalVariable references within 389 // the expression tree. If found, it will generate instructions and will 390 // return a non-null Value* that points to the new root instruction. 391 // 392 // If C does not contain any GlobalVariable references, this returns nullptr. 393 // 394 // If this function creates new instructions, then it will insert them 395 // before InsertionPoint. 396 static Value *rewriteGlobalVariablesInConstant( 397 Constant *C, SmallDenseMap<GlobalVariable *, Value *> &GVLoadMap, 398 IRBuilder<> &IRBuilderAtEntry) { 399 if (C->getValueID() == Value::GlobalVariableVal) { 400 GlobalVariable *GV = cast<GlobalVariable>(C); 401 if (globalVariableNeedsRedirect(GV)) { 402 return GVLoadMap.at(GV); 403 } else { 404 return nullptr; 405 } 406 } 407 408 // Scan the operands of this expression. 409 410 SmallVector<Value *, 8> ReplacedValues; 411 bool ReplacedAnyOperands = false; 412 413 unsigned NumOperands = C->getNumOperands(); 414 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { 415 Value *OldValue = C->getOperand(OpIndex); 416 Value *ReplacedValue = nullptr; 417 if (Constant *OldConstant = dyn_cast<Constant>(OldValue)) { 418 ReplacedValue = rewriteGlobalVariablesInConstant(OldConstant, GVLoadMap, 419 IRBuilderAtEntry); 420 } 421 // Do not use short-circuiting, here. We need to traverse the whole tree. 422 ReplacedAnyOperands |= ReplacedValue != nullptr; 423 ReplacedValues.push_back(ReplacedValue); 424 } 425 426 // If none of our operands were replaced, then don't rewrite this expression. 427 if (!ReplacedAnyOperands) { 428 return nullptr; 429 } 430 431 // We need to rewrite this expression. Convert this constant expression 432 // to an instruction, then replace any operands as needed. 433 Instruction *NewInst = cast<ConstantExpr>(C)->getAsInstruction(); 434 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { 435 Value *ReplacedValue = ReplacedValues[OpIndex]; 436 if (ReplacedValue != nullptr) { 437 NewInst->setOperand(OpIndex, ReplacedValue); 438 } 439 } 440 441 // Insert the new instruction before the reference instruction. 442 IRBuilderAtEntry.Insert(NewInst); 443 444 return NewInst; 445 } 446 447 static bool searchConstantExprForGlobalVariables( 448 Value *V, SmallDenseMap<GlobalVariable *, Value *> &GVLoadMap, 449 SmallVector<GlobalVariableUse> &GVUses) { 450 451 SmallVector<Value *, 8> ReplacedOperands; 452 453 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { 454 if (globalVariableNeedsRedirect(GV)) { 455 GVLoadMap[GV] = nullptr; 456 return true; 457 } else { 458 return false; 459 } 460 } 461 462 if (User *U = dyn_cast<User>(V)) { 463 unsigned NumOperands = U->getNumOperands(); 464 bool FoundAny = false; 465 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { 466 Value *Op = U->getOperand(OpIndex); 467 // Do not use short-circuiting, here. We need to traverse the whole tree. 468 FoundAny |= searchConstantExprForGlobalVariables(Op, GVLoadMap, GVUses); 469 } 470 return FoundAny; 471 } else { 472 return false; 473 } 474 } 475 476 // Processes a function that is marked for hot-patching. 477 // 478 // If a function is marked for hot-patching, we generate an S_HOTPATCHFUNC 479 // CodeView debug symbol. Tools that generate hot-patches look for 480 // S_HOTPATCHFUNC in final PDBs so that they can find functions that have been 481 // hot-patched and so that they can distinguish hot-patched functions from 482 // non-hot-patched functions. 483 // 484 // Also, in functions that are hot-patched, we must indirect all access to 485 // (mutable) global variables through a pointer. This pointer may point into the 486 // unpatched ("base") binary or may point into the patched image, depending on 487 // whether a hot-patch was loaded as a patch or as a base image. These 488 // indirections go through a new global variable, named `__ref_<Foo>` where 489 // `<Foo>` is the original symbol name of the global variable. 490 // 491 // This function handles rewriting accesses to global variables, but the 492 // generation of S_HOTPATCHFUNC occurs in 493 // CodeViewDebug::emitHotPatchInformation(). 494 // 495 // Returns true if any global variable references were found and rewritten. 496 bool WindowsSecureHotPatching::runOnFunction( 497 Function &F, 498 SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) { 499 // Scan the function for references to global variables. If we find such a 500 // reference, create (if necessary) the __ref_* variable, then add an entry 501 // to the GVUses table. 502 // 503 // We ignore references to global variables if the variable is marked with 504 // AllowDirectAccessInHotPatchFunction. 505 506 SmallDenseMap<GlobalVariable *, Value *> GVLoadMap; 507 SmallVector<GlobalVariableUse> GVUses; 508 509 for (auto &I : instructions(F)) { 510 unsigned NumOperands = I.getNumOperands(); 511 for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { 512 Value *V = I.getOperand(OpIndex); 513 514 bool FoundAnyGVUses = false; 515 516 switch (V->getValueID()) { 517 case Value::GlobalVariableVal: { 518 // Discover all uses of GlobalVariable, these will need to be replaced. 519 GlobalVariable *GV = cast<GlobalVariable>(V); 520 if (globalVariableNeedsRedirect(GV)) { 521 GVLoadMap.insert(std::make_pair(GV, nullptr)); 522 FoundAnyGVUses = true; 523 } 524 break; 525 } 526 527 case Value::ConstantExprVal: { 528 ConstantExpr *CE = cast<ConstantExpr>(V); 529 if (searchConstantExprForGlobalVariables(CE, GVLoadMap, GVUses)) { 530 FoundAnyGVUses = true; 531 } 532 break; 533 } 534 535 default: 536 break; 537 } 538 539 if (FoundAnyGVUses) { 540 GVUses.push_back(GlobalVariableUse{&I, OpIndex}); 541 } 542 } 543 } 544 545 // If this function did not reference any global variables then we have no 546 // work to do. Most functions do not access global variables. 547 if (GVUses.empty()) { 548 return false; 549 } 550 551 // We know that there is at least one instruction that needs to be rewritten. 552 // Generate a Load instruction for each unique GlobalVariable used by this 553 // function. The Load instructions are inserted at the beginning of the 554 // entry block. Since entry blocks cannot contain PHI instructions, there is 555 // no need to skip PHI instructions. 556 557 // We use a single IRBuilder for inserting Load instructions as well as the 558 // constants that we convert to instructions. Because constants do not 559 // depend on any dynamic values (they're constant, after all!), it is safe 560 // to move them to the start of entry BB. 561 562 auto &EntryBlock = F.getEntryBlock(); 563 IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin()); 564 565 for (auto &[GV, LoadValue] : GVLoadMap) { 566 assert(LoadValue == nullptr); 567 GlobalVariable *RefGV = getOrCreateRefVariable(F, RefMapping, GV); 568 LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->getValueType(), RefGV); 569 } 570 571 const DISubprogram *Subprogram = F.getSubprogram(); 572 DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr; 573 DIBuilder DebugInfo{*F.getParent(), true, Unit}; 574 575 // Go back to the instructions and rewrite their uses of GlobalVariable. 576 // Because a ConstantExpr can be a tree, it may reference more than one 577 // GlobalVariable. 578 579 for (auto &GVUse : GVUses) { 580 Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op); 581 Value *NewOperandValue; 582 583 switch (OldOperandValue->getValueID()) { 584 case Value::GlobalVariableVal: { 585 // This is easy. Look up the replacement value and store the operand. 586 Value *OperandValue = GVUse.User->getOperand(GVUse.Op); 587 GlobalVariable *GV = cast<GlobalVariable>(OperandValue); 588 NewOperandValue = GVLoadMap.at(GV); 589 break; 590 } 591 592 case Value::ConstantExprVal: { 593 // Walk the recursive tree of the ConstantExpr. If we find a 594 // GlobalVariable then replace it with the loaded value and rewrite 595 // the ConstantExpr to an Instruction and insert it before the 596 // current instruction. 597 Value *OperandValue = GVUse.User->getOperand(GVUse.Op); 598 ConstantExpr *CE = cast<ConstantExpr>(OperandValue); 599 NewOperandValue = 600 rewriteGlobalVariablesInConstant(CE, GVLoadMap, IRBuilderAtEntry); 601 assert(NewOperandValue != nullptr); 602 break; 603 } 604 605 default: 606 // We should only ever get here because a GVUse was created in the first 607 // pass, and this only happens for GlobalVariableVal and ConstantExprVal. 608 llvm_unreachable_internal( 609 "unexpected Value in second pass of hot-patching"); 610 break; 611 } 612 613 GVUse.User->setOperand(GVUse.Op, NewOperandValue); 614 } 615 616 return true; 617 } 618