1 //===-- Assembler.h ---------------------------------------------*- C++ -*-===// 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 /// \file 10 /// Defines classes to assemble functions composed of a single basic block of 11 /// MCInsts. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_ASSEMBLER_H 16 #define LLVM_TOOLS_LLVM_EXEGESIS_ASSEMBLER_H 17 18 #include <memory> 19 20 #include "BenchmarkCode.h" 21 #include "Error.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/ADT/BitVector.h" 24 #include "llvm/CodeGen/MachineFunction.h" 25 #include "llvm/CodeGen/MachineModuleInfo.h" 26 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 27 #include "llvm/IR/LLVMContext.h" 28 #include "llvm/IR/Module.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/Object/Binary.h" 31 #include "llvm/Object/ObjectFile.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include "llvm/Target/TargetMachine.h" 34 35 namespace llvm { 36 namespace exegesis { 37 38 class ExegesisTarget; 39 40 // Gather the set of reserved registers (depends on function's calling 41 // convention and target machine). 42 BitVector getFunctionReservedRegs(const TargetMachine &TM); 43 44 // Helper to fill in a basic block. 45 class BasicBlockFiller { 46 public: 47 BasicBlockFiller(MachineFunction &MF, MachineBasicBlock *MBB, 48 const MCInstrInfo *MCII); 49 50 void addInstruction(const MCInst &Inst, const DebugLoc &DL = DebugLoc()); 51 void addInstructions(ArrayRef<MCInst> Insts, const DebugLoc &DL = DebugLoc()); 52 53 void addReturn(const ExegesisTarget &ET, bool SubprocessCleanup, 54 const DebugLoc &DL = DebugLoc()); 55 56 MachineFunction &MF; 57 MachineBasicBlock *const MBB; 58 const MCInstrInfo *const MCII; 59 }; 60 61 // Helper to fill in a function. 62 class FunctionFiller { 63 public: 64 FunctionFiller(MachineFunction &MF, std::vector<MCRegister> RegistersSetUp); 65 66 // Adds a basic block to the function. 67 BasicBlockFiller addBasicBlock(); 68 69 // Returns the function entry point. 70 BasicBlockFiller getEntry() { return Entry; } 71 72 MachineFunction &MF; 73 const MCInstrInfo *const MCII; 74 75 // Returns the set of registers in the snippet setup code. 76 ArrayRef<MCRegister> getRegistersSetUp() const; 77 78 private: 79 BasicBlockFiller Entry; 80 // The set of registers that are set up in the basic block. 81 std::vector<MCRegister> RegistersSetUp; 82 }; 83 84 // A callback that fills a function. 85 using FillFunction = std::function<void(FunctionFiller &)>; 86 87 // Creates a temporary `void foo(char*)` function containing the provided 88 // Instructions. Runs a set of llvm Passes to provide correct prologue and 89 // epilogue. Once the MachineFunction is ready, it is assembled for TM to 90 // AsmStream, the temporary function is eventually discarded. 91 Error assembleToStream(const ExegesisTarget &ET, 92 std::unique_ptr<TargetMachine> TM, 93 ArrayRef<MCRegister> LiveIns, const FillFunction &Fill, 94 raw_pwrite_stream &AsmStreamm, const BenchmarkKey &Key, 95 bool GenerateMemoryInstructions); 96 97 // Creates an ObjectFile in the format understood by the host. 98 // Note: the resulting object keeps a copy of Buffer so it can be discarded once 99 // this function returns. 100 object::OwningBinary<object::ObjectFile> getObjectFromBuffer(StringRef Buffer); 101 102 // Loads the content of Filename as on ObjectFile and returns it. 103 object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename); 104 105 // Consumes an ObjectFile containing a `void foo(char*)` function and make it 106 // executable. 107 class ExecutableFunction { 108 public: 109 static Expected<ExecutableFunction> 110 create(std::unique_ptr<TargetMachine> TM, 111 object::OwningBinary<object::ObjectFile> &&ObjectFileHolder); 112 113 // Retrieves the function as an array of bytes. 114 StringRef getFunctionBytes() const { return FunctionBytes; } 115 116 // Executes the function. 117 void operator()(char *Memory) const { 118 ((void (*)(char *))(uintptr_t)FunctionBytes.data())(Memory); 119 } 120 121 StringRef FunctionBytes; 122 123 private: 124 ExecutableFunction(std::unique_ptr<LLVMContext> Ctx, 125 std::unique_ptr<orc::LLJIT> EJIT, StringRef FunctionBytes); 126 127 std::unique_ptr<LLVMContext> Context; 128 std::unique_ptr<orc::LLJIT> ExecJIT; 129 }; 130 131 // Copies benchmark function's bytes from benchmark object. 132 Error getBenchmarkFunctionBytes(const StringRef InputData, 133 std::vector<uint8_t> &Bytes); 134 135 // Creates a void(int8*) MachineFunction. 136 MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionID, 137 Module *Module, 138 MachineModuleInfo *MMI); 139 140 } // namespace exegesis 141 } // namespace llvm 142 143 #endif // LLVM_TOOLS_LLVM_EXEGESIS_ASSEMBLER_H 144