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