WinCOFFStreamer.cpp revision 0933134a304b47d3767aad202df9f0e09743da6d
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/MCStreamer.h" 17#include "llvm/MC/MCAsmBackend.h" 18#include "llvm/MC/MCAsmLayout.h" 19#include "llvm/MC/MCAssembler.h" 20#include "llvm/MC/MCCodeEmitter.h" 21#include "llvm/MC/MCContext.h" 22#include "llvm/MC/MCExpr.h" 23#include "llvm/MC/MCObjectStreamer.h" 24#include "llvm/MC/MCSection.h" 25#include "llvm/MC/MCSectionCOFF.h" 26#include "llvm/MC/MCSymbol.h" 27#include "llvm/MC/MCValue.h" 28#include "llvm/MC/MCWin64EH.h" 29#include "llvm/Support/COFF.h" 30#include "llvm/Support/Debug.h" 31#include "llvm/Support/ErrorHandling.h" 32#include "llvm/Support/TargetRegistry.h" 33#include "llvm/Support/raw_ostream.h" 34 35using namespace llvm; 36 37namespace { 38class WinCOFFStreamer : public MCObjectStreamer { 39public: 40 MCSymbol const *CurSymbol; 41 42 WinCOFFStreamer(MCContext &Context, 43 MCAsmBackend &MAB, 44 MCCodeEmitter &CE, 45 raw_ostream &OS); 46 47 void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 48 unsigned ByteAlignment, bool External); 49 50 // MCStreamer interface 51 52 virtual void InitSections(); 53 virtual void InitToTextSection(); 54 virtual void EmitLabel(MCSymbol *Symbol); 55 virtual void EmitDebugLabel(MCSymbol *Symbol); 56 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 57 virtual void EmitThumbFunc(MCSymbol *Func); 58 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 59 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 60 virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); 61 virtual void EmitCOFFSymbolStorageClass(int StorageClass); 62 virtual void EmitCOFFSymbolType(int Type); 63 virtual void EndCOFFSymbolDef(); 64 virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); 65 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 66 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 67 unsigned ByteAlignment); 68 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 69 unsigned ByteAlignment); 70 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 71 uint64_t Size,unsigned ByteAlignment); 72 virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 73 uint64_t Size, unsigned ByteAlignment); 74 virtual void EmitFileDirective(StringRef Filename); 75 virtual void EmitWin64EHHandlerData(); 76 virtual void FinishImpl(); 77 78private: 79 virtual void EmitInstToData(const MCInst &Inst) { 80 MCDataFragment *DF = getOrCreateDataFragment(); 81 82 SmallVector<MCFixup, 4> Fixups; 83 SmallString<256> Code; 84 raw_svector_ostream VecOS(Code); 85 getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); 86 VecOS.flush(); 87 88 // Add the fixups and data. 89 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 90 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 91 DF->getFixups().push_back(Fixups[i]); 92 } 93 DF->getContents().append(Code.begin(), Code.end()); 94 } 95 96 void SetSection(StringRef Section, 97 unsigned Characteristics, 98 SectionKind Kind) { 99 SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind)); 100 } 101 102 void SetSectionText() { 103 SetSection(".text", 104 COFF::IMAGE_SCN_CNT_CODE 105 | COFF::IMAGE_SCN_MEM_EXECUTE 106 | COFF::IMAGE_SCN_MEM_READ, 107 SectionKind::getText()); 108 EmitCodeAlignment(4, 0); 109 } 110 111 void SetSectionData() { 112 SetSection(".data", 113 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 114 | COFF::IMAGE_SCN_MEM_READ 115 | COFF::IMAGE_SCN_MEM_WRITE, 116 SectionKind::getDataRel()); 117 EmitCodeAlignment(4, 0); 118 } 119 120 void SetSectionBSS() { 121 SetSection(".bss", 122 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 123 | COFF::IMAGE_SCN_MEM_READ 124 | COFF::IMAGE_SCN_MEM_WRITE, 125 SectionKind::getBSS()); 126 EmitCodeAlignment(4, 0); 127 } 128}; 129} // end anonymous namespace. 130 131WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, 132 MCAsmBackend &MAB, 133 MCCodeEmitter &CE, 134 raw_ostream &OS) 135 : MCObjectStreamer(Context, MAB, OS, &CE) 136 , CurSymbol(NULL) { 137} 138 139void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 140 unsigned ByteAlignment, bool External) { 141 assert(!Symbol->isInSection() && "Symbol must not already have a section!"); 142 143 std::string SectionName(".bss$linkonce"); 144 SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); 145 146 MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); 147 148 unsigned Characteristics = 149 COFF::IMAGE_SCN_LNK_COMDAT | 150 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 151 COFF::IMAGE_SCN_MEM_READ | 152 COFF::IMAGE_SCN_MEM_WRITE; 153 154 int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; 155 156 const MCSection *Section = MCStreamer::getContext().getCOFFSection( 157 SectionName, Characteristics, Selection, SectionKind::getBSS()); 158 159 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); 160 161 if (SectionData.getAlignment() < ByteAlignment) 162 SectionData.setAlignment(ByteAlignment); 163 164 SymbolData.setExternal(External); 165 166 Symbol->setSection(*Section); 167 168 if (ByteAlignment != 1) 169 new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); 170 171 SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); 172} 173 174// MCStreamer interface 175 176void WinCOFFStreamer::InitToTextSection() { 177 SetSectionText(); 178} 179 180void WinCOFFStreamer::InitSections() { 181 SetSectionText(); 182 SetSectionData(); 183 SetSectionBSS(); 184 SetSectionText(); 185} 186 187void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { 188 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 189 MCObjectStreamer::EmitLabel(Symbol); 190} 191 192void WinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) { 193 EmitLabel(Symbol); 194} 195void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 196 llvm_unreachable("not implemented"); 197} 198 199void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { 200 llvm_unreachable("not implemented"); 201} 202 203void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 204 MCSymbolAttr Attribute) { 205 assert(Symbol && "Symbol must be non-null!"); 206 assert((Symbol->isInSection() 207 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 208 : true) && "Got non COFF section in the COFF backend!"); 209 switch (Attribute) { 210 case MCSA_WeakReference: 211 case MCSA_Weak: { 212 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 213 SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); 214 SD.setExternal(true); 215 } 216 break; 217 218 case MCSA_Global: 219 getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); 220 break; 221 222 default: 223 llvm_unreachable("unsupported attribute"); 224 } 225} 226 227void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 228 llvm_unreachable("not implemented"); 229} 230 231void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 232 assert((Symbol->isInSection() 233 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 234 : true) && "Got non COFF section in the COFF backend!"); 235 assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " 236 "to BeginCOFFSymbolDef!"); 237 CurSymbol = Symbol; 238} 239 240void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 241 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 242 assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " 243 "the first byte!"); 244 245 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 246 StorageClass << COFF::SF_ClassShift, 247 COFF::SF_ClassMask); 248} 249 250void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { 251 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 252 assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " 253 "bytes"); 254 255 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 256 Type << COFF::SF_TypeShift, 257 COFF::SF_TypeMask); 258} 259 260void WinCOFFStreamer::EndCOFFSymbolDef() { 261 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 262 CurSymbol = NULL; 263} 264 265void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) 266{ 267 MCDataFragment *DF = getOrCreateDataFragment(); 268 269 DF->getFixups().push_back( 270 MCFixup::Create(DF->getContents().size(), 271 MCSymbolRefExpr::Create (Symbol, getContext ()), 272 FK_SecRel_4)); 273 DF->getContents().resize(DF->getContents().size() + 4, 0); 274} 275 276void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 277 llvm_unreachable("not implemented"); 278} 279 280void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 281 unsigned ByteAlignment) { 282 assert((Symbol->isInSection() 283 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 284 : true) && "Got non COFF section in the COFF backend!"); 285 AddCommonSymbol(Symbol, Size, ByteAlignment, true); 286} 287 288void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 289 unsigned ByteAlignment) { 290 assert((Symbol->isInSection() 291 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 292 : true) && "Got non COFF section in the COFF backend!"); 293 AddCommonSymbol(Symbol, Size, ByteAlignment, false); 294} 295 296void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 297 uint64_t Size,unsigned ByteAlignment) { 298 llvm_unreachable("not implemented"); 299} 300 301void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 302 uint64_t Size, unsigned ByteAlignment) { 303 llvm_unreachable("not implemented"); 304} 305 306void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { 307 // Ignore for now, linkers don't care, and proper debug 308 // info will be a much large effort. 309} 310 311void WinCOFFStreamer::EmitWin64EHHandlerData() { 312 MCStreamer::EmitWin64EHHandlerData(); 313 314 // We have to emit the unwind info now, because this directive 315 // actually switches to the .xdata section! 316 MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo()); 317} 318 319void WinCOFFStreamer::FinishImpl() { 320 EmitW64Tables(); 321 MCObjectStreamer::FinishImpl(); 322} 323 324namespace llvm 325{ 326 MCStreamer *createWinCOFFStreamer(MCContext &Context, 327 MCAsmBackend &MAB, 328 MCCodeEmitter &CE, 329 raw_ostream &OS, 330 bool RelaxAll) { 331 WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS); 332 S->getAssembler().setRelaxAll(RelaxAll); 333 return S; 334 } 335} 336