xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- ConstantPools.cpp - ConstantPool class -----------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file implements the ConstantPool and  AssemblerConstantPools classes.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "llvm/MC/ConstantPools.h"
14*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
15*0b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
16*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
17*0b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
18*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric using namespace llvm;
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric //
23*0b57cec5SDimitry Andric // ConstantPool implementation
24*0b57cec5SDimitry Andric //
25*0b57cec5SDimitry Andric // Emit the contents of the constant pool using the provided streamer.
26*0b57cec5SDimitry Andric void ConstantPool::emitEntries(MCStreamer &Streamer) {
27*0b57cec5SDimitry Andric   if (Entries.empty())
28*0b57cec5SDimitry Andric     return;
29*0b57cec5SDimitry Andric   Streamer.EmitDataRegion(MCDR_DataRegion);
30*0b57cec5SDimitry Andric   for (const ConstantPoolEntry &Entry : Entries) {
31*0b57cec5SDimitry Andric     Streamer.EmitCodeAlignment(Entry.Size); // align naturally
32*0b57cec5SDimitry Andric     Streamer.EmitLabel(Entry.Label);
33*0b57cec5SDimitry Andric     Streamer.EmitValue(Entry.Value, Entry.Size, Entry.Loc);
34*0b57cec5SDimitry Andric   }
35*0b57cec5SDimitry Andric   Streamer.EmitDataRegion(MCDR_DataRegionEnd);
36*0b57cec5SDimitry Andric   Entries.clear();
37*0b57cec5SDimitry Andric }
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
40*0b57cec5SDimitry Andric                                      unsigned Size, SMLoc Loc) {
41*0b57cec5SDimitry Andric   const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
42*0b57cec5SDimitry Andric 
43*0b57cec5SDimitry Andric   // Check if there is existing entry for the same constant. If so, reuse it.
44*0b57cec5SDimitry Andric   auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end();
45*0b57cec5SDimitry Andric   if (Itr != CachedEntries.end())
46*0b57cec5SDimitry Andric     return Itr->second;
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   MCSymbol *CPEntryLabel = Context.createTempSymbol();
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric   Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
51*0b57cec5SDimitry Andric   const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
52*0b57cec5SDimitry Andric   if (C)
53*0b57cec5SDimitry Andric     CachedEntries[C->getValue()] = SymRef;
54*0b57cec5SDimitry Andric   return SymRef;
55*0b57cec5SDimitry Andric }
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric bool ConstantPool::empty() { return Entries.empty(); }
58*0b57cec5SDimitry Andric 
59*0b57cec5SDimitry Andric void ConstantPool::clearCache() {
60*0b57cec5SDimitry Andric   CachedEntries.clear();
61*0b57cec5SDimitry Andric }
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric //
64*0b57cec5SDimitry Andric // AssemblerConstantPools implementation
65*0b57cec5SDimitry Andric //
66*0b57cec5SDimitry Andric ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) {
67*0b57cec5SDimitry Andric   ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
68*0b57cec5SDimitry Andric   if (CP == ConstantPools.end())
69*0b57cec5SDimitry Andric     return nullptr;
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric   return &CP->second;
72*0b57cec5SDimitry Andric }
73*0b57cec5SDimitry Andric 
74*0b57cec5SDimitry Andric ConstantPool &
75*0b57cec5SDimitry Andric AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) {
76*0b57cec5SDimitry Andric   return ConstantPools[Section];
77*0b57cec5SDimitry Andric }
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric static void emitConstantPool(MCStreamer &Streamer, MCSection *Section,
80*0b57cec5SDimitry Andric                              ConstantPool &CP) {
81*0b57cec5SDimitry Andric   if (!CP.empty()) {
82*0b57cec5SDimitry Andric     Streamer.SwitchSection(Section);
83*0b57cec5SDimitry Andric     CP.emitEntries(Streamer);
84*0b57cec5SDimitry Andric   }
85*0b57cec5SDimitry Andric }
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
88*0b57cec5SDimitry Andric   // Dump contents of assembler constant pools.
89*0b57cec5SDimitry Andric   for (auto &CPI : ConstantPools) {
90*0b57cec5SDimitry Andric     MCSection *Section = CPI.first;
91*0b57cec5SDimitry Andric     ConstantPool &CP = CPI.second;
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric     emitConstantPool(Streamer, Section, CP);
94*0b57cec5SDimitry Andric   }
95*0b57cec5SDimitry Andric }
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
98*0b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
99*0b57cec5SDimitry Andric   if (ConstantPool *CP = getConstantPool(Section))
100*0b57cec5SDimitry Andric     emitConstantPool(Streamer, Section, *CP);
101*0b57cec5SDimitry Andric }
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
104*0b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
105*0b57cec5SDimitry Andric   if (ConstantPool *CP = getConstantPool(Section))
106*0b57cec5SDimitry Andric     CP->clearCache();
107*0b57cec5SDimitry Andric }
108*0b57cec5SDimitry Andric 
109*0b57cec5SDimitry Andric const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
110*0b57cec5SDimitry Andric                                                const MCExpr *Expr,
111*0b57cec5SDimitry Andric                                                unsigned Size, SMLoc Loc) {
112*0b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
113*0b57cec5SDimitry Andric   return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
114*0b57cec5SDimitry Andric                                                    Size, Loc);
115*0b57cec5SDimitry Andric }
116