MCAsmStreamer.cpp revision 71d259bc4be4f5c7a8a30c6be8da105074ff805a
1//===- lib/MC/MCAsmStreamer.cpp - Text Assembly 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/MCStreamer.h" 11 12#include "llvm/MC/MCContext.h" 13#include "llvm/MC/MCSection.h" 14#include "llvm/MC/MCSymbol.h" 15#include "llvm/MC/MCValue.h" 16#include "llvm/Support/raw_ostream.h" 17using namespace llvm; 18 19namespace { 20 21 class MCAsmStreamer : public MCStreamer { 22 raw_ostream &OS; 23 24 MCSection *CurSection; 25 26 public: 27 MCAsmStreamer(MCContext &Context, raw_ostream &_OS) 28 : MCStreamer(Context), OS(_OS) {} 29 ~MCAsmStreamer() {} 30 31 /// @name MCStreamer Interface 32 /// @{ 33 34 virtual void SwitchSection(MCSection *Section); 35 36 virtual void EmitLabel(MCSymbol *Symbol); 37 38 virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 39 bool MakeAbsolute = false); 40 41 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 42 43 virtual void EmitBytes(const char *Data, unsigned Length); 44 45 virtual void EmitValue(const MCValue &Value, unsigned Size); 46 47 virtual void EmitInstruction(const MCInst &Inst); 48 49 virtual void Finish(); 50 51 /// @} 52 }; 53 54} 55 56/// Allow printing values directly to a raw_ostream. 57inline raw_ostream &operator<<(raw_ostream &os, const MCValue &Value) { 58 if (Value.getSymA()) { 59 os << Value.getSymA()->getName(); 60 if (Value.getSymB()) 61 os << " - " << Value.getSymB()->getName(); 62 if (Value.getCst()) 63 os << " + " << Value.getCst(); 64 } else { 65 assert(!Value.getSymB() && "Invalid machine code value!"); 66 os << Value.getCst(); 67 } 68 69 return os; 70} 71 72void MCAsmStreamer::SwitchSection(MCSection *Section) { 73 if (Section != CurSection) { 74 CurSection = Section; 75 76 // FIXME: Really we would like the segment, flags, etc. to be separate 77 // values instead of embedded in the name. Not all assemblers understand all 78 // this stuff though. 79 OS << ".section " << Section->getName() << "\n"; 80 } 81} 82 83void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 84 assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!"); 85 assert(CurSection && "Cannot emit before setting section!"); 86 assert(!getContext().GetSymbolValue(Symbol) && 87 "Cannot emit symbol which was directly assigned to!"); 88 89 OS << Symbol->getName() << ":\n"; 90 Symbol->setSection(CurSection); 91} 92 93void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 94 bool MakeAbsolute) { 95 assert(!Symbol->getSection() && "Cannot assign to a label!"); 96 97 if (MakeAbsolute) { 98 OS << ".set " << Symbol->getName() << ", " << Value << '\n'; 99 } else { 100 OS << Symbol->getName() << " = " << Value << '\n'; 101 } 102 103 getContext().SetSymbolValue(Symbol, Value); 104} 105 106void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 107 SymbolAttr Attribute) { 108 switch (Attribute) { 109 case Global: OS << ".globl"; break; 110 case Hidden: OS << ".hidden"; break; 111 case IndirectSymbol: OS << ".indirect_symbol"; break; 112 case Internal: OS << ".internal"; break; 113 case LazyReference: OS << ".lazy_reference"; break; 114 case NoDeadStrip: OS << ".no_dead_strip"; break; 115 case PrivateExtern: OS << ".private_extern"; break; 116 case Protected: OS << ".protected"; break; 117 case Reference: OS << ".reference"; break; 118 case Weak: OS << ".weak"; break; 119 case WeakDefinition: OS << ".weak_definition"; break; 120 case WeakReference: OS << ".weak_reference"; break; 121 } 122 123 OS << ' ' << Symbol->getName() << '\n'; 124} 125 126void MCAsmStreamer::EmitBytes(const char *Data, unsigned Length) { 127 assert(CurSection && "Cannot emit contents before setting section!"); 128 for (unsigned i = 0; i != Length; ++i) 129 OS << ".byte " << (unsigned) Data[i] << '\n'; 130} 131 132void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) { 133 assert(CurSection && "Cannot emit contents before setting section!"); 134 // Need target hooks to know how to print this. 135 switch (Size) { 136 default: 137 assert(0 && "Invalid size for machine code value!"); 138 case 1: OS << ".byte"; break; 139 case 2: OS << ".short"; break; 140 case 4: OS << ".long"; break; 141 case 8: OS << ".quad"; break; 142 } 143 144 OS << ' ' << Value << '\n'; 145} 146 147void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 148 assert(CurSection && "Cannot emit contents before setting section!"); 149 // FIXME: Implement. 150 OS << "# FIXME: Implement instruction printing!\n"; 151} 152 153void MCAsmStreamer::Finish() { 154 OS.flush(); 155} 156 157MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS) { 158 return new MCAsmStreamer(Context, OS); 159} 160