blob: 035826690cdfaba2c1caa4f975dc47fe22885859 [file] [log] [blame]
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +00001//===- 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
Rafael Espindola835439a2010-12-22 22:04:28 +000010#include "llvm/MC/MCAsmInfo.h"
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +000011#include "llvm/MC/MCObjectStreamer.h"
12
Michael J. Spencer8067adc2010-07-19 06:13:10 +000013#include "llvm/Support/ErrorHandling.h"
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +000014#include "llvm/MC/MCAssembler.h"
Benjamin Kramer1abcd062010-07-29 17:48:06 +000015#include "llvm/MC/MCCodeEmitter.h"
Rafael Espindola89b93722010-12-10 07:39:47 +000016#include "llvm/MC/MCContext.h"
Rafael Espindolaf89671d2010-11-01 16:27:31 +000017#include "llvm/MC/MCDwarf.h"
Michael J. Spencer8067adc2010-07-19 06:13:10 +000018#include "llvm/MC/MCExpr.h"
Rafael Espindolaea4afa92010-11-28 17:18:55 +000019#include "llvm/MC/MCSymbol.h"
Benjamin Kramer1abcd062010-07-29 17:48:06 +000020#include "llvm/Target/TargetAsmBackend.h"
Rafael Espindola89b93722010-12-10 07:39:47 +000021#include "llvm/Target/TargetAsmInfo.h"
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +000022using namespace llvm;
23
24MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB,
Daniel Dunbarfeb7ba32010-12-17 02:45:41 +000025 raw_ostream &OS, MCCodeEmitter *Emitter_)
26 : MCStreamer(Context),
27 Assembler(new MCAssembler(Context, TAB,
28 *Emitter_, *TAB.createObjectWriter(OS),
29 OS)),
Daniel Dunbar83b46712010-06-16 20:04:25 +000030 CurSectionData(0)
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +000031{
32}
33
34MCObjectStreamer::~MCObjectStreamer() {
Benjamin Kramer1abcd062010-07-29 17:48:06 +000035 delete &Assembler->getBackend();
36 delete &Assembler->getEmitter();
Daniel Dunbarfeb7ba32010-12-17 02:45:41 +000037 delete &Assembler->getWriter();
Daniel Dunbar8dc68ab2010-06-16 20:04:22 +000038 delete Assembler;
39}
Daniel Dunbar83b46712010-06-16 20:04:25 +000040
Michael J. Spencer8067adc2010-07-19 06:13:10 +000041MCFragment *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()) {
Evan Cheng75972122011-01-13 07:58:56 +000059 case MCExpr::Target:
60 cast<MCTargetExpr>(Value)->AddValueSymbols(Assembler);
61 break;
62
Michael J. Spencer8067adc2010-07-19 06:13:10 +000063 case MCExpr::Constant:
64 break;
65
66 case MCExpr::Binary: {
67 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
68 AddValueSymbols(BE->getLHS());
69 AddValueSymbols(BE->getRHS());
70 break;
71 }
72
73 case MCExpr::SymbolRef:
74 Assembler->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
75 break;
76
77 case MCExpr::Unary:
78 AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr());
79 break;
80 }
81
82 return Value;
83}
84
Rafael Espindola89b93722010-12-10 07:39:47 +000085void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
86 bool isPCRel, unsigned AddrSpace) {
Rafael Espindola6f950232010-11-28 23:08:47 +000087 assert(AddrSpace == 0 && "Address space must be 0!");
88 MCDataFragment *DF = getOrCreateDataFragment();
89
90 // Avoid fixups when possible.
91 int64_t AbsValue;
Rafael Espindolad0764822010-12-18 03:57:21 +000092 if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) {
Rafael Espindola2df042c2010-12-03 02:54:21 +000093 EmitIntValue(AbsValue, Size, AddrSpace);
94 return;
Rafael Espindola6f950232010-11-28 23:08:47 +000095 }
Rafael Espindola2df042c2010-12-03 02:54:21 +000096 DF->addFixup(MCFixup::Create(DF->getContents().size(),
Rafael Espindola835439a2010-12-22 22:04:28 +000097 Value,
Rafael Espindola89b93722010-12-10 07:39:47 +000098 MCFixup::getKindForSize(Size, isPCRel)));
Rafael Espindola2df042c2010-12-03 02:54:21 +000099 DF->getContents().resize(DF->getContents().size() + Size, 0);
Rafael Espindola6f950232010-11-28 23:08:47 +0000100}
101
Rafael Espindolaea4afa92010-11-28 17:18:55 +0000102void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
103 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000104 assert(getCurrentSection() && "Cannot emit before setting section!");
Rafael Espindolaea4afa92010-11-28 17:18:55 +0000105
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000106 Symbol->setSection(*getCurrentSection());
Rafael Espindolaea4afa92010-11-28 17:18:55 +0000107
108 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
109
110 // FIXME: This is wasteful, we don't necessarily need to create a data
111 // fragment. Instead, we should mark the symbol as pointing into the data
112 // fragment if it exists, otherwise we should just queue the label and set its
113 // fragment pointer when we emit the next fragment.
114 MCDataFragment *F = getOrCreateDataFragment();
115 assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
116 SD.setFragment(F);
117 SD.setOffset(F->getContents().size());
118}
119
Rafael Espindola3ff57092010-11-02 17:22:24 +0000120void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
121 unsigned AddrSpace) {
Rafael Espindola660b5fc2010-12-03 01:19:49 +0000122 int64_t IntValue;
Rafael Espindolad0764822010-12-18 03:57:21 +0000123 if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) {
Rafael Espindola660b5fc2010-12-03 01:19:49 +0000124 EmitULEB128IntValue(IntValue, AddrSpace);
125 return;
126 }
Rafael Espindola3ff57092010-11-02 17:22:24 +0000127 new MCLEBFragment(*Value, false, getCurrentSectionData());
128}
129
130void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
131 unsigned AddrSpace) {
Rafael Espindola660b5fc2010-12-03 01:19:49 +0000132 int64_t IntValue;
Rafael Espindolad0764822010-12-18 03:57:21 +0000133 if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) {
Rafael Espindola660b5fc2010-12-03 01:19:49 +0000134 EmitSLEB128IntValue(IntValue, AddrSpace);
135 return;
136 }
Rafael Espindola3ff57092010-11-02 17:22:24 +0000137 new MCLEBFragment(*Value, true, getCurrentSectionData());
138}
139
Rafael Espindola484291c2010-11-01 14:28:48 +0000140void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
141 const MCSymbol *Symbol) {
142 report_fatal_error("This file format doesn't support weak aliases.");
143}
144
Rafael Espindola7768a9d2011-02-16 01:08:29 +0000145void MCObjectStreamer::ChangeSection(const MCSection *Section) {
Daniel Dunbar83b46712010-06-16 20:04:25 +0000146 assert(Section && "Cannot switch to a null section!");
147
Daniel Dunbar83b46712010-06-16 20:04:25 +0000148 CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
149}
150
Rafael Espindolaf89671d2010-11-01 16:27:31 +0000151void MCObjectStreamer::EmitInstruction(const MCInst &Inst) {
152 // Scan for values.
153 for (unsigned i = Inst.getNumOperands(); i--; )
154 if (Inst.getOperand(i).isExpr())
155 AddValueSymbols(Inst.getOperand(i).getExpr());
156
157 getCurrentSectionData()->setHasInstructions(true);
158
159 // Now that a machine instruction has been assembled into this section, make
160 // a line entry for any .loc directive that has been seen.
161 MCLineEntry::Make(this, getCurrentSection());
162
163 // If this instruction doesn't need relaxation, just emit it as data.
164 if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
165 EmitInstToData(Inst);
166 return;
167 }
168
169 // Otherwise, if we are relaxing everything, relax the instruction as much as
170 // possible and emit it as data.
171 if (getAssembler().getRelaxAll()) {
172 MCInst Relaxed;
173 getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
174 while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
175 getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
176 EmitInstToData(Relaxed);
177 return;
178 }
179
180 // Otherwise emit to a separate fragment.
181 EmitInstToFragment(Inst);
182}
183
Rafael Espindoladedb0452010-12-02 05:44:06 +0000184void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) {
185 MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData());
186
187 raw_svector_ostream VecOS(IF->getCode());
188 getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups());
189}
190
Rafael Espindola245a1e22010-12-28 05:39:27 +0000191static const MCExpr *BuildSymbolDiff(MCContext &Context,
192 const MCSymbol *A, const MCSymbol *B) {
193 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
194 const MCExpr *ARef =
195 MCSymbolRefExpr::Create(A, Variant, Context);
196 const MCExpr *BRef =
197 MCSymbolRefExpr::Create(B, Variant, Context);
198 const MCExpr *AddrDelta =
199 MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context);
200 return AddrDelta;
201}
202
203static const MCExpr *ForceExpAbs(MCObjectStreamer *Streamer,
204 MCContext &Context, const MCExpr* Expr) {
205 if (Context.getAsmInfo().hasAggressiveSymbolFolding())
206 return Expr;
207
208 MCSymbol *ABS = Context.CreateTempSymbol();
209 Streamer->EmitAssignment(ABS, Expr);
210 return MCSymbolRefExpr::Create(ABS, Context);
211}
212
Rafael Espindola32a006e2010-12-03 00:55:40 +0000213void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
214 const MCSymbol *LastLabel,
215 const MCSymbol *Label) {
216 if (!LastLabel) {
Rafael Espindola89b93722010-12-10 07:39:47 +0000217 int PointerSize = getContext().getTargetAsmInfo().getPointerSize();
Rafael Espindola32a006e2010-12-03 00:55:40 +0000218 EmitDwarfSetLineAddr(LineDelta, Label, PointerSize);
219 return;
220 }
Rafael Espindola245a1e22010-12-28 05:39:27 +0000221 const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel);
Rafael Espindola32a006e2010-12-03 00:55:40 +0000222 int64_t Res;
Rafael Espindolad0764822010-12-18 03:57:21 +0000223 if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) {
Rafael Espindola32a006e2010-12-03 00:55:40 +0000224 MCDwarfLineAddr::Emit(this, LineDelta, Res);
225 return;
226 }
Rafael Espindola245a1e22010-12-28 05:39:27 +0000227 AddrDelta = ForceExpAbs(this, getContext(), AddrDelta);
Rafael Espindola32a006e2010-12-03 00:55:40 +0000228 new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());
229}
230
Rafael Espindola245a1e22010-12-28 05:39:27 +0000231void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
232 const MCSymbol *Label) {
233 const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel);
234 int64_t Res;
235 if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) {
236 MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
237 return;
238 }
239 AddrDelta = ForceExpAbs(this, getContext(), AddrDelta);
240 new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData());
241}
242
Rafael Espindolae2393052010-12-02 05:59:38 +0000243void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
244 unsigned char Value) {
245 new MCOrgFragment(*Offset, Value, getCurrentSectionData());
246}
247
Daniel Dunbar83b46712010-06-16 20:04:25 +0000248void MCObjectStreamer::Finish() {
Rafael Espindola89b93722010-12-10 07:39:47 +0000249 // Dump out the dwarf file & directory tables and line tables.
250 if (getContext().hasDwarfFiles())
251 MCDwarfFileTable::Emit(this);
252
Daniel Dunbar83b46712010-06-16 20:04:25 +0000253 getAssembler().Finish();
254}