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