| //===-- CSKYTargetStreamer.h - CSKY Target Streamer ----------*- C++ -*----===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "CSKYTargetStreamer.h" | |
| #include "CSKYSubtarget.h" | |
| #include "llvm/CodeGen/MachineFrameInfo.h" | |
| #include "llvm/CodeGen/TargetSubtargetInfo.h" | |
| #include "llvm/MC/MCContext.h" | |
| #include "llvm/MC/MCSectionELF.h" | |
| #include "llvm/Support/FormattedStream.h" | |
| using namespace llvm; | |
| // | |
| // ConstantPool implementation | |
| // | |
| // Emit the contents of the constant pool using the provided streamer. | |
| void CSKYConstantPool::emitAll(MCStreamer &Streamer) { | |
| if (Entries.empty()) | |
| return; | |
| if (CurrentSection != nullptr) | |
| Streamer.switchSection(CurrentSection); | |
| Streamer.emitDataRegion(MCDR_DataRegion); | |
| for (const ConstantPoolEntry &Entry : Entries) { | |
| Streamer.emitCodeAlignment( | |
| Align(Entry.Size), | |
| Streamer.getContext().getSubtargetInfo()); // align naturally | |
| Streamer.emitLabel(Entry.Label); | |
| Streamer.emitValue(Entry.Value, Entry.Size, Entry.Loc); | |
| } | |
| Streamer.emitDataRegion(MCDR_DataRegionEnd); | |
| Entries.clear(); | |
| } | |
| const MCExpr *CSKYConstantPool::addEntry(MCStreamer &Streamer, | |
| const MCExpr *Value, unsigned Size, | |
| SMLoc Loc, const MCExpr *AdjustExpr) { | |
| if (CurrentSection == nullptr) | |
| CurrentSection = Streamer.getCurrentSectionOnly(); | |
| auto &Context = Streamer.getContext(); | |
| const MCConstantExpr *C = dyn_cast<MCConstantExpr>(Value); | |
| // Check if there is existing entry for the same constant. If so, reuse it. | |
| auto Itr = C ? CachedEntries.find(C->getValue()) : CachedEntries.end(); | |
| if (Itr != CachedEntries.end()) | |
| return Itr->second; | |
| MCSymbol *CPEntryLabel = Context.createTempSymbol(); | |
| const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context); | |
| if (AdjustExpr) { | |
| const CSKYMCExpr *CSKYExpr = cast<CSKYMCExpr>(Value); | |
| Value = MCBinaryExpr::createSub(AdjustExpr, SymRef, Context); | |
| Value = MCBinaryExpr::createSub(CSKYExpr->getSubExpr(), Value, Context); | |
| Value = CSKYMCExpr::create(Value, CSKYExpr->getKind(), Context); | |
| } | |
| Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc)); | |
| if (C) | |
| CachedEntries[C->getValue()] = SymRef; | |
| return SymRef; | |
| } | |
| bool CSKYConstantPool::empty() { return Entries.empty(); } | |
| void CSKYConstantPool::clearCache() { | |
| CurrentSection = nullptr; | |
| CachedEntries.clear(); | |
| } | |
| CSKYTargetStreamer::CSKYTargetStreamer(MCStreamer &S) | |
| : MCTargetStreamer(S), ConstantPool(new CSKYConstantPool()) {} | |
| const MCExpr * | |
| CSKYTargetStreamer::addConstantPoolEntry(const MCExpr *Expr, SMLoc Loc, | |
| const MCExpr *AdjustExpr) { | |
| auto ELFRefKind = CSKYMCExpr::VK_CSKY_Invalid; | |
| ConstantCounter++; | |
| const MCExpr *OrigExpr = Expr; | |
| if (const CSKYMCExpr *CE = dyn_cast<CSKYMCExpr>(Expr)) { | |
| Expr = CE->getSubExpr(); | |
| ELFRefKind = CE->getKind(); | |
| } | |
| if (const MCSymbolRefExpr *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr)) { | |
| const MCSymbol *Sym = &SymExpr->getSymbol(); | |
| SymbolIndex Index = {Sym, ELFRefKind}; | |
| if (ConstantMap.find(Index) == ConstantMap.end()) { | |
| ConstantMap[Index] = | |
| ConstantPool->addEntry(getStreamer(), OrigExpr, 4, Loc, AdjustExpr); | |
| } | |
| return ConstantMap[Index]; | |
| } | |
| return ConstantPool->addEntry(getStreamer(), Expr, 4, Loc, AdjustExpr); | |
| } | |
| void CSKYTargetStreamer::emitCurrentConstantPool() { | |
| ConstantPool->emitAll(Streamer); | |
| ConstantPool->clearCache(); | |
| } | |
| // finish() - write out any non-empty assembler constant pools. | |
| void CSKYTargetStreamer::finish() { | |
| if (ConstantCounter != 0) { | |
| ConstantPool->emitAll(Streamer); | |
| } | |
| finishAttributeSection(); | |
| } | |
| void CSKYTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) {} | |
| void CSKYTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {} | |
| void CSKYTargetStreamer::emitTextAttribute(unsigned Attribute, | |
| StringRef String) {} | |
| void CSKYTargetStreamer::finishAttributeSection() {} | |
| void CSKYTargetAsmStreamer::emitAttribute(unsigned Attribute, unsigned Value) { | |
| OS << "\t.csky_attribute\t" << Attribute << ", " << Twine(Value) << "\n"; | |
| } | |
| void CSKYTargetAsmStreamer::emitTextAttribute(unsigned Attribute, | |
| StringRef String) { | |
| OS << "\t.csky_attribute\t" << Attribute << ", \"" << String << "\"\n"; | |
| } | |
| void CSKYTargetAsmStreamer::finishAttributeSection() {} |