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