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