MCAsmStreamer.cpp revision 663c2d2580e6e9b2435785c7e5a2de18758860a3
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->getSection() == 0 && "Cannot emit a symbol twice!"); 111 assert(CurSection && "Cannot emit before setting section!"); 112 assert(!getContext().GetSymbolValue(Symbol) && 113 "Cannot emit symbol which was directly assigned to!"); 114 115 OS << Symbol << ":\n"; 116 Symbol->setSection(CurSection); 117 Symbol->setExternal(false); 118} 119 120void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 121 switch (Flag) { 122 default: assert(0 && "Invalid flag!"); 123 case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 124 } 125 OS << '\n'; 126} 127 128void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 129 bool MakeAbsolute) { 130 assert(!Symbol->getSection() && "Cannot assign to a label!"); 131 132 if (MakeAbsolute) { 133 OS << ".set " << Symbol << ", " << Value << '\n'; 134 135 // HACK: If the value isn't already absolute, set the symbol value to 136 // itself, we want to use the .set absolute value, not the actual 137 // expression. 138 if (!Value.isAbsolute()) 139 getContext().SetSymbolValue(Symbol, MCValue::get(Symbol)); 140 else 141 getContext().SetSymbolValue(Symbol, Value); 142 } else { 143 OS << Symbol << " = " << Value << '\n'; 144 getContext().SetSymbolValue(Symbol, Value); 145 } 146} 147 148void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 149 SymbolAttr Attribute) { 150 switch (Attribute) { 151 case Global: OS << ".globl"; break; 152 case Hidden: OS << ".hidden"; break; 153 case IndirectSymbol: OS << ".indirect_symbol"; break; 154 case Internal: OS << ".internal"; break; 155 case LazyReference: OS << ".lazy_reference"; break; 156 case NoDeadStrip: OS << ".no_dead_strip"; break; 157 case PrivateExtern: OS << ".private_extern"; break; 158 case Protected: OS << ".protected"; break; 159 case Reference: OS << ".reference"; break; 160 case Weak: OS << ".weak"; break; 161 case WeakDefinition: OS << ".weak_definition"; break; 162 case WeakReference: OS << ".weak_reference"; break; 163 } 164 165 OS << ' ' << Symbol << '\n'; 166} 167 168void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 169 OS << ".desc" << ' ' << Symbol << ',' << DescValue << '\n'; 170} 171 172void MCAsmStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { 173 OS << ".lsym" << ' ' << Symbol << ',' << Value << '\n'; 174} 175 176void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 177 unsigned Pow2Alignment, bool IsLocal) { 178 if (IsLocal) 179 OS << ".lcomm"; 180 else 181 OS << ".comm"; 182 OS << ' ' << Symbol << ',' << Size; 183 if (Pow2Alignment != 0) 184 OS << ',' << Pow2Alignment; 185 OS << '\n'; 186} 187 188void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 189 unsigned Size, unsigned Pow2Alignment) { 190 // Note: a .zerofill directive does not switch sections. 191 OS << ".zerofill "; 192 193 // This is a mach-o specific directive. 194 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 195 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 196 197 if (Symbol != NULL) { 198 OS << ',' << Symbol << ',' << Size; 199 if (Pow2Alignment != 0) 200 OS << ',' << Pow2Alignment; 201 } 202 OS << '\n'; 203} 204 205void MCAsmStreamer::EmitBytes(const StringRef &Data) { 206 assert(CurSection && "Cannot emit contents before setting section!"); 207 for (unsigned i = 0, e = Data.size(); i != e; ++i) 208 OS << ".byte " << (unsigned) (unsigned char) Data[i] << '\n'; 209} 210 211void MCAsmStreamer::EmitValue(const MCValue &Value, unsigned Size) { 212 assert(CurSection && "Cannot emit contents before setting section!"); 213 // Need target hooks to know how to print this. 214 switch (Size) { 215 default: 216 llvm_unreachable("Invalid size for machine code value!"); 217 case 1: OS << ".byte"; break; 218 case 2: OS << ".short"; break; 219 case 4: OS << ".long"; break; 220 case 8: OS << ".quad"; break; 221 } 222 223 OS << ' ' << truncateToSize(Value, Size) << '\n'; 224} 225 226void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 227 unsigned ValueSize, 228 unsigned MaxBytesToEmit) { 229 // Some assemblers don't support non-power of two alignments, so we always 230 // emit alignments as a power of two if possible. 231 if (isPowerOf2_32(ByteAlignment)) { 232 OS << TAI.getAlignDirective(); 233 234 if (TAI.getAlignmentIsInBytes()) 235 OS << ByteAlignment; 236 else 237 OS << Log2_32(ByteAlignment); 238 239 if (Value || MaxBytesToEmit) { 240 OS << ", " << truncateToSize(Value, ValueSize); 241 242 if (MaxBytesToEmit) 243 OS << ", " << MaxBytesToEmit; 244 } 245 OS << '\n'; 246 return; 247 } 248 249 // Non-power of two alignment. This is not widely supported by assemblers. 250 // FIXME: Parameterize this based on TAI. 251 switch (ValueSize) { 252 default: llvm_unreachable("Invalid size for machine code value!"); 253 case 1: OS << ".balign"; break; 254 case 2: OS << ".balignw"; break; 255 case 4: OS << ".balignl"; break; 256 case 8: llvm_unreachable("Unsupported alignment size!"); 257 } 258 259 OS << ' ' << ByteAlignment; 260 OS << ", " << truncateToSize(Value, ValueSize); 261 if (MaxBytesToEmit) 262 OS << ", " << MaxBytesToEmit; 263 OS << '\n'; 264} 265 266void MCAsmStreamer::EmitValueToOffset(const MCValue &Offset, 267 unsigned char Value) { 268 // FIXME: Verify that Offset is associated with the current section. 269 OS << ".org " << Offset << ", " << (unsigned) Value << '\n'; 270} 271 272static raw_ostream &operator<<(raw_ostream &OS, const MCOperand &Op) { 273 if (Op.isReg()) 274 return OS << "reg:" << Op.getReg(); 275 if (Op.isImm()) 276 return OS << "imm:" << Op.getImm(); 277 if (Op.isMBBLabel()) 278 return OS << "mbblabel:(" 279 << Op.getMBBLabelFunction() << ", " << Op.getMBBLabelBlock(); 280 assert(Op.isMCValue() && "Invalid operand!"); 281 return OS << "val:" << Op.getMCValue(); 282} 283 284void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 285 assert(CurSection && "Cannot emit contents before setting section!"); 286 287 // If we have an AsmPrinter, use that to print. 288 if (Printer) { 289 Printer->printMCInst(&Inst); 290 return; 291 } 292 293 // Otherwise fall back to a structural printing for now. Eventually we should 294 // always have access to the target specific printer. 295 OS << "MCInst(" 296 << "opcode=" << Inst.getOpcode() << ", " 297 << "operands=["; 298 for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { 299 if (i) 300 OS << ", "; 301 OS << Inst.getOperand(i); 302 } 303 OS << "])\n"; 304} 305 306void MCAsmStreamer::Finish() { 307 OS.flush(); 308} 309 310MCStreamer *llvm::createAsmStreamer(MCContext &Context, raw_ostream &OS, 311 const TargetAsmInfo &TAI, AsmPrinter *AP) { 312 return new MCAsmStreamer(Context, OS, TAI, AP); 313} 314