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