MCStreamer.cpp revision debd7e4e8bc5cfe61bfb71835ce2b1a3fbccc2be
1//===- lib/MC/MCStreamer.cpp - Streaming Machine Code 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 "llvm/MC/MCAsmInfo.h"
11#include "llvm/MC/MCContext.h"
12#include "llvm/MC/MCStreamer.h"
13#include "llvm/MC/MCExpr.h"
14#include "llvm/MC/MCObjectWriter.h"
15#include "llvm/MC/MCSymbol.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/raw_ostream.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/Twine.h"
20#include <cstdlib>
21using namespace llvm;
22
23MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) {
24  const MCSection *section = NULL;
25  SectionStack.push_back(std::make_pair(section, section));
26}
27
28MCStreamer::~MCStreamer() {
29}
30
31const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context,
32                                          const MCSymbol *A,
33                                          const MCSymbol *B) {
34  MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
35  const MCExpr *ARef =
36    MCSymbolRefExpr::Create(A, Variant, Context);
37  const MCExpr *BRef =
38    MCSymbolRefExpr::Create(B, Variant, Context);
39  const MCExpr *AddrDelta =
40    MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context);
41  return AddrDelta;
42}
43
44const MCExpr *MCStreamer::ForceExpAbs(MCStreamer *Streamer,
45                                      MCContext &Context, const MCExpr* Expr) {
46 if (Context.getAsmInfo().hasAggressiveSymbolFolding())
47   return Expr;
48
49 MCSymbol *ABS = Context.CreateTempSymbol();
50 Streamer->EmitAssignment(ABS, Expr);
51 return MCSymbolRefExpr::Create(ABS, Context);
52}
53
54raw_ostream &MCStreamer::GetCommentOS() {
55  // By default, discard comments.
56  return nulls();
57}
58
59void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta,
60                                      const MCSymbol *Label, int PointerSize) {
61  // emit the sequence to set the address
62  EmitIntValue(dwarf::DW_LNS_extended_op, 1);
63  EmitULEB128IntValue(PointerSize + 1);
64  EmitIntValue(dwarf::DW_LNE_set_address, 1);
65  EmitSymbolValue(Label, PointerSize);
66
67  // emit the sequence for the LineDelta (from 1) and a zero address delta.
68  MCDwarfLineAddr::Emit(this, LineDelta, 0);
69}
70
71/// EmitIntValue - Special case of EmitValue that avoids the client having to
72/// pass in a MCExpr for constant integers.
73void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
74                              unsigned AddrSpace) {
75  assert(Size <= 8 && "Invalid size");
76  assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
77         "Invalid size");
78  char buf[8];
79  // FIXME: Endianness assumption.
80  for (unsigned i = 0; i != Size; ++i)
81    buf[i] = uint8_t(Value >> (i * 8));
82  EmitBytes(StringRef(buf, Size), AddrSpace);
83}
84
85/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
86/// client having to pass in a MCExpr for constant integers.
87void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
88  SmallString<32> Tmp;
89  raw_svector_ostream OSE(Tmp);
90  MCObjectWriter::EncodeULEB128(Value, OSE);
91  EmitBytes(OSE.str(), AddrSpace);
92}
93
94/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
95/// client having to pass in a MCExpr for constant integers.
96void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
97  SmallString<32> Tmp;
98  raw_svector_ostream OSE(Tmp);
99  MCObjectWriter::EncodeSLEB128(Value, OSE);
100  EmitBytes(OSE.str(), AddrSpace);
101}
102
103void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size,
104                              unsigned AddrSpace) {
105  if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) {
106    EmitValue(Value, Size, AddrSpace);
107    return;
108  }
109  MCSymbol *ABS = getContext().CreateTempSymbol();
110  EmitAssignment(ABS, Value);
111  EmitSymbolValue(ABS, Size, AddrSpace);
112}
113
114
115void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size,
116                           unsigned AddrSpace) {
117  EmitValueImpl(Value, Size, AddrSpace);
118}
119
120void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
121                                  unsigned AddrSpace) {
122  EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size,
123                AddrSpace);
124}
125
126void MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
127  report_fatal_error("unsupported directive in streamer");
128}
129
130/// EmitFill - Emit NumBytes bytes worth of the value specified by
131/// FillValue.  This implements directives such as '.space'.
132void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
133                          unsigned AddrSpace) {
134  const MCExpr *E = MCConstantExpr::Create(FillValue, getContext());
135  for (uint64_t i = 0, e = NumBytes; i != e; ++i)
136    EmitValue(E, 1, AddrSpace);
137}
138
139bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo,
140                                        StringRef Filename) {
141  return getContext().GetDwarfFile(Filename, FileNo) == 0;
142}
143
144void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
145                                       unsigned Column, unsigned Flags,
146                                       unsigned Isa,
147                                       unsigned Discriminator,
148                                       StringRef FileName) {
149  getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
150                                  Discriminator);
151}
152
153MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() {
154  if (FrameInfos.empty())
155    return NULL;
156  return &FrameInfos.back();
157}
158
159void MCStreamer::EnsureValidFrame() {
160  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
161  if (!CurFrame || CurFrame->End)
162    report_fatal_error("No open frame");
163}
164
165void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
166                                     MCSymbol *EHSymbol) {
167}
168
169void MCStreamer::EmitLabel(MCSymbol *Symbol) {
170  assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
171  assert(getCurrentSection() && "Cannot emit before setting section!");
172  Symbol->setSection(*getCurrentSection());
173
174  StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix();
175  if (!Symbol->getName().startswith(Prefix))
176    LastNonPrivate = Symbol;
177}
178
179void MCStreamer::EmitCFIStartProc() {
180  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
181  if (CurFrame && !CurFrame->End)
182    report_fatal_error("Starting a frame before finishing the previous one!");
183  MCDwarfFrameInfo Frame;
184  Frame.Begin = getContext().CreateTempSymbol();
185  Frame.Function = LastNonPrivate;
186  EmitLabel(Frame.Begin);
187  FrameInfos.push_back(Frame);
188}
189
190void MCStreamer::EmitCFIEndProc() {
191  EnsureValidFrame();
192  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
193  CurFrame->End = getContext().CreateTempSymbol();
194  EmitLabel(CurFrame->End);
195}
196
197void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
198  EnsureValidFrame();
199  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
200  MCSymbol *Label = getContext().CreateTempSymbol();
201  EmitLabel(Label);
202  MachineLocation Dest(MachineLocation::VirtualFP);
203  MachineLocation Source(Register, -Offset);
204  MCCFIInstruction Instruction(Label, Dest, Source);
205  CurFrame->Instructions.push_back(Instruction);
206}
207
208void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
209  EnsureValidFrame();
210  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
211  MCSymbol *Label = getContext().CreateTempSymbol();
212  EmitLabel(Label);
213  MachineLocation Dest(MachineLocation::VirtualFP);
214  MachineLocation Source(MachineLocation::VirtualFP, -Offset);
215  MCCFIInstruction Instruction(Label, Dest, Source);
216  CurFrame->Instructions.push_back(Instruction);
217}
218
219void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
220  EnsureValidFrame();
221  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
222  MCSymbol *Label = getContext().CreateTempSymbol();
223  EmitLabel(Label);
224  MachineLocation Dest(MachineLocation::VirtualFP);
225  MachineLocation Source(MachineLocation::VirtualFP, Adjustment);
226  MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source);
227  CurFrame->Instructions.push_back(Instruction);
228}
229
230void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
231  EnsureValidFrame();
232  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
233  MCSymbol *Label = getContext().CreateTempSymbol();
234  EmitLabel(Label);
235  MachineLocation Dest(Register);
236  MachineLocation Source(MachineLocation::VirtualFP);
237  MCCFIInstruction Instruction(Label, Dest, Source);
238  CurFrame->Instructions.push_back(Instruction);
239}
240
241void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
242  EnsureValidFrame();
243  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
244  MCSymbol *Label = getContext().CreateTempSymbol();
245  EmitLabel(Label);
246  MachineLocation Dest(Register, Offset);
247  MachineLocation Source(Register, Offset);
248  MCCFIInstruction Instruction(Label, Dest, Source);
249  CurFrame->Instructions.push_back(Instruction);
250}
251
252void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
253  EnsureValidFrame();
254  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
255  MCSymbol *Label = getContext().CreateTempSymbol();
256  EmitLabel(Label);
257  MachineLocation Dest(Register, Offset);
258  MachineLocation Source(Register, Offset);
259  MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source);
260  CurFrame->Instructions.push_back(Instruction);
261}
262
263void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
264                                    unsigned Encoding) {
265  EnsureValidFrame();
266  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
267  CurFrame->Personality = Sym;
268  CurFrame->PersonalityEncoding = Encoding;
269}
270
271void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
272  EnsureValidFrame();
273  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
274  CurFrame->Lsda = Sym;
275  CurFrame->LsdaEncoding = Encoding;
276}
277
278void MCStreamer::EmitCFIRememberState() {
279  EnsureValidFrame();
280  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
281  MCSymbol *Label = getContext().CreateTempSymbol();
282  EmitLabel(Label);
283  MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label);
284  CurFrame->Instructions.push_back(Instruction);
285}
286
287void MCStreamer::EmitCFIRestoreState() {
288  // FIXME: Error if there is no matching cfi_remember_state.
289  EnsureValidFrame();
290  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
291  MCSymbol *Label = getContext().CreateTempSymbol();
292  EmitLabel(Label);
293  MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label);
294  CurFrame->Instructions.push_back(Instruction);
295}
296
297void MCStreamer::EmitCFISameValue(int64_t Register) {
298  EnsureValidFrame();
299  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
300  MCSymbol *Label = getContext().CreateTempSymbol();
301  EmitLabel(Label);
302  MCCFIInstruction Instruction(MCCFIInstruction::SameValue, Label, Register);
303  CurFrame->Instructions.push_back(Instruction);
304}
305
306void MCStreamer::EmitFnStart() {
307  errs() << "Not implemented yet\n";
308  abort();
309}
310
311void MCStreamer::EmitFnEnd() {
312  errs() << "Not implemented yet\n";
313  abort();
314}
315
316void MCStreamer::EmitCantUnwind() {
317  errs() << "Not implemented yet\n";
318  abort();
319}
320
321void MCStreamer::EmitHandlerData() {
322  errs() << "Not implemented yet\n";
323  abort();
324}
325
326void MCStreamer::EmitPersonality(const MCSymbol *Personality) {
327  errs() << "Not implemented yet\n";
328  abort();
329}
330
331void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) {
332  errs() << "Not implemented yet\n";
333  abort();
334}
335
336void MCStreamer::EmitPad(int64_t Offset) {
337  errs() << "Not implemented yet\n";
338  abort();
339}
340
341void MCStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool) {
342  errs() << "Not implemented yet\n";
343  abort();
344}
345
346/// EmitRawText - If this file is backed by an assembly streamer, this dumps
347/// the specified string in the output .s file.  This capability is
348/// indicated by the hasRawTextSupport() predicate.
349void MCStreamer::EmitRawText(StringRef String) {
350  errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
351  " something must not be fully mc'ized\n";
352  abort();
353}
354
355void MCStreamer::EmitRawText(const Twine &T) {
356  SmallString<128> Str;
357  T.toVector(Str);
358  EmitRawText(Str.str());
359}
360