2009-08-01 01:02:00 +08:00
|
|
|
//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
|
|
|
|
//
|
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
|
2009-08-01 01:02:00 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/MC/MCSection.h"
|
2022-02-08 22:32:21 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2018-04-30 22:59:11 +08:00
|
|
|
#include "llvm/Config/llvm-config.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include "llvm/MC/MCFragment.h"
|
2015-03-24 05:22:04 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-08-09 06:41:53 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-09 06:23:19 +08:00
|
|
|
#include <utility>
|
2009-08-01 01:02:00 +08:00
|
|
|
|
2017-02-09 06:23:19 +08:00
|
|
|
using namespace llvm;
|
2009-08-09 06:41:53 +08:00
|
|
|
|
2020-04-16 06:49:05 +08:00
|
|
|
MCSection::MCSection(SectionVariant V, StringRef Name, SectionKind K,
|
|
|
|
MCSymbol *Begin)
|
2015-06-01 09:05:07 +08:00
|
|
|
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
|
2020-04-16 06:49:05 +08:00
|
|
|
IsRegistered(false), DummyFragment(this), Name(Name), Variant(V),
|
|
|
|
Kind(K) {}
|
2015-05-26 07:14:17 +08:00
|
|
|
|
2015-05-22 03:20:38 +08:00
|
|
|
MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
|
2015-03-24 05:22:04 +08:00
|
|
|
if (!End)
|
2020-12-22 06:04:13 +08:00
|
|
|
End = Ctx.createTempSymbol("sec_end");
|
2015-03-24 05:22:04 +08:00
|
|
|
return End;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MCSection::hasEnded() const { return End && End->isInSection(); }
|
|
|
|
|
2020-03-21 19:39:34 +08:00
|
|
|
MCSection::~MCSection() = default;
|
|
|
|
|
2015-05-25 23:04:26 +08:00
|
|
|
void MCSection::setBundleLockState(BundleLockStateType NewState) {
|
|
|
|
if (NewState == NotBundleLocked) {
|
|
|
|
if (BundleLockNestingDepth == 0) {
|
|
|
|
report_fatal_error("Mismatched bundle_lock/unlock directives");
|
|
|
|
}
|
|
|
|
if (--BundleLockNestingDepth == 0) {
|
|
|
|
BundleLockState = NotBundleLocked;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If any of the directives is an align_to_end directive, the whole nested
|
|
|
|
// group is align_to_end. So don't downgrade from align_to_end to just locked.
|
|
|
|
if (BundleLockState != BundleLockedAlignToEnd) {
|
|
|
|
BundleLockState = NewState;
|
|
|
|
}
|
|
|
|
++BundleLockNestingDepth;
|
|
|
|
}
|
2015-05-26 06:57:48 +08:00
|
|
|
|
2015-05-27 23:14:11 +08:00
|
|
|
MCSection::iterator
|
2015-05-27 21:37:28 +08:00
|
|
|
MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
|
2015-05-27 23:14:11 +08:00
|
|
|
if (Subsection == 0 && SubsectionFragmentMap.empty())
|
2015-05-27 21:37:28 +08:00
|
|
|
return end();
|
|
|
|
|
2021-01-30 15:23:35 +08:00
|
|
|
SmallVectorImpl<std::pair<unsigned, MCFragment *>>::iterator MI = lower_bound(
|
|
|
|
SubsectionFragmentMap, std::make_pair(Subsection, (MCFragment *)nullptr));
|
2015-05-27 21:37:28 +08:00
|
|
|
bool ExactMatch = false;
|
2015-05-27 23:14:11 +08:00
|
|
|
if (MI != SubsectionFragmentMap.end()) {
|
2015-05-27 21:37:28 +08:00
|
|
|
ExactMatch = MI->first == Subsection;
|
|
|
|
if (ExactMatch)
|
|
|
|
++MI;
|
|
|
|
}
|
2015-05-27 23:14:11 +08:00
|
|
|
iterator IP;
|
|
|
|
if (MI == SubsectionFragmentMap.end())
|
2015-05-27 21:37:28 +08:00
|
|
|
IP = end();
|
|
|
|
else
|
2015-10-10 08:13:11 +08:00
|
|
|
IP = MI->second->getIterator();
|
2015-05-27 21:37:28 +08:00
|
|
|
if (!ExactMatch && Subsection != 0) {
|
|
|
|
// The GNU as documentation claims that subsections have an alignment of 4,
|
|
|
|
// although this appears not to be the case.
|
|
|
|
MCFragment *F = new MCDataFragment();
|
2015-05-27 23:14:11 +08:00
|
|
|
SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F));
|
2015-05-27 21:37:28 +08:00
|
|
|
getFragmentList().insert(IP, F);
|
|
|
|
F->setParent(this);
|
2020-09-10 02:58:22 +08:00
|
|
|
F->setSubsectionNumber(Subsection);
|
2015-05-27 21:37:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return IP;
|
|
|
|
}
|
|
|
|
|
2020-04-15 02:05:21 +08:00
|
|
|
StringRef MCSection::getVirtualSectionKind() const { return "virtual"; }
|
|
|
|
|
|
|
|
void MCSection::addPendingLabel(MCSymbol *label, unsigned Subsection) {
|
[ 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-12 02:42:37 +08:00
|
|
|
PendingLabels.push_back(PendingLabel(label, Subsection));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCSection::flushPendingLabels(MCFragment *F, uint64_t FOffset,
|
|
|
|
unsigned Subsection) {
|
|
|
|
if (PendingLabels.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set the fragment and fragment offset for all pending symbols in the
|
|
|
|
// specified Subsection, and remove those symbols from the pending list.
|
|
|
|
for (auto It = PendingLabels.begin(); It != PendingLabels.end(); ++It) {
|
|
|
|
PendingLabel& Label = *It;
|
|
|
|
if (Label.Subsection == Subsection) {
|
|
|
|
Label.Sym->setFragment(F);
|
|
|
|
Label.Sym->setOffset(FOffset);
|
|
|
|
PendingLabels.erase(It--);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCSection::flushPendingLabels() {
|
|
|
|
// Make sure all remaining pending labels point to data fragments, by
|
|
|
|
// creating new empty data fragments for each Subsection with labels pending.
|
|
|
|
while (!PendingLabels.empty()) {
|
|
|
|
PendingLabel& Label = PendingLabels[0];
|
|
|
|
iterator CurInsertionPoint =
|
|
|
|
this->getSubsectionInsertionPoint(Label.Subsection);
|
|
|
|
MCFragment *F = new MCDataFragment();
|
|
|
|
getFragmentList().insert(CurInsertionPoint, F);
|
|
|
|
F->setParent(this);
|
|
|
|
flushPendingLabels(F, 0, Label.Subsection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-15 22:32:27 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
2017-06-22 06:19:17 +08:00
|
|
|
LLVM_DUMP_METHOD void MCSection::dump() const {
|
2017-02-09 06:23:19 +08:00
|
|
|
raw_ostream &OS = errs();
|
2015-05-26 07:14:17 +08:00
|
|
|
|
2015-05-27 23:14:11 +08:00
|
|
|
OS << "<MCSection";
|
|
|
|
OS << " Fragments:[\n ";
|
|
|
|
for (auto it = begin(), ie = end(); it != ie; ++it) {
|
|
|
|
if (it != begin())
|
|
|
|
OS << ",\n ";
|
|
|
|
it->dump();
|
|
|
|
}
|
|
|
|
OS << "]>";
|
2015-05-26 07:14:17 +08:00
|
|
|
}
|
2017-01-28 10:02:38 +08:00
|
|
|
#endif
|