xref: /freebsd/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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(std::make_pair(C->getValue(), Size));
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 =
54         CachedSymbolEntries.find(std::make_pair(&(S->getSymbol()), Size));
55     if (SItr != CachedSymbolEntries.end())
56       return SItr->second;
57   }
58 
59   MCSymbol *CPEntryLabel = Context.createTempSymbol();
60 
61   Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
62   const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
63   if (C)
64     CachedConstantEntries[std::make_pair(C->getValue(), Size)] = SymRef;
65   if (S)
66     CachedSymbolEntries[std::make_pair(&(S->getSymbol()), Size)] = SymRef;
67   return SymRef;
68 }
69 
70 bool ConstantPool::empty() { return Entries.empty(); }
71 
72 void ConstantPool::clearCache() {
73   CachedConstantEntries.clear();
74   CachedSymbolEntries.clear();
75 }
76 
77 //
78 // AssemblerConstantPools implementation
79 //
80 ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) {
81   ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
82   if (CP == ConstantPools.end())
83     return nullptr;
84 
85   return &CP->second;
86 }
87 
88 ConstantPool &
89 AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) {
90   return ConstantPools[Section];
91 }
92 
93 static void emitConstantPool(MCStreamer &Streamer, MCSection *Section,
94                              ConstantPool &CP) {
95   if (!CP.empty()) {
96     Streamer.switchSection(Section);
97     CP.emitEntries(Streamer);
98   }
99 }
100 
101 void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
102   // Dump contents of assembler constant pools.
103   for (auto &CPI : ConstantPools) {
104     MCSection *Section = CPI.first;
105     ConstantPool &CP = CPI.second;
106 
107     emitConstantPool(Streamer, Section, CP);
108   }
109 }
110 
111 void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
112   MCSection *Section = Streamer.getCurrentSectionOnly();
113   if (ConstantPool *CP = getConstantPool(Section))
114     emitConstantPool(Streamer, Section, *CP);
115 }
116 
117 void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
118   MCSection *Section = Streamer.getCurrentSectionOnly();
119   if (ConstantPool *CP = getConstantPool(Section))
120     CP->clearCache();
121 }
122 
123 const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
124                                                const MCExpr *Expr,
125                                                unsigned Size, SMLoc Loc) {
126   MCSection *Section = Streamer.getCurrentSectionOnly();
127   return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
128                                                    Size, Loc);
129 }
130