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