WinCOFFStreamer.cpp revision 8067adc271d7ccfcd28a238d73942b21a5e2bc62
1//===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===// 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// This file contains an implementation of a Win32 COFF object file streamer. 11// 12//===----------------------------------------------------------------------===// 13 14#define DEBUG_TYPE "WinCOFFStreamer" 15 16#include "llvm/MC/MCObjectStreamer.h" 17#include "llvm/MC/MCContext.h" 18#include "llvm/MC/MCSection.h" 19#include "llvm/MC/MCSymbol.h" 20#include "llvm/MC/MCExpr.h" 21#include "llvm/MC/MCValue.h" 22#include "llvm/MC/MCAssembler.h" 23#include "llvm/MC/MCAsmLayout.h" 24#include "llvm/MC/MCCodeEmitter.h" 25#include "llvm/MC/MCSectionCOFF.h" 26#include "llvm/Target/TargetRegistry.h" 27#include "llvm/Target/TargetAsmBackend.h" 28#include "llvm/ADT/StringMap.h" 29 30#include "llvm/Support/COFF.h" 31#include "llvm/Support/Debug.h" 32#include "llvm/Support/ErrorHandling.h" 33#include "llvm/Support/raw_ostream.h" 34using namespace llvm; 35 36namespace { 37class WinCOFFStreamer : public MCObjectStreamer { 38public: 39 MCSymbol const *CurSymbol; 40 41 WinCOFFStreamer(MCContext &Context, 42 TargetAsmBackend &TAB, 43 MCCodeEmitter &CE, 44 raw_ostream &OS); 45 46 void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 47 unsigned ByteAlignment, bool External); 48 49 // MCStreamer interface 50 51 virtual void EmitLabel(MCSymbol *Symbol); 52 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 53 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 54 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 55 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 56 virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); 57 virtual void EmitCOFFSymbolStorageClass(int StorageClass); 58 virtual void EmitCOFFSymbolType(int Type); 59 virtual void EndCOFFSymbolDef(); 60 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 61 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 62 unsigned ByteAlignment); 63 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); 64 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 65 unsigned Size,unsigned ByteAlignment); 66 virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 67 uint64_t Size, unsigned ByteAlignment); 68 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 69 virtual void EmitValue(const MCExpr *Value, unsigned Size, 70 unsigned AddrSpace); 71 virtual void EmitGPRel32Value(const MCExpr *Value); 72 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 73 unsigned ValueSize, unsigned MaxBytesToEmit); 74 virtual void EmitCodeAlignment(unsigned ByteAlignment, 75 unsigned MaxBytesToEmit); 76 virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value); 77 virtual void EmitFileDirective(StringRef Filename); 78 virtual void EmitDwarfFileDirective(unsigned FileNo,StringRef Filename); 79 virtual void EmitInstruction(const MCInst &Instruction); 80 virtual void Finish(); 81}; 82} // end anonymous namespace. 83 84WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, 85 TargetAsmBackend &TAB, 86 MCCodeEmitter &CE, 87 raw_ostream &OS) 88 : MCObjectStreamer(Context, TAB, OS, &CE) 89 , CurSymbol(NULL) { 90} 91 92void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 93 unsigned ByteAlignment, bool External) { 94 assert(!Symbol->isInSection() && "Symbol must not already have a section!"); 95 96 std::string SectionName(".bss$linkonce"); 97 SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); 98 99 MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); 100 101 unsigned Characteristics = 102 COFF::IMAGE_SCN_LNK_COMDAT | 103 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 104 COFF::IMAGE_SCN_MEM_READ | 105 COFF::IMAGE_SCN_MEM_WRITE; 106 107 int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; 108 109 const MCSection *Section = MCStreamer::getContext().getCOFFSection( 110 SectionName, Characteristics, Selection, SectionKind::getBSS()); 111 112 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); 113 114 if (SectionData.getAlignment() < ByteAlignment) 115 SectionData.setAlignment(ByteAlignment); 116 117 SymbolData.setExternal(External); 118 119 Symbol->setSection(*Section); 120 121 if (ByteAlignment != 1) 122 new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); 123 124 SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); 125} 126 127// MCStreamer interface 128 129void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { 130 // TODO: This is copied almost exactly from the MachOStreamer. Consider 131 // merging into MCObjectStreamer? 132 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 133 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); 134 assert(CurSection && "Cannot emit before setting section!"); 135 136 Symbol->setSection(*CurSection); 137 138 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 139 140 // FIXME: This is wasteful, we don't necessarily need to create a data 141 // fragment. Instead, we should mark the symbol as pointing into the data 142 // fragment if it exists, otherwise we should just queue the label and set its 143 // fragment pointer when we emit the next fragment. 144 MCDataFragment *F = getOrCreateDataFragment(); 145 assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); 146 SD.setFragment(F); 147 SD.setOffset(F->getContents().size()); 148} 149 150void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 151 llvm_unreachable("not implemented"); 152} 153 154void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 155 // TODO: This is exactly the same as MachOStreamer. Consider merging into 156 // MCObjectStreamer. 157 getAssembler().getOrCreateSymbolData(*Symbol); 158 AddValueSymbols(Value); 159 Symbol->setVariableValue(Value); 160} 161 162void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 163 MCSymbolAttr Attribute) { 164 switch (Attribute) { 165 case MCSA_WeakReference: 166 getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags( 167 COFF::SF_WeakReference, 168 COFF::SF_WeakReference); 169 break; 170 171 case MCSA_Global: 172 getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); 173 break; 174 175 default: 176 llvm_unreachable("unsupported attribute"); 177 break; 178 } 179} 180 181void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 182 llvm_unreachable("not implemented"); 183} 184 185void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 186 assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " 187 "to BeginCOFFSymbolDef!"); 188 CurSymbol = Symbol; 189} 190 191void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 192 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 193 assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " 194 "the first byte!"); 195 196 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 197 StorageClass << COFF::SF_ClassShift, 198 COFF::SF_ClassMask); 199} 200 201void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { 202 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 203 assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " 204 "bytes"); 205 206 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 207 Type << COFF::SF_TypeShift, 208 COFF::SF_TypeMask); 209} 210 211void WinCOFFStreamer::EndCOFFSymbolDef() { 212 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 213 CurSymbol = NULL; 214} 215 216void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 217 llvm_unreachable("not implemented"); 218} 219 220void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 221 unsigned ByteAlignment) { 222 AddCommonSymbol(Symbol, Size, ByteAlignment, true); 223} 224 225void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 226 AddCommonSymbol(Symbol, Size, 1, false); 227} 228 229void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 230 unsigned Size,unsigned ByteAlignment) { 231 llvm_unreachable("not implemented"); 232} 233 234void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 235 uint64_t Size, unsigned ByteAlignment) { 236 llvm_unreachable("not implemented"); 237} 238 239void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 240 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 241 // MCObjectStreamer? 242 getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); 243} 244 245void WinCOFFStreamer::EmitValue(const MCExpr *Value, unsigned Size, 246 unsigned AddrSpace) { 247 assert(AddrSpace == 0 && "Address space must be 0!"); 248 249 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 250 // MCObjectStreamer? 251 MCDataFragment *DF = getOrCreateDataFragment(); 252 253 // Avoid fixups when possible. 254 int64_t AbsValue; 255 if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { 256 // FIXME: Endianness assumption. 257 for (unsigned i = 0; i != Size; ++i) 258 DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); 259 } else { 260 DF->addFixup(MCFixup::Create(DF->getContents().size(), 261 AddValueSymbols(Value), 262 MCFixup::getKindForSize(Size))); 263 DF->getContents().resize(DF->getContents().size() + Size, 0); 264 } 265} 266 267void WinCOFFStreamer::EmitGPRel32Value(const MCExpr *Value) { 268 llvm_unreachable("not implemented"); 269} 270 271void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment, 272 int64_t Value, 273 unsigned ValueSize, 274 unsigned MaxBytesToEmit) { 275 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 276 // MCObjectStreamer? 277 if (MaxBytesToEmit == 0) 278 MaxBytesToEmit = ByteAlignment; 279 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 280 getCurrentSectionData()); 281 282 // Update the maximum alignment on the current section if necessary. 283 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 284 getCurrentSectionData()->setAlignment(ByteAlignment); 285} 286 287void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment, 288 unsigned MaxBytesToEmit) { 289 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 290 // MCObjectStreamer? 291 if (MaxBytesToEmit == 0) 292 MaxBytesToEmit = ByteAlignment; 293 MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, 294 getCurrentSectionData()); 295 F->setEmitNops(true); 296 297 // Update the maximum alignment on the current section if necessary. 298 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 299 getCurrentSectionData()->setAlignment(ByteAlignment); 300} 301 302void WinCOFFStreamer::EmitValueToOffset(const MCExpr *Offset, 303 unsigned char Value) { 304 llvm_unreachable("not implemented"); 305} 306 307void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { 308 // Ignore for now, linkers don't care, and proper debug 309 // info will be a much large effort. 310} 311 312void WinCOFFStreamer::EmitDwarfFileDirective(unsigned FileNo, 313 StringRef Filename) { 314 llvm_unreachable("not implemented"); 315} 316 317void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) { 318 for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i) 319 if (Instruction.getOperand(i).isExpr()) 320 AddValueSymbols(Instruction.getOperand(i).getExpr()); 321 322 getCurrentSectionData()->setHasInstructions(true); 323 324 MCInstFragment *Fragment = 325 new MCInstFragment(Instruction, getCurrentSectionData()); 326 327 raw_svector_ostream VecOS(Fragment->getCode()); 328 329 getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS, 330 Fragment->getFixups()); 331} 332 333void WinCOFFStreamer::Finish() { 334 MCObjectStreamer::Finish(); 335} 336 337namespace llvm 338{ 339 MCStreamer *createWinCOFFStreamer(MCContext &Context, 340 TargetAsmBackend &TAB, 341 MCCodeEmitter &CE, 342 raw_ostream &OS) { 343 return new WinCOFFStreamer(Context, TAB, CE, OS); 344 } 345} 346