Home | History | Annotate | Download | only in MC
      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/MC/MCWin64EH.h"
     27 #include "llvm/MC/MCAsmBackend.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/TargetRegistry.h"
     34 #include "llvm/Support/raw_ostream.h"
     35 using namespace llvm;
     36 
     37 namespace {
     38 class WinCOFFStreamer : public MCObjectStreamer {
     39 public:
     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 EmitLabel(MCSymbol *Symbol);
     54   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
     55   virtual void EmitThumbFunc(MCSymbol *Func);
     56   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
     57   virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
     58   virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
     59   virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol);
     60   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
     61   virtual void EmitCOFFSymbolType(int Type);
     62   virtual void EndCOFFSymbolDef();
     63   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
     64   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     65                                 unsigned ByteAlignment);
     66   virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     67                                      unsigned ByteAlignment);
     68   virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
     69                             unsigned Size,unsigned ByteAlignment);
     70   virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
     71                               uint64_t Size, unsigned ByteAlignment);
     72   virtual void EmitBytes(StringRef Data, 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 EmitFileDirective(StringRef Filename);
     78   virtual void EmitInstruction(const MCInst &Instruction);
     79   virtual void EmitWin64EHHandlerData();
     80   virtual void Finish();
     81 
     82 private:
     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 
    126 WinCOFFStreamer::WinCOFFStreamer(MCContext &Context,
    127                                  MCAsmBackend &MAB,
    128                                  MCCodeEmitter &CE,
    129                                  raw_ostream &OS)
    130     : MCObjectStreamer(Context, MAB, OS, &CE)
    131     , CurSymbol(NULL) {
    132 }
    133 
    134 void 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 
    171 void WinCOFFStreamer::InitSections() {
    172   SetSectionText();
    173   SetSectionData();
    174   SetSectionBSS();
    175   SetSectionText();
    176 }
    177 
    178 void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
    179   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
    180   MCObjectStreamer::EmitLabel(Symbol);
    181 }
    182 
    183 void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
    184   llvm_unreachable("not implemented");
    185 }
    186 
    187 void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
    188   llvm_unreachable("not implemented");
    189 }
    190 
    191 void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
    192   assert((Symbol->isInSection()
    193          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    194          : true) && "Got non COFF section in the COFF backend!");
    195   // FIXME: This is all very ugly and depressing. What needs to happen here
    196   // depends on quite a few things that are all part of relaxation, which we
    197   // don't really even do.
    198 
    199   if (Value->getKind() != MCExpr::SymbolRef) {
    200     // TODO: This is exactly the same as MachOStreamer. Consider merging into
    201     // MCObjectStreamer.
    202     getAssembler().getOrCreateSymbolData(*Symbol);
    203     AddValueSymbols(Value);
    204     Symbol->setVariableValue(Value);
    205   } else {
    206     // FIXME: This is a horrible way to do this :(. This should really be
    207     // handled after we are done with the MC* objects and immediately before
    208     // writing out the object file when we know exactly what the symbol should
    209     // look like in the coff symbol table. I'm not doing that now because the
    210     // COFF object writer doesn't have a clearly defined separation between MC
    211     // data structures, the object writers data structures, and the raw, POD,
    212     // data structures that get written to disk.
    213 
    214     // Copy over the aliased data.
    215     MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
    216     const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData(
    217       dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol());
    218 
    219     // FIXME: This is particularly nasty because it breaks as soon as any data
    220     // members of MCSymbolData change.
    221     SD.CommonAlign     = RealSD.CommonAlign;
    222     SD.CommonSize      = RealSD.CommonSize;
    223     SD.Flags           = RealSD.Flags;
    224     SD.Fragment        = RealSD.Fragment;
    225     SD.Index           = RealSD.Index;
    226     SD.IsExternal      = RealSD.IsExternal;
    227     SD.IsPrivateExtern = RealSD.IsPrivateExtern;
    228     SD.Offset          = RealSD.Offset;
    229     SD.SymbolSize      = RealSD.SymbolSize;
    230   }
    231 }
    232 
    233 void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
    234                                           MCSymbolAttr Attribute) {
    235   assert(Symbol && "Symbol must be non-null!");
    236   assert((Symbol->isInSection()
    237          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    238          : true) && "Got non COFF section in the COFF backend!");
    239   switch (Attribute) {
    240   case MCSA_WeakReference:
    241   case MCSA_Weak: {
    242       MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
    243       SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
    244       SD.setExternal(true);
    245     }
    246     break;
    247 
    248   case MCSA_Global:
    249     getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true);
    250     break;
    251 
    252   default:
    253     llvm_unreachable("unsupported attribute");
    254     break;
    255   }
    256 }
    257 
    258 void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
    259   llvm_unreachable("not implemented");
    260 }
    261 
    262 void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) {
    263   assert((Symbol->isInSection()
    264          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    265          : true) && "Got non COFF section in the COFF backend!");
    266   assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls "
    267                               "to BeginCOFFSymbolDef!");
    268   CurSymbol = Symbol;
    269 }
    270 
    271 void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
    272   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    273   assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in "
    274                                         "the first byte!");
    275 
    276   getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags(
    277     StorageClass << COFF::SF_ClassShift,
    278     COFF::SF_ClassMask);
    279 }
    280 
    281 void WinCOFFStreamer::EmitCOFFSymbolType(int Type) {
    282   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    283   assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 "
    284                                   "bytes");
    285 
    286   getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags(
    287     Type << COFF::SF_TypeShift,
    288     COFF::SF_TypeMask);
    289 }
    290 
    291 void WinCOFFStreamer::EndCOFFSymbolDef() {
    292   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    293   CurSymbol = NULL;
    294 }
    295 
    296 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
    297   llvm_unreachable("not implemented");
    298 }
    299 
    300 void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
    301                                        unsigned ByteAlignment) {
    302   assert((Symbol->isInSection()
    303          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    304          : true) && "Got non COFF section in the COFF backend!");
    305   AddCommonSymbol(Symbol, Size, ByteAlignment, true);
    306 }
    307 
    308 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
    309                                             unsigned ByteAlignment) {
    310   assert((Symbol->isInSection()
    311          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    312          : true) && "Got non COFF section in the COFF backend!");
    313   AddCommonSymbol(Symbol, Size, ByteAlignment, false);
    314 }
    315 
    316 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
    317                                    unsigned Size,unsigned ByteAlignment) {
    318   llvm_unreachable("not implemented");
    319 }
    320 
    321 void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
    322                                      uint64_t Size, unsigned ByteAlignment) {
    323   llvm_unreachable("not implemented");
    324 }
    325 
    326 void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
    327   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    328   // MCObjectStreamer?
    329   getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
    330 }
    331 
    332 void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
    333                                            int64_t Value,
    334                                            unsigned ValueSize,
    335                                            unsigned MaxBytesToEmit) {
    336   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    337   // MCObjectStreamer?
    338   if (MaxBytesToEmit == 0)
    339     MaxBytesToEmit = ByteAlignment;
    340   new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
    341                       getCurrentSectionData());
    342 
    343   // Update the maximum alignment on the current section if necessary.
    344   if (ByteAlignment > getCurrentSectionData()->getAlignment())
    345     getCurrentSectionData()->setAlignment(ByteAlignment);
    346 }
    347 
    348 void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment,
    349                                         unsigned MaxBytesToEmit) {
    350   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    351   // MCObjectStreamer?
    352   if (MaxBytesToEmit == 0)
    353     MaxBytesToEmit = ByteAlignment;
    354   MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit,
    355                                            getCurrentSectionData());
    356   F->setEmitNops(true);
    357 
    358   // Update the maximum alignment on the current section if necessary.
    359   if (ByteAlignment > getCurrentSectionData()->getAlignment())
    360     getCurrentSectionData()->setAlignment(ByteAlignment);
    361 }
    362 
    363 void WinCOFFStreamer::EmitFileDirective(StringRef Filename) {
    364   // Ignore for now, linkers don't care, and proper debug
    365   // info will be a much large effort.
    366 }
    367 
    368 void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) {
    369   for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i)
    370     if (Instruction.getOperand(i).isExpr())
    371       AddValueSymbols(Instruction.getOperand(i).getExpr());
    372 
    373   getCurrentSectionData()->setHasInstructions(true);
    374 
    375   MCInstFragment *Fragment =
    376     new MCInstFragment(Instruction, getCurrentSectionData());
    377 
    378   raw_svector_ostream VecOS(Fragment->getCode());
    379 
    380   getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS,
    381                                                 Fragment->getFixups());
    382 }
    383 
    384 void WinCOFFStreamer::EmitWin64EHHandlerData() {
    385   MCStreamer::EmitWin64EHHandlerData();
    386 
    387   // We have to emit the unwind info now, because this directive
    388   // actually switches to the .xdata section!
    389   MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo());
    390 }
    391 
    392 void WinCOFFStreamer::Finish() {
    393   EmitW64Tables();
    394   MCObjectStreamer::Finish();
    395 }
    396 
    397 namespace llvm
    398 {
    399   MCStreamer *createWinCOFFStreamer(MCContext &Context,
    400                                     MCAsmBackend &MAB,
    401                                     MCCodeEmitter &CE,
    402                                     raw_ostream &OS,
    403                                     bool RelaxAll) {
    404     WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS);
    405     S->getAssembler().setRelaxAll(RelaxAll);
    406     return S;
    407   }
    408 }
    409