Thumb's forced-PC-alignment requirement applies to the _total_ displacement, not...
[oota-llvm.git] / lib / MC / MCExpr.cpp
index eb556937b6120e936c058a11cc04e099cef3cc4c..41feaa837573b129049fb0c4d435751156978904 100644 (file)
@@ -237,27 +237,7 @@ void MCTargetExpr::Anchor() {}
 
 /* *** */
 
-bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
-  return EvaluateAsAbsolute(Res, 0, 0, 0);
-}
-
-bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
-                                const MCAsmLayout &Layout) const {
-  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0);
-}
-
-bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
-                                const MCAsmLayout &Layout,
-                                const SectionAddrMap &Addrs) const {
-  return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs);
-}
-
-bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
-  return EvaluateAsAbsolute(Res, &Asm, 0, 0);
-}
-
-bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
-                                const MCAsmLayout *Layout,
+bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout,
                                 const SectionAddrMap *Addrs) const {
   MCValue Value;
 
@@ -291,6 +271,25 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
   return true;
 }
 
+/// \brief Helper method for \see EvaluateSymbolAdd().
+static void AttemptToFoldSymbolOffsetDifference(const MCAsmLayout *Layout,
+                                                const MCSymbolRefExpr *&A,
+                                                const MCSymbolRefExpr *&B,
+                                                int64_t &Addend) {
+  const MCAssembler &Asm = Layout->getAssembler();
+
+  if (A && B &&
+      Asm.getWriter().IsSymbolRefDifferenceFullyResolved(Asm, A, B)) {
+    // Eagerly evaluate.
+    Addend += (Layout->getSymbolOffset(&Asm.getSymbolData(A->getSymbol())) -
+               Layout->getSymbolOffset(&Asm.getSymbolData(B->getSymbol())));
+
+    // Clear the symbol expr pointers to indicate we have folded these
+    // operands.
+    A = B = 0;
+  }
+}
+
 /// \brief Evaluate the result of an add between (conceptually) two MCValues.
 ///
 /// This routine conceptually attempts to construct an MCValue:
@@ -320,20 +319,37 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
   // Fold the result constant immediately.
   int64_t Result_Cst = LHS_Cst + RHS_Cst;
 
+  // If we have a layout, we can fold resolved differences.
+  if (Layout) {
+    // First, fold out any differences which are fully resolved. By
+    // reassociating terms in
+    //   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
+    // we have the four possible differences:
+    //   (LHS_A - LHS_B),
+    //   (LHS_A - RHS_B),
+    //   (RHS_A - LHS_B),
+    //   (RHS_A - RHS_B).
+    // Since we are attempting to be as aggresive as possible about folding, we
+    // attempt to evaluate each possible alternative.
+    AttemptToFoldSymbolOffsetDifference(Layout, LHS_A, LHS_B, Result_Cst);
+    AttemptToFoldSymbolOffsetDifference(Layout, LHS_A, RHS_B, Result_Cst);
+    AttemptToFoldSymbolOffsetDifference(Layout, RHS_A, LHS_B, Result_Cst);
+    AttemptToFoldSymbolOffsetDifference(Layout, RHS_A, RHS_B, Result_Cst);
+  }
+
   // We can't represent the addition or subtraction of two symbols.
   if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
     return false;
 
+  // At this point, we have at most one additive symbol and one subtractive
+  // symbol -- find them.
   const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;
   const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;
-  if (B) {
-    // If we have a negated symbol, then we must have also have a non-negated
-    // symbol in order to encode the expression. We can do this check later to
-    // permit expressions which eventually fold to a representable form -- such
-    // as (a + (0 - b)) -- if necessary.
-    if (!A)
-      return false;
-  }
+
+  // If we have a negated symbol, then we must have also have a non-negated
+  // symbol in order to encode the expression.
+  if (B && !A)
+    return false;
 
   // Absolutize symbol differences between defined symbols when we have a
   // layout object and the target requests it.
@@ -375,14 +391,6 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
   return true;
 }
 
-bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
-                                   const MCAsmLayout *Layout) const {
-  if (Layout)
-    return EvaluateAsRelocatableImpl(Res, Layout, 0, false);
-  else
-    return EvaluateAsRelocatableImpl(Res, 0, 0, false);
-}
-
 bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
                                        const MCAsmLayout *Layout,
                                        const SectionAddrMap *Addrs,