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"
|
2021-05-26 08:20:52 +08:00
|
|
|
#include "llvm/CodeGen/MachineModuleSlotTracker.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"
|
2021-05-26 08:20:52 +08:00
|
|
|
#include "llvm/CodeGen/TargetFrameLowering.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"
|
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);
|
2021-05-26 08:20:52 +08:00
|
|
|
void convertMachineMetadataNodes(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
MachineModuleSlotTracker &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());
|
2021-05-26 08:20:52 +08:00
|
|
|
MachineModuleSlotTracker MST(&MF);
|
2017-12-16 06:22:58 +08:00
|
|
|
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);
|
[DebugInfo][InstrRef][1/4] Support transformations that widen values
Very late in compilation, backends like X86 will perform optimisations like
this:
$cx = MOV16rm $rax, ...
->
$rcx = MOV64rm $rax, ...
Widening the load from 16 bits to 64 bits. SEeing how the lower 16 bits
remain the same, this doesn't affect execution. However, any debug
instruction reference to the defined operand now refers to a 64 bit value,
nto a 16 bit one, which might be unexpected. Elsewhere in codegen, there's
often this pattern:
CALL64pcrel32 @foo, implicit-def $rax
%0:gr64 = COPY $rax
%1:gr32 = COPY %0.sub_32bit
Where we want to refer to the definition of $eax by the call, but don't
want to refer the copies (they don't define values in the way
LiveDebugValues sees it). To solve this, add a subregister field to the
existing "substitutions" facility, so that we can describe a field within
a larger value definition. I would imagine that this would be used most
often when a value is widened, and we need to refer to the original,
narrower definition.
Differential Revision: https://reviews.llvm.org/D88891
2021-07-01 17:59:22 +08:00
|
|
|
for (const auto &Sub : MF.DebugValueSubstitutions) {
|
2021-07-09 22:32:30 +08:00
|
|
|
const auto &SubSrc = Sub.Src;
|
|
|
|
const auto &SubDest = Sub.Dest;
|
[DebugInfo][InstrRef][1/4] Support transformations that widen values
Very late in compilation, backends like X86 will perform optimisations like
this:
$cx = MOV16rm $rax, ...
->
$rcx = MOV64rm $rax, ...
Widening the load from 16 bits to 64 bits. SEeing how the lower 16 bits
remain the same, this doesn't affect execution. However, any debug
instruction reference to the defined operand now refers to a 64 bit value,
nto a 16 bit one, which might be unexpected. Elsewhere in codegen, there's
often this pattern:
CALL64pcrel32 @foo, implicit-def $rax
%0:gr64 = COPY $rax
%1:gr32 = COPY %0.sub_32bit
Where we want to refer to the definition of $eax by the call, but don't
want to refer the copies (they don't define values in the way
LiveDebugValues sees it). To solve this, add a subregister field to the
existing "substitutions" facility, so that we can describe a field within
a larger value definition. I would imagine that this would be used most
often when a value is widened, and we need to refer to the original,
narrower definition.
Differential Revision: https://reviews.llvm.org/D88891
2021-07-01 17:59:22 +08:00
|
|
|
YamlMF.DebugValueSubstitutions.push_back({SubSrc.first, SubSrc.second,
|
2021-07-09 22:32:30 +08:00
|
|
|
SubDest.first,
|
|
|
|
SubDest.second,
|
|
|
|
Sub.Subreg});
|
[DebugInfo][InstrRef][1/4] Support transformations that widen values
Very late in compilation, backends like X86 will perform optimisations like
this:
$cx = MOV16rm $rax, ...
->
$rcx = MOV64rm $rax, ...
Widening the load from 16 bits to 64 bits. SEeing how the lower 16 bits
remain the same, this doesn't affect execution. However, any debug
instruction reference to the defined operand now refers to a 64 bit value,
nto a 16 bit one, which might be unexpected. Elsewhere in codegen, there's
often this pattern:
CALL64pcrel32 @foo, implicit-def $rax
%0:gr64 = COPY $rax
%1:gr32 = COPY %0.sub_32bit
Where we want to refer to the definition of $eax by the call, but don't
want to refer the copies (they don't define values in the way
LiveDebugValues sees it). To solve this, add a subregister field to the
existing "substitutions" facility, so that we can describe a field within
a larger value definition. I would imagine that this would be used most
often when a value is widened, and we need to refer to the original,
narrower definition.
Differential Revision: https://reviews.llvm.org/D88891
2021-07-01 17:59:22 +08:00
|
|
|
}
|
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();
|
2021-05-26 08:20:52 +08:00
|
|
|
// Convert machine metadata collected during the print of the machine
|
|
|
|
// function.
|
|
|
|
convertMachineMetadataNodes(YamlMF, MF, MST);
|
|
|
|
|
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();
|
2021-03-22 00:00:55 +08:00
|
|
|
YamlMFI.HasTailCall = MFI.hasTailCall();
|
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();
|
2020-10-27 23:17:38 +08:00
|
|
|
|
2015-07-14 02:07:26 +08:00
|
|
|
// Process fixed stack objects.
|
2020-10-27 23:17:38 +08:00
|
|
|
assert(YMF.FixedStackObjects.empty());
|
|
|
|
SmallVector<int, 32> FixedStackObjectsIdx;
|
|
|
|
const int BeginIdx = MFI.getObjectIndexBegin();
|
|
|
|
if (BeginIdx < 0)
|
|
|
|
FixedStackObjectsIdx.reserve(-BeginIdx);
|
|
|
|
|
2015-07-11 02:13:57 +08:00
|
|
|
unsigned ID = 0;
|
2020-10-27 23:17:38 +08:00
|
|
|
for (int I = BeginIdx; I < 0; ++I, ++ID) {
|
|
|
|
FixedStackObjectsIdx.push_back(-1); // Fill index for possible dead.
|
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);
|
2020-10-27 23:17:38 +08:00
|
|
|
// Save the ID' position in FixedStackObjects storage vector.
|
|
|
|
FixedStackObjectsIdx[ID] = YMF.FixedStackObjects.size();
|
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.
|
2020-10-27 23:17:38 +08:00
|
|
|
assert(YMF.StackObjects.empty());
|
|
|
|
SmallVector<unsigned, 32> StackObjectsIdx;
|
|
|
|
const int EndIdx = MFI.getObjectIndexEnd();
|
|
|
|
if (EndIdx > 0)
|
|
|
|
StackObjectsIdx.reserve(EndIdx);
|
2015-07-14 02:07:26 +08:00
|
|
|
ID = 0;
|
2020-10-27 23:17:38 +08:00
|
|
|
for (int I = 0; I < EndIdx; ++I, ++ID) {
|
|
|
|
StackObjectsIdx.push_back(-1); // Fill index for possible dead.
|
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(
|
2020-12-29 00:41:25 +08:00
|
|
|
Alloca->hasName() ? Alloca->getName() : "");
|
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
|
|
|
|
2020-10-27 23:17:38 +08:00
|
|
|
// Save the ID' position in StackObjects storage vector.
|
|
|
|
StackObjectsIdx[ID] = YMF.StackObjects.size();
|
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()) {
|
2020-10-27 23:17:38 +08:00
|
|
|
const int FrameIdx = CSInfo.getFrameIdx();
|
|
|
|
if (!CSInfo.isSpilledToReg() && MFI.isDeadObjectIndex(FrameIdx))
|
2019-05-28 21:08:31 +08:00
|
|
|
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()) {
|
2020-10-27 23:17:38 +08:00
|
|
|
assert(FrameIdx >= MFI.getObjectIndexBegin() &&
|
|
|
|
FrameIdx < MFI.getObjectIndexEnd() &&
|
2018-11-10 00:36:24 +08:00
|
|
|
"Invalid stack object index");
|
2020-10-27 23:17:38 +08:00
|
|
|
if (FrameIdx < 0) { // Negative index means fixed objects.
|
|
|
|
auto &Object =
|
|
|
|
YMF.FixedStackObjects
|
|
|
|
[FixedStackObjectsIdx[FrameIdx + MFI.getNumFixedObjects()]];
|
|
|
|
Object.CalleeSavedRegister = Reg;
|
|
|
|
Object.CalleeSavedRestored = CSInfo.isRestored();
|
2018-11-10 00:36:24 +08:00
|
|
|
} else {
|
2020-10-27 23:17:38 +08:00
|
|
|
auto &Object = YMF.StackObjects[StackObjectsIdx[FrameIdx]];
|
|
|
|
Object.CalleeSavedRegister = Reg;
|
|
|
|
Object.CalleeSavedRestored = CSInfo.isRestored();
|
2018-11-10 00:36:24 +08:00
|
|
|
}
|
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);
|
2020-10-27 23:17:38 +08:00
|
|
|
assert(LocalObject.first >= 0 && "Expected a locally mapped stack object");
|
|
|
|
YMF.StackObjects[StackObjectsIdx[LocalObject.first]].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()) {
|
2020-10-27 23:17:38 +08:00
|
|
|
assert(DebugVar.Slot >= MFI.getObjectIndexBegin() &&
|
|
|
|
DebugVar.Slot < MFI.getObjectIndexEnd() &&
|
2015-08-19 08:13:25 +08:00
|
|
|
"Invalid stack object index");
|
2020-10-27 23:17:38 +08:00
|
|
|
if (DebugVar.Slot < 0) { // Negative index means fixed objects.
|
|
|
|
auto &Object =
|
|
|
|
YMF.FixedStackObjects[FixedStackObjectsIdx[DebugVar.Slot +
|
|
|
|
MFI.getNumFixedObjects()]];
|
2018-04-26 02:58:06 +08:00
|
|
|
printStackObjectDbgInfo(DebugVar, Object, MST);
|
|
|
|
} else {
|
2020-10-27 23:17:38 +08:00
|
|
|
auto &Object = YMF.StackObjects[StackObjectsIdx[DebugVar.Slot]];
|
2018-04-26 02:58:06 +08:00
|
|
|
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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-05-26 08:20:52 +08:00
|
|
|
void MIRPrinter::convertMachineMetadataNodes(yaml::MachineFunction &YMF,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
MachineModuleSlotTracker &MST) {
|
|
|
|
MachineModuleSlotTracker::MachineMDNodeListType MDList;
|
|
|
|
MST.collectMachineMDNodes(MDList);
|
|
|
|
for (auto &MD : MDList) {
|
|
|
|
std::string NS;
|
|
|
|
raw_string_ostream StrOS(NS);
|
|
|
|
MD.second->print(StrOS, MST, MF.getFunction().getParent());
|
|
|
|
YMF.MachineMetadataNodes.push_back(StrOS.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-05-13 00:43:24 +08:00
|
|
|
YamlConstant.Alignment = Constant.getAlign();
|
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");
|
2020-07-25 00:18:09 +08:00
|
|
|
MBB.printName(OS,
|
|
|
|
MachineBasicBlock::PrintNameIr |
|
|
|
|
MachineBasicBlock::PrintNameAttributes,
|
|
|
|
&MST);
|
2015-08-14 07:10:16 +08:00
|
|
|
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 ";
|
2020-05-30 03:15:07 +08:00
|
|
|
if (MI.getFlag(MachineInstr::NoMerge))
|
|
|
|
OS << "nomerge ";
|
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-10-14 17:47:44 +08:00
|
|
|
if (auto Num = MI.peekDebugInstrNum()) {
|
|
|
|
if (NeedComma)
|
|
|
|
OS << ',';
|
|
|
|
OS << " debug-instr-number " << Num;
|
|
|
|
NeedComma = true;
|
|
|
|
}
|
|
|
|
|
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] Add comments to INLINEASM immediate flag MachineOperands
Summary:
The INLINEASM MIR instructions use immediate operands to encode the values of some operands.
The MachineInstr pretty printer function already handles those operands and prints human readable annotations instead of the immediates. This patch adds similar annotations to the output of the MIRPrinter, however uses the new MIROperandComment feature.
Reviewers: SjoerdMeijer, arsenm, efriedma
Reviewed By: arsenm
Subscribers: qcolombet, sdardis, jvesely, wdng, nhaehnle, hiraditya, jrtc27, atanasyan, kerbowa, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78088
2020-04-14 15:24:40 +08:00
|
|
|
std::string MOComment = TII->createMIROperandComment(MI, Op, OpIdx, 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
|
|
|
|
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);
|
|
|
|
}
|