WinCOFFStreamer.cpp revision 86c3647ddfa8c39ed5d9eba9f2547544270c7bde
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 InitSections(); 52 virtual void EmitLabel(MCSymbol *Symbol); 53 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 54 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 55 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 56 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 57 virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); 58 virtual void EmitCOFFSymbolStorageClass(int StorageClass); 59 virtual void EmitCOFFSymbolType(int Type); 60 virtual void EndCOFFSymbolDef(); 61 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 62 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 63 unsigned ByteAlignment); 64 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); 65 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 66 unsigned Size,unsigned ByteAlignment); 67 virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 68 uint64_t Size, unsigned ByteAlignment); 69 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 70 virtual void EmitValue(const MCExpr *Value, unsigned Size, 71 unsigned AddrSpace); 72 virtual void EmitGPRel32Value(const MCExpr *Value); 73 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 74 unsigned ValueSize, unsigned MaxBytesToEmit); 75 virtual void EmitCodeAlignment(unsigned ByteAlignment, 76 unsigned MaxBytesToEmit); 77 virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value); 78 virtual void EmitFileDirective(StringRef Filename); 79 virtual void EmitDwarfFileDirective(unsigned FileNo,StringRef Filename); 80 virtual void EmitInstruction(const MCInst &Instruction); 81 virtual void Finish(); 82}; 83} // end anonymous namespace. 84 85WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, 86 TargetAsmBackend &TAB, 87 MCCodeEmitter &CE, 88 raw_ostream &OS) 89 : MCObjectStreamer(Context, TAB, OS, &CE, true) 90 , CurSymbol(NULL) { 91} 92 93void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 94 unsigned ByteAlignment, bool External) { 95 assert(!Symbol->isInSection() && "Symbol must not already have a section!"); 96 97 std::string SectionName(".bss$linkonce"); 98 SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); 99 100 MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); 101 102 unsigned Characteristics = 103 COFF::IMAGE_SCN_LNK_COMDAT | 104 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 105 COFF::IMAGE_SCN_MEM_READ | 106 COFF::IMAGE_SCN_MEM_WRITE; 107 108 int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; 109 110 const MCSection *Section = MCStreamer::getContext().getCOFFSection( 111 SectionName, Characteristics, Selection, SectionKind::getBSS()); 112 113 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); 114 115 if (SectionData.getAlignment() < ByteAlignment) 116 SectionData.setAlignment(ByteAlignment); 117 118 SymbolData.setExternal(External); 119 120 Symbol->setSection(*Section); 121 122 if (ByteAlignment != 1) 123 new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); 124 125 SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); 126} 127 128// MCStreamer interface 129 130void WinCOFFStreamer::InitSections() { 131} 132 133void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { 134 // TODO: This is copied almost exactly from the MachOStreamer. Consider 135 // merging into MCObjectStreamer? 136 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 137 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); 138 assert(CurSection && "Cannot emit before setting section!"); 139 140 Symbol->setSection(*CurSection); 141 142 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 143 144 // FIXME: This is wasteful, we don't necessarily need to create a data 145 // fragment. Instead, we should mark the symbol as pointing into the data 146 // fragment if it exists, otherwise we should just queue the label and set its 147 // fragment pointer when we emit the next fragment. 148 MCDataFragment *DF = getOrCreateDataFragment(); 149 150 assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); 151 SD.setFragment(DF); 152 SD.setOffset(DF->getContents().size()); 153} 154 155void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 156 llvm_unreachable("not implemented"); 157} 158 159void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 160 // FIXME: This is all very ugly and depressing. What needs to happen here 161 // depends on quite a few things that are all part of relaxation, which we 162 // don't really even do. 163 164 if (Value->getKind() != MCExpr::SymbolRef) { 165 // TODO: This is exactly the same as MachOStreamer. Consider merging into 166 // MCObjectStreamer. 167 getAssembler().getOrCreateSymbolData(*Symbol); 168 AddValueSymbols(Value); 169 Symbol->setVariableValue(Value); 170 } else { 171 // FIXME: This is a horrible way to do this :(. This should really be 172 // handled after we are done with the MC* objects and immediately before 173 // writing out the object file when we know exactly what the symbol should 174 // look like in the coff symbol table. I'm not doing that now because the 175 // COFF object writer doesn't have a clearly defined separation between MC 176 // data structures, the object writers data structures, and the raw, POD, 177 // data structures that get written to disk. 178 179 // Copy over the aliased data. 180 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 181 const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData( 182 dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol()); 183 184 // FIXME: This is particularly nasty because it breaks as soon as any data 185 // members of MCSymbolData change. 186 SD.CommonAlign = RealSD.CommonAlign; 187 SD.CommonSize = RealSD.CommonSize; 188 SD.Flags = RealSD.Flags; 189 SD.Fragment = RealSD.Fragment; 190 SD.Index = RealSD.Index; 191 SD.IsExternal = RealSD.IsExternal; 192 SD.IsPrivateExtern = RealSD.IsPrivateExtern; 193 SD.Offset = RealSD.Offset; 194 SD.SymbolSize = RealSD.SymbolSize; 195 } 196} 197 198void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 199 MCSymbolAttr Attribute) { 200 switch (Attribute) { 201 case MCSA_WeakReference: 202 getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags( 203 COFF::SF_WeakReference, 204 COFF::SF_WeakReference); 205 break; 206 207 case MCSA_Global: 208 getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); 209 break; 210 211 default: 212 llvm_unreachable("unsupported attribute"); 213 break; 214 } 215} 216 217void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 218 llvm_unreachable("not implemented"); 219} 220 221void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 222 assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " 223 "to BeginCOFFSymbolDef!"); 224 CurSymbol = Symbol; 225} 226 227void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 228 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 229 assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " 230 "the first byte!"); 231 232 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 233 StorageClass << COFF::SF_ClassShift, 234 COFF::SF_ClassMask); 235} 236 237void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { 238 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 239 assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " 240 "bytes"); 241 242 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 243 Type << COFF::SF_TypeShift, 244 COFF::SF_TypeMask); 245} 246 247void WinCOFFStreamer::EndCOFFSymbolDef() { 248 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 249 CurSymbol = NULL; 250} 251 252void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 253 llvm_unreachable("not implemented"); 254} 255 256void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 257 unsigned ByteAlignment) { 258 AddCommonSymbol(Symbol, Size, ByteAlignment, true); 259} 260 261void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 262 AddCommonSymbol(Symbol, Size, 1, false); 263} 264 265void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 266 unsigned Size,unsigned ByteAlignment) { 267 llvm_unreachable("not implemented"); 268} 269 270void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 271 uint64_t Size, unsigned ByteAlignment) { 272 llvm_unreachable("not implemented"); 273} 274 275void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 276 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 277 // MCObjectStreamer? 278 getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); 279} 280 281void WinCOFFStreamer::EmitValue(const MCExpr *Value, unsigned Size, 282 unsigned AddrSpace) { 283 assert(AddrSpace == 0 && "Address space must be 0!"); 284 285 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 286 // MCObjectStreamer? 287 MCDataFragment *DF = getOrCreateDataFragment(); 288 289 // Avoid fixups when possible. 290 int64_t AbsValue; 291 if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { 292 // FIXME: Endianness assumption. 293 for (unsigned i = 0; i != Size; ++i) 294 DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); 295 } else { 296 DF->addFixup(MCFixup::Create(DF->getContents().size(), 297 AddValueSymbols(Value), 298 MCFixup::getKindForSize(Size))); 299 DF->getContents().resize(DF->getContents().size() + Size, 0); 300 } 301} 302 303void WinCOFFStreamer::EmitGPRel32Value(const MCExpr *Value) { 304 llvm_unreachable("not implemented"); 305} 306 307void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment, 308 int64_t Value, 309 unsigned ValueSize, 310 unsigned MaxBytesToEmit) { 311 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 312 // MCObjectStreamer? 313 if (MaxBytesToEmit == 0) 314 MaxBytesToEmit = ByteAlignment; 315 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 316 getCurrentSectionData()); 317 318 // Update the maximum alignment on the current section if necessary. 319 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 320 getCurrentSectionData()->setAlignment(ByteAlignment); 321} 322 323void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment, 324 unsigned MaxBytesToEmit) { 325 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 326 // MCObjectStreamer? 327 if (MaxBytesToEmit == 0) 328 MaxBytesToEmit = ByteAlignment; 329 MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, 330 getCurrentSectionData()); 331 F->setEmitNops(true); 332 333 // Update the maximum alignment on the current section if necessary. 334 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 335 getCurrentSectionData()->setAlignment(ByteAlignment); 336} 337 338void WinCOFFStreamer::EmitValueToOffset(const MCExpr *Offset, 339 unsigned char Value) { 340 llvm_unreachable("not implemented"); 341} 342 343void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { 344 // Ignore for now, linkers don't care, and proper debug 345 // info will be a much large effort. 346} 347 348void WinCOFFStreamer::EmitDwarfFileDirective(unsigned FileNo, 349 StringRef Filename) { 350 llvm_unreachable("not implemented"); 351} 352 353void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) { 354 for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i) 355 if (Instruction.getOperand(i).isExpr()) 356 AddValueSymbols(Instruction.getOperand(i).getExpr()); 357 358 getCurrentSectionData()->setHasInstructions(true); 359 360 MCInstFragment *Fragment = 361 new MCInstFragment(Instruction, getCurrentSectionData()); 362 363 raw_svector_ostream VecOS(Fragment->getCode()); 364 365 getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS, 366 Fragment->getFixups()); 367} 368 369void WinCOFFStreamer::Finish() { 370 MCObjectStreamer::Finish(); 371} 372 373namespace llvm 374{ 375 MCStreamer *createWinCOFFStreamer(MCContext &Context, 376 TargetAsmBackend &TAB, 377 MCCodeEmitter &CE, 378 raw_ostream &OS, 379 bool RelaxAll) { 380 WinCOFFStreamer *S = new WinCOFFStreamer(Context, TAB, CE, OS); 381 S->getAssembler().setRelaxAll(RelaxAll); 382 return S; 383 } 384} 385