Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:28

0001 //===---- IndirectThunks.h - Indirect thunk insertion helpers ---*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// Contains a base ThunkInserter class that simplifies injection of MI thunks
0011 /// as well as a default implementation of MachineFunctionPass wrapping
0012 /// several `ThunkInserter`s for targets to extend.
0013 ///
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_CODEGEN_INDIRECTTHUNKS_H
0017 #define LLVM_CODEGEN_INDIRECTTHUNKS_H
0018 
0019 #include "llvm/CodeGen/MachineFunction.h"
0020 #include "llvm/CodeGen/MachineFunctionPass.h"
0021 #include "llvm/CodeGen/MachineModuleInfo.h"
0022 #include "llvm/IR/IRBuilder.h"
0023 #include "llvm/IR/Module.h"
0024 
0025 namespace llvm {
0026 
0027 /// This class assists in inserting MI thunk functions into the module and
0028 /// rewriting the existing machine functions to call these thunks.
0029 ///
0030 /// One of the common cases is implementing security mitigations that involve
0031 /// replacing some machine code patterns with calls to special thunk functions.
0032 ///
0033 /// Inserting a module pass late in the codegen pipeline may increase memory
0034 /// usage, as it serializes the transformations and forces preceding passes to
0035 /// produce machine code for all functions before running the module pass.
0036 /// For that reason, ThunkInserter can be driven by a MachineFunctionPass by
0037 /// passing one MachineFunction at a time to its `run(MMI, MF)` method.
0038 /// Then, the derived class should
0039 /// * call createThunkFunction from its insertThunks method exactly once for
0040 ///   each of the thunk functions to be inserted
0041 /// * populate the thunk in its populateThunk method
0042 ///
0043 /// Note that if some other pass is responsible for rewriting the functions,
0044 /// the insertThunks method may simply create all possible thunks at once,
0045 /// probably postponed until the first occurrence of possibly affected MF.
0046 ///
0047 /// Alternatively, insertThunks method can rewrite MF by itself and only insert
0048 /// the thunks being called. In that case InsertedThunks variable can be used
0049 /// to track which thunks were already inserted.
0050 ///
0051 /// In any case, the thunk function has to be inserted on behalf of some other
0052 /// function and then populated on its own "iteration" later - this is because
0053 /// MachineFunctionPass will see the newly created functions, but they first
0054 /// have to go through the preceding passes from the same pass manager,
0055 /// possibly even through the instruction selector.
0056 //
0057 // FIXME Maybe implement a documented and less surprising way of modifying
0058 //       the module from a MachineFunctionPass that is restricted to inserting
0059 //       completely new functions to the module.
0060 template <typename Derived, typename InsertedThunksTy = bool>
0061 class ThunkInserter {
0062   Derived &getDerived() { return *static_cast<Derived *>(this); }
0063 
0064   // A variable used to track whether (and possible which) thunks have been
0065   // inserted so far. InsertedThunksTy is usually a bool, but can be other types
0066   // to represent more than one type of thunk. Requires an |= operator to
0067   // accumulate results.
0068   InsertedThunksTy InsertedThunks;
0069 
0070 protected:
0071   // Interface for subclasses to use.
0072 
0073   /// Create an empty thunk function.
0074   ///
0075   /// The new function will eventually be passed to populateThunk. If multiple
0076   /// thunks are created, populateThunk can distinguish them by their names.
0077   void createThunkFunction(MachineModuleInfo &MMI, StringRef Name,
0078                            bool Comdat = true, StringRef TargetAttrs = "");
0079 
0080 protected:
0081   // Interface for subclasses to implement.
0082   //
0083   // Note: all functions are non-virtual and are called via getDerived().
0084   // Note: only doInitialization() has an implementation.
0085 
0086   /// Initializes thunk inserter.
0087   void doInitialization(Module &M) {}
0088 
0089   /// Returns common prefix for thunk function's names.
0090   const char *getThunkPrefix(); // undefined
0091 
0092   /// Checks if MF may use thunks (true - maybe, false - definitely not).
0093   bool mayUseThunk(const MachineFunction &MF); // undefined
0094 
0095   /// Rewrites the function if necessary, returns the set of thunks added.
0096   InsertedThunksTy insertThunks(MachineModuleInfo &MMI, MachineFunction &MF,
0097                                 InsertedThunksTy ExistingThunks); // undefined
0098 
0099   /// Populate the thunk function with instructions.
0100   ///
0101   /// If multiple thunks are created, the content that must be inserted in the
0102   /// thunk function body should be derived from the MF's name.
0103   ///
0104   /// Depending on the preceding passes in the pass manager, by the time
0105   /// populateThunk is called, MF may have a few target-specific instructions
0106   /// (such as a single MBB containing the return instruction).
0107   void populateThunk(MachineFunction &MF); // undefined
0108 
0109 public:
0110   void init(Module &M) {
0111     InsertedThunks = InsertedThunksTy{};
0112     getDerived().doInitialization(M);
0113   }
0114   // return `true` if `MMI` or `MF` was modified
0115   bool run(MachineModuleInfo &MMI, MachineFunction &MF);
0116 };
0117 
0118 template <typename Derived, typename InsertedThunksTy>
0119 void ThunkInserter<Derived, InsertedThunksTy>::createThunkFunction(
0120     MachineModuleInfo &MMI, StringRef Name, bool Comdat,
0121     StringRef TargetAttrs) {
0122   assert(Name.starts_with(getDerived().getThunkPrefix()) &&
0123          "Created a thunk with an unexpected prefix!");
0124 
0125   Module &M = const_cast<Module &>(*MMI.getModule());
0126   LLVMContext &Ctx = M.getContext();
0127   auto *Type = FunctionType::get(Type::getVoidTy(Ctx), false);
0128   Function *F = Function::Create(Type,
0129                                  Comdat ? GlobalValue::LinkOnceODRLinkage
0130                                         : GlobalValue::InternalLinkage,
0131                                  Name, &M);
0132   if (Comdat) {
0133     F->setVisibility(GlobalValue::HiddenVisibility);
0134     F->setComdat(M.getOrInsertComdat(Name));
0135   }
0136 
0137   // Add Attributes so that we don't create a frame, unwind information, or
0138   // inline.
0139   AttrBuilder B(Ctx);
0140   B.addAttribute(llvm::Attribute::NoUnwind);
0141   B.addAttribute(llvm::Attribute::Naked);
0142   if (TargetAttrs != "")
0143     B.addAttribute("target-features", TargetAttrs);
0144   F->addFnAttrs(B);
0145 
0146   // Populate our function a bit so that we can verify.
0147   BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F);
0148   IRBuilder<> Builder(Entry);
0149 
0150   Builder.CreateRetVoid();
0151 
0152   // MachineFunctions aren't created automatically for the IR-level constructs
0153   // we already made. Create them and insert them into the module.
0154   MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
0155   // A MachineBasicBlock must not be created for the Entry block; code
0156   // generation from an empty naked function in C source code also does not
0157   // generate one.  At least GlobalISel asserts if this invariant isn't
0158   // respected.
0159 
0160   // Set MF properties. We never use vregs...
0161   MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
0162 }
0163 
0164 template <typename Derived, typename InsertedThunksTy>
0165 bool ThunkInserter<Derived, InsertedThunksTy>::run(MachineModuleInfo &MMI,
0166                                                    MachineFunction &MF) {
0167   // If MF is not a thunk, check to see if we need to insert a thunk.
0168   if (!MF.getName().starts_with(getDerived().getThunkPrefix())) {
0169     // Only add thunks if one of the functions may use them.
0170     if (!getDerived().mayUseThunk(MF))
0171       return false;
0172 
0173     // The target can use InsertedThunks to detect whether relevant thunks
0174     // have already been inserted.
0175     // FIXME: Provide the way for insertThunks to notify us whether it changed
0176     //        the MF, instead of conservatively assuming it did.
0177     InsertedThunks |= getDerived().insertThunks(MMI, MF, InsertedThunks);
0178     return true;
0179   }
0180 
0181   // If this *is* a thunk function, we need to populate it with the correct MI.
0182   getDerived().populateThunk(MF);
0183   return true;
0184 }
0185 
0186 /// Basic implementation of MachineFunctionPass wrapping one or more
0187 /// `ThunkInserter`s passed as type parameters.
0188 template <typename... Inserters>
0189 class ThunkInserterPass : public MachineFunctionPass {
0190 protected:
0191   std::tuple<Inserters...> TIs;
0192 
0193   ThunkInserterPass(char &ID) : MachineFunctionPass(ID) {}
0194 
0195 public:
0196   bool doInitialization(Module &M) override {
0197     initTIs(M, TIs);
0198     return false;
0199   }
0200 
0201   bool runOnMachineFunction(MachineFunction &MF) override {
0202     auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
0203     return runTIs(MMI, MF, TIs);
0204   }
0205 
0206 private:
0207   template <typename... ThunkInserterT>
0208   static void initTIs(Module &M,
0209                       std::tuple<ThunkInserterT...> &ThunkInserters) {
0210     (..., std::get<ThunkInserterT>(ThunkInserters).init(M));
0211   }
0212 
0213   template <typename... ThunkInserterT>
0214   static bool runTIs(MachineModuleInfo &MMI, MachineFunction &MF,
0215                      std::tuple<ThunkInserterT...> &ThunkInserters) {
0216     return (0 | ... | std::get<ThunkInserterT>(ThunkInserters).run(MMI, MF));
0217   }
0218 };
0219 
0220 } // namespace llvm
0221 
0222 #endif