10b57cec5SDimitry Andric //===-------- MipsELFStreamer.cpp - ELF Object Output ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "MipsELFStreamer.h"
100b57cec5SDimitry Andric #include "MipsOptionRecord.h"
110b57cec5SDimitry Andric #include "MipsTargetStreamer.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
210b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric
MipsELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)250b57cec5SDimitry Andric MipsELFStreamer::MipsELFStreamer(MCContext &Context,
260b57cec5SDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
270b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter> OW,
280b57cec5SDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter)
290b57cec5SDimitry Andric : MCELFStreamer(Context, std::move(MAB), std::move(OW),
300b57cec5SDimitry Andric std::move(Emitter)) {
310b57cec5SDimitry Andric RegInfoRecord = new MipsRegInfoRecord(this, Context);
320b57cec5SDimitry Andric MipsOptionRecords.push_back(
330b57cec5SDimitry Andric std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord));
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)365ffd83dbSDimitry Andric void MipsELFStreamer::emitInstruction(const MCInst &Inst,
370b57cec5SDimitry Andric const MCSubtargetInfo &STI) {
385ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI);
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric MCContext &Context = getContext();
410b57cec5SDimitry Andric const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo();
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) {
440b57cec5SDimitry Andric const MCOperand &Op = Inst.getOperand(OpIndex);
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric if (!Op.isReg())
470b57cec5SDimitry Andric continue;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric unsigned Reg = Op.getReg();
500b57cec5SDimitry Andric RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo);
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric createPendingLabelRelocs();
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
emitCFIStartProcImpl(MCDwarfFrameInfo & Frame)565ffd83dbSDimitry Andric void MipsELFStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
570b57cec5SDimitry Andric Frame.Begin = getContext().createTempSymbol();
585ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Frame.Begin);
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
emitCFILabel()615ffd83dbSDimitry Andric MCSymbol *MipsELFStreamer::emitCFILabel() {
620b57cec5SDimitry Andric MCSymbol *Label = getContext().createTempSymbol("cfi", true);
635ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Label);
640b57cec5SDimitry Andric return Label;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
emitCFIEndProcImpl(MCDwarfFrameInfo & Frame)675ffd83dbSDimitry Andric void MipsELFStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
680b57cec5SDimitry Andric Frame.End = getContext().createTempSymbol();
695ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Frame.End);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric
createPendingLabelRelocs()720b57cec5SDimitry Andric void MipsELFStreamer::createPendingLabelRelocs() {
730b57cec5SDimitry Andric MipsTargetELFStreamer *ELFTargetStreamer =
740b57cec5SDimitry Andric static_cast<MipsTargetELFStreamer *>(getTargetStreamer());
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric // FIXME: Also mark labels when in MIPS16 mode.
770b57cec5SDimitry Andric if (ELFTargetStreamer->isMicroMipsEnabled()) {
780b57cec5SDimitry Andric for (auto *L : Labels) {
790b57cec5SDimitry Andric auto *Label = cast<MCSymbolELF>(L);
800b57cec5SDimitry Andric getAssembler().registerSymbol(*Label);
810b57cec5SDimitry Andric Label->setOther(ELF::STO_MIPS_MICROMIPS);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric Labels.clear();
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
emitLabel(MCSymbol * Symbol,SMLoc Loc)885ffd83dbSDimitry Andric void MipsELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
895ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Symbol);
900b57cec5SDimitry Andric Labels.push_back(Symbol);
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
switchSection(MCSection * Section,uint32_t Subsection)93*0fca6ea1SDimitry Andric void MipsELFStreamer::switchSection(MCSection *Section, uint32_t Subsection) {
9481ad6265SDimitry Andric MCELFStreamer::switchSection(Section, Subsection);
950b57cec5SDimitry Andric Labels.clear();
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)985ffd83dbSDimitry Andric void MipsELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
990b57cec5SDimitry Andric SMLoc Loc) {
1005ffd83dbSDimitry Andric MCELFStreamer::emitValueImpl(Value, Size, Loc);
1010b57cec5SDimitry Andric Labels.clear();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
emitIntValue(uint64_t Value,unsigned Size)1045ffd83dbSDimitry Andric void MipsELFStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1055ffd83dbSDimitry Andric MCELFStreamer::emitIntValue(Value, Size);
1060b57cec5SDimitry Andric Labels.clear();
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
EmitMipsOptionRecords()1090b57cec5SDimitry Andric void MipsELFStreamer::EmitMipsOptionRecords() {
1100b57cec5SDimitry Andric for (const auto &I : MipsOptionRecords)
1110b57cec5SDimitry Andric I->EmitMipsOptionRecord();
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
114*0fca6ea1SDimitry Andric MCELFStreamer *
createMipsELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)115*0fca6ea1SDimitry Andric llvm::createMipsELFStreamer(MCContext &Context,
116*0fca6ea1SDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
117*0fca6ea1SDimitry Andric std::unique_ptr<MCObjectWriter> OW,
118*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) {
1190b57cec5SDimitry Andric return new MipsELFStreamer(Context, std::move(MAB), std::move(OW),
1200b57cec5SDimitry Andric std::move(Emitter));
1210b57cec5SDimitry Andric }
122