MCAsmStreamer.cpp revision c22e0b2443afdedb6d9b225b938ad404d63cdbe6
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/CodeGen/AsmPrinter.h" 13#include "llvm/MC/MCContext.h" 14#include "llvm/MC/MCInst.h" 15#include "llvm/MC/MCSectionMachO.h" 16#include "llvm/MC/MCSymbol.h" 17#include "llvm/MC/MCValue.h" 18#include "llvm/Support/ErrorHandling.h" 19#include "llvm/Support/raw_ostream.h" 20 21using namespace llvm; 22 23namespace { 24 25 class MCAsmStreamer : public MCStreamer { 26 raw_ostream &OS; 27 28 AsmPrinter *Printer; 29 30 MCSection *CurSection; 31 32 public: 33 MCAsmStreamer(MCContext &Context, raw_ostream &_OS, AsmPrinter *_AsmPrinter) 34 : MCStreamer(Context), OS(_OS), Printer(_AsmPrinter), CurSection(0) {} 35 ~MCAsmStreamer() {} 36 37 /// @name MCStreamer Interface 38 /// @{ 39 40 virtual void SwitchSection(MCSection *Section); 41 42 virtual void EmitLabel(MCSymbol *Symbol); 43 44 virtual void EmitAssemblerFlag(AssemblerFlag Flag); 45 46 virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 47 bool MakeAbsolute = false); 48 49 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 50 51 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 52 53 virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value); 54 55 virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 56 unsigned Pow2Alignment, bool IsLocal); 57 58 virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL, 59 unsigned Size = 0, unsigned Pow2Alignment = 0); 60 61 virtual void EmitBytes(const StringRef &Data); 62 63 virtual void EmitValue(const MCValue &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 MCValue &Offset, 70 unsigned char Value = 0); 71 72 virtual void EmitInstruction(const MCInst &Inst); 73 74 virtual void Finish(); 75 76 /// @} 77 }; 78 79} 80 81/// Allow printing symbols directly to a raw_ostream with proper quoting. 82static inline raw_ostream &operator<<(raw_ostream &os, const MCSymbol *S) { 83 S->print(os); 84 85 return os; 86} 87 88/// Allow printing values directly to a raw_ostream. 89static inline raw_ostream &operator<<(raw_ostream &os, const MCValue &Value) { 90 Value.print(os); 91 92 return os; 93} 94 95static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 96 assert(Bytes && "Invalid size!"); 97 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 98} 99 100static inline MCValue truncateToSize(const MCValue &Value, unsigned Bytes) { 101 return MCValue::get(Value.getSymA(), Value.getSymB(), 102 truncateToSize(Value.getConstant(), Bytes)); 103} 104 105void MCAsmStreamer::SwitchSection(MCSection *Section) { 106 if (Section != CurSection) { 107 CurSection = Section; 108 109 // FIXME: Needs TargetAsmInfo! 110 Section->PrintSwitchToSection(*(const TargetAsmInfo*)0, OS); 111 } 112} 113 114void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 115 assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!"); 116 assert(CurSection && "Cannot emit before setting section!"); 117 assert(!getContext().GetSymbolValue(Symbol) && 118 "Cannot emit symbol which was directly assigned to!"); 119 120 OS << Symbol << ":\n"; 121 Symbol->setSection(CurSection); 122 Symbol->setExternal(false); 123} 124 125void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 126 switch (Flag) { 127 default: assert(0 && "Invalid flag!"); 128 case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 129 } 130 OS << '\n'; 131} 132 133void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 134 bool MakeAbsolute) { 135 assert(!Symbol->getSection() && "Cannot assign to a label!"); 136 137 if (MakeAbsolute) { 138 OS << ".set " << Symbol << ", " << Value << '\n'; 139 } else { 140 OS << Symbol << " = " << Value << '\n'; 141 } 142 143 getContext().SetSymbolValue(Symbol, Value); 144} 145 146void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 147 SymbolAttr Attribute) { 148 switch (Attribute) { 149 case Global: OS << ".globl"; break; 150 case Hidden: OS << ".hidden"; break; 151 case IndirectSymbol: OS << ".indirect_symbol"; break; 152 case Internal: OS << ".internal"; break; 153 case LazyReference: OS << ".lazy_reference"; break; 154 case NoDeadStrip: OS << ".no_dead_strip"; break; 155 case PrivateExtern: OS << ".private_extern"; break; 156 case Protected: OS << ".protected"; break; 157 case Reference: OS << ".reference"; break; 158 case Weak: OS << ".weak"; break; 159 case WeakDefinition: OS << ".weak_definition"; break; 160 case WeakReference: OS << ".weak_reference"; break; 161 } 162 163 OS << ' ' << Symbol << '\n'; 164} 165 166void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 167 OS << ".desc" << ' ' << Symbol << ',' << DescValue << '\n'; 168} 169 170void MCAsmStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { 171 OS << ".lsym" << ' ' << Symbol << ',' << Value << '\n'; 172} 173 174void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 175 unsigned Pow2Alignment, bool IsLocal) { 176 if (IsLocal) 177 OS << ".lcomm"; 178 else 179 OS << ".comm"; 180 OS << ' ' << Symbol << ',' << Size; 181 if (Pow2Alignment != 0) 182 OS << ',' << Pow2Alignment; 183 OS << '\n'; 184} 185 186void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 187 unsigned Size, unsigned Pow2Alignment) { 188 // Note: a .zerofill directive does not switch sections. 189 OS << ".zerofill "; 190 191 // This is a mach-o specific directive. 192 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 193 OS << '"' << MOSection->getSegmentName() << "," 194 << 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) 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 .balign, so we always emit as .p2align if 229 // this is a power of two. Otherwise we assume the client knows the target 230 // supports .balign and use that. 231 unsigned Pow2 = Log2_32(ByteAlignment); 232 bool IsPow2 = (1U << Pow2) == ByteAlignment; 233 234 switch (ValueSize) { 235 default: 236 llvm_unreachable("Invalid size for machine code value!"); 237 case 8: 238 llvm_unreachable("Unsupported alignment size!"); 239 case 1: OS << (IsPow2 ? ".p2align" : ".balign"); break; 240 case 2: OS << (IsPow2 ? ".p2alignw" : ".balignw"); break; 241 case 4: OS << (IsPow2 ? ".p2alignl" : ".balignl"); break; 242 } 243 244 OS << ' ' << (IsPow2 ? Pow2 : ByteAlignment); 245 246 OS << ", " << truncateToSize(Value, ValueSize); 247 if (MaxBytesToEmit) 248 OS << ", " << MaxBytesToEmit; 249 OS << '\n'; 250} 251 252void MCAsmStreamer::EmitValueToOffset(const MCValue &Offset, 253 unsigned char Value) { 254 // FIXME: Verify that Offset is associated with the current section. 255 OS << ".org " << Offset << ", " << (unsigned) Value << '\n'; 256} 257 258static raw_ostream &operator<<(raw_ostream &OS, const MCOperand &Op) { 259 if (Op.isReg()) 260 return OS << "reg:" << Op.getReg(); 261 if (Op.isImm()) 262 return OS << "imm:" << Op.getImm(); 263 if (Op.isMBBLabel()) 264 return OS << "mbblabel:(" 265 << Op.getMBBLabelFunction() << ", " << Op.getMBBLabelBlock(); 266 assert(Op.isMCValue() && "Invalid operand!"); 267 return OS << "val:" << Op.getMCValue(); 268} 269 270void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 271 assert(CurSection && "Cannot emit contents before setting section!"); 272 273 // If we have an AsmPrinter, use that to print. 274 if (Printer) { 275 Printer->printMCInst(&Inst); 276 return; 277 } 278 279 // Otherwise fall back to a structural printing for now. Eventually we should 280 // always have access to the target specific printer. 281 OS << "MCInst(" 282 << "opcode=" << Inst.getOpcode() << ", " 283 << "operands=["; 284 for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { 285 if (i) 286 OS << ", "; 287 OS << Inst.getOperand(i); 288 } 289 OS << "])\n"; 290} 291 292void MCAsmStreamer::Finish() { 293 OS.flush(); 294} 295 296MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, 297 AsmPrinter *AP) { 298 return new MCAsmStreamer(Context, OS, AP); 299} 300