Fix pr19645.
The fix itself is fairly simple: move getAccessVariant to MCValue so that we
replace the old weak expression evaluation with the far more general
EvaluateAsRelocatable.
This then requires that EvaluateAsRelocatable stop when it finds a non
trivial reference kind. And that in turn requires the ELF writer to look
harder for weak references.
Last but not least, this found a case where we were being bug by bug
compatible with gas and accepting an invalid input. I reported pr19647
to track it.
llvm-svn: 207920
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index 7b69c7a..6a384c1 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -16,7 +16,6 @@
MCELF.cpp
MCELFObjectTargetWriter.cpp
MCELFStreamer.cpp
- MCFixup.cpp
MCFunction.cpp
MCExpr.cpp
MCExternalSymbolizer.cpp
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 3bce121..0a54627 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -787,6 +787,25 @@
return false;
}
+static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) {
+ const MCSymbol &Sym = Ref.getSymbol();
+
+ if (Ref.getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ return &Sym;
+
+ if (!Sym.isVariable())
+ return nullptr;
+
+ const MCExpr *Expr = Sym.getVariableValue();
+ const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
+ if (!Inner)
+ return nullptr;
+
+ if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
+ return &Inner->getSymbol();
+ return nullptr;
+}
+
void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
@@ -872,8 +891,8 @@
if (const MCSymbol *R = Renames.lookup(SymA))
SymA = R;
- if (RefA->getKind() == MCSymbolRefExpr::VK_WEAKREF)
- WeakrefUsedInReloc.insert(SymA);
+ if (const MCSymbol *WeakRef = getWeakRef(*RefA))
+ WeakrefUsedInReloc.insert(WeakRef);
else
UsedInReloc.insert(SymA);
}
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 60b14ad..ff5009f 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -658,12 +658,11 @@
case SymbolRef: {
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
- bool IsWeakRef = SRE->getKind() == MCSymbolRefExpr::VK_WEAKREF;
const MCSymbol &Sym = SRE->getSymbol();
const MCAsmInfo &MCAsmInfo = SRE->getMCAsmInfo();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable() && !IsWeakRef) {
+ if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
if (Sym.getVariableValue()->EvaluateAsRelocatableImpl(
Res, Asm, Layout, Addrs, true, ForceVarExpansion)) {
const MCSymbolRefExpr *A = Res.getSymA();
diff --git a/llvm/lib/MC/MCFixup.cpp b/llvm/lib/MC/MCFixup.cpp
deleted file mode 100644
index e41e673..0000000
--- a/llvm/lib/MC/MCFixup.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- MCFixup.cpp - Assembly Fixup Implementation ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/MC/MCFixup.h"
-using namespace llvm;
-
-static MCSymbolRefExpr::VariantKind getAccessVariant(const MCExpr *Expr) {
- switch (Expr->getKind()) {
- case MCExpr::Unary: {
- assert(getAccessVariant(cast<MCUnaryExpr>(Expr)->getSubExpr()) ==
- MCSymbolRefExpr::VK_None);
- return MCSymbolRefExpr::VK_None;
- }
-
- case MCExpr::Target:
- llvm_unreachable("unsupported");
-
- case MCExpr::Constant:
- return MCSymbolRefExpr::VK_None;
-
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(Expr);
- return SRE->getKind();
- }
- case MCExpr::Binary: {
- const MCBinaryExpr *ABE = cast<MCBinaryExpr>(Expr);
- assert(getAccessVariant(ABE->getRHS()) == MCSymbolRefExpr::VK_None);
- return getAccessVariant(ABE->getLHS());
- }
- }
- llvm_unreachable("unknown MCExpr kind");
-}
-
-MCSymbolRefExpr::VariantKind MCFixup::getAccessVariant() const {
- return ::getAccessVariant(getValue());
-}
diff --git a/llvm/lib/MC/MCValue.cpp b/llvm/lib/MC/MCValue.cpp
index 21d9e21..9dfc56e 100644
--- a/llvm/lib/MC/MCValue.cpp
+++ b/llvm/lib/MC/MCValue.cpp
@@ -10,6 +10,7 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -41,3 +42,20 @@
print(dbgs(), nullptr);
}
#endif
+
+MCSymbolRefExpr::VariantKind MCValue::getAccessVariant() const {
+ const MCSymbolRefExpr *B = getSymB();
+ if (B) {
+ if (B->getKind() != MCSymbolRefExpr::VK_None)
+ llvm_unreachable("unsupported");
+ }
+
+ const MCSymbolRefExpr *A = getSymA();
+ if (!A)
+ return MCSymbolRefExpr::VK_None;
+
+ MCSymbolRefExpr::VariantKind Kind = A->getKind();
+ if (Kind == MCSymbolRefExpr::VK_WEAKREF)
+ return MCSymbolRefExpr::VK_None;
+ return Kind;
+}