#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmBackend.h"
+#include "llvm/Target/TargetAsmInfo.h"
using namespace llvm;
public:
MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
raw_ostream &OS, MCCodeEmitter *Emitter)
- : MCObjectStreamer(Context, TAB, OS, Emitter, false) {}
+ : MCObjectStreamer(Context, TAB, OS, Emitter) {}
~MCELFStreamer() {}
SD.setSize(Value);
}
- virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {
- assert(0 && "ELF doesn't support this directive");
- }
+ virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
+
virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
unsigned Size = 0, unsigned ByteAlignment = 0) {
assert(0 && "ELF doesn't support this directive");
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();
virtual void EmitInstToFragment(const MCInst &Inst);
virtual void EmitInstToData(const MCInst &Inst);
+ void fixSymbolsInTLSFixups(const MCExpr *expr);
+
struct LocalCommon {
MCSymbolData *SD;
uint64_t Size;
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());
+ MCSymbolData &SD = getAssembler().getSymbolData(*Symbol);
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());
}
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
Symbol->setVariableValue(AddValueSymbols(Value));
}
-// This is a hack. To be able to implement weakrefs the writer has to be able
-// to distinguish
-// .weakref foo, bar
-// .long foo
-// from
-// .weakref foo, bar
-// .long bar
-// since the first case should produce a weak undefined reference and the second
-// one a strong one.
-// If we created foo as a regular alias pointing to bar (foo = bar), then
-// MCExpr::EvaluateAsRelocatable would recurse on foo and the writer would
-// never see it used in a relocation.
-// What we do is create a MCTargetExpr that when evaluated produces a symbol
-// ref to a temporary symbol. This temporary symbol in turn is a variable
-// that equals the original symbol (tmp = bar). With this hack the writer
-// gets a relocation with tmp and can correctly implement weak references.
-
-namespace {
-class WeakRefExpr : public MCTargetExpr {
-private:
- const MCSymbolRefExpr *Alias;
-
- explicit WeakRefExpr(const MCSymbolRefExpr *Alias_)
- : MCTargetExpr(), Alias(Alias_) {}
-
-public:
- virtual void PrintImpl(raw_ostream &OS) const {
- llvm_unreachable("Unimplemented");
- }
-
- virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
- const MCAsmLayout *Layout) const {
- Res = MCValue::get(Alias, 0, 0);
- return true;
- }
-
- static const WeakRefExpr *Create(const MCSymbol *Alias, MCContext &Ctx) {
- const MCSymbolRefExpr *A = MCSymbolRefExpr::Create(Alias, Ctx);
- return new (Ctx) WeakRefExpr(A);
- }
-};
-} // end anonymous namespace
-
void MCELFStreamer::SwitchSection(const MCSection *Section) {
const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
if (Grp)
getAssembler().getOrCreateSymbolData(*Symbol);
MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
-
- // Create the alias that actually points to Symbol
- const MCSymbolRefExpr *SymRef = MCSymbolRefExpr::Create(Symbol, getContext());
- MCSymbol *RealAlias = getContext().CreateTempSymbol();
- RealAlias->setVariableValue(SymRef);
-
- MCSymbolData &RealAliasSD = getAssembler().getOrCreateSymbolData(*RealAlias);
- RealAliasSD.setFlags(RealAliasSD.getFlags() | ELF_Other_Weakref);
-
- const MCExpr *Value = WeakRefExpr::Create(RealAlias, getContext());
+ const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext());
Alias->setVariableValue(Value);
}
case MCSA_LazyReference:
case MCSA_Reference:
case MCSA_NoDeadStrip:
+ case MCSA_SymbolResolver:
case MCSA_PrivateExtern:
case MCSA_WeakDefinition:
case MCSA_WeakDefAutoPrivate:
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);
+ 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,
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) {
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_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());
+ 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());
}
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 (!FrameInfos.empty())
+ MCDwarfFrameEmitter::Emit(*this);
for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
e = LocalCommons.end();