Change MCExpr::EvaluateAsRelocatableImpl of variables to return the original
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 15 Nov 2010 16:33:49 +0000 (16:33 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 15 Nov 2010 16:33:49 +0000 (16:33 +0000)
variable if recursing fails to simplify it.

Factor AliasedSymbol to be a method of MCSymbol.

Update MCAssembler::EvaluateFixup to match the change in
EvaluateAsRelocatableImpl.

Remove the WeakRefExpr hack, as the object writer now sees the weakref with
no extra effort needed.

Nothing else is using MCTargetExpr, but keep it for now.

Now that the ELF writer sees relocations with aliases, handle

    .weak    foo2
foo2:
    .weak    bar2
    .set    bar2,foo2
    .quad    bar2

the same way gas does and produce a relocation with bar2.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119152 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCSymbol.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCAssembler.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCExpr.cpp
lib/MC/MCSymbol.cpp
test/MC/ELF/alias-reloc.s

index 99e705e596f130dc0537a49ea62e5841a06bcf31..7da4d7c15e3bbc8e3313985f7a6cbdb76058130c 100644 (file)
@@ -138,6 +138,11 @@ namespace llvm {
       return Value;
     }
 
+    // AliasedSymbol() - If this is an alias (a = b), return the symbol
+    // we ultimately point to. For a non alias, this just returns the symbol
+    // itself.
+    const MCSymbol &AliasedSymbol() const;
+
     void setVariableValue(const MCExpr *Value);
 
     /// @}
index e11d68e8d8d42201583475bef9a5dfbd896ce5e6..18d8e74216ba529d95d2696a5192c2b899f71c3a 100644 (file)
@@ -504,31 +504,6 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) {
   return 0;
 }
 
-static const MCSymbol &AliasedSymbol(const MCSymbol &Symbol) {
-  const MCSymbol *S = &Symbol;
-  while (S->isVariable()) {
-    const MCExpr *Value = S->getVariableValue();
-    MCExpr::ExprKind Kind = Value->getKind();
-    switch (Kind) {
-    case MCExpr::SymbolRef: {
-      const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
-      S = &Ref->getSymbol();
-      break;
-    }
-    case MCExpr::Target: {
-      const MCTargetExpr *TExp = static_cast<const MCTargetExpr*>(Value);
-      MCValue Res;
-      TExp->EvaluateAsRelocatableImpl(Res, NULL);
-      S = &Res.getSymA()->getSymbol();
-      break;
-    }
-    default:
-      return *S;
-    }
-  }
-  return *S;
-}
-
 void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
   // The presence of symbol versions causes undefined symbols and
   // versions declared with @@@ to be renamed.
@@ -536,7 +511,7 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
   for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
          ie = Asm.symbol_end(); it != ie; ++it) {
     const MCSymbol &Alias = it->getSymbol();
-    const MCSymbol &Symbol = AliasedSymbol(Alias);
+    const MCSymbol &Symbol = Alias.AliasedSymbol();
     MCSymbolData &SD = Asm.getSymbolData(Symbol);
 
     // Not an alias.
@@ -572,7 +547,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF,
                                   const MCAsmLayout &Layout) {
   MCSymbolData &OrigData = *MSD.SymbolData;
   MCSymbolData &Data =
-    Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol()));
+    Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol());
 
   bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
     Data.getSymbol().isVariable();
