diff options
author | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
---|---|---|
committer | Jush Lu <jush.msn@gmail.com> | 2011-03-09 19:39:16 +0800 |
commit | b5530586d68bd25831a6796b5d3199cb0769a35c (patch) | |
tree | fac4a03b53b6a64b0c00f433e4d8b3c9f2bc67cd /lib/MC/MCELFStreamer.cpp | |
parent | b4e17c5bf4361bbdeced39aa071150d7fa9c3c10 (diff) | |
parent | d01f50f42ce60207ed6d27fb1778e456d83be06c (diff) | |
download | external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.zip external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.gz external_llvm-b5530586d68bd25831a6796b5d3199cb0769a35c.tar.bz2 |
Merge upstream r127116
Diffstat (limited to 'lib/MC/MCELFStreamer.cpp')
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 331 |
1 files changed, 91 insertions, 240 deletions
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 157c0c0..464c136 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -11,18 +11,14 @@ // //===----------------------------------------------------------------------===// +#include "MCELFStreamer.h" +#include "MCELF.h" #include "llvm/MC/MCStreamer.h" - -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCContext.h" #include "llvm/MC/MCCodeEmitter.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/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" @@ -30,159 +26,10 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" using namespace llvm; -namespace { - -static void SetBinding(MCSymbolData &SD, unsigned Binding) { - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); - SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); -} - -static unsigned GetBinding(const MCSymbolData &SD) { - uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; - assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || - Binding == ELF::STB_WEAK); - return Binding; -} - -static void SetType(MCSymbolData &SD, unsigned Type) { - assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || - Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || - Type == ELF::STT_FILE || Type == ELF::STT_COMMON || - Type == ELF::STT_TLS); - - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); - SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); -} - -static void SetVisibility(MCSymbolData &SD, unsigned Visibility) { - assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || - Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); - - uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift); - SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); -} - -class MCELFStreamer : public MCObjectStreamer { -public: - MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter, false) {} - - ~MCELFStreamer() {} - - /// @name MCStreamer Interface - /// @{ - - virtual void InitSections(); - 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 SwitchSection(const MCSection *Section); - virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EmitCOFFSymbolStorageClass(int StorageClass) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EmitCOFFSymbolType(int Type) { - assert(0 && "ELF doesn't support this directive"); - } - - virtual void EndCOFFSymbolDef() { - assert(0 && "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) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - unsigned Size = 0, unsigned ByteAlignment = 0) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) { - assert(0 && "ELF doesn't support this directive"); - } - virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); - virtual void EmitGPRel32Value(const MCExpr *Value) { - assert(0 && "ELF doesn't support this directive"); - } - 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 EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0); - - virtual void EmitFileDirective(StringRef Filename); - virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename) { - DEBUG(dbgs() << "FIXME: MCELFStreamer:EmitDwarfFileDirective not implemented\n"); - } - - virtual void Finish(); - -private: - virtual void EmitInstToFragment(const MCInst &Inst); - virtual void EmitInstToData(const MCInst &Inst); - - struct LocalCommon { - MCSymbolData *SD; - uint64_t Size; - unsigned ByteAlignment; - }; - std::vector<LocalCommon> LocalCommons; - - SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; - /// @} - void SetSection(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind) { - SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); - } - - void SetSectionData() { - SetSection(".data", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, - SectionKind::getDataRel()); - EmitCodeAlignment(4, 0); - } - void SetSectionText() { - SetSection(".text", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_EXECINSTR | - MCSectionELF::SHF_ALLOC, SectionKind::getText()); - EmitCodeAlignment(4, 0); - } - void SetSectionBss() { - SetSection(".bss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE | - MCSectionELF::SHF_ALLOC, SectionKind::getBSS()); - EmitCodeAlignment(4, 0); - } -}; - -} // end anonymous namespace. - 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. @@ -195,24 +42,13 @@ void MCELFStreamer::InitSections() { void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); - Symbol->setSection(*CurSection); - - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + MCObjectStreamer::EmitLabel(Symbol); const MCSectionELF &Section = static_cast<const MCSectionELF&>(Symbol->getSection()); - if (Section.getFlags() & MCSectionELF::SHF_TLS) - SetType(SD, ELF::STT_TLS); - - // FIXME: This is wasteful, we don't necessarily need to create a data - // fragment. Instead, we should mark the symbol as pointing into the data - // fragment if it exists, otherwise we should just queue the label and set its - // fragment pointer when we emit the next fragment. - MCDataFragment *F = getOrCreateDataFragment(); - - assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); - SD.setFragment(F); - SD.setOffset(F->getContents().size()); + MCSymbolData &SD = getAssembler().getSymbolData(*Symbol); + if (Section.getFlags() & ELF::SHF_TLS) + MCELF::SetType(SD, ELF::STT_TLS); } void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { @@ -240,11 +76,11 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { Symbol->setVariableValue(AddValueSymbols(Value)); } -void MCELFStreamer::SwitchSection(const MCSection *Section) { +void MCELFStreamer::ChangeSection(const MCSection *Section) { const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup(); if (Grp) getAssembler().getOrCreateSymbolData(*Grp); - this->MCObjectStreamer::SwitchSection(Section); + this->MCObjectStreamer::ChangeSection(Section); } void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -284,6 +120,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_LazyReference: case MCSA_Reference: case MCSA_NoDeadStrip: + case MCSA_SymbolResolver: case MCSA_PrivateExtern: case MCSA_WeakDefinition: case MCSA_WeakDefAutoPrivate: @@ -298,54 +135,54 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, break; case MCSA_Global: - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); SD.setExternal(true); BindingExplicitlySet.insert(Symbol); break; case MCSA_WeakReference: case MCSA_Weak: - SetBinding(SD, ELF::STB_WEAK); + MCELF::SetBinding(SD, ELF::STB_WEAK); SD.setExternal(true); BindingExplicitlySet.insert(Symbol); break; case MCSA_Local: - SetBinding(SD, ELF::STB_LOCAL); + MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); BindingExplicitlySet.insert(Symbol); break; case MCSA_ELF_TypeFunction: - SetType(SD, ELF::STT_FUNC); + MCELF::SetType(SD, ELF::STT_FUNC); break; case MCSA_ELF_TypeObject: - SetType(SD, ELF::STT_OBJECT); + MCELF::SetType(SD, ELF::STT_OBJECT); break; case MCSA_ELF_TypeTLS: - SetType(SD, ELF::STT_TLS); + MCELF::SetType(SD, ELF::STT_TLS); break; case MCSA_ELF_TypeCommon: - SetType(SD, ELF::STT_COMMON); + MCELF::SetType(SD, ELF::STT_COMMON); break; case MCSA_ELF_TypeNoType: - SetType(SD, ELF::STT_NOTYPE); + MCELF::SetType(SD, ELF::STT_NOTYPE); break; case MCSA_Protected: - SetVisibility(SD, ELF::STV_PROTECTED); + MCELF::SetVisibility(SD, ELF::STV_PROTECTED); break; case MCSA_Hidden: - SetVisibility(SD, ELF::STV_HIDDEN); + MCELF::SetVisibility(SD, ELF::STV_HIDDEN); break; case MCSA_Internal: - SetVisibility(SD, ELF::STV_INTERNAL); + MCELF::SetVisibility(SD, ELF::STV_INTERNAL); break; } } @@ -355,17 +192,17 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); if (!BindingExplicitlySet.count(Symbol)) { - SetBinding(SD, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); SD.setExternal(true); } - SetType(SD, ELF::STT_OBJECT); + MCELF::SetType(SD, ELF::STT_OBJECT); - if (GetBinding(SD) == ELF_STB_Local) { + if (MCELF::GetBinding(SD) == ELF_STB_Local) { const MCSection *Section = getAssembler().getContext().getELFSection(".bss", - MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE | - MCSectionELF::SHF_ALLOC, + ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); Symbol->setSection(*Section); @@ -378,29 +215,20 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, SD.setSize(MCConstantExpr::Create(Size, getContext())); } -void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { - // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into - // MCObjectStreamer. - getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); +void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + // FIXME: Should this be caught and done earlier? + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + MCELF::SetBinding(SD, ELF::STB_LOCAL); + SD.setExternal(false); + BindingExplicitlySet.insert(Symbol); + // FIXME: ByteAlignment is not needed here, but is required. + EmitCommonSymbol(Symbol, Size, 1); } -void MCELFStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) { +void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into // MCObjectStreamer. - MCDataFragment *DF = getOrCreateDataFragment(); - - // Avoid fixups when possible. - int64_t AbsValue; - if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { - // FIXME: Endianness assumption. - for (unsigned i = 0; i != Size; ++i) - DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); - } else { - DF->addFixup(MCFixup::Create(DF->getContents().size(), AddValueSymbols(Value), - MCFixup::getKindForSize(Size))); - DF->getContents().resize(DF->getContents().size() + Size, 0); - } + getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); } void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, @@ -433,18 +261,11 @@ void MCELFStreamer::EmitCodeAlignment(unsigned ByteAlignment, getCurrentSectionData()->setAlignment(ByteAlignment); } -void MCELFStreamer::EmitValueToOffset(const MCExpr *Offset, - unsigned char Value) { - // TODO: This is exactly the same as MCMachOStreamer. Consider merging into - // MCObjectStreamer. - new MCOrgFragment(*Offset, Value, getCurrentSectionData()); -} - // 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) { MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename); - Symbol->setSection(*CurSection); + Symbol->setSection(*getCurrentSection()); Symbol->setAbsolute(); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); @@ -452,21 +273,52 @@ void MCELFStreamer::EmitFileDirective(StringRef Filename) { SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default); } -void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) { - MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData()); +void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { + switch (expr->getKind()) { + case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); + case MCExpr::Constant: + break; - // Add the fixups and data. - // - // FIXME: Revisit this design decision when relaxation is done, we may be - // able to get away with not storing any extra data in the MCInst. - SmallVector<MCFixup, 4> Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); - VecOS.flush(); + case MCExpr::Binary: { + const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); + fixSymbolsInTLSFixups(be->getLHS()); + fixSymbolsInTLSFixups(be->getRHS()); + break; + } - IF->getCode() = Code; - IF->getFixups() = Fixups; + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); + switch (symRef.getKind()) { + default: + return; + case MCSymbolRefExpr::VK_NTPOFF: + case MCSymbolRefExpr::VK_GOTNTPOFF: + case MCSymbolRefExpr::VK_TLSGD: + case MCSymbolRefExpr::VK_TLSLDM: + case MCSymbolRefExpr::VK_TPOFF: + case MCSymbolRefExpr::VK_DTPOFF: + case MCSymbolRefExpr::VK_GOTTPOFF: + case MCSymbolRefExpr::VK_TLSLD: + case MCSymbolRefExpr::VK_ARM_TLSGD: + break; + } + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol()); + MCELF::SetType(SD, ELF::STT_TLS); + break; + } + + case MCExpr::Unary: + fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); + break; + } +} + +void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) { + this->MCObjectStreamer::EmitInstToFragment(Inst); + MCInstFragment &F = *cast<MCInstFragment>(getCurrentFragment()); + + for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) + fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); } void MCELFStreamer::EmitInstToData(const MCInst &Inst) { @@ -478,6 +330,9 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); VecOS.flush(); + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) + fixSymbolsInTLSFixups(Fixups[i].getValue()); + // Add the fixups and data. for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); @@ -487,14 +342,8 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) { } void MCELFStreamer::Finish() { - // FIXME: duplicated code with the MachO streamer. - // Dump out the dwarf file & directory tables and line tables. - if (getContext().hasDwarfFiles()) { - const MCSection *DwarfLineSection = - getContext().getELFSection(".debug_line", 0, 0, - SectionKind::getDataRelLocal()); - MCDwarfFileTable::Emit(this, DwarfLineSection); - } + if (getNumFrameInfos()) + MCDwarfFrameEmitter::Emit(*this); for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(), e = LocalCommons.end(); @@ -520,10 +369,12 @@ void MCELFStreamer::Finish() { } MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll) { + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack) { MCELFStreamer *S = new MCELFStreamer(Context, TAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); + if (NoExecStack) + S->getAssembler().setNoExecStack(true); return S; } |