MCStreamer.cpp revision 90a5a0cd7c353651c953020b1e41b4c6e2f21883
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/Support/ErrorHandling.h"
16#include "llvm/Support/raw_ostream.h"
17#include "llvm/ADT/SmallString.h"
18#include "llvm/ADT/Twine.h"
19#include <cstdlib>
20using namespace llvm;
21
22MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurSection(0),
23                                         PrevSection(0) {
24}
25
26MCStreamer::~MCStreamer() {
27}
28
29raw_ostream &MCStreamer::GetCommentOS() {
30  // By default, discard comments.
31  return nulls();
32}
33
34void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta,
35                                      const MCSymbol *Label, int PointerSize) {
36  // emit the sequence to set the address
37  EmitIntValue(dwarf::DW_LNS_extended_op, 1);
38  EmitULEB128IntValue(PointerSize + 1);
39  EmitIntValue(dwarf::DW_LNE_set_address, 1);
40  EmitSymbolValue(Label, PointerSize);
41
42  // emit the sequence for the LineDelta (from 1) and a zero address delta.
43  MCDwarfLineAddr::Emit(this, LineDelta, 0);
44}
45
46/// EmitIntValue - Special case of EmitValue that avoids the client having to
47/// pass in a MCExpr for constant integers.
48void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
49                              unsigned AddrSpace) {
50  assert(Size <= 8 && "Invalid size");
51  assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
52         "Invalid size");
53  char buf[8];
54  // FIXME: Endianness assumption.
55  for (unsigned i = 0; i != Size; ++i)
56    buf[i] = uint8_t(Value >> (i * 8));
57  EmitBytes(StringRef(buf, Size), AddrSpace);
58}
59
60/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
61/// client having to pass in a MCExpr for constant integers.
62void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
63  SmallString<32> Tmp;
64  raw_svector_ostream OSE(Tmp);
65  MCObjectWriter::EncodeULEB128(Value, OSE);
66  EmitBytes(OSE.str(), AddrSpace);
67}
68
69/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
70/// client having to pass in a MCExpr for constant integers.
71void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
72  SmallString<32> Tmp;
73  raw_svector_ostream OSE(Tmp);
74  MCObjectWriter::EncodeSLEB128(Value, OSE);
75  EmitBytes(OSE.str(), AddrSpace);
76}
77
78void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size,
79                              unsigned AddrSpace) {
80  if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) {
81    EmitValue(Value, Size, AddrSpace);
82    return;
83  }
84  MCSymbol *ABS = getContext().CreateTempSymbol();
85  EmitAssignment(ABS, Value);
86  EmitSymbolValue(ABS, Size, AddrSpace);
87}
88
89
90void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size,
91                           unsigned AddrSpace) {
92  EmitValueImpl(Value, Size, false, AddrSpace);
93}
94
95void MCStreamer::EmitPCRelValue(const MCExpr *Value, unsigned Size,
96                                unsigned AddrSpace) {
97  EmitValueImpl(Value, Size, true, AddrSpace);
98}
99
100void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
101                                 bool isPCRel, unsigned AddrSpace) {
102  EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, isPCRel,
103                AddrSpace);
104}
105
106void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
107                                 unsigned AddrSpace) {
108  EmitSymbolValue(Sym, Size, false, AddrSpace);
109}
110
111void MCStreamer::EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size,
112                                      unsigned AddrSpace) {
113  EmitSymbolValue(Sym, Size, true, AddrSpace);
114}
115
116void MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
117  report_fatal_error("unsupported directive in streamer");
118}
119
120/// EmitFill - Emit NumBytes bytes worth of the value specified by
121/// FillValue.  This implements directives such as '.space'.
122void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
123                          unsigned AddrSpace) {
124  const MCExpr *E = MCConstantExpr::Create(FillValue, getContext());
125  for (uint64_t i = 0, e = NumBytes; i != e; ++i)
126    EmitValue(E, 1, AddrSpace);
127}
128
129bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo,
130                                        StringRef Filename) {
131  return getContext().GetDwarfFile(Filename, FileNo) == 0;
132}
133
134void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
135                                       unsigned Column, unsigned Flags,
136                                       unsigned Isa,
137                                       unsigned Discriminator) {
138  getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
139                                  Discriminator);
140}
141
142MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() {
143  if (FrameInfos.empty())
144    return NULL;
145  return &FrameInfos.back();
146}
147
148void MCStreamer::EnsureValidFrame() {
149  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
150  if (!CurFrame || CurFrame->End)
151    report_fatal_error("No open frame");
152}
153
154bool MCStreamer::EmitCFIStartProc() {
155  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
156  if (CurFrame && !CurFrame->End) {
157    report_fatal_error("Starting a frame before finishing the previous one!");
158    return true;
159  }
160  MCDwarfFrameInfo Frame = {0, 0, 0, 0};
161  Frame.Begin = getContext().CreateTempSymbol();
162  EmitLabel(Frame.Begin);
163  FrameInfos.push_back(Frame);
164  return false;
165}
166
167bool MCStreamer::EmitCFIEndProc() {
168  EnsureValidFrame();
169  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
170  CurFrame->End = getContext().CreateTempSymbol();
171  EmitLabel(CurFrame->End);
172  return false;
173}
174
175bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
176  EnsureValidFrame();
177  return false;
178}
179
180bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
181  EnsureValidFrame();
182  return false;
183}
184
185bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
186  EnsureValidFrame();
187  return false;
188}
189
190bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym) {
191  EnsureValidFrame();
192  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
193  CurFrame->Personality = Sym;
194  return false;
195}
196
197bool MCStreamer::EmitCFILsda(const MCSymbol *Sym) {
198  EnsureValidFrame();
199  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
200  CurFrame->Lsda = Sym;
201  return false;
202}
203
204/// EmitRawText - If this file is backed by an assembly streamer, this dumps
205/// the specified string in the output .s file.  This capability is
206/// indicated by the hasRawTextSupport() predicate.
207void MCStreamer::EmitRawText(StringRef String) {
208  errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
209  " something must not be fully mc'ized\n";
210  abort();
211}
212
213void MCStreamer::EmitRawText(const Twine &T) {
214  SmallString<128> Str;
215  T.toVector(Str);
216  EmitRawText(Str.str());
217}
218