MCAsmStreamer.cpp revision 8cb9a3b13f3226b7e741768b69d26ecd6b5231f1
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#include "llvm/ADT/SmallString.h" 12#include "llvm/MC/MCAsmInfo.h" 13#include "llvm/MC/MCCodeEmitter.h" 14#include "llvm/MC/MCContext.h" 15#include "llvm/MC/MCExpr.h" 16#include "llvm/MC/MCInst.h" 17#include "llvm/MC/MCInstPrinter.h" 18#include "llvm/MC/MCSectionMachO.h" 19#include "llvm/MC/MCSymbol.h" 20#include "llvm/Support/ErrorHandling.h" 21#include "llvm/Support/MathExtras.h" 22#include "llvm/Support/Format.h" 23#include "llvm/Support/raw_ostream.h" 24using namespace llvm; 25 26namespace { 27 28class MCAsmStreamer : public MCStreamer { 29 raw_ostream &OS; 30 const MCAsmInfo &MAI; 31 MCInstPrinter *InstPrinter; 32 MCCodeEmitter *Emitter; 33public: 34 MCAsmStreamer(MCContext &Context, raw_ostream &_OS, const MCAsmInfo &tai, 35 MCInstPrinter *_Printer, MCCodeEmitter *_Emitter) 36 : MCStreamer(Context), OS(_OS), MAI(tai), InstPrinter(_Printer), 37 Emitter(_Emitter) {} 38 ~MCAsmStreamer() {} 39 40 /// @name MCStreamer Interface 41 /// @{ 42 43 virtual void SwitchSection(const MCSection *Section); 44 45 virtual void EmitLabel(MCSymbol *Symbol); 46 47 virtual void EmitAssemblerFlag(AssemblerFlag Flag); 48 49 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 50 51 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 52 53 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 54 55 virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 56 unsigned ByteAlignment); 57 58 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, 59 unsigned Size = 0, unsigned ByteAlignment = 0); 60 61 virtual void EmitBytes(StringRef Data); 62 63 virtual void EmitValue(const MCExpr *Value, unsigned Size); 64 65 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 66 unsigned ValueSize = 1, 67 unsigned MaxBytesToEmit = 0); 68 69 virtual void EmitValueToOffset(const MCExpr *Offset, 70 unsigned char Value = 0); 71 72 virtual void EmitInstruction(const MCInst &Inst); 73 74 virtual void Finish(); 75 76 /// @} 77}; 78 79} // end anonymous namespace. 80 81static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 82 assert(Bytes && "Invalid size!"); 83 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 84} 85 86static inline const MCExpr *truncateToSize(const MCExpr *Value, 87 unsigned Bytes) { 88 // FIXME: Do we really need this routine? 89 return Value; 90} 91 92void MCAsmStreamer::SwitchSection(const MCSection *Section) { 93 assert(Section && "Cannot switch to a null section!"); 94 if (Section != CurSection) { 95 CurSection = Section; 96 Section->PrintSwitchToSection(MAI, OS); 97 } 98} 99 100void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 101 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 102 assert(CurSection && "Cannot emit before setting section!"); 103 104 OS << *Symbol << ":\n"; 105 Symbol->setSection(*CurSection); 106} 107 108void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 109 switch (Flag) { 110 default: assert(0 && "Invalid flag!"); 111 case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 112 } 113 OS << '\n'; 114} 115 116void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 117 // Only absolute symbols can be redefined. 118 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 119 "Cannot define a symbol twice!"); 120 121 OS << *Symbol << " = " << *Value << '\n'; 122 123 // FIXME: Lift context changes into super class. 124 // FIXME: Set associated section. 125 Symbol->setValue(Value); 126} 127 128void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 129 SymbolAttr Attribute) { 130 switch (Attribute) { 131 case Global: OS << ".globl"; break; 132 case Hidden: OS << ".hidden"; break; 133 case IndirectSymbol: OS << ".indirect_symbol"; break; 134 case Internal: OS << ".internal"; break; 135 case LazyReference: OS << ".lazy_reference"; break; 136 case NoDeadStrip: OS << ".no_dead_strip"; break; 137 case PrivateExtern: OS << ".private_extern"; break; 138 case Protected: OS << ".protected"; break; 139 case Reference: OS << ".reference"; break; 140 case Weak: OS << ".weak"; break; 141 case WeakDefinition: OS << ".weak_definition"; break; 142 case WeakReference: OS << ".weak_reference"; break; 143 } 144 145 OS << ' ' << *Symbol << '\n'; 146} 147 148void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 149 OS << ".desc" << ' ' << *Symbol << ',' << DescValue << '\n'; 150} 151 152void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 153 unsigned ByteAlignment) { 154 OS << ".comm " << *Symbol << ',' << Size; 155 if (ByteAlignment != 0) 156 OS << ',' << Log2_32(ByteAlignment); 157 OS << '\n'; 158} 159 160void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 161 unsigned Size, unsigned ByteAlignment) { 162 // Note: a .zerofill directive does not switch sections. 163 OS << ".zerofill "; 164 165 // This is a mach-o specific directive. 166 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 167 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 168 169 if (Symbol != NULL) { 170 OS << ',' << *Symbol << ',' << Size; 171 if (ByteAlignment != 0) 172 OS << ',' << Log2_32(ByteAlignment); 173 } 174 OS << '\n'; 175} 176 177void MCAsmStreamer::EmitBytes(StringRef Data) { 178 assert(CurSection && "Cannot emit contents before setting section!"); 179 for (unsigned i = 0, e = Data.size(); i != e; ++i) 180 OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n'; 181} 182 183void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size) { 184 assert(CurSection && "Cannot emit contents before setting section!"); 185 // Need target hooks to know how to print this. 186 switch (Size) { 187 default: 188 llvm_unreachable("Invalid size for machine code value!"); 189 case 1: OS << ".byte"; break; 190 case 2: OS << ".short"; break; 191 case 4: OS << ".long"; break; 192 case 8: OS << ".quad"; break; 193 } 194 195 OS << ' ' << *truncateToSize(Value, Size) << '\n'; 196} 197 198void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 199 unsigned ValueSize, 200 unsigned MaxBytesToEmit) { 201 // Some assemblers don't support non-power of two alignments, so we always 202 // emit alignments as a power of two if possible. 203 if (isPowerOf2_32(ByteAlignment)) { 204 switch (ValueSize) { 205 default: llvm_unreachable("Invalid size for machine code value!"); 206 case 1: OS << MAI.getAlignDirective(); break; 207 // FIXME: use MAI for this! 208 case 2: OS << ".p2alignw "; break; 209 case 4: OS << ".p2alignl "; break; 210 case 8: llvm_unreachable("Unsupported alignment size!"); 211 } 212 213 if (MAI.getAlignmentIsInBytes()) 214 OS << ByteAlignment; 215 else 216 OS << Log2_32(ByteAlignment); 217 218 if (Value || MaxBytesToEmit) { 219 OS << ", 0x"; 220 OS.write_hex(truncateToSize(Value, ValueSize)); 221 222 if (MaxBytesToEmit) 223 OS << ", " << MaxBytesToEmit; 224 } 225 OS << '\n'; 226 return; 227 } 228 229 // Non-power of two alignment. This is not widely supported by assemblers. 230 // FIXME: Parameterize this based on MAI. 231 switch (ValueSize) { 232 default: llvm_unreachable("Invalid size for machine code value!"); 233 case 1: OS << ".balign"; break; 234 case 2: OS << ".balignw"; break; 235 case 4: OS << ".balignl"; break; 236 case 8: llvm_unreachable("Unsupported alignment size!"); 237 } 238 239 OS << ' ' << ByteAlignment; 240 OS << ", " << truncateToSize(Value, ValueSize); 241 if (MaxBytesToEmit) 242 OS << ", " << MaxBytesToEmit; 243 OS << '\n'; 244} 245 246void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, 247 unsigned char Value) { 248 // FIXME: Verify that Offset is associated with the current section. 249 OS << ".org " << *Offset << ", " << (unsigned) Value << '\n'; 250} 251 252void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 253 assert(CurSection && "Cannot emit contents before setting section!"); 254 255 // If we have an AsmPrinter, use that to print. 256 if (InstPrinter) { 257 InstPrinter->printInst(&Inst); 258 OS << '\n'; 259 260 // Show the encoding if we have a code emitter. 261 if (Emitter) { 262 SmallString<256> Code; 263 raw_svector_ostream VecOS(Code); 264 Emitter->EncodeInstruction(Inst, VecOS); 265 VecOS.flush(); 266 267 OS.indent(20); 268 OS << " # encoding: ["; 269 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 270 if (i) 271 OS << ','; 272 OS << format("%#04x", uint8_t(Code[i])); 273 } 274 OS << "]\n"; 275 } 276 277 return; 278 } 279 280 // Otherwise fall back to a structural printing for now. Eventually we should 281 // always have access to the target specific printer. 282 Inst.print(OS, &MAI); 283 OS << '\n'; 284} 285 286void MCAsmStreamer::Finish() { 287 OS.flush(); 288} 289 290MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, 291 const MCAsmInfo &MAI, MCInstPrinter *IP, 292 MCCodeEmitter *CE) { 293 return new MCAsmStreamer(Context, OS, MAI, IP, CE); 294} 295