2015-06-16 07:52:35 +08:00
|
|
|
//===- MIRPrinter.cpp - MIR serialization format printer ------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-06-16 07:52:35 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the class that prints out the LLVM IR and machine
|
|
|
|
// functions using the MIR serialization format.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/MIRPrinter.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/None.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2016-09-12 19:20:10 +08:00
|
|
|
#include "llvm/ADT/SmallBitVector.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2016-04-09 00:26:22 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/MIRYamlMapping.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2015-07-21 04:51:18 +08:00
|
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
MIR Serialization: Serialize the simple MachineFrameInfo attributes.
This commit serializes the 13 scalar boolean and integer attributes from the
MachineFrameInfo class: IsFrameAddressTaken, IsReturnAddressTaken, HasStackMap,
HasPatchPoint, StackSize, OffsetAdjustment, MaxAlignment, AdjustsStack,
HasCalls, MaxCallFrameSize, HasOpaqueSPAdjustment, HasVAStart, and
HasMustTailInVarArgFunc. These attributes are serialized as part
of the frameInfo YAML mapping, which itself is a part of the machine function's
YAML mapping.
llvm-svn: 241844
2015-07-10 03:55:27 +08:00
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2016-04-09 00:26:22 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
|
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
2015-08-04 07:08:19 +08:00
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
2015-06-25 03:56:10 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/CodeGen/PseudoSourceValue.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2019-06-17 17:13:29 +08:00
|
|
|
#include "llvm/CodeGen/TargetFrameLowering.h"
|
2015-06-20 01:43:07 +08:00
|
|
|
#include "llvm/IR/BasicBlock.h"
|
2015-07-29 01:28:03 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2016-04-15 02:29:59 +08:00
|
|
|
#include "llvm/IR/DebugInfo.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/IR/DebugLoc.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/GlobalValue.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
2016-04-09 00:26:22 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
2016-07-30 04:32:59 +08:00
|
|
|
#include "llvm/IR/Intrinsics.h"
|
2015-06-16 07:52:35 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
2015-07-08 07:27:53 +08:00
|
|
|
#include "llvm/IR/ModuleSlotTracker.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/MC/LaneBitmask.h"
|
[x86/MIR] Implement support for pre- and post-instruction symbols, as
well as MIR parsing support for `MCSymbol` `MachineOperand`s.
The only real way to test pre- and post-instruction symbol support is to
use them in operands, so I ended up implementing that within the patch
as well. I can split out the operand support if folks really want but it
doesn't really seem worth it.
The functional implementation of pre- and post-instruction symbols is
now *completely trivial*. Two tiny bits of code in the (misnamed)
AsmPrinter. It should be completely target independent as well. We emit
these exactly the same way as we emit basic block labels. Most of the
code here is to give full dumping, MIR printing, and MIR parsing support
so that we can write useful tests.
The MIR parsing of MC symbol operands still isn't 100%, as it forces the
symbols to be non-temporary and non-local symbols with names. However,
those names often can encode most (if not all) of the special semantics
desired, and unnamed symbols seem especially annoying to serialize and
de-serialize. While this isn't perfect or full support, it seems plenty
to write tests that exercise usage of these kinds of operands.
The MIR support for pre-and post-instruction symbols was quite
straightforward. I chose to print them out in an as-if-operand syntax
similar to debug locations as this seemed the cleanest way and let me
use nice introducer tokens rather than inventing more magic punctuation
like we use for memoperands.
However, supporting MIR-based parsing of these symbols caused me to
change the design of the symbol support to allow setting arbitrary
symbols. Without this, I don't see any reasonable way to test things
with MIR.
Differential Revision: https://reviews.llvm.org/D50833
llvm-svn: 339962
2018-08-17 07:11:05 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/MC/MCDwarf.h"
|
2015-08-22 05:12:44 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/Support/AtomicOrdering.h"
|
|
|
|
#include "llvm/Support/BranchProbability.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2016-11-19 03:37:24 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/Support/LowLevelTypeImpl.h"
|
|
|
|
#include "llvm/Support/YAMLTraits.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2016-07-30 04:32:59 +08:00
|
|
|
#include "llvm/Target/TargetIntrinsicInfo.h"
|
2017-06-07 06:22:41 +08:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cinttypes>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iterator>
|
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2015-06-16 07:52:35 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2017-12-01 08:53:10 +08:00
|
|
|
static cl::opt<bool> SimplifyMIR(
|
|
|
|
"simplify-mir", cl::Hidden,
|
2017-05-06 05:09:30 +08:00
|
|
|
cl::desc("Leave out unnecessary information when printing MIR"));
|
|
|
|
|
2020-04-07 01:57:21 +08:00
|
|
|
static cl::opt<bool> PrintLocations("mir-debug-loc", cl::Hidden, cl::init(true),
|
|
|
|
cl::desc("Print MIR debug-locations"));
|
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
namespace {
|
|
|
|
|
2015-07-17 07:37:45 +08:00
|
|
|
/// This structure describes how to print out stack object references.
|
|
|
|
struct FrameIndexOperand {
|
|
|
|
std::string Name;
|
|
|
|
unsigned ID;
|
|
|
|
bool IsFixed;
|
|
|
|
|
|
|
|
FrameIndexOperand(StringRef Name, unsigned ID, bool IsFixed)
|
|
|
|
: Name(Name.str()), ID(ID), IsFixed(IsFixed) {}
|
|
|
|
|
|
|
|
/// Return an ordinary stack object reference.
|
|
|
|
static FrameIndexOperand create(StringRef Name, unsigned ID) {
|
|
|
|
return FrameIndexOperand(Name, ID, /*IsFixed=*/false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return a fixed stack object reference.
|
|
|
|
static FrameIndexOperand createFixed(unsigned ID) {
|
|
|
|
return FrameIndexOperand("", ID, /*IsFixed=*/true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-07-31 00:54:38 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
/// This class prints out the machine functions using the MIR serialization
|
|
|
|
/// format.
|
|
|
|
class MIRPrinter {
|
|
|
|
raw_ostream &OS;
|
2015-06-30 00:57:06 +08:00
|
|
|
DenseMap<const uint32_t *, unsigned> RegisterMaskIds;
|
2015-07-17 07:37:45 +08:00
|
|
|
/// Maps from stack object indices to operand indices which will be used when
|
|
|
|
/// printing frame index machine operands.
|
|
|
|
DenseMap<int, FrameIndexOperand> StackObjectOperandMapping;
|
2015-06-16 07:52:35 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
MIRPrinter(raw_ostream &OS) : OS(OS) {}
|
|
|
|
|
|
|
|
void print(const MachineFunction &MF);
|
2015-06-20 01:43:07 +08:00
|
|
|
|
2015-07-10 06:23:13 +08:00
|
|
|
void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
|
|
|
|
const TargetRegisterInfo *TRI);
|
2015-07-30 05:09:09 +08:00
|
|
|
void convert(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
|
|
|
|
const MachineFrameInfo &MFI);
|
2015-07-21 04:51:18 +08:00
|
|
|
void convert(yaml::MachineFunction &MF,
|
|
|
|
const MachineConstantPool &ConstantPool);
|
2015-07-16 07:31:07 +08:00
|
|
|
void convert(ModuleSlotTracker &MST, yaml::MachineJumpTable &YamlJTI,
|
|
|
|
const MachineJumpTableInfo &JTI);
|
2016-12-01 07:48:50 +08:00
|
|
|
void convertStackObjects(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF, ModuleSlotTracker &MST);
|
2019-06-27 15:48:06 +08:00
|
|
|
void convertCallSiteObjects(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
ModuleSlotTracker &MST);
|
2015-06-30 00:57:06 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
void initRegisterMaskIds(const MachineFunction &MF);
|
2015-06-16 07:52:35 +08:00
|
|
|
};
|
|
|
|
|
2015-06-23 01:02:30 +08:00
|
|
|
/// This class prints out the machine instructions using the MIR serialization
|
|
|
|
/// format.
|
|
|
|
class MIPrinter {
|
|
|
|
raw_ostream &OS;
|
2015-07-08 07:27:53 +08:00
|
|
|
ModuleSlotTracker &MST;
|
2015-06-30 00:57:06 +08:00
|
|
|
const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds;
|
2015-07-17 07:37:45 +08:00
|
|
|
const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping;
|
2017-07-12 06:23:00 +08:00
|
|
|
/// Synchronization scope names registered with LLVMContext.
|
|
|
|
SmallVector<StringRef, 8> SSNs;
|
2015-06-23 01:02:30 +08:00
|
|
|
|
2017-05-06 05:09:30 +08:00
|
|
|
bool canPredictBranchProbabilities(const MachineBasicBlock &MBB) const;
|
|
|
|
bool canPredictSuccessors(const MachineBasicBlock &MBB) const;
|
|
|
|
|
2015-06-23 01:02:30 +08:00
|
|
|
public:
|
2015-07-08 07:27:53 +08:00
|
|
|
MIPrinter(raw_ostream &OS, ModuleSlotTracker &MST,
|
2015-07-17 07:37:45 +08:00
|
|
|
const DenseMap<const uint32_t *, unsigned> &RegisterMaskIds,
|
|
|
|
const DenseMap<int, FrameIndexOperand> &StackObjectOperandMapping)
|
|
|
|
: OS(OS), MST(MST), RegisterMaskIds(RegisterMaskIds),
|
|
|
|
StackObjectOperandMapping(StackObjectOperandMapping) {}
|
2015-06-23 01:02:30 +08:00
|
|
|
|
2015-08-14 07:10:16 +08:00
|
|
|
void print(const MachineBasicBlock &MBB);
|
|
|
|
|
2015-06-23 01:02:30 +08:00
|
|
|
void print(const MachineInstr &MI);
|
2015-07-17 07:37:45 +08:00
|
|
|
void printStackObjectReference(int FrameIndex);
|
2017-11-07 05:46:06 +08:00
|
|
|
void print(const MachineInstr &MI, unsigned OpIdx,
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
const TargetRegisterInfo *TRI, const TargetInstrInfo *TII,
|
|
|
|
bool ShouldPrintRegisterTies, LLT TypeToPrint,
|
|
|
|
bool PrintDef = true);
|
2015-06-23 01:02:30 +08:00
|
|
|
};
|
|
|
|
|
2015-08-14 07:10:16 +08:00
|
|
|
} // end namespace llvm
|
2015-06-16 07:52:35 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
namespace yaml {
|
|
|
|
|
|
|
|
/// This struct serializes the LLVM IR module.
|
|
|
|
template <> struct BlockScalarTraits<Module> {
|
|
|
|
static void output(const Module &Mod, void *Ctxt, raw_ostream &OS) {
|
|
|
|
Mod.print(OS, nullptr);
|
|
|
|
}
|
2017-06-07 06:22:41 +08:00
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
static StringRef input(StringRef Str, void *Ctxt, Module &Mod) {
|
|
|
|
llvm_unreachable("LLVM Module is supposed to be parsed separately");
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace yaml
|
|
|
|
} // end namespace llvm
|
|
|
|
|
2017-11-28 20:42:37 +08:00
|
|
|
static void printRegMIR(unsigned Reg, yaml::StringValue &Dest,
|
|
|
|
const TargetRegisterInfo *TRI) {
|
2015-07-25 04:35:40 +08:00
|
|
|
raw_string_ostream OS(Dest.Value);
|
2017-12-01 00:12:24 +08:00
|
|
|
OS << printReg(Reg, TRI);
|
2015-07-25 04:35:40 +08:00
|
|
|
}
|
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
void MIRPrinter::print(const MachineFunction &MF) {
|
2015-06-30 00:57:06 +08:00
|
|
|
initRegisterMaskIds(MF);
|
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
yaml::MachineFunction YamlMF;
|
|
|
|
YamlMF.Name = MF.getName();
|
2020-04-01 17:25:48 +08:00
|
|
|
YamlMF.Alignment = MF.getAlignment();
|
2015-06-16 08:10:47 +08:00
|
|
|
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
|
2018-10-25 05:07:38 +08:00
|
|
|
YamlMF.HasWinCFI = MF.hasWinCFI();
|
2016-03-29 01:05:30 +08:00
|
|
|
|
2016-08-02 23:10:25 +08:00
|
|
|
YamlMF.Legalized = MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::Legalized);
|
2016-08-03 00:17:10 +08:00
|
|
|
YamlMF.RegBankSelected = MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::RegBankSelected);
|
2016-08-03 00:49:19 +08:00
|
|
|
YamlMF.Selected = MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::Selected);
|
[GlobalISel] Print/Parse FailedISel MachineFunction property
FailedISel MachineFunction property is part of the CodeGen pipeline
state as much as every other property, notably, Legalized,
RegBankSelected, and Selected. Let's make that part of the state also
serializable / de-serializable, so if GlobalISel aborts on some of the
functions of a large module, but not the others, it could be easily seen
and the state of the pipeline could be maintained through llc's
invocations with -stop-after / -start-after.
To make MIR printable and generally to not to break it too much too
soon, this patch also defers cleaning up the vreg -> LLT map until
ResetMachineFunctionPass.
To make MIR with FailedISel: true also machine verifiable, machine
verifier is changed so it treats a MIR-module as non-regbankselected and
non-selected if there is FailedISel property set.
Reviewers: qcolombet, ab
Reviewed By: dsanders
Subscribers: javed.absar, rovka, kristof.beyls, llvm-commits
Differential Revision: https://reviews.llvm.org/D42877
llvm-svn: 326343
2018-03-01 01:55:45 +08:00
|
|
|
YamlMF.FailedISel = MF.getProperties().hasProperty(
|
|
|
|
MachineFunctionProperties::Property::FailedISel);
|
2016-08-02 23:10:25 +08:00
|
|
|
|
2015-07-10 06:23:13 +08:00
|
|
|
convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
|
2017-12-16 06:22:58 +08:00
|
|
|
ModuleSlotTracker MST(MF.getFunction().getParent());
|
|
|
|
MST.incorporateFunction(MF.getFunction());
|
2016-07-29 02:40:00 +08:00
|
|
|
convert(MST, YamlMF.FrameInfo, MF.getFrameInfo());
|
2016-12-01 07:48:50 +08:00
|
|
|
convertStackObjects(YamlMF, MF, MST);
|
2019-06-27 15:48:06 +08:00
|
|
|
convertCallSiteObjects(YamlMF, MF, MST);
|
2015-07-21 04:51:18 +08:00
|
|
|
if (const auto *ConstantPool = MF.getConstantPool())
|
|
|
|
convert(YamlMF, *ConstantPool);
|
2015-07-16 07:31:07 +08:00
|
|
|
if (const auto *JumpTableInfo = MF.getJumpTableInfo())
|
|
|
|
convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
|
2019-03-15 06:54:43 +08:00
|
|
|
|
|
|
|
const TargetMachine &TM = MF.getTarget();
|
|
|
|
YamlMF.MachineFuncInfo =
|
|
|
|
std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF));
|
|
|
|
|
2015-08-14 07:10:16 +08:00
|
|
|
raw_string_ostream StrOS(YamlMF.Body.Value.Value);
|
|
|
|
bool IsNewlineNeeded = false;
|
2015-06-20 01:43:07 +08:00
|
|
|
for (const auto &MBB : MF) {
|
2015-08-14 07:10:16 +08:00
|
|
|
if (IsNewlineNeeded)
|
|
|
|
StrOS << "\n";
|
|
|
|
MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
|
|
|
|
.print(MBB);
|
|
|
|
IsNewlineNeeded = true;
|
2015-06-20 01:43:07 +08:00
|
|
|
}
|
2015-08-14 07:10:16 +08:00
|
|
|
StrOS.flush();
|
2015-06-16 07:52:35 +08:00
|
|
|
yaml::Output Out(OS);
|
2017-06-06 16:16:19 +08:00
|
|
|
if (!SimplifyMIR)
|
|
|
|
Out.setWriteDefaultValues(true);
|
2015-06-16 07:52:35 +08:00
|
|
|
Out << YamlMF;
|
|
|
|
}
|
|
|
|
|
2017-03-19 16:14:18 +08:00
|
|
|
static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS,
|
|
|
|
const TargetRegisterInfo *TRI) {
|
|
|
|
assert(RegMask && "Can't print an empty register mask");
|
|
|
|
OS << StringRef("CustomRegMask(");
|
|
|
|
|
|
|
|
bool IsRegInRegMaskFound = false;
|
|
|
|
for (int I = 0, E = TRI->getNumRegs(); I < E; I++) {
|
|
|
|
// Check whether the register is asserted in regmask.
|
|
|
|
if (RegMask[I / 32] & (1u << (I % 32))) {
|
|
|
|
if (IsRegInRegMaskFound)
|
|
|
|
OS << ',';
|
2017-12-01 00:12:24 +08:00
|
|
|
OS << printReg(I, TRI);
|
2017-03-19 16:14:18 +08:00
|
|
|
IsRegInRegMaskFound = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << ')';
|
|
|
|
}
|
|
|
|
|
2017-10-25 02:04:54 +08:00
|
|
|
static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest,
|
|
|
|
const MachineRegisterInfo &RegInfo,
|
|
|
|
const TargetRegisterInfo *TRI) {
|
|
|
|
raw_string_ostream OS(Dest.Value);
|
2017-12-07 18:40:31 +08:00
|
|
|
OS << printRegClassOrBank(Reg, RegInfo, TRI);
|
2017-10-25 02:04:54 +08:00
|
|
|
}
|
|
|
|
|
2018-04-26 02:58:06 +08:00
|
|
|
template <typename T>
|
|
|
|
static void
|
|
|
|
printStackObjectDbgInfo(const MachineFunction::VariableDbgInfo &DebugVar,
|
|
|
|
T &Object, ModuleSlotTracker &MST) {
|
|
|
|
std::array<std::string *, 3> Outputs{{&Object.DebugVar.Value,
|
|
|
|
&Object.DebugExpr.Value,
|
|
|
|
&Object.DebugLoc.Value}};
|
|
|
|
std::array<const Metadata *, 3> Metas{{DebugVar.Var,
|
|
|
|
DebugVar.Expr,
|
|
|
|
DebugVar.Loc}};
|
|
|
|
for (unsigned i = 0; i < 3; ++i) {
|
|
|
|
raw_string_ostream StrOS(*Outputs[i]);
|
|
|
|
Metas[i]->printAsOperand(StrOS, MST);
|
|
|
|
}
|
|
|
|
}
|
2017-10-25 02:04:54 +08:00
|
|
|
|
2015-06-25 03:56:10 +08:00
|
|
|
void MIRPrinter::convert(yaml::MachineFunction &MF,
|
2015-07-10 06:23:13 +08:00
|
|
|
const MachineRegisterInfo &RegInfo,
|
|
|
|
const TargetRegisterInfo *TRI) {
|
2015-06-25 03:56:10 +08:00
|
|
|
MF.TracksRegLiveness = RegInfo.tracksLiveness();
|
2015-07-10 06:23:13 +08:00
|
|
|
|
|
|
|
// Print the virtual register definitions.
|
|
|
|
for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
|
2019-08-02 07:27:28 +08:00
|
|
|
unsigned Reg = Register::index2VirtReg(I);
|
2015-07-10 06:23:13 +08:00
|
|
|
yaml::VirtualRegisterDefinition VReg;
|
|
|
|
VReg.ID = I;
|
2018-03-31 02:15:54 +08:00
|
|
|
if (RegInfo.getVRegName(Reg) != "")
|
|
|
|
continue;
|
2017-12-07 18:40:31 +08:00
|
|
|
::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI);
|
2015-07-25 04:35:40 +08:00
|
|
|
unsigned PreferredReg = RegInfo.getSimpleHint(Reg);
|
|
|
|
if (PreferredReg)
|
2017-11-28 20:42:37 +08:00
|
|
|
printRegMIR(PreferredReg, VReg.PreferredRegister, TRI);
|
2015-07-10 06:23:13 +08:00
|
|
|
MF.VirtualRegisters.push_back(VReg);
|
|
|
|
}
|
2015-07-28 01:42:45 +08:00
|
|
|
|
|
|
|
// Print the live ins.
|
2017-10-17 03:08:41 +08:00
|
|
|
for (std::pair<unsigned, unsigned> LI : RegInfo.liveins()) {
|
2015-07-28 01:42:45 +08:00
|
|
|
yaml::MachineFunctionLiveIn LiveIn;
|
2017-11-28 20:42:37 +08:00
|
|
|
printRegMIR(LI.first, LiveIn.Register, TRI);
|
2017-10-17 03:08:41 +08:00
|
|
|
if (LI.second)
|
2017-11-28 20:42:37 +08:00
|
|
|
printRegMIR(LI.second, LiveIn.VirtualRegister, TRI);
|
2015-07-28 01:42:45 +08:00
|
|
|
MF.LiveIns.push_back(LiveIn);
|
|
|
|
}
|
2017-03-19 16:14:18 +08:00
|
|
|
|
|
|
|
// Prints the callee saved registers.
|
|
|
|
if (RegInfo.isUpdatedCSRsInitialized()) {
|
|
|
|
const MCPhysReg *CalleeSavedRegs = RegInfo.getCalleeSavedRegs();
|
|
|
|
std::vector<yaml::FlowStringValue> CalleeSavedRegisters;
|
|
|
|
for (const MCPhysReg *I = CalleeSavedRegs; *I; ++I) {
|
2015-08-11 08:32:49 +08:00
|
|
|
yaml::FlowStringValue Reg;
|
2017-11-28 20:42:37 +08:00
|
|
|
printRegMIR(*I, Reg, TRI);
|
2015-08-11 08:32:49 +08:00
|
|
|
CalleeSavedRegisters.push_back(Reg);
|
|
|
|
}
|
2017-03-19 16:14:18 +08:00
|
|
|
MF.CalleeSavedRegisters = CalleeSavedRegisters;
|
2015-08-11 08:32:49 +08:00
|
|
|
}
|
2015-06-25 03:56:10 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 05:09:09 +08:00
|
|
|
void MIRPrinter::convert(ModuleSlotTracker &MST,
|
|
|
|
yaml::MachineFrameInfo &YamlMFI,
|
MIR Serialization: Serialize the simple MachineFrameInfo attributes.
This commit serializes the 13 scalar boolean and integer attributes from the
MachineFrameInfo class: IsFrameAddressTaken, IsReturnAddressTaken, HasStackMap,
HasPatchPoint, StackSize, OffsetAdjustment, MaxAlignment, AdjustsStack,
HasCalls, MaxCallFrameSize, HasOpaqueSPAdjustment, HasVAStart, and
HasMustTailInVarArgFunc. These attributes are serialized as part
of the frameInfo YAML mapping, which itself is a part of the machine function's
YAML mapping.
llvm-svn: 241844
2015-07-10 03:55:27 +08:00
|
|
|
const MachineFrameInfo &MFI) {
|
|
|
|
YamlMFI.IsFrameAddressTaken = MFI.isFrameAddressTaken();
|
|
|
|
YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken();
|
|
|
|
YamlMFI.HasStackMap = MFI.hasStackMap();
|
|
|
|
YamlMFI.HasPatchPoint = MFI.hasPatchPoint();
|
|
|
|
YamlMFI.StackSize = MFI.getStackSize();
|
|
|
|
YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment();
|
[Alignment][NFC] Deprecate getMaxAlignment
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet
Subscribers: jholewinski, arsenm, dschuff, jyknight, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, hiraditya, aheejin, kbarton, fedor.sergeev, asb, rbar, johnrusso, simoncook, sabuasal, niosHD, jrtc27, MaskRay, zzheng, edward-jones, atanasyan, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, Jim, lenary, s.egerton, pzheng, sameer.abuasal, apazos, luismarques, kerbowa, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D76348
2020-03-18 17:50:38 +08:00
|
|
|
YamlMFI.MaxAlignment = MFI.getMaxAlign().value();
|
MIR Serialization: Serialize the simple MachineFrameInfo attributes.
This commit serializes the 13 scalar boolean and integer attributes from the
MachineFrameInfo class: IsFrameAddressTaken, IsReturnAddressTaken, HasStackMap,
HasPatchPoint, StackSize, OffsetAdjustment, MaxAlignment, AdjustsStack,
HasCalls, MaxCallFrameSize, HasOpaqueSPAdjustment, HasVAStart, and
HasMustTailInVarArgFunc. These attributes are serialized as part
of the frameInfo YAML mapping, which itself is a part of the machine function's
YAML mapping.
llvm-svn: 241844
2015-07-10 03:55:27 +08:00
|
|
|
YamlMFI.AdjustsStack = MFI.adjustsStack();
|
|
|
|
YamlMFI.HasCalls = MFI.hasCalls();
|
2017-05-02 06:32:25 +08:00
|
|
|
YamlMFI.MaxCallFrameSize = MFI.isMaxCallFrameSizeComputed()
|
|
|
|
? MFI.getMaxCallFrameSize() : ~0u;
|
[codeview] Emit S_FRAMEPROC and use S_DEFRANGE_FRAMEPOINTER_REL
Summary:
Before this change, LLVM would always describe locals on the stack as
being relative to some specific register, RSP, ESP, EBP, ESI, etc.
Variables in stack memory are pretty common, so there is a special
S_DEFRANGE_FRAMEPOINTER_REL symbol for them. This change uses it to
reduce the size of our debug info.
On top of the size savings, there are cases on 32-bit x86 where local
variables are addressed from ESP, but ESP changes across the function.
Unlike in DWARF, there is no FPO data to describe the stack adjustments
made to push arguments onto the stack and pop them off after the call,
which makes it hard for the debugger to find the local variables in
frames further up the stack.
To handle this, CodeView has a special VFRAME register, which
corresponds to the $T0 variable set by our FPO data in 32-bit. Offsets
to local variables are instead relative to this value.
This is part of PR38857.
Reviewers: hans, zturner, javed.absar
Subscribers: aprantl, hiraditya, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D52217
llvm-svn: 343543
2018-10-02 05:59:45 +08:00
|
|
|
YamlMFI.CVBytesOfCalleeSavedRegisters =
|
|
|
|
MFI.getCVBytesOfCalleeSavedRegisters();
|
MIR Serialization: Serialize the simple MachineFrameInfo attributes.
This commit serializes the 13 scalar boolean and integer attributes from the
MachineFrameInfo class: IsFrameAddressTaken, IsReturnAddressTaken, HasStackMap,
HasPatchPoint, StackSize, OffsetAdjustment, MaxAlignment, AdjustsStack,
HasCalls, MaxCallFrameSize, HasOpaqueSPAdjustment, HasVAStart, and
HasMustTailInVarArgFunc. These attributes are serialized as part
of the frameInfo YAML mapping, which itself is a part of the machine function's
YAML mapping.
llvm-svn: 241844
2015-07-10 03:55:27 +08:00
|
|
|
YamlMFI.HasOpaqueSPAdjustment = MFI.hasOpaqueSPAdjustment();
|
|
|
|
YamlMFI.HasVAStart = MFI.hasVAStart();
|
|
|
|
YamlMFI.HasMustTailInVarArgFunc = MFI.hasMustTailInVarArgFunc();
|
2018-04-06 16:56:25 +08:00
|
|
|
YamlMFI.LocalFrameSize = MFI.getLocalFrameSize();
|
2015-07-30 05:09:09 +08:00
|
|
|
if (MFI.getSavePoint()) {
|
|
|
|
raw_string_ostream StrOS(YamlMFI.SavePoint.Value);
|
2017-12-05 01:18:51 +08:00
|
|
|
StrOS << printMBBReference(*MFI.getSavePoint());
|
2015-07-30 05:09:09 +08:00
|
|
|
}
|
|
|
|
if (MFI.getRestorePoint()) {
|
|
|
|
raw_string_ostream StrOS(YamlMFI.RestorePoint.Value);
|
2017-12-05 01:18:51 +08:00
|
|
|
StrOS << printMBBReference(*MFI.getRestorePoint());
|
2015-07-30 05:09:09 +08:00
|
|
|
}
|
MIR Serialization: Serialize the simple MachineFrameInfo attributes.
This commit serializes the 13 scalar boolean and integer attributes from the
MachineFrameInfo class: IsFrameAddressTaken, IsReturnAddressTaken, HasStackMap,
HasPatchPoint, StackSize, OffsetAdjustment, MaxAlignment, AdjustsStack,
HasCalls, MaxCallFrameSize, HasOpaqueSPAdjustment, HasVAStart, and
HasMustTailInVarArgFunc. These attributes are serialized as part
of the frameInfo YAML mapping, which itself is a part of the machine function's
YAML mapping.
llvm-svn: 241844
2015-07-10 03:55:27 +08:00
|
|
|
}
|
|
|
|
|
2016-12-01 07:48:50 +08:00
|
|
|
void MIRPrinter::convertStackObjects(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
ModuleSlotTracker &MST) {
|
|
|
|
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
|
2015-07-14 02:07:26 +08:00
|
|
|
// Process fixed stack objects.
|
2015-07-11 02:13:57 +08:00
|
|
|
unsigned ID = 0;
|
2019-02-23 03:30:38 +08:00
|
|
|
for (int I = MFI.getObjectIndexBegin(); I < 0; ++I, ++ID) {
|
2015-07-14 02:07:26 +08:00
|
|
|
if (MFI.isDeadObjectIndex(I))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
yaml::FixedMachineStackObject YamlObject;
|
2015-07-17 07:37:45 +08:00
|
|
|
YamlObject.ID = ID;
|
2015-07-14 02:07:26 +08:00
|
|
|
YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
|
|
|
|
? yaml::FixedMachineStackObject::SpillSlot
|
|
|
|
: yaml::FixedMachineStackObject::DefaultType;
|
|
|
|
YamlObject.Offset = MFI.getObjectOffset(I);
|
|
|
|
YamlObject.Size = MFI.getObjectSize(I);
|
2020-04-01 17:25:48 +08:00
|
|
|
YamlObject.Alignment = MFI.getObjectAlign(I);
|
2019-06-17 17:13:29 +08:00
|
|
|
YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
|
2015-07-14 02:07:26 +08:00
|
|
|
YamlObject.IsImmutable = MFI.isImmutableObjectIndex(I);
|
|
|
|
YamlObject.IsAliased = MFI.isAliasedObjectIndex(I);
|
2016-12-01 07:48:50 +08:00
|
|
|
YMF.FixedStackObjects.push_back(YamlObject);
|
2015-07-17 07:37:45 +08:00
|
|
|
StackObjectOperandMapping.insert(
|
2019-02-23 03:30:38 +08:00
|
|
|
std::make_pair(I, FrameIndexOperand::createFixed(ID)));
|
2015-07-14 02:07:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Process ordinary stack objects.
|
|
|
|
ID = 0;
|
2019-02-23 03:30:38 +08:00
|
|
|
for (int I = 0, E = MFI.getObjectIndexEnd(); I < E; ++I, ++ID) {
|
2015-07-11 02:13:57 +08:00
|
|
|
if (MFI.isDeadObjectIndex(I))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
yaml::MachineStackObject YamlObject;
|
2015-07-17 07:37:45 +08:00
|
|
|
YamlObject.ID = ID;
|
2015-07-16 06:14:49 +08:00
|
|
|
if (const auto *Alloca = MFI.getObjectAllocation(I))
|
2020-01-29 03:23:46 +08:00
|
|
|
YamlObject.Name.Value = std::string(
|
|
|
|
Alloca->hasName() ? Alloca->getName() : "<unnamed alloca>");
|
2015-07-11 02:13:57 +08:00
|
|
|
YamlObject.Type = MFI.isSpillSlotObjectIndex(I)
|
|
|
|
? yaml::MachineStackObject::SpillSlot
|
2015-07-14 08:26:26 +08:00
|
|
|
: MFI.isVariableSizedObjectIndex(I)
|
|
|
|
? yaml::MachineStackObject::VariableSized
|
|
|
|
: yaml::MachineStackObject::DefaultType;
|
2015-07-11 02:13:57 +08:00
|
|
|
YamlObject.Offset = MFI.getObjectOffset(I);
|
|
|
|
YamlObject.Size = MFI.getObjectSize(I);
|
2020-04-01 17:25:48 +08:00
|
|
|
YamlObject.Alignment = MFI.getObjectAlign(I);
|
2019-06-17 17:13:29 +08:00
|
|
|
YamlObject.StackID = (TargetStackID::Value)MFI.getStackID(I);
|
2015-07-11 02:13:57 +08:00
|
|
|
|
2016-12-01 07:48:50 +08:00
|
|
|
YMF.StackObjects.push_back(YamlObject);
|
2015-07-17 07:37:45 +08:00
|
|
|
StackObjectOperandMapping.insert(std::make_pair(
|
2019-02-23 03:30:38 +08:00
|
|
|
I, FrameIndexOperand::create(YamlObject.Name.Value, ID)));
|
2015-07-11 02:13:57 +08:00
|
|
|
}
|
2015-07-25 06:22:50 +08:00
|
|
|
|
|
|
|
for (const auto &CSInfo : MFI.getCalleeSavedInfo()) {
|
2019-05-28 21:08:31 +08:00
|
|
|
if (!CSInfo.isSpilledToReg() && MFI.isDeadObjectIndex(CSInfo.getFrameIdx()))
|
|
|
|
continue;
|
|
|
|
|
2015-07-25 06:22:50 +08:00
|
|
|
yaml::StringValue Reg;
|
2017-11-28 20:42:37 +08:00
|
|
|
printRegMIR(CSInfo.getReg(), Reg, TRI);
|
2018-11-10 00:36:24 +08:00
|
|
|
if (!CSInfo.isSpilledToReg()) {
|
|
|
|
auto StackObjectInfo = StackObjectOperandMapping.find(CSInfo.getFrameIdx());
|
|
|
|
assert(StackObjectInfo != StackObjectOperandMapping.end() &&
|
|
|
|
"Invalid stack object index");
|
|
|
|
const FrameIndexOperand &StackObject = StackObjectInfo->second;
|
|
|
|
if (StackObject.IsFixed) {
|
|
|
|
YMF.FixedStackObjects[StackObject.ID].CalleeSavedRegister = Reg;
|
|
|
|
YMF.FixedStackObjects[StackObject.ID].CalleeSavedRestored =
|
|
|
|
CSInfo.isRestored();
|
|
|
|
} else {
|
|
|
|
YMF.StackObjects[StackObject.ID].CalleeSavedRegister = Reg;
|
|
|
|
YMF.StackObjects[StackObject.ID].CalleeSavedRestored =
|
|
|
|
CSInfo.isRestored();
|
|
|
|
}
|
2017-09-29 02:52:14 +08:00
|
|
|
}
|
2015-07-25 06:22:50 +08:00
|
|
|
}
|
2015-08-18 06:17:42 +08:00
|
|
|
for (unsigned I = 0, E = MFI.getLocalFrameObjectCount(); I < E; ++I) {
|
|
|
|
auto LocalObject = MFI.getLocalFrameObjectMap(I);
|
|
|
|
auto StackObjectInfo = StackObjectOperandMapping.find(LocalObject.first);
|
|
|
|
assert(StackObjectInfo != StackObjectOperandMapping.end() &&
|
|
|
|
"Invalid stack object index");
|
|
|
|
const FrameIndexOperand &StackObject = StackObjectInfo->second;
|
|
|
|
assert(!StackObject.IsFixed && "Expected a locally mapped stack object");
|
2016-12-01 07:48:50 +08:00
|
|
|
YMF.StackObjects[StackObject.ID].LocalOffset = LocalObject.second;
|
2015-08-18 06:17:42 +08:00
|
|
|
}
|
2015-08-19 06:26:26 +08:00
|
|
|
|
|
|
|
// Print the stack object references in the frame information class after
|
|
|
|
// converting the stack objects.
|
|
|
|
if (MFI.hasStackProtectorIndex()) {
|
2016-12-01 07:48:50 +08:00
|
|
|
raw_string_ostream StrOS(YMF.FrameInfo.StackProtector.Value);
|
2015-08-19 06:26:26 +08:00
|
|
|
MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
|
|
|
|
.printStackObjectReference(MFI.getStackProtectorIndex());
|
|
|
|
}
|
2015-08-19 08:13:25 +08:00
|
|
|
|
|
|
|
// Print the debug variable information.
|
2016-12-01 07:48:50 +08:00
|
|
|
for (const MachineFunction::VariableDbgInfo &DebugVar :
|
|
|
|
MF.getVariableDbgInfo()) {
|
2015-08-19 08:13:25 +08:00
|
|
|
auto StackObjectInfo = StackObjectOperandMapping.find(DebugVar.Slot);
|
|
|
|
assert(StackObjectInfo != StackObjectOperandMapping.end() &&
|
|
|
|
"Invalid stack object index");
|
|
|
|
const FrameIndexOperand &StackObject = StackObjectInfo->second;
|
2018-04-26 02:58:06 +08:00
|
|
|
if (StackObject.IsFixed) {
|
|
|
|
auto &Object = YMF.FixedStackObjects[StackObject.ID];
|
|
|
|
printStackObjectDbgInfo(DebugVar, Object, MST);
|
|
|
|
} else {
|
|
|
|
auto &Object = YMF.StackObjects[StackObject.ID];
|
|
|
|
printStackObjectDbgInfo(DebugVar, Object, MST);
|
2015-08-19 08:13:25 +08:00
|
|
|
}
|
|
|
|
}
|
2015-07-11 02:13:57 +08:00
|
|
|
}
|
|
|
|
|
2019-06-27 15:48:06 +08:00
|
|
|
void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
ModuleSlotTracker &MST) {
|
|
|
|
const auto *TRI = MF.getSubtarget().getRegisterInfo();
|
|
|
|
for (auto CSInfo : MF.getCallSitesInfo()) {
|
|
|
|
yaml::CallSiteInfo YmlCS;
|
|
|
|
yaml::CallSiteInfo::MachineInstrLoc CallLocation;
|
|
|
|
|
|
|
|
// Prepare instruction position.
|
2019-08-19 20:41:22 +08:00
|
|
|
MachineBasicBlock::const_instr_iterator CallI = CSInfo.first->getIterator();
|
2019-06-27 15:48:06 +08:00
|
|
|
CallLocation.BlockNum = CallI->getParent()->getNumber();
|
|
|
|
// Get call instruction offset from the beginning of block.
|
2019-08-19 20:41:22 +08:00
|
|
|
CallLocation.Offset =
|
|
|
|
std::distance(CallI->getParent()->instr_begin(), CallI);
|
2019-06-27 15:48:06 +08:00
|
|
|
YmlCS.CallLocation = CallLocation;
|
|
|
|
// Construct call arguments and theirs forwarding register info.
|
|
|
|
for (auto ArgReg : CSInfo.second) {
|
|
|
|
yaml::CallSiteInfo::ArgRegPair YmlArgReg;
|
|
|
|
YmlArgReg.ArgNo = ArgReg.ArgNo;
|
|
|
|
printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI);
|
|
|
|
YmlCS.ArgForwardingRegs.emplace_back(YmlArgReg);
|
|
|
|
}
|
|
|
|
YMF.CallSitesInfo.push_back(YmlCS);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort call info by position of call instructions.
|
|
|
|
llvm::sort(YMF.CallSitesInfo.begin(), YMF.CallSitesInfo.end(),
|
|
|
|
[](yaml::CallSiteInfo A, yaml::CallSiteInfo B) {
|
|
|
|
if (A.CallLocation.BlockNum == B.CallLocation.BlockNum)
|
|
|
|
return A.CallLocation.Offset < B.CallLocation.Offset;
|
|
|
|
return A.CallLocation.BlockNum < B.CallLocation.BlockNum;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-07-21 04:51:18 +08:00
|
|
|
void MIRPrinter::convert(yaml::MachineFunction &MF,
|
|
|
|
const MachineConstantPool &ConstantPool) {
|
|
|
|
unsigned ID = 0;
|
|
|
|
for (const MachineConstantPoolEntry &Constant : ConstantPool.getConstants()) {
|
|
|
|
std::string Str;
|
|
|
|
raw_string_ostream StrOS(Str);
|
2017-08-02 19:09:30 +08:00
|
|
|
if (Constant.isMachineConstantPoolEntry()) {
|
|
|
|
Constant.Val.MachineCPVal->print(StrOS);
|
|
|
|
} else {
|
|
|
|
Constant.Val.ConstVal->printAsOperand(StrOS);
|
|
|
|
}
|
|
|
|
|
|
|
|
yaml::MachineConstantPoolValue YamlConstant;
|
2015-07-21 04:51:18 +08:00
|
|
|
YamlConstant.ID = ID++;
|
|
|
|
YamlConstant.Value = StrOS.str();
|
2020-04-01 17:25:48 +08:00
|
|
|
YamlConstant.Alignment = MaybeAlign(Constant.getAlignment());
|
2017-08-02 19:09:30 +08:00
|
|
|
YamlConstant.IsTargetSpecific = Constant.isMachineConstantPoolEntry();
|
|
|
|
|
2015-07-21 04:51:18 +08:00
|
|
|
MF.Constants.push_back(YamlConstant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-16 07:31:07 +08:00
|
|
|
void MIRPrinter::convert(ModuleSlotTracker &MST,
|
|
|
|
yaml::MachineJumpTable &YamlJTI,
|
|
|
|
const MachineJumpTableInfo &JTI) {
|
|
|
|
YamlJTI.Kind = JTI.getEntryKind();
|
|
|
|
unsigned ID = 0;
|
|
|
|
for (const auto &Table : JTI.getJumpTables()) {
|
|
|
|
std::string Str;
|
|
|
|
yaml::MachineJumpTable::Entry Entry;
|
|
|
|
Entry.ID = ID++;
|
|
|
|
for (const auto *MBB : Table.MBBs) {
|
|
|
|
raw_string_ostream StrOS(Str);
|
2017-12-05 01:18:51 +08:00
|
|
|
StrOS << printMBBReference(*MBB);
|
2015-07-16 07:31:07 +08:00
|
|
|
Entry.Blocks.push_back(StrOS.str());
|
|
|
|
Str.clear();
|
|
|
|
}
|
|
|
|
YamlJTI.Entries.push_back(Entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-14 07:10:16 +08:00
|
|
|
void MIRPrinter::initRegisterMaskIds(const MachineFunction &MF) {
|
|
|
|
const auto *TRI = MF.getSubtarget().getRegisterInfo();
|
|
|
|
unsigned I = 0;
|
|
|
|
for (const uint32_t *Mask : TRI->getRegMasks())
|
|
|
|
RegisterMaskIds.insert(std::make_pair(Mask, I++));
|
|
|
|
}
|
|
|
|
|
2017-05-06 05:09:30 +08:00
|
|
|
void llvm::guessSuccessors(const MachineBasicBlock &MBB,
|
|
|
|
SmallVectorImpl<MachineBasicBlock*> &Result,
|
|
|
|
bool &IsFallthrough) {
|
|
|
|
SmallPtrSet<MachineBasicBlock*,8> Seen;
|
|
|
|
|
|
|
|
for (const MachineInstr &MI : MBB) {
|
|
|
|
if (MI.isPHI())
|
|
|
|
continue;
|
|
|
|
for (const MachineOperand &MO : MI.operands()) {
|
|
|
|
if (!MO.isMBB())
|
|
|
|
continue;
|
|
|
|
MachineBasicBlock *Succ = MO.getMBB();
|
|
|
|
auto RP = Seen.insert(Succ);
|
|
|
|
if (RP.second)
|
|
|
|
Result.push_back(Succ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MachineBasicBlock::const_iterator I = MBB.getLastNonDebugInstr();
|
|
|
|
IsFallthrough = I == MBB.end() || !I->isBarrier();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MIPrinter::canPredictBranchProbabilities(const MachineBasicBlock &MBB) const {
|
|
|
|
if (MBB.succ_size() <= 1)
|
|
|
|
return true;
|
|
|
|
if (!MBB.hasSuccessorProbabilities())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
SmallVector<BranchProbability,8> Normalized(MBB.Probs.begin(),
|
|
|
|
MBB.Probs.end());
|
|
|
|
BranchProbability::normalizeProbabilities(Normalized.begin(),
|
|
|
|
Normalized.end());
|
|
|
|
SmallVector<BranchProbability,8> Equal(Normalized.size());
|
|
|
|
BranchProbability::normalizeProbabilities(Equal.begin(), Equal.end());
|
|
|
|
|
|
|
|
return std::equal(Normalized.begin(), Normalized.end(), Equal.begin());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MIPrinter::canPredictSuccessors(const MachineBasicBlock &MBB) const {
|
|
|
|
SmallVector<MachineBasicBlock*,8> GuessedSuccs;
|
|
|
|
bool GuessedFallthrough;
|
|
|
|
guessSuccessors(MBB, GuessedSuccs, GuessedFallthrough);
|
|
|
|
if (GuessedFallthrough) {
|
|
|
|
const MachineFunction &MF = *MBB.getParent();
|
|
|
|
MachineFunction::const_iterator NextI = std::next(MBB.getIterator());
|
|
|
|
if (NextI != MF.end()) {
|
|
|
|
MachineBasicBlock *Next = const_cast<MachineBasicBlock*>(&*NextI);
|
|
|
|
if (!is_contained(GuessedSuccs, Next))
|
|
|
|
GuessedSuccs.push_back(Next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (GuessedSuccs.size() != MBB.succ_size())
|
|
|
|
return false;
|
|
|
|
return std::equal(MBB.succ_begin(), MBB.succ_end(), GuessedSuccs.begin());
|
|
|
|
}
|
|
|
|
|
2015-08-14 07:10:16 +08:00
|
|
|
void MIPrinter::print(const MachineBasicBlock &MBB) {
|
2015-06-27 00:46:11 +08:00
|
|
|
assert(MBB.getNumber() >= 0 && "Invalid MBB number");
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << "bb." << MBB.getNumber();
|
|
|
|
bool HasAttributes = false;
|
2015-07-28 06:42:41 +08:00
|
|
|
if (const auto *BB = MBB.getBasicBlock()) {
|
|
|
|
if (BB->hasName()) {
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << "." << BB->getName();
|
2015-07-28 06:42:41 +08:00
|
|
|
} else {
|
2015-08-14 07:10:16 +08:00
|
|
|
HasAttributes = true;
|
|
|
|
OS << " (";
|
2015-07-28 06:42:41 +08:00
|
|
|
int Slot = MST.getLocalSlot(BB);
|
|
|
|
if (Slot == -1)
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << "<ir-block badref>";
|
2015-07-28 06:42:41 +08:00
|
|
|
else
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << (Twine("%ir-block.") + Twine(Slot)).str();
|
2015-07-28 06:42:41 +08:00
|
|
|
}
|
|
|
|
}
|
2015-08-14 07:10:16 +08:00
|
|
|
if (MBB.hasAddressTaken()) {
|
|
|
|
OS << (HasAttributes ? ", " : " (");
|
|
|
|
OS << "address-taken";
|
|
|
|
HasAttributes = true;
|
|
|
|
}
|
2015-08-28 07:27:47 +08:00
|
|
|
if (MBB.isEHPad()) {
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << (HasAttributes ? ", " : " (");
|
|
|
|
OS << "landing-pad";
|
|
|
|
HasAttributes = true;
|
2015-07-01 02:16:42 +08:00
|
|
|
}
|
2020-03-21 05:06:27 +08:00
|
|
|
if (MBB.isEHFuncletEntry()) {
|
|
|
|
OS << (HasAttributes ? ", " : " (");
|
|
|
|
OS << "ehfunclet-entry";
|
|
|
|
HasAttributes = true;
|
|
|
|
}
|
[Alignment][NFC] Deprecate Align::None()
Summary:
This is a follow up on https://reviews.llvm.org/D71473#inline-647262.
There's a caveat here that `Align(1)` relies on the compiler understanding of `Log2_64` implementation to produce good code. One could use `Align()` as a replacement but I believe it is less clear that the alignment is one in that case.
Reviewers: xbolva00, courbet, bollu
Subscribers: arsenm, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, hiraditya, kbarton, jrtc27, atanasyan, jsji, Jim, kerbowa, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73099
2020-01-21 22:00:04 +08:00
|
|
|
if (MBB.getAlignment() != Align(1)) {
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << (HasAttributes ? ", " : " (");
|
[Alignment][NFC] Remove LogAlignment functions
Summary:
This is patch is part of a series to introduce an Alignment type.
See this thread for context: http://lists.llvm.org/pipermail/llvm-dev/2019-July/133851.html
See this patch for the introduction of the type: https://reviews.llvm.org/D64790
Reviewers: courbet
Subscribers: arsenm, sdardis, nemanjai, jvesely, nhaehnle, hiraditya, kbarton, jrtc27, MaskRay, atanasyan, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67620
llvm-svn: 372231
2019-09-18 23:49:49 +08:00
|
|
|
OS << "align " << MBB.getAlignment().value();
|
2015-08-14 07:10:16 +08:00
|
|
|
HasAttributes = true;
|
2015-07-31 00:54:38 +08:00
|
|
|
}
|
2020-03-17 06:56:02 +08:00
|
|
|
if (MBB.getSectionType() != MBBS_None) {
|
|
|
|
OS << (HasAttributes ? ", " : " (");
|
|
|
|
OS << "bbsections ";
|
|
|
|
switch (MBB.getSectionType()) {
|
|
|
|
case MBBS_Entry:
|
|
|
|
OS << "Entry";
|
|
|
|
break;
|
|
|
|
case MBBS_Exception:
|
|
|
|
OS << "Exception";
|
|
|
|
break;
|
|
|
|
case MBBS_Cold:
|
|
|
|
OS << "Cold";
|
|
|
|
break;
|
|
|
|
case MBBS_Unique:
|
|
|
|
OS << "Unique";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
llvm_unreachable("No such section type");
|
|
|
|
}
|
|
|
|
HasAttributes = true;
|
|
|
|
}
|
2015-08-14 07:10:16 +08:00
|
|
|
if (HasAttributes)
|
|
|
|
OS << ")";
|
|
|
|
OS << ":\n";
|
|
|
|
|
|
|
|
bool HasLineAttributes = false;
|
|
|
|
// Print the successors
|
2017-05-06 05:09:30 +08:00
|
|
|
bool canPredictProbs = canPredictBranchProbabilities(MBB);
|
2017-09-20 07:34:12 +08:00
|
|
|
// Even if the list of successors is empty, if we cannot guess it,
|
|
|
|
// we need to print it to tell the parser that the list is empty.
|
|
|
|
// This is needed, because MI model unreachable as empty blocks
|
|
|
|
// with an empty successor list. If the parser would see that
|
|
|
|
// without the successor list, it would guess the code would
|
|
|
|
// fallthrough.
|
|
|
|
if ((!MBB.succ_empty() && !SimplifyMIR) || !canPredictProbs ||
|
|
|
|
!canPredictSuccessors(MBB)) {
|
2015-08-14 07:10:16 +08:00
|
|
|
OS.indent(2) << "successors: ";
|
|
|
|
for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) {
|
|
|
|
if (I != MBB.succ_begin())
|
|
|
|
OS << ", ";
|
2017-12-05 01:18:51 +08:00
|
|
|
OS << printMBBReference(**I);
|
2017-05-06 05:09:30 +08:00
|
|
|
if (!SimplifyMIR || !canPredictProbs)
|
2016-11-19 03:37:24 +08:00
|
|
|
OS << '('
|
|
|
|
<< format("0x%08" PRIx32, MBB.getSuccProbability(I).getNumerator())
|
|
|
|
<< ')';
|
2015-08-14 07:10:16 +08:00
|
|
|
}
|
|
|
|
OS << "\n";
|
|
|
|
HasLineAttributes = true;
|
|
|
|
}
|
|
|
|
|
2015-07-15 05:24:41 +08:00
|
|
|
// Print the live in registers.
|
2017-01-06 04:01:19 +08:00
|
|
|
const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
|
|
|
|
if (MRI.tracksLiveness() && !MBB.livein_empty()) {
|
|
|
|
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
|
2015-08-14 07:10:16 +08:00
|
|
|
OS.indent(2) << "liveins: ";
|
2015-08-25 06:59:52 +08:00
|
|
|
bool First = true;
|
2015-09-10 02:08:03 +08:00
|
|
|
for (const auto &LI : MBB.liveins()) {
|
2015-08-25 06:59:52 +08:00
|
|
|
if (!First)
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << ", ";
|
2015-08-25 06:59:52 +08:00
|
|
|
First = false;
|
2017-12-01 00:12:24 +08:00
|
|
|
OS << printReg(LI.PhysReg, &TRI);
|
2016-12-15 22:36:06 +08:00
|
|
|
if (!LI.LaneMask.all())
|
2016-10-13 05:06:45 +08:00
|
|
|
OS << ":0x" << PrintLaneMask(LI.LaneMask);
|
2015-08-14 07:10:16 +08:00
|
|
|
}
|
|
|
|
OS << "\n";
|
|
|
|
HasLineAttributes = true;
|
2015-07-15 05:24:41 +08:00
|
|
|
}
|
2015-08-14 07:10:16 +08:00
|
|
|
|
|
|
|
if (HasLineAttributes)
|
|
|
|
OS << "\n";
|
2015-08-15 02:57:24 +08:00
|
|
|
bool IsInBundle = false;
|
|
|
|
for (auto I = MBB.instr_begin(), E = MBB.instr_end(); I != E; ++I) {
|
|
|
|
const MachineInstr &MI = *I;
|
|
|
|
if (IsInBundle && !MI.isInsideBundle()) {
|
|
|
|
OS.indent(2) << "}\n";
|
|
|
|
IsInBundle = false;
|
|
|
|
}
|
|
|
|
OS.indent(IsInBundle ? 4 : 2);
|
2015-08-14 07:10:16 +08:00
|
|
|
print(MI);
|
2015-08-15 02:57:24 +08:00
|
|
|
if (!IsInBundle && MI.getFlag(MachineInstr::BundledSucc)) {
|
|
|
|
OS << " {";
|
|
|
|
IsInBundle = true;
|
|
|
|
}
|
2015-08-14 07:10:16 +08:00
|
|
|
OS << "\n";
|
2015-06-23 01:02:30 +08:00
|
|
|
}
|
2015-08-15 02:57:24 +08:00
|
|
|
if (IsInBundle)
|
|
|
|
OS.indent(2) << "}\n";
|
2015-06-23 01:02:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MIPrinter::print(const MachineInstr &MI) {
|
2017-10-11 07:50:49 +08:00
|
|
|
const auto *MF = MI.getMF();
|
2016-03-08 05:57:52 +08:00
|
|
|
const auto &MRI = MF->getRegInfo();
|
|
|
|
const auto &SubTarget = MF->getSubtarget();
|
2015-06-24 00:35:26 +08:00
|
|
|
const auto *TRI = SubTarget.getRegisterInfo();
|
|
|
|
assert(TRI && "Expected target register info");
|
2015-06-23 01:02:30 +08:00
|
|
|
const auto *TII = SubTarget.getInstrInfo();
|
|
|
|
assert(TII && "Expected target instruction info");
|
2015-07-22 06:28:27 +08:00
|
|
|
if (MI.isCFIInstruction())
|
|
|
|
assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
|
2015-06-23 01:02:30 +08:00
|
|
|
|
2016-09-12 19:20:10 +08:00
|
|
|
SmallBitVector PrintedTypes(8);
|
2017-12-07 18:40:31 +08:00
|
|
|
bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies();
|
2015-06-24 00:35:26 +08:00
|
|
|
unsigned I = 0, E = MI.getNumOperands();
|
|
|
|
for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
|
|
|
|
!MI.getOperand(I).isImplicit();
|
|
|
|
++I) {
|
|
|
|
if (I)
|
|
|
|
OS << ", ";
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
print(MI, I, TRI, TII, ShouldPrintRegisterTies,
|
2017-12-07 18:40:31 +08:00
|
|
|
MI.getTypeToPrint(I, PrintedTypes, MRI),
|
|
|
|
/*PrintDef=*/false);
|
2015-06-24 00:35:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (I)
|
|
|
|
OS << " = ";
|
2015-07-17 08:24:15 +08:00
|
|
|
if (MI.getFlag(MachineInstr::FrameSetup))
|
|
|
|
OS << "frame-setup ";
|
2018-03-14 03:53:16 +08:00
|
|
|
if (MI.getFlag(MachineInstr::FrameDestroy))
|
2018-01-09 19:33:22 +08:00
|
|
|
OS << "frame-destroy ";
|
2018-05-03 08:07:56 +08:00
|
|
|
if (MI.getFlag(MachineInstr::FmNoNans))
|
|
|
|
OS << "nnan ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmNoInfs))
|
|
|
|
OS << "ninf ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmNsz))
|
|
|
|
OS << "nsz ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmArcp))
|
|
|
|
OS << "arcp ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmContract))
|
|
|
|
OS << "contract ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmAfn))
|
|
|
|
OS << "afn ";
|
|
|
|
if (MI.getFlag(MachineInstr::FmReassoc))
|
|
|
|
OS << "reassoc ";
|
2018-09-12 05:35:32 +08:00
|
|
|
if (MI.getFlag(MachineInstr::NoUWrap))
|
|
|
|
OS << "nuw ";
|
|
|
|
if (MI.getFlag(MachineInstr::NoSWrap))
|
|
|
|
OS << "nsw ";
|
|
|
|
if (MI.getFlag(MachineInstr::IsExact))
|
|
|
|
OS << "exact ";
|
2020-01-10 22:31:10 +08:00
|
|
|
if (MI.getFlag(MachineInstr::NoFPExcept))
|
|
|
|
OS << "nofpexcept ";
|
2018-01-09 19:33:22 +08:00
|
|
|
|
2015-06-23 01:02:30 +08:00
|
|
|
OS << TII->getName(MI.getOpcode());
|
2015-06-24 00:35:26 +08:00
|
|
|
if (I < E)
|
|
|
|
OS << ' ';
|
|
|
|
|
|
|
|
bool NeedComma = false;
|
|
|
|
for (; I < E; ++I) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ", ";
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
print(MI, I, TRI, TII, ShouldPrintRegisterTies,
|
2017-12-07 18:40:31 +08:00
|
|
|
MI.getTypeToPrint(I, PrintedTypes, MRI));
|
2015-06-24 00:35:26 +08:00
|
|
|
NeedComma = true;
|
|
|
|
}
|
2015-07-23 05:15:11 +08:00
|
|
|
|
[x86/MIR] Implement support for pre- and post-instruction symbols, as
well as MIR parsing support for `MCSymbol` `MachineOperand`s.
The only real way to test pre- and post-instruction symbol support is to
use them in operands, so I ended up implementing that within the patch
as well. I can split out the operand support if folks really want but it
doesn't really seem worth it.
The functional implementation of pre- and post-instruction symbols is
now *completely trivial*. Two tiny bits of code in the (misnamed)
AsmPrinter. It should be completely target independent as well. We emit
these exactly the same way as we emit basic block labels. Most of the
code here is to give full dumping, MIR printing, and MIR parsing support
so that we can write useful tests.
The MIR parsing of MC symbol operands still isn't 100%, as it forces the
symbols to be non-temporary and non-local symbols with names. However,
those names often can encode most (if not all) of the special semantics
desired, and unnamed symbols seem especially annoying to serialize and
de-serialize. While this isn't perfect or full support, it seems plenty
to write tests that exercise usage of these kinds of operands.
The MIR support for pre-and post-instruction symbols was quite
straightforward. I chose to print them out in an as-if-operand syntax
similar to debug locations as this seemed the cleanest way and let me
use nice introducer tokens rather than inventing more magic punctuation
like we use for memoperands.
However, supporting MIR-based parsing of these symbols caused me to
change the design of the symbol support to allow setting arbitrary
symbols. Without this, I don't see any reasonable way to test things
with MIR.
Differential Revision: https://reviews.llvm.org/D50833
llvm-svn: 339962
2018-08-17 07:11:05 +08:00
|
|
|
// Print any optional symbols attached to this instruction as-if they were
|
|
|
|
// operands.
|
|
|
|
if (MCSymbol *PreInstrSymbol = MI.getPreInstrSymbol()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ',';
|
|
|
|
OS << " pre-instr-symbol ";
|
|
|
|
MachineOperand::printSymbol(OS, *PreInstrSymbol);
|
|
|
|
NeedComma = true;
|
|
|
|
}
|
|
|
|
if (MCSymbol *PostInstrSymbol = MI.getPostInstrSymbol()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ',';
|
|
|
|
OS << " post-instr-symbol ";
|
|
|
|
MachineOperand::printSymbol(OS, *PostInstrSymbol);
|
|
|
|
NeedComma = true;
|
|
|
|
}
|
2019-11-06 02:54:50 +08:00
|
|
|
if (MDNode *HeapAllocMarker = MI.getHeapAllocMarker()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ',';
|
|
|
|
OS << " heap-alloc-marker ";
|
|
|
|
HeapAllocMarker->printAsOperand(OS, MST);
|
|
|
|
NeedComma = true;
|
|
|
|
}
|
[x86/MIR] Implement support for pre- and post-instruction symbols, as
well as MIR parsing support for `MCSymbol` `MachineOperand`s.
The only real way to test pre- and post-instruction symbol support is to
use them in operands, so I ended up implementing that within the patch
as well. I can split out the operand support if folks really want but it
doesn't really seem worth it.
The functional implementation of pre- and post-instruction symbols is
now *completely trivial*. Two tiny bits of code in the (misnamed)
AsmPrinter. It should be completely target independent as well. We emit
these exactly the same way as we emit basic block labels. Most of the
code here is to give full dumping, MIR printing, and MIR parsing support
so that we can write useful tests.
The MIR parsing of MC symbol operands still isn't 100%, as it forces the
symbols to be non-temporary and non-local symbols with names. However,
those names often can encode most (if not all) of the special semantics
desired, and unnamed symbols seem especially annoying to serialize and
de-serialize. While this isn't perfect or full support, it seems plenty
to write tests that exercise usage of these kinds of operands.
The MIR support for pre-and post-instruction symbols was quite
straightforward. I chose to print them out in an as-if-operand syntax
similar to debug locations as this seemed the cleanest way and let me
use nice introducer tokens rather than inventing more magic punctuation
like we use for memoperands.
However, supporting MIR-based parsing of these symbols caused me to
change the design of the symbol support to allow setting arbitrary
symbols. Without this, I don't see any reasonable way to test things
with MIR.
Differential Revision: https://reviews.llvm.org/D50833
llvm-svn: 339962
2018-08-17 07:11:05 +08:00
|
|
|
|
2020-04-07 01:57:21 +08:00
|
|
|
if (PrintLocations) {
|
|
|
|
if (const DebugLoc &DL = MI.getDebugLoc()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ',';
|
|
|
|
OS << " debug-location ";
|
|
|
|
DL->printAsOperand(OS, MST);
|
|
|
|
}
|
2015-07-23 05:15:11 +08:00
|
|
|
}
|
2015-08-04 07:08:19 +08:00
|
|
|
|
|
|
|
if (!MI.memoperands_empty()) {
|
|
|
|
OS << " :: ";
|
2017-12-16 06:22:58 +08:00
|
|
|
const LLVMContext &Context = MF->getFunction().getContext();
|
2018-03-15 05:52:13 +08:00
|
|
|
const MachineFrameInfo &MFI = MF->getFrameInfo();
|
2015-08-04 07:08:19 +08:00
|
|
|
bool NeedComma = false;
|
|
|
|
for (const auto *Op : MI.memoperands()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ", ";
|
2020-01-10 18:18:11 +08:00
|
|
|
Op->print(OS, MST, SSNs, Context, &MFI, TII);
|
2015-08-04 07:08:19 +08:00
|
|
|
NeedComma = true;
|
|
|
|
}
|
|
|
|
}
|
2015-06-24 00:35:26 +08:00
|
|
|
}
|
|
|
|
|
2015-07-17 07:37:45 +08:00
|
|
|
void MIPrinter::printStackObjectReference(int FrameIndex) {
|
|
|
|
auto ObjectInfo = StackObjectOperandMapping.find(FrameIndex);
|
|
|
|
assert(ObjectInfo != StackObjectOperandMapping.end() &&
|
|
|
|
"Invalid frame index");
|
|
|
|
const FrameIndexOperand &Operand = ObjectInfo->second;
|
2017-12-16 00:33:45 +08:00
|
|
|
MachineOperand::printStackObjectReference(OS, Operand.ID, Operand.IsFixed,
|
|
|
|
Operand.Name);
|
2015-07-17 07:37:45 +08:00
|
|
|
}
|
|
|
|
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
static std::string formatOperandComment(std::string Comment) {
|
|
|
|
if (Comment.empty())
|
|
|
|
return Comment;
|
|
|
|
return std::string(" /* " + Comment + " */");
|
|
|
|
}
|
|
|
|
|
2017-11-07 05:46:06 +08:00
|
|
|
void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx,
|
|
|
|
const TargetRegisterInfo *TRI,
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
const TargetInstrInfo *TII,
|
2017-11-07 05:46:06 +08:00
|
|
|
bool ShouldPrintRegisterTies, LLT TypeToPrint,
|
2017-12-07 18:40:31 +08:00
|
|
|
bool PrintDef) {
|
2017-11-07 05:46:06 +08:00
|
|
|
const MachineOperand &Op = MI.getOperand(OpIdx);
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
std::string MOComment = TII->createMIROperandComment(MI, Op, OpIdx);
|
|
|
|
|
2015-06-24 00:35:26 +08:00
|
|
|
switch (Op.getType()) {
|
2017-12-09 06:53:21 +08:00
|
|
|
case MachineOperand::MO_Immediate:
|
|
|
|
if (MI.isOperandSubregIdx(OpIdx)) {
|
2017-12-14 18:03:09 +08:00
|
|
|
MachineOperand::printTargetFlags(OS, Op);
|
2018-01-16 18:53:11 +08:00
|
|
|
MachineOperand::printSubRegIdx(OS, Op.getImm(), TRI);
|
2017-12-09 06:53:21 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
LLVM_FALLTHROUGH;
|
2017-12-08 19:40:06 +08:00
|
|
|
case MachineOperand::MO_Register:
|
2017-12-08 19:48:02 +08:00
|
|
|
case MachineOperand::MO_CImmediate:
|
2017-12-20 05:47:00 +08:00
|
|
|
case MachineOperand::MO_FPImmediate:
|
2017-12-13 18:30:45 +08:00
|
|
|
case MachineOperand::MO_MachineBasicBlock:
|
2017-12-13 18:30:51 +08:00
|
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
2017-12-13 18:30:59 +08:00
|
|
|
case MachineOperand::MO_TargetIndex:
|
2017-12-14 18:02:58 +08:00
|
|
|
case MachineOperand::MO_JumpTableIndex:
|
2017-12-14 18:03:09 +08:00
|
|
|
case MachineOperand::MO_ExternalSymbol:
|
2017-12-14 18:03:14 +08:00
|
|
|
case MachineOperand::MO_GlobalAddress:
|
2017-12-14 18:03:18 +08:00
|
|
|
case MachineOperand::MO_RegisterLiveOut:
|
2017-12-14 18:03:23 +08:00
|
|
|
case MachineOperand::MO_Metadata:
|
2017-12-20 00:51:52 +08:00
|
|
|
case MachineOperand::MO_MCSymbol:
|
2017-12-20 05:47:05 +08:00
|
|
|
case MachineOperand::MO_CFIIndex:
|
2017-12-20 05:47:10 +08:00
|
|
|
case MachineOperand::MO_IntrinsicID:
|
2017-12-20 05:47:14 +08:00
|
|
|
case MachineOperand::MO_Predicate:
|
2019-08-13 23:34:38 +08:00
|
|
|
case MachineOperand::MO_BlockAddress:
|
|
|
|
case MachineOperand::MO_ShuffleMask: {
|
2017-12-07 18:40:31 +08:00
|
|
|
unsigned TiedOperandIdx = 0;
|
2017-12-09 06:53:21 +08:00
|
|
|
if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef())
|
2017-12-07 18:40:31 +08:00
|
|
|
TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx);
|
|
|
|
const TargetIntrinsicInfo *TII = MI.getMF()->getTarget().getIntrinsicInfo();
|
2020-01-09 12:02:37 +08:00
|
|
|
Op.print(OS, MST, TypeToPrint, OpIdx, PrintDef, /*IsStandalone=*/false,
|
2018-01-19 01:59:06 +08:00
|
|
|
ShouldPrintRegisterTies, TiedOperandIdx, TRI, TII);
|
[MIR][ARM] MachineOperand comments
This adds infrastructure to print and parse MIR MachineOperand comments.
The motivation for the ARM backend is to print condition code names instead of
magic constants that are difficult to read (for human beings). For example,
instead of this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14, $noreg
t2Bcc %bb.4, 0, killed $cpsr
we now print this:
dead renamable $r2, $cpsr = tEOR killed renamable $r2, renamable $r1, 14 /* CC::always */, $noreg
t2Bcc %bb.4, 0 /* CC:eq */, killed $cpsr
This shows that MachineOperand comments are enclosed between /* and */. In this
example, the EOR instruction is not conditionally executed (i.e. it is "always
executed"), which is encoded by the 14 immediate machine operand. Thus, now
this machine operand has /* CC::always */ as a comment. The 0 on the next
conditional branch instruction represents the equal condition code, thus now
this operand has /* CC:eq */ as a comment.
As it is a comment, the MI lexer/parser completely ignores it. The benefit is
that this keeps the change in the lexer extremely minimal and no target
specific parsing needs to be done. The changes on the MIPrinter side are also
minimal, as there is only one target hooks that is used to create the machine
operand comments.
Differential Revision: https://reviews.llvm.org/D74306
2020-02-24 22:19:21 +08:00
|
|
|
OS << formatOperandComment(MOComment);
|
2015-06-24 00:35:26 +08:00
|
|
|
break;
|
2017-10-25 02:04:54 +08:00
|
|
|
}
|
2015-07-17 07:37:45 +08:00
|
|
|
case MachineOperand::MO_FrameIndex:
|
|
|
|
printStackObjectReference(Op.getIndex());
|
|
|
|
break;
|
2015-06-30 00:57:06 +08:00
|
|
|
case MachineOperand::MO_RegisterMask: {
|
|
|
|
auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask());
|
|
|
|
if (RegMaskInfo != RegisterMaskIds.end())
|
|
|
|
OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower();
|
|
|
|
else
|
2017-03-19 16:14:18 +08:00
|
|
|
printCustomRegMask(Op.getRegMask(), OS, TRI);
|
2015-06-30 00:57:06 +08:00
|
|
|
break;
|
|
|
|
}
|
2015-06-24 00:35:26 +08:00
|
|
|
}
|
2015-06-20 01:43:07 +08:00
|
|
|
}
|
|
|
|
|
2020-01-09 12:02:37 +08:00
|
|
|
void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V,
|
|
|
|
ModuleSlotTracker &MST) {
|
|
|
|
if (isa<GlobalValue>(V)) {
|
|
|
|
V.printAsOperand(OS, /*PrintType=*/false, MST);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isa<Constant>(V)) {
|
|
|
|
// Machine memory operands can load/store to/from constant value pointers.
|
|
|
|
OS << '`';
|
|
|
|
V.printAsOperand(OS, /*PrintType=*/true, MST);
|
|
|
|
OS << '`';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
OS << "%ir.";
|
|
|
|
if (V.hasName()) {
|
|
|
|
printLLVMNameWithoutPrefix(OS, V.getName());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int Slot = MST.getCurrentFunction() ? MST.getLocalSlot(&V) : -1;
|
|
|
|
MachineOperand::printIRSlotNumber(OS, Slot);
|
|
|
|
}
|
|
|
|
|
2015-06-16 07:52:35 +08:00
|
|
|
void llvm::printMIR(raw_ostream &OS, const Module &M) {
|
|
|
|
yaml::Output Out(OS);
|
|
|
|
Out << const_cast<Module &>(M);
|
|
|
|
}
|
|
|
|
|
|
|
|
void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) {
|
|
|
|
MIRPrinter Printer(OS);
|
|
|
|
Printer.print(MF);
|
|
|
|
}
|