MCObjectStreamer.cpp revision 2d8e3e741f49baadfc72403de9c4b362a07af8d9
1//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
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 "llvm/MC/MCObjectStreamer.h"
11
12#include "llvm/Support/ErrorHandling.h"
13#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCCodeEmitter.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCDwarf.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCSymbol.h"
19#include "llvm/Target/TargetAsmBackend.h"
20#include "llvm/Target/TargetAsmInfo.h"
21using namespace llvm;
22
23MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
24                                   raw_ostream &_OS, MCCodeEmitter *_Emitter)
25  : MCStreamer(Context), Assembler(new MCAssembler(Context, TAB,
26                                                   *_Emitter,
27                                                   _OS)),
28    CurSectionData(0)
29{
30}
31
32MCObjectStreamer::~MCObjectStreamer() {
33  delete &Assembler->getBackend();
34  delete &Assembler->getEmitter();
35  delete Assembler;
36}
37
38MCFragment *MCObjectStreamer::getCurrentFragment() const {
39  assert(getCurrentSectionData() && "No current section!");
40
41  if (!getCurrentSectionData()->empty())
42    return &getCurrentSectionData()->getFragmentList().back();
43
44  return 0;
45}
46
47MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const {
48  MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
49  if (!F)
50    F = new MCDataFragment(getCurrentSectionData());
51  return F;
52}
53
54const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
55  switch (Value->getKind()) {
56  case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!");
57  case MCExpr::Constant:
58    break;
59
60  case MCExpr::Binary: {
61    const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
62    AddValueSymbols(BE->getLHS());
63    AddValueSymbols(BE->getRHS());
64    break;
65  }
66
67  case MCExpr::SymbolRef:
68    Assembler->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
69    break;
70
71  case MCExpr::Unary:
72    AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr());
73    break;
74  }
75
76  return Value;
77}
78
79void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
80                                     bool isPCRel, unsigned AddrSpace) {
81  assert(AddrSpace == 0 && "Address space must be 0!");
82  MCDataFragment *DF = getOrCreateDataFragment();
83
84  // Avoid fixups when possible.
85  int64_t AbsValue;
86  if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) {
87    EmitIntValue(AbsValue, Size, AddrSpace);
88    return;
89  }
90  DF->addFixup(MCFixup::Create(DF->getContents().size(),
91                               AddValueSymbols(Value),
92                               MCFixup::getKindForSize(Size, isPCRel)));
93  DF->getContents().resize(DF->getContents().size() + Size, 0);
94}
95
96void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
97  assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
98  assert(CurSection && "Cannot emit before setting section!");
99
100  Symbol->setSection(*CurSection);
101
102  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
103
104  // FIXME: This is wasteful, we don't necessarily need to create a data
105  // fragment. Instead, we should mark the symbol as pointing into the data
106  // fragment if it exists, otherwise we should just queue the label and set its
107  // fragment pointer when we emit the next fragment.
108  MCDataFragment *F = getOrCreateDataFragment();
109  assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
110  SD.setFragment(F);
111  SD.setOffset(F->getContents().size());
112}
113
114void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
115                                        unsigned AddrSpace) {
116  int64_t IntValue;
117  if (Value->EvaluateAsAbsolute(IntValue)) {
118    EmitULEB128IntValue(IntValue, AddrSpace);
119    return;
120  }
121  new MCLEBFragment(*Value, false, getCurrentSectionData());
122}
123
124void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
125                                        unsigned AddrSpace) {
126  int64_t IntValue;
127  if (Value->EvaluateAsAbsolute(IntValue)) {
128    EmitSLEB128IntValue(IntValue, AddrSpace);
129    return;
130  }
131  new MCLEBFragment(*Value, true, getCurrentSectionData());
132}
133
134void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
135                                         const MCSymbol *Symbol) {
136  report_fatal_error("This file format doesn't support weak aliases.");
137}
138
139void MCObjectStreamer::SwitchSection(const MCSection *Section) {
140  assert(Section && "Cannot switch to a null section!");
141
142  // If already in this section, then this is a noop.
143  if (Section == CurSection) return;
144
145  PrevSection = CurSection;
146  CurSection = Section;
147  CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
148}
149
150void MCObjectStreamer::EmitInstruction(const MCInst &Inst) {
151  // Scan for values.
152  for (unsigned i = Inst.getNumOperands(); i--; )
153    if (Inst.getOperand(i).isExpr())
154      AddValueSymbols(Inst.getOperand(i).getExpr());
155
156  getCurrentSectionData()->setHasInstructions(true);
157
158  // Now that a machine instruction has been assembled into this section, make
159  // a line entry for any .loc directive that has been seen.
160  MCLineEntry::Make(this, getCurrentSection());
161
162  // If this instruction doesn't need relaxation, just emit it as data.
163  if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
164    EmitInstToData(Inst);
165    return;
166  }
167
168  // Otherwise, if we are relaxing everything, relax the instruction as much as
169  // possible and emit it as data.
170  if (getAssembler().getRelaxAll()) {
171    MCInst Relaxed;
172    getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
173    while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
174      getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
175    EmitInstToData(Relaxed);
176    return;
177  }
178
179  // Otherwise emit to a separate fragment.
180  EmitInstToFragment(Inst);
181}
182
183void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
184  MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());
185
186  raw_svector_ostream VecOS(IF->getCode());
187  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups());
188}
189
190void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
191                                                const MCSymbol *LastLabel,
192                                                const MCSymbol *Label) {
193  if (!LastLabel) {
194    int PointerSize = getContext().getTargetAsmInfo().getPointerSize();
195    EmitDwarfSetLineAddr(LineDelta, Label, PointerSize);
196    return;
197  }
198  MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
199  const MCExpr *LabelRef =
200    MCSymbolRefExpr::Create(Label, Variant, getContext());
201  const MCExpr *LastLabelRef =
202    MCSymbolRefExpr::Create(LastLabel, Variant, getContext());
203  const MCExpr *AddrDelta =
204    MCBinaryExpr::Create(MCBinaryExpr::Sub, LabelRef, LastLabelRef,
205                         getContext());
206  int64_t Res;
207  if (AddrDelta->EvaluateAsAbsolute(Res)) {
208    MCDwarfLineAddr::Emit(this, LineDelta, Res);
209    return;
210  }
211  new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());
212}
213
214void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
215                                        unsigned char Value) {
216  new MCOrgFragment(*Offset, Value, getCurrentSectionData());
217}
218
219void MCObjectStreamer::Finish() {
220  // Dump out the dwarf file & directory tables and line tables.
221  if (getContext().hasDwarfFiles())
222    MCDwarfFileTable::Emit(this);
223
224  getAssembler().Finish();
225}
226