[llvm] Stop including unordered_map (NFC)
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / Assembler.cpp
blobe17d239faa47e214bca78fd56863b2df444ee571
1 //===-- Assembler.cpp -------------------------------------------*- 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 //===----------------------------------------------------------------------===//
9 #include "Assembler.h"
11 #include "SnippetRepetitor.h"
12 #include "SubprocessMemory.h"
13 #include "Target.h"
14 #include "llvm/Analysis/TargetLibraryInfo.h"
15 #include "llvm/CodeGen/FunctionLoweringInfo.h"
16 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
17 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineModuleInfo.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/TargetInstrInfo.h"
22 #include "llvm/CodeGen/TargetLowering.h"
23 #include "llvm/CodeGen/TargetPassConfig.h"
24 #include "llvm/CodeGen/TargetSubtargetInfo.h"
25 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
26 #include "llvm/IR/BasicBlock.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/LegacyPassManager.h"
29 #include "llvm/MC/MCInstrInfo.h"
30 #include "llvm/Object/SymbolSize.h"
31 #include "llvm/Support/Alignment.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/raw_ostream.h"
35 #ifdef HAVE_LIBPFM
36 #include "perfmon/perf_event.h"
37 #endif // HAVE_LIBPFM
39 namespace llvm {
40 namespace exegesis {
42 static constexpr const char ModuleID[] = "ExegesisInfoTest";
43 static constexpr const char FunctionID[] = "foo";
44 static const Align kFunctionAlignment(4096);
46 // Fills the given basic block with register setup code, and returns true if
47 // all registers could be setup correctly.
48 static bool generateSnippetSetupCode(
49 const ExegesisTarget &ET, const MCSubtargetInfo *const MSI,
50 ArrayRef<RegisterValue> RegisterInitialValues, BasicBlockFiller &BBF,
51 const BenchmarkKey &Key, bool GenerateMemoryInstructions) {
52 bool IsSnippetSetupComplete = true;
53 if (GenerateMemoryInstructions) {
54 BBF.addInstructions(ET.generateMemoryInitialSetup());
55 for (const MemoryMapping &MM : Key.MemoryMappings) {
56 BBF.addInstructions(ET.generateMmap(
57 MM.Address, Key.MemoryValues.at(MM.MemoryValueName).SizeBytes,
58 ET.getAuxiliaryMemoryStartAddress() +
59 sizeof(int) * (Key.MemoryValues.at(MM.MemoryValueName).Index +
60 SubprocessMemory::AuxiliaryMemoryOffset)));
62 BBF.addInstructions(ET.setStackRegisterToAuxMem());
64 Register StackPointerRegister = BBF.MF.getSubtarget()
65 .getTargetLowering()
66 ->getStackPointerRegisterToSaveRestore();
67 for (const RegisterValue &RV : RegisterInitialValues) {
68 if (GenerateMemoryInstructions) {
69 // If we're generating memory instructions, don't load in the value for
70 // the register with the stack pointer as it will be used later to finish
71 // the setup.
72 if (RV.Register == StackPointerRegister)
73 continue;
75 // Load a constant in the register.
76 const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
77 if (SetRegisterCode.empty())
78 IsSnippetSetupComplete = false;
79 BBF.addInstructions(SetRegisterCode);
81 if (GenerateMemoryInstructions) {
82 #ifdef HAVE_LIBPFM
83 BBF.addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_RESET, true));
84 #endif // HAVE_LIBPFM
85 for (const RegisterValue &RV : RegisterInitialValues) {
86 // Load in the stack register now as we're done using it elsewhere
87 // and need to set the value in preparation for executing the
88 // snippet.
89 if (RV.Register == StackPointerRegister)
90 continue;
91 const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
92 if (SetRegisterCode.empty())
93 IsSnippetSetupComplete = false;
94 BBF.addInstructions(SetRegisterCode);
95 break;
98 return IsSnippetSetupComplete;
101 // Small utility function to add named passes.
102 static bool addPass(PassManagerBase &PM, StringRef PassName,
103 TargetPassConfig &TPC) {
104 const PassRegistry *PR = PassRegistry::getPassRegistry();
105 const PassInfo *PI = PR->getPassInfo(PassName);
106 if (!PI) {
107 errs() << " run-pass " << PassName << " is not registered.\n";
108 return true;
111 if (!PI->getNormalCtor()) {
112 errs() << " cannot create pass: " << PI->getPassName() << "\n";
113 return true;
115 Pass *P = PI->getNormalCtor()();
116 std::string Banner = std::string("After ") + std::string(P->getPassName());
117 PM.add(P);
118 TPC.printAndVerify(Banner);
120 return false;
123 MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionName,
124 Module *Module,
125 MachineModuleInfo *MMI) {
126 Type *const ReturnType = Type::getInt32Ty(Module->getContext());
127 Type *const MemParamType = PointerType::get(
128 Type::getInt8Ty(Module->getContext()), 0 /*default address space*/);
129 FunctionType *FunctionType =
130 FunctionType::get(ReturnType, {MemParamType}, false);
131 Function *const F = Function::Create(
132 FunctionType, GlobalValue::ExternalLinkage, FunctionName, Module);
133 BasicBlock *BB = BasicBlock::Create(Module->getContext(), "", F);
134 new UnreachableInst(Module->getContext(), BB);
135 return MMI->getOrCreateMachineFunction(*F);
138 BasicBlockFiller::BasicBlockFiller(MachineFunction &MF, MachineBasicBlock *MBB,
139 const MCInstrInfo *MCII)
140 : MF(MF), MBB(MBB), MCII(MCII) {}
142 void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
143 const unsigned Opcode = Inst.getOpcode();
144 const MCInstrDesc &MCID = MCII->get(Opcode);
145 MachineInstrBuilder Builder = BuildMI(MBB, DL, MCID);
146 for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;
147 ++OpIndex) {
148 const MCOperand &Op = Inst.getOperand(OpIndex);
149 if (Op.isReg()) {
150 const bool IsDef = OpIndex < MCID.getNumDefs();
151 unsigned Flags = 0;
152 const MCOperandInfo &OpInfo = MCID.operands().begin()[OpIndex];
153 if (IsDef && !OpInfo.isOptionalDef())
154 Flags |= RegState::Define;
155 Builder.addReg(Op.getReg(), Flags);
156 } else if (Op.isImm()) {
157 Builder.addImm(Op.getImm());
158 } else if (!Op.isValid()) {
159 llvm_unreachable("Operand is not set");
160 } else {
161 llvm_unreachable("Not yet implemented");
166 void BasicBlockFiller::addInstructions(ArrayRef<MCInst> Insts,
167 const DebugLoc &DL) {
168 for (const MCInst &Inst : Insts)
169 addInstruction(Inst, DL);
172 void BasicBlockFiller::addReturn(const ExegesisTarget &ET,
173 bool SubprocessCleanup, const DebugLoc &DL) {
174 // Insert cleanup code
175 if (SubprocessCleanup) {
176 #ifdef HAVE_LIBPFM
177 addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_DISABLE, false));
178 #endif // HAVE_LIBPFM
179 #ifdef __linux__
180 addInstructions(ET.generateExitSyscall(0));
181 #endif // __linux__
183 // Insert the return code.
184 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
185 if (TII->getReturnOpcode() < TII->getNumOpcodes()) {
186 BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
187 } else {
188 MachineIRBuilder MIB(MF);
189 MIB.setMBB(*MBB);
191 FunctionLoweringInfo FuncInfo;
192 FuncInfo.CanLowerReturn = true;
193 MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {}, FuncInfo,
198 FunctionFiller::FunctionFiller(MachineFunction &MF,
199 std::vector<unsigned> RegistersSetUp)
200 : MF(MF), MCII(MF.getTarget().getMCInstrInfo()), Entry(addBasicBlock()),
201 RegistersSetUp(std::move(RegistersSetUp)) {}
203 BasicBlockFiller FunctionFiller::addBasicBlock() {
204 MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
205 MF.push_back(MBB);
206 return BasicBlockFiller(MF, MBB, MCII);
209 ArrayRef<unsigned> FunctionFiller::getRegistersSetUp() const {
210 return RegistersSetUp;
213 static std::unique_ptr<Module>
214 createModule(const std::unique_ptr<LLVMContext> &Context, const DataLayout &DL) {
215 auto Mod = std::make_unique<Module>(ModuleID, *Context);
216 Mod->setDataLayout(DL);
217 return Mod;
220 BitVector getFunctionReservedRegs(const TargetMachine &TM) {
221 std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
222 std::unique_ptr<Module> Module = createModule(Context, TM.createDataLayout());
223 // TODO: This only works for targets implementing LLVMTargetMachine.
224 const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine &>(TM);
225 auto MMIWP = std::make_unique<MachineModuleInfoWrapperPass>(&LLVMTM);
226 MachineFunction &MF = createVoidVoidPtrMachineFunction(
227 FunctionID, Module.get(), &MMIWP->getMMI());
228 // Saving reserved registers for client.
229 return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF);
232 Error assembleToStream(const ExegesisTarget &ET,
233 std::unique_ptr<LLVMTargetMachine> TM,
234 ArrayRef<unsigned> LiveIns,
235 ArrayRef<RegisterValue> RegisterInitialValues,
236 const FillFunction &Fill, raw_pwrite_stream &AsmStream,
237 const BenchmarkKey &Key,
238 bool GenerateMemoryInstructions) {
239 auto Context = std::make_unique<LLVMContext>();
240 std::unique_ptr<Module> Module =
241 createModule(Context, TM->createDataLayout());
242 auto MMIWP = std::make_unique<MachineModuleInfoWrapperPass>(TM.get());
243 MachineFunction &MF = createVoidVoidPtrMachineFunction(
244 FunctionID, Module.get(), &MMIWP.get()->getMMI());
245 MF.ensureAlignment(kFunctionAlignment);
247 // We need to instruct the passes that we're done with SSA and virtual
248 // registers.
249 auto &Properties = MF.getProperties();
250 Properties.set(MachineFunctionProperties::Property::NoVRegs);
251 Properties.reset(MachineFunctionProperties::Property::IsSSA);
252 Properties.set(MachineFunctionProperties::Property::NoPHIs);
254 for (const unsigned Reg : LiveIns)
255 MF.getRegInfo().addLiveIn(Reg);
257 if (GenerateMemoryInstructions) {
258 for (const unsigned Reg : ET.getArgumentRegisters())
259 MF.getRegInfo().addLiveIn(Reg);
260 // Add a live in for registers that need saving so that the machine verifier
261 // doesn't fail if the register is never defined.
262 for (const unsigned Reg : ET.getRegistersNeedSaving())
263 MF.getRegInfo().addLiveIn(Reg);
266 std::vector<unsigned> RegistersSetUp;
267 for (const auto &InitValue : RegisterInitialValues) {
268 RegistersSetUp.push_back(InitValue.Register);
270 FunctionFiller Sink(MF, std::move(RegistersSetUp));
271 auto Entry = Sink.getEntry();
273 for (const unsigned Reg : LiveIns)
274 Entry.MBB->addLiveIn(Reg);
276 if (GenerateMemoryInstructions) {
277 for (const unsigned Reg : ET.getArgumentRegisters())
278 Entry.MBB->addLiveIn(Reg);
279 // Add a live in for registers that need saving so that the machine verifier
280 // doesn't fail if the register is never defined.
281 for (const unsigned Reg : ET.getRegistersNeedSaving())
282 Entry.MBB->addLiveIn(Reg);
285 const bool IsSnippetSetupComplete = generateSnippetSetupCode(
286 ET, TM->getMCSubtargetInfo(), RegisterInitialValues, Entry, Key,
287 GenerateMemoryInstructions);
289 // If the snippet setup is not complete, we disable liveliness tracking. This
290 // means that we won't know what values are in the registers.
291 // FIXME: this should probably be an assertion.
292 if (!IsSnippetSetupComplete)
293 Properties.reset(MachineFunctionProperties::Property::TracksLiveness);
295 Fill(Sink);
297 // prologue/epilogue pass needs the reserved registers to be frozen, this
298 // is usually done by the SelectionDAGISel pass.
299 MF.getRegInfo().freezeReservedRegs(MF);
301 // We create the pass manager, run the passes to populate AsmBuffer.
302 MCContext &MCContext = MMIWP->getMMI().getContext();
303 legacy::PassManager PM;
305 TargetLibraryInfoImpl TLII(Triple(Module->getTargetTriple()));
306 PM.add(new TargetLibraryInfoWrapperPass(TLII));
308 TargetPassConfig *TPC = TM->createPassConfig(PM);
309 PM.add(TPC);
310 PM.add(MMIWP.release());
311 TPC->printAndVerify("MachineFunctionGenerator::assemble");
312 // Add target-specific passes.
313 ET.addTargetSpecificPasses(PM);
314 TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses");
315 // Adding the following passes:
316 // - postrapseudos: expands pseudo return instructions used on some targets.
317 // - machineverifier: checks that the MachineFunction is well formed.
318 // - prologepilog: saves and restore callee saved registers.
319 for (const char *PassName :
320 {"postrapseudos", "machineverifier", "prologepilog"})
321 if (addPass(PM, PassName, *TPC))
322 return make_error<Failure>("Unable to add a mandatory pass");
323 TPC->setInitialized();
325 // AsmPrinter is responsible for generating the assembly into AsmBuffer.
326 if (TM->addAsmPrinter(PM, AsmStream, nullptr, CodeGenFileType::ObjectFile,
327 MCContext))
328 return make_error<Failure>("Cannot add AsmPrinter passes");
330 PM.run(*Module); // Run all the passes
331 return Error::success();
334 object::OwningBinary<object::ObjectFile>
335 getObjectFromBuffer(StringRef InputData) {
336 // Storing the generated assembly into a MemoryBuffer that owns the memory.
337 std::unique_ptr<MemoryBuffer> Buffer =
338 MemoryBuffer::getMemBufferCopy(InputData);
339 // Create the ObjectFile from the MemoryBuffer.
340 std::unique_ptr<object::ObjectFile> Obj =
341 cantFail(object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()));
342 // Returning both the MemoryBuffer and the ObjectFile.
343 return object::OwningBinary<object::ObjectFile>(std::move(Obj),
344 std::move(Buffer));
347 object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename) {
348 return cantFail(object::ObjectFile::createObjectFile(Filename));
351 Expected<ExecutableFunction> ExecutableFunction::create(
352 std::unique_ptr<LLVMTargetMachine> TM,
353 object::OwningBinary<object::ObjectFile> &&ObjectFileHolder) {
354 assert(ObjectFileHolder.getBinary() && "cannot create object file");
355 std::unique_ptr<LLVMContext> Ctx = std::make_unique<LLVMContext>();
357 auto SymbolSizes = object::computeSymbolSizes(*ObjectFileHolder.getBinary());
358 // Get the size of the function that we want to call into (with the name of
359 // FunctionID). This should always be the third symbol returned by
360 // calculateSymbolSizes.
361 assert(SymbolSizes.size() == 3);
362 assert(cantFail(std::get<0>(SymbolSizes[2]).getName()) == FunctionID);
363 uintptr_t CodeSize = std::get<1>(SymbolSizes[2]);
365 auto EJITOrErr = orc::LLJITBuilder().create();
366 if (!EJITOrErr)
367 return EJITOrErr.takeError();
369 auto EJIT = std::move(*EJITOrErr);
371 if (auto ObjErr =
372 EJIT->addObjectFile(std::get<1>(ObjectFileHolder.takeBinary())))
373 return std::move(ObjErr);
375 auto FunctionAddressOrErr = EJIT->lookup(FunctionID);
376 if (!FunctionAddressOrErr)
377 return FunctionAddressOrErr.takeError();
379 const uint64_t FunctionAddress = FunctionAddressOrErr->getValue();
381 assert(isAligned(kFunctionAlignment, FunctionAddress) &&
382 "function is not properly aligned");
384 StringRef FBytes =
385 StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize);
386 return ExecutableFunction(std::move(Ctx), std::move(EJIT), FBytes);
389 ExecutableFunction::ExecutableFunction(std::unique_ptr<LLVMContext> Ctx,
390 std::unique_ptr<orc::LLJIT> EJIT,
391 StringRef FB)
392 : FunctionBytes(FB), Context(std::move(Ctx)), ExecJIT(std::move(EJIT)) {}
394 Error getBenchmarkFunctionBytes(const StringRef InputData,
395 std::vector<uint8_t> &Bytes) {
396 const auto Holder = getObjectFromBuffer(InputData);
397 const auto *Obj = Holder.getBinary();
398 // See RuntimeDyldImpl::loadObjectImpl(Obj) for much more complete
399 // implementation.
401 // Find the only function in the object file.
402 SmallVector<object::SymbolRef, 1> Functions;
403 for (auto &Sym : Obj->symbols()) {
404 auto SymType = Sym.getType();
405 if (SymType && *SymType == object::SymbolRef::Type::ST_Function)
406 Functions.push_back(Sym);
408 if (Functions.size() != 1)
409 return make_error<Failure>("Exactly one function expected");
411 // Find the containing section - it is assumed to contain only this function.
412 auto SectionOrErr = Functions.front().getSection();
413 if (!SectionOrErr || *SectionOrErr == Obj->section_end())
414 return make_error<Failure>("Section not found");
416 auto Address = Functions.front().getAddress();
417 if (!Address || *Address != SectionOrErr.get()->getAddress())
418 return make_error<Failure>("Unexpected layout");
420 auto ContentsOrErr = SectionOrErr.get()->getContents();
421 if (!ContentsOrErr)
422 return ContentsOrErr.takeError();
423 Bytes.assign(ContentsOrErr->begin(), ContentsOrErr->end());
424 return Error::success();
427 } // namespace exegesis
428 } // namespace llvm