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