MCAsmStreamer.cpp revision d79d9dce47d505369662ae5111dba24f9ccdef68
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/MC/MCAsmInfo.h" 12#include "llvm/MC/MCCodeEmitter.h" 13#include "llvm/MC/MCContext.h" 14#include "llvm/MC/MCExpr.h" 15#include "llvm/MC/MCInst.h" 16#include "llvm/MC/MCInstPrinter.h" 17#include "llvm/MC/MCSectionMachO.h" 18#include "llvm/MC/MCSymbol.h" 19#include "llvm/ADT/SmallString.h" 20#include "llvm/ADT/Twine.h" 21#include "llvm/Support/ErrorHandling.h" 22#include "llvm/Support/MathExtras.h" 23#include "llvm/Support/Format.h" 24#include "llvm/Support/FormattedStream.h" 25using namespace llvm; 26 27namespace { 28 29class MCAsmStreamer : public MCStreamer { 30 formatted_raw_ostream &OS; 31 const MCAsmInfo &MAI; 32 bool IsLittleEndian, IsVerboseAsm; 33 MCInstPrinter *InstPrinter; 34 MCCodeEmitter *Emitter; 35 36 SmallString<128> CommentToEmit; 37 raw_svector_ostream CommentStream; 38public: 39 MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, 40 const MCAsmInfo &mai, 41 bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, 42 MCCodeEmitter *emitter) 43 : MCStreamer(Context), OS(os), MAI(mai), IsLittleEndian(isLittleEndian), 44 IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter), 45 CommentStream(CommentToEmit) {} 46 ~MCAsmStreamer() {} 47 48 bool isLittleEndian() const { return IsLittleEndian; } 49 50 51 inline void EmitEOL() { 52 // If we don't have any comments, just emit a \n. 53 if (!IsVerboseAsm) { 54 OS << '\n'; 55 return; 56 } 57 EmitCommentsAndEOL(); 58 } 59 void EmitCommentsAndEOL(); 60 61 /// AddComment - Add a comment that can be emitted to the generated .s 62 /// file if applicable as a QoI issue to make the output of the compiler 63 /// more readable. This only affects the MCAsmStreamer, and only when 64 /// verbose assembly output is enabled. 65 virtual void AddComment(const Twine &T); 66 67 /// GetCommentOS - Return a raw_ostream that comments can be written to. 68 /// Unlike AddComment, you are required to terminate comments with \n if you 69 /// use this method. 70 virtual raw_ostream &GetCommentOS() { 71 if (!IsVerboseAsm) 72 return nulls(); // Discard comments unless in verbose asm mode. 73 return CommentStream; 74 } 75 76 /// @name MCStreamer Interface 77 /// @{ 78 79 virtual void SwitchSection(const MCSection *Section); 80 81 virtual void EmitLabel(MCSymbol *Symbol); 82 83 virtual void EmitAssemblerFlag(AssemblerFlag Flag); 84 85 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 86 87 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 88 89 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 90 91 virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 92 unsigned ByteAlignment); 93 94 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, 95 unsigned Size = 0, unsigned ByteAlignment = 0); 96 97 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 98 99 virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); 100 virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace); 101 102 virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, 103 unsigned AddrSpace); 104 105 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 106 unsigned ValueSize = 1, 107 unsigned MaxBytesToEmit = 0); 108 109 virtual void EmitValueToOffset(const MCExpr *Offset, 110 unsigned char Value = 0); 111 112 virtual void EmitInstruction(const MCInst &Inst); 113 114 virtual void Finish(); 115 116 /// @} 117}; 118 119} // end anonymous namespace. 120 121/// AddComment - Add a comment that can be emitted to the generated .s 122/// file if applicable as a QoI issue to make the output of the compiler 123/// more readable. This only affects the MCAsmStreamer, and only when 124/// verbose assembly output is enabled. 125void MCAsmStreamer::AddComment(const Twine &T) { 126 if (!IsVerboseAsm) return; 127 128 // Make sure that CommentStream is flushed. 129 CommentStream.flush(); 130 131 T.toVector(CommentToEmit); 132 // Each comment goes on its own line. 133 CommentToEmit.push_back('\n'); 134} 135 136void MCAsmStreamer::EmitCommentsAndEOL() { 137 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 138 OS << '\n'; 139 return; 140 } 141 142 CommentStream.flush(); 143 StringRef Comments = CommentToEmit.str(); 144 145 assert(Comments.back() == '\n' && 146 "Comment array not newline terminated"); 147 do { 148 // Emit a line of comments. 149 OS.PadToColumn(MAI.getCommentColumn()); 150 size_t Position = Comments.find('\n'); 151 OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; 152 153 Comments = Comments.substr(Position+1); 154 } while (!Comments.empty()); 155 156 CommentStream.clear(); 157} 158 159 160static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 161 assert(Bytes && "Invalid size!"); 162 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 163} 164 165static inline const MCExpr *truncateToSize(const MCExpr *Value, 166 unsigned Bytes) { 167 // FIXME: Do we really need this routine? 168 return Value; 169} 170 171void MCAsmStreamer::SwitchSection(const MCSection *Section) { 172 assert(Section && "Cannot switch to a null section!"); 173 if (Section != CurSection) { 174 CurSection = Section; 175 Section->PrintSwitchToSection(MAI, OS); 176 } 177} 178 179void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 180 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 181 assert(CurSection && "Cannot emit before setting section!"); 182 183 OS << *Symbol << ":"; 184 EmitEOL(); 185 Symbol->setSection(*CurSection); 186} 187 188void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 189 switch (Flag) { 190 default: assert(0 && "Invalid flag!"); 191 case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 192 } 193 EmitEOL(); 194} 195 196void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 197 // Only absolute symbols can be redefined. 198 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 199 "Cannot define a symbol twice!"); 200 201 OS << *Symbol << " = " << *Value; 202 EmitEOL(); 203 204 // FIXME: Lift context changes into super class. 205 // FIXME: Set associated section. 206 Symbol->setValue(Value); 207} 208 209void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 210 SymbolAttr Attribute) { 211 switch (Attribute) { 212 case Global: OS << MAI.getGlobalDirective(); break; // .globl 213 case Hidden: OS << ".hidden "; break; 214 case IndirectSymbol: OS << ".indirect_symbol "; break; 215 case Internal: OS << ".internal "; break; 216 case LazyReference: OS << ".lazy_reference "; break; 217 case NoDeadStrip: OS << ".no_dead_strip "; break; 218 case PrivateExtern: OS << ".private_extern "; break; 219 case Protected: OS << ".protected "; break; 220 case Reference: OS << ".reference "; break; 221 case Weak: OS << ".weak "; break; 222 case WeakDefinition: OS << ".weak_definition "; break; 223 case WeakReference: OS << ".weak_reference "; break; 224 } 225 226 OS << *Symbol; 227 EmitEOL(); 228} 229 230void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 231 OS << ".desc" << ' ' << *Symbol << ',' << DescValue; 232 EmitEOL(); 233} 234 235void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 236 unsigned ByteAlignment) { 237 OS << MAI.getCOMMDirective() << *Symbol << ',' << Size; 238 if (ByteAlignment != 0 && MAI.getCOMMDirectiveTakesAlignment()) { 239 if (MAI.getAlignmentIsInBytes()) 240 OS << ',' << ByteAlignment; 241 else 242 OS << ',' << Log2_32(ByteAlignment); 243 } 244 EmitEOL(); 245} 246 247void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 248 unsigned Size, unsigned ByteAlignment) { 249 // Note: a .zerofill directive does not switch sections. 250 OS << ".zerofill "; 251 252 // This is a mach-o specific directive. 253 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 254 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 255 256 if (Symbol != NULL) { 257 OS << ',' << *Symbol << ',' << Size; 258 if (ByteAlignment != 0) 259 OS << ',' << Log2_32(ByteAlignment); 260 } 261 EmitEOL(); 262} 263 264void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 265 assert(CurSection && "Cannot emit contents before setting section!"); 266 const char *Directive = MAI.getData8bitsDirective(AddrSpace); 267 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 268 OS << Directive << (unsigned)(unsigned char)Data[i]; 269 EmitEOL(); 270 } 271} 272 273/// EmitIntValue - Special case of EmitValue that avoids the client having 274/// to pass in a MCExpr for constant integers. 275void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, 276 unsigned AddrSpace) { 277 assert(CurSection && "Cannot emit contents before setting section!"); 278 const char *Directive = 0; 279 switch (Size) { 280 default: break; 281 case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; 282 case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; 283 case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; 284 case 8: 285 Directive = MAI.getData64bitsDirective(AddrSpace); 286 // If the target doesn't support 64-bit data, emit as two 32-bit halves. 287 if (Directive) break; 288 if (isLittleEndian()) { 289 EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); 290 EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); 291 } else { 292 EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); 293 EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); 294 } 295 return; 296 } 297 298 assert(Directive && "Invalid size for machine code value!"); 299 OS << Directive << truncateToSize(Value, Size); 300 EmitEOL(); 301} 302 303void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, 304 unsigned AddrSpace) { 305 assert(CurSection && "Cannot emit contents before setting section!"); 306 const char *Directive = 0; 307 switch (Size) { 308 default: break; 309 case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; 310 case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; 311 case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; 312 case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break; 313 } 314 315 assert(Directive && "Invalid size for machine code value!"); 316 OS << Directive << *truncateToSize(Value, Size); 317 EmitEOL(); 318} 319 320/// EmitFill - Emit NumBytes bytes worth of the value specified by 321/// FillValue. This implements directives such as '.space'. 322void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, 323 unsigned AddrSpace) { 324 if (NumBytes == 0) return; 325 326 if (AddrSpace == 0) 327 if (const char *ZeroDirective = MAI.getZeroDirective()) { 328 OS << ZeroDirective << NumBytes; 329 if (FillValue != 0) 330 OS << ',' << (int)FillValue; 331 EmitEOL(); 332 return; 333 } 334 335 // Emit a byte at a time. 336 MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); 337} 338 339void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 340 unsigned ValueSize, 341 unsigned MaxBytesToEmit) { 342 // Some assemblers don't support non-power of two alignments, so we always 343 // emit alignments as a power of two if possible. 344 if (isPowerOf2_32(ByteAlignment)) { 345 switch (ValueSize) { 346 default: llvm_unreachable("Invalid size for machine code value!"); 347 case 1: OS << MAI.getAlignDirective(); break; 348 // FIXME: use MAI for this! 349 case 2: OS << ".p2alignw "; break; 350 case 4: OS << ".p2alignl "; break; 351 case 8: llvm_unreachable("Unsupported alignment size!"); 352 } 353 354 if (MAI.getAlignmentIsInBytes()) 355 OS << ByteAlignment; 356 else 357 OS << Log2_32(ByteAlignment); 358 359 if (Value || MaxBytesToEmit) { 360 OS << ", 0x"; 361 OS.write_hex(truncateToSize(Value, ValueSize)); 362 363 if (MaxBytesToEmit) 364 OS << ", " << MaxBytesToEmit; 365 } 366 EmitEOL(); 367 return; 368 } 369 370 // Non-power of two alignment. This is not widely supported by assemblers. 371 // FIXME: Parameterize this based on MAI. 372 switch (ValueSize) { 373 default: llvm_unreachable("Invalid size for machine code value!"); 374 case 1: OS << ".balign"; break; 375 case 2: OS << ".balignw"; break; 376 case 4: OS << ".balignl"; break; 377 case 8: llvm_unreachable("Unsupported alignment size!"); 378 } 379 380 OS << ' ' << ByteAlignment; 381 OS << ", " << truncateToSize(Value, ValueSize); 382 if (MaxBytesToEmit) 383 OS << ", " << MaxBytesToEmit; 384 EmitEOL(); 385} 386 387void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, 388 unsigned char Value) { 389 // FIXME: Verify that Offset is associated with the current section. 390 OS << ".org " << *Offset << ", " << (unsigned) Value; 391 EmitEOL(); 392} 393 394void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 395 assert(CurSection && "Cannot emit contents before setting section!"); 396 397 // If we have an AsmPrinter, use that to print. 398 if (InstPrinter) { 399 InstPrinter->printInst(&Inst); 400 EmitEOL(); 401 402 // Show the encoding if we have a code emitter. 403 if (Emitter) { 404 SmallString<256> Code; 405 raw_svector_ostream VecOS(Code); 406 Emitter->EncodeInstruction(Inst, VecOS); 407 VecOS.flush(); 408 409 OS.indent(20); 410 OS << " # encoding: ["; 411 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 412 if (i) 413 OS << ','; 414 OS << format("%#04x", uint8_t(Code[i])); 415 } 416 OS << "]\n"; 417 } 418 419 return; 420 } 421 422 // Otherwise fall back to a structural printing for now. Eventually we should 423 // always have access to the target specific printer. 424 Inst.print(OS, &MAI); 425 EmitEOL(); 426} 427 428void MCAsmStreamer::Finish() { 429 OS.flush(); 430} 431 432MCStreamer *llvm::createAsmStreamer(MCContext &Context, 433 formatted_raw_ostream &OS, 434 const MCAsmInfo &MAI, bool isLittleEndian, 435 bool isVerboseAsm, MCInstPrinter *IP, 436 MCCodeEmitter *CE) { 437 return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm, 438 IP, CE); 439} 440