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