1c10132aaSChris Lattner //===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===//
2c10132aaSChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c10132aaSChris Lattner //
7c10132aaSChris Lattner //===----------------------------------------------------------------------===//
8c10132aaSChris Lattner 
96bda14b3SChandler Carruth #include "llvm/MC/MCSection.h"
10*ef736a1cSserge-sans-paille #include "llvm/ADT/STLExtras.h"
113d8b0ebbSEugene Zelenko #include "llvm/ADT/SmallVector.h"
12432a3883SNico Weber #include "llvm/Config/llvm-config.h"
13ed0881b2SChandler Carruth #include "llvm/MC/MCContext.h"
143d8b0ebbSEugene Zelenko #include "llvm/MC/MCFragment.h"
15f2b408c6SRafael Espindola #include "llvm/MC/MCSymbol.h"
163d8b0ebbSEugene Zelenko #include "llvm/Support/Compiler.h"
173d8b0ebbSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
181cb9396fSChris Lattner #include "llvm/Support/raw_ostream.h"
193d8b0ebbSEugene Zelenko #include <utility>
20c10132aaSChris Lattner 
213d8b0ebbSEugene Zelenko using namespace llvm;
221cb9396fSChris Lattner 
MCSection(SectionVariant V,StringRef Name,SectionKind K,MCSymbol * Begin)2390a63f6dSFangrui Song MCSection::MCSection(SectionVariant V, StringRef Name, SectionKind K,
2490a63f6dSFangrui Song                      MCSymbol *Begin)
25a66395e1SRafael Espindola     : Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
2690a63f6dSFangrui Song       IsRegistered(false), DummyFragment(this), Name(Name), Variant(V),
2790a63f6dSFangrui Song       Kind(K) {}
28a554c05dSRafael Espindola 
getEndSymbol(MCContext & Ctx)290709a7bdSRafael Espindola MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) {
30f2b408c6SRafael Espindola   if (!End)
31d9a0c40bSFangrui Song     End = Ctx.createTempSymbol("sec_end");
32f2b408c6SRafael Espindola   return End;
33f2b408c6SRafael Espindola }
34f2b408c6SRafael Espindola 
hasEnded() const35f2b408c6SRafael Espindola bool MCSection::hasEnded() const { return End && End->isInSection(); }
36f2b408c6SRafael Espindola 
37f9a86505SSimon Pilgrim MCSection::~MCSection() = default;
38f9a86505SSimon Pilgrim 
setBundleLockState(BundleLockStateType NewState)39b028cc80SRafael Espindola void MCSection::setBundleLockState(BundleLockStateType NewState) {
40b028cc80SRafael Espindola   if (NewState == NotBundleLocked) {
41b028cc80SRafael Espindola     if (BundleLockNestingDepth == 0) {
42b028cc80SRafael Espindola       report_fatal_error("Mismatched bundle_lock/unlock directives");
43b028cc80SRafael Espindola     }
44b028cc80SRafael Espindola     if (--BundleLockNestingDepth == 0) {
45b028cc80SRafael Espindola       BundleLockState = NotBundleLocked;
46b028cc80SRafael Espindola     }
47b028cc80SRafael Espindola     return;
48b028cc80SRafael Espindola   }
49b028cc80SRafael Espindola 
50b028cc80SRafael Espindola   // If any of the directives is an align_to_end directive, the whole nested
51b028cc80SRafael Espindola   // group is align_to_end. So don't downgrade from align_to_end to just locked.
52b028cc80SRafael Espindola   if (BundleLockState != BundleLockedAlignToEnd) {
53b028cc80SRafael Espindola     BundleLockState = NewState;
54b028cc80SRafael Espindola   }
55b028cc80SRafael Espindola   ++BundleLockNestingDepth;
56b028cc80SRafael Espindola }
5709266badSRafael Espindola 
58a32d0e9eSRafael Espindola MCSection::iterator
getSubsectionInsertionPoint(unsigned Subsection)598c05c6e2SRafael Espindola MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
60a32d0e9eSRafael Espindola   if (Subsection == 0 && SubsectionFragmentMap.empty())
618c05c6e2SRafael Espindola     return end();
628c05c6e2SRafael Espindola 
631a2d67faSKazu Hirata   SmallVectorImpl<std::pair<unsigned, MCFragment *>>::iterator MI = lower_bound(
641a2d67faSKazu Hirata       SubsectionFragmentMap, std::make_pair(Subsection, (MCFragment *)nullptr));
658c05c6e2SRafael Espindola   bool ExactMatch = false;
66a32d0e9eSRafael Espindola   if (MI != SubsectionFragmentMap.end()) {
678c05c6e2SRafael Espindola     ExactMatch = MI->first == Subsection;
688c05c6e2SRafael Espindola     if (ExactMatch)
698c05c6e2SRafael Espindola       ++MI;
708c05c6e2SRafael Espindola   }
71a32d0e9eSRafael Espindola   iterator IP;
72a32d0e9eSRafael Espindola   if (MI == SubsectionFragmentMap.end())
738c05c6e2SRafael Espindola     IP = end();
748c05c6e2SRafael Espindola   else
75a5f45da2SDuncan P. N. Exon Smith     IP = MI->second->getIterator();
768c05c6e2SRafael Espindola   if (!ExactMatch && Subsection != 0) {
778c05c6e2SRafael Espindola     // The GNU as documentation claims that subsections have an alignment of 4,
788c05c6e2SRafael Espindola     // although this appears not to be the case.
798c05c6e2SRafael Espindola     MCFragment *F = new MCDataFragment();
80a32d0e9eSRafael Espindola     SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F));
818c05c6e2SRafael Espindola     getFragmentList().insert(IP, F);
828c05c6e2SRafael Espindola     F->setParent(this);
83415a4fbeSJian Cai     F->setSubsectionNumber(Subsection);
848c05c6e2SRafael Espindola   }
858c05c6e2SRafael Espindola 
868c05c6e2SRafael Espindola   return IP;
878c05c6e2SRafael Espindola }
888c05c6e2SRafael Espindola 
getVirtualSectionKind() const89e13a8a1fSFangrui Song StringRef MCSection::getVirtualSectionKind() const { return "virtual"; }
90e13a8a1fSFangrui Song 
addPendingLabel(MCSymbol * label,unsigned Subsection)916f95d33eSMichael Trent void MCSection::addPendingLabel(MCSymbol *label, unsigned Subsection) {
926f95d33eSMichael Trent   PendingLabels.push_back(PendingLabel(label, Subsection));
936f95d33eSMichael Trent }
946f95d33eSMichael Trent 
flushPendingLabels(MCFragment * F,uint64_t FOffset,unsigned Subsection)956f95d33eSMichael Trent void MCSection::flushPendingLabels(MCFragment *F, uint64_t FOffset,
966f95d33eSMichael Trent 				   unsigned Subsection) {
976f95d33eSMichael Trent   if (PendingLabels.empty())
986f95d33eSMichael Trent     return;
996f95d33eSMichael Trent 
1006f95d33eSMichael Trent   // Set the fragment and fragment offset for all pending symbols in the
1016f95d33eSMichael Trent   // specified Subsection, and remove those symbols from the pending list.
1026f95d33eSMichael Trent   for (auto It = PendingLabels.begin(); It != PendingLabels.end(); ++It) {
1036f95d33eSMichael Trent     PendingLabel& Label = *It;
1046f95d33eSMichael Trent     if (Label.Subsection == Subsection) {
1056f95d33eSMichael Trent       Label.Sym->setFragment(F);
1066f95d33eSMichael Trent       Label.Sym->setOffset(FOffset);
1076f95d33eSMichael Trent       PendingLabels.erase(It--);
1086f95d33eSMichael Trent     }
1096f95d33eSMichael Trent   }
1106f95d33eSMichael Trent }
1116f95d33eSMichael Trent 
flushPendingLabels()1126f95d33eSMichael Trent void MCSection::flushPendingLabels() {
1136f95d33eSMichael Trent   // Make sure all remaining pending labels point to data fragments, by
1146f95d33eSMichael Trent   // creating new empty data fragments for each Subsection with labels pending.
1156f95d33eSMichael Trent   while (!PendingLabels.empty()) {
1166f95d33eSMichael Trent     PendingLabel& Label = PendingLabels[0];
1176f95d33eSMichael Trent     iterator CurInsertionPoint =
1186f95d33eSMichael Trent       this->getSubsectionInsertionPoint(Label.Subsection);
1196f95d33eSMichael Trent     MCFragment *F = new MCDataFragment();
1206f95d33eSMichael Trent     getFragmentList().insert(CurInsertionPoint, F);
1216f95d33eSMichael Trent     F->setParent(this);
1226f95d33eSMichael Trent     flushPendingLabels(F, 0, Label.Subsection);
1236f95d33eSMichael Trent   }
1246f95d33eSMichael Trent }
1256f95d33eSMichael Trent 
126615eb470SAaron Ballman #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const127705f798bSSam Clegg LLVM_DUMP_METHOD void MCSection::dump() const {
1283d8b0ebbSEugene Zelenko   raw_ostream &OS = errs();
129a554c05dSRafael Espindola 
130a32d0e9eSRafael Espindola   OS << "<MCSection";
131a32d0e9eSRafael Espindola   OS << " Fragments:[\n      ";
132a32d0e9eSRafael Espindola   for (auto it = begin(), ie = end(); it != ie; ++it) {
133a32d0e9eSRafael Espindola     if (it != begin())
134a32d0e9eSRafael Espindola       OS << ",\n      ";
135a32d0e9eSRafael Espindola     it->dump();
136a32d0e9eSRafael Espindola   }
137a32d0e9eSRafael Espindola   OS << "]>";
138a554c05dSRafael Espindola }
1398c209aa8SMatthias Braun #endif
140