109467b48Spatrick //===-- Assembler.cpp -------------------------------------------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "Assembler.h"
1009467b48Spatrick 
1109467b48Spatrick #include "SnippetRepetitor.h"
1209467b48Spatrick #include "Target.h"
1309467b48Spatrick #include "llvm/Analysis/TargetLibraryInfo.h"
1473471bf0Spatrick #include "llvm/CodeGen/FunctionLoweringInfo.h"
1509467b48Spatrick #include "llvm/CodeGen/GlobalISel/CallLowering.h"
1609467b48Spatrick #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1709467b48Spatrick #include "llvm/CodeGen/MachineInstrBuilder.h"
1809467b48Spatrick #include "llvm/CodeGen/MachineModuleInfo.h"
1909467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
2009467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
2109467b48Spatrick #include "llvm/CodeGen/TargetPassConfig.h"
2209467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
2309467b48Spatrick #include "llvm/ExecutionEngine/SectionMemoryManager.h"
2409467b48Spatrick #include "llvm/IR/LegacyPassManager.h"
2509467b48Spatrick #include "llvm/MC/MCInstrInfo.h"
2609467b48Spatrick #include "llvm/Support/Alignment.h"
2709467b48Spatrick #include "llvm/Support/MemoryBuffer.h"
2809467b48Spatrick 
2909467b48Spatrick namespace llvm {
3009467b48Spatrick namespace exegesis {
3109467b48Spatrick 
3209467b48Spatrick static constexpr const char ModuleID[] = "ExegesisInfoTest";
3309467b48Spatrick static constexpr const char FunctionID[] = "foo";
3409467b48Spatrick static const Align kFunctionAlignment(4096);
3509467b48Spatrick 
3609467b48Spatrick // Fills the given basic block with register setup code, and returns true if
3709467b48Spatrick // all registers could be setup correctly.
generateSnippetSetupCode(const ExegesisTarget & ET,const MCSubtargetInfo * const MSI,ArrayRef<RegisterValue> RegisterInitialValues,BasicBlockFiller & BBF)3809467b48Spatrick static bool generateSnippetSetupCode(
3909467b48Spatrick     const ExegesisTarget &ET, const MCSubtargetInfo *const MSI,
4009467b48Spatrick     ArrayRef<RegisterValue> RegisterInitialValues, BasicBlockFiller &BBF) {
4109467b48Spatrick   bool IsSnippetSetupComplete = true;
4209467b48Spatrick   for (const RegisterValue &RV : RegisterInitialValues) {
4309467b48Spatrick     // Load a constant in the register.
4409467b48Spatrick     const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
4509467b48Spatrick     if (SetRegisterCode.empty())
4609467b48Spatrick       IsSnippetSetupComplete = false;
4709467b48Spatrick     BBF.addInstructions(SetRegisterCode);
4809467b48Spatrick   }
4909467b48Spatrick   return IsSnippetSetupComplete;
5009467b48Spatrick }
5109467b48Spatrick 
5209467b48Spatrick // Small utility function to add named passes.
addPass(PassManagerBase & PM,StringRef PassName,TargetPassConfig & TPC)5309467b48Spatrick static bool addPass(PassManagerBase &PM, StringRef PassName,
5409467b48Spatrick                     TargetPassConfig &TPC) {
5509467b48Spatrick   const PassRegistry *PR = PassRegistry::getPassRegistry();
5609467b48Spatrick   const PassInfo *PI = PR->getPassInfo(PassName);
5709467b48Spatrick   if (!PI) {
5809467b48Spatrick     errs() << " run-pass " << PassName << " is not registered.\n";
5909467b48Spatrick     return true;
6009467b48Spatrick   }
6109467b48Spatrick 
6209467b48Spatrick   if (!PI->getNormalCtor()) {
6309467b48Spatrick     errs() << " cannot create pass: " << PI->getPassName() << "\n";
6409467b48Spatrick     return true;
6509467b48Spatrick   }
6609467b48Spatrick   Pass *P = PI->getNormalCtor()();
6709467b48Spatrick   std::string Banner = std::string("After ") + std::string(P->getPassName());
6809467b48Spatrick   PM.add(P);
6909467b48Spatrick   TPC.printAndVerify(Banner);
7009467b48Spatrick 
7109467b48Spatrick   return false;
7209467b48Spatrick }
7309467b48Spatrick 
createVoidVoidPtrMachineFunction(StringRef FunctionName,Module * Module,MachineModuleInfo * MMI)7409467b48Spatrick MachineFunction &createVoidVoidPtrMachineFunction(StringRef FunctionName,
7509467b48Spatrick                                                   Module *Module,
7609467b48Spatrick                                                   MachineModuleInfo *MMI) {
7709467b48Spatrick   Type *const ReturnType = Type::getInt32Ty(Module->getContext());
7809467b48Spatrick   Type *const MemParamType = PointerType::get(
7909467b48Spatrick       Type::getInt8Ty(Module->getContext()), 0 /*default address space*/);
8009467b48Spatrick   FunctionType *FunctionType =
8109467b48Spatrick       FunctionType::get(ReturnType, {MemParamType}, false);
8209467b48Spatrick   Function *const F = Function::Create(
8309467b48Spatrick       FunctionType, GlobalValue::InternalLinkage, FunctionName, Module);
8409467b48Spatrick   // Making sure we can create a MachineFunction out of this Function even if it
8509467b48Spatrick   // contains no IR.
8609467b48Spatrick   F->setIsMaterializable(true);
8709467b48Spatrick   return MMI->getOrCreateMachineFunction(*F);
8809467b48Spatrick }
8909467b48Spatrick 
BasicBlockFiller(MachineFunction & MF,MachineBasicBlock * MBB,const MCInstrInfo * MCII)9009467b48Spatrick BasicBlockFiller::BasicBlockFiller(MachineFunction &MF, MachineBasicBlock *MBB,
9109467b48Spatrick                                    const MCInstrInfo *MCII)
9209467b48Spatrick     : MF(MF), MBB(MBB), MCII(MCII) {}
9309467b48Spatrick 
addInstruction(const MCInst & Inst,const DebugLoc & DL)9409467b48Spatrick void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
9509467b48Spatrick   const unsigned Opcode = Inst.getOpcode();
9609467b48Spatrick   const MCInstrDesc &MCID = MCII->get(Opcode);
9709467b48Spatrick   MachineInstrBuilder Builder = BuildMI(MBB, DL, MCID);
9809467b48Spatrick   for (unsigned OpIndex = 0, E = Inst.getNumOperands(); OpIndex < E;
9909467b48Spatrick        ++OpIndex) {
10009467b48Spatrick     const MCOperand &Op = Inst.getOperand(OpIndex);
10109467b48Spatrick     if (Op.isReg()) {
10209467b48Spatrick       const bool IsDef = OpIndex < MCID.getNumDefs();
10309467b48Spatrick       unsigned Flags = 0;
10409467b48Spatrick       const MCOperandInfo &OpInfo = MCID.operands().begin()[OpIndex];
10509467b48Spatrick       if (IsDef && !OpInfo.isOptionalDef())
10609467b48Spatrick         Flags |= RegState::Define;
10709467b48Spatrick       Builder.addReg(Op.getReg(), Flags);
10809467b48Spatrick     } else if (Op.isImm()) {
10909467b48Spatrick       Builder.addImm(Op.getImm());
11009467b48Spatrick     } else if (!Op.isValid()) {
11109467b48Spatrick       llvm_unreachable("Operand is not set");
11209467b48Spatrick     } else {
11309467b48Spatrick       llvm_unreachable("Not yet implemented");
11409467b48Spatrick     }
11509467b48Spatrick   }
11609467b48Spatrick }
11709467b48Spatrick 
addInstructions(ArrayRef<MCInst> Insts,const DebugLoc & DL)11809467b48Spatrick void BasicBlockFiller::addInstructions(ArrayRef<MCInst> Insts,
11909467b48Spatrick                                        const DebugLoc &DL) {
12009467b48Spatrick   for (const MCInst &Inst : Insts)
12109467b48Spatrick     addInstruction(Inst, DL);
12209467b48Spatrick }
12309467b48Spatrick 
addReturn(const DebugLoc & DL)12409467b48Spatrick void BasicBlockFiller::addReturn(const DebugLoc &DL) {
12509467b48Spatrick   // Insert the return code.
12609467b48Spatrick   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
12709467b48Spatrick   if (TII->getReturnOpcode() < TII->getNumOpcodes()) {
12809467b48Spatrick     BuildMI(MBB, DL, TII->get(TII->getReturnOpcode()));
12909467b48Spatrick   } else {
13009467b48Spatrick     MachineIRBuilder MIB(MF);
13109467b48Spatrick     MIB.setMBB(*MBB);
13273471bf0Spatrick 
13373471bf0Spatrick     FunctionLoweringInfo FuncInfo;
13473471bf0Spatrick     FuncInfo.CanLowerReturn = true;
13573471bf0Spatrick     MF.getSubtarget().getCallLowering()->lowerReturn(MIB, nullptr, {},
13673471bf0Spatrick                                                      FuncInfo);
13709467b48Spatrick   }
13809467b48Spatrick }
13909467b48Spatrick 
FunctionFiller(MachineFunction & MF,std::vector<unsigned> RegistersSetUp)14009467b48Spatrick FunctionFiller::FunctionFiller(MachineFunction &MF,
14109467b48Spatrick                                std::vector<unsigned> RegistersSetUp)
14209467b48Spatrick     : MF(MF), MCII(MF.getTarget().getMCInstrInfo()), Entry(addBasicBlock()),
14309467b48Spatrick       RegistersSetUp(std::move(RegistersSetUp)) {}
14409467b48Spatrick 
addBasicBlock()14509467b48Spatrick BasicBlockFiller FunctionFiller::addBasicBlock() {
14609467b48Spatrick   MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
14709467b48Spatrick   MF.push_back(MBB);
14809467b48Spatrick   return BasicBlockFiller(MF, MBB, MCII);
14909467b48Spatrick }
15009467b48Spatrick 
getRegistersSetUp() const15109467b48Spatrick ArrayRef<unsigned> FunctionFiller::getRegistersSetUp() const {
15209467b48Spatrick   return RegistersSetUp;
15309467b48Spatrick }
15409467b48Spatrick 
15509467b48Spatrick static std::unique_ptr<Module>
createModule(const std::unique_ptr<LLVMContext> & Context,const DataLayout & DL)156*d415bd75Srobert createModule(const std::unique_ptr<LLVMContext> &Context, const DataLayout &DL) {
15709467b48Spatrick   auto Mod = std::make_unique<Module>(ModuleID, *Context);
15809467b48Spatrick   Mod->setDataLayout(DL);
15909467b48Spatrick   return Mod;
16009467b48Spatrick }
16109467b48Spatrick 
getFunctionReservedRegs(const TargetMachine & TM)16209467b48Spatrick BitVector getFunctionReservedRegs(const TargetMachine &TM) {
16309467b48Spatrick   std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
16409467b48Spatrick   std::unique_ptr<Module> Module = createModule(Context, TM.createDataLayout());
16509467b48Spatrick   // TODO: This only works for targets implementing LLVMTargetMachine.
16609467b48Spatrick   const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine &>(TM);
16709467b48Spatrick   std::unique_ptr<MachineModuleInfoWrapperPass> MMIWP =
16809467b48Spatrick       std::make_unique<MachineModuleInfoWrapperPass>(&LLVMTM);
16909467b48Spatrick   MachineFunction &MF = createVoidVoidPtrMachineFunction(
17009467b48Spatrick       FunctionID, Module.get(), &MMIWP.get()->getMMI());
17109467b48Spatrick   // Saving reserved registers for client.
17209467b48Spatrick   return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF);
17309467b48Spatrick }
17409467b48Spatrick 
assembleToStream(const ExegesisTarget & ET,std::unique_ptr<LLVMTargetMachine> TM,ArrayRef<unsigned> LiveIns,ArrayRef<RegisterValue> RegisterInitialValues,const FillFunction & Fill,raw_pwrite_stream & AsmStream)175097a140dSpatrick Error assembleToStream(const ExegesisTarget &ET,
17609467b48Spatrick                        std::unique_ptr<LLVMTargetMachine> TM,
17709467b48Spatrick                        ArrayRef<unsigned> LiveIns,
17809467b48Spatrick                        ArrayRef<RegisterValue> RegisterInitialValues,
17909467b48Spatrick                        const FillFunction &Fill, raw_pwrite_stream &AsmStream) {
18009467b48Spatrick   auto Context = std::make_unique<LLVMContext>();
18109467b48Spatrick   std::unique_ptr<Module> Module =
18209467b48Spatrick       createModule(Context, TM->createDataLayout());
18309467b48Spatrick   auto MMIWP = std::make_unique<MachineModuleInfoWrapperPass>(TM.get());
18409467b48Spatrick   MachineFunction &MF = createVoidVoidPtrMachineFunction(
18509467b48Spatrick       FunctionID, Module.get(), &MMIWP.get()->getMMI());
18609467b48Spatrick   MF.ensureAlignment(kFunctionAlignment);
18709467b48Spatrick 
18809467b48Spatrick   // We need to instruct the passes that we're done with SSA and virtual
18909467b48Spatrick   // registers.
19009467b48Spatrick   auto &Properties = MF.getProperties();
19109467b48Spatrick   Properties.set(MachineFunctionProperties::Property::NoVRegs);
19209467b48Spatrick   Properties.reset(MachineFunctionProperties::Property::IsSSA);
19309467b48Spatrick   Properties.set(MachineFunctionProperties::Property::NoPHIs);
19409467b48Spatrick 
19509467b48Spatrick   for (const unsigned Reg : LiveIns)
19609467b48Spatrick     MF.getRegInfo().addLiveIn(Reg);
19709467b48Spatrick 
19809467b48Spatrick   std::vector<unsigned> RegistersSetUp;
19909467b48Spatrick   for (const auto &InitValue : RegisterInitialValues) {
20009467b48Spatrick     RegistersSetUp.push_back(InitValue.Register);
20109467b48Spatrick   }
20209467b48Spatrick   FunctionFiller Sink(MF, std::move(RegistersSetUp));
20309467b48Spatrick   auto Entry = Sink.getEntry();
20409467b48Spatrick   for (const unsigned Reg : LiveIns)
20509467b48Spatrick     Entry.MBB->addLiveIn(Reg);
20609467b48Spatrick 
20709467b48Spatrick   const bool IsSnippetSetupComplete = generateSnippetSetupCode(
20809467b48Spatrick       ET, TM->getMCSubtargetInfo(), RegisterInitialValues, Entry);
20909467b48Spatrick 
21009467b48Spatrick   // If the snippet setup is not complete, we disable liveliness tracking. This
21109467b48Spatrick   // means that we won't know what values are in the registers.
212*d415bd75Srobert   // FIXME: this should probably be an assertion.
21309467b48Spatrick   if (!IsSnippetSetupComplete)
21409467b48Spatrick     Properties.reset(MachineFunctionProperties::Property::TracksLiveness);
21509467b48Spatrick 
21609467b48Spatrick   Fill(Sink);
21709467b48Spatrick 
21809467b48Spatrick   // prologue/epilogue pass needs the reserved registers to be frozen, this
21909467b48Spatrick   // is usually done by the SelectionDAGISel pass.
22009467b48Spatrick   MF.getRegInfo().freezeReservedRegs(MF);
22109467b48Spatrick 
22209467b48Spatrick   // We create the pass manager, run the passes to populate AsmBuffer.
22309467b48Spatrick   MCContext &MCContext = MMIWP->getMMI().getContext();
22409467b48Spatrick   legacy::PassManager PM;
22509467b48Spatrick 
22609467b48Spatrick   TargetLibraryInfoImpl TLII(Triple(Module->getTargetTriple()));
22709467b48Spatrick   PM.add(new TargetLibraryInfoWrapperPass(TLII));
22809467b48Spatrick 
22909467b48Spatrick   TargetPassConfig *TPC = TM->createPassConfig(PM);
23009467b48Spatrick   PM.add(TPC);
23109467b48Spatrick   PM.add(MMIWP.release());
23209467b48Spatrick   TPC->printAndVerify("MachineFunctionGenerator::assemble");
23309467b48Spatrick   // Add target-specific passes.
23409467b48Spatrick   ET.addTargetSpecificPasses(PM);
23509467b48Spatrick   TPC->printAndVerify("After ExegesisTarget::addTargetSpecificPasses");
23609467b48Spatrick   // Adding the following passes:
23709467b48Spatrick   // - postrapseudos: expands pseudo return instructions used on some targets.
23809467b48Spatrick   // - machineverifier: checks that the MachineFunction is well formed.
23909467b48Spatrick   // - prologepilog: saves and restore callee saved registers.
24009467b48Spatrick   for (const char *PassName :
24109467b48Spatrick        {"postrapseudos", "machineverifier", "prologepilog"})
24209467b48Spatrick     if (addPass(PM, PassName, *TPC))
243097a140dSpatrick       return make_error<Failure>("Unable to add a mandatory pass");
24409467b48Spatrick   TPC->setInitialized();
24509467b48Spatrick 
24609467b48Spatrick   // AsmPrinter is responsible for generating the assembly into AsmBuffer.
247097a140dSpatrick   if (TM->addAsmPrinter(PM, AsmStream, nullptr, CGFT_ObjectFile, MCContext))
248097a140dSpatrick     return make_error<Failure>("Cannot add AsmPrinter passes");
24909467b48Spatrick 
25009467b48Spatrick   PM.run(*Module); // Run all the passes
251097a140dSpatrick   return Error::success();
25209467b48Spatrick }
25309467b48Spatrick 
25409467b48Spatrick object::OwningBinary<object::ObjectFile>
getObjectFromBuffer(StringRef InputData)25509467b48Spatrick getObjectFromBuffer(StringRef InputData) {
25609467b48Spatrick   // Storing the generated assembly into a MemoryBuffer that owns the memory.
25709467b48Spatrick   std::unique_ptr<MemoryBuffer> Buffer =
25809467b48Spatrick       MemoryBuffer::getMemBufferCopy(InputData);
25909467b48Spatrick   // Create the ObjectFile from the MemoryBuffer.
26009467b48Spatrick   std::unique_ptr<object::ObjectFile> Obj =
26109467b48Spatrick       cantFail(object::ObjectFile::createObjectFile(Buffer->getMemBufferRef()));
26209467b48Spatrick   // Returning both the MemoryBuffer and the ObjectFile.
26309467b48Spatrick   return object::OwningBinary<object::ObjectFile>(std::move(Obj),
26409467b48Spatrick                                                   std::move(Buffer));
26509467b48Spatrick }
26609467b48Spatrick 
getObjectFromFile(StringRef Filename)26709467b48Spatrick object::OwningBinary<object::ObjectFile> getObjectFromFile(StringRef Filename) {
26809467b48Spatrick   return cantFail(object::ObjectFile::createObjectFile(Filename));
26909467b48Spatrick }
27009467b48Spatrick 
27109467b48Spatrick namespace {
27209467b48Spatrick 
27309467b48Spatrick // Implementation of this class relies on the fact that a single object with a
27409467b48Spatrick // single function will be loaded into memory.
27509467b48Spatrick class TrackingSectionMemoryManager : public SectionMemoryManager {
27609467b48Spatrick public:
TrackingSectionMemoryManager(uintptr_t * CodeSize)27709467b48Spatrick   explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
27809467b48Spatrick       : CodeSize(CodeSize) {}
27909467b48Spatrick 
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)28009467b48Spatrick   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
28109467b48Spatrick                                unsigned SectionID,
28209467b48Spatrick                                StringRef SectionName) override {
28309467b48Spatrick     *CodeSize = Size;
28409467b48Spatrick     return SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID,
28509467b48Spatrick                                                      SectionName);
28609467b48Spatrick   }
28709467b48Spatrick 
28809467b48Spatrick private:
28909467b48Spatrick   uintptr_t *const CodeSize = nullptr;
29009467b48Spatrick };
29109467b48Spatrick 
29209467b48Spatrick } // namespace
29309467b48Spatrick 
ExecutableFunction(std::unique_ptr<LLVMTargetMachine> TM,object::OwningBinary<object::ObjectFile> && ObjectFileHolder)29409467b48Spatrick ExecutableFunction::ExecutableFunction(
29509467b48Spatrick     std::unique_ptr<LLVMTargetMachine> TM,
29609467b48Spatrick     object::OwningBinary<object::ObjectFile> &&ObjectFileHolder)
29709467b48Spatrick     : Context(std::make_unique<LLVMContext>()) {
29809467b48Spatrick   assert(ObjectFileHolder.getBinary() && "cannot create object file");
29909467b48Spatrick   // Initializing the execution engine.
30009467b48Spatrick   // We need to use the JIT EngineKind to be able to add an object file.
30109467b48Spatrick   LLVMLinkInMCJIT();
30209467b48Spatrick   uintptr_t CodeSize = 0;
30309467b48Spatrick   std::string Error;
30409467b48Spatrick   ExecEngine.reset(
30509467b48Spatrick       EngineBuilder(createModule(Context, TM->createDataLayout()))
30609467b48Spatrick           .setErrorStr(&Error)
30709467b48Spatrick           .setMCPU(TM->getTargetCPU())
30809467b48Spatrick           .setEngineKind(EngineKind::JIT)
30909467b48Spatrick           .setMCJITMemoryManager(
31009467b48Spatrick               std::make_unique<TrackingSectionMemoryManager>(&CodeSize))
31109467b48Spatrick           .create(TM.release()));
31209467b48Spatrick   if (!ExecEngine)
313*d415bd75Srobert     report_fatal_error(Twine(Error));
31409467b48Spatrick   // Adding the generated object file containing the assembled function.
31509467b48Spatrick   // The ExecutionEngine makes sure the object file is copied into an
31609467b48Spatrick   // executable page.
31709467b48Spatrick   ExecEngine->addObjectFile(std::move(ObjectFileHolder));
31809467b48Spatrick   // Fetching function bytes.
31909467b48Spatrick   const uint64_t FunctionAddress = ExecEngine->getFunctionAddress(FunctionID);
32009467b48Spatrick   assert(isAligned(kFunctionAlignment, FunctionAddress) &&
32109467b48Spatrick          "function is not properly aligned");
32209467b48Spatrick   FunctionBytes =
32309467b48Spatrick       StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize);
32409467b48Spatrick }
32509467b48Spatrick 
32609467b48Spatrick } // namespace exegesis
32709467b48Spatrick } // namespace llvm
328