WinCOFFStreamer.cpp revision d47f4a9c982d264e46a6a2fe0f357288768bb5b9
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 assert((Symbol->isInSection() 161 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 162 : true) && "Got non COFF section in the COFF backend!"); 163 // FIXME: This is all very ugly and depressing. What needs to happen here 164 // depends on quite a few things that are all part of relaxation, which we 165 // don't really even do. 166 167 if (Value->getKind() != MCExpr::SymbolRef) { 168 // TODO: This is exactly the same as MachOStreamer. Consider merging into 169 // MCObjectStreamer. 170 getAssembler().getOrCreateSymbolData(*Symbol); 171 AddValueSymbols(Value); 172 Symbol->setVariableValue(Value); 173 } else { 174 // FIXME: This is a horrible way to do this :(. This should really be 175 // handled after we are done with the MC* objects and immediately before 176 // writing out the object file when we know exactly what the symbol should 177 // look like in the coff symbol table. I'm not doing that now because the 178 // COFF object writer doesn't have a clearly defined separation between MC 179 // data structures, the object writers data structures, and the raw, POD, 180 // data structures that get written to disk. 181 182 // Copy over the aliased data. 183 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 184 const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData( 185 dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol()); 186 187 // FIXME: This is particularly nasty because it breaks as soon as any data 188 // members of MCSymbolData change. 189 SD.CommonAlign = RealSD.CommonAlign; 190 SD.CommonSize = RealSD.CommonSize; 191 SD.Flags = RealSD.Flags; 192 SD.Fragment = RealSD.Fragment; 193 SD.Index = RealSD.Index; 194 SD.IsExternal = RealSD.IsExternal; 195 SD.IsPrivateExtern = RealSD.IsPrivateExtern; 196 SD.Offset = RealSD.Offset; 197 SD.SymbolSize = RealSD.SymbolSize; 198 } 199} 200 201void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 202 MCSymbolAttr Attribute) { 203 assert(Symbol && "Symbol must be non-null!"); 204 assert((Symbol->isInSection() 205 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 206 : true) && "Got non COFF section in the COFF backend!"); 207 switch (Attribute) { 208 case MCSA_WeakReference: 209 getAssembler().getOrCreateSymbolData(*Symbol).modifyFlags( 210 COFF::SF_WeakReference, 211 COFF::SF_WeakReference); 212 break; 213 214 case MCSA_Global: 215 getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); 216 break; 217 218 default: 219 llvm_unreachable("unsupported attribute"); 220 break; 221 } 222} 223 224void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 225 llvm_unreachable("not implemented"); 226} 227 228void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 229 assert((Symbol->isInSection() 230 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 231 : true) && "Got non COFF section in the COFF backend!"); 232 assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " 233 "to BeginCOFFSymbolDef!"); 234 CurSymbol = Symbol; 235} 236 237void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 238 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 239 assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " 240 "the first byte!"); 241 242 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 243 StorageClass << COFF::SF_ClassShift, 244 COFF::SF_ClassMask); 245} 246 247void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { 248 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 249 assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " 250 "bytes"); 251 252 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 253 Type << COFF::SF_TypeShift, 254 COFF::SF_TypeMask); 255} 256 257void WinCOFFStreamer::EndCOFFSymbolDef() { 258 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 259 CurSymbol = NULL; 260} 261 262void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 263 llvm_unreachable("not implemented"); 264} 265 266void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 267 unsigned ByteAlignment) { 268 assert((Symbol->isInSection() 269 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 270 : true) && "Got non COFF section in the COFF backend!"); 271 AddCommonSymbol(Symbol, Size, ByteAlignment, true); 272} 273 274void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 275 assert((Symbol->isInSection() 276 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 277 : true) && "Got non COFF section in the COFF backend!"); 278 AddCommonSymbol(Symbol, Size, 1, false); 279} 280 281void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 282 unsigned Size,unsigned ByteAlignment) { 283 llvm_unreachable("not implemented"); 284} 285 286void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 287 uint64_t Size, unsigned ByteAlignment) { 288 llvm_unreachable("not implemented"); 289} 290 291void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 292 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 293 // MCObjectStreamer? 294 getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); 295} 296 297void WinCOFFStreamer::EmitValue(const MCExpr *Value, unsigned Size, 298 unsigned AddrSpace) { 299 assert(AddrSpace == 0 && "Address space must be 0!"); 300 301 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 302 // MCObjectStreamer? 303 MCDataFragment *DF = getOrCreateDataFragment(); 304 305 // Avoid fixups when possible. 306 int64_t AbsValue; 307 if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { 308 // FIXME: Endianness assumption. 309 for (unsigned i = 0; i != Size; ++i) 310 DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); 311 } else { 312 DF->addFixup(MCFixup::Create(DF->getContents().size(), 313 AddValueSymbols(Value), 314 MCFixup::getKindForSize(Size))); 315 DF->getContents().resize(DF->getContents().size() + Size, 0); 316 } 317} 318 319void WinCOFFStreamer::EmitGPRel32Value(const MCExpr *Value) { 320 llvm_unreachable("not implemented"); 321} 322 323void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment, 324 int64_t Value, 325 unsigned ValueSize, 326 unsigned MaxBytesToEmit) { 327 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 328 // MCObjectStreamer? 329 if (MaxBytesToEmit == 0) 330 MaxBytesToEmit = ByteAlignment; 331 new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, 332 getCurrentSectionData()); 333 334 // Update the maximum alignment on the current section if necessary. 335 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 336 getCurrentSectionData()->setAlignment(ByteAlignment); 337} 338 339void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment, 340 unsigned MaxBytesToEmit) { 341 // TODO: This is copied exactly from the MachOStreamer. Consider merging into 342 // MCObjectStreamer? 343 if (MaxBytesToEmit == 0) 344 MaxBytesToEmit = ByteAlignment; 345 MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, 346 getCurrentSectionData()); 347 F->setEmitNops(true); 348 349 // Update the maximum alignment on the current section if necessary. 350 if (ByteAlignment > getCurrentSectionData()->getAlignment()) 351 getCurrentSectionData()->setAlignment(ByteAlignment); 352} 353 354void WinCOFFStreamer::EmitValueToOffset(const MCExpr *Offset, 355 unsigned char Value) { 356 llvm_unreachable("not implemented"); 357} 358 359void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { 360 // Ignore for now, linkers don't care, and proper debug 361 // info will be a much large effort. 362} 363 364void WinCOFFStreamer::EmitDwarfFileDirective(unsigned FileNo, 365 StringRef Filename) { 366 llvm_unreachable("not implemented"); 367} 368 369void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) { 370 for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i) 371 if (Instruction.getOperand(i).isExpr()) 372 AddValueSymbols(Instruction.getOperand(i).getExpr()); 373 374 getCurrentSectionData()->setHasInstructions(true); 375 376 MCInstFragment *Fragment = 377 new MCInstFragment(Instruction, getCurrentSectionData()); 378 379 raw_svector_ostream VecOS(Fragment->getCode()); 380 381 getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS, 382 Fragment->getFixups()); 383} 384 385void WinCOFFStreamer::Finish() { 386 MCObjectStreamer::Finish(); 387} 388 389namespace llvm 390{ 391 MCStreamer *createWinCOFFStreamer(MCContext &Context, 392 TargetAsmBackend &TAB, 393 MCCodeEmitter &CE, 394 raw_ostream &OS, 395 bool RelaxAll) { 396 WinCOFFStreamer *S = new WinCOFFStreamer(Context, TAB, CE, OS); 397 S->getAssembler().setRelaxAll(RelaxAll); 398 return S; 399 } 400} 401