MCMachOStreamer.cpp revision 205407
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/MCCodeEmitter.h" 15#include "llvm/MC/MCExpr.h" 16#include "llvm/MC/MCInst.h" 17#include "llvm/MC/MCSection.h" 18#include "llvm/MC/MCSymbol.h" 19#include "llvm/Support/ErrorHandling.h" 20#include "llvm/Support/raw_ostream.h" 21using namespace llvm; 22 23namespace { 24 25class MCMachOStreamer : public MCStreamer { 26 /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest 27 /// 16 bits of the implementation defined flags. 28 enum SymbolFlags { // See <mach-o/nlist.h>. 29 SF_DescFlagsMask = 0xFFFF, 30 31 // Reference type flags. 32 SF_ReferenceTypeMask = 0x0007, 33 SF_ReferenceTypeUndefinedNonLazy = 0x0000, 34 SF_ReferenceTypeUndefinedLazy = 0x0001, 35 SF_ReferenceTypeDefined = 0x0002, 36 SF_ReferenceTypePrivateDefined = 0x0003, 37 SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, 38 SF_ReferenceTypePrivateUndefinedLazy = 0x0005, 39 40 // Other 'desc' flags. 41 SF_NoDeadStrip = 0x0020, 42 SF_WeakReference = 0x0040, 43 SF_WeakDefinition = 0x0080 44 }; 45 46private: 47 MCAssembler Assembler; 48 MCSectionData *CurSectionData; 49 50private: 51 MCFragment *getCurrentFragment() const { 52 assert(CurSectionData && "No current section!"); 53 54 if (!CurSectionData->empty()) 55 return &CurSectionData->getFragmentList().back(); 56 57 return 0; 58 } 59 60public: 61 MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, 62 raw_ostream &_OS, MCCodeEmitter *_Emitter) 63 : MCStreamer(Context), Assembler(Context, TAB, *_Emitter, _OS), 64 CurSectionData(0) {} 65 ~MCMachOStreamer() {} 66 67 const MCExpr *AddValueSymbols(const MCExpr *Value) { 68 switch (Value->getKind()) { 69 case MCExpr::Target: assert(0 && "Can't handle target exprs yet!"); 70 case MCExpr::Constant: 71 break; 72 73 case MCExpr::Binary: { 74 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); 75 AddValueSymbols(BE->getLHS()); 76 AddValueSymbols(BE->getRHS()); 77 break; 78 } 79 80 case MCExpr::SymbolRef: 81 Assembler.getOrCreateSymbolData( 82 cast<MCSymbolRefExpr>(Value)->getSymbol()); 83 break; 84 85 case MCExpr::Unary: 86 AddValueSymbols(cast<MCUnaryExpr>(Value)->getSubExpr()); 87 break; 88 } 89 90 return Value; 91 } 92 93 /// @name MCStreamer Interface 94 /// @{ 95 96 virtual void SwitchSection(const MCSection *Section); 97 virtual void EmitLabel(MCSymbol *Symbol); 98 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 99 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 100 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 101 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 102 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 103 unsigned ByteAlignment); 104 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 105 assert(0 && "macho doesn't support this directive"); 106 } 107 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 108 assert(0 && "macho doesn't support this directive"); 109 } 110 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, 111 unsigned Size = 0, unsigned ByteAlignment = 0); 112 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 113 virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); 114 virtual void EmitGPRel32Value(const MCExpr *Value) { 115 assert(0 && "macho doesn't support this directive"); 116 } 117 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 118 unsigned ValueSize = 1, 119 unsigned MaxBytesToEmit = 0); 120 virtual void EmitCodeAlignment(unsigned ByteAlignment, 121 unsigned MaxBytesToEmit = 0); 122 virtual void EmitValueToOffset(const MCExpr *Offset, 123 unsigned char Value = 0); 124 125 virtual void EmitFileDirective(StringRef Filename) { 126 errs() << "FIXME: MCMachoStreamer:EmitFileDirective not implemented\n"; 127 } 128 virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename) { 129 errs() << "FIXME: MCMachoStreamer:EmitDwarfFileDirective not implemented\n"; 130 } 131 132 virtual void EmitInstruction(const MCInst &Inst); 133 virtual void Finish(); 134 135 /// @} 136}; 137 138} // end anonymous namespace. 139 140void MCMachOStreamer::SwitchSection(const MCSection *Section) { 141 assert(Section && "Cannot switch to a null section!"); 142 143 // If already in this section, then this is a noop. 144 if (Section == CurSection) return; 145 146 CurSection = Section; 147 CurSectionData = &Assembler.getOrCreateSectionData(*Section); 148} 149 150void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { 151 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 152 153 // FIXME: We should also use offsets into Fill fragments. 154 MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 155 if (!F) 156 F = new MCDataFragment(CurSectionData); 157 158 MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); 159 assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); 160 SD.setFragment(F); 161 SD.setOffset(F->getContents().size()); 162 163 // This causes the reference type and weak reference flags to be cleared. 164 SD.setFlags(SD.getFlags() & ~(SF_WeakReference | SF_ReferenceTypeMask)); 165 166 Symbol->setSection(*CurSection); 167} 168 169void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 170 switch (Flag) { 171 case MCAF_SubsectionsViaSymbols: 172 Assembler.setSubsectionsViaSymbols(true); 173 return; 174 } 175 176 assert(0 && "invalid assembler flag!"); 177} 178 179void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 180 // Only absolute symbols can be redefined. 181 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 182 "Cannot define a symbol twice!"); 183 184 // FIXME: Lift context changes into super class. 185 // FIXME: Set associated section. 186 Symbol->setValue(AddValueSymbols(Value)); 187} 188 189void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 190 MCSymbolAttr Attribute) { 191 // Indirect symbols are handled differently, to match how 'as' handles 192 // them. This makes writing matching .o files easier. 193 if (Attribute == MCSA_IndirectSymbol) { 194 // Note that we intentionally cannot use the symbol data here; this is 195 // important for matching the string table that 'as' generates. 196 IndirectSymbolData ISD; 197 ISD.Symbol = Symbol; 198 ISD.SectionData = CurSectionData; 199 Assembler.getIndirectSymbols().push_back(ISD); 200 return; 201 } 202 203 // Adding a symbol attribute always introduces the symbol, note that an 204 // important side effect of calling getOrCreateSymbolData here is to register 205 // the symbol with the assembler. 206 MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); 207 208 // The implementation of symbol attributes is designed to match 'as', but it 209 // leaves much to desired. It doesn't really make sense to arbitrarily add and 210 // remove flags, but 'as' allows this (in particular, see .desc). 211 // 212 // In the future it might be worth trying to make these operations more well 213 // defined. 214 switch (Attribute) { 215 case MCSA_Invalid: 216 case MCSA_ELF_TypeFunction: 217 case MCSA_ELF_TypeIndFunction: 218 case MCSA_ELF_TypeObject: 219 case MCSA_ELF_TypeTLS: 220 case MCSA_ELF_TypeCommon: 221 case MCSA_ELF_TypeNoType: 222 case MCSA_IndirectSymbol: 223 case MCSA_Hidden: 224 case MCSA_Internal: 225 case MCSA_Protected: 226 case MCSA_Weak: 227 case MCSA_Local: 228 assert(0 && "Invalid symbol attribute for Mach-O!"); 229 break; 230 231 case MCSA_Global: 232 SD.setExternal(true); 233 break; 234 235 case MCSA_LazyReference: 236 // FIXME: This requires -dynamic. 237 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 238 if (Symbol->isUndefined()) 239 SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); 240 break; 241 242 // Since .reference sets the no dead strip bit, it is equivalent to 243 // .no_dead_strip in practice. 244 case MCSA_Reference: 245 case MCSA_NoDeadStrip: 246 SD.setFlags(SD.getFlags() | SF_NoDeadStrip); 247 break; 248 249 case MCSA_PrivateExtern: 250 SD.setExternal(true); 251 SD.setPrivateExtern(true); 252 break; 253 254 case MCSA_WeakReference: 255 // FIXME: This requires -dynamic. 256 if (Symbol->isUndefined()) 257 SD.setFlags(SD.getFlags() | SF_WeakReference); 258 break; 259 260 case MCSA_WeakDefinition: 261 // FIXME: 'as' enforces that this is defined and global. The manual claims 262 // it has to be in a coalesced section, but this isn't enforced. 263 SD.setFlags(SD.getFlags() | SF_WeakDefinition); 264 break; 265 } 266} 267 268void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 269 // Encode the 'desc' value into the lowest implementation defined bits. 270 assert(DescValue == (DescValue & SF_DescFlagsMask) && 271 "Invalid .desc value!"); 272 Assembler.getOrCreateSymbolData(*Symbol).setFlags(DescValue&SF_DescFlagsMask); 273} 274 275void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 276 unsigned ByteAlignment) { 277 // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. 278 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 279 280 MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); 281 SD.setExternal(true); 282 SD.setCommon(Size, ByteAlignment); 283} 284 285void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 286 unsigned Size, unsigned ByteAlignment) { 287 MCSectionData &SectData = Assembler.getOrCreateSectionData(*Section); 288 289 // The symbol may not be present, which only creates the section. 290 if (!Symbol) 291 return; 292 293 // FIXME: Assert that this section has the zerofill type. 294 295 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 296 297 MCSymbolData &SD = Assembler.getOrCreateSymbolData(*Symbol); 298 299 MCFragment *F = new MCZeroFillFragment(Size, ByteAlignment, &SectData); 300 SD.setFragment(F); 301 302 Symbol->setSection(*Section); 303 304 // Update the maximum alignment on the zero fill section if necessary. 305 if (ByteAlignment > SectData.getAlignment()) 306 SectData.setAlignment(ByteAlignment); 307} 308 309void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 310 MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 311 if (!DF) 312 DF = new MCDataFragment(CurSectionData); 313 DF->getContents().append(Data.begin(), Data.end()); 314} 315 316void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, 317 unsigned AddrSpace) { 318 MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 319 if (!DF) 320 DF = new MCDataFragment(CurSectionData); 321 322 // Avoid fixups when possible. 323 int64_t AbsValue; 324 if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { 325 // FIXME: Endianness assumption. 326 for (unsigned i = 0; i != Size; ++i) 327 DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); 328 } else { 329 DF->addFixup(MCAsmFixup(DF->getContents().size(), *AddValueSymbols(Value), 330 MCFixup::getKindForSize(Size))); 331 DF->getContents().resize(DF->getContents().size() + Size, 0); 332 } 333} 334 335void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, 336 int64_t Value, unsigned ValueSize, 337 unsigned MaxBytesToEmit) { 338 if (MaxBytesToEmit == 0) 339 MaxBytesToEmit = ByteAlignment; 340 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 341 false /* EmitNops */, CurSectionData); 342 343 // Update the maximum alignment on the current section if necessary. 344 if (ByteAlignment > CurSectionData->getAlignment()) 345 CurSectionData->setAlignment(ByteAlignment); 346} 347 348void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment, 349 unsigned MaxBytesToEmit) { 350 if (MaxBytesToEmit == 0) 351 MaxBytesToEmit = ByteAlignment; 352 // FIXME the 0x90 is the default x86 1 byte nop opcode. 353 new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit, 354 true /* EmitNops */, CurSectionData); 355 356 // Update the maximum alignment on the current section if necessary. 357 if (ByteAlignment > CurSectionData->getAlignment()) 358 CurSectionData->setAlignment(ByteAlignment); 359} 360 361void MCMachOStreamer::EmitValueToOffset(const MCExpr *Offset, 362 unsigned char Value) { 363 new MCOrgFragment(*Offset, Value, CurSectionData); 364} 365 366void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { 367 // Scan for values. 368 for (unsigned i = 0; i != Inst.getNumOperands(); ++i) 369 if (Inst.getOperand(i).isExpr()) 370 AddValueSymbols(Inst.getOperand(i).getExpr()); 371 372 CurSectionData->setHasInstructions(true); 373 374 SmallVector<MCFixup, 4> Fixups; 375 SmallString<256> Code; 376 raw_svector_ostream VecOS(Code); 377 Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups); 378 VecOS.flush(); 379 380 // Add the fixups and data. 381 MCDataFragment *DF = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); 382 if (!DF) 383 DF = new MCDataFragment(CurSectionData); 384 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 385 MCFixup &F = Fixups[i]; 386 DF->addFixup(MCAsmFixup(DF->getContents().size()+F.getOffset(), 387 *F.getValue(), F.getKind())); 388 } 389 DF->getContents().append(Code.begin(), Code.end()); 390} 391 392void MCMachOStreamer::Finish() { 393 Assembler.Finish(); 394} 395 396MCStreamer *llvm::createMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, 397 raw_ostream &OS, MCCodeEmitter *CE) { 398 return new MCMachOStreamer(Context, TAB, OS, CE); 399} 400