1 //===-- InMemoryAssembler.cpp -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "InMemoryAssembler.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/CodeGen/MachineInstrBuilder.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/TargetInstrInfo.h"
17 #include "llvm/CodeGen/TargetPassConfig.h"
18 #include "llvm/ExecutionEngine/ExecutionEngine.h"
19 #include "llvm/ExecutionEngine/MCJIT.h"
20 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
21 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/IR/LegacyPassManager.h"
23 #include "llvm/MC/MCFixup.h"
24 #include "llvm/MC/MCInstrDesc.h"
25 #include "llvm/Object/Binary.h"
26 #include "llvm/Object/ObjectFile.h"
27 #include "llvm/PassInfo.h"
28 #include "llvm/PassRegistry.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/Target/TargetMachine.h"
31 #include "llvm/Target/TargetOptions.h"
35 static constexpr const char ModuleID[] = "ExegesisInfoTest";
36 static constexpr const char FunctionID[] = "foo";
38 // Small utility function to add named passes.
39 static bool addPass(llvm::PassManagerBase &PM, llvm::StringRef PassName,
40 llvm::TargetPassConfig &TPC) {
41 const llvm::PassRegistry *PR = llvm::PassRegistry::getPassRegistry();
42 const llvm::PassInfo *PI = PR->getPassInfo(PassName);
44 llvm::errs() << " run-pass " << PassName << " is not registered.\n";
48 if (!PI->getNormalCtor()) {
49 llvm::errs() << " cannot create pass: " << PI->getPassName() << "\n";
52 llvm::Pass *P = PI->getNormalCtor()();
53 std::string Banner = std::string("After ") + std::string(P->getPassName());
55 TPC.printAndVerify(Banner);
60 // Creates a void MachineFunction with no argument.
61 static llvm::MachineFunction &
62 createVoidVoidMachineFunction(llvm::StringRef FunctionID, llvm::Module *Module,
63 llvm::MachineModuleInfo *MMI) {
64 llvm::Type *const ReturnType = llvm::Type::getInt32Ty(Module->getContext());
65 llvm::FunctionType *FunctionType = llvm::FunctionType::get(ReturnType, false);
66 llvm::Function *const F = llvm::Function::Create(
67 FunctionType, llvm::GlobalValue::InternalLinkage, FunctionID, Module);
68 // Making sure we can create a MachineFunction out of this Function even if it
70 F->setIsMaterializable(true);
71 return MMI->getOrCreateMachineFunction(*F);
74 static llvm::object::OwningBinary<llvm::object::ObjectFile>
75 assemble(llvm::Module *Module, std::unique_ptr<llvm::MachineModuleInfo> MMI,
76 llvm::LLVMTargetMachine *LLVMTM) {
77 llvm::legacy::PassManager PM;
78 llvm::MCContext &Context = MMI->getContext();
80 llvm::TargetLibraryInfoImpl TLII(llvm::Triple(Module->getTargetTriple()));
81 PM.add(new llvm::TargetLibraryInfoWrapperPass(TLII));
83 llvm::TargetPassConfig *TPC = LLVMTM->createPassConfig(PM);
85 PM.add(MMI.release());
86 TPC->printAndVerify("MachineFunctionGenerator::assemble");
87 // Adding the following passes:
88 // - machineverifier: checks that the MachineFunction is well formed.
89 // - prologepilog: saves and restore callee saved registers.
90 for (const char *PassName : {"machineverifier", "prologepilog"})
91 if (addPass(PM, PassName, *TPC))
92 llvm::report_fatal_error("Unable to add a mandatory pass");
93 TPC->setInitialized();
95 llvm::SmallVector<char, 4096> AsmBuffer;
96 llvm::raw_svector_ostream AsmStream(AsmBuffer);
97 // AsmPrinter is responsible for generating the assembly into AsmBuffer.
98 if (LLVMTM->addAsmPrinter(PM, AsmStream, llvm::TargetMachine::CGFT_ObjectFile,
100 llvm::report_fatal_error("Cannot add AsmPrinter passes");
102 PM.run(*Module); // Run all the passes
104 // Storing the generated assembly into a MemoryBuffer that owns the memory.
105 std::unique_ptr<llvm::MemoryBuffer> Buffer =
106 llvm::MemoryBuffer::getMemBufferCopy(AsmStream.str());
107 // Create the ObjectFile from the MemoryBuffer.
108 std::unique_ptr<llvm::object::ObjectFile> Obj = llvm::cantFail(
109 llvm::object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()));
110 // Returning both the MemoryBuffer and the ObjectFile.
111 return llvm::object::OwningBinary<llvm::object::ObjectFile>(
112 std::move(Obj), std::move(Buffer));
115 static void fillMachineFunction(llvm::MachineFunction &MF,
116 llvm::ArrayRef<llvm::MCInst> Instructions) {
117 llvm::MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
119 const llvm::MCInstrInfo *MCII = MF.getTarget().getMCInstrInfo();
120 const llvm::DebugLoc DL;
121 for (const llvm::MCInst &Inst : Instructions) {
122 const unsigned Opcode = Inst.getOpcode();
123 const llvm::MCInstrDesc &MCID = MCII->get(Opcode);
124 llvm::MachineInstrBuilder Builder = llvm::BuildMI(MBB, DL, MCID);
125 for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;
127 const llvm::MCOperand &Op = Inst.getOperand(OpIndex);
129 const bool IsDef = OpIndex < MCID.getNumDefs();
131 const llvm::MCOperandInfo &OpInfo = MCID.operands().begin()[OpIndex];
132 if (IsDef && !OpInfo.isOptionalDef())
133 Flags |= llvm::RegState::Define;
134 Builder.addReg(Op.getReg(), Flags);
135 } else if (Op.isImm()) {
136 Builder.addImm(Op.getImm());
138 llvm_unreachable("Not yet implemented");
142 // Adding the Return Opcode.
143 const llvm::TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
144 llvm::BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
149 // Implementation of this class relies on the fact that a single object with a
150 // single function will be loaded into memory.
151 class TrackingSectionMemoryManager : public llvm::SectionMemoryManager {
153 explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
154 : CodeSize(CodeSize) {}
156 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
158 llvm::StringRef SectionName) override {
160 return llvm::SectionMemoryManager::allocateCodeSection(
161 Size, Alignment, SectionID, SectionName);
165 uintptr_t *const CodeSize = nullptr;
170 JitFunctionContext::JitFunctionContext(
171 std::unique_ptr<llvm::LLVMTargetMachine> TheTM)
172 : Context(llvm::make_unique<llvm::LLVMContext>()), TM(std::move(TheTM)),
173 MMI(llvm::make_unique<llvm::MachineModuleInfo>(TM.get())),
174 Module(llvm::make_unique<llvm::Module>(ModuleID, *Context)) {
175 Module->setDataLayout(TM->createDataLayout());
176 MF = &createVoidVoidMachineFunction(FunctionID, Module.get(), MMI.get());
177 // We need to instruct the passes that we're done with SSA and virtual
179 auto &Properties = MF->getProperties();
180 Properties.set(llvm::MachineFunctionProperties::Property::NoVRegs);
181 Properties.reset(llvm::MachineFunctionProperties::Property::IsSSA);
182 Properties.reset(llvm::MachineFunctionProperties::Property::TracksLiveness);
183 // prologue/epilogue pass needs the reserved registers to be frozen, this is
184 // usually done by the SelectionDAGISel pass.
185 MF->getRegInfo().freezeReservedRegs(*MF);
186 // Saving reserved registers for client.
187 ReservedRegs = MF->getSubtarget().getRegisterInfo()->getReservedRegs(*MF);
190 JitFunction::JitFunction(JitFunctionContext &&Context,
191 llvm::ArrayRef<llvm::MCInst> Instructions)
192 : FunctionContext(std::move(Context)) {
193 fillMachineFunction(*FunctionContext.MF, Instructions);
194 // We create the pass manager, run the passes and returns the produced
196 llvm::object::OwningBinary<llvm::object::ObjectFile> ObjHolder =
197 assemble(FunctionContext.Module.get(), std::move(FunctionContext.MMI),
198 FunctionContext.TM.get());
199 assert(ObjHolder.getBinary() && "cannot create object file");
200 // Initializing the execution engine.
201 // We need to use the JIT EngineKind to be able to add an object file.
203 uintptr_t CodeSize = 0;
206 llvm::EngineBuilder(std::move(FunctionContext.Module))
208 .setMCPU(FunctionContext.TM->getTargetCPU())
209 .setEngineKind(llvm::EngineKind::JIT)
210 .setMCJITMemoryManager(
211 llvm::make_unique<TrackingSectionMemoryManager>(&CodeSize))
212 .create(FunctionContext.TM.release()));
214 llvm::report_fatal_error(Error);
215 // Adding the generated object file containing the assembled function.
216 // The ExecutionEngine makes sure the object file is copied into an
218 ExecEngine->addObjectFile(ObjHolder.takeBinary().first);
221 llvm::StringRef(reinterpret_cast<const char *>(
222 ExecEngine->getFunctionAddress(FunctionID)),
226 } // namespace exegesis