Implement base Calling Convention functionality. Implement stack load/store register operations. Implement call lowering.
120 lines
3.8 KiB
C++
120 lines
3.8 KiB
C++
//===-- 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);
|
|
}
|