OSDN Git Service

Re-land r329156 "Add llvm-exegesis tool."
[android-x86/external-llvm.git] / tools / llvm-exegesis / lib / InMemoryAssembler.cpp
1 //===-- InMemoryAssembler.cpp -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
32
33 namespace exegesis {
34
35 static constexpr const char ModuleID[] = "ExegesisInfoTest";
36 static constexpr const char FunctionID[] = "foo";
37
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);
43   if (!PI) {
44     llvm::errs() << " run-pass " << PassName << " is not registered.\n";
45     return true;
46   }
47
48   if (!PI->getNormalCtor()) {
49     llvm::errs() << " cannot create pass: " << PI->getPassName() << "\n";
50     return true;
51   }
52   llvm::Pass *P = PI->getNormalCtor()();
53   std::string Banner = std::string("After ") + std::string(P->getPassName());
54   PM.add(P);
55   TPC.printAndVerify(Banner);
56
57   return false;
58 }
59
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
69   // contains no IR.
70   F->setIsMaterializable(true);
71   return MMI->getOrCreateMachineFunction(*F);
72 }
73
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();
79
80   llvm::TargetLibraryInfoImpl TLII(llvm::Triple(Module->getTargetTriple()));
81   PM.add(new llvm::TargetLibraryInfoWrapperPass(TLII));
82
83   llvm::TargetPassConfig *TPC = LLVMTM->createPassConfig(PM);
84   PM.add(TPC);
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();
94
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,
99                             Context))
100     llvm::report_fatal_error("Cannot add AsmPrinter passes");
101
102   PM.run(*Module); // Run all the passes
103
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));
113 }
114
115 static void fillMachineFunction(llvm::MachineFunction &MF,
116                                 llvm::ArrayRef<llvm::MCInst> Instructions) {
117   llvm::MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
118   MF.push_back(MBB);
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;
126          ++OpIndex) {
127       const llvm::MCOperand &Op = Inst.getOperand(OpIndex);
128       if (Op.isReg()) {
129         const bool IsDef = OpIndex < MCID.getNumDefs();
130         unsigned Flags = 0;
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());
137       } else {
138         llvm_unreachable("Not yet implemented");
139       }
140     }
141   }
142   // Adding the Return Opcode.
143   const llvm::TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
144   llvm::BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
145 }
146
147 namespace {
148
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 {
152 public:
153   explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
154       : CodeSize(CodeSize) {}
155
156   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
157                                unsigned SectionID,
158                                llvm::StringRef SectionName) override {
159     *CodeSize = Size;
160     return llvm::SectionMemoryManager::allocateCodeSection(
161         Size, Alignment, SectionID, SectionName);
162   }
163
164 private:
165   uintptr_t *const CodeSize = nullptr;
166 };
167
168 } // namespace
169
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
178   // registers.
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);
188 }
189
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
195   // ObjectFile.
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.
202   LLVMLinkInMCJIT();
203   uintptr_t CodeSize = 0;
204   std::string Error;
205   ExecEngine.reset(
206       llvm::EngineBuilder(std::move(FunctionContext.Module))
207           .setErrorStr(&Error)
208           .setMCPU(FunctionContext.TM->getTargetCPU())
209           .setEngineKind(llvm::EngineKind::JIT)
210           .setMCJITMemoryManager(
211               llvm::make_unique<TrackingSectionMemoryManager>(&CodeSize))
212           .create(FunctionContext.TM.release()));
213   if (!ExecEngine)
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
217   // executable page.
218   ExecEngine->addObjectFile(ObjHolder.takeBinary().first);
219   // Setting function
220   FunctionBytes =
221       llvm::StringRef(reinterpret_cast<const char *>(
222                           ExecEngine->getFunctionAddress(FunctionID)),
223                       CodeSize);
224 }
225
226 } // namespace exegesis