X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCELFStreamer.cpp;h=6ac9d9d51cbc77333e6b285fb579553f1793c498;hb=f323424d71a8c7c129f4fc7c9c109ca6ce2f4460;hp=0b366da44ced424adf7e00834330b2cea7539806;hpb=3507d24547ce668c9a50c72b6748c0a303e295c1;p=oota-llvm.git diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 0b366da44ce..6ac9d9d51cb 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -11,13 +11,19 @@ // //===----------------------------------------------------------------------===// -#include "MCELFStreamer.h" #include "MCELF.h" -#include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" @@ -29,6 +35,123 @@ using namespace llvm; +namespace { +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter, + MCAssembler *Assembler) + : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler) {} + + + ~MCELFStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + llvm_unreachable("ELF doesn't support this directive"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + llvm_unreachable("ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + llvm_unreachable("ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolType(int Type) { + llvm_unreachable("ELF doesn't support this directive"); + } + + virtual void EndCOFFSymbolDef() { + llvm_unreachable("ELF doesn't support this directive"); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setSize(Value); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + llvm_unreachable("ELF doesn't support this directive"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + llvm_unreachable("ELF doesn't support this directive"); + } + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + unsigned AddrSpace); + + virtual void EmitFileDirective(StringRef Filename); + + virtual void FinishImpl(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector LocalCommons; + + SmallPtrSet BindingExplicitlySet; + /// @} + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); + } + + void SetSectionData() { + SetSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + void SetSectionText() { + SetSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + void SetSectionBss() { + SetSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } +}; +} + void MCELFStreamer::InitSections() { // This emulates the same behavior of GNU as. This makes it easier // to compare the output as the major sections are in the same order. @@ -61,7 +184,7 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { return; } - assert(0 && "invalid assembler flag!"); + llvm_unreachable("invalid assembler flag!"); } void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { @@ -130,10 +253,8 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_WeakDefinition: case MCSA_WeakDefAutoPrivate: case MCSA_Invalid: - case MCSA_ELF_TypeIndFunction: case MCSA_IndirectSymbol: - assert(0 && "Invalid symbol attribute for ELF!"); - break; + llvm_unreachable("Invalid symbol attribute for ELF!"); case MCSA_ELF_TypeGnuUniqueObject: // Ignore for now. @@ -162,6 +283,10 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCELF::SetType(SD, ELF::STT_FUNC); break; + case MCSA_ELF_TypeIndFunction: + MCELF::SetType(SD, ELF::STT_GNU_IFUNC); + break; + case MCSA_ELF_TypeObject: MCELF::SetType(SD, ELF::STT_OBJECT); break; @@ -205,10 +330,10 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, if (MCELF::GetBinding(SD) == ELF_STB_Local) { const MCSection *Section = getAssembler().getContext().getELFSection(".bss", - ELF::SHT_NOBITS, - ELF::SHF_WRITE | - ELF::SHF_ALLOC, - SectionKind::getBSS()); + ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, + SectionKind::getBSS()); Symbol->setSection(*Section); struct LocalCommon L = {&SD, Size, ByteAlignment}; @@ -266,6 +391,13 @@ void MCELFStreamer::EmitCodeAlignment(unsigned ByteAlignment, getCurrentSectionData()->setAlignment(ByteAlignment); } +void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + fixSymbolsInTLSFixups(Value); + MCObjectStreamer::EmitValueImpl(Value, Size, AddrSpace); +} + + // Add a symbol for the file name of this module. This is the second // entry in the module's symbol table (the first being the null symbol). void MCELFStreamer::EmitFileDirective(StringRef Filename) { @@ -353,7 +485,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { DF->getContents().append(Code.begin(), Code.end()); } -void MCELFStreamer::Finish() { +void MCELFStreamer::FinishImpl() { EmitFrames(true); for (std::vector::const_iterator i = LocalCommons.begin(), @@ -376,7 +508,7 @@ void MCELFStreamer::Finish() { SectData.setAlignment(ByteAlignment); } - this->MCObjectStreamer::Finish(); + this->MCObjectStreamer::FinishImpl(); } MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,