Add an assert.
[oota-llvm.git] / lib / MC / MCELFStreamer.cpp
index 2a12fa240b6080931bbe068d6bd5b10a56de9398..cac48170642d7fb3b1ab0a7bea279003c01098d2 100644 (file)
@@ -35,6 +35,38 @@ 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,
@@ -49,8 +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");
@@ -103,9 +137,6 @@ public:
                                  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();
 
@@ -165,6 +196,11 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
 
   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
@@ -178,7 +214,9 @@ void MCELFStreamer::EmitLabel(MCSymbol *Symbol) {
 
 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;
@@ -187,6 +225,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.
@@ -195,98 +237,21 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
   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(*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
@@ -325,6 +290,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);
@@ -387,6 +356,8 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     SD.setExternal(true);
   }
 
+  SetType(SD, ELF::STT_OBJECT);
+
   if (GetBinding(SD) == ELF_STB_Local) {
     const MCSection *Section = getAssembler().getContext().getELFSection(".bss",
                                                                     MCSectionELF::SHT_NOBITS,
@@ -519,7 +490,10 @@ void MCELFStreamer::Finish() {
     const MCSection *DwarfLineSection =
       getContext().getELFSection(".debug_line", 0, 0,
                                  SectionKind::getDataRelLocal());
-    MCDwarfFileTable::Emit(this, DwarfLineSection);
+    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(),