//===-- XtensaTargetStreamer.cpp - Xtensa Target Streamer Methods ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file provides Xtensa specific target streamer methods.
//
//===----------------------------------------------------------------------===//
#include "XtensaTargetStreamer.h"
#include "XtensaInstPrinter.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
static std::string getLiteralSectionName(StringRef CSectionName) {
std::size_t Pos = CSectionName.find(".text");
std::string SectionName;
if (Pos != std::string::npos) {
SectionName = CSectionName.substr(0, Pos);
if (Pos > 0)
SectionName += ".text";
CSectionName = CSectionName.drop_front(Pos);
CSectionName.consume_front(".text");
SectionName += ".literal";
SectionName += CSectionName;
} else {
SectionName = CSectionName;
SectionName += ".literal";
}
return SectionName;
}
XtensaTargetStreamer::XtensaTargetStreamer(MCStreamer &S)
: MCTargetStreamer(S) {}
XtensaTargetAsmStreamer::XtensaTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
: XtensaTargetStreamer(S), OS(OS) {}
void XtensaTargetAsmStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
bool SwitchLiteralSection, SMLoc L) {
SmallString<60> Str;
raw_svector_ostream LiteralStr(Str);
LiteralStr << "\t.literal " << LblSym->getName() << ", ";
if (auto CE = dyn_cast<MCConstantExpr>(Value)) {
LiteralStr << CE->getValue() << "\n";
} else if (auto SRE = dyn_cast<MCSymbolRefExpr>(Value)) {
const MCSymbol &Sym = SRE->getSymbol();
LiteralStr << Sym.getName() << "\n";
} else {
llvm_unreachable("unexpected constant pool entry type");
}
OS << LiteralStr.str();
}
void XtensaTargetAsmStreamer::emitLiteralPosition() {
OS << "\t.literal_position\n";
}
void XtensaTargetAsmStreamer::startLiteralSection(MCSection *BaseSection) {
emitLiteralPosition();
}
XtensaTargetELFStreamer::XtensaTargetELFStreamer(MCStreamer &S)
: XtensaTargetStreamer(S) {}
void XtensaTargetELFStreamer::emitLiteral(MCSymbol *LblSym, const MCExpr *Value,
bool SwitchLiteralSection, SMLoc L) {
MCStreamer &OutStreamer = getStreamer();
if (SwitchLiteralSection) {
MCContext &Context = OutStreamer.getContext();
auto *CS = static_cast<MCSectionELF *>(OutStreamer.getCurrentSectionOnly());
std::string SectionName = getLiteralSectionName(CS->getName());
MCSection *ConstSection = Context.getELFSection(
SectionName, ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
OutStreamer.pushSection();
OutStreamer.switchSection(ConstSection);
}
OutStreamer.emitLabel(LblSym, L);
OutStreamer.emitValue(Value, 4, L);
if (SwitchLiteralSection) {
OutStreamer.popSection();
}
}
void XtensaTargetELFStreamer::startLiteralSection(MCSection *BaseSection) {
MCContext &Context = getStreamer().getContext();
std::string SectionName = getLiteralSectionName(BaseSection->getName());
MCSection *ConstSection = Context.getELFSection(
SectionName, ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
ConstSection->setAlignment(Align(4));
}
MCELFStreamer &XtensaTargetELFStreamer::getStreamer() {
return static_cast<MCELFStreamer &>(Streamer);
}