MCStreamer.cpp revision 218893
1195098Sed//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
2195098Sed//
3195098Sed//                     The LLVM Compiler Infrastructure
4195098Sed//
5195098Sed// This file is distributed under the University of Illinois Open Source
6195098Sed// License. See LICENSE.TXT for details.
7195098Sed//
8195098Sed//===----------------------------------------------------------------------===//
9195098Sed
10218893Sdim#include "llvm/MC/MCAsmInfo.h"
11218893Sdim#include "llvm/MC/MCContext.h"
12195098Sed#include "llvm/MC/MCStreamer.h"
13202878Srdivacky#include "llvm/MC/MCExpr.h"
14218893Sdim#include "llvm/MC/MCObjectWriter.h"
15218893Sdim#include "llvm/Support/ErrorHandling.h"
16202878Srdivacky#include "llvm/Support/raw_ostream.h"
17206274Srdivacky#include "llvm/ADT/SmallString.h"
18206274Srdivacky#include "llvm/ADT/Twine.h"
19206274Srdivacky#include <cstdlib>
20195098Sedusing namespace llvm;
21195098Sed
22218893SdimMCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) {
23218893Sdim  PrevSectionStack.push_back(NULL);
24218893Sdim  CurSectionStack.push_back(NULL);
25195098Sed}
26195098Sed
27195098SedMCStreamer::~MCStreamer() {
28195098Sed}
29202878Srdivacky
30202878Srdivackyraw_ostream &MCStreamer::GetCommentOS() {
31202878Srdivacky  // By default, discard comments.
32202878Srdivacky  return nulls();
33202878Srdivacky}
34202878Srdivacky
35218893Sdimvoid MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta,
36218893Sdim                                      const MCSymbol *Label, int PointerSize) {
37218893Sdim  // emit the sequence to set the address
38218893Sdim  EmitIntValue(dwarf::DW_LNS_extended_op, 1);
39218893Sdim  EmitULEB128IntValue(PointerSize + 1);
40218893Sdim  EmitIntValue(dwarf::DW_LNE_set_address, 1);
41218893Sdim  EmitSymbolValue(Label, PointerSize);
42202878Srdivacky
43218893Sdim  // emit the sequence for the LineDelta (from 1) and a zero address delta.
44218893Sdim  MCDwarfLineAddr::Emit(this, LineDelta, 0);
45218893Sdim}
46218893Sdim
47202878Srdivacky/// EmitIntValue - Special case of EmitValue that avoids the client having to
48202878Srdivacky/// pass in a MCExpr for constant integers.
49202878Srdivackyvoid MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
50202878Srdivacky                              unsigned AddrSpace) {
51218893Sdim  assert(Size <= 8 && "Invalid size");
52218893Sdim  assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) &&
53218893Sdim         "Invalid size");
54218893Sdim  char buf[8];
55218893Sdim  // FIXME: Endianness assumption.
56218893Sdim  for (unsigned i = 0; i != Size; ++i)
57218893Sdim    buf[i] = uint8_t(Value >> (i * 8));
58218893Sdim  EmitBytes(StringRef(buf, Size), AddrSpace);
59202878Srdivacky}
60202878Srdivacky
61218893Sdim/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
62218893Sdim/// client having to pass in a MCExpr for constant integers.
63218893Sdimvoid MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
64218893Sdim  SmallString<32> Tmp;
65218893Sdim  raw_svector_ostream OSE(Tmp);
66218893Sdim  MCObjectWriter::EncodeULEB128(Value, OSE);
67218893Sdim  EmitBytes(OSE.str(), AddrSpace);
68218893Sdim}
69218893Sdim
70218893Sdim/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
71218893Sdim/// client having to pass in a MCExpr for constant integers.
72218893Sdimvoid MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
73218893Sdim  SmallString<32> Tmp;
74218893Sdim  raw_svector_ostream OSE(Tmp);
75218893Sdim  MCObjectWriter::EncodeSLEB128(Value, OSE);
76218893Sdim  EmitBytes(OSE.str(), AddrSpace);
77218893Sdim}
78218893Sdim
79218893Sdimvoid MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size,
80218893Sdim                              unsigned AddrSpace) {
81218893Sdim  if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) {
82218893Sdim    EmitValue(Value, Size, AddrSpace);
83218893Sdim    return;
84218893Sdim  }
85218893Sdim  MCSymbol *ABS = getContext().CreateTempSymbol();
86218893Sdim  EmitAssignment(ABS, Value);
87218893Sdim  EmitSymbolValue(ABS, Size, AddrSpace);
88218893Sdim}
89218893Sdim
90218893Sdim
91218893Sdimvoid MCStreamer::EmitValue(const MCExpr *Value, unsigned Size,
92218893Sdim                           unsigned AddrSpace) {
93218893Sdim  EmitValueImpl(Value, Size, false, AddrSpace);
94218893Sdim}
95218893Sdim
96218893Sdimvoid MCStreamer::EmitPCRelValue(const MCExpr *Value, unsigned Size,
97218893Sdim                                unsigned AddrSpace) {
98218893Sdim  EmitValueImpl(Value, Size, true, AddrSpace);
99218893Sdim}
100218893Sdim
101204961Srdivackyvoid MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
102218893Sdim                                 bool isPCRel, unsigned AddrSpace) {
103218893Sdim  EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, isPCRel,
104218893Sdim                AddrSpace);
105218893Sdim}
106218893Sdim
107218893Sdimvoid MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
108204961Srdivacky                                 unsigned AddrSpace) {
109218893Sdim  EmitSymbolValue(Sym, Size, false, AddrSpace);
110204961Srdivacky}
111204961Srdivacky
112218893Sdimvoid MCStreamer::EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size,
113218893Sdim                                      unsigned AddrSpace) {
114218893Sdim  EmitSymbolValue(Sym, Size, true, AddrSpace);
115218893Sdim}
116218893Sdim
117218893Sdimvoid MCStreamer::EmitGPRel32Value(const MCExpr *Value) {
118218893Sdim  report_fatal_error("unsupported directive in streamer");
119218893Sdim}
120218893Sdim
121202878Srdivacky/// EmitFill - Emit NumBytes bytes worth of the value specified by
122202878Srdivacky/// FillValue.  This implements directives such as '.space'.
123202878Srdivackyvoid MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
124202878Srdivacky                          unsigned AddrSpace) {
125202878Srdivacky  const MCExpr *E = MCConstantExpr::Create(FillValue, getContext());
126202878Srdivacky  for (uint64_t i = 0, e = NumBytes; i != e; ++i)
127202878Srdivacky    EmitValue(E, 1, AddrSpace);
128202878Srdivacky}
129206274Srdivacky
130218893Sdimbool MCStreamer::EmitDwarfFileDirective(unsigned FileNo,
131218893Sdim                                        StringRef Filename) {
132218893Sdim  return getContext().GetDwarfFile(Filename, FileNo) == 0;
133218893Sdim}
134218893Sdim
135218893Sdimvoid MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
136218893Sdim                                       unsigned Column, unsigned Flags,
137218893Sdim                                       unsigned Isa,
138218893Sdim                                       unsigned Discriminator) {
139218893Sdim  getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa,
140218893Sdim                                  Discriminator);
141218893Sdim}
142218893Sdim
143218893SdimMCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() {
144218893Sdim  if (FrameInfos.empty())
145218893Sdim    return NULL;
146218893Sdim  return &FrameInfos.back();
147218893Sdim}
148218893Sdim
149218893Sdimvoid MCStreamer::EnsureValidFrame() {
150218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
151218893Sdim  if (!CurFrame || CurFrame->End)
152218893Sdim    report_fatal_error("No open frame");
153218893Sdim}
154218893Sdim
155218893Sdimbool MCStreamer::EmitCFIStartProc() {
156218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
157218893Sdim  if (CurFrame && !CurFrame->End) {
158218893Sdim    report_fatal_error("Starting a frame before finishing the previous one!");
159218893Sdim    return true;
160218893Sdim  }
161218893Sdim  MCDwarfFrameInfo Frame;
162218893Sdim  Frame.Begin = getContext().CreateTempSymbol();
163218893Sdim  EmitLabel(Frame.Begin);
164218893Sdim  FrameInfos.push_back(Frame);
165218893Sdim  return false;
166218893Sdim}
167218893Sdim
168218893Sdimbool MCStreamer::EmitCFIEndProc() {
169218893Sdim  EnsureValidFrame();
170218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
171218893Sdim  CurFrame->End = getContext().CreateTempSymbol();
172218893Sdim  EmitLabel(CurFrame->End);
173218893Sdim  return false;
174218893Sdim}
175218893Sdim
176218893Sdimbool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
177218893Sdim  EnsureValidFrame();
178218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
179218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
180218893Sdim  EmitLabel(Label);
181218893Sdim  MachineLocation Dest(MachineLocation::VirtualFP);
182218893Sdim  MachineLocation Source(Register, -Offset);
183218893Sdim  MCCFIInstruction Instruction(Label, Dest, Source);
184218893Sdim  CurFrame->Instructions.push_back(Instruction);
185218893Sdim  return false;
186218893Sdim}
187218893Sdim
188218893Sdimbool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
189218893Sdim  EnsureValidFrame();
190218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
191218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
192218893Sdim  EmitLabel(Label);
193218893Sdim  MachineLocation Dest(MachineLocation::VirtualFP);
194218893Sdim  MachineLocation Source(MachineLocation::VirtualFP, -Offset);
195218893Sdim  MCCFIInstruction Instruction(Label, Dest, Source);
196218893Sdim  CurFrame->Instructions.push_back(Instruction);
197218893Sdim  return false;
198218893Sdim}
199218893Sdim
200218893Sdimbool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) {
201218893Sdim  EnsureValidFrame();
202218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
203218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
204218893Sdim  EmitLabel(Label);
205218893Sdim  MachineLocation Dest(Register);
206218893Sdim  MachineLocation Source(MachineLocation::VirtualFP);
207218893Sdim  MCCFIInstruction Instruction(Label, Dest, Source);
208218893Sdim  CurFrame->Instructions.push_back(Instruction);
209218893Sdim  return false;
210218893Sdim}
211218893Sdim
212218893Sdimbool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
213218893Sdim  EnsureValidFrame();
214218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
215218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
216218893Sdim  EmitLabel(Label);
217218893Sdim  MachineLocation Dest(Register, Offset);
218218893Sdim  MachineLocation Source(Register, Offset);
219218893Sdim  MCCFIInstruction Instruction(Label, Dest, Source);
220218893Sdim  CurFrame->Instructions.push_back(Instruction);
221218893Sdim  return false;
222218893Sdim}
223218893Sdim
224218893Sdimbool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym,
225218893Sdim                                    unsigned Encoding) {
226218893Sdim  EnsureValidFrame();
227218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
228218893Sdim  CurFrame->Personality = Sym;
229218893Sdim  CurFrame->PersonalityEncoding = Encoding;
230218893Sdim  return false;
231218893Sdim}
232218893Sdim
233218893Sdimbool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
234218893Sdim  EnsureValidFrame();
235218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
236218893Sdim  CurFrame->Lsda = Sym;
237218893Sdim  CurFrame->LsdaEncoding = Encoding;
238218893Sdim  return false;
239218893Sdim}
240218893Sdim
241218893Sdimbool MCStreamer::EmitCFIRememberState() {
242218893Sdim  EnsureValidFrame();
243218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
244218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
245218893Sdim  EmitLabel(Label);
246218893Sdim  MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label);
247218893Sdim  CurFrame->Instructions.push_back(Instruction);
248218893Sdim  return false;
249218893Sdim}
250218893Sdim
251218893Sdimbool MCStreamer::EmitCFIRestoreState() {
252218893Sdim  // FIXME: Error if there is no matching cfi_remember_state.
253218893Sdim  EnsureValidFrame();
254218893Sdim  MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
255218893Sdim  MCSymbol *Label = getContext().CreateTempSymbol();
256218893Sdim  EmitLabel(Label);
257218893Sdim  MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label);
258218893Sdim  CurFrame->Instructions.push_back(Instruction);
259218893Sdim  return false;
260218893Sdim}
261218893Sdim
262208599Srdivacky/// EmitRawText - If this file is backed by an assembly streamer, this dumps
263206274Srdivacky/// the specified string in the output .s file.  This capability is
264206274Srdivacky/// indicated by the hasRawTextSupport() predicate.
265206274Srdivackyvoid MCStreamer::EmitRawText(StringRef String) {
266206274Srdivacky  errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
267206274Srdivacky  " something must not be fully mc'ized\n";
268206274Srdivacky  abort();
269206274Srdivacky}
270206274Srdivacky
271206274Srdivackyvoid MCStreamer::EmitRawText(const Twine &T) {
272206274Srdivacky  SmallString<128> Str;
273206274Srdivacky  T.toVector(Str);
274206274Srdivacky  EmitRawText(Str.str());
275206274Srdivacky}
276