1 //===-- Assembler.cpp -------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "Assembler.h"
13 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
14 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
15 #include "llvm/CodeGen/MachineInstrBuilder.h"
16 #include "llvm/CodeGen/MachineModuleInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/TargetInstrInfo.h"
19 #include "llvm/CodeGen/TargetPassConfig.h"
20 #include "llvm/CodeGen/TargetSubtargetInfo.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
22 #include "llvm/IR/LegacyPassManager.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #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 std::vector
<llvm::MCInst
> Result
;
37 for (const RegisterValue
&RV
: RegisterInitialValues
) {
38 // Load a constant in the register.
39 const auto SetRegisterCode
= ET
.setRegTo(*MSI
, RV
.Register
, RV
.Value
);
40 if (SetRegisterCode
.empty())
41 IsSnippetSetupComplete
= false;
42 Result
.insert(Result
.end(), SetRegisterCode
.begin(), SetRegisterCode
.end());
47 // Small utility function to add named passes.
48 static bool addPass(llvm::PassManagerBase
&PM
, llvm::StringRef PassName
,
49 llvm::TargetPassConfig
&TPC
) {
50 const llvm::PassRegistry
*PR
= llvm::PassRegistry::getPassRegistry();
51 const llvm::PassInfo
*PI
= PR
->getPassInfo(PassName
);
53 llvm::errs() << " run-pass " << PassName
<< " is not registered.\n";
57 if (!PI
->getNormalCtor()) {
58 llvm::errs() << " cannot create pass: " << PI
->getPassName() << "\n";
61 llvm::Pass
*P
= PI
->getNormalCtor()();
62 std::string Banner
= std::string("After ") + std::string(P
->getPassName());
64 TPC
.printAndVerify(Banner
);
69 // Creates a void(int8*) MachineFunction.
70 static llvm::MachineFunction
&
71 createVoidVoidPtrMachineFunction(llvm::StringRef FunctionID
,
73 llvm::MachineModuleInfo
*MMI
) {
74 llvm::Type
*const ReturnType
= llvm::Type::getInt32Ty(Module
->getContext());
75 llvm::Type
*const MemParamType
= llvm::PointerType::get(
76 llvm::Type::getInt8Ty(Module
->getContext()), 0 /*default address space*/);
77 llvm::FunctionType
*FunctionType
=
78 llvm::FunctionType::get(ReturnType
, {MemParamType
}, false);
79 llvm::Function
*const F
= llvm::Function::Create(
80 FunctionType
, llvm::GlobalValue::InternalLinkage
, FunctionID
, Module
);
81 // Making sure we can create a MachineFunction out of this Function even if it
83 F
->setIsMaterializable(true);
84 return MMI
->getOrCreateMachineFunction(*F
);
87 static void fillMachineFunction(llvm::MachineFunction
&MF
,
88 llvm::ArrayRef
<unsigned> LiveIns
,
89 llvm::ArrayRef
<llvm::MCInst
> Instructions
) {
90 llvm::MachineBasicBlock
*MBB
= MF
.CreateMachineBasicBlock();
92 for (const unsigned Reg
: LiveIns
)
94 const llvm::MCInstrInfo
*MCII
= MF
.getTarget().getMCInstrInfo();
96 for (const llvm::MCInst
&Inst
: Instructions
) {
97 const unsigned Opcode
= Inst
.getOpcode();
98 const llvm::MCInstrDesc
&MCID
= MCII
->get(Opcode
);
99 llvm::MachineInstrBuilder Builder
= llvm::BuildMI(MBB
, DL
, MCID
);
100 for (unsigned OpIndex
= 0, E
= Inst
.getNumOperands(); OpIndex
< E
;
102 const llvm::MCOperand
&Op
= Inst
.getOperand(OpIndex
);
104 const bool IsDef
= OpIndex
< MCID
.getNumDefs();
106 const llvm::MCOperandInfo
&OpInfo
= MCID
.operands().begin()[OpIndex
];
107 if (IsDef
&& !OpInfo
.isOptionalDef())
108 Flags
|= llvm::RegState::Define
;
109 Builder
.addReg(Op
.getReg(), Flags
);
110 } else if (Op
.isImm()) {
111 Builder
.addImm(Op
.getImm());
113 llvm_unreachable("Not yet implemented");
117 // Insert the return code.
118 const llvm::TargetInstrInfo
*TII
= MF
.getSubtarget().getInstrInfo();
119 if (TII
->getReturnOpcode() < TII
->getNumOpcodes()) {
120 llvm::BuildMI(MBB
, DL
, TII
->get(TII
->getReturnOpcode()));
122 llvm::MachineIRBuilder
MIB(MF
);
124 MF
.getSubtarget().getCallLowering()->lowerReturn(MIB
, nullptr, 0);
128 static std::unique_ptr
<llvm::Module
>
129 createModule(const std::unique_ptr
<llvm::LLVMContext
> &Context
,
130 const llvm::DataLayout DL
) {
131 auto Module
= llvm::make_unique
<llvm::Module
>(ModuleID
, *Context
);
132 Module
->setDataLayout(DL
);
136 llvm::BitVector
getFunctionReservedRegs(const llvm::TargetMachine
&TM
) {
137 std::unique_ptr
<llvm::LLVMContext
> Context
=
138 llvm::make_unique
<llvm::LLVMContext
>();
139 std::unique_ptr
<llvm::Module
> Module
=
140 createModule(Context
, TM
.createDataLayout());
141 std::unique_ptr
<llvm::MachineModuleInfo
> MMI
=
142 llvm::make_unique
<llvm::MachineModuleInfo
>(&TM
);
143 llvm::MachineFunction
&MF
=
144 createVoidVoidPtrMachineFunction(FunctionID
, Module
.get(), MMI
.get());
145 // Saving reserved registers for client.
146 return MF
.getSubtarget().getRegisterInfo()->getReservedRegs(MF
);
149 void assembleToStream(const ExegesisTarget
&ET
,
150 std::unique_ptr
<llvm::LLVMTargetMachine
> TM
,
151 llvm::ArrayRef
<unsigned> LiveIns
,
152 llvm::ArrayRef
<RegisterValue
> RegisterInitialValues
,
153 llvm::ArrayRef
<llvm::MCInst
> Instructions
,
154 llvm::raw_pwrite_stream
&AsmStream
) {
155 std::unique_ptr
<llvm::LLVMContext
> Context
=
156 llvm::make_unique
<llvm::LLVMContext
>();
157 std::unique_ptr
<llvm::Module
> Module
=
158 createModule(Context
, TM
->createDataLayout());
159 std::unique_ptr
<llvm::MachineModuleInfo
> MMI
=
160 llvm::make_unique
<llvm::MachineModuleInfo
>(TM
.get());
161 llvm::MachineFunction
&MF
=
162 createVoidVoidPtrMachineFunction(FunctionID
, Module
.get(), MMI
.get());
164 // We need to instruct the passes that we're done with SSA and virtual
166 auto &Properties
= MF
.getProperties();
167 Properties
.set(llvm::MachineFunctionProperties::Property::NoVRegs
);
168 Properties
.reset(llvm::MachineFunctionProperties::Property::IsSSA
);
170 for (const unsigned Reg
: LiveIns
)
171 MF
.getRegInfo().addLiveIn(Reg
);
173 bool IsSnippetSetupComplete
= false;
174 std::vector
<llvm::MCInst
> Code
=
175 generateSnippetSetupCode(ET
, TM
->getMCSubtargetInfo(),
176 RegisterInitialValues
, IsSnippetSetupComplete
);
178 Code
.insert(Code
.end(), Instructions
.begin(), Instructions
.end());
180 // If the snippet setup is not complete, we disable liveliness tracking. This
181 // means that we won't know what values are in the registers.
182 if (!IsSnippetSetupComplete
)
183 Properties
.reset(llvm::MachineFunctionProperties::Property::TracksLiveness
);
185 // prologue/epilogue pass needs the reserved registers to be frozen, this
186 // is usually done by the SelectionDAGISel pass.
187 MF
.getRegInfo().freezeReservedRegs(MF
);
189 // Fill the MachineFunction from the instructions.
190 fillMachineFunction(MF
, LiveIns
, Code
);
192 // We create the pass manager, run the passes to populate AsmBuffer.
193 llvm::MCContext
&MCContext
= MMI
->getContext();
194 llvm::legacy::PassManager PM
;
196 llvm::TargetLibraryInfoImpl
TLII(llvm::Triple(Module
->getTargetTriple()));
197 PM
.add(new llvm::TargetLibraryInfoWrapperPass(TLII
));
199 llvm::TargetPassConfig
*TPC
= TM
->createPassConfig(PM
);
201 PM
.add(MMI
.release());
202 TPC
->printAndVerify("MachineFunctionGenerator::assemble");
203 // Add target-specific passes.
204 ET
.addTargetSpecificPasses(PM
);
205 TPC
->printAndVerify("After ExegesisTarget::addTargetSpecificPasses");
206 // Adding the following passes:
207 // - machineverifier: checks that the MachineFunction is well formed.
208 // - prologepilog: saves and restore callee saved registers.
209 for (const char *PassName
: {"machineverifier", "prologepilog"})
210 if (addPass(PM
, PassName
, *TPC
))
211 llvm::report_fatal_error("Unable to add a mandatory pass");
212 TPC
->setInitialized();
214 // AsmPrinter is responsible for generating the assembly into AsmBuffer.
215 if (TM
->addAsmPrinter(PM
, AsmStream
, nullptr,
216 llvm::TargetMachine::CGFT_ObjectFile
, MCContext
))
217 llvm::report_fatal_error("Cannot add AsmPrinter passes");
219 PM
.run(*Module
); // Run all the passes
222 llvm::object::OwningBinary
<llvm::object::ObjectFile
>
223 getObjectFromBuffer(llvm::StringRef InputData
) {
224 // Storing the generated assembly into a MemoryBuffer that owns the memory.
225 std::unique_ptr
<llvm::MemoryBuffer
> Buffer
=
226 llvm::MemoryBuffer::getMemBufferCopy(InputData
);
227 // Create the ObjectFile from the MemoryBuffer.
228 std::unique_ptr
<llvm::object::ObjectFile
> Obj
= llvm::cantFail(
229 llvm::object::ObjectFile::createObjectFile(Buffer
->getMemBufferRef()));
230 // Returning both the MemoryBuffer and the ObjectFile.
231 return llvm::object::OwningBinary
<llvm::object::ObjectFile
>(
232 std::move(Obj
), std::move(Buffer
));
235 llvm::object::OwningBinary
<llvm::object::ObjectFile
>
236 getObjectFromFile(llvm::StringRef Filename
) {
237 return llvm::cantFail(llvm::object::ObjectFile::createObjectFile(Filename
));
242 // Implementation of this class relies on the fact that a single object with a
243 // single function will be loaded into memory.
244 class TrackingSectionMemoryManager
: public llvm::SectionMemoryManager
{
246 explicit TrackingSectionMemoryManager(uintptr_t *CodeSize
)
247 : CodeSize(CodeSize
) {}
249 uint8_t *allocateCodeSection(uintptr_t Size
, unsigned Alignment
,
251 llvm::StringRef SectionName
) override
{
253 return llvm::SectionMemoryManager::allocateCodeSection(
254 Size
, Alignment
, SectionID
, SectionName
);
258 uintptr_t *const CodeSize
= nullptr;
263 ExecutableFunction::ExecutableFunction(
264 std::unique_ptr
<llvm::LLVMTargetMachine
> TM
,
265 llvm::object::OwningBinary
<llvm::object::ObjectFile
> &&ObjectFileHolder
)
266 : Context(llvm::make_unique
<llvm::LLVMContext
>()) {
267 assert(ObjectFileHolder
.getBinary() && "cannot create object file");
268 // Initializing the execution engine.
269 // We need to use the JIT EngineKind to be able to add an object file.
271 uintptr_t CodeSize
= 0;
274 llvm::EngineBuilder(createModule(Context
, TM
->createDataLayout()))
276 .setMCPU(TM
->getTargetCPU())
277 .setEngineKind(llvm::EngineKind::JIT
)
278 .setMCJITMemoryManager(
279 llvm::make_unique
<TrackingSectionMemoryManager
>(&CodeSize
))
280 .create(TM
.release()));
282 llvm::report_fatal_error(Error
);
283 // Adding the generated object file containing the assembled function.
284 // The ExecutionEngine makes sure the object file is copied into an
286 ExecEngine
->addObjectFile(std::move(ObjectFileHolder
));
287 // Fetching function bytes.
289 llvm::StringRef(reinterpret_cast<const char *>(
290 ExecEngine
->getFunctionAddress(FunctionID
)),
294 } // namespace exegesis