MCStreamer.cpp revision b4601bd2ffdde372f1323f6b6ec98acd433501ce
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;
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  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
178  MCSymbol *Label = getContext().CreateTempSymbol();
179  EmitLabel(Label);
180  MachineLocation Dest(MachineLocation::VirtualFP);
181  MachineLocation Source(MachineLocation::VirtualFP, -Offset);
182  MCCFIInstruction Instruction(Label, Dest, Source);
183  CurFrame->Instructions.push_back(Instruction);
184  return false;
185}
186
187bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
188  EnsureValidFrame();
189  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
190  MCSymbol *Label = getContext().CreateTempSymbol();
191  EmitLabel(Label);
192  MachineLocation Dest(Register);
193  MachineLocation Source(MachineLocation::VirtualFP);
194  MCCFIInstruction Instruction(Label, Dest, Source);
195  CurFrame->Instructions.push_back(Instruction);
196  return false;
197  return false;
198}
199
200bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
201  EnsureValidFrame();
202  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
203  MCSymbol *Label = getContext().CreateTempSymbol();
204  EmitLabel(Label);
205  MachineLocation Dest(Register, Offset);
206  MachineLocation Source(Register, Offset);
207  MCCFIInstruction Instruction(Label, Dest, Source);
208  CurFrame->Instructions.push_back(Instruction);
209  return false;
210}
211
212bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
213                                    unsigned Encoding) {
214  EnsureValidFrame();
215  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
216  CurFrame->Personality = Sym;
217  CurFrame->PersonalityEncoding = Encoding;
218  return false;
219}
220
221bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
222  EnsureValidFrame();
223  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
224  CurFrame->Lsda = Sym;
225  CurFrame->LsdaEncoding = Encoding;
226  return false;
227}
228
229bool MCStreamer::EmitCFIRememberState() {
230  EnsureValidFrame();
231  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
232  MCSymbol *Label = getContext().CreateTempSymbol();
233  EmitLabel(Label);
234  MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label);
235  CurFrame->Instructions.push_back(Instruction);
236  return false;
237}
238
239bool MCStreamer::EmitCFIRestoreState() {
240  // FIXME: Error if there is no matching cfi_remember_state.
241  EnsureValidFrame();
242  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
243  MCSymbol *Label = getContext().CreateTempSymbol();
244  EmitLabel(Label);
245  MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label);
246  CurFrame->Instructions.push_back(Instruction);
247  return false;
248}
249
250/// EmitRawText - If this file is backed by an assembly streamer, this dumps
251/// the specified string in the output .s file.  This capability is
252/// indicated by the hasRawTextSupport() predicate.
253void MCStreamer::EmitRawText(StringRef String) {
254  errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
255  " something must not be fully mc'ized\n";
256  abort();
257}
258
259void MCStreamer::EmitRawText(const Twine &T) {
260  SmallString<128> Str;
261  T.toVector(Str);
262  EmitRawText(Str.str());
263}
264