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