2009-06-24 00:01:43 +02:00
|
|
|
//===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01: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
|
2009-06-24 00:01:43 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-07-01 08:31:49 +02:00
|
|
|
//
|
|
|
|
// This file declares the MCSection class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-06-24 00:01:43 +02:00
|
|
|
|
|
|
|
#ifndef LLVM_MC_MCSECTION_H
|
|
|
|
#define LLVM_MC_MCSECTION_H
|
|
|
|
|
2017-02-08 23:23:19 +01:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/ADT/ilist.h"
|
2015-12-29 10:06:16 +01:00
|
|
|
#include "llvm/MC/MCFragment.h"
|
2009-08-01 23:30:49 +02:00
|
|
|
#include "llvm/MC/SectionKind.h"
|
[Alignment] Introduce llvm::Align to MCSection
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, JDevlieghere
Subscribers: arsenm, sdardis, jvesely, nhaehnle, sbc100, hiraditya, aheejin, jrtc27, atanasyan, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67486
llvm-svn: 371831
2019-09-13 11:29:59 +02:00
|
|
|
#include "llvm/Support/Alignment.h"
|
2017-02-08 23:23:19 +01:00
|
|
|
#include <cassert>
|
|
|
|
#include <utility>
|
2009-06-24 00:01:43 +02:00
|
|
|
|
2009-07-31 19:02:00 +02:00
|
|
|
namespace llvm {
|
2017-02-08 23:23:19 +01:00
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
class MCAsmInfo;
|
2015-03-23 22:22:04 +01:00
|
|
|
class MCContext;
|
2015-03-10 14:56:44 +01:00
|
|
|
class MCExpr;
|
2015-03-10 17:58:10 +01:00
|
|
|
class MCSymbol;
|
2015-03-10 14:56:44 +01:00
|
|
|
class raw_ostream;
|
2017-02-08 23:23:19 +01:00
|
|
|
class Triple;
|
2010-07-01 03:00:22 +02:00
|
|
|
|
2016-08-30 20:40:47 +02:00
|
|
|
template <> struct ilist_alloc_traits<MCFragment> {
|
2015-06-18 00:01:28 +02:00
|
|
|
static void deleteNode(MCFragment *V);
|
|
|
|
};
|
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
/// Instances of this class represent a uniqued identifier for a section in the
|
|
|
|
/// current translation unit. The MCContext class uniques and creates these.
|
|
|
|
class MCSection {
|
|
|
|
public:
|
2020-02-15 05:15:55 +01:00
|
|
|
static constexpr unsigned NonUniqueID = ~0U;
|
|
|
|
|
2021-07-27 17:26:00 +02:00
|
|
|
enum SectionVariant {
|
|
|
|
SV_COFF = 0,
|
|
|
|
SV_ELF,
|
|
|
|
SV_GOFF,
|
|
|
|
SV_MachO,
|
|
|
|
SV_Wasm,
|
|
|
|
SV_XCOFF
|
|
|
|
};
|
2010-05-17 23:54:26 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Express the state of bundle locked groups while emitting code.
|
2015-05-25 17:04:26 +02:00
|
|
|
enum BundleLockStateType {
|
|
|
|
NotBundleLocked,
|
|
|
|
BundleLocked,
|
|
|
|
BundleLockedAlignToEnd
|
|
|
|
};
|
|
|
|
|
2017-04-27 00:31:39 +02:00
|
|
|
using FragmentListType = iplist<MCFragment>;
|
2015-05-27 17:14:11 +02:00
|
|
|
|
2017-04-27 00:31:39 +02:00
|
|
|
using const_iterator = FragmentListType::const_iterator;
|
|
|
|
using iterator = FragmentListType::iterator;
|
2015-05-27 17:14:11 +02:00
|
|
|
|
2017-04-27 00:31:39 +02:00
|
|
|
using const_reverse_iterator = FragmentListType::const_reverse_iterator;
|
|
|
|
using reverse_iterator = FragmentListType::reverse_iterator;
|
2015-05-27 17:14:11 +02:00
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
private:
|
2015-05-21 21:20:38 +02:00
|
|
|
MCSymbol *Begin;
|
2015-05-25 16:04:31 +02:00
|
|
|
MCSymbol *End = nullptr;
|
2015-05-21 21:20:38 +02:00
|
|
|
/// The alignment requirement of this section.
|
2019-09-27 14:54:21 +02:00
|
|
|
Align Alignment;
|
2015-05-25 16:00:56 +02:00
|
|
|
/// The section index in the assemblers section list.
|
2015-05-25 16:18:24 +02:00
|
|
|
unsigned Ordinal = 0;
|
2015-05-25 16:25:28 +02:00
|
|
|
/// The index of this section in the layout order.
|
|
|
|
unsigned LayoutOrder;
|
2015-03-10 17:58:10 +01:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Keeping track of bundle-locked state.
|
2015-05-25 17:04:26 +02:00
|
|
|
BundleLockStateType BundleLockState = NotBundleLocked;
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Current nesting depth of bundle_lock directives.
|
2015-05-25 17:04:26 +02:00
|
|
|
unsigned BundleLockNestingDepth = 0;
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// We've seen a bundle_lock directive but not its first instruction
|
2015-05-25 17:04:26 +02:00
|
|
|
/// yet.
|
2017-02-08 23:23:19 +01:00
|
|
|
bool BundleGroupBeforeFirstInst : 1;
|
2015-05-25 17:04:26 +02:00
|
|
|
|
2015-05-25 20:34:26 +02:00
|
|
|
/// Whether this section has had instructions emitted into it.
|
2017-02-08 23:23:19 +01:00
|
|
|
bool HasInstructions : 1;
|
2015-05-25 20:34:26 +02:00
|
|
|
|
2017-02-08 23:23:19 +01:00
|
|
|
bool IsRegistered : 1;
|
2015-06-01 03:30:01 +02:00
|
|
|
|
2015-10-05 14:07:05 +02:00
|
|
|
MCDummyFragment DummyFragment;
|
|
|
|
|
2015-05-27 17:14:11 +02:00
|
|
|
FragmentListType Fragments;
|
|
|
|
|
|
|
|
/// Mapping from subsection number to insertion point for subsection numbers
|
|
|
|
/// below that number.
|
|
|
|
SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap;
|
2015-05-26 01:14:17 +02:00
|
|
|
|
[ MC ] Match labels to existing fragments even when switching sections.
(This commit restores the original branch (4272372c571) and applies an
additional change dropped from the original in a bad merge. This change
should address the previous bot failures. Both changes reviewed by pete.)
Summary:
This commit builds upon Derek Schuff's 2014 commit for attaching labels to
existing fragments ( Diff Revision: http://reviews.llvm.org/D5915 )
When temporary labels appear ahead of a fragment, MCObjectStreamer will
track the temporary label symbol in a "Pending Labels" list. Labels are
associated with fragments when a real fragment arrives; otherwise, an empty
data fragment will be created if the streamer's section changes or if the
stream finishes.
This commit moves the "Pending Labels" list into each MCStream, so that
this label-fragment matching process is resilient to section changes. If
the streamer emits a label in a new section, switches to another section to
do other work, then switches back to the first section and emits a
fragment, that initial label will be associated with this new fragment.
Labels will only receive empty data fragments in the case where no other
fragment exists for that section.
The downstream effects of this can be seen in Mach-O relocations. The
previous approach could produce local section relocations and external
symbol relocations for the same data in an object file, and this mix of
relocation types resulted in problems in the ld64 Mach-O linker. This
commit ensures relocations triggered by temporary labels are consistent.
Reviewers: pete, ab, dschuff
Reviewed By: pete, dschuff
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71368
2019-12-11 19:42:37 +01:00
|
|
|
/// State for tracking labels that don't yet have Fragments
|
|
|
|
struct PendingLabel {
|
|
|
|
MCSymbol* Sym;
|
|
|
|
unsigned Subsection;
|
|
|
|
PendingLabel(MCSymbol* Sym, unsigned Subsection = 0)
|
|
|
|
: Sym(Sym), Subsection(Subsection) {}
|
|
|
|
};
|
|
|
|
SmallVector<PendingLabel, 2> PendingLabels;
|
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
protected:
|
2020-04-16 00:49:05 +02:00
|
|
|
// TODO Make Name private when possible.
|
|
|
|
StringRef Name;
|
2015-03-10 14:56:44 +01:00
|
|
|
SectionVariant Variant;
|
|
|
|
SectionKind Kind;
|
2017-02-08 23:23:19 +01:00
|
|
|
|
2020-04-16 00:49:05 +02:00
|
|
|
MCSection(SectionVariant V, StringRef Name, SectionKind K, MCSymbol *Begin);
|
2020-03-21 12:39:34 +01:00
|
|
|
~MCSection();
|
2010-05-17 23:54:26 +02:00
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
public:
|
2017-02-08 23:23:19 +01:00
|
|
|
MCSection(const MCSection &) = delete;
|
|
|
|
MCSection &operator=(const MCSection &) = delete;
|
|
|
|
|
2020-04-16 00:49:05 +02:00
|
|
|
StringRef getName() const { return Name; }
|
2015-03-10 14:56:44 +01:00
|
|
|
SectionKind getKind() const { return Kind; }
|
2010-04-05 01:22:29 +02:00
|
|
|
|
2015-03-10 14:56:44 +01:00
|
|
|
SectionVariant getVariant() const { return Variant; }
|
2010-10-04 19:32:41 +02:00
|
|
|
|
2015-05-21 21:20:38 +02:00
|
|
|
MCSymbol *getBeginSymbol() { return Begin; }
|
|
|
|
const MCSymbol *getBeginSymbol() const {
|
|
|
|
return const_cast<MCSection *>(this)->getBeginSymbol();
|
|
|
|
}
|
|
|
|
void setBeginSymbol(MCSymbol *Sym) {
|
2015-05-21 18:52:32 +02:00
|
|
|
assert(!Begin);
|
|
|
|
Begin = Sym;
|
|
|
|
}
|
2015-05-21 21:20:38 +02:00
|
|
|
MCSymbol *getEndSymbol(MCContext &Ctx);
|
2015-03-23 22:22:04 +01:00
|
|
|
bool hasEnded() const;
|
2015-03-10 17:58:10 +01:00
|
|
|
|
[Alignment] Introduce llvm::Align to MCSection
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, JDevlieghere
Subscribers: arsenm, sdardis, jvesely, nhaehnle, sbc100, hiraditya, aheejin, jrtc27, atanasyan, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67486
llvm-svn: 371831
2019-09-13 11:29:59 +02:00
|
|
|
unsigned getAlignment() const { return Alignment.value(); }
|
2019-09-27 14:54:21 +02:00
|
|
|
void setAlignment(Align Value) { Alignment = Value; }
|
2015-05-21 21:20:38 +02:00
|
|
|
|
2015-05-25 16:00:56 +02:00
|
|
|
unsigned getOrdinal() const { return Ordinal; }
|
|
|
|
void setOrdinal(unsigned Value) { Ordinal = Value; }
|
|
|
|
|
2015-05-25 16:25:28 +02:00
|
|
|
unsigned getLayoutOrder() const { return LayoutOrder; }
|
|
|
|
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
|
|
|
|
|
2015-05-25 17:04:26 +02:00
|
|
|
BundleLockStateType getBundleLockState() const { return BundleLockState; }
|
|
|
|
void setBundleLockState(BundleLockStateType NewState);
|
|
|
|
bool isBundleLocked() const { return BundleLockState != NotBundleLocked; }
|
|
|
|
|
|
|
|
bool isBundleGroupBeforeFirstInst() const {
|
|
|
|
return BundleGroupBeforeFirstInst;
|
|
|
|
}
|
|
|
|
void setBundleGroupBeforeFirstInst(bool IsFirst) {
|
|
|
|
BundleGroupBeforeFirstInst = IsFirst;
|
|
|
|
}
|
|
|
|
|
2015-05-25 20:34:26 +02:00
|
|
|
bool hasInstructions() const { return HasInstructions; }
|
|
|
|
void setHasInstructions(bool Value) { HasInstructions = Value; }
|
|
|
|
|
2015-06-01 03:30:01 +02:00
|
|
|
bool isRegistered() const { return IsRegistered; }
|
|
|
|
void setIsRegistered(bool Value) { IsRegistered = Value; }
|
|
|
|
|
2015-05-27 17:14:11 +02:00
|
|
|
MCSection::FragmentListType &getFragmentList() { return Fragments; }
|
|
|
|
const MCSection::FragmentListType &getFragmentList() const {
|
2015-05-26 01:14:17 +02:00
|
|
|
return const_cast<MCSection *>(this)->getFragmentList();
|
|
|
|
}
|
|
|
|
|
ADT: Avoid relying on UB in ilist_node::getNextNode()
Re-implement `ilist_node::getNextNode()` and `getPrevNode()` without
relying on the sentinel having a "next" pointer. Instead, get access to
the owning list and compare against the `begin()` and `end()` iterators.
This only works when the node *can* get access to the owning list. The
new support is in `ilist_node_with_parent<>`, and any class `Ty`
inheriting from `ilist_node<NodeTy>` that wants `getNextNode()` and/or
`getPrevNode()` should inherit from
`ilist_node_with_parent<NodeTy, ParentTy>` instead. The requirements:
- `NodeTy` must have a `getParent()` function that returns the parent.
- `ParentTy` must have a `getSublistAccess()` static that, given a(n
ignored) `NodeTy*` (to determine which list), returns a member field
pointer to the appropriate `ilist<>`.
This isn't the cleanest way to get access to the owning list, but it
leverages the API already used in the IR hierarchy (see, e.g.,
`Instruction::getSublistAccess()`).
If anyone feels like ripping out the calls to `getNextNode()` and
`getPrevNode()` and replacing with direct iterator logic, they can also
remove the access function, etc., but as an incremental step, I'm
maintaining the API where it's currently used in tree.
If these requirements are *not* met, call sites with access to the ilist
can call `iplist<NodeTy>::getNextNode(NodeTy*)` directly, as in
ilistTest.cpp.
Why rewrite this?
The old code was broken, calling `getNext()` on a sentinel that possibly
didn't have a "next" pointer at all! The new code avoids that
particular flavour of UB (see the commit message for r252538 for more
details about the "lucky" memory layout that made this function so
interesting).
There's still some UB here: the end iterator gets downcast to `NodeTy*`,
even when it's a sentinel (which is typically
`ilist_half_node<NodeTy*>`). I'll tackle that in follow-up commits.
See this llvm-dev thread for more details:
http://lists.llvm.org/pipermail/llvm-dev/2015-October/091115.html
What's the danger?
There might be some code that relies on `getNextNode()` or
`getPrevNode()` *never* returning `nullptr` -- i.e., that relies on them
being broken when the sentinel is an `ilist_half_node<NodeTy>`. I tried
to root out those cases with the audits I did leading up to r252380, but
it's possible I missed one or two. I hope not.
(If (1) you have out-of-tree code, (2) you've reverted r252380
temporarily, and (3) you get some weird crashes with this commit, then I
recommend un-reverting r252380 and auditing the compile errors looking
for "strange" implicit conversions.)
llvm-svn: 252694
2015-11-11 03:26:42 +01:00
|
|
|
/// Support for MCFragment::getNextNode().
|
|
|
|
static FragmentListType MCSection::*getSublistAccess(MCFragment *) {
|
|
|
|
return &MCSection::Fragments;
|
|
|
|
}
|
|
|
|
|
2015-10-05 14:07:05 +02:00
|
|
|
const MCDummyFragment &getDummyFragment() const { return DummyFragment; }
|
|
|
|
MCDummyFragment &getDummyFragment() { return DummyFragment; }
|
|
|
|
|
2016-09-12 02:17:09 +02:00
|
|
|
iterator begin() { return Fragments.begin(); }
|
|
|
|
const_iterator begin() const { return Fragments.begin(); }
|
2015-05-26 01:14:17 +02:00
|
|
|
|
2016-09-12 02:17:09 +02:00
|
|
|
iterator end() { return Fragments.end(); }
|
|
|
|
const_iterator end() const { return Fragments.end(); }
|
2015-05-26 01:14:17 +02:00
|
|
|
|
2015-05-27 17:14:11 +02:00
|
|
|
MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection);
|
|
|
|
|
2017-06-22 00:19:17 +02:00
|
|
|
void dump() const;
|
2015-05-27 15:37:28 +02:00
|
|
|
|
2017-01-30 16:38:43 +01:00
|
|
|
virtual void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
|
|
|
raw_ostream &OS,
|
2015-03-10 14:56:44 +01:00
|
|
|
const MCExpr *Subsection) const = 0;
|
|
|
|
|
|
|
|
/// Return true if a .align directive should use "optimized nops" to fill
|
|
|
|
/// instead of 0s.
|
|
|
|
virtual bool UseCodeAlign() const = 0;
|
|
|
|
|
|
|
|
/// Check whether this section is "virtual", that is has no actual object
|
|
|
|
/// file contents.
|
|
|
|
virtual bool isVirtualSection() const = 0;
|
[ MC ] Match labels to existing fragments even when switching sections.
(This commit restores the original branch (4272372c571) and applies an
additional change dropped from the original in a bad merge. This change
should address the previous bot failures. Both changes reviewed by pete.)
Summary:
This commit builds upon Derek Schuff's 2014 commit for attaching labels to
existing fragments ( Diff Revision: http://reviews.llvm.org/D5915 )
When temporary labels appear ahead of a fragment, MCObjectStreamer will
track the temporary label symbol in a "Pending Labels" list. Labels are
associated with fragments when a real fragment arrives; otherwise, an empty
data fragment will be created if the streamer's section changes or if the
stream finishes.
This commit moves the "Pending Labels" list into each MCStream, so that
this label-fragment matching process is resilient to section changes. If
the streamer emits a label in a new section, switches to another section to
do other work, then switches back to the first section and emits a
fragment, that initial label will be associated with this new fragment.
Labels will only receive empty data fragments in the case where no other
fragment exists for that section.
The downstream effects of this can be seen in Mach-O relocations. The
previous approach could produce local section relocations and external
symbol relocations for the same data in an object file, and this mix of
relocation types resulted in problems in the ld64 Mach-O linker. This
commit ensures relocations triggered by temporary labels are consistent.
Reviewers: pete, ab, dschuff
Reviewed By: pete, dschuff
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71368
2019-12-11 19:42:37 +01:00
|
|
|
|
2020-04-14 20:05:21 +02:00
|
|
|
virtual StringRef getVirtualSectionKind() const;
|
|
|
|
|
[ MC ] Match labels to existing fragments even when switching sections.
(This commit restores the original branch (4272372c571) and applies an
additional change dropped from the original in a bad merge. This change
should address the previous bot failures. Both changes reviewed by pete.)
Summary:
This commit builds upon Derek Schuff's 2014 commit for attaching labels to
existing fragments ( Diff Revision: http://reviews.llvm.org/D5915 )
When temporary labels appear ahead of a fragment, MCObjectStreamer will
track the temporary label symbol in a "Pending Labels" list. Labels are
associated with fragments when a real fragment arrives; otherwise, an empty
data fragment will be created if the streamer's section changes or if the
stream finishes.
This commit moves the "Pending Labels" list into each MCStream, so that
this label-fragment matching process is resilient to section changes. If
the streamer emits a label in a new section, switches to another section to
do other work, then switches back to the first section and emits a
fragment, that initial label will be associated with this new fragment.
Labels will only receive empty data fragments in the case where no other
fragment exists for that section.
The downstream effects of this can be seen in Mach-O relocations. The
previous approach could produce local section relocations and external
symbol relocations for the same data in an object file, and this mix of
relocation types resulted in problems in the ld64 Mach-O linker. This
commit ensures relocations triggered by temporary labels are consistent.
Reviewers: pete, ab, dschuff
Reviewed By: pete, dschuff
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71368
2019-12-11 19:42:37 +01:00
|
|
|
/// Add a pending label for the requested subsection. This label will be
|
|
|
|
/// associated with a fragment in flushPendingLabels()
|
|
|
|
void addPendingLabel(MCSymbol* label, unsigned Subsection = 0);
|
|
|
|
|
|
|
|
/// Associate all pending labels in a subsection with a fragment.
|
|
|
|
void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0,
|
|
|
|
unsigned Subsection = 0);
|
|
|
|
|
|
|
|
/// Associate all pending labels with empty data fragments. One fragment
|
|
|
|
/// will be created for each subsection as necessary.
|
|
|
|
void flushPendingLabels();
|
2015-03-10 14:56:44 +01:00
|
|
|
};
|
2010-07-01 03:00:22 +02:00
|
|
|
|
2009-06-24 00:01:43 +02:00
|
|
|
} // end namespace llvm
|
|
|
|
|
2017-02-08 23:23:19 +01:00
|
|
|
#endif // LLVM_MC_MCSECTION_H
|