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/MCObjectWriter.h"
20 #include "llvm/MC/MCSymbolELF.h"
21 #include "llvm/Support/Casting.h"
22 
23 using namespace llvm;
24 
25 MipsELFStreamer::MipsELFStreamer(MCContext &Context,
26                                  std::unique_ptr<MCAsmBackend> MAB,
27                                  std::unique_ptr<MCObjectWriter> OW,
28                                  std::unique_ptr<MCCodeEmitter> Emitter)
29     : MCELFStreamer(Context, std::move(MAB), std::move(OW),
30                     std::move(Emitter)) {
31   RegInfoRecord = new MipsRegInfoRecord(this, Context);
32   MipsOptionRecords.push_back(
33       std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord));
34 }
35 
36 void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
37                                       const MCSubtargetInfo &STI, bool) {
38   MCELFStreamer::EmitInstruction(Inst, STI);
39 
40   MCContext &Context = getContext();
41   const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo();
42 
43   for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) {
44     const MCOperand &Op = Inst.getOperand(OpIndex);
45 
46     if (!Op.isReg())
47       continue;
48 
49     unsigned Reg = Op.getReg();
50     RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo);
51   }
52 
53   createPendingLabelRelocs();
54 }
55 
56 void MipsELFStreamer::createPendingLabelRelocs() {
57   MipsTargetELFStreamer *ELFTargetStreamer =
58       static_cast<MipsTargetELFStreamer *>(getTargetStreamer());
59 
60   // FIXME: Also mark labels when in MIPS16 mode.
61   if (ELFTargetStreamer->isMicroMipsEnabled()) {
62     for (auto *L : Labels) {
63       auto *Label = cast<MCSymbolELF>(L);
64       getAssembler().registerSymbol(*Label);
65       Label->setOther(ELF::STO_MIPS_MICROMIPS);
66     }
67   }
68 
69   Labels.clear();
70 }
71 
72 void MipsELFStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
73   MCELFStreamer::EmitLabel(Symbol);
74   Labels.push_back(Symbol);
75 }
76 
77 void MipsELFStreamer::SwitchSection(MCSection *Section,
78                                     const MCExpr *Subsection) {
79   MCELFStreamer::SwitchSection(Section, Subsection);
80   Labels.clear();
81 }
82 
83 void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
84                                     SMLoc Loc) {
85   MCELFStreamer::EmitValueImpl(Value, Size, Loc);
86   Labels.clear();
87 }
88 
89 void MipsELFStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
90   MCELFStreamer::EmitIntValue(Value, Size);
91   Labels.clear();
92 }
93 
94 void MipsELFStreamer::EmitMipsOptionRecords() {
95   for (const auto &I : MipsOptionRecords)
96     I->EmitMipsOptionRecord();
97 }
98 
99 MCELFStreamer *llvm::createMipsELFStreamer(
100     MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
101     std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
102     bool RelaxAll) {
103   return new MipsELFStreamer(Context, std::move(MAB), std::move(OW),
104                              std::move(Emitter));
105 }
106