Write => in a more normal form.
[oota-llvm.git] / lib / MC / MCExpr.cpp
index cee5673bc072a707e93141b7cd0f09dfac7530b3..f7ed35374e4a6456e0c5804998c683c93dd2f1e6 100644 (file)
@@ -238,23 +238,27 @@ void MCTargetExpr::Anchor() {}
 /* *** */
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const {
-  return EvaluateAsAbsolute(Res, 0, 0);
+  return EvaluateAsAbsolute(Res, 0, 0, 0);
 }
 
 bool MCExpr::EvaluateAsAbsolute(int64_t &Res,
-                                const MCAsmLayout *Layout) const {
-  if (Layout)
-    return EvaluateAsAbsolute(Res, &Layout->getAssembler(), Layout);
-  else
-    return EvaluateAsAbsolute(Res, 0, 0);
+                                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);
+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) const {
+                                const MCAsmLayout *Layout,
+                                const SectionAddrMap *Addrs) const {
   MCValue Value;
 
   // Fast path constants.
@@ -263,7 +267,7 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
     return true;
   }
 
-  if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, false) ||
+  if (!EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, Addrs) ||
       !Value.isAbsolute()) {
     // EvaluateAsAbsolute is defined to return the "current value" of
     // the expression if we are given a Layout object, even in cases
@@ -271,11 +275,11 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
     if (Layout) {
       Res = Value.getConstant();
       if (Value.getSymA()) {
-       Res += Layout->getSymbolAddress(
+       Res += Layout->getSymbolOffset(
           &Layout->getAssembler().getSymbolData(Value.getSymA()->getSymbol()));
       }
       if (Value.getSymB()) {
-       Res -= Layout->getSymbolAddress(
+       Res -= Layout->getSymbolOffset(
           &Layout->getAssembler().getSymbolData(Value.getSymB()->getSymbol()));
       }
     }
@@ -286,19 +290,42 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,
   return true;
 }
 
-static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
-                                const MCAssembler *Asm,
+/// \brief Evaluate the result of an add between (conceptually) two MCValues.
+///
+/// This routine conceptually attempts to construct an MCValue:
+///   Result = (Result_A - Result_B + Result_Cst)
+/// from two MCValue's LHS and RHS where
+///   Result = LHS + RHS
+/// and
+///   Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).
+///
+/// This routine attempts to aggresively fold the operands such that the result
+/// is representable in an MCValue, but may not always succeed.
+///
+/// \returns True on success, false if the result is not representable in an
+/// MCValue.
+static bool EvaluateSymbolicAdd(const MCAssembler *Asm,
+                                const MCAsmLayout *Layout,
+                                const SectionAddrMap *Addrs,
                                 bool InSet,
                                 const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
                                 const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
                                 MCValue &Res) {
-  // We can't add or subtract two symbols.
-  if ((LHS.getSymA() && RHS_A) ||
-      (LHS.getSymB() && RHS_B))
+  // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy
+  // about dealing with modifiers. This will ultimately bite us, one day.
+  const MCSymbolRefExpr *LHS_A = LHS.getSymA();
+  const MCSymbolRefExpr *LHS_B = LHS.getSymB();
+  int64_t LHS_Cst = LHS.getConstant();
+
+  // Fold the result constant immediately.
+  int64_t Result_Cst = LHS_Cst + RHS_Cst;
+
+  // We can't represent the addition or subtraction of two symbols.
+  if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
     return false;
 
-  const MCSymbolRefExpr *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
-  const MCSymbolRefExpr *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
+  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
@@ -311,7 +338,8 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
   // Absolutize symbol differences between defined symbols when we have a
   // layout object and the target requests it.
 
-  assert(!(Layout && !Asm));
+  assert((!Layout || Asm) &&
+         "Must have an assembler object if layout is given!");
 
   if (Asm && A && B) {
     const MCSymbol &SA = A->getSymbol();
@@ -324,22 +352,29 @@ static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout,
       if (AD.getFragment() == BD.getFragment()) {
         Res = MCValue::get(+ AD.getOffset()
                            - BD.getOffset()
-                           + LHS.getConstant()
-                           + RHS_Cst);
+                           + Result_Cst);
         return true;
       }
 
       if (Layout) {
-        Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
-                           - Layout->getSymbolAddress(&BD)
-                           + LHS.getConstant()
-                           + RHS_Cst);
+        const MCSectionData &SecA = *AD.getFragment()->getParent();
+        const MCSectionData &SecB = *BD.getFragment()->getParent();
+        int64_t Val = + Layout->getSymbolOffset(&AD)
+                      - Layout->getSymbolOffset(&BD)
+                      + Result_Cst;
+        if (&SecA != &SecB) {
+          if (!Addrs)
+            return false;
+          Val += Addrs->lookup(&SecA);
+          Val -= Addrs->lookup(&SecB);
+        }
+        Res = MCValue::get(Val);
         return true;
       }
     }
   }
 
-  Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
+  Res = MCValue::get(A, B, Result_Cst);
   return true;
 }
 
@@ -347,14 +382,15 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
                                    const MCAsmLayout *Layout) const {
   if (Layout)
     return EvaluateAsRelocatableImpl(Res, &Layout->getAssembler(), Layout,
-                                     false);
+                                     0, false);
   else
-    return EvaluateAsRelocatableImpl(Res, 0, 0, false);
+    return EvaluateAsRelocatableImpl(Res, 0, 0, 0, false);
 }
 
 bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
                                        const MCAssembler *Asm,
                                        const MCAsmLayout *Layout,
+                                       const SectionAddrMap *Addrs,
                                        bool InSet) const {
   ++stats::MCExprEvaluate;
 
@@ -374,6 +410,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
       bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm,
                                                                    Layout,
+                                                                   Addrs,
                                                                    true);
       // If we failed to simplify this to a constant, let the target
       // handle it.
@@ -390,7 +427,7 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     MCValue Value;
 
     if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout,
-                                                      InSet))
+                                                      Addrs, InSet))
       return false;
 
     switch (AUE->getOpcode()) {
@@ -424,9 +461,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     MCValue LHSValue, RHSValue;
 
     if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout,
-                                                  InSet) ||
+                                                  Addrs, InSet) ||
         !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout,
-                                                  InSet))
+                                                  Addrs, InSet))
       return false;
 
     // We only support a few operations on non-constant expressions, handle
@@ -437,13 +474,13 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
         return false;
       case MCBinaryExpr::Sub:
         // Negate RHS and add.
-        return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymB(), RHSValue.getSymA(),
                                    -RHSValue.getConstant(),
                                    Res);
 
       case MCBinaryExpr::Add:
-        return EvaluateSymbolicAdd(Layout, Asm, InSet, LHSValue,
+        return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue,
                                    RHSValue.getSymA(), RHSValue.getSymB(),
                                    RHSValue.getConstant(),
                                    Res);