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
20using namespace llvm;
21
22//
23// ConstantPool implementation
24//
25// Emit the contents of the constant pool using the provided streamer.
26void ConstantPool::emitEntries(MCStreamer &Streamer) {
27  if (Entries.empty())
28    return;
29  Streamer.EmitDataRegion(MCDR_DataRegion);
30  for (const ConstantPoolEntry &Entry : Entries) {
31    Streamer.EmitCodeAlignment(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
39const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
40                                     unsigned Size, SMLoc Loc) {
41  const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
42
43  // Check if there is existing entry for the same constant. If so, reuse it.
44  auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end();
45  if (Itr != CachedEntries.end())
46    return Itr->second;
47
48  MCSymbol *CPEntryLabel = Context.createTempSymbol();
49
50  Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
51  const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
52  if (C)
53    CachedEntries[C->getValue()] = SymRef;
54  return SymRef;
55}
56
57bool ConstantPool::empty() { return Entries.empty(); }
58
59void ConstantPool::clearCache() {
60  CachedEntries.clear();
61}
62
63//
64// AssemblerConstantPools implementation
65//
66ConstantPool *AssemblerConstantPools::getConstantPool(MCSection *Section) {
67  ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
68  if (CP == ConstantPools.end())
69    return nullptr;
70
71  return &CP->second;
72}
73
74ConstantPool &
75AssemblerConstantPools::getOrCreateConstantPool(MCSection *Section) {
76  return ConstantPools[Section];
77}
78
79static void emitConstantPool(MCStreamer &Streamer, MCSection *Section,
80                             ConstantPool &CP) {
81  if (!CP.empty()) {
82    Streamer.SwitchSection(Section);
83    CP.emitEntries(Streamer);
84  }
85}
86
87void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
88  // Dump contents of assembler constant pools.
89  for (auto &CPI : ConstantPools) {
90    MCSection *Section = CPI.first;
91    ConstantPool &CP = CPI.second;
92
93    emitConstantPool(Streamer, Section, CP);
94  }
95}
96
97void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
98  MCSection *Section = Streamer.getCurrentSectionOnly();
99  if (ConstantPool *CP = getConstantPool(Section))
100    emitConstantPool(Streamer, Section, *CP);
101}
102
103void AssemblerConstantPools::clearCacheForCurrentSection(MCStreamer &Streamer) {
104  MCSection *Section = Streamer.getCurrentSectionOnly();
105  if (ConstantPool *CP = getConstantPool(Section))
106    CP->clearCache();
107}
108
109const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
110                                               const MCExpr *Expr,
111                                               unsigned Size, SMLoc Loc) {
112  MCSection *Section = Streamer.getCurrentSectionOnly();
113  return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
114                                                   Size, Loc);
115}
116