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