1 //===-- Assembler.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 "Assembler.h"
11 
12 #include "Target.h"
13 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
14 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineModuleInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/TargetInstrInfo.h"
19 #include "llvm/CodeGen/TargetPassConfig.h"
20 #include "llvm/CodeGen/TargetSubtargetInfo.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
22 #include "llvm/IR/LegacyPassManager.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 
26 namespace llvm {
27 namespace exegesis {
28 
29 static constexpr const char ModuleID[] = "ExegesisInfoTest";
30 static constexpr const char FunctionID[] = "foo";
31 
32 static std::vector<llvm::MCInst>
generateSnippetSetupCode(const ExegesisTarget & ET,const llvm::MCSubtargetInfo * const MSI,llvm::ArrayRef<RegisterValue> RegisterInitialValues,bool & IsSnippetSetupComplete)33 generateSnippetSetupCode(const ExegesisTarget &ET,
34                          const llvm::MCSubtargetInfo *const MSI,
35                          llvm::ArrayRef<RegisterValue> RegisterInitialValues,
36                          bool &IsSnippetSetupComplete) {
37   IsSnippetSetupComplete = true;
38   std::vector<llvm::MCInst> Result;
39   for (const RegisterValue &RV : RegisterInitialValues) {
40     // Load a constant in the register.
41     const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
42     if (SetRegisterCode.empty())
43       IsSnippetSetupComplete = false;
44     Result.insert(Result.end(), SetRegisterCode.begin(), SetRegisterCode.end());
45   }
46   return Result;
47 }
48 
49 // Small utility function to add named passes.
addPass(llvm::PassManagerBase & PM,llvm::StringRef PassName,llvm::TargetPassConfig & TPC)50 static bool addPass(llvm::PassManagerBase &PM, llvm::StringRef PassName,
51                     llvm::TargetPassConfig &TPC) {
52   const llvm::PassRegistry *PR = llvm::PassRegistry::getPassRegistry();
53   const llvm::PassInfo *PI = PR->getPassInfo(PassName);
54   if (!PI) {
55     llvm::errs() << " run-pass " << PassName << " is not registered.\n";
56     return true;
57   }
58 
59   if (!PI->getNormalCtor()) {
60     llvm::errs() << " cannot create pass: " << PI->getPassName() << "\n";
61     return true;
62   }
63   llvm::Pass *P = PI->getNormalCtor()();
64   std::string Banner = std::string("After ") + std::string(P->getPassName());
65   PM.add(P);
66   TPC.printAndVerify(Banner);
67 
68   return false;
69 }
70 
71 // Creates a void(int8*) MachineFunction.
72 static llvm::MachineFunction &
createVoidVoidPtrMachineFunction(llvm::StringRef FunctionID,llvm::Module * Module,llvm::MachineModuleInfo * MMI)73 createVoidVoidPtrMachineFunction(llvm::StringRef FunctionID,
74                                  llvm::Module *Module,
75                                  llvm::MachineModuleInfo *MMI) {
76   llvm::Type *const ReturnType = llvm::Type::getInt32Ty(Module->getContext());
77   llvm::Type *const MemParamType = llvm::PointerType::get(
78       llvm::Type::getInt8Ty(Module->getContext()), 0 /*default address space*/);
79   llvm::FunctionType *FunctionType =
80       llvm::FunctionType::get(ReturnType, {MemParamType}, false);
81   llvm::Function *const F = llvm::Function::Create(
82       FunctionType, llvm::GlobalValue::InternalLinkage, FunctionID, Module);
83   // Making sure we can create a MachineFunction out of this Function even if it
84   // contains no IR.
85   F->setIsMaterializable(true);
86   return MMI->getOrCreateMachineFunction(*F);
87 }
88 
fillMachineFunction(llvm::MachineFunction & MF,llvm::ArrayRef<unsigned> LiveIns,llvm::ArrayRef<llvm::MCInst> Instructions)89 static void fillMachineFunction(llvm::MachineFunction &MF,
90                                 llvm::ArrayRef<unsigned> LiveIns,
91                                 llvm::ArrayRef<llvm::MCInst> Instructions) {
92   llvm::MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
93   MF.push_back(MBB);
94   for (const unsigned Reg : LiveIns)
95     MBB->addLiveIn(Reg);
96   const llvm::MCInstrInfo *MCII = MF.getTarget().getMCInstrInfo();
97   llvm::DebugLoc DL;
98   for (const llvm::MCInst &Inst : Instructions) {
99     const unsigned Opcode = Inst.getOpcode();
100     const llvm::MCInstrDesc &MCID = MCII->get(Opcode);
101     llvm::MachineInstrBuilder Builder = llvm::BuildMI(MBB, DL, MCID);
102     for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;
103          ++OpIndex) {
104       const llvm::MCOperand &Op = Inst.getOperand(OpIndex);
105       if (Op.isReg()) {
106         const bool IsDef = OpIndex < MCID.getNumDefs();
107         unsigned Flags = 0;
108         const llvm::MCOperandInfo &OpInfo = MCID.operands().begin()[OpIndex];
109         if (IsDef && !OpInfo.isOptionalDef())
110           Flags |= llvm::RegState::Define;
111         Builder.addReg(Op.getReg(), Flags);
112       } else if (Op.isImm()) {
113         Builder.addImm(Op.getImm());
114       } else if (!Op.isValid()) {
115         llvm_unreachable("Operand is not set");
116       } else {
117         llvm_unreachable("Not yet implemented");
118       }
119     }
120   }
121   // Insert the return code.
122   const llvm::TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
123   if (TII->getReturnOpcode() < TII->getNumOpcodes()) {
124     llvm::BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
125   } else {
126     llvm::MachineIRBuilder MIB(MF);
127     MIB.setMBB(*MBB);
128     MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {});
129   }
130 }
131 
132 static std::unique_ptr<llvm::Module>
createModule(const std::unique_ptr<llvm::LLVMContext> & Context,const llvm::DataLayout DL)133 createModule(const std::unique_ptr<llvm::LLVMContext> &Context,
134              const llvm::DataLayout DL) {
135   auto Module = llvm::make_unique<llvm::Module>(ModuleID, *Context);
136   Module->setDataLayout(DL);
137   return Module;
138 }
139 
getFunctionReservedRegs(const llvm::TargetMachine & TM)140 llvm::BitVector getFunctionReservedRegs(const llvm::TargetMachine &TM) {
141   std::unique_ptr<llvm::LLVMContext> Context =
142       llvm::make_unique<llvm::LLVMContext>();
143   std::unique_ptr<llvm::Module> Module =
144       createModule(Context, TM.createDataLayout());
145   // TODO: This only works for targets implementing LLVMTargetMachine.
146   const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine&>(TM);
147   std::unique_ptr<llvm::MachineModuleInfo> MMI =
148       llvm::make_unique<llvm::MachineModuleInfo>(&LLVMTM);
149   llvm::MachineFunction &MF =
150       createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get());
151   // Saving reserved registers for client.
152   return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF);
153 }
154 
assembleToStream(const ExegesisTarget & ET,std::unique_ptr<llvm::LLVMTargetMachine> TM,llvm::ArrayRef<unsigned> LiveIns,llvm::ArrayRef<RegisterValue> RegisterInitialValues,llvm::ArrayRef<llvm::MCInst> Instructions,llvm::raw_pwrite_stream & AsmStream)155 void assembleToStream(const ExegesisTarget &ET,
156                       std::unique_ptr<llvm::LLVMTargetMachine> TM,
157                       llvm::ArrayRef<unsigned> LiveIns,
158                       llvm::ArrayRef<RegisterValue> RegisterInitialValues,
159                       llvm::ArrayRef<llvm::MCInst> Instructions,
160                       llvm::raw_pwrite_stream &AsmStream) {
161   std::unique_ptr<llvm::LLVMContext> Context =
162       llvm::make_unique<llvm::LLVMContext>();
163   std::unique_ptr<llvm::Module> Module =
164       createModule(Context, TM->createDataLayout());
165   std::unique_ptr<llvm::MachineModuleInfo> MMI =
166       llvm::make_unique<llvm::MachineModuleInfo>(TM.get());
167   llvm::MachineFunction &MF =
168       createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get());
169 
170   // We need to instruct the passes that we're done with SSA and virtual
171   // registers.
172   auto &Properties = MF.getProperties();
173   Properties.set(llvm::MachineFunctionProperties::Property::NoVRegs);
174   Properties.reset(llvm::MachineFunctionProperties::Property::IsSSA);
175 
176   for (const unsigned Reg : LiveIns)
177     MF.getRegInfo().addLiveIn(Reg);
178 
179   bool IsSnippetSetupComplete;
180   std::vector<llvm::MCInst> Code =
181       generateSnippetSetupCode(ET, TM->getMCSubtargetInfo(),
182                                RegisterInitialValues, IsSnippetSetupComplete);
183 
184   Code.insert(Code.end(), Instructions.begin(), Instructions.end());
185 
186   // If the snippet setup is not complete, we disable liveliness tracking. This
187   // means that we won't know what values are in the registers.
188   if (!IsSnippetSetupComplete)
189     Properties.reset(llvm::MachineFunctionProperties::Property::TracksLiveness);
190 
191   // prologue/epilogue pass needs the reserved registers to be frozen, this
192   // is usually done by the SelectionDAGISel pass.
193   MF.getRegInfo().freezeReservedRegs(MF);
194 
195   // Fill the MachineFunction from the instructions.
196   fillMachineFunction(MF, LiveIns, Code);
197 
198   // We create the pass manager, run the passes to populate AsmBuffer.
199   llvm::MCContext &MCContext = MMI->getContext();
200   llvm::legacy::PassManager PM;
201 
202   llvm::TargetLibraryInfoImpl TLII(llvm::Triple(Module->getTargetTriple()));
203   PM.add(new llvm::TargetLibraryInfoWrapperPass(TLII));
204 
205   llvm::TargetPassConfig *TPC = TM->createPassConfig(PM);
206   PM.add(TPC);
207   PM.add(MMI.release());
208   TPC->printAndVerify("MachineFunctionGenerator::assemble");
209   // Add target-specific passes.
210   ET.addTargetSpecificPasses(PM);
211   TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses");
212   // Adding the following passes:
213   // - machineverifier: checks that the MachineFunction is well formed.
214   // - prologepilog: saves and restore callee saved registers.
215   for (const char *PassName : {"machineverifier", "prologepilog"})
216     if (addPass(PM, PassName, *TPC))
217       llvm::report_fatal_error("Unable to add a mandatory pass");
218   TPC->setInitialized();
219 
220   // AsmPrinter is responsible for generating the assembly into AsmBuffer.
221   if (TM->addAsmPrinter(PM, AsmStream, nullptr,
222                         llvm::TargetMachine::CGFT_ObjectFile, MCContext))
223     llvm::report_fatal_error("Cannot add AsmPrinter passes");
224 
225   PM.run(*Module); // Run all the passes
226 }
227 
228 llvm::object::OwningBinary<llvm::object::ObjectFile>
getObjectFromBuffer(llvm::StringRef InputData)229 getObjectFromBuffer(llvm::StringRef InputData) {
230   // Storing the generated assembly into a MemoryBuffer that owns the memory.
231   std::unique_ptr<llvm::MemoryBuffer> Buffer =
232       llvm::MemoryBuffer::getMemBufferCopy(InputData);
233   // Create the ObjectFile from the MemoryBuffer.
234   std::unique_ptr<llvm::object::ObjectFile> Obj = llvm::cantFail(
235       llvm::object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()));
236   // Returning both the MemoryBuffer and the ObjectFile.
237   return llvm::object::OwningBinary<llvm::object::ObjectFile>(
238       std::move(Obj), std::move(Buffer));
239 }
240 
241 llvm::object::OwningBinary<llvm::object::ObjectFile>
getObjectFromFile(llvm::StringRef Filename)242 getObjectFromFile(llvm::StringRef Filename) {
243   return llvm::cantFail(llvm::object::ObjectFile::createObjectFile(Filename));
244 }
245 
246 namespace {
247 
248 // Implementation of this class relies on the fact that a single object with a
249 // single function will be loaded into memory.
250 class TrackingSectionMemoryManager : public llvm::SectionMemoryManager {
251 public:
TrackingSectionMemoryManager(uintptr_t * CodeSize)252   explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
253       : CodeSize(CodeSize) {}
254 
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,llvm::StringRef SectionName)255   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
256                                unsigned SectionID,
257                                llvm::StringRef SectionName) override {
258     *CodeSize = Size;
259     return llvm::SectionMemoryManager::allocateCodeSection(
260         Size, Alignment, SectionID, SectionName);
261   }
262 
263 private:
264   uintptr_t *const CodeSize = nullptr;
265 };
266 
267 } // namespace
268 
ExecutableFunction(std::unique_ptr<llvm::LLVMTargetMachine> TM,llvm::object::OwningBinary<llvm::object::ObjectFile> && ObjectFileHolder)269 ExecutableFunction::ExecutableFunction(
270     std::unique_ptr<llvm::LLVMTargetMachine> TM,
271     llvm::object::OwningBinary<llvm::object::ObjectFile> &&ObjectFileHolder)
272     : Context(llvm::make_unique<llvm::LLVMContext>()) {
273   assert(ObjectFileHolder.getBinary() && "cannot create object file");
274   // Initializing the execution engine.
275   // We need to use the JIT EngineKind to be able to add an object file.
276   LLVMLinkInMCJIT();
277   uintptr_t CodeSize = 0;
278   std::string Error;
279   ExecEngine.reset(
280       llvm::EngineBuilder(createModule(Context, TM->createDataLayout()))
281           .setErrorStr(&Error)
282           .setMCPU(TM->getTargetCPU())
283           .setEngineKind(llvm::EngineKind::JIT)
284           .setMCJITMemoryManager(
285               llvm::make_unique<TrackingSectionMemoryManager>(&CodeSize))
286           .create(TM.release()));
287   if (!ExecEngine)
288     llvm::report_fatal_error(Error);
289   // Adding the generated object file containing the assembled function.
290   // The ExecutionEngine makes sure the object file is copied into an
291   // executable page.
292   ExecEngine->addObjectFile(std::move(ObjectFileHolder));
293   // Fetching function bytes.
294   FunctionBytes =
295       llvm::StringRef(reinterpret_cast<const char *>(
296                           ExecEngine->getFunctionAddress(FunctionID)),
297                       CodeSize);
298 }
299 
300 } // namespace exegesis
301 } // namespace llvm
302