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
64using namespace llvm;
65
66static cl::opt<bool> SimplifyMIR(
67 "simplify-mir", cl::Hidden,
68 cl::desc("Leave out unnecessary information when printing MIR"));
69
70static cl::opt<bool> PrintLocations("mir-debug-loc", cl::Hidden, cl::init(Val: true),
71 cl::desc("Print MIR debug-locations"));
72
73namespace {
74
75/// This structure describes how to print out stack object references.
76struct 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
95struct 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
110namespace llvm::yaml {
111
112/// This struct serializes the LLVM IR module.
113template <> 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
126static 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
132static DenseMap<const uint32_t *, unsigned>
133initRegisterMaskIds(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
142static void printMBB(raw_ostream &OS, MFPrintState &State,
143 const MachineBasicBlock &MBB);
144static void convertMRI(yaml::MachineFunction &YamlMF, const MachineFunction &MF,
145 const MachineRegisterInfo &RegInfo,
146 const TargetRegisterInfo *TRI);
147static void convertMCP(yaml::MachineFunction &MF,
148 const MachineConstantPool &ConstantPool);
149static void convertMJTI(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
150 const MachineJumpTableInfo &JTI);
151static void convertMFI(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
152 const MachineFrameInfo &MFI);
153static void convertStackObjects(yaml::MachineFunction &YMF,
154 const MachineFunction &MF,
155 ModuleSlotTracker &MST, MFPrintState &State);
156static void convertEntryValueObjects(yaml::MachineFunction &YMF,
157 const MachineFunction &MF,
158 ModuleSlotTracker &MST);
159static void convertCallSiteObjects(yaml::MachineFunction &YMF,
160 const MachineFunction &MF,
161 ModuleSlotTracker &MST);
162static void convertMachineMetadataNodes(yaml::MachineFunction &YMF,
163 const MachineFunction &MF,
164 MachineModuleSlotTracker &MST);
165static void convertCalledGlobals(yaml::MachineFunction &YMF,
166 const MachineFunction &MF,
167 MachineModuleSlotTracker &MST);
168
169static 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
244static 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
263static 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
270template <typename T>
271static void
272printStackObjectDbgInfo(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
286static 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
295static 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
337static 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
368static 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
381static 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
392static 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
524static 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
557static 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
570static 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
592static 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
613static 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
631void 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
652static 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
670static void printMI(raw_ostream &OS, MFPrintState &State,
671 const MachineInstr &MI);
672
673static 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
681void 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
750static 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
878static std::string formatOperandComment(std::string Comment) {
879 if (Comment.empty())
880 return Comment;
881 return std::string(" /* " + Comment + " */");
882}
883
884static 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 MOComment = 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
945void 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
967void llvm::printMIR(raw_ostream &OS, const Module &M) {
968 yaml::Output Out(OS);
969 Out << const_cast<Module &>(M);
970}
971
972void llvm::printMIR(raw_ostream &OS, const MachineModuleInfo &MMI,
973 const MachineFunction &MF) {
974 printMF(OS, MMI, MF);
975}
976