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