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,
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");
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();
MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*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
void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
switch (Flag) {
- case MCAF_SyntaxUnified: return; // no-op here?
+ case MCAF_SyntaxUnified: return; // no-op here.
+ case MCAF_Code16: return; // no-op here.
+ case MCAF_Code32: return; // 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?
+}
+
void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
// TODO: This is exactly the same as WinCOFFStreamer. Consider merging into
// MCObjectStreamer.
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.
-
-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);
- }
-};
+void MCELFStreamer::SwitchSection(const MCSection *Section) {
+ const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
+ if (Grp)
+ getAssembler().getOrCreateSymbolData(*Grp);
+ this->MCObjectStreamer::SwitchSection(Section);
+}
void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
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);
}
-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));
-}
-
void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
MCSymbolAttr Attribute) {
// Indirect symbols are handled differently, to match how 'as' handles
assert(0 && "Invalid symbol attribute for ELF!");
break;
+ case MCSA_ELF_TypeGnuUniqueObject:
+ // Ignore for now.
+ break;
+
case MCSA_Global:
SetBinding(SD, ELF::STB_GLOBAL);
SD.setExternal(true);
SD.setExternal(true);
}
+ SetType(SD, ELF::STT_OBJECT);
+
if (GetBinding(SD) == ELF_STB_Local) {
const MCSection *Section = getAssembler().getContext().getELFSection(".bss",
MCSectionELF::SHT_NOBITS,
}
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());
+ MCSectionData &DLS =
+ getAssembler().getOrCreateSectionData(*DwarfLineSection);
+ int PointerSize = getAssembler().getBackend().getPointerSize();
+ MCDwarfFileTable::Emit(this, DwarfLineSection, &DLS, PointerSize);
+ }
+
for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(),
e = LocalCommons.end();
i != e; ++i) {