| 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 | |