Thumb's forced-PC-alignment requirement applies to the _total_ displacement, not...
[oota-llvm.git] / lib / MC / MCExpr.cpp
index f7ed35374e4a6456e0c5804998c683c93dd2f1e6..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;
 
@@ -267,7 +247,8 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
     return true;
   }
 
-  if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) ||
+  // FIXME: This use of Addrs is wrong, right?
+  if (!EvaluateAsRelocatableImpl(Value, Layout, Addrs, /*InSet=*/Addrs) ||
       !Value.isAbsolute()) {
     // EvaluateAsAbsolute is defined to return the "current value" of
     // the expression if we are given a Layout object, even in cases
@@ -290,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:
@@ -304,8 +304,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
 ///
 /// \returns True on success, false if the result is not representable in an
 /// MCValue.
-static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
-                                const MCAsmLayout *Layout,
+static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
                                 const SectionAddrMap *Addrs,
                                 bool InSet,
                                 const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
@@ -320,34 +319,48 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
   // 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.
-
-  assert((!Layout || Asm) &&
-         "Must have an assembler object if layout is given!");
-
-  if (Asm && A && B) {
+  if (Layout && A && B) {
+    const MCAssembler &Asm = Layout->getAssembler();
     const MCSymbol &SA = A->getSymbol();
     const MCSymbol &SB = B->getSymbol();
-    const MCObjectFormat &F = Asm->getBackend().getObjectFormat();
+    const MCObjectFormat &F = Asm.getBackend().getObjectFormat();
     if (SA.isDefined() && SB.isDefined() && F.isAbsolute(InSet, SA, SB)) {
-      MCSymbolData &AD = Asm->getSymbolData(A->getSymbol());
-      MCSymbolData &BD = Asm->getSymbolData(B->getSymbol());
+      MCSymbolData &AD = Asm.getSymbolData(A->getSymbol());
+      MCSymbolData &BD = Asm.getSymbolData(B->getSymbol());
 
       if (AD.getFragment() == BD.getFragment()) {
         Res = MCValue::get(+ AD.getOffset()
@@ -378,17 +391,7 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
   return true;
 }
 
-bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
-                                   const MCAsmLayout *Layout) const {
-  if (Layout)
-    return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout,
-                                     0, false);
-  else
-    return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false);
-}
-
 bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
-                                       const MCAssembler *Asm,
                                        const MCAsmLayout *Layout,
                                        const SectionAddrMap *Addrs,
                                        bool InSet) const {
@@ -408,10 +411,8 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
 
     // Evaluate recursively if this is a variable.
     if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
-      bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
-                                                                   Layout,
-                                                                   Addrs,
-                                                                   true);
+      bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+                                                                   Addrs, true);
       // If we failed to simplify this to a constant, let the target
       // handle it.
       if (Ret && !Res.getSymA() && !Res.getSymB())
@@ -426,7 +427,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
     MCValue Value;
 
-    if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
+    if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Layout,
                                                       Addrs, InSet))
       return false;
 
@@ -460,9 +461,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
     MCValue LHSValue, RHSValue;
 
-    if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
+    if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Layout,
                                                   Addrs, InSet) ||
-        !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
+        !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Layout,
                                                   Addrs, InSet))
       return false;
 
@@ -474,13 +475,13 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
         return false;
       case MCBinaryExpr::Sub:
         // Negate RHS and add.
-        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymB(), RHSValue.getSymA(),
                                    -RHSValue.getConstant(),
                                    Res);
 
       case MCBinaryExpr::Add:
-        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymA(), RHSValue.getSymB(),
                                    RHSValue.getConstant(),
                                    Res);