[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / Assembler.cpp
blob167fb6373377c28a7a5714437da3eb5aaec2aa74
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/TargetPassConfig.h"
23 #include "llvm/CodeGen/TargetSubtargetInfo.h"
24 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
25 #include "llvm/IR/BasicBlock.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/LegacyPassManager.h"
28 #include "llvm/MC/MCInstrInfo.h"
29 #include "llvm/Support/Alignment.h"
30 #include "llvm/Support/MemoryBuffer.h"
31 #include "llvm/Support/raw_ostream.h"
33 #ifdef HAVE_LIBPFM
34 #include "perfmon/perf_event.h"
35 #endif // HAVE_LIBPFM
37 namespace llvm {
38 namespace exegesis {
40 static constexpr const char ModuleID[] = "ExegesisInfoTest";
41 static constexpr const char FunctionID[] = "foo";
42 static const Align kFunctionAlignment(4096);
44 // Fills the given basic block with register setup code, and returns true if
45 // all registers could be setup correctly.
46 static bool generateSnippetSetupCode(
47 const ExegesisTarget &ET, const MCSubtargetInfo *const MSI,
48 ArrayRef<RegisterValue> RegisterInitialValues, BasicBlockFiller &BBF,
49 const BenchmarkKey &Key, bool GenerateMemoryInstructions) {
50 bool IsSnippetSetupComplete = true;
51 if (GenerateMemoryInstructions) {
52 BBF.addInstructions(ET.generateMemoryInitialSetup());
53 for (const MemoryMapping &MM : Key.MemoryMappings) {
54 BBF.addInstructions(ET.generateMmap(
55 MM.Address, Key.MemoryValues.at(MM.MemoryValueName).SizeBytes,
56 ET.getAuxiliaryMemoryStartAddress() +
57 sizeof(int) * (Key.MemoryValues.at(MM.MemoryValueName).Index +
58 SubprocessMemory::AuxiliaryMemoryOffset)));
60 BBF.addInstructions(ET.setStackRegisterToAuxMem());
62 for (const RegisterValue &RV : RegisterInitialValues) {
63 // Load a constant in the register.
64 const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
65 if (SetRegisterCode.empty())
66 IsSnippetSetupComplete = false;
67 BBF.addInstructions(SetRegisterCode);
69 if (GenerateMemoryInstructions) {
70 #ifdef HAVE_LIBPFM
71 BBF.addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_RESET, true));
72 #endif // HAVE_LIBPFM
74 return IsSnippetSetupComplete;
77 // Small utility function to add named passes.
78 static bool addPass(PassManagerBase &PM, StringRef PassName,
79 TargetPassConfig &TPC) {
80 const PassRegistry *PR = PassRegistry::getPassRegistry();
81 const PassInfo *PI = PR->getPassInfo(PassName);
82 if (!PI) {
83 errs() << " run-pass " << PassName << " is not registered.\n";
84 return true;
87 if (!PI->getNormalCtor()) {
88 errs() << " cannot create pass: " << PI->getPassName() << "\n";
89 return true;
91 Pass *P = PI->getNormalCtor()();
92 std::string Banner = std::string("After ") + std::string(P->getPassName());
93 PM.add(P);
94 TPC.printAndVerify(Banner);
96 return false;
99 MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionName,
100 Module *Module,
101 MachineModuleInfo *MMI) {
102 Type *const ReturnType = Type::getInt32Ty(Module->getContext());
103 Type *const MemParamType = PointerType::get(
104 Type::getInt8Ty(Module->getContext()), 0 /*default address space*/);
105 FunctionType *FunctionType =
106 FunctionType::get(ReturnType, {MemParamType}, false);
107 Function *const F = Function::Create(
108 FunctionType, GlobalValue::InternalLinkage, FunctionName, Module);
109 BasicBlock *BB = BasicBlock::Create(Module->getContext(), "", F);
110 new UnreachableInst(Module->getContext(), BB);
111 return MMI->getOrCreateMachineFunction(*F);
114 BasicBlockFiller::BasicBlockFiller(MachineFunction &MF, MachineBasicBlock *MBB,
115 const MCInstrInfo *MCII)
116 : MF(MF), MBB(MBB), MCII(MCII) {}
118 void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
119 const unsigned Opcode = Inst.getOpcode();
120 const MCInstrDesc &MCID = MCII->get(Opcode);
121 MachineInstrBuilder Builder = BuildMI(MBB, DL, MCID);
122 for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;
123 ++OpIndex) {
124 const MCOperand &Op = Inst.getOperand(OpIndex);
125 if (Op.isReg()) {
126 const bool IsDef = OpIndex < MCID.getNumDefs();
127 unsigned Flags = 0;
128 const MCOperandInfo &OpInfo = MCID.operands().begin()[OpIndex];
129 if (IsDef && !OpInfo.isOptionalDef())
130 Flags |= RegState::Define;
131 Builder.addReg(Op.getReg(), Flags);
132 } else if (Op.isImm()) {
133 Builder.addImm(Op.getImm());
134 } else if (!Op.isValid()) {
135 llvm_unreachable("Operand is not set");
136 } else {
137 llvm_unreachable("Not yet implemented");
142 void BasicBlockFiller::addInstructions(ArrayRef<MCInst> Insts,
143 const DebugLoc &DL) {
144 for (const MCInst &Inst : Insts)
145 addInstruction(Inst, DL);
148 void BasicBlockFiller::addReturn(const ExegesisTarget &ET,
149 bool SubprocessCleanup, const DebugLoc &DL) {
150 // Insert cleanup code
151 if (SubprocessCleanup) {
152 #ifdef HAVE_LIBPFM
153 addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_DISABLE, false));
154 #endif // HAVE_LIBPFM
155 #ifdef __linux__
156 addInstructions(ET.generateExitSyscall(0));
157 #endif // __linux__
159 // Insert the return code.
160 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
161 if (TII->getReturnOpcode() < TII->getNumOpcodes()) {
162 BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
163 } else {
164 MachineIRBuilder MIB(MF);
165 MIB.setMBB(*MBB);
167 FunctionLoweringInfo FuncInfo;
168 FuncInfo.CanLowerReturn = true;
169 MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {}, FuncInfo,
174 FunctionFiller::FunctionFiller(MachineFunction &MF,
175 std::vector<unsigned> RegistersSetUp)
176 : MF(MF), MCII(MF.getTarget().getMCInstrInfo()), Entry(addBasicBlock()),
177 RegistersSetUp(std::move(RegistersSetUp)) {}
179 BasicBlockFiller FunctionFiller::addBasicBlock() {
180 MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
181 MF.push_back(MBB);
182 return BasicBlockFiller(MF, MBB, MCII);
185 ArrayRef<unsigned> FunctionFiller::getRegistersSetUp() const {
186 return RegistersSetUp;
189 static std::unique_ptr<Module>
190 createModule(const std::unique_ptr<LLVMContext> &Context, const DataLayout &DL) {
191 auto Mod = std::make_unique<Module>(ModuleID, *Context);
192 Mod->setDataLayout(DL);
193 return Mod;
196 BitVector getFunctionReservedRegs(const TargetMachine &TM) {
197 std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
198 std::unique_ptr<Module> Module = createModule(Context, TM.createDataLayout());
199 // TODO: This only works for targets implementing LLVMTargetMachine.
200 const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine &>(TM);
201 auto MMIWP = std::make_unique<MachineModuleInfoWrapperPass>(&LLVMTM);
202 MachineFunction &MF = createVoidVoidPtrMachineFunction(
203 FunctionID, Module.get(), &MMIWP->getMMI());
204 // Saving reserved registers for client.
205 return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF);
208 Error assembleToStream(const ExegesisTarget &ET,
209 std::unique_ptr<LLVMTargetMachine> TM,
210 ArrayRef<unsigned> LiveIns,
211 ArrayRef<RegisterValue> RegisterInitialValues,
212 const FillFunction &Fill, raw_pwrite_stream &AsmStream,
213 const BenchmarkKey &Key,
214 bool GenerateMemoryInstructions) {
215 auto Context = std::make_unique<LLVMContext>();
216 std::unique_ptr<Module> Module =
217 createModule(Context, TM->createDataLayout());
218 auto MMIWP = std::make_unique<MachineModuleInfoWrapperPass>(TM.get());
219 MachineFunction &MF = createVoidVoidPtrMachineFunction(
220 FunctionID, Module.get(), &MMIWP.get()->getMMI());
221 MF.ensureAlignment(kFunctionAlignment);
223 // We need to instruct the passes that we're done with SSA and virtual
224 // registers.
225 auto &Properties = MF.getProperties();
226 Properties.set(MachineFunctionProperties::Property::NoVRegs);
227 Properties.reset(MachineFunctionProperties::Property::IsSSA);
228 Properties.set(MachineFunctionProperties::Property::NoPHIs);
230 for (const unsigned Reg : LiveIns)
231 MF.getRegInfo().addLiveIn(Reg);
233 if (GenerateMemoryInstructions) {
234 for (const unsigned Reg : ET.getArgumentRegisters())
235 MF.getRegInfo().addLiveIn(Reg);
236 // Add a live in for registers that need saving so that the machine verifier
237 // doesn't fail if the register is never defined.
238 for (const unsigned Reg : ET.getRegistersNeedSaving())
239 MF.getRegInfo().addLiveIn(Reg);
242 std::vector<unsigned> RegistersSetUp;
243 for (const auto &InitValue : RegisterInitialValues) {
244 RegistersSetUp.push_back(InitValue.Register);
246 FunctionFiller Sink(MF, std::move(RegistersSetUp));
247 auto Entry = Sink.getEntry();
249 for (const unsigned Reg : LiveIns)
250 Entry.MBB->addLiveIn(Reg);
252 if (GenerateMemoryInstructions) {
253 for (const unsigned Reg : ET.getArgumentRegisters())
254 Entry.MBB->addLiveIn(Reg);
255 // Add a live in for registers that need saving so that the machine verifier
256 // doesn't fail if the register is never defined.
257 for (const unsigned Reg : ET.getRegistersNeedSaving())
258 Entry.MBB->addLiveIn(Reg);
261 const bool IsSnippetSetupComplete = generateSnippetSetupCode(
262 ET, TM->getMCSubtargetInfo(), RegisterInitialValues, Entry, Key,
263 GenerateMemoryInstructions);
265 // If the snippet setup is not complete, we disable liveliness tracking. This
266 // means that we won't know what values are in the registers.
267 // FIXME: this should probably be an assertion.
268 if (!IsSnippetSetupComplete)
269 Properties.reset(MachineFunctionProperties::Property::TracksLiveness);
271 Fill(Sink);
273 // prologue/epilogue pass needs the reserved registers to be frozen, this
274 // is usually done by the SelectionDAGISel pass.
275 MF.getRegInfo().freezeReservedRegs(MF);
277 // We create the pass manager, run the passes to populate AsmBuffer.
278 MCContext &MCContext = MMIWP->getMMI().getContext();
279 legacy::PassManager PM;
281 TargetLibraryInfoImpl TLII(Triple(Module->getTargetTriple()));
282 PM.add(new TargetLibraryInfoWrapperPass(TLII));
284 TargetPassConfig *TPC = TM->createPassConfig(PM);
285 PM.add(TPC);
286 PM.add(MMIWP.release());
287 TPC->printAndVerify("MachineFunctionGenerator::assemble");
288 // Add target-specific passes.
289 ET.addTargetSpecificPasses(PM);
290 TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses");
291 // Adding the following passes:
292 // - postrapseudos: expands pseudo return instructions used on some targets.
293 // - machineverifier: checks that the MachineFunction is well formed.
294 // - prologepilog: saves and restore callee saved registers.
295 for (const char *PassName :
296 {"postrapseudos", "machineverifier", "prologepilog"})
297 if (addPass(PM, PassName, *TPC))
298 return make_error<Failure>("Unable to add a mandatory pass");
299 TPC->setInitialized();
301 // AsmPrinter is responsible for generating the assembly into AsmBuffer.
302 if (TM->addAsmPrinter(PM, AsmStream, nullptr, CodeGenFileType::ObjectFile,
303 MCContext))
304 return make_error<Failure>("Cannot add AsmPrinter passes");
306 PM.run(*Module); // Run all the passes
307 return Error::success();
310 object::OwningBinary<object::ObjectFile>
311 getObjectFromBuffer(StringRef InputData) {
312 // Storing the generated assembly into a MemoryBuffer that owns the memory.
313 std::unique_ptr<MemoryBuffer> Buffer =
314 MemoryBuffer::getMemBufferCopy(InputData);
315 // Create the ObjectFile from the MemoryBuffer.
316 std::unique_ptr<object::ObjectFile> Obj =
317 cantFail(object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()));
318 // Returning both the MemoryBuffer and the ObjectFile.
319 return object::OwningBinary<object::ObjectFile>(std::move(Obj),
320 std::move(Buffer));
323 object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename) {
324 return cantFail(object::ObjectFile::createObjectFile(Filename));
327 namespace {
329 // Implementation of this class relies on the fact that a single object with a
330 // single function will be loaded into memory.
331 class TrackingSectionMemoryManager : public SectionMemoryManager {
332 public:
333 explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
334 : CodeSize(CodeSize) {}
336 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
337 unsigned SectionID,
338 StringRef SectionName) override {
339 *CodeSize = Size;
340 return SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID,
341 SectionName);
344 private:
345 uintptr_t *const CodeSize = nullptr;
348 } // namespace
350 ExecutableFunction::ExecutableFunction(
351 std::unique_ptr<LLVMTargetMachine> TM,
352 object::OwningBinary<object::ObjectFile> &&ObjectFileHolder)
353 : Context(std::make_unique<LLVMContext>()) {
354 assert(ObjectFileHolder.getBinary() && "cannot create object file");
355 // Initializing the execution engine.
356 // We need to use the JIT EngineKind to be able to add an object file.
357 LLVMLinkInMCJIT();
358 uintptr_t CodeSize = 0;
359 std::string Error;
360 ExecEngine.reset(
361 EngineBuilder(createModule(Context, TM->createDataLayout()))
362 .setErrorStr(&Error)
363 .setMCPU(TM->getTargetCPU())
364 .setEngineKind(EngineKind::JIT)
365 .setMCJITMemoryManager(
366 std::make_unique<TrackingSectionMemoryManager>(&CodeSize))
367 .create(TM.release()));
368 if (!ExecEngine)
369 report_fatal_error(Twine(Error));
370 // Adding the generated object file containing the assembled function.
371 // The ExecutionEngine makes sure the object file is copied into an
372 // executable page.
373 ExecEngine->addObjectFile(std::move(ObjectFileHolder));
374 // Fetching function bytes.
375 const uint64_t FunctionAddress = ExecEngine->getFunctionAddress(FunctionID);
376 assert(isAligned(kFunctionAlignment, FunctionAddress) &&
377 "function is not properly aligned");
378 FunctionBytes =
379 StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize);
382 Error getBenchmarkFunctionBytes(const StringRef InputData,
383 std::vector<uint8_t> &Bytes) {
384 const auto Holder = getObjectFromBuffer(InputData);
385 const auto *Obj = Holder.getBinary();
386 // See RuntimeDyldImpl::loadObjectImpl(Obj) for much more complete
387 // implementation.
389 // Find the only function in the object file.
390 SmallVector<object::SymbolRef, 1> Functions;
391 for (auto &Sym : Obj->symbols()) {
392 auto SymType = Sym.getType();
393 if (SymType && *SymType == object::SymbolRef::Type::ST_Function)
394 Functions.push_back(Sym);
396 if (Functions.size() != 1)
397 return make_error<Failure>("Exactly one function expected");
399 // Find the containing section - it is assumed to contain only this function.
400 auto SectionOrErr = Functions.front().getSection();
401 if (!SectionOrErr || *SectionOrErr == Obj->section_end())
402 return make_error<Failure>("Section not found");
404 auto Address = Functions.front().getAddress();
405 if (!Address || *Address != SectionOrErr.get()->getAddress())
406 return make_error<Failure>("Unexpected layout");
408 auto ContentsOrErr = SectionOrErr.get()->getContents();
409 if (!ContentsOrErr)
410 return ContentsOrErr.takeError();
411 Bytes.assign(ContentsOrErr->begin(), ContentsOrErr->end());
412 return Error::success();
415 } // namespace exegesis
416 } // namespace llvm