xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ConstantPools.cpp - ConstantPool class -----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the ConstantPool and  AssemblerConstantPools classes.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/MC/ConstantPools.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
180b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric // ConstantPool implementation
240b57cec5SDimitry Andric //
250b57cec5SDimitry Andric // Emit the contents of the constant pool using the provided streamer.
260b57cec5SDimitry Andric void ConstantPool::emitEntries(MCStreamer &Streamer) {
270b57cec5SDimitry Andric   if (Entries.empty())
280b57cec5SDimitry Andric     return;
295ffd83dbSDimitry Andric   Streamer.emitDataRegion(MCDR_DataRegion);
300b57cec5SDimitry Andric   for (const ConstantPoolEntry &Entry : Entries) {
31bdd1243dSDimitry Andric     Streamer.emitValueToAlignment(Align(Entry.Size)); // align naturally
325ffd83dbSDimitry Andric     Streamer.emitLabel(Entry.Label);
335ffd83dbSDimitry Andric     Streamer.emitValue(Entry.Value, Entry.Size, Entry.Loc);
340b57cec5SDimitry Andric   }
355ffd83dbSDimitry Andric   Streamer.emitDataRegion(MCDR_DataRegionEnd);
360b57cec5SDimitry Andric   Entries.clear();
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
400b57cec5SDimitry Andric                                      unsigned Size, SMLoc Loc) {
410b57cec5SDimitry Andric   const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
4281ad6265SDimitry Andric   const MCSymbolRefExpr *S = dyn_cast<MCSymbolRefExpr>(Value);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   // Check if there is existing entry for the same constant. If so, reuse it.
4581ad6265SDimitry Andric   if (C) {
46*0fca6ea1SDimitry Andric     auto CItr = CachedConstantEntries.find(std::make_pair(C->getValue(), Size));
4781ad6265SDimitry Andric     if (CItr != CachedConstantEntries.end())
4881ad6265SDimitry Andric       return CItr->second;
4981ad6265SDimitry Andric   }
5081ad6265SDimitry Andric 
5181ad6265SDimitry Andric   // Check if there is existing entry for the same symbol. If so, reuse it.
5281ad6265SDimitry Andric   if (S) {
53*0fca6ea1SDimitry Andric     auto SItr =
54*0fca6ea1SDimitry Andric         CachedSymbolEntries.find(std::make_pair(&(S->getSymbol()), Size));
5581ad6265SDimitry Andric     if (SItr != CachedSymbolEntries.end())
5681ad6265SDimitry Andric       return SItr->second;
5781ad6265SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   MCSymbol *CPEntryLabel = Context.createTempSymbol();
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
620b57cec5SDimitry Andric   const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
630b57cec5SDimitry Andric   if (C)
64*0fca6ea1SDimitry Andric     CachedConstantEntries[std::make_pair(C->getValue(), Size)] = SymRef;
6581ad6265SDimitry Andric   if (S)
66*0fca6ea1SDimitry Andric     CachedSymbolEntries[std::make_pair(&(S->getSymbol()), Size)] = SymRef;
670b57cec5SDimitry Andric   return SymRef;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric bool ConstantPool::empty() { return Entries.empty(); }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric void ConstantPool::clearCache() {
7381ad6265SDimitry Andric   CachedConstantEntries.clear();
7481ad6265SDimitry Andric   CachedSymbolEntries.clear();
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric //
780b57cec5SDimitry Andric // AssemblerConstantPools implementation
790b57cec5SDimitry Andric //
800b57cec5SDimitry Andric ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) {
810b57cec5SDimitry Andric   ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
820b57cec5SDimitry Andric   if (CP == ConstantPools.end())
830b57cec5SDimitry Andric     return nullptr;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   return &CP->second;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric ConstantPool &
890b57cec5SDimitry Andric AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) {
900b57cec5SDimitry Andric   return ConstantPools[Section];
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric static void emitConstantPool(MCStreamer &Streamer, MCSection *Section,
940b57cec5SDimitry Andric                              ConstantPool &CP) {
950b57cec5SDimitry Andric   if (!CP.empty()) {
9681ad6265SDimitry Andric     Streamer.switchSection(Section);
970b57cec5SDimitry Andric     CP.emitEntries(Streamer);
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
1020b57cec5SDimitry Andric   // Dump contents of assembler constant pools.
1030b57cec5SDimitry Andric   for (auto &CPI : ConstantPools) {
1040b57cec5SDimitry Andric     MCSection *Section = CPI.first;
1050b57cec5SDimitry Andric     ConstantPool &CP = CPI.second;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric     emitConstantPool(Streamer, Section, CP);
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
1120b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
1130b57cec5SDimitry Andric   if (ConstantPool *CP = getConstantPool(Section))
1140b57cec5SDimitry Andric     emitConstantPool(Streamer, Section, *CP);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
1180b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
1190b57cec5SDimitry Andric   if (ConstantPool *CP = getConstantPool(Section))
1200b57cec5SDimitry Andric     CP->clearCache();
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
1240b57cec5SDimitry Andric                                                const MCExpr *Expr,
1250b57cec5SDimitry Andric                                                unsigned Size, SMLoc Loc) {
1260b57cec5SDimitry Andric   MCSection *Section = Streamer.getCurrentSectionOnly();
1270b57cec5SDimitry Andric   return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
1280b57cec5SDimitry Andric                                                    Size, Loc);
1290b57cec5SDimitry Andric }
130