1 //===-- CSKYTargetStreamer.h - CSKY Target Streamer ----------*- C++ -*----===//
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 #include "CSKYTargetStreamer.h"
10 #include "CSKYSubtarget.h"
11 #include "llvm/CodeGen/MachineFrameInfo.h"
12 #include "llvm/CodeGen/TargetSubtargetInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCSectionELF.h"
15 #include "llvm/Support/FormattedStream.h"
16 
17 using namespace llvm;
18 
19 //
20 // ConstantPool implementation
21 //
22 // Emit the contents of the constant pool using the provided streamer.
23 void CSKYConstantPool::emitAll(MCStreamer &Streamer) {
24   if (Entries.empty())
25     return;
26 
27   if (CurrentSection != nullptr)
28     Streamer.switchSection(CurrentSection);
29 
30   Streamer.emitDataRegion(MCDR_DataRegion);
31   for (const ConstantPoolEntry &Entry : Entries) {
32     Streamer.emitCodeAlignment(
33         Align(Entry.Size),
34         Streamer.getContext().getSubtargetInfo()); // align naturally
35     Streamer.emitLabel(Entry.Label);
36     Streamer.emitValue(Entry.Value, Entry.Size, Entry.Loc);
37   }
38   Streamer.emitDataRegion(MCDR_DataRegionEnd);
39   Entries.clear();
40 }
41 
42 const MCExpr *CSKYConstantPool::addEntry(MCStreamer &Streamer,
43                                          const MCExpr *Value, unsigned Size,
44                                          SMLoc Loc, const MCExpr *AdjustExpr) {
45   if (CurrentSection == nullptr)
46     CurrentSection = Streamer.getCurrentSectionOnly();
47 
48   auto &Context = Streamer.getContext();
49 
50   const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value);
51 
52   // Check if there is existing entry for the same constant. If so, reuse it.
53   auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end();
54   if (Itr != CachedEntries.end())
55     return Itr->second;
56 
57   MCSymbol *CPEntryLabel = Context.createTempSymbol();
58   const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context);
59 
60   if (AdjustExpr) {
61     const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Value);
62 
63     Value = MCBinaryExpr::createSub(AdjustExpr, SymRef, Context);
64     Value = MCBinaryExpr::createSub(CSKYExpr->getSubExpr(), Value, Context);
65     Value = CSKYMCExpr::create(Value, CSKYExpr->getKind(), Context);
66   }
67 
68   Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc));
69 
70   if (C)
71     CachedEntries[C->getValue()] = SymRef;
72   return SymRef;
73 }
74 
75 bool CSKYConstantPool::empty() { return Entries.empty(); }
76 
77 void CSKYConstantPool::clearCache() {
78   CurrentSection = nullptr;
79   CachedEntries.clear();
80 }
81 
82 CSKYTargetStreamer::CSKYTargetStreamer(MCStreamer &S)
83     : MCTargetStreamer(S), ConstantPool(new CSKYConstantPool()) {}
84 
85 const MCExpr *
86 CSKYTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc,
87                                          const MCExpr *AdjustExpr) {
88   auto ELFRefKind = CSKYMCExpr::VK_CSKY_Invalid;
89   ConstantCounter++;
90 
91   const MCExpr *OrigExpr = Expr;
92 
93   if (const CSKYMCExpr *CE = dyn_cast<CSKYMCExpr>(Expr)) {
94     Expr = CE->getSubExpr();
95     ELFRefKind = CE->getKind();
96   }
97 
98   if (const MCSymbolRefExpr *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
99     const MCSymbol *Sym = &SymExpr->getSymbol();
100 
101     SymbolIndex Index = {Sym, ELFRefKind};
102 
103     if (ConstantMap.find(Index) == ConstantMap.end()) {
104       ConstantMap[Index] =
105           ConstantPool->addEntry(getStreamer(), OrigExpr, 4, Loc, AdjustExpr);
106     }
107     return ConstantMap[Index];
108   }
109 
110   return ConstantPool->addEntry(getStreamer(), Expr, 4, Loc, AdjustExpr);
111 }
112 
113 void CSKYTargetStreamer::emitCurrentConstantPool() {
114   ConstantPool->emitAll(Streamer);
115   ConstantPool->clearCache();
116 }
117 
118 // finish() - write out any non-empty assembler constant pools.
119 void CSKYTargetStreamer::finish() {
120   if (ConstantCounter != 0) {
121     ConstantPool->emitAll(Streamer);
122   }
123 
124   finishAttributeSection();
125 }
126 
127 void CSKYTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {}
128 
129 void CSKYTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
130 void CSKYTargetStreamer::emitTextAttribute(unsigned Attribute,
131                                            StringRef String) {}
132 void CSKYTargetStreamer::finishAttributeSection() {}
133 
134 void CSKYTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
135   OS << "\t.csky_attribute\t" << Attribute << ", " << Twine(Value) << "\n";
136 }
137 
138 void CSKYTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
139                                               StringRef String) {
140   OS << "\t.csky_attribute\t" << Attribute << ", \"" << String << "\"\n";
141 }
142 
143 void CSKYTargetAsmStreamer::finishAttributeSection() {}
144