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