191bc56edSDimitry Andric //===-------- MipsELFStreamer.cpp - ELF Object Output ---------------------===//
291bc56edSDimitry Andric //
391bc56edSDimitry Andric //                     The LLVM Compiler Infrastructure
491bc56edSDimitry Andric //
591bc56edSDimitry Andric // This file is distributed under the University of Illinois Open Source
691bc56edSDimitry Andric // License. See LICENSE.TXT for details.
791bc56edSDimitry Andric //
891bc56edSDimitry Andric //===----------------------------------------------------------------------===//
991bc56edSDimitry Andric 
1091bc56edSDimitry Andric #include "MipsELFStreamer.h"
117a7e6055SDimitry Andric #include "MipsOptionRecord.h"
1239d628a0SDimitry Andric #include "MipsTargetStreamer.h"
13db17bf38SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
142cab237bSDimitry Andric #include "llvm/MC/MCAsmBackend.h"
157a7e6055SDimitry Andric #include "llvm/MC/MCAssembler.h"
162cab237bSDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
177a7e6055SDimitry Andric #include "llvm/MC/MCContext.h"
18*4ba319b5SDimitry Andric #include "llvm/MC/MCDwarf.h"
1991bc56edSDimitry Andric #include "llvm/MC/MCInst.h"
20*4ba319b5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
2197bc6c73SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
227a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
2339d628a0SDimitry Andric 
2439d628a0SDimitry Andric using namespace llvm;
2591bc56edSDimitry Andric 
MipsELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)262cab237bSDimitry Andric MipsELFStreamer::MipsELFStreamer(MCContext &Context,
272cab237bSDimitry Andric                                  std::unique_ptr<MCAsmBackend> MAB,
28*4ba319b5SDimitry Andric                                  std::unique_ptr<MCObjectWriter> OW,
292cab237bSDimitry Andric                                  std::unique_ptr<MCCodeEmitter> Emitter)
30*4ba319b5SDimitry Andric     : MCELFStreamer(Context, std::move(MAB), std::move(OW),
31*4ba319b5SDimitry Andric                     std::move(Emitter)) {
322cab237bSDimitry Andric   RegInfoRecord = new MipsRegInfoRecord(this, Context);
332cab237bSDimitry Andric   MipsOptionRecords.push_back(
342cab237bSDimitry Andric       std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord));
352cab237bSDimitry Andric }
362cab237bSDimitry Andric 
EmitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,bool)3791bc56edSDimitry Andric void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
387a7e6055SDimitry Andric                                       const MCSubtargetInfo &STI, bool) {
3991bc56edSDimitry Andric   MCELFStreamer::EmitInstruction(Inst, STI);
4091bc56edSDimitry Andric 
4191bc56edSDimitry Andric   MCContext &Context = getContext();
4291bc56edSDimitry Andric   const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo();
4391bc56edSDimitry Andric 
4491bc56edSDimitry Andric   for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) {
4591bc56edSDimitry Andric     const MCOperand &Op = Inst.getOperand(OpIndex);
4691bc56edSDimitry Andric 
4791bc56edSDimitry Andric     if (!Op.isReg())
4891bc56edSDimitry Andric       continue;
4991bc56edSDimitry Andric 
5091bc56edSDimitry Andric     unsigned Reg = Op.getReg();
5191bc56edSDimitry Andric     RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo);
5291bc56edSDimitry Andric   }
5339d628a0SDimitry Andric 
54ff0cc061SDimitry Andric   createPendingLabelRelocs();
55ff0cc061SDimitry Andric }
56ff0cc061SDimitry Andric 
EmitCFIStartProcImpl(MCDwarfFrameInfo & Frame)57*4ba319b5SDimitry Andric void MipsELFStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
58*4ba319b5SDimitry Andric   Frame.Begin = getContext().createTempSymbol();
59*4ba319b5SDimitry Andric   MCELFStreamer::EmitLabel(Frame.Begin);
60*4ba319b5SDimitry Andric }
61*4ba319b5SDimitry Andric 
EmitCFILabel()62*4ba319b5SDimitry Andric MCSymbol *MipsELFStreamer::EmitCFILabel() {
63*4ba319b5SDimitry Andric   MCSymbol *Label = getContext().createTempSymbol("cfi", true);
64*4ba319b5SDimitry Andric   MCELFStreamer::EmitLabel(Label);
65*4ba319b5SDimitry Andric   return Label;
66*4ba319b5SDimitry Andric }
67*4ba319b5SDimitry Andric 
EmitCFIEndProcImpl(MCDwarfFrameInfo & Frame)68*4ba319b5SDimitry Andric void MipsELFStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
69*4ba319b5SDimitry Andric   Frame.End = getContext().createTempSymbol();
70*4ba319b5SDimitry Andric   MCELFStreamer::EmitLabel(Frame.End);
71*4ba319b5SDimitry Andric }
72*4ba319b5SDimitry Andric 
createPendingLabelRelocs()73ff0cc061SDimitry Andric void MipsELFStreamer::createPendingLabelRelocs() {
74ff0cc061SDimitry Andric   MipsTargetELFStreamer *ELFTargetStreamer =
75ff0cc061SDimitry Andric       static_cast<MipsTargetELFStreamer *>(getTargetStreamer());
76ff0cc061SDimitry Andric 
77ff0cc061SDimitry Andric   // FIXME: Also mark labels when in MIPS16 mode.
7839d628a0SDimitry Andric   if (ELFTargetStreamer->isMicroMipsEnabled()) {
7997bc6c73SDimitry Andric     for (auto *L : Labels) {
8097bc6c73SDimitry Andric       auto *Label = cast<MCSymbolELF>(L);
8197bc6c73SDimitry Andric       getAssembler().registerSymbol(*Label);
8297bc6c73SDimitry Andric       Label->setOther(ELF::STO_MIPS_MICROMIPS);
8339d628a0SDimitry Andric     }
8439d628a0SDimitry Andric   }
8539d628a0SDimitry Andric 
8639d628a0SDimitry Andric   Labels.clear();
8739d628a0SDimitry Andric }
8839d628a0SDimitry Andric 
EmitLabel(MCSymbol * Symbol,SMLoc Loc)897a7e6055SDimitry Andric void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
9039d628a0SDimitry Andric   MCELFStreamer::EmitLabel(Symbol);
9139d628a0SDimitry Andric   Labels.push_back(Symbol);
9239d628a0SDimitry Andric }
9339d628a0SDimitry Andric 
SwitchSection(MCSection * Section,const MCExpr * Subsection)94ff0cc061SDimitry Andric void MipsELFStreamer::SwitchSection(MCSection *Section,
9539d628a0SDimitry Andric                                     const MCExpr *Subsection) {
9639d628a0SDimitry Andric   MCELFStreamer::SwitchSection(Section, Subsection);
9739d628a0SDimitry Andric   Labels.clear();
9839d628a0SDimitry Andric }
9939d628a0SDimitry Andric 
EmitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)10039d628a0SDimitry Andric void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
1017d523365SDimitry Andric                                     SMLoc Loc) {
10239d628a0SDimitry Andric   MCELFStreamer::EmitValueImpl(Value, Size, Loc);
10339d628a0SDimitry Andric   Labels.clear();
10491bc56edSDimitry Andric }
10591bc56edSDimitry Andric 
EmitIntValue(uint64_t Value,unsigned Size)106*4ba319b5SDimitry Andric void MipsELFStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
107*4ba319b5SDimitry Andric   MCELFStreamer::EmitIntValue(Value, Size);
108*4ba319b5SDimitry Andric   Labels.clear();
109*4ba319b5SDimitry Andric }
110*4ba319b5SDimitry Andric 
EmitMipsOptionRecords()11191bc56edSDimitry Andric void MipsELFStreamer::EmitMipsOptionRecords() {
11291bc56edSDimitry Andric   for (const auto &I : MipsOptionRecords)
11391bc56edSDimitry Andric     I->EmitMipsOptionRecord();
11491bc56edSDimitry Andric }
11591bc56edSDimitry Andric 
createMipsELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter,bool RelaxAll)1162cab237bSDimitry Andric MCELFStreamer *llvm::createMipsELFStreamer(
1172cab237bSDimitry Andric     MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
118*4ba319b5SDimitry Andric     std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
11939d628a0SDimitry Andric     bool RelaxAll) {
120*4ba319b5SDimitry Andric   return new MipsELFStreamer(Context, std::move(MAB), std::move(OW),
121*4ba319b5SDimitry Andric                              std::move(Emitter));
12291bc56edSDimitry Andric }
123