//
//===----------------------------------------------------------------------===//
+#include "MCELFStreamer.h"
+#include "MCELF.h"
#include "llvm/MC/MCStreamer.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/MC/MCAsmBackend.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmBackend.h"
using namespace llvm;
-namespace {
-
-class MCELFStreamer : public MCObjectStreamer {
- void EmitInstToFragment(const MCInst &Inst);
- void EmitInstToData(const MCInst &Inst);
-public:
- MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter) {}
-
- ~MCELFStreamer() {}
-
- /// @name MCStreamer Interface
- /// @{
-
- virtual void EmitLabel(MCSymbol *Symbol);
- virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
- virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
- 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 EmitInstruction(const MCInst &Inst);
- virtual void Finish();
-
- /// @}
-};
-
-} // 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.
+ SetSectionText();
+ SetSectionData();
+ SetSectionBss();
+ SetSectionText();
+}
void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
- // 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();
- MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
- assert(!SD.getFragment() && "Unexpected fragment on symbol data!");
- SD.setFragment(F);
- SD.setOffset(F->getContents().size());
+ MCObjectStreamer::EmitLabel(Symbol);
- Symbol->setSection(*CurSection);
+ const MCSectionELF &Section =
+ static_cast<const MCSectionELF&>(Symbol->getSection());
+ MCSymbolData &SD = getAssembler().getSymbolData(*Symbol);
+ if (Section.getFlags() & ELF::SHF_TLS)
+ MCELF::SetType(SD, ELF::STT_TLS);
}
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
+ case MCAF_SyntaxUnified: return; // no-op here.
+ case MCAF_Code16: return; // Change parsing mode; no-op here.
+ case MCAF_Code32: return; // Change parsing mode; no-op here.
+ case MCAF_Code64: return; // Change parsing mode; no-op here.
case MCAF_SubsectionsViaSymbols:
getAssembler().setSubsectionsViaSymbols(true);
return;
assert(0 && "invalid assembler flag!");
}
+void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) {
+ // FIXME: Anything needed here to flag the function as thumb?
+
+ getAssembler().setIsThumbFunc(Func);
+
+ MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
+ SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
+}
+
void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
// MCObjectStreamer.
Symbol->setVariableValue(AddValueSymbols(Value));
}
+void MCELFStreamer::ChangeSection(const MCSection *Section) {
+ const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
+ if (Grp)
+ getAssembler().getOrCreateSymbolData(*Grp);
+ this->MCObjectStreamer::ChangeSection(Section);
+}
+
+void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+ getAssembler().getOrCreateSymbolData(*Symbol);
+ MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
+ AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
+ const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext());
+ Alias->setVariableValue(Value);
+}
+
void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
case MCSA_LazyReference:
case MCSA_Reference:
case MCSA_NoDeadStrip:
+ case MCSA_SymbolResolver:
case MCSA_PrivateExtern:
- case MCSA_WeakReference:
case MCSA_WeakDefinition:
case MCSA_WeakDefAutoPrivate:
case MCSA_Invalid:
assert(0 && "Invalid symbol attribute for ELF!");
break;
+ case MCSA_ELF_TypeGnuUniqueObject:
+ // Ignore for now.
+ break;
+
case MCSA_Global:
- SD.setFlags(SD.getFlags() | ELF_STB_Global);
+ MCELF::SetBinding(SD, ELF::STB_GLOBAL);
SD.setExternal(true);
+ BindingExplicitlySet.insert(Symbol);
break;
+ case MCSA_WeakReference:
case MCSA_Weak:
- SD.setFlags(SD.getFlags() | ELF_STB_Weak);
+ MCELF::SetBinding(SD, ELF::STB_WEAK);
+ SD.setExternal(true);
+ BindingExplicitlySet.insert(Symbol);
break;
case MCSA_Local:
- SD.setFlags(SD.getFlags() | ELF_STB_Local);
+ MCELF::SetBinding(SD, ELF::STB_LOCAL);
+ SD.setExternal(false);
+ BindingExplicitlySet.insert(Symbol);
break;
case MCSA_ELF_TypeFunction:
- SD.setFlags(SD.getFlags() | ELF_STT_Func);
+ MCELF::SetType(SD, ELF::STT_FUNC);
break;
case MCSA_ELF_TypeObject:
- SD.setFlags(SD.getFlags() | ELF_STT_Object);
+ MCELF::SetType(SD, ELF::STT_OBJECT);
break;
case MCSA_ELF_TypeTLS:
- SD.setFlags(SD.getFlags() | ELF_STT_Tls);
+ MCELF::SetType(SD, ELF::STT_TLS);
break;
case MCSA_ELF_TypeCommon:
- SD.setFlags(SD.getFlags() | ELF_STT_Common);
+ MCELF::SetType(SD, ELF::STT_COMMON);
break;
case MCSA_ELF_TypeNoType:
- SD.setFlags(SD.getFlags() | ELF_STT_Notype);
+ MCELF::SetType(SD, ELF::STT_NOTYPE);
break;
case MCSA_Protected:
- SD.setFlags(SD.getFlags() | ELF_STV_Protected);
+ MCELF::SetVisibility(SD, ELF::STV_PROTECTED);
break;
case MCSA_Hidden:
- SD.setFlags(SD.getFlags() | ELF_STV_Hidden);
+ MCELF::SetVisibility(SD, ELF::STV_HIDDEN);
break;
case MCSA_Internal:
- SD.setFlags(SD.getFlags() | ELF_STV_Internal);
+ MCELF::SetVisibility(SD, ELF::STV_INTERNAL);
break;
}
}
unsigned ByteAlignment) {
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
- if ((SD.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local) {
+ if (!BindingExplicitlySet.count(Symbol)) {
+ MCELF::SetBinding(SD, ELF::STB_GLOBAL);
+ SD.setExternal(true);
+ }
+
+ MCELF::SetType(SD, ELF::STT_OBJECT);
+
+ 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());
-
- MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section);
- MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
- SD.setFragment(F);
Symbol->setSection(*Section);
- SD.setSize(MCConstantExpr::Create(Size, getContext()));
+
+ struct LocalCommon L = {&SD, Size, ByteAlignment};
+ LocalCommons.push_back(L);
} else {
- SD.setExternal(true);
+ SD.setCommon(Size, ByteAlignment);
}
- SD.setCommon(Size, ByteAlignment);
+ 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,
+ unsigned ByteAlignment) {
+ // 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);
+ EmitCommonSymbol(Symbol, Size, ByteAlignment);
}
-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,
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);
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;
+ }
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
+ switch (symRef.getKind()) {
+ default:
+ return;
+ case MCSymbolRefExpr::VK_GOTTPOFF:
+ case MCSymbolRefExpr::VK_INDNTPOFF:
+ case MCSymbolRefExpr::VK_NTPOFF:
+ case MCSymbolRefExpr::VK_GOTNTPOFF:
+ case MCSymbolRefExpr::VK_TLSGD:
+ case MCSymbolRefExpr::VK_TLSLD:
+ case MCSymbolRefExpr::VK_TLSLDM:
+ case MCSymbolRefExpr::VK_TPOFF:
+ case MCSymbolRefExpr::VK_DTPOFF:
+ case MCSymbolRefExpr::VK_ARM_TLSGD:
+ case MCSymbolRefExpr::VK_ARM_TPOFF:
+ case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
+ break;
+ }
+ MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol());
+ MCELF::SetType(SD, ELF::STT_TLS);
+ break;
+ }
- IF->getCode() = Code;
- IF->getFixups() = Fixups;
+ 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) {
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());
DF->getContents().append(Code.begin(), Code.end());
}
-void MCELFStreamer::EmitInstruction(const MCInst &Inst) {
- // Scan for values.
- for (unsigned i = 0; i != Inst.getNumOperands(); ++i)
- if (Inst.getOperand(i).isExpr())
- AddValueSymbols(Inst.getOperand(i).getExpr());
+void MCELFStreamer::Finish() {
+ EmitFrames(true);
- getCurrentSectionData()->setHasInstructions(true);
+ for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
+ e = LocalCommons.end();
+ i != e; ++i) {
+ MCSymbolData *SD = i->SD;
+ uint64_t Size = i->Size;
+ unsigned ByteAlignment = i->ByteAlignment;
+ const MCSymbol &Symbol = SD->getSymbol();
+ const MCSection &Section = Symbol.getSection();
- // If this instruction doesn't need relaxation, just emit it as data.
- if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
- EmitInstToData(Inst);
- return;
- }
+ MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section);
+ new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData);
- // Otherwise, if we are relaxing everything, relax the instruction as much as
- // possible and emit it as data.
- if (getAssembler().getRelaxAll()) {
- MCInst Relaxed;
- getAssembler().getBackend().RelaxInstruction(Inst, Relaxed);
- while (getAssembler().getBackend().MayNeedRelaxation(Relaxed))
- getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed);
- EmitInstToData(Relaxed);
- return;
- }
+ MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
+ SD->setFragment(F);
- // Otherwise emit to a separate fragment.
- EmitInstToFragment(Inst);
-}
+ // Update the maximum alignment of the section if necessary.
+ if (ByteAlignment > SectData.getAlignment())
+ SectData.setAlignment(ByteAlignment);
+ }
-void MCELFStreamer::Finish() {
- getAssembler().Finish();
+ this->MCObjectStreamer::Finish();
}
-MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
- raw_ostream &OS, MCCodeEmitter *CE,
- bool RelaxAll) {
- MCELFStreamer *S = new MCELFStreamer(Context, TAB, OS, CE);
+MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB,
+ raw_ostream &OS, MCCodeEmitter *CE,
+ bool RelaxAll, bool NoExecStack) {
+ MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE);
if (RelaxAll)
S->getAssembler().setRelaxAll(true);
+ if (NoExecStack)
+ S->getAssembler().setNoExecStack(true);
return S;
}