1218885Sdim//===- lib/MC/MCPureStreamer.cpp - MC "Pure" Object Output ----------------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim
10218885Sdim#include "llvm/MC/MCStreamer.h"
11218885Sdim#include "llvm/MC/MCAssembler.h"
12218885Sdim#include "llvm/MC/MCCodeEmitter.h"
13218885Sdim#include "llvm/MC/MCContext.h"
14218885Sdim#include "llvm/MC/MCExpr.h"
15251662Sdim#include "llvm/MC/MCObjectFileInfo.h"
16218885Sdim#include "llvm/MC/MCObjectStreamer.h"
17218885Sdim#include "llvm/MC/MCSymbol.h"
18218885Sdim#include "llvm/Support/ErrorHandling.h"
19218885Sdim
20218885Sdimusing namespace llvm;
21218885Sdim
22218885Sdimnamespace {
23218885Sdim
24218885Sdimclass MCPureStreamer : public MCObjectStreamer {
25218885Sdimprivate:
26218885Sdim  virtual void EmitInstToFragment(const MCInst &Inst);
27218885Sdim  virtual void EmitInstToData(const MCInst &Inst);
28218885Sdim
29218885Sdimpublic:
30249423Sdim  MCPureStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
31249423Sdim                 MCCodeEmitter *Emitter)
32263508Sdim      : MCObjectStreamer(Context, 0, TAB, OS, Emitter) {}
33218885Sdim
34218885Sdim  /// @name MCStreamer Interface
35218885Sdim  /// @{
36218885Sdim
37218885Sdim  virtual void InitSections();
38249423Sdim  virtual void InitToTextSection();
39218885Sdim  virtual void EmitLabel(MCSymbol *Symbol);
40249423Sdim  virtual void EmitDebugLabel(MCSymbol *Symbol);
41218885Sdim  virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
42239462Sdim                            uint64_t Size = 0, unsigned ByteAlignment = 0);
43263508Sdim  virtual void EmitBytes(StringRef Data);
44218885Sdim  virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
45218885Sdim                                    unsigned ValueSize = 1,
46218885Sdim                                    unsigned MaxBytesToEmit = 0);
47218885Sdim  virtual void EmitCodeAlignment(unsigned ByteAlignment,
48218885Sdim                                 unsigned MaxBytesToEmit = 0);
49234353Sdim  virtual bool EmitValueToOffset(const MCExpr *Offset,
50218885Sdim                                 unsigned char Value = 0);
51234353Sdim  virtual void FinishImpl();
52218885Sdim
53218885Sdim
54263508Sdim  virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) {
55218885Sdim    report_fatal_error("unsupported directive in pure streamer");
56263508Sdim    return false;
57218885Sdim  }
58218885Sdim  virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
59218885Sdim    report_fatal_error("unsupported directive in pure streamer");
60218885Sdim  }
61218885Sdim  virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
62218885Sdim                              uint64_t Size, unsigned ByteAlignment = 0) {
63218885Sdim    report_fatal_error("unsupported directive in pure streamer");
64218885Sdim  }
65218885Sdim  virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
66218885Sdim    report_fatal_error("unsupported directive in pure streamer");
67218885Sdim  }
68218885Sdim  virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
69218885Sdim                                unsigned ByteAlignment) {
70218885Sdim    report_fatal_error("unsupported directive in pure streamer");
71218885Sdim  }
72218885Sdim  virtual void EmitThumbFunc(MCSymbol *Func) {
73218885Sdim    report_fatal_error("unsupported directive in pure streamer");
74218885Sdim  }
75218885Sdim  virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {
76218885Sdim    report_fatal_error("unsupported directive in pure streamer");
77218885Sdim  }
78218885Sdim  virtual void EmitCOFFSymbolStorageClass(int StorageClass) {
79218885Sdim    report_fatal_error("unsupported directive in pure streamer");
80218885Sdim  }
81218885Sdim  virtual void EmitCOFFSymbolType(int Type) {
82218885Sdim    report_fatal_error("unsupported directive in pure streamer");
83218885Sdim  }
84218885Sdim  virtual void EndCOFFSymbolDef() {
85218885Sdim    report_fatal_error("unsupported directive in pure streamer");
86218885Sdim  }
87218885Sdim  virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
88218885Sdim    report_fatal_error("unsupported directive in pure streamer");
89218885Sdim  }
90226633Sdim  virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
91226633Sdim                                     unsigned ByteAlignment) {
92218885Sdim    report_fatal_error("unsupported directive in pure streamer");
93218885Sdim  }
94218885Sdim  virtual void EmitFileDirective(StringRef Filename) {
95218885Sdim    report_fatal_error("unsupported directive in pure streamer");
96218885Sdim  }
97263508Sdim  virtual void EmitIdent(StringRef IdentString) {
98263508Sdim    report_fatal_error("unsupported directive in pure streamer");
99263508Sdim  }
100234353Sdim  virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
101249423Sdim                                      StringRef Filename, unsigned CUID = 0) {
102218885Sdim    report_fatal_error("unsupported directive in pure streamer");
103218885Sdim  }
104218885Sdim};
105218885Sdim
106218885Sdim} // end anonymous namespace.
107218885Sdim
108218885Sdimvoid MCPureStreamer::InitSections() {
109249423Sdim  InitToTextSection();
110249423Sdim}
111249423Sdim
112249423Sdimvoid MCPureStreamer::InitToTextSection() {
113251662Sdim  SwitchSection(getContext().getObjectFileInfo()->getTextSection());
114218885Sdim}
115218885Sdim
116218885Sdimvoid MCPureStreamer::EmitLabel(MCSymbol *Symbol) {
117218885Sdim  assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
118218885Sdim  assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
119251662Sdim  assert(getCurrentSection().first && "Cannot emit before setting section!");
120218885Sdim
121263508Sdim  AssignSection(Symbol, getCurrentSection().first);
122218885Sdim
123218885Sdim  MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
124218885Sdim
125218885Sdim  // We have to create a new fragment if this is an atom defining symbol,
126218885Sdim  // fragments cannot span atoms.
127218885Sdim  if (getAssembler().isSymbolLinkerVisible(SD.getSymbol()))
128251662Sdim    insert(new MCDataFragment());
129218885Sdim
130218885Sdim  // FIXME: This is wasteful, we don't necessarily need to create a data
131218885Sdim  // fragment. Instead, we should mark the symbol as pointing into the data
132218885Sdim  // fragment if it exists, otherwise we should just queue the label and set its
133218885Sdim  // fragment pointer when we emit the next fragment.
134218885Sdim  MCDataFragment *F = getOrCreateDataFragment();
135218885Sdim  assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
136218885Sdim  SD.setFragment(F);
137218885Sdim  SD.setOffset(F->getContents().size());
138218885Sdim}
139218885Sdim
140249423Sdim
141249423Sdimvoid MCPureStreamer::EmitDebugLabel(MCSymbol *Symbol) {
142249423Sdim  EmitLabel(Symbol);
143218885Sdim}
144218885Sdim
145218885Sdimvoid MCPureStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
146239462Sdim                                  uint64_t Size, unsigned ByteAlignment) {
147218885Sdim  report_fatal_error("not yet implemented in pure streamer");
148218885Sdim}
149218885Sdim
150263508Sdimvoid MCPureStreamer::EmitBytes(StringRef Data) {
151218885Sdim  // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
152218885Sdim  // MCObjectStreamer.
153218885Sdim  getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
154218885Sdim}
155218885Sdim
156218885Sdimvoid MCPureStreamer::EmitValueToAlignment(unsigned ByteAlignment,
157218885Sdim                                          int64_t Value, unsigned ValueSize,
158218885Sdim                                          unsigned MaxBytesToEmit) {
159218885Sdim  // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
160218885Sdim  // MCObjectStreamer.
161218885Sdim  if (MaxBytesToEmit == 0)
162218885Sdim    MaxBytesToEmit = ByteAlignment;
163251662Sdim  insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit));
164218885Sdim
165218885Sdim  // Update the maximum alignment on the current section if necessary.
166218885Sdim  if (ByteAlignment > getCurrentSectionData()->getAlignment())
167218885Sdim    getCurrentSectionData()->setAlignment(ByteAlignment);
168218885Sdim}
169218885Sdim
170218885Sdimvoid MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment,
171218885Sdim                                       unsigned MaxBytesToEmit) {
172218885Sdim  // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
173218885Sdim  // MCObjectStreamer.
174218885Sdim  if (MaxBytesToEmit == 0)
175218885Sdim    MaxBytesToEmit = ByteAlignment;
176251662Sdim  MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit);
177251662Sdim  insert(F);
178218885Sdim  F->setEmitNops(true);
179218885Sdim
180218885Sdim  // Update the maximum alignment on the current section if necessary.
181218885Sdim  if (ByteAlignment > getCurrentSectionData()->getAlignment())
182218885Sdim    getCurrentSectionData()->setAlignment(ByteAlignment);
183218885Sdim}
184218885Sdim
185234353Sdimbool MCPureStreamer::EmitValueToOffset(const MCExpr *Offset,
186218885Sdim                                       unsigned char Value) {
187251662Sdim  insert(new MCOrgFragment(*Offset, Value));
188234353Sdim  return false;
189218885Sdim}
190218885Sdim
191218885Sdimvoid MCPureStreamer::EmitInstToFragment(const MCInst &Inst) {
192251662Sdim  MCRelaxableFragment *IF = new MCRelaxableFragment(Inst);
193251662Sdim  insert(IF);
194218885Sdim
195218885Sdim  // Add the fixups and data.
196218885Sdim  //
197218885Sdim  // FIXME: Revisit this design decision when relaxation is done, we may be
198218885Sdim  // able to get away with not storing any extra data in the MCInst.
199218885Sdim  SmallVector<MCFixup, 4> Fixups;
200218885Sdim  SmallString<256> Code;
201218885Sdim  raw_svector_ostream VecOS(Code);
202218885Sdim  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
203218885Sdim  VecOS.flush();
204218885Sdim
205249423Sdim  IF->getContents() = Code;
206218885Sdim  IF->getFixups() = Fixups;
207218885Sdim}
208218885Sdim
209218885Sdimvoid MCPureStreamer::EmitInstToData(const MCInst &Inst) {
210218885Sdim  MCDataFragment *DF = getOrCreateDataFragment();
211218885Sdim
212218885Sdim  SmallVector<MCFixup, 4> Fixups;
213218885Sdim  SmallString<256> Code;
214218885Sdim  raw_svector_ostream VecOS(Code);
215218885Sdim  getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
216218885Sdim  VecOS.flush();
217218885Sdim
218218885Sdim  // Add the fixups and data.
219218885Sdim  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
220218885Sdim    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
221249423Sdim    DF->getFixups().push_back(Fixups[i]);
222218885Sdim  }
223218885Sdim  DF->getContents().append(Code.begin(), Code.end());
224218885Sdim}
225218885Sdim
226234353Sdimvoid MCPureStreamer::FinishImpl() {
227218885Sdim  // FIXME: Handle DWARF tables?
228218885Sdim
229234353Sdim  this->MCObjectStreamer::FinishImpl();
230218885Sdim}
231218885Sdim
232226633SdimMCStreamer *llvm::createPureStreamer(MCContext &Context, MCAsmBackend &MAB,
233218885Sdim                                     raw_ostream &OS, MCCodeEmitter *CE) {
234226633Sdim  return new MCPureStreamer(Context, MAB, OS, CE);
235218885Sdim}
236