MCMachOStreamer.cpp revision a421de11df9d2a07b9f95a1ad817467af426803a
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 const MCValue &AddValueSymbols(const MCValue &Value) { 76 if (Value.getSymA()) 77 getSymbolData(*const_cast<MCSymbol*>(Value.getSymA())); 78 if (Value.getSymB()) 79 getSymbolData(*const_cast<MCSymbol*>(Value.getSymB())); 80 return Value; 81 } 82 83 /// @name MCStreamer Interface 84 /// @{ 85 86 virtual void SwitchSection(const MCSection *Section); 87 88 virtual void EmitLabel(MCSymbol *Symbol); 89 90 virtual void EmitAssemblerFlag(AssemblerFlag Flag); 91 92 virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value, 93 bool MakeAbsolute = false); 94 95 virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute); 96 97 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 98 99 virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value); 100 101 virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 102 unsigned Pow2Alignment, bool IsLocal); 103 104 virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL, 105 unsigned Size = 0, unsigned Pow2Alignment = 0); 106 107 virtual void EmitBytes(const StringRef &Data); 108 109 virtual void EmitValue(const MCValue &Value, unsigned Size); 110 111 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 112 unsigned ValueSize = 1, 113 unsigned MaxBytesToEmit = 0); 114 115 virtual void EmitValueToOffset(const MCValue &Offset, 116 unsigned char Value = 0); 117 118 virtual void EmitInstruction(const MCInst &Inst); 119 120 virtual void Finish(); 121 122 /// @} 123}; 124 125} // end anonymous namespace. 126 127void MCMachOStreamer::SwitchSection(const MCSection *Section) { 128 assert(Section && "Cannot switch to a null section!"); 129 130 // If already in this section, then this is a noop. 131 if (Section == CurSection) return; 132 133 CurSection = Section; 134 MCSectionData *&Entry = SectionMap[Section]; 135 136 if (!Entry) 137 Entry = new MCSectionData(*Section, &Assembler); 138 139 CurSectionData = Entry; 140} 141 142void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { 143 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 144 145 // FIXME: We should also use offsets into Fill fragments. 146 MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 147 if (!F) 148 F = new MCDataFragment(CurSectionData); 149 150 MCSymbolData &SD = getSymbolData(*Symbol); 151 assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); 152 SD.setFragment(F); 153 SD.setOffset(F->getContents().size()); 154 155 // This causes the reference type and weak reference flags to be cleared. 156 SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask)); 157 158 Symbol->setSection(*CurSection); 159} 160 161void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) { 162 llvm_unreachable("FIXME: Not yet implemented!"); 163} 164 165void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, 166 const MCValue &Value, 167 bool MakeAbsolute) { 168 // Only absolute symbols can be redefined. 169 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 170 "Cannot define a symbol twice!"); 171 172 llvm_unreachable("FIXME: Not yet implemented!"); 173} 174 175void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 176 SymbolAttr Attribute) { 177 // Indirect symbols are handled differently, to match how 'as' handles 178 // them. This makes writing matching .o files easier. 179 if (Attribute == MCStreamer::IndirectSymbol) { 180 // Note that we intentionally cannot use the symbol data here; this is 181 // important for matching the string table that 'as' generates. 182 IndirectSymbolData ISD; 183 ISD.Symbol = Symbol; 184 ISD.SectionData = CurSectionData; 185 Assembler.getIndirectSymbols().push_back(ISD); 186 return; 187 } 188 189 // Adding a symbol attribute always introduces the symbol, note that an 190 // important side effect of calling getSymbolData here is to register the 191 // symbol with the assembler. 192 MCSymbolData &SD = getSymbolData(*Symbol); 193 194 // The implementation of symbol attributes is designed to match 'as', but it 195 // leaves much to desired. It doesn't really make sense to arbitrarily add and 196 // remove flags, but 'as' allows this (in particular, see .desc). 197 // 198 // In the future it might be worth trying to make these operations more well 199 // defined. 200 switch (Attribute) { 201 case MCStreamer::IndirectSymbol: 202 case MCStreamer::Hidden: 203 case MCStreamer::Internal: 204 case MCStreamer::Protected: 205 case MCStreamer::Weak: 206 assert(0 && "Invalid symbol attribute for Mach-O!"); 207 break; 208 209 case MCStreamer::Global: 210 getSymbolData(*Symbol).setExternal(true); 211 break; 212 213 case MCStreamer::LazyReference: 214 // FIXME: This requires -dynamic. 215 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 216 if (Symbol->isUndefined()) 217 SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); 218 break; 219 220 // Since .reference sets the no dead strip bit, it is equivalent to 221 // .no_dead_strip in practice. 222 case MCStreamer::Reference: 223 case MCStreamer::NoDeadStrip: 224 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 225 break; 226 227 case MCStreamer::PrivateExtern: 228 SD.setExternal(true); 229 SD.setPrivateExtern(true); 230 break; 231 232 case MCStreamer::WeakReference: 233 // FIXME: This requires -dynamic. 234 if (Symbol->isUndefined()) 235 SD.setFlags(SD.getFlags() | SF_WeakReference); 236 break; 237 238 case MCStreamer::WeakDefinition: 239 // FIXME: 'as' enforces that this is defined and global. The manual claims 240 // it has to be in a coalesced section, but this isn't enforced. 241 SD.setFlags(SD.getFlags() | SF_WeakDefinition); 242 break; 243 } 244} 245 246void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 247 // Encode the 'desc' value into the lowest implementation defined bits. 248 assert(DescValue == (DescValue & SF_DescFlagsMask) && 249 "Invalid .desc value!"); 250 getSymbolData(*Symbol).setFlags(DescValue & SF_DescFlagsMask); 251} 252 253void MCMachOStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) { 254 llvm_unreachable("FIXME: Not yet implemented!"); 255} 256 257void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, 258 unsigned Pow2Alignment, 259 bool IsLocal) { 260 llvm_unreachable("FIXME: Not yet implemented!"); 261} 262 263void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 264 unsigned Size, unsigned Pow2Alignment) { 265 llvm_unreachable("FIXME: Not yet implemented!"); 266} 267 268void MCMachOStreamer::EmitBytes(const StringRef &Data) { 269 MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 270 if (!DF) 271 DF = new MCDataFragment(CurSectionData); 272 DF->getContents().append(Data.begin(), Data.end()); 273} 274 275void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) { 276 new MCFillFragment(AddValueSymbols(Value), Size, 1, CurSectionData); 277} 278 279void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, 280 int64_t Value, unsigned ValueSize, 281 unsigned MaxBytesToEmit) { 282 if (MaxBytesToEmit == 0) 283 MaxBytesToEmit = ByteAlignment; 284 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 285 CurSectionData); 286 287 // Update the maximum alignment on the current section if necessary. 288 if (ByteAlignment > CurSectionData->getAlignment()) 289 CurSectionData->setAlignment(ByteAlignment); 290} 291 292void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset, 293 unsigned char Value) { 294 new MCOrgFragment(AddValueSymbols(Offset), Value, CurSectionData); 295} 296 297void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { 298 llvm_unreachable("FIXME: Not yet implemented!"); 299} 300 301void MCMachOStreamer::Finish() { 302 Assembler.Finish(); 303} 304 305MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS) { 306 return new MCMachOStreamer(Context, OS); 307} 308