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 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 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 565ffd83dbSDimitry Andric void MipsELFStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 570b57cec5SDimitry Andric Frame.Begin = getContext().createTempSymbol(); 585ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Frame.Begin); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 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 675ffd83dbSDimitry Andric void MipsELFStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 680b57cec5SDimitry Andric Frame.End = getContext().createTempSymbol(); 695ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Frame.End); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 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 885ffd83dbSDimitry Andric void MipsELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { 895ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Symbol); 900b57cec5SDimitry Andric Labels.push_back(Symbol); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 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 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 1045ffd83dbSDimitry Andric void MipsELFStreamer::emitIntValue(uint64_t Value, unsigned Size) { 1055ffd83dbSDimitry Andric MCELFStreamer::emitIntValue(Value, Size); 1060b57cec5SDimitry Andric Labels.clear(); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric void MipsELFStreamer::EmitMipsOptionRecords() { 1100b57cec5SDimitry Andric for (const auto &I : MipsOptionRecords) 1110b57cec5SDimitry Andric I->EmitMipsOptionRecord(); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 114*0fca6ea1SDimitry Andric MCELFStreamer * 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