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