MCMachOStreamer.cpp revision 6aff2fbd56d4bc2d6029f7c9bd49a97f6dc01213
1//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object 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/MCAssembler.h" 13#include "llvm/MC/MCContext.h" 14#include "llvm/MC/MCSection.h" 15#include "llvm/MC/MCSymbol.h" 16#include "llvm/Support/ErrorHandling.h" 17using namespace llvm; 18 19namespace { 20 21class MCMachOStreamer : public MCStreamer { 22 /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest 23 /// 16 bits of the implementation defined flags. 24 enum SymbolFlags { // See <mach-o/nlist.h>. 25 SF_DescFlagsMask = 0xFFFF, 26 27 // Reference type flags. 28 SF_ReferenceTypeMask = 0x0007, 29 SF_ReferenceTypeUndefinedNonLazy = 0x0000, 30 SF_ReferenceTypeUndefinedLazy = 0x0001, 31 SF_ReferenceTypeDefined = 0x0002, 32 SF_ReferenceTypePrivateDefined = 0x0003, 33 SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, 34 SF_ReferenceTypePrivateUndefinedLazy = 0x0005, 35 36 // Other 'desc' flags. 37 SF_NoDeadStrip = 0x0020, 38 SF_WeakReference = 0x0040, 39 SF_WeakDefinition = 0x0080 40 }; 41 42private: 43 MCAssembler Assembler; 44 45 MCSectionData *CurSectionData; 46 47 DenseMap<const MCSection*, MCSectionData*> SectionMap; 48 49 DenseMap<const MCSymbol*, MCSymbolData*> SymbolMap; 50 51private: 52 MCFragment *getCurrentFragment() const { 53 assert(CurSectionData && "No current section!"); 54 55 if (!CurSectionData->empty()) 56 return &CurSectionData->getFragmentList().back(); 57 58 return 0; 59 } 60 61 MCSymbolData &getSymbolData(MCSymbol &Symbol) { 62 MCSymbolData *&Entry = SymbolMap[&Symbol]; 63 64 if (!Entry) 65 Entry = new MCSymbolData(Symbol, 0, 0, &Assembler); 66 67 return *Entry; 68 } 69 70public: 71 MCMachOStreamer(MCContext &Context, raw_ostream &_OS) 72 : MCStreamer(Context), Assembler(_OS), CurSectionData(0) {} 73 ~MCMachOStreamer() {} 74 75 /// @name MCStreamer Interface 76 /// @{ 77 78 virtual void SwitchSection(const MCSection *Section); 79 80 virtual void EmitLabel(MCSymbol *Symbol); 81 82 virtual void EmitAssemblerFlag(AssemblerFlag Flag); 83 84 virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 85 bool MakeAbsolute = false); 86 87 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 88 89 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 90 91 virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value); 92 93 virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 94 unsigned Pow2Alignment, bool IsLocal); 95 96 virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL, 97 unsigned Size = 0, unsigned Pow2Alignment = 0); 98 99 virtual void EmitBytes(const StringRef &Data); 100 101 virtual void EmitValue(const MCValue &Value, unsigned Size); 102 103 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 104 unsigned ValueSize = 1, 105 unsigned MaxBytesToEmit = 0); 106 107 virtual void EmitValueToOffset(const MCValue &Offset, 108 unsigned char Value = 0); 109 110 virtual void EmitInstruction(const MCInst &Inst); 111 112 virtual void Finish(); 113 114 /// @} 115}; 116 117} // end anonymous namespace. 118 119void MCMachOStreamer::SwitchSection(const MCSection *Section) { 120 assert(Section && "Cannot switch to a null section!"); 121 122 // If already in this section, then this is a noop. 123 if (Section == CurSection) return; 124 125 CurSection = Section; 126 MCSectionData *&Entry = SectionMap[Section]; 127 128 if (!Entry) 129 Entry = new MCSectionData(*Section, &Assembler); 130 131 CurSectionData = Entry; 132} 133 134void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { 135 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 136 137 MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 138 if (!F) 139 F = new MCDataFragment(CurSectionData); 140 141 MCSymbolData &SD = getSymbolData(*Symbol); 142 assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); 143 SD.setFragment(F); 144 SD.setOffset(F->getContents().size()); 145 146 // This causes the reference type and weak reference flags to be cleared. 147 SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask)); 148 149 Symbol->setSection(*CurSection); 150} 151 152void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 153 llvm_unreachable("FIXME: Not yet implemented!"); 154} 155 156void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, 157 const MCValue &Value, 158 bool MakeAbsolute) { 159 // Only absolute symbols can be redefined. 160 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 161 "Cannot define a symbol twice!"); 162 163 llvm_unreachable("FIXME: Not yet implemented!"); 164} 165 166void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 167 SymbolAttr Attribute) { 168 // Adding a symbol attribute always introduces the symbol, note that an 169 // important side effect of calling getSymbolData here is to register the 170 // symbol with the assembler. 171 MCSymbolData &SD = getSymbolData(*Symbol); 172 173 // The implementation of symbol attributes is designed to match 'as', but it 174 // leaves much to desired. It doesn't really make sense to arbitrarily add and 175 // remove flags, but 'as' allows this (in particular, see .desc). 176 // 177 // In the future it might be worth trying to make these operations more well 178 // defined. 179 switch (Attribute) { 180 case MCStreamer::Hidden: 181 case MCStreamer::Internal: 182 case MCStreamer::Protected: 183 case MCStreamer::Weak: 184 assert(0 && "Invalid symbol attribute for Mach-O!"); 185 break; 186 187 case MCStreamer::Global: 188 getSymbolData(*Symbol).setExternal(true); 189 break; 190 191 case MCStreamer::LazyReference: 192 // FIXME: This requires -dynamic. 193 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 194 if (Symbol->isUndefined()) 195 SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); 196 break; 197 198 case MCStreamer::IndirectSymbol: 199 llvm_unreachable("FIXME: Not yet implemented!"); 200 break; 201 202 // Since .reference sets the no dead strip bit, it is equivalent to 203 // .no_dead_strip in practice. 204 case MCStreamer::Reference: 205 case MCStreamer::NoDeadStrip: 206 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 207 break; 208 209 case MCStreamer::PrivateExtern: 210 SD.setExternal(true); 211 SD.setPrivateExtern(true); 212 break; 213 214 case MCStreamer::WeakReference: 215 // FIXME: This requires -dynamic. 216 if (Symbol->isUndefined()) 217 SD.setFlags(SD.getFlags() | SF_WeakReference); 218 break; 219 220 case MCStreamer::WeakDefinition: 221 // FIXME: 'as' enforces that this is defined and global. The manual claims 222 // it has to be in a coalesced section, but this isn't enforced. 223 SD.setFlags(SD.getFlags() | SF_WeakDefinition); 224 break; 225 } 226} 227 228void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 229 // Encode the 'desc' value into the lowest implementation defined bits. 230 assert(DescValue == (DescValue & SF_DescFlagsMask) && 231 "Invalid .desc value!"); 232 getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); 233} 234 235void MCMachOStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { 236 llvm_unreachable("FIXME: Not yet implemented!"); 237} 238 239void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 240 unsigned Pow2Alignment, 241 bool IsLocal) { 242 llvm_unreachable("FIXME: Not yet implemented!"); 243} 244 245void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 246 unsigned Size, unsigned Pow2Alignment) { 247 llvm_unreachable("FIXME: Not yet implemented!"); 248} 249 250void MCMachOStreamer::EmitBytes(const StringRef &Data) { 251 MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 252 if (!DF) 253 DF = new MCDataFragment(CurSectionData); 254 DF->getContents().append(Data.begin(), Data.end()); 255} 256 257void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) { 258 new MCFillFragment(Value, Size, 1, CurSectionData); 259} 260 261void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, 262 int64_t Value, unsigned ValueSize, 263 unsigned MaxBytesToEmit) { 264 if (MaxBytesToEmit == 0) 265 MaxBytesToEmit = ByteAlignment; 266 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 267 CurSectionData); 268 269 // Update the maximum alignment on the current section if necessary. 270 if (ByteAlignment > CurSectionData->getAlignment()) 271 CurSectionData->setAlignment(ByteAlignment); 272} 273 274void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset, 275 unsigned char Value) { 276 new MCOrgFragment(Offset, Value, CurSectionData); 277} 278 279void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { 280 llvm_unreachable("FIXME: Not yet implemented!"); 281} 282 283void MCMachOStreamer::Finish() { 284 Assembler.Finish(); 285} 286 287MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS) { 288 return new MCMachOStreamer(Context, OS); 289} 290