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