Handle a peculiar comdat case: Creating a section with an undefined
[oota-llvm.git] / lib / MC / MCELFStreamer.cpp
index 6bf61a194c60ef4345d87dbdf38495a7e28f4b8a..1f4f1461a571479c938f0e3f18cbbe69398ad91b 100644 (file)
@@ -24,6 +24,7 @@
 #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"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -34,9 +35,39 @@ 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 {
-  void EmitInstToFragment(const MCInst &Inst);
-  void EmitInstToData(const MCInst &Inst);
 public:
   MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB,
                   raw_ostream &OS, MCCodeEmitter *Emitter)
@@ -50,7 +81,10 @@ public:
   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");
@@ -107,10 +141,19 @@ public:
     DEBUG(dbgs() << "FIXME: MCELFStreamer:EmitDwarfFileDirective not implemented\n");
   }
 
-  virtual void EmitInstruction(const MCInst &Inst);
   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,
@@ -149,22 +192,6 @@ void MCELFStreamer::InitSections() {
   SetSectionText();
 }
 
-static bool isSymbolLinkerVisible(const MCAssembler &Asm,
-                                  const MCSymbolData &Data) {
-  const MCSymbol &Symbol = Data.getSymbol();
-  // Absolute temporary labels are never visible.
-  if (!Symbol.isInSection())
-    return false;
-
-  if (Asm.getBackend().doesSectionRequireSymbols(Symbol.getSection()))
-    return true;
-
-  if (!Data.isExternal())
-    return false;
-
-  return Asm.isSymbolLinkerVisible(Symbol);
-}
-
 void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
 
@@ -172,10 +199,10 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
 
   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
 
-  // We have to create a new fragment if this is an atom defining symbol,
-  // fragments cannot span atoms.
-  if (isSymbolLinkerVisible(getAssembler(), SD))
-    new MCDataFragment(getCurrentSectionData());
+  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
@@ -190,6 +217,9 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
 
 void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
   switch (Flag) {
+  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;
@@ -198,6 +228,10 @@ void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
   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.
@@ -206,36 +240,71 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
   Symbol->setVariableValue(AddValueSymbols(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));
-}
+// 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.
 
-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;
-}
+namespace {
+class WeakRefExpr : public MCTargetExpr {
+private:
+  const MCSymbolRefExpr *Alias;
 
-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);
+  explicit WeakRefExpr(const MCSymbolRefExpr *Alias_)
+    : MCTargetExpr(), Alias(Alias_) {}
 
-  uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift);
-  SD.setFlags(OtherFlags | (Type << ELF_STT_Shift));
+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(*Grp);
+  this->MCObjectStreamer::SwitchSection(Section);
 }
 
-static void SetVisibility(MCSymbolData &SD, unsigned Visibility) {
-  assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL ||
-         Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED);
+void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
+  getAssembler().getOrCreateSymbolData(*Symbol);
+  MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
+  AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
 
-  uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift);
-  SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift));
+  // 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());
+  Alias->setVariableValue(Value);
 }
 
 void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
@@ -276,6 +345,10 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
     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);
@@ -285,6 +358,7 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
   case MCSA_WeakReference:
   case MCSA_Weak:
     SetBinding(SD, ELF::STB_WEAK);
+    SD.setExternal(true);
     BindingExplicitlySet.insert(Symbol);
     break;
 
@@ -343,17 +417,10 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                                                     MCSectionELF::SHF_WRITE |
                                                                     MCSectionELF::SHF_ALLOC,
                                                                     SectionKind::getBSS());
-
-    MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section);
-    new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData);
-
-    MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
-    SD.setFragment(F);
     Symbol->setSection(*Section);
 
-    // Update the maximum alignment of the section if necessary.
-    if (ByteAlignment > SectData.getAlignment())
-      SectData.setAlignment(ByteAlignment);
+    struct LocalCommon L = {&SD, Size, ByteAlignment};
+    LocalCommons.push_back(L);
   } else {
     SD.setCommon(Size, ByteAlignment);
   }
@@ -469,64 +536,34 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
   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());
-
-  getCurrentSectionData()->setHasInstructions(true);
-
-  // If this instruction doesn't need relaxation, just emit it as data.
-  if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) {
-    EmitInstToData(Inst);
-    return;
+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);
   }
 
-  // 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;
-  }
+  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();
 
-  // Otherwise emit to a separate fragment.
-  EmitInstToFragment(Inst);
-}
+    MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section);
+    new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData);
 
-void MCELFStreamer::Finish() {
-  // FIXME: We create more atoms than it is necessary. Some relocations to
-  // merge sections can be implemented with section address + offset,
-  // figure out which ones and why.
-
-  // First, scan the symbol table to build a lookup table from fragments to
-  // defining symbols.
-  DenseMap<const MCFragment*, MCSymbolData*> DefiningSymbolMap;
-  for (MCAssembler::symbol_iterator it = getAssembler().symbol_begin(),
-         ie = getAssembler().symbol_end(); it != ie; ++it) {
-    if (isSymbolLinkerVisible(getAssembler(), *it) &&
-        it->getFragment()) {
-      // An atom defining symbol should never be internal to a fragment.
-      assert(it->getOffset() == 0 && "Invalid offset in atom defining symbol!");
-      DefiningSymbolMap[it->getFragment()] = it;
-    }
-  }
+    MCFragment *F = new MCFillFragment(0, 0, Size, &SectData);
+    SD->setFragment(F);
 
-  // Set the fragment atom associations by tracking the last seen atom defining
-  // symbol.
-  for (MCAssembler::iterator it = getAssembler().begin(),
-         ie = getAssembler().end(); it != ie; ++it) {
-    MCSymbolData *CurrentAtom = 0;
-    for (MCSectionData::iterator it2 = it->begin(),
-           ie2 = it->end(); it2 != ie2; ++it2) {
-      if (MCSymbolData *SD = DefiningSymbolMap.lookup(it2))
-        CurrentAtom = SD;
-      it2->setAtom(CurrentAtom);
-    }
+    // Update the maximum alignment of the section if necessary.
+    if (ByteAlignment > SectData.getAlignment())
+      SectData.setAlignment(ByteAlignment);
   }
 
   this->MCObjectStreamer::Finish();