summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/CodeGen/AsmPrinter.h5
-rw-r--r--llvm/include/llvm/MC/MCAsmBackend.h42
-rw-r--r--llvm/include/llvm/MC/MCAssembler.h2
-rw-r--r--llvm/include/llvm/MC/MCCodePadder.h243
-rw-r--r--llvm/include/llvm/MC/MCFragment.h93
-rw-r--r--llvm/include/llvm/MC/MCObjectStreamer.h6
-rw-r--r--llvm/include/llvm/MC/MCStreamer.h7
7 files changed, 397 insertions, 1 deletions
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index d755f10b80f..e0788e02d51 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -58,6 +58,7 @@ class MachineModuleInfo;
class MachineOptimizationRemarkEmitter;
class MCAsmInfo;
class MCCFIInstruction;
+struct MCCodePaddingContext;
class MCContext;
class MCExpr;
class MCInst;
@@ -377,7 +378,7 @@ public:
virtual void EmitBasicBlockStart(const MachineBasicBlock &MBB) const;
/// Targets can override this to emit stuff at the end of a basic block.
- virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {}
+ virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB);
/// Targets should implement this to emit instructions.
virtual void EmitInstruction(const MachineInstr *) {
@@ -626,6 +627,8 @@ private:
/// Emit GlobalAlias or GlobalIFunc.
void emitGlobalIndirectSymbol(Module &M,
const GlobalIndirectSymbol& GIS);
+ void setupCodePaddingContext(const MachineBasicBlock &MBB,
+ MCCodePaddingContext &Context) const;
};
} // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h
index e756399720b..d6b9302c222 100644
--- a/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/llvm/include/llvm/MC/MCAsmBackend.h
@@ -15,17 +15,22 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFragment.h"
#include <cstdint>
+#include <memory>
namespace llvm {
class MCAsmLayout;
class MCAssembler;
class MCCFIInstruction;
+class MCCodePadder;
struct MCFixupKindInfo;
class MCFragment;
class MCInst;
+class MCObjectStreamer;
class MCObjectWriter;
+struct MCCodePaddingContext;
class MCRelaxableFragment;
class MCSubtargetInfo;
class MCValue;
@@ -33,8 +38,11 @@ class raw_pwrite_stream;
/// Generic interface to target specific assembler backends.
class MCAsmBackend {
+ std::unique_ptr<MCCodePadder> CodePadder;
+
protected: // Can only create subclasses.
MCAsmBackend();
+ MCAsmBackend(std::unique_ptr<MCCodePadder> TargetCodePadder);
public:
MCAsmBackend(const MCAsmBackend &) = delete;
@@ -133,6 +141,40 @@ public:
generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const {
return 0;
}
+
+ /// Handles all target related code padding when starting to write a new
+ /// basic block to an object file.
+ ///
+ /// \param OS The streamer used for writing the padding data and function.
+ /// \param Context the context of the padding, Embeds the basic block's
+ /// parameters.
+ void handleCodePaddingBasicBlockStart(MCObjectStreamer *OS,
+ const MCCodePaddingContext &Context);
+ /// Handles all target related code padding after writing a block to an object
+ /// file.
+ ///
+ /// \param Context the context of the padding, Embeds the basic block's
+ /// parameters.
+ void handleCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context);
+ /// Handles all target related code padding before writing a new instruction
+ /// to an object file.
+ ///
+ /// \param Inst the instruction.
+ void handleCodePaddingInstructionBegin(const MCInst &Inst);
+ /// Handles all target related code padding after writing an instruction to an
+ /// object file.
+ ///
+ /// \param Inst the instruction.
+ void handleCodePaddingInstructionEnd(const MCInst &Inst);
+
+ /// Relaxes a fragment (changes the size of the padding) according to target
+ /// requirements. The new size computation is done w.r.t a layout.
+ ///
+ /// \param Fragment The fragment to relax.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns true iff any relaxation occured.
+ bool relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout);
};
} // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 4f1b5a8b3d7..1ce6b09355d 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -183,6 +183,8 @@ private:
bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF);
+ bool relaxPaddingFragment(MCAsmLayout &Layout, MCPaddingFragment &PF);
+
bool relaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF);
bool relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF);
diff --git a/llvm/include/llvm/MC/MCCodePadder.h b/llvm/include/llvm/MC/MCCodePadder.h
new file mode 100644
index 00000000000..b590773d2ed
--- /dev/null
+++ b/llvm/include/llvm/MC/MCCodePadder.h
@@ -0,0 +1,243 @@
+//===- llvm/MC/CodePadder.h - MC Code Padder --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCCODEPADDER_H
+#define LLVM_MC_MCCODEPADDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class MCAsmLayout;
+class MCCodePaddingPolicy;
+class MCFragment;
+class MCInst;
+class MCObjectStreamer;
+class MCPaddingFragment;
+class MCSection;
+
+typedef SmallVector<const MCPaddingFragment *, 8> MCPFRange;
+
+struct MCCodePaddingContext {
+ bool IsPaddingActive;
+ bool IsBasicBlockInsideInnermostLoop;
+ bool IsBasicBlockReachableViaFallthrough;
+ bool IsBasicBlockReachableViaBranch;
+};
+
+/// Target-independent base class incharge of all code padding decisions for a
+/// target. During encoding it determines if and where MCPaddingFragments will
+/// be located, as later on, when layout information is available, it determines
+/// their sizes.
+class MCCodePadder {
+ MCCodePadder(const MCCodePadder &) = delete;
+ void operator=(const MCCodePadder &) = delete;
+
+ /// Determines if the MCCodePaddingPolicies are active.
+ bool ArePoliciesActive;
+
+ /// All the supported MCCodePaddingPolicies.
+ SmallPtrSet<MCCodePaddingPolicy *, 4> CodePaddingPolicies;
+
+ /// A pointer to the fragment of the instruction whose padding is currently
+ /// done for.
+ MCPaddingFragment *CurrHandledInstFragment;
+
+ /// A map holding the jurisdiction for each padding fragment. Key: padding
+ /// fragment. Value: The fragment's jurisdiction. A jurisdiction is a vector
+ /// of padding fragments whose conditions are being controlled by another
+ /// fragment, the key fragment.
+ DenseMap<MCPaddingFragment *, MCPFRange> FragmentToJurisdiction;
+ MCPFRange &getJurisdiction(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
+
+ /// A map holding the maximal instruction window size relevant for a padding
+ /// fragment.
+ DenseMap<MCPaddingFragment *, uint64_t> FragmentToMaxWindowSize;
+ uint64_t getMaxWindowSize(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
+
+protected:
+ /// The current streamer, used to stream code padding.
+ MCObjectStreamer *OS;
+
+ bool addPolicy(MCCodePaddingPolicy *Policy);
+
+ virtual bool
+ basicBlockRequiresInsertionPoint(const MCCodePaddingContext &Context) {
+ return false;
+ }
+
+ virtual bool instructionRequiresInsertionPoint(const MCInst &Inst) {
+ return false;
+ }
+
+ virtual bool usePoliciesForBasicBlock(const MCCodePaddingContext &Context) {
+ return Context.IsPaddingActive;
+ }
+
+public:
+ MCCodePadder()
+ : ArePoliciesActive(false), CurrHandledInstFragment(nullptr),
+ OS(nullptr) {}
+ virtual ~MCCodePadder();
+
+ /// Handles all target related code padding when starting to write a new
+ /// basic block to an object file.
+ ///
+ /// \param OS The streamer used for writing the padding data and function.
+ /// \param Context the context of the padding, Embeds the basic block's
+ /// parameters.
+ void handleBasicBlockStart(MCObjectStreamer *OS,
+ const MCCodePaddingContext &Context);
+ /// Handles all target related code padding when done writing a block to an
+ /// object file.
+ ///
+ /// \param Context the context of the padding, Embeds the basic block's
+ /// parameters.
+ void handleBasicBlockEnd(const MCCodePaddingContext &Context);
+ /// Handles all target related code padding before writing a new instruction
+ /// to an object file.
+ ///
+ /// \param Inst the instruction.
+ void handleInstructionBegin(const MCInst &Inst);
+ /// Handles all target related code padding after writing an instruction to an
+ /// object file.
+ ///
+ /// \param Inst the instruction.
+ void handleInstructionEnd(const MCInst &Inst);
+
+ /// Relaxes a fragment (changes the size of the padding) according to target
+ /// requirements. The new size computation is done w.r.t a layout.
+ ///
+ /// \param Fragment The fragment to relax.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns true iff any relaxation occured.
+ bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout);
+};
+
+/// The base class for all padding policies, i.e. a rule or set of rules to pad
+/// the generated code.
+class MCCodePaddingPolicy {
+ MCCodePaddingPolicy() = delete;
+ MCCodePaddingPolicy(const MCCodePaddingPolicy &) = delete;
+ void operator=(const MCCodePaddingPolicy &) = delete;
+
+protected:
+ /// A mask holding the kind of this policy, i.e. only the i'th bit will be set
+ /// where i is the kind number.
+ const uint64_t KindMask;
+ /// Instruction window size relevant to this policy.
+ const uint64_t WindowSize;
+ /// A boolean indicating which byte of the instruction determies its
+ /// instruction window. If true - the last byte of the instructions, o.w. -
+ /// the first byte of the instruction.
+ const bool InstByteIsLastByte;
+
+ MCCodePaddingPolicy(uint64_t Kind, uint64_t WindowSize,
+ bool InstByteIsLastByte)
+ : KindMask(UINT64_C(1) << Kind), WindowSize(WindowSize),
+ InstByteIsLastByte(InstByteIsLastByte) {}
+
+ /// Computes and returns the offset of the consecutive fragment of a given
+ /// fragment.
+ ///
+ /// \param Fragment The fragment whose consecutive offset will be computed.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns the offset of the consecutive fragment of \p Fragment.
+ static uint64_t getNextFragmentOffset(const MCFragment *Fragment,
+ const MCAsmLayout &Layout);
+ /// Returns the instruction byte of an instruction pointed by a given
+ /// MCPaddingFragment. An instruction byte is the address of the byte of an
+ /// instruction which determines its instruction window.
+ ///
+ /// \param Fragment The fragment pointing to the instruction.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns the instruction byte of an instruction pointed by \p Fragment.
+ uint64_t getFragmentInstByte(const MCPaddingFragment *Fragment,
+ MCAsmLayout &Layout) const;
+ uint64_t computeWindowEndAddress(const MCPaddingFragment *Fragment,
+ uint64_t Offset, MCAsmLayout &Layout) const;
+
+ /// Computes and returns the penalty weight of a first instruction window in a
+ /// range. This requires a special function since the first window does not
+ /// contain all the padding fragments in that window. It only contains all the
+ /// padding fragments starting from the relevant insertion point.
+ ///
+ /// \param Window The first window.
+ /// \param Offset The offset of the parent section relative to the beginning
+ /// of the file, mod the window size.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns the penalty weight of a first instruction window in a range, \p
+ /// Window.
+ double computeFirstWindowPenaltyWeight(const MCPFRange &Window,
+ uint64_t Offset,
+ MCAsmLayout &Layout) const;
+ /// Computes and returns the penalty caused by an instruction window.
+ ///
+ /// \param Window The instruction window.
+ /// \param Offset The offset of the parent section relative to the beginning
+ /// of the file, mod the window size.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns the penalty caused by \p Window.
+ virtual double computeWindowPenaltyWeight(const MCPFRange &Window,
+ uint64_t Offset,
+ MCAsmLayout &Layout) const = 0;
+
+public:
+ virtual ~MCCodePaddingPolicy() {}
+
+ /// Returns the kind mask of this policy - A mask holding the kind of this
+ /// policy, i.e. only the i'th bit will be set where i is the kind number.
+ uint64_t getKindMask() const { return KindMask; }
+ /// Returns the instruction window size relevant to this policy.
+ uint64_t getWindowSize() const { return WindowSize; }
+ /// Returns true if the last byte of an instruction determines its instruction
+ /// window, or false if the first of an instruction determines it.
+ bool isInstByteLastByte() const { return InstByteIsLastByte; }
+
+ /// Returns true iff this policy needs padding for a given basic block.
+ ///
+ /// \param Context the context of the padding, Embeds the basic block's
+ /// parameters.
+ ///
+ /// \returns true iff this policy needs padding for the basic block.
+ virtual bool
+ basicBlockRequiresPaddingFragment(const MCCodePaddingContext &Context) const {
+ return false;
+ }
+ /// Returns true iff this policy needs padding for a given instruction.
+ ///
+ /// \param Inst The given instruction.
+ ///
+ /// \returns true iff this policy needs padding for \p Inst.
+ virtual bool instructionRequiresPaddingFragment(const MCInst &Inst) const {
+ return false;
+ }
+ /// Computes and returns the penalty caused by a range of instruction windows.
+ /// The weight is computed for each window separelty and then accumulated.
+ ///
+ /// \param Range The range.
+ /// \param Offset The offset of the parent section relative to the beginning
+ /// of the file, mod the window size.
+ /// \param Layout Code layout information.
+ ///
+ /// \returns the penalty caused by \p Range.
+ double computeRangePenaltyWeight(const MCPFRange &Range, uint64_t Offset,
+ MCAsmLayout &Layout) const;
+};
+
+} // namespace llvm
+
+#endif // LLVM_MC_MCCODEPADDER_H
diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h
index 284ca50e19d..7c66b2126cd 100644
--- a/llvm/include/llvm/MC/MCFragment.h
+++ b/llvm/include/llvm/MC/MCFragment.h
@@ -41,6 +41,7 @@ public:
FT_Dwarf,
FT_DwarfFrame,
FT_LEB,
+ FT_Padding,
FT_SafeSEH,
FT_CVInlineLines,
FT_CVDefRange,
@@ -323,6 +324,98 @@ public:
}
};
+/// Fragment for adding required padding.
+/// This fragment is always inserted before an instruction, and holds that
+/// instruction as context information (as well as a mask of kinds) for
+/// determining the padding size.
+///
+class MCPaddingFragment : public MCFragment {
+ /// A mask containing all the kinds relevant to this fragment. i.e. the i'th
+ /// bit will be set iff kind i is relevant to this fragment.
+ uint64_t PaddingPoliciesMask;
+ /// A boolean indicating if this fragment will actually hold padding. If its
+ /// value is false, then this fragment serves only as a placeholder,
+ /// containing data to assist other insertion point in their decision making.
+ bool IsInsertionPoint;
+
+ uint64_t Size;
+
+ struct MCInstInfo {
+ bool IsInitialized;
+ MCInst Inst;
+ /// A boolean indicating whether the instruction pointed by this fragment is
+ /// a fixed size instruction or a relaxable instruction held by a
+ /// MCRelaxableFragment.
+ bool IsImmutableSizedInst;
+ union {
+ /// If the instruction is a fixed size instruction, hold its size.
+ size_t InstSize;
+ /// Otherwise, hold a pointer to the MCRelaxableFragment holding it.
+ MCRelaxableFragment *InstFragment;
+ };
+ };
+ MCInstInfo InstInfo;
+
+public:
+ static const uint64_t PFK_None = UINT64_C(0);
+
+ enum MCPaddingFragmentKind {
+ // values 0-7 are reserved for future target independet values.
+
+ FirstTargetPerfNopFragmentKind = 8,
+
+ /// Limit range of target MCPerfNopFragment kinds to fit in uint64_t
+ MaxTargetPerfNopFragmentKind = 63
+ };
+
+ MCPaddingFragment(MCSection *Sec = nullptr)
+ : MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None),
+ IsInsertionPoint(false), Size(UINT64_C(0)),
+ InstInfo({false, MCInst(), false, {0}}) {}
+
+ bool isInsertionPoint() const { return IsInsertionPoint; }
+ void setAsInsertionPoint() { IsInsertionPoint = true; }
+ uint64_t getPaddingPoliciesMask() const { return PaddingPoliciesMask; }
+ void setPaddingPoliciesMask(uint64_t Value) { PaddingPoliciesMask = Value; }
+ bool hasPaddingPolicy(uint64_t PolicyMask) const {
+ assert(isPowerOf2_64(PolicyMask) &&
+ "Policy mask must contain exactly one policy");
+ return (getPaddingPoliciesMask() & PolicyMask) != PFK_None;
+ }
+ const MCInst &getInst() const {
+ assert(isInstructionInitialized() && "Fragment has no instruction!");
+ return InstInfo.Inst;
+ }
+ size_t getInstSize() const {
+ assert(isInstructionInitialized() && "Fragment has no instruction!");
+ if (InstInfo.IsImmutableSizedInst)
+ return InstInfo.InstSize;
+ assert(InstInfo.InstFragment != nullptr &&
+ "Must have a valid InstFragment to retrieve InstSize from");
+ return InstInfo.InstFragment->getContents().size();
+ }
+ void setInstAndInstSize(const MCInst &Inst, size_t InstSize) {
+ InstInfo.IsInitialized = true;
+ InstInfo.IsImmutableSizedInst = true;
+ InstInfo.Inst = Inst;
+ InstInfo.InstSize = InstSize;
+ }
+ void setInstAndInstFragment(const MCInst &Inst,
+ MCRelaxableFragment *InstFragment) {
+ InstInfo.IsInitialized = true;
+ InstInfo.IsImmutableSizedInst = false;
+ InstInfo.Inst = Inst;
+ InstInfo.InstFragment = InstFragment;
+ }
+ uint64_t getSize() const { return Size; }
+ void setSize(uint64_t Value) { Size = Value; }
+ bool isInstructionInitialized() const { return InstInfo.IsInitialized; }
+
+ static bool classof(const MCFragment *F) {
+ return F->getKind() == MCFragment::FT_Padding;
+ }
+};
+
class MCFillFragment : public MCFragment {
/// Value to use for filling bytes.
uint8_t Value;
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index 183b6238f31..a3dbc56ebc1 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -47,6 +47,7 @@ class MCObjectStreamer : public MCStreamer {
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
MCSymbol *EmitCFILabel() override;
+ void EmitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
protected:
MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
@@ -76,6 +77,7 @@ public:
/// Get a data fragment to write into, creating a new one if the current
/// fragment is not a data fragment.
MCDataFragment *getOrCreateDataFragment();
+ MCPaddingFragment *getOrCreatePaddingFragment();
protected:
bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection);
@@ -121,6 +123,10 @@ public:
unsigned MaxBytesToEmit = 0) override;
void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
SMLoc Loc) override;
+ void
+ EmitCodePaddingBasicBlockStart(const MCCodePaddingContext &Context) override;
+ void
+ EmitCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context) override;
void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags,
unsigned Isa, unsigned Discriminator,
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 479a7e2a748..58003d7d596 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -38,6 +38,7 @@ class AssemblerConstantPools;
class formatted_raw_ostream;
class MCAsmBackend;
class MCCodeEmitter;
+struct MCCodePaddingContext;
class MCContext;
class MCExpr;
class MCInst;
@@ -716,6 +717,12 @@ public:
virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value,
SMLoc Loc);
+ virtual void
+ EmitCodePaddingBasicBlockStart(const MCCodePaddingContext &Context) {}
+
+ virtual void
+ EmitCodePaddingBasicBlockEnd(const MCCodePaddingContext &Context) {}
+
/// @}
/// \brief Switch to a new logical file. This is used to implement the '.file
OpenPOWER on IntegriCloud