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