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