1 | //===- MIRPrinter.cpp - MIR serialization format printer ------------------===// |
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 | // This file implements the class that prints out the LLVM IR and machine |
10 | // functions using the MIR serialization format. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/CodeGen/MIRPrinter.h" |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/SmallBitVector.h" |
18 | #include "llvm/ADT/SmallPtrSet.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/CodeGen/MIRYamlMapping.h" |
22 | #include "llvm/CodeGen/MachineBasicBlock.h" |
23 | #include "llvm/CodeGen/MachineConstantPool.h" |
24 | #include "llvm/CodeGen/MachineFrameInfo.h" |
25 | #include "llvm/CodeGen/MachineFunction.h" |
26 | #include "llvm/CodeGen/MachineInstr.h" |
27 | #include "llvm/CodeGen/MachineJumpTableInfo.h" |
28 | #include "llvm/CodeGen/MachineMemOperand.h" |
29 | #include "llvm/CodeGen/MachineModuleSlotTracker.h" |
30 | #include "llvm/CodeGen/MachineOperand.h" |
31 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
32 | #include "llvm/CodeGen/TargetFrameLowering.h" |
33 | #include "llvm/CodeGen/TargetInstrInfo.h" |
34 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
35 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
36 | #include "llvm/CodeGenTypes/LowLevelType.h" |
37 | #include "llvm/IR/DebugInfoMetadata.h" |
38 | #include "llvm/IR/DebugLoc.h" |
39 | #include "llvm/IR/Function.h" |
40 | #include "llvm/IR/IRPrintingPasses.h" |
41 | #include "llvm/IR/Instructions.h" |
42 | #include "llvm/IR/Module.h" |
43 | #include "llvm/IR/ModuleSlotTracker.h" |
44 | #include "llvm/IR/Value.h" |
45 | #include "llvm/MC/LaneBitmask.h" |
46 | #include "llvm/Support/BranchProbability.h" |
47 | #include "llvm/Support/Casting.h" |
48 | #include "llvm/Support/CommandLine.h" |
49 | #include "llvm/Support/ErrorHandling.h" |
50 | #include "llvm/Support/Format.h" |
51 | #include "llvm/Support/YAMLTraits.h" |
52 | #include "llvm/Support/raw_ostream.h" |
53 | #include "llvm/Target/TargetMachine.h" |
54 | #include <algorithm> |
55 | #include <cassert> |
56 | #include <cinttypes> |
57 | #include <cstdint> |
58 | #include <iterator> |
59 | #include <string> |
60 | #include <utility> |
61 | #include <vector> |
62 | |
63 | using namespace llvm; |
64 | |
65 | static cl::opt<bool> SimplifyMIR( |
66 | "simplify-mir" , cl::Hidden, |
67 | cl::desc("Leave out unnecessary information when printing MIR" )); |
68 | |
69 | static cl::opt<bool> PrintLocations("mir-debug-loc" , cl::Hidden, cl::init(Val: true), |
70 | cl::desc("Print MIR debug-locations" )); |
71 | |
72 | extern cl::opt<bool> WriteNewDbgInfoFormat; |
73 | |
74 | namespace { |
75 | |
76 | /// This structure describes how to print out stack object references. |
77 | struct FrameIndexOperand { |
78 | std::string Name; |
79 | unsigned ID; |
80 | bool IsFixed; |
81 | |
82 | FrameIndexOperand(StringRef Name, unsigned ID, bool IsFixed) |
83 | : Name(Name.str()), ID(ID), IsFixed(IsFixed) {} |
84 | |
85 | /// Return an ordinary stack object reference. |
86 | static FrameIndexOperand create(StringRef Name, unsigned ID) { |
87 | return FrameIndexOperand(Name, ID, /*IsFixed=*/false); |
88 | } |
89 | |
90 | /// Return a fixed stack object reference. |
91 | static FrameIndexOperand createFixed(unsigned ID) { |
92 | return FrameIndexOperand("" , ID, /*IsFixed=*/true); |
93 | } |
94 | }; |
95 | |
96 | } // end anonymous namespace |
97 | |
98 | namespace llvm { |
99 | |
100 | /// This class prints out the machine functions using the MIR serialization |
101 | /// format. |
102 | class MIRPrinter { |
103 | raw_ostream &OS; |
104 | DenseMap<const uint32_t *, unsigned> RegisterMaskIds; |
105 | /// Maps from stack object indices to operand indices which will be used when |
106 | /// printing frame index machine operands. |
107 | DenseMap<int, FrameIndexOperand> StackObjectOperandMapping; |
108 | |
109 | public: |
110 | MIRPrinter(raw_ostream &OS) : OS(OS) {} |
111 | |
112 | void print(const MachineFunction &MF); |
113 | |
114 | void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo, |
115 | const TargetRegisterInfo *TRI); |
116 | void convert(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI, |
117 | const MachineFrameInfo &MFI); |
118 | void convert(yaml::MachineFunction &MF, |
119 | const MachineConstantPool &ConstantPool); |
120 | void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI, |
121 | const MachineJumpTableInfo &JTI); |
122 | void convertStackObjects(yaml::MachineFunction &YMF, |
123 | const MachineFunction &MF, ModuleSlotTracker &MST); |
124 | void convertEntryValueObjects(yaml::MachineFunction &YMF, |
125 | const MachineFunction &MF, |
126 | ModuleSlotTracker &MST); |
127 | void convertCallSiteObjects(yaml::MachineFunction &YMF, |
128 | const MachineFunction &MF, |
129 | ModuleSlotTracker &MST); |
130 | void convertMachineMetadataNodes(yaml::MachineFunction &YMF, |
131 | const MachineFunction &MF, |
132 | MachineModuleSlotTracker &MST); |
133 | |
134 | private: |
135 | void initRegisterMaskIds(const MachineFunction &MF); |
136 | }; |
137 | |
138 | /// This class prints out the machine instructions using the MIR serialization |
139 | /// format. |
140 | class MIPrinter { |
141 | raw_ostream &OS; |
142 | ModuleSlotTracker &MST; |
143 | const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds; |
144 | const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping; |
145 | /// Synchronization scope names registered with LLVMContext. |
146 | SmallVector<StringRef, 8> SSNs; |
147 | |
148 | bool canPredictBranchProbabilities(const MachineBasicBlock &MBB) const; |
149 | bool canPredictSuccessors(const MachineBasicBlock &MBB) const; |
150 | |
151 | public: |
152 | MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST, |
153 | const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds, |
154 | const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping) |
155 | : OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds), |
156 | StackObjectOperandMapping(StackObjectOperandMapping) {} |
157 | |
158 | void print(const MachineBasicBlock &MBB); |
159 | |
160 | void print(const MachineInstr &MI); |
161 | void printStackObjectReference(int FrameIndex); |
162 | void print(const MachineInstr &MI, unsigned OpIdx, |
163 | const TargetRegisterInfo *TRI, const TargetInstrInfo *TII, |
164 | bool ShouldPrintRegisterTies, LLT TypeToPrint, |
165 | bool PrintDef = true); |
166 | }; |
167 | |
168 | } // end namespace llvm |
169 | |
170 | namespace llvm { |
171 | namespace yaml { |
172 | |
173 | /// This struct serializes the LLVM IR module. |
174 | template <> struct BlockScalarTraits<Module> { |
175 | static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) { |
176 | Mod.print(OS, AAW: nullptr); |
177 | } |
178 | |
179 | static StringRef input(StringRef Str, void *Ctxt, Module &Mod) { |
180 | llvm_unreachable("LLVM Module is supposed to be parsed separately" ); |
181 | return "" ; |
182 | } |
183 | }; |
184 | |
185 | } // end namespace yaml |
186 | } // end namespace llvm |
187 | |
188 | static void printRegMIR(unsigned Reg, yaml::StringValue &Dest, |
189 | const TargetRegisterInfo *TRI) { |
190 | raw_string_ostream OS(Dest.Value); |
191 | OS << printReg(Reg, TRI); |
192 | } |
193 | |
194 | void MIRPrinter::print(const MachineFunction &MF) { |
195 | initRegisterMaskIds(MF); |
196 | |
197 | yaml::MachineFunction YamlMF; |
198 | YamlMF.Name = MF.getName(); |
199 | YamlMF.Alignment = MF.getAlignment(); |
200 | YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); |
201 | YamlMF.HasWinCFI = MF.hasWinCFI(); |
202 | |
203 | YamlMF.CallsEHReturn = MF.callsEHReturn(); |
204 | YamlMF.CallsUnwindInit = MF.callsUnwindInit(); |
205 | YamlMF.HasEHCatchret = MF.hasEHCatchret(); |
206 | YamlMF.HasEHScopes = MF.hasEHScopes(); |
207 | YamlMF.HasEHFunclets = MF.hasEHFunclets(); |
208 | YamlMF.IsOutlined = MF.isOutlined(); |
209 | YamlMF.UseDebugInstrRef = MF.useDebugInstrRef(); |
210 | |
211 | YamlMF.Legalized = MF.getProperties().hasProperty( |
212 | P: MachineFunctionProperties::Property::Legalized); |
213 | YamlMF.RegBankSelected = MF.getProperties().hasProperty( |
214 | P: MachineFunctionProperties::Property::RegBankSelected); |
215 | YamlMF.Selected = MF.getProperties().hasProperty( |
216 | P: MachineFunctionProperties::Property::Selected); |
217 | YamlMF.FailedISel = MF.getProperties().hasProperty( |
218 | P: MachineFunctionProperties::Property::FailedISel); |
219 | YamlMF.FailsVerification = MF.getProperties().hasProperty( |
220 | P: MachineFunctionProperties::Property::FailsVerification); |
221 | YamlMF.TracksDebugUserValues = MF.getProperties().hasProperty( |
222 | P: MachineFunctionProperties::Property::TracksDebugUserValues); |
223 | |
224 | convert(MF&: YamlMF, RegInfo: MF.getRegInfo(), TRI: MF.getSubtarget().getRegisterInfo()); |
225 | MachineModuleSlotTracker MST(&MF); |
226 | MST.incorporateFunction(F: MF.getFunction()); |
227 | convert(MST, YamlMFI&: YamlMF.FrameInfo, MFI: MF.getFrameInfo()); |
228 | convertStackObjects(YMF&: YamlMF, MF, MST); |
229 | convertEntryValueObjects(YMF&: YamlMF, MF, MST); |
230 | convertCallSiteObjects(YMF&: YamlMF, MF, MST); |
231 | for (const auto &Sub : MF.DebugValueSubstitutions) { |
232 | const auto &SubSrc = Sub.Src; |
233 | const auto &SubDest = Sub.Dest; |
234 | YamlMF.DebugValueSubstitutions.push_back(x: {.SrcInst: SubSrc.first, .SrcOp: SubSrc.second, |
235 | .DstInst: SubDest.first, |
236 | .DstOp: SubDest.second, |
237 | .Subreg: Sub.Subreg}); |
238 | } |
239 | if (const auto *ConstantPool = MF.getConstantPool()) |
240 | convert(MF&: YamlMF, ConstantPool: *ConstantPool); |
241 | if (const auto *JumpTableInfo = MF.getJumpTableInfo()) |
242 | convert(MST, YamlJTI&: YamlMF.JumpTableInfo, JTI: *JumpTableInfo); |
243 | |
244 | const TargetMachine &TM = MF.getTarget(); |
245 | YamlMF.MachineFuncInfo = |
246 | std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF)); |
247 | |
248 | raw_string_ostream StrOS(YamlMF.Body.Value.Value); |
249 | bool IsNewlineNeeded = false; |
250 | for (const auto &MBB : MF) { |
251 | if (IsNewlineNeeded) |
252 | StrOS << "\n" ; |
253 | MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) |
254 | .print(MBB); |
255 | IsNewlineNeeded = true; |
256 | } |
257 | StrOS.flush(); |
258 | // Convert machine metadata collected during the print of the machine |
259 | // function. |
260 | convertMachineMetadataNodes(YMF&: YamlMF, MF, MST); |
261 | |
262 | yaml::Output Out(OS); |
263 | if (!SimplifyMIR) |
264 | Out.setWriteDefaultValues(true); |
265 | Out << YamlMF; |
266 | } |
267 | |
268 | static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS, |
269 | const TargetRegisterInfo *TRI) { |
270 | assert(RegMask && "Can't print an empty register mask" ); |
271 | OS << StringRef("CustomRegMask(" ); |
272 | |
273 | bool IsRegInRegMaskFound = false; |
274 | for (int I = 0, E = TRI->getNumRegs(); I < E; I++) { |
275 | // Check whether the register is asserted in regmask. |
276 | if (RegMask[I / 32] & (1u << (I % 32))) { |
277 | if (IsRegInRegMaskFound) |
278 | OS << ','; |
279 | OS << printReg(Reg: I, TRI); |
280 | IsRegInRegMaskFound = true; |
281 | } |
282 | } |
283 | |
284 | OS << ')'; |
285 | } |
286 | |
287 | static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest, |
288 | const MachineRegisterInfo &RegInfo, |
289 | const TargetRegisterInfo *TRI) { |
290 | raw_string_ostream OS(Dest.Value); |
291 | OS << printRegClassOrBank(Reg, RegInfo, TRI); |
292 | } |
293 | |
294 | template <typename T> |
295 | static void |
296 | printStackObjectDbgInfo(const MachineFunction::VariableDbgInfo &DebugVar, |
297 | T &Object, ModuleSlotTracker &MST) { |
298 | std::array<std::string *, 3> Outputs{{&Object.DebugVar.Value, |
299 | &Object.DebugExpr.Value, |
300 | &Object.DebugLoc.Value}}; |
301 | std::array<const Metadata *, 3> Metas{._M_elems: {DebugVar.Var, |
302 | DebugVar.Expr, |
303 | DebugVar.Loc}}; |
304 | for (unsigned i = 0; i < 3; ++i) { |
305 | raw_string_ostream StrOS(*Outputs[i]); |
306 | Metas[i]->printAsOperand(OS&: StrOS, MST); |
307 | } |
308 | } |
309 | |
310 | void MIRPrinter::convert(yaml::MachineFunction &MF, |
311 | const MachineRegisterInfo &RegInfo, |
312 | const TargetRegisterInfo *TRI) { |
313 | MF.TracksRegLiveness = RegInfo.tracksLiveness(); |
314 | |
315 | // Print the virtual register definitions. |
316 | for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) { |
317 | Register Reg = Register::index2VirtReg(Index: I); |
318 | yaml::VirtualRegisterDefinition VReg; |
319 | VReg.ID = I; |
320 | if (RegInfo.getVRegName(Reg) != "" ) |
321 | continue; |
322 | ::printRegClassOrBank(Reg, Dest&: VReg.Class, RegInfo, TRI); |
323 | Register PreferredReg = RegInfo.getSimpleHint(VReg: Reg); |
324 | if (PreferredReg) |
325 | printRegMIR(Reg: PreferredReg, Dest&: VReg.PreferredRegister, TRI); |
326 | MF.VirtualRegisters.push_back(x: VReg); |
327 | } |
328 | |
329 | // Print the live ins. |
330 | for (std::pair<unsigned, unsigned> LI : RegInfo.liveins()) { |
331 | yaml::MachineFunctionLiveIn LiveIn; |
332 | printRegMIR(Reg: LI.first, Dest&: LiveIn.Register, TRI); |
333 | if (LI.second) |
334 | printRegMIR(Reg: LI.second, Dest&: LiveIn.VirtualRegister, TRI); |
335 | MF.LiveIns.push_back(x: LiveIn); |
336 | } |
337 | |
338 | // Prints the callee saved registers. |
339 | if (RegInfo.isUpdatedCSRsInitialized()) { |
340 | const MCPhysReg *CalleeSavedRegs = RegInfo.getCalleeSavedRegs(); |
341 | std::vector<yaml::FlowStringValue> CalleeSavedRegisters; |
342 | for (const MCPhysReg *I = CalleeSavedRegs; *I; ++I) { |
343 | yaml::FlowStringValue Reg; |
344 | printRegMIR(Reg: *I, Dest&: Reg, TRI); |
345 | CalleeSavedRegisters.push_back(x: Reg); |
346 | } |
347 | MF.CalleeSavedRegisters = CalleeSavedRegisters; |
348 | } |
349 | } |
350 | |
351 | void MIRPrinter::convert(ModuleSlotTracker &MST, |
352 | yaml::MachineFrameInfo &YamlMFI, |
353 | const MachineFrameInfo &MFI) { |
354 | YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken(); |
355 | YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken(); |
356 | YamlMFI.HasStackMap = MFI.hasStackMap(); |
357 | YamlMFI.HasPatchPoint = MFI.hasPatchPoint(); |
358 | YamlMFI.StackSize = MFI.getStackSize(); |
359 | YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment(); |
360 | YamlMFI.MaxAlignment = MFI.getMaxAlign().value(); |
361 | YamlMFI.AdjustsStack = MFI.adjustsStack(); |
362 | YamlMFI.HasCalls = MFI.hasCalls(); |
363 | YamlMFI.MaxCallFrameSize = MFI.isMaxCallFrameSizeComputed() |
364 | ? MFI.getMaxCallFrameSize() : ~0u; |
365 | YamlMFI.CVBytesOfCalleeSavedRegisters = |
366 | MFI.getCVBytesOfCalleeSavedRegisters(); |
367 | YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment(); |
368 | YamlMFI.HasVAStart = MFI.hasVAStart(); |
369 | YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc(); |
370 | YamlMFI.HasTailCall = MFI.hasTailCall(); |
371 | YamlMFI.IsCalleeSavedInfoValid = MFI.isCalleeSavedInfoValid(); |
372 | YamlMFI.LocalFrameSize = MFI.getLocalFrameSize(); |
373 | if (MFI.getSavePoint()) { |
374 | raw_string_ostream StrOS(YamlMFI.SavePoint.Value); |
375 | StrOS << printMBBReference(MBB: *MFI.getSavePoint()); |
376 | } |
377 | if (MFI.getRestorePoint()) { |
378 | raw_string_ostream StrOS(YamlMFI.RestorePoint.Value); |
379 | StrOS << printMBBReference(MBB: *MFI.getRestorePoint()); |
380 | } |
381 | } |
382 | |
383 | void MIRPrinter::convertEntryValueObjects(yaml::MachineFunction &YMF, |
384 | const MachineFunction &MF, |
385 | ModuleSlotTracker &MST) { |
386 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
387 | for (const MachineFunction::VariableDbgInfo &DebugVar : |
388 | MF.getEntryValueVariableDbgInfo()) { |
389 | yaml::EntryValueObject &Obj = YMF.EntryValueObjects.emplace_back(); |
390 | printStackObjectDbgInfo(DebugVar, Object&: Obj, MST); |
391 | MCRegister EntryValReg = DebugVar.getEntryValueRegister(); |
392 | printRegMIR(Reg: EntryValReg, Dest&: Obj.EntryValueRegister, TRI); |
393 | } |
394 | } |
395 | |
396 | void MIRPrinter::convertStackObjects(yaml::MachineFunction &YMF, |
397 | const MachineFunction &MF, |
398 | ModuleSlotTracker &MST) { |
399 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
400 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); |
401 | |
402 | // Process fixed stack objects. |
403 | assert(YMF.FixedStackObjects.empty()); |
404 | SmallVector<int, 32> FixedStackObjectsIdx; |
405 | const int BeginIdx = MFI.getObjectIndexBegin(); |
406 | if (BeginIdx < 0) |
407 | FixedStackObjectsIdx.reserve(N: -BeginIdx); |
408 | |
409 | unsigned ID = 0; |
410 | for (int I = BeginIdx; I < 0; ++I, ++ID) { |
411 | FixedStackObjectsIdx.push_back(Elt: -1); // Fill index for possible dead. |
412 | if (MFI.isDeadObjectIndex(ObjectIdx: I)) |
413 | continue; |
414 | |
415 | yaml::FixedMachineStackObject YamlObject; |
416 | YamlObject.ID = ID; |
417 | YamlObject.Type = MFI.isSpillSlotObjectIndex(ObjectIdx: I) |
418 | ? yaml::FixedMachineStackObject::SpillSlot |
419 | : yaml::FixedMachineStackObject::DefaultType; |
420 | YamlObject.Offset = MFI.getObjectOffset(ObjectIdx: I); |
421 | YamlObject.Size = MFI.getObjectSize(ObjectIdx: I); |
422 | YamlObject.Alignment = MFI.getObjectAlign(ObjectIdx: I); |
423 | YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(ObjectIdx: I); |
424 | YamlObject.IsImmutable = MFI.isImmutableObjectIndex(ObjectIdx: I); |
425 | YamlObject.IsAliased = MFI.isAliasedObjectIndex(ObjectIdx: I); |
426 | // Save the ID' position in FixedStackObjects storage vector. |
427 | FixedStackObjectsIdx[ID] = YMF.FixedStackObjects.size(); |
428 | YMF.FixedStackObjects.push_back(x: YamlObject); |
429 | StackObjectOperandMapping.insert( |
430 | KV: std::make_pair(x&: I, y: FrameIndexOperand::createFixed(ID))); |
431 | } |
432 | |
433 | // Process ordinary stack objects. |
434 | assert(YMF.StackObjects.empty()); |
435 | SmallVector<unsigned, 32> StackObjectsIdx; |
436 | const int EndIdx = MFI.getObjectIndexEnd(); |
437 | if (EndIdx > 0) |
438 | StackObjectsIdx.reserve(N: EndIdx); |
439 | ID = 0; |
440 | for (int I = 0; I < EndIdx; ++I, ++ID) { |
441 | StackObjectsIdx.push_back(Elt: -1); // Fill index for possible dead. |
442 | if (MFI.isDeadObjectIndex(ObjectIdx: I)) |
443 | continue; |
444 | |
445 | yaml::MachineStackObject YamlObject; |
446 | YamlObject.ID = ID; |
447 | if (const auto *Alloca = MFI.getObjectAllocation(ObjectIdx: I)) |
448 | YamlObject.Name.Value = std::string( |
449 | Alloca->hasName() ? Alloca->getName() : "" ); |
450 | YamlObject.Type = MFI.isSpillSlotObjectIndex(ObjectIdx: I) |
451 | ? yaml::MachineStackObject::SpillSlot |
452 | : MFI.isVariableSizedObjectIndex(ObjectIdx: I) |
453 | ? yaml::MachineStackObject::VariableSized |
454 | : yaml::MachineStackObject::DefaultType; |
455 | YamlObject.Offset = MFI.getObjectOffset(ObjectIdx: I); |
456 | YamlObject.Size = MFI.getObjectSize(ObjectIdx: I); |
457 | YamlObject.Alignment = MFI.getObjectAlign(ObjectIdx: I); |
458 | YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(ObjectIdx: I); |
459 | |
460 | // Save the ID' position in StackObjects storage vector. |
461 | StackObjectsIdx[ID] = YMF.StackObjects.size(); |
462 | YMF.StackObjects.push_back(x: YamlObject); |
463 | StackObjectOperandMapping.insert(KV: std::make_pair( |
464 | x&: I, y: FrameIndexOperand::create(Name: YamlObject.Name.Value, ID))); |
465 | } |
466 | |
467 | for (const auto &CSInfo : MFI.getCalleeSavedInfo()) { |
468 | const int FrameIdx = CSInfo.getFrameIdx(); |
469 | if (!CSInfo.isSpilledToReg() && MFI.isDeadObjectIndex(ObjectIdx: FrameIdx)) |
470 | continue; |
471 | |
472 | yaml::StringValue Reg; |
473 | printRegMIR(Reg: CSInfo.getReg(), Dest&: Reg, TRI); |
474 | if (!CSInfo.isSpilledToReg()) { |
475 | assert(FrameIdx >= MFI.getObjectIndexBegin() && |
476 | FrameIdx < MFI.getObjectIndexEnd() && |
477 | "Invalid stack object index" ); |
478 | if (FrameIdx < 0) { // Negative index means fixed objects. |
479 | auto &Object = |
480 | YMF.FixedStackObjects |
481 | [FixedStackObjectsIdx[FrameIdx + MFI.getNumFixedObjects()]]; |
482 | Object.CalleeSavedRegister = Reg; |
483 | Object.CalleeSavedRestored = CSInfo.isRestored(); |
484 | } else { |
485 | auto &Object = YMF.StackObjects[StackObjectsIdx[FrameIdx]]; |
486 | Object.CalleeSavedRegister = Reg; |
487 | Object.CalleeSavedRestored = CSInfo.isRestored(); |
488 | } |
489 | } |
490 | } |
491 | for (unsigned I = 0, E = MFI.getLocalFrameObjectCount(); I < E; ++I) { |
492 | auto LocalObject = MFI.getLocalFrameObjectMap(i: I); |
493 | assert(LocalObject.first >= 0 && "Expected a locally mapped stack object" ); |
494 | YMF.StackObjects[StackObjectsIdx[LocalObject.first]].LocalOffset = |
495 | LocalObject.second; |
496 | } |
497 | |
498 | // Print the stack object references in the frame information class after |
499 | // converting the stack objects. |
500 | if (MFI.hasStackProtectorIndex()) { |
501 | raw_string_ostream StrOS(YMF.FrameInfo.StackProtector.Value); |
502 | MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) |
503 | .printStackObjectReference(FrameIndex: MFI.getStackProtectorIndex()); |
504 | } |
505 | |
506 | if (MFI.hasFunctionContextIndex()) { |
507 | raw_string_ostream StrOS(YMF.FrameInfo.FunctionContext.Value); |
508 | MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) |
509 | .printStackObjectReference(FrameIndex: MFI.getFunctionContextIndex()); |
510 | } |
511 | |
512 | // Print the debug variable information. |
513 | for (const MachineFunction::VariableDbgInfo &DebugVar : |
514 | MF.getInStackSlotVariableDbgInfo()) { |
515 | int Idx = DebugVar.getStackSlot(); |
516 | assert(Idx >= MFI.getObjectIndexBegin() && Idx < MFI.getObjectIndexEnd() && |
517 | "Invalid stack object index" ); |
518 | if (Idx < 0) { // Negative index means fixed objects. |
519 | auto &Object = |
520 | YMF.FixedStackObjects[FixedStackObjectsIdx[Idx + |
521 | MFI.getNumFixedObjects()]]; |
522 | printStackObjectDbgInfo(DebugVar, Object, MST); |
523 | } else { |
524 | auto &Object = YMF.StackObjects[StackObjectsIdx[Idx]]; |
525 | printStackObjectDbgInfo(DebugVar, Object, MST); |
526 | } |
527 | } |
528 | } |
529 | |
530 | void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF, |
531 | const MachineFunction &MF, |
532 | ModuleSlotTracker &MST) { |
533 | const auto *TRI = MF.getSubtarget().getRegisterInfo(); |
534 | for (auto CSInfo : MF.getCallSitesInfo()) { |
535 | yaml::CallSiteInfo YmlCS; |
536 | yaml::CallSiteInfo::MachineInstrLoc CallLocation; |
537 | |
538 | // Prepare instruction position. |
539 | MachineBasicBlock::const_instr_iterator CallI = CSInfo.first->getIterator(); |
540 | CallLocation.BlockNum = CallI->getParent()->getNumber(); |
541 | // Get call instruction offset from the beginning of block. |
542 | CallLocation.Offset = |
543 | std::distance(first: CallI->getParent()->instr_begin(), last: CallI); |
544 | YmlCS.CallLocation = CallLocation; |
545 | // Construct call arguments and theirs forwarding register info. |
546 | for (auto ArgReg : CSInfo.second.ArgRegPairs) { |
547 | yaml::CallSiteInfo::ArgRegPair YmlArgReg; |
548 | YmlArgReg.ArgNo = ArgReg.ArgNo; |
549 | printRegMIR(Reg: ArgReg.Reg, Dest&: YmlArgReg.Reg, TRI); |
550 | YmlCS.ArgForwardingRegs.emplace_back(args&: YmlArgReg); |
551 | } |
552 | YMF.CallSitesInfo.push_back(x: YmlCS); |
553 | } |
554 | |
555 | // Sort call info by position of call instructions. |
556 | llvm::sort(Start: YMF.CallSitesInfo.begin(), End: YMF.CallSitesInfo.end(), |
557 | Comp: [](yaml::CallSiteInfo A, yaml::CallSiteInfo B) { |
558 | if (A.CallLocation.BlockNum == B.CallLocation.BlockNum) |
559 | return A.CallLocation.Offset < B.CallLocation.Offset; |
560 | return A.CallLocation.BlockNum < B.CallLocation.BlockNum; |
561 | }); |
562 | } |
563 | |
564 | void MIRPrinter::convertMachineMetadataNodes(yaml::MachineFunction &YMF, |
565 | const MachineFunction &MF, |
566 | MachineModuleSlotTracker &MST) { |
567 | MachineModuleSlotTracker::MachineMDNodeListType MDList; |
568 | MST.collectMachineMDNodes(L&: MDList); |
569 | for (auto &MD : MDList) { |
570 | std::string NS; |
571 | raw_string_ostream StrOS(NS); |
572 | MD.second->print(OS&: StrOS, MST, M: MF.getFunction().getParent()); |
573 | YMF.MachineMetadataNodes.push_back(x: NS); |
574 | } |
575 | } |
576 | |
577 | void MIRPrinter::convert(yaml::MachineFunction &MF, |
578 | const MachineConstantPool &ConstantPool) { |
579 | unsigned ID = 0; |
580 | for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) { |
581 | std::string Str; |
582 | raw_string_ostream StrOS(Str); |
583 | if (Constant.isMachineConstantPoolEntry()) { |
584 | Constant.Val.MachineCPVal->print(O&: StrOS); |
585 | } else { |
586 | Constant.Val.ConstVal->printAsOperand(O&: StrOS); |
587 | } |
588 | |
589 | yaml::MachineConstantPoolValue YamlConstant; |
590 | YamlConstant.ID = ID++; |
591 | YamlConstant.Value = Str; |
592 | YamlConstant.Alignment = Constant.getAlign(); |
593 | YamlConstant.IsTargetSpecific = Constant.isMachineConstantPoolEntry(); |
594 | |
595 | MF.Constants.push_back(x: YamlConstant); |
596 | } |
597 | } |
598 | |
599 | void MIRPrinter::convert(ModuleSlotTracker &MST, |
600 | yaml::MachineJumpTable &YamlJTI, |
601 | const MachineJumpTableInfo &JTI) { |
602 | YamlJTI.Kind = JTI.getEntryKind(); |
603 | unsigned ID = 0; |
604 | for (const auto &Table : JTI.getJumpTables()) { |
605 | std::string Str; |
606 | yaml::MachineJumpTable::Entry Entry; |
607 | Entry.ID = ID++; |
608 | for (const auto *MBB : Table.MBBs) { |
609 | raw_string_ostream StrOS(Str); |
610 | StrOS << printMBBReference(MBB: *MBB); |
611 | Entry.Blocks.push_back(x: Str); |
612 | Str.clear(); |
613 | } |
614 | YamlJTI.Entries.push_back(x: Entry); |
615 | } |
616 | } |
617 | |
618 | void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) { |
619 | const auto *TRI = MF.getSubtarget().getRegisterInfo(); |
620 | unsigned I = 0; |
621 | for (const uint32_t *Mask : TRI->getRegMasks()) |
622 | RegisterMaskIds.insert(KV: std::make_pair(x&: Mask, y: I++)); |
623 | } |
624 | |
625 | void llvm::guessSuccessors(const MachineBasicBlock &MBB, |
626 | SmallVectorImpl<MachineBasicBlock*> &Result, |
627 | bool &IsFallthrough) { |
628 | SmallPtrSet<MachineBasicBlock*,8> Seen; |
629 | |
630 | for (const MachineInstr &MI : MBB) { |
631 | if (MI.isPHI()) |
632 | continue; |
633 | for (const MachineOperand &MO : MI.operands()) { |
634 | if (!MO.isMBB()) |
635 | continue; |
636 | MachineBasicBlock *Succ = MO.getMBB(); |
637 | auto RP = Seen.insert(Ptr: Succ); |
638 | if (RP.second) |
639 | Result.push_back(Elt: Succ); |
640 | } |
641 | } |
642 | MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr(); |
643 | IsFallthrough = I == MBB.end() || !I->isBarrier(); |
644 | } |
645 | |
646 | bool |
647 | MIPrinter::canPredictBranchProbabilities(const MachineBasicBlock &MBB) const { |
648 | if (MBB.succ_size() <= 1) |
649 | return true; |
650 | if (!MBB.hasSuccessorProbabilities()) |
651 | return true; |
652 | |
653 | SmallVector<BranchProbability,8> Normalized(MBB.Probs.begin(), |
654 | MBB.Probs.end()); |
655 | BranchProbability::normalizeProbabilities(Begin: Normalized.begin(), |
656 | End: Normalized.end()); |
657 | SmallVector<BranchProbability,8> Equal(Normalized.size()); |
658 | BranchProbability::normalizeProbabilities(Begin: Equal.begin(), End: Equal.end()); |
659 | |
660 | return std::equal(Normalized.begin(), Normalized.end(), Equal.begin()); |
661 | } |
662 | |
663 | bool MIPrinter::canPredictSuccessors(const MachineBasicBlock &MBB) const { |
664 | SmallVector<MachineBasicBlock*,8> GuessedSuccs; |
665 | bool GuessedFallthrough; |
666 | guessSuccessors(MBB, Result&: GuessedSuccs, IsFallthrough&: GuessedFallthrough); |
667 | if (GuessedFallthrough) { |
668 | const MachineFunction &MF = *MBB.getParent(); |
669 | MachineFunction::const_iterator NextI = std::next(x: MBB.getIterator()); |
670 | if (NextI != MF.end()) { |
671 | MachineBasicBlock *Next = const_cast<MachineBasicBlock*>(&*NextI); |
672 | if (!is_contained(Range&: GuessedSuccs, Element: Next)) |
673 | GuessedSuccs.push_back(Elt: Next); |
674 | } |
675 | } |
676 | if (GuessedSuccs.size() != MBB.succ_size()) |
677 | return false; |
678 | return std::equal(MBB.succ_begin(), MBB.succ_end(), GuessedSuccs.begin()); |
679 | } |
680 | |
681 | void MIPrinter::print(const MachineBasicBlock &MBB) { |
682 | assert(MBB.getNumber() >= 0 && "Invalid MBB number" ); |
683 | MBB.printName(os&: OS, |
684 | printNameFlags: MachineBasicBlock::PrintNameIr | |
685 | MachineBasicBlock::PrintNameAttributes, |
686 | moduleSlotTracker: &MST); |
687 | OS << ":\n" ; |
688 | |
689 | bool HasLineAttributes = false; |
690 | // Print the successors |
691 | bool canPredictProbs = canPredictBranchProbabilities(MBB); |
692 | // Even if the list of successors is empty, if we cannot guess it, |
693 | // we need to print it to tell the parser that the list is empty. |
694 | // This is needed, because MI model unreachable as empty blocks |
695 | // with an empty successor list. If the parser would see that |
696 | // without the successor list, it would guess the code would |
697 | // fallthrough. |
698 | if ((!MBB.succ_empty() && !SimplifyMIR) || !canPredictProbs || |
699 | !canPredictSuccessors(MBB)) { |
700 | OS.indent(NumSpaces: 2) << "successors:" ; |
701 | if (!MBB.succ_empty()) |
702 | OS << " " ; |
703 | for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) { |
704 | if (I != MBB.succ_begin()) |
705 | OS << ", " ; |
706 | OS << printMBBReference(MBB: **I); |
707 | if (!SimplifyMIR || !canPredictProbs) |
708 | OS << '(' |
709 | << format(Fmt: "0x%08" PRIx32, Vals: MBB.getSuccProbability(Succ: I).getNumerator()) |
710 | << ')'; |
711 | } |
712 | OS << "\n" ; |
713 | HasLineAttributes = true; |
714 | } |
715 | |
716 | // Print the live in registers. |
717 | const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); |
718 | if (!MBB.livein_empty()) { |
719 | const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); |
720 | OS.indent(NumSpaces: 2) << "liveins: " ; |
721 | bool First = true; |
722 | for (const auto &LI : MBB.liveins_dbg()) { |
723 | if (!First) |
724 | OS << ", " ; |
725 | First = false; |
726 | OS << printReg(Reg: LI.PhysReg, TRI: &TRI); |
727 | if (!LI.LaneMask.all()) |
728 | OS << ":0x" << PrintLaneMask(LaneMask: LI.LaneMask); |
729 | } |
730 | OS << "\n" ; |
731 | HasLineAttributes = true; |
732 | } |
733 | |
734 | if (HasLineAttributes && !MBB.empty()) |
735 | OS << "\n" ; |
736 | bool IsInBundle = false; |
737 | for (const MachineInstr &MI : MBB.instrs()) { |
738 | if (IsInBundle && !MI.isInsideBundle()) { |
739 | OS.indent(NumSpaces: 2) << "}\n" ; |
740 | IsInBundle = false; |
741 | } |
742 | OS.indent(NumSpaces: IsInBundle ? 4 : 2); |
743 | print(MI); |
744 | if (!IsInBundle && MI.getFlag(Flag: MachineInstr::BundledSucc)) { |
745 | OS << " {" ; |
746 | IsInBundle = true; |
747 | } |
748 | OS << "\n" ; |
749 | } |
750 | if (IsInBundle) |
751 | OS.indent(NumSpaces: 2) << "}\n" ; |
752 | } |
753 | |
754 | void MIPrinter::print(const MachineInstr &MI) { |
755 | const auto *MF = MI.getMF(); |
756 | const auto &MRI = MF->getRegInfo(); |
757 | const auto &SubTarget = MF->getSubtarget(); |
758 | const auto *TRI = SubTarget.getRegisterInfo(); |
759 | assert(TRI && "Expected target register info" ); |
760 | const auto *TII = SubTarget.getInstrInfo(); |
761 | assert(TII && "Expected target instruction info" ); |
762 | if (MI.isCFIInstruction()) |
763 | assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction" ); |
764 | |
765 | SmallBitVector PrintedTypes(8); |
766 | bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies(); |
767 | unsigned I = 0, E = MI.getNumOperands(); |
768 | for (; I < E && MI.getOperand(i: I).isReg() && MI.getOperand(i: I).isDef() && |
769 | !MI.getOperand(i: I).isImplicit(); |
770 | ++I) { |
771 | if (I) |
772 | OS << ", " ; |
773 | print(MI, OpIdx: I, TRI, TII, ShouldPrintRegisterTies, |
774 | TypeToPrint: MI.getTypeToPrint(OpIdx: I, PrintedTypes, MRI), |
775 | /*PrintDef=*/false); |
776 | } |
777 | |
778 | if (I) |
779 | OS << " = " ; |
780 | if (MI.getFlag(Flag: MachineInstr::FrameSetup)) |
781 | OS << "frame-setup " ; |
782 | if (MI.getFlag(Flag: MachineInstr::FrameDestroy)) |
783 | OS << "frame-destroy " ; |
784 | if (MI.getFlag(Flag: MachineInstr::FmNoNans)) |
785 | OS << "nnan " ; |
786 | if (MI.getFlag(Flag: MachineInstr::FmNoInfs)) |
787 | OS << "ninf " ; |
788 | if (MI.getFlag(Flag: MachineInstr::FmNsz)) |
789 | OS << "nsz " ; |
790 | if (MI.getFlag(Flag: MachineInstr::FmArcp)) |
791 | OS << "arcp " ; |
792 | if (MI.getFlag(Flag: MachineInstr::FmContract)) |
793 | OS << "contract " ; |
794 | if (MI.getFlag(Flag: MachineInstr::FmAfn)) |
795 | OS << "afn " ; |
796 | if (MI.getFlag(Flag: MachineInstr::FmReassoc)) |
797 | OS << "reassoc " ; |
798 | if (MI.getFlag(Flag: MachineInstr::NoUWrap)) |
799 | OS << "nuw " ; |
800 | if (MI.getFlag(Flag: MachineInstr::NoSWrap)) |
801 | OS << "nsw " ; |
802 | if (MI.getFlag(Flag: MachineInstr::IsExact)) |
803 | OS << "exact " ; |
804 | if (MI.getFlag(Flag: MachineInstr::NoFPExcept)) |
805 | OS << "nofpexcept " ; |
806 | if (MI.getFlag(Flag: MachineInstr::NoMerge)) |
807 | OS << "nomerge " ; |
808 | if (MI.getFlag(Flag: MachineInstr::Unpredictable)) |
809 | OS << "unpredictable " ; |
810 | if (MI.getFlag(Flag: MachineInstr::NoConvergent)) |
811 | OS << "noconvergent " ; |
812 | if (MI.getFlag(Flag: MachineInstr::NonNeg)) |
813 | OS << "nneg " ; |
814 | if (MI.getFlag(Flag: MachineInstr::Disjoint)) |
815 | OS << "disjoint " ; |
816 | if (MI.getFlag(Flag: MachineInstr::NoUSWrap)) |
817 | OS << "nusw " ; |
818 | |
819 | OS << TII->getName(Opcode: MI.getOpcode()); |
820 | if (I < E) |
821 | OS << ' '; |
822 | |
823 | bool NeedComma = false; |
824 | for (; I < E; ++I) { |
825 | if (NeedComma) |
826 | OS << ", " ; |
827 | print(MI, OpIdx: I, TRI, TII, ShouldPrintRegisterTies, |
828 | TypeToPrint: MI.getTypeToPrint(OpIdx: I, PrintedTypes, MRI)); |
829 | NeedComma = true; |
830 | } |
831 | |
832 | // Print any optional symbols attached to this instruction as-if they were |
833 | // operands. |
834 | if (MCSymbol *PreInstrSymbol = MI.getPreInstrSymbol()) { |
835 | if (NeedComma) |
836 | OS << ','; |
837 | OS << " pre-instr-symbol " ; |
838 | MachineOperand::printSymbol(OS, Sym&: *PreInstrSymbol); |
839 | NeedComma = true; |
840 | } |
841 | if (MCSymbol *PostInstrSymbol = MI.getPostInstrSymbol()) { |
842 | if (NeedComma) |
843 | OS << ','; |
844 | OS << " post-instr-symbol " ; |
845 | MachineOperand::printSymbol(OS, Sym&: *PostInstrSymbol); |
846 | NeedComma = true; |
847 | } |
848 | if (MDNode *HeapAllocMarker = MI.getHeapAllocMarker()) { |
849 | if (NeedComma) |
850 | OS << ','; |
851 | OS << " heap-alloc-marker " ; |
852 | HeapAllocMarker->printAsOperand(OS, MST); |
853 | NeedComma = true; |
854 | } |
855 | if (MDNode *PCSections = MI.getPCSections()) { |
856 | if (NeedComma) |
857 | OS << ','; |
858 | OS << " pcsections " ; |
859 | PCSections->printAsOperand(OS, MST); |
860 | NeedComma = true; |
861 | } |
862 | if (MDNode *MMRA = MI.getMMRAMetadata()) { |
863 | if (NeedComma) |
864 | OS << ','; |
865 | OS << " mmra " ; |
866 | MMRA->printAsOperand(OS, MST); |
867 | NeedComma = true; |
868 | } |
869 | if (uint32_t CFIType = MI.getCFIType()) { |
870 | if (NeedComma) |
871 | OS << ','; |
872 | OS << " cfi-type " << CFIType; |
873 | NeedComma = true; |
874 | } |
875 | |
876 | if (auto Num = MI.peekDebugInstrNum()) { |
877 | if (NeedComma) |
878 | OS << ','; |
879 | OS << " debug-instr-number " << Num; |
880 | NeedComma = true; |
881 | } |
882 | |
883 | if (PrintLocations) { |
884 | if (const DebugLoc &DL = MI.getDebugLoc()) { |
885 | if (NeedComma) |
886 | OS << ','; |
887 | OS << " debug-location " ; |
888 | DL->printAsOperand(OS, MST); |
889 | } |
890 | } |
891 | |
892 | if (!MI.memoperands_empty()) { |
893 | OS << " :: " ; |
894 | const LLVMContext &Context = MF->getFunction().getContext(); |
895 | const MachineFrameInfo &MFI = MF->getFrameInfo(); |
896 | bool NeedComma = false; |
897 | for (const auto *Op : MI.memoperands()) { |
898 | if (NeedComma) |
899 | OS << ", " ; |
900 | Op->print(OS, MST, SSNs, Context, MFI: &MFI, TII); |
901 | NeedComma = true; |
902 | } |
903 | } |
904 | } |
905 | |
906 | void MIPrinter::printStackObjectReference(int FrameIndex) { |
907 | auto ObjectInfo = StackObjectOperandMapping.find(Val: FrameIndex); |
908 | assert(ObjectInfo != StackObjectOperandMapping.end() && |
909 | "Invalid frame index" ); |
910 | const FrameIndexOperand &Operand = ObjectInfo->second; |
911 | MachineOperand::printStackObjectReference(OS, FrameIndex: Operand.ID, IsFixed: Operand.IsFixed, |
912 | Name: Operand.Name); |
913 | } |
914 | |
915 | static std::string formatOperandComment(std::string ) { |
916 | if (Comment.empty()) |
917 | return Comment; |
918 | return std::string(" /* " + Comment + " */" ); |
919 | } |
920 | |
921 | void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx, |
922 | const TargetRegisterInfo *TRI, |
923 | const TargetInstrInfo *TII, |
924 | bool ShouldPrintRegisterTies, LLT TypeToPrint, |
925 | bool PrintDef) { |
926 | const MachineOperand &Op = MI.getOperand(i: OpIdx); |
927 | std::string = TII->createMIROperandComment(MI, Op, OpIdx, TRI); |
928 | |
929 | switch (Op.getType()) { |
930 | case MachineOperand::MO_Immediate: |
931 | if (MI.isOperandSubregIdx(OpIdx)) { |
932 | MachineOperand::printTargetFlags(OS, Op); |
933 | MachineOperand::printSubRegIdx(OS, Index: Op.getImm(), TRI); |
934 | break; |
935 | } |
936 | [[fallthrough]]; |
937 | case MachineOperand::MO_Register: |
938 | case MachineOperand::MO_CImmediate: |
939 | case MachineOperand::MO_FPImmediate: |
940 | case MachineOperand::MO_MachineBasicBlock: |
941 | case MachineOperand::MO_ConstantPoolIndex: |
942 | case MachineOperand::MO_TargetIndex: |
943 | case MachineOperand::MO_JumpTableIndex: |
944 | case MachineOperand::MO_ExternalSymbol: |
945 | case MachineOperand::MO_GlobalAddress: |
946 | case MachineOperand::MO_RegisterLiveOut: |
947 | case MachineOperand::MO_Metadata: |
948 | case MachineOperand::MO_MCSymbol: |
949 | case MachineOperand::MO_CFIIndex: |
950 | case MachineOperand::MO_IntrinsicID: |
951 | case MachineOperand::MO_Predicate: |
952 | case MachineOperand::MO_BlockAddress: |
953 | case MachineOperand::MO_DbgInstrRef: |
954 | case MachineOperand::MO_ShuffleMask: { |
955 | unsigned TiedOperandIdx = 0; |
956 | if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef()) |
957 | TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx); |
958 | const TargetIntrinsicInfo *TII = MI.getMF()->getTarget().getIntrinsicInfo(); |
959 | Op.print(os&: OS, MST, TypeToPrint, OpIdx, PrintDef, /*IsStandalone=*/false, |
960 | ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo: TII); |
961 | OS << formatOperandComment(Comment: MOComment); |
962 | break; |
963 | } |
964 | case MachineOperand::MO_FrameIndex: |
965 | printStackObjectReference(FrameIndex: Op.getIndex()); |
966 | break; |
967 | case MachineOperand::MO_RegisterMask: { |
968 | auto RegMaskInfo = RegisterMaskIds.find(Val: Op.getRegMask()); |
969 | if (RegMaskInfo != RegisterMaskIds.end()) |
970 | OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower(); |
971 | else |
972 | printCustomRegMask(RegMask: Op.getRegMask(), OS, TRI); |
973 | break; |
974 | } |
975 | } |
976 | } |
977 | |
978 | void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V, |
979 | ModuleSlotTracker &MST) { |
980 | if (isa<GlobalValue>(Val: V)) { |
981 | V.printAsOperand(O&: OS, /*PrintType=*/false, MST); |
982 | return; |
983 | } |
984 | if (isa<Constant>(Val: V)) { |
985 | // Machine memory operands can load/store to/from constant value pointers. |
986 | OS << '`'; |
987 | V.printAsOperand(O&: OS, /*PrintType=*/true, MST); |
988 | OS << '`'; |
989 | return; |
990 | } |
991 | OS << "%ir." ; |
992 | if (V.hasName()) { |
993 | printLLVMNameWithoutPrefix(OS, Name: V.getName()); |
994 | return; |
995 | } |
996 | int Slot = MST.getCurrentFunction() ? MST.getLocalSlot(V: &V) : -1; |
997 | MachineOperand::printIRSlotNumber(OS, Slot); |
998 | } |
999 | |
1000 | void llvm::printMIR(raw_ostream &OS, const Module &M) { |
1001 | ScopedDbgInfoFormatSetter FormatSetter(const_cast<Module &>(M), |
1002 | WriteNewDbgInfoFormat); |
1003 | |
1004 | yaml::Output Out(OS); |
1005 | Out << const_cast<Module &>(M); |
1006 | } |
1007 | |
1008 | void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) { |
1009 | // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info |
1010 | // in dbg.value format. |
1011 | ScopedDbgInfoFormatSetter FormatSetter( |
1012 | const_cast<Function &>(MF.getFunction()), WriteNewDbgInfoFormat); |
1013 | |
1014 | MIRPrinter Printer(OS); |
1015 | Printer.print(MF); |
1016 | } |
1017 | |