Provide a version of getSymbolOffset that returns false on error.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 30 Apr 2014 21:51:13 +0000 (21:51 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 30 Apr 2014 21:51:13 +0000 (21:51 +0000)
This simplifies ELFObjectWriter::SymbolValue a bit more. This new version
will also be used in the COFF writer to fix pr19147.

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

include/llvm/MC/MCAsmLayout.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCAssembler.cpp

index 3058b7b48742db623837d325dd3736c17139ff12..d942e273a4c602b986033ee4de63de2142127a08 100644 (file)
@@ -102,6 +102,10 @@ public:
 
   /// \brief Get the offset of the given symbol, as computed in the current
   /// layout.
+  /// \result True on success.
+  bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const;
+
+  /// \brief Variant that reports a fatal error if the offset is not computable.
   uint64_t getSymbolOffset(const MCSymbolData *SD) const;
 
   /// @}
index 27e34da6322e8a0929e08acdeaedcd6a99eaf266..9c224b3da6a8fce499f61bc5dc74895bac61c5bf 100644 (file)
@@ -486,34 +486,16 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
     Write16(ShstrtabIndex);
 }
 
-uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
+uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
                                       const MCAsmLayout &Layout) {
-  MCSymbolData *Data = &OrigData;
-  if (Data->isCommon() && Data->isExternal())
-    return Data->getCommonAlignment();
-
-  const MCSymbol *Symbol = &Data->getSymbol();
-  MCAssembler &Asm = Layout.getAssembler();
-  bool IsThumb = Asm.isThumbFunc(Symbol);
-
-  // Given how we implement symver, we can end up with an symbol reference
-  // to an undefined symbol. Walk past it first.
-  if (Symbol->isVariable()) {
-    const MCExpr *Expr = Symbol->getVariableValue();
-    if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
-      if (Ref->getKind() == MCSymbolRefExpr::VK_None) {
-        Symbol = &Ref->getSymbol();
-        Data = &Asm.getOrCreateSymbolData(*Symbol);
-      }
-    }
-  }
+  if (Data.isCommon() && Data.isExternal())
+    return Data.getCommonAlignment();
 
-  if (!Symbol->isVariable() && !Data->getFragment())
+  uint64_t Res;
+  if (!Layout.getSymbolOffset(&Data, Res))
     return 0;
 
-  uint64_t Res = Layout.getSymbolOffset(Data);
-
-  if (IsThumb)
+  if (Layout.getAssembler().isThumbFunc(&Data.getSymbol()))
     Res |= 1;
 
   return Res;
index a96e4ba15146f4d851b46aca83845312b2edb9a8..c65e44e531306de050ef8d2aaf0ea12197403412 100644 (file)
@@ -118,37 +118,66 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
 }
 
 // Simple getSymbolOffset helper for the non-varibale case.
-static uint64_t getLabelOffset(const MCAsmLayout &Layout,
-                               const MCSymbolData &SD) {
-  if (!SD.getFragment())
-    report_fatal_error("unable to evaluate offset to undefined symbol '" +
-                       SD.getSymbol().getName() + "'");
-  return Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset();
+static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbolData &SD,
+                           bool ReportError, uint64_t &Val) {
+  if (!SD.getFragment()) {
+    if (ReportError)
+      report_fatal_error("unable to evaluate offset to undefined symbol '" +
+                         SD.getSymbol().getName() + "'");
+    return false;
+  }
+  Val = Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset();
+  return true;
 }
 
-uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
+static bool getSymbolOffsetImpl(const MCAsmLayout &Layout,
+                                const MCSymbolData *SD, bool ReportError,
+                                uint64_t &Val) {
   const MCSymbol &S = SD->getSymbol();
 
   if (!S.isVariable())
-    return getLabelOffset(*this, *SD);
+    return getLabelOffset(Layout, *SD, ReportError, Val);
 
   // If SD is a variable, evaluate it.
   MCValue Target;
-  if (!S.getVariableValue()->EvaluateAsValue(Target, this))
+  if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout))
     report_fatal_error("unable to evaluate offset for variable '" +
                        S.getName() + "'");
 
   uint64_t Offset = Target.getConstant();
 
+  const MCAssembler &Asm = Layout.getAssembler();
+
   const MCSymbolRefExpr *A = Target.getSymA();
-  if (A)
-    Offset += getLabelOffset(*this, Assembler.getSymbolData(A->getSymbol()));
+  if (A) {
+    uint64_t ValA;
+    if (!getLabelOffset(Layout, Asm.getSymbolData(A->getSymbol()), ReportError,
+                        ValA))
+      return false;
+    Offset += ValA;
+  }
 
   const MCSymbolRefExpr *B = Target.getSymB();
-  if (B)
-    Offset -= getLabelOffset(*this, Assembler.getSymbolData(B->getSymbol()));
+  if (B) {
+    uint64_t ValB;
+    if (!getLabelOffset(Layout, Asm.getSymbolData(B->getSymbol()), ReportError,
+                        ValB))
+      return false;
+    Offset -= ValB;
+  }
+
+  Val = Offset;
+  return true;
+}
 
-  return Offset;
+bool MCAsmLayout::getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const {
+  return getSymbolOffsetImpl(*this, SD, false, Val);
+}
+
+uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
+  uint64_t Val;
+  getSymbolOffsetImpl(*this, SD, true, Val);
+  return Val;
 }
 
 uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {