LLVM API Documentation
00001 //===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains an implementation of a Windows COFF object file streamer. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/ADT/StringExtras.h" 00015 #include "llvm/MC/MCStreamer.h" 00016 #include "llvm/MC/MCAsmBackend.h" 00017 #include "llvm/MC/MCAsmLayout.h" 00018 #include "llvm/MC/MCAssembler.h" 00019 #include "llvm/MC/MCCodeEmitter.h" 00020 #include "llvm/MC/MCContext.h" 00021 #include "llvm/MC/MCExpr.h" 00022 #include "llvm/MC/MCObjectFileInfo.h" 00023 #include "llvm/MC/MCObjectStreamer.h" 00024 #include "llvm/MC/MCSection.h" 00025 #include "llvm/MC/MCSectionCOFF.h" 00026 #include "llvm/MC/MCSymbol.h" 00027 #include "llvm/MC/MCValue.h" 00028 #include "llvm/MC/MCWinCOFFStreamer.h" 00029 #include "llvm/Support/COFF.h" 00030 #include "llvm/Support/Debug.h" 00031 #include "llvm/Support/ErrorHandling.h" 00032 #include "llvm/Support/TargetRegistry.h" 00033 #include "llvm/Support/raw_ostream.h" 00034 00035 using namespace llvm; 00036 00037 #define DEBUG_TYPE "WinCOFFStreamer" 00038 00039 namespace llvm { 00040 MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, 00041 MCCodeEmitter &CE, raw_ostream &OS) 00042 : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {} 00043 00044 void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, 00045 const MCSubtargetInfo &STI) { 00046 MCDataFragment *DF = getOrCreateDataFragment(); 00047 00048 SmallVector<MCFixup, 4> Fixups; 00049 SmallString<256> Code; 00050 raw_svector_ostream VecOS(Code); 00051 getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI); 00052 VecOS.flush(); 00053 00054 // Add the fixups and data. 00055 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 00056 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 00057 DF->getFixups().push_back(Fixups[i]); 00058 } 00059 00060 DF->getContents().append(Code.begin(), Code.end()); 00061 } 00062 00063 void MCWinCOFFStreamer::InitSections() { 00064 // FIXME: this is identical to the ELF one. 00065 // This emulates the same behavior of GNU as. This makes it easier 00066 // to compare the output as the major sections are in the same order. 00067 SwitchSection(getContext().getObjectFileInfo()->getTextSection()); 00068 EmitCodeAlignment(4); 00069 00070 SwitchSection(getContext().getObjectFileInfo()->getDataSection()); 00071 EmitCodeAlignment(4); 00072 00073 SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); 00074 EmitCodeAlignment(4); 00075 00076 SwitchSection(getContext().getObjectFileInfo()->getTextSection()); 00077 } 00078 00079 void MCWinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { 00080 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 00081 MCObjectStreamer::EmitLabel(Symbol); 00082 } 00083 00084 void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 00085 llvm_unreachable("not implemented"); 00086 } 00087 00088 void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { 00089 llvm_unreachable("not implemented"); 00090 } 00091 00092 bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 00093 MCSymbolAttr Attribute) { 00094 assert(Symbol && "Symbol must be non-null!"); 00095 assert((!Symbol->isInSection() || 00096 Symbol->getSection().getVariant() == MCSection::SV_COFF) && 00097 "Got non-COFF section in the COFF backend!"); 00098 00099 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 00100 00101 switch (Attribute) { 00102 default: return false; 00103 case MCSA_WeakReference: 00104 case MCSA_Weak: 00105 SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); 00106 SD.setExternal(true); 00107 break; 00108 case MCSA_Global: 00109 SD.setExternal(true); 00110 break; 00111 } 00112 00113 return true; 00114 } 00115 00116 void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 00117 llvm_unreachable("not implemented"); 00118 } 00119 00120 void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 00121 assert((!Symbol->isInSection() || 00122 Symbol->getSection().getVariant() == MCSection::SV_COFF) && 00123 "Got non-COFF section in the COFF backend!"); 00124 00125 if (CurSymbol) 00126 FatalError("starting a new symbol definition without completing the " 00127 "previous one"); 00128 CurSymbol = Symbol; 00129 } 00130 00131 void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 00132 if (!CurSymbol) 00133 FatalError("storage class specified outside of symbol definition"); 00134 00135 if (StorageClass & ~0xff) 00136 FatalError(Twine("storage class value '") + itostr(StorageClass) + 00137 "' out of range"); 00138 00139 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol); 00140 SD.modifyFlags(StorageClass << COFF::SF_ClassShift, COFF::SF_ClassMask); 00141 } 00142 00143 void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { 00144 if (!CurSymbol) 00145 FatalError("symbol type specified outside of a symbol definition"); 00146 00147 if (Type & ~0xffff) 00148 FatalError(Twine("type value '") + itostr(Type) + "' out of range"); 00149 00150 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*CurSymbol); 00151 SD.modifyFlags(Type << COFF::SF_TypeShift, COFF::SF_TypeMask); 00152 } 00153 00154 void MCWinCOFFStreamer::EndCOFFSymbolDef() { 00155 if (!CurSymbol) 00156 FatalError("ending symbol definition without starting one"); 00157 CurSymbol = nullptr; 00158 } 00159 00160 void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { 00161 MCDataFragment *DF = getOrCreateDataFragment(); 00162 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext()); 00163 MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_2); 00164 DF->getFixups().push_back(Fixup); 00165 DF->getContents().resize(DF->getContents().size() + 4, 0); 00166 } 00167 00168 void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { 00169 MCDataFragment *DF = getOrCreateDataFragment(); 00170 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext()); 00171 MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_4); 00172 DF->getFixups().push_back(Fixup); 00173 DF->getContents().resize(DF->getContents().size() + 4, 0); 00174 } 00175 00176 void MCWinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 00177 llvm_unreachable("not supported"); 00178 } 00179 00180 void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 00181 unsigned ByteAlignment) { 00182 assert((!Symbol->isInSection() || 00183 Symbol->getSection().getVariant() == MCSection::SV_COFF) && 00184 "Got non-COFF section in the COFF backend!"); 00185 00186 if (ByteAlignment > 32) 00187 report_fatal_error("alignment is limited to 32-bytes"); 00188 00189 AssignSection(Symbol, nullptr); 00190 00191 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 00192 SD.setExternal(true); 00193 SD.setCommon(Size, ByteAlignment); 00194 } 00195 00196 void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 00197 unsigned ByteAlignment) { 00198 assert(!Symbol->isInSection() && "Symbol must not already have a section!"); 00199 00200 const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); 00201 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); 00202 if (SectionData.getAlignment() < ByteAlignment) 00203 SectionData.setAlignment(ByteAlignment); 00204 00205 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 00206 SD.setExternal(false); 00207 00208 AssignSection(Symbol, Section); 00209 00210 if (ByteAlignment != 1) 00211 new MCAlignFragment(ByteAlignment, /*_Value=*/0, /*_ValueSize=*/0, 00212 ByteAlignment, &SectionData); 00213 00214 MCFillFragment *Fragment = 00215 new MCFillFragment(/*_Value=*/0, /*_ValueSize=*/0, Size, &SectionData); 00216 SD.setFragment(Fragment); 00217 } 00218 00219 void MCWinCOFFStreamer::EmitZerofill(const MCSection *Section, 00220 MCSymbol *Symbol, uint64_t Size, 00221 unsigned ByteAlignment) { 00222 llvm_unreachable("not implemented"); 00223 } 00224 00225 void MCWinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, 00226 MCSymbol *Symbol, uint64_t Size, 00227 unsigned ByteAlignment) { 00228 llvm_unreachable("not implemented"); 00229 } 00230 00231 void MCWinCOFFStreamer::EmitFileDirective(StringRef Filename) { 00232 getAssembler().addFileName(Filename); 00233 } 00234 00235 // TODO: Implement this if you want to emit .comment section in COFF obj files. 00236 void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { 00237 llvm_unreachable("not implemented"); 00238 } 00239 00240 void MCWinCOFFStreamer::EmitWinEHHandlerData() { 00241 llvm_unreachable("not implemented"); 00242 } 00243 00244 void MCWinCOFFStreamer::FinishImpl() { 00245 MCObjectStreamer::FinishImpl(); 00246 } 00247 00248 LLVM_ATTRIBUTE_NORETURN 00249 void MCWinCOFFStreamer::FatalError(const Twine &Msg) const { 00250 getContext().FatalError(SMLoc(), Msg); 00251 } 00252 } 00253