@@ -673,28 +648,24 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
                                                const MCValue &Target,
                                                const MCFragment &F) const {
   const MCSymbol &Symbol = Target.getSymA()->getSymbol();
-  const MCSymbol &ASymbol = AliasedSymbol(Symbol);
-  const MCSymbol *RenamedP = Renames.lookup(&Symbol);
-
-  if (!RenamedP) {
-    if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None ||
-        Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
-      RenamedP = &ASymbol;
-    else
-      RenamedP = &Symbol;
+  const MCSymbol &ASymbol = Symbol.AliasedSymbol();
+  const MCSymbol *Renamed = Renames.lookup(&Symbol);
+  const MCSymbolData &SD = Asm.getSymbolData(Symbol);
+
+  if (ASymbol.isUndefined()) {
+    if (Renamed)
+      return Renamed;
+    return &ASymbol;
   }
-  const MCSymbol &Renamed = *RenamedP;
-
-  MCSymbolData &SD = Asm.getSymbolData(Symbol);
-
-  if (Symbol.isUndefined())
-    return &Renamed;
 
-  if (SD.isExternal())
-    return &Renamed;
+  if (SD.isExternal()) {
+    if (Renamed)
+      return Renamed;
+    return &Symbol;
+  }
 
   const MCSectionELF &Section =
-    static_cast<const MCSectionELF&>(Symbol.getSection());
+    static_cast<const MCSectionELF&>(ASymbol.getSection());
 
   if (Section.getKind().isBSS())
     return NULL;
@@ -706,13 +677,18 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm,
   if (&Sec2 != &Section &&
       (Kind == MCSymbolRefExpr::VK_PLT ||
        Kind == MCSymbolRefExpr::VK_GOTPCREL ||
-       Kind == MCSymbolRefExpr::VK_GOTOFF))
-    return &Renamed;
+       Kind == MCSymbolRefExpr::VK_GOTOFF)) {
+    if (Renamed)
+      return Renamed;
+    return &Symbol;
+  }
 
   if (Section.getFlags() & MCSectionELF::SHF_MERGE) {
-    if (Target.getConstant() != 0)
-      return &Renamed;
-    return NULL;
+    if (Target.getConstant() == 0)
+      return NULL;
+    if (Renamed)
+      return Renamed;
+    return &Symbol;
   }
 
   return NULL;
@@ -742,7 +718,7 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
   if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
     return true;
 
-  const MCSymbol &A = AliasedSymbol(Symbol);
+  const MCSymbol &A = Symbol.AliasedSymbol();
   if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
     return false;
 
@@ -761,7 +737,7 @@ static bool isLocal(const MCSymbolData &Data, bool isSignature,
     return false;
 
   const MCSymbol &Symbol = Data.getSymbol();
-  const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
+  const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
 
   if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) {
     if (isSignature && !isUsedInReloc)
@@ -830,7 +806,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm,
 
     ELFSymbolData MSD;
     MSD.SymbolData = it;
-    const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
+    const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
 
     // Undefined symbols are global, but this is the first place we
     // are able to set it.
@@ -1104,13 +1080,13 @@ bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm,
   const MCSection *SectionA = 0;
   const MCSymbol *SymbolA = 0;
   if (const MCSymbolRefExpr *A = Target.getSymA()) {
-    SymbolA = &A->getSymbol();
+    SymbolA = &A->getSymbol().AliasedSymbol();
     SectionA = &SymbolA->getSection();
   }
 
   const MCSection *SectionB = 0;
   if (const MCSymbolRefExpr *B = Target.getSymB()) {
-    SectionB = &B->getSymbol().getSection();
+    SectionB = &B->getSymbol().AliasedSymbol().getSection();
   }
 
   if (!BaseSection)
@@ -1413,6 +1389,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
   int Index = 0;
   int64_t Value = Target.getConstant();
   const MCSymbol &Symbol = Target.getSymA()->getSymbol();
+  const MCSymbol &ASymbol = Symbol.AliasedSymbol();
   const MCSymbol *RelocSymbol = SymbolToReloc(Asm, Target, *Fragment);
 
   bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
@@ -1432,7 +1409,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
     }
 
     if (!RelocSymbol) {
-      MCSymbolData &SD = Asm.getSymbolData(Symbol);
+      MCSymbolData &SD = Asm.getSymbolData(ASymbol);
       MCFragment *F = SD.getFragment();
 
       Index = F->getParent()->getOrdinal();
index 8e87d5b5ee9b031b65bfaadf9470088b0ebdb074..c80dc3c2483219908c4ca6e76a3a0c775ae8a775 100644 (file)
@@ -285,14 +285,16 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
     Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
   bool IsResolved = true;
   if (const MCSymbolRefExpr *A = Target.getSymA()) {
-    if (A->getSymbol().isDefined())
-      Value += Layout.getSymbolAddress(&getSymbolData(A->getSymbol()));
+    const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
+    if (Sym.isDefined())
+      Value += Layout.getSymbolAddress(&getSymbolData(Sym));
     else
       IsResolved = false;
   }
   if (const MCSymbolRefExpr *B = Target.getSymB()) {
-    if (B->getSymbol().isDefined())
-      Value -= Layout.getSymbolAddress(&getSymbolData(B->getSymbol()));
+    const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
+    if (Sym.isDefined())
+      Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
     else
       IsResolved = false;
   }
index a2d94f5ba15e1a24d39bda1c0e03c5a83b2c8bb3..157c0c0b647eea9d0f89a2969417721bea3080c0 100644 (file)
@@ -240,49 +240,6 @@ 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)
@@ -294,16 +251,7 @@ 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);
 }
 
