1 //===-------- MipsELFStreamer.cpp - ELF Object Output ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "MipsELFStreamer.h"
11 #include "MipsOptionRecord.h"
12 #include "MipsTargetStreamer.h"
13 #include "llvm/BinaryFormat/ELF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCAssembler.h"
16 #include "llvm/MC/MCCodeEmitter.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCSymbolELF.h"
20 #include "llvm/Support/Casting.h"
21 
22 using namespace llvm;
23 
24 MipsELFStreamer::MipsELFStreamer(MCContext &Context,
25                                  std::unique_ptr<MCAsmBackend> MAB,
26                                  raw_pwrite_stream &OS,
27                                  std::unique_ptr<MCCodeEmitter> Emitter)
28     : MCELFStreamer(Context, std::move(MAB), OS, std::move(Emitter)) {
29   RegInfoRecord = new MipsRegInfoRecord(this, Context);
30   MipsOptionRecords.push_back(
31       std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord));
32 }
33 
34 void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
35                                       const MCSubtargetInfo &STI, bool) {
36   MCELFStreamer::EmitInstruction(Inst, STI);
37 
38   MCContext &Context = getContext();
39   const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo();
40 
41   for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) {
42     const MCOperand &Op = Inst.getOperand(OpIndex);
43 
44     if (!Op.isReg())
45       continue;
46 
47     unsigned Reg = Op.getReg();
48     RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo);
49   }
50 
51   createPendingLabelRelocs();
52 }
53 
54 void MipsELFStreamer::createPendingLabelRelocs() {
55   MipsTargetELFStreamer *ELFTargetStreamer =
56       static_cast<MipsTargetELFStreamer *>(getTargetStreamer());
57 
58   // FIXME: Also mark labels when in MIPS16 mode.
59   if (ELFTargetStreamer->isMicroMipsEnabled()) {
60     for (auto *L : Labels) {
61       auto *Label = cast<MCSymbolELF>(L);
62       getAssembler().registerSymbol(*Label);
63       Label->setOther(ELF::STO_MIPS_MICROMIPS);
64     }
65   }
66 
67   Labels.clear();
68 }
69 
70 void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
71   MCELFStreamer::EmitLabel(Symbol);
72   Labels.push_back(Symbol);
73 }
74 
75 void MipsELFStreamer::SwitchSection(MCSection *Section,
76                                     const MCExpr *Subsection) {
77   MCELFStreamer::SwitchSection(Section, Subsection);
78   Labels.clear();
79 }
80 
81 void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
82                                     SMLoc Loc) {
83   MCELFStreamer::EmitValueImpl(Value, Size, Loc);
84   Labels.clear();
85 }
86 
87 void MipsELFStreamer::EmitMipsOptionRecords() {
88   for (const auto &I : MipsOptionRecords)
89     I->EmitMipsOptionRecord();
90 }
91 
92 MCELFStreamer *llvm::createMipsELFStreamer(
93     MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
94     raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter,
95     bool RelaxAll) {
96   return new MipsELFStreamer(Context, std::move(MAB), OS, std::move(Emitter));
97 }
98