Add some limited support for labels in org directives. Hopefully enough to fix
[oota-llvm.git] / lib / MC / MCObjectStreamer.cpp
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"
22 using namespace llvm;
23
24 MCObjectStreamer::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
34 MCObjectStreamer::~MCObjectStreamer() {
35   delete &Assembler->getBackend();
36   delete &Assembler->getEmitter();
37   delete &Assembler->getWriter();
38   delete Assembler;
39 }
40
41 MCFragment *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
50 MCDataFragment *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
57 const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
58   switch (Value->getKind()) {
59   case MCExpr::Target:
60     cast<MCTargetExpr>(Value)->AddValueSymbols(Assembler);
61     break;
62
63   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
85 void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
86                                      bool isPCRel, unsigned AddrSpace) {
87   assert(AddrSpace == 0 && "Address space must be 0!");
88   MCDataFragment *DF = getOrCreateDataFragment();
89
90   // Avoid fixups when possible.
91   int64_t AbsValue;
92   if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) {
93     EmitIntValue(AbsValue, Size, AddrSpace);
94     return;
95   }
96   DF->addFixup(MCFixup::Create(DF->getContents().size(),
97                                Value,
98                                MCFixup::getKindForSize(Size, isPCRel)));
99   DF->getContents().resize(DF->getContents().size() + Size, 0);
100 }
101
102 void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
103   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
104   assert(getCurrentSection() && "Cannot emit before setting section!");
105
106   Symbol->setSection(*getCurrentSection());
107
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
120 void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
121                                         unsigned AddrSpace) {
122   int64_t IntValue;
123   if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) {
124     EmitULEB128IntValue(IntValue, AddrSpace);
125     return;
126   }
127   new MCLEBFragment(*Value, false, getCurrentSectionData());
128 }
129
130 void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
131                                         unsigned AddrSpace) {
132   int64_t IntValue;
133   if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) {
134     EmitSLEB128IntValue(IntValue, AddrSpace);
135     return;
136   }
137   new MCLEBFragment(*Value, true, getCurrentSectionData());
138 }
139
140 void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
141                                          const MCSymbol *Symbol) {
142   report_fatal_error("This file format doesn't support weak aliases.");
143 }
144
145 void MCObjectStreamer::ChangeSection(const MCSection *Section) {
146   assert(Section && "Cannot switch to a null section!");
147
148   CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
149 }
150
151 void 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
184 void 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
191 static 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
203 static 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
213 void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
214                                                 const MCSymbol *LastLabel,
215                                                 const MCSymbol *Label) {
216   if (!LastLabel) {
217     int PointerSize = getContext().getTargetAsmInfo().getPointerSize();
218     EmitDwarfSetLineAddr(LineDelta, Label, PointerSize);
219     return;
220   }
221   const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel);
222   int64_t Res;
223   if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) {
224     MCDwarfLineAddr::Emit(this, LineDelta, Res);
225     return;
226   }
227   AddrDelta = ForceExpAbs(this, getContext(), AddrDelta);
228   new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData());
229 }
230
231 void 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
243 void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
244                                         unsigned char Value) {
245   int64_t Res;
246   if (Offset->EvaluateAsAbsolute(Res, getAssembler())) {
247     new MCOrgFragment(*Offset, Value, getCurrentSectionData());
248     return;
249   }
250
251   MCSymbol *CurrentPos = getContext().CreateTempSymbol();
252   EmitLabel(CurrentPos);
253   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
254   const MCExpr *Ref =
255     MCSymbolRefExpr::Create(CurrentPos, Variant, getContext());
256   const MCExpr *Delta =
257     MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext());
258
259   if (!Delta->EvaluateAsAbsolute(Res, getAssembler()))
260     report_fatal_error("expected assembly-time absolute expression");
261   EmitFill(Res, Value, 0);
262 }
263
264 void MCObjectStreamer::Finish() {
265   // Dump out the dwarf file & directory tables and line tables.
266   if (getContext().hasDwarfFiles())
267     MCDwarfFileTable::Emit(this);
268
269   getAssembler().Finish();
270 }