index b1617ecc5eca559278e20e3dd8f616c2eb977659..eea736e559f0cb27a58a59c75df25e5402f7dcb1 100644 (file)
@@ -336,9 +336,14 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     const MCSymbol &Sym = SRE->getSymbol();
 
     // Evaluate recursively if this is a variable.
-    if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None)
-      return Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
-                                                               true);
+    if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
+      bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+                                                                   true);
+      // If we failed to simplify this to a constant, let the target
+      // handle it.
+      if (Ret && !Res.getSymA() && !Res.getSymB())
+        return true;
+    }
 
     Res = MCValue::get(SRE, 0, 0);
     return true;
index ebd3144a15389e01eb0b51b2dbd365464d8d681e..1c71f267a4b5cbd711fbc6ef9602d90777a55c64 100644 (file)
@@ -39,6 +39,18 @@ static bool NameNeedsQuoting(StringRef Str) {
   return false;
 }
 
+const MCSymbol &MCSymbol::AliasedSymbol() const {
+  const MCSymbol *S = this;
+  while (S->isVariable()) {
+    const MCExpr *Value = S->getVariableValue();
+    if (Value->getKind() != MCExpr::SymbolRef)
+      return *S;
+    const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
+    S = &Ref->getSymbol();
+  }
+  return *S;
+}
+
 void MCSymbol::setVariableValue(const MCExpr *Value) {
   assert(!IsUsed && "Cannot set a variable that has already been used.");
   assert(Value && "Invalid variable value!");
index 352a2a2a042162fadf204a94400f7add6c859eb8..6ad11343aec969f8765f6de0445135f09ceefd08 100644 (file)
@@ -8,6 +8,15 @@ bar = foo
         .section zed, "", @progbits
         call bar@PLT
 
+
+// Test that this produres a relocation with bar2
+
+    .weak    foo2
+foo2:
+    .weak    bar2
+    .set    bar2,foo2
+    .quad    bar2
+
 // CHECK:       # Symbol 0x00000001
 // CHECK-NEXT:  (('st_name', 0x00000005) # 'bar'
 // CHECK-NEXT:   ('st_bind', 0x00000000)
@@ -18,9 +27,26 @@ bar = foo
 // CHECK-NEXT:   ('st_size', 0x00000000)
 // CHECK-NEXT:  ),
 
+// CHECK:      # Symbol 0x00000006
+// CHECK-NEXT: (('st_name', 0x0000000e) # 'bar2'
+// CHECK-NEXT:  ('st_bind', 0x00000002)
+// CHECK-NEXT:  ('st_type', 0x00000000)
+// CHECK-NEXT:  ('st_other', 0x00000000)
+// CHECK-NEXT:  ('st_shndx', 0x00000004)
+// CHECK-NEXT:  ('st_value', 0x00000005)
+// CHECK-NEXT:  ('st_size', 0x00000000)
+// CHECK-NEXT: ),
+
 // CHECK:       # Relocation 0x00000000
 // CHECK-NEXT:  (('r_offset', 0x00000001)
 // CHECK-NEXT:   ('r_sym', 0x00000001)
 // CHECK-NEXT:   ('r_type', 0x00000004)
 // CHECK-NEXT:   ('r_addend', 0xfffffffc)
 // CHECK-NEXT:  ),
+
+// CHECK:      # Relocation 0x00000001
+// CHECK-NEXT: (('r_offset', 0x00000005)
+// CHECK-NEXT:  ('r_sym', 0x00000006)
+// CHECK-NEXT:  ('r_type', 0x00000001)
+// CHECK-NEXT:  ('r_addend', 0x00000000)
+// CHECK-NEXT: ),