[llvm-commits] [llvm] r74496 - in /llvm/trunk: include/llvm/MC/MCSymbol.h include/llvm/MC/MCValue.h tools/llvm-mc/AsmExpr.cpp tools/llvm-mc/AsmExpr.h tools/llvm-mc/AsmParser.cpp tools/llvm-mc/AsmParser.h

Daniel Dunbar daniel at zuster.org
Mon Jun 29 18:49:52 PDT 2009


Author: ddunbar
Date: Mon Jun 29 20:49:52 2009
New Revision: 74496

URL: http://llvm.org/viewvc/llvm-project?rev=74496&view=rev
Log:
llvm-mc: Evaluation for relocatable expressions.

Modified:
    llvm/trunk/include/llvm/MC/MCSymbol.h
    llvm/trunk/include/llvm/MC/MCValue.h
    llvm/trunk/tools/llvm-mc/AsmExpr.cpp
    llvm/trunk/tools/llvm-mc/AsmExpr.h
    llvm/trunk/tools/llvm-mc/AsmParser.cpp
    llvm/trunk/tools/llvm-mc/AsmParser.h

Modified: llvm/trunk/include/llvm/MC/MCSymbol.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCSymbol.h?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/include/llvm/MC/MCSymbol.h (original)
+++ llvm/trunk/include/llvm/MC/MCSymbol.h Mon Jun 29 20:49:52 2009
@@ -13,6 +13,8 @@
 #include <string>
 
 namespace llvm {
+  class MCSection;
+
   class MCSymbol {
     MCSection *Section;
     std::string Name;

Modified: llvm/trunk/include/llvm/MC/MCValue.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCValue.h?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/include/llvm/MC/MCValue.h (original)
+++ llvm/trunk/include/llvm/MC/MCValue.h Mon Jun 29 20:49:52 2009
@@ -15,6 +15,8 @@
 #define LLVM_MC_MCVALUE_H
 
 #include "llvm/Support/DataTypes.h"
+#include "llvm/MC/MCSymbol.h"
+#include <cassert>
 
 namespace llvm {
 class MCSymbol;
@@ -23,6 +25,9 @@
 /// form, this can hold "SymbolA - SymbolB + imm64".  Not all targets supports
 /// relocations of this general form, but we need to represent this anyway.
 ///
+/// In the general form, SymbolB can only be defined if SymbolA is, and both
+/// must be in the same (non-external) section.
+///
 /// Note that this class must remain a simple POD value class, because we need
 /// it to live in unions etc.
 class MCValue {
@@ -35,9 +40,21 @@
   MCSymbol *getSymB() const { return SymB; }
 
   bool isConstant() const { return !SymA && !SymB; }
-  
+
+  /// getAssociatedSection - For relocatable values, return the section the
+  /// value is associated with.
+  ///
+  /// @result - The value's associated section, or null for external or constant
+  /// values.
+  MCSection *getAssociatedSection() const {
+    return SymA ? SymA->getSection() : 0;
+  }
+
   static MCValue get(MCSymbol *SymA, MCSymbol *SymB = 0, int64_t Val = 0) {
     MCValue R;
+    assert((!SymB || (SymA && SymA->getSection() && 
+                      SymA->getSection() == SymB->getSection())) &&
+           "Invalid relocatable MCValue!");
     R.Cst = Val;
     R.SymA = SymA;
     R.SymB = SymB;

Modified: llvm/trunk/tools/llvm-mc/AsmExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmExpr.cpp?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmExpr.cpp (original)
+++ llvm/trunk/tools/llvm-mc/AsmExpr.cpp Mon Jun 29 20:49:52 2009
@@ -9,6 +9,7 @@
 
 #include "AsmExpr.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
 using namespace llvm;
 
@@ -16,38 +17,61 @@
 }
 
 bool AsmExpr::EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const {
+  MCValue Value;
+  
+  if (!EvaluateAsRelocatable(Ctx, Value) || !Value.isConstant())
+    return false;
+
+  Res = Value.getConstant();
+  return true;
+}
+
+bool AsmExpr::EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const {
   switch (getKind()) {
   default:
     assert(0 && "Invalid assembly expression kind!");
 
   case Constant:
-    Res = cast<AsmConstantExpr>(this)->getValue();
+    Res = MCValue::get(cast<AsmConstantExpr>(this)->getValue());
     return true;
 
   case SymbolRef: {
     MCSymbol *Sym = cast<AsmSymbolRefExpr>(this)->getSymbol();
-    const MCValue *Value = Ctx.GetSymbolValue(Sym);
-
-    // FIXME: Return more information about the failure.
-    if (!Value || !Value->isConstant())
-      return false;
-
-    Res = Value->getConstant();
+    if (const MCValue *Value = Ctx.GetSymbolValue(Sym))
+      Res = *Value;
+    else
+      Res = MCValue::get(Sym, 0, 0);
     return true;
   }
 
   case Unary: {
     const AsmUnaryExpr *AUE = cast<AsmUnaryExpr>(this);
-    int64_t Value;
+    MCValue Value;
 
-    if (!AUE->getSubExpr()->EvaluateAsAbsolute(Ctx, Value))
+    if (!AUE->getSubExpr()->EvaluateAsRelocatable(Ctx, Value))
       return false;
 
     switch (AUE->getOpcode()) {
-    case AsmUnaryExpr::LNot:  Res = !Value; break;
-    case AsmUnaryExpr::Minus: Res = -Value; break;
-    case AsmUnaryExpr::Not:   Res = ~Value; break;
-    case AsmUnaryExpr::Plus:  Res = +Value; break;
+    case AsmUnaryExpr::LNot:
+      if (!Value.isConstant())
+        return false;
+      Res = MCValue::get(!Value.getConstant());
+      break;
+    case AsmUnaryExpr::Minus:
+      /// -(a - b + const) ==> (b - a - const)
+      if (Value.getSymA() && !Value.getSymA())
+        return false;
+      Res = MCValue::get(Value.getSymB(), Value.getSymA(), 
+                         -Value.getConstant()); 
+      break;
+    case AsmUnaryExpr::Not:
+      if (!Value.isConstant())
+        return false;
+      Res = MCValue::get(~Value.getConstant()); 
+      break;
+    case AsmUnaryExpr::Plus:
+      Res = Value;
+      break;
     }
 
     return true;
@@ -55,36 +79,75 @@
 
   case Binary: {
     const AsmBinaryExpr *ABE = cast<AsmBinaryExpr>(this);
-    int64_t LHS, RHS;
+    MCValue LHSValue, RHSValue;
     
-    if (!ABE->getLHS()->EvaluateAsAbsolute(Ctx, LHS) ||
-        !ABE->getRHS()->EvaluateAsAbsolute(Ctx, RHS))
+    if (!ABE->getLHS()->EvaluateAsRelocatable(Ctx, LHSValue) ||
+        !ABE->getRHS()->EvaluateAsRelocatable(Ctx, RHSValue))
       return false;
 
+    // We only support a few operations on non-constant expressions, handle
+    // those first.
+    if (!LHSValue.isConstant() || !RHSValue.isConstant()) {
+      switch (ABE->getOpcode()) {
+      default:
+        return false;
+      case AsmBinaryExpr::Sub:
+        // Negate RHS and fall through.
+        RHSValue = MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(), 
+                                -RHSValue.getConstant());
+      case AsmBinaryExpr::Add:
+        // (a_0 - b_0 + cst_0) + (a_1 - b_1 + cst_1)
+
+        // We can't add or subtract two symbols.
+        if ((LHSValue.getSymA() && RHSValue.getSymB()) ||
+            (LHSValue.getSymB() && RHSValue.getSymB()))
+          return false;
+
+        MCSymbol *A = 
+          LHSValue.getSymA() ? LHSValue.getSymA() : RHSValue.getSymA();
+        MCSymbol *B = 
+          LHSValue.getSymB() ? LHSValue.getSymB() : RHSValue.getSymB();
+        if (B) {
+          // If we have a negated symbol, then we must have also have a
+          // non-negated symbol, and both symbols must be in the same
+          // non-external section. 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 || !A->getSection() || A->getSection() != B->getSection())
+            return false;
+        }
+        Res = MCValue::get(A, B, 
+                           LHSValue.getConstant() + RHSValue.getConstant());
+        return true;
+      }
+    }
+
     // FIXME: We need target hooks for the evaluation. It may be limited in
     // width, and gas defines the result of comparisons differently from Apple
     // as (the result is sign extended).
+    int64_t Result, LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();
     switch (ABE->getOpcode()) {
-    case AsmBinaryExpr::Add:  Res = LHS + RHS; break;
-    case AsmBinaryExpr::And:  Res = LHS & RHS; break;
-    case AsmBinaryExpr::Div:  Res = LHS / RHS; break;
-    case AsmBinaryExpr::EQ:   Res = LHS == RHS; break;
-    case AsmBinaryExpr::GT:   Res = LHS > RHS; break;
-    case AsmBinaryExpr::GTE:  Res = LHS >= RHS; break;
-    case AsmBinaryExpr::LAnd: Res = LHS && RHS; break;
-    case AsmBinaryExpr::LOr:  Res = LHS || RHS; break;
-    case AsmBinaryExpr::LT:   Res = LHS < RHS; break;
-    case AsmBinaryExpr::LTE:  Res = LHS <= RHS; break;
-    case AsmBinaryExpr::Mod:  Res = LHS % RHS; break;
-    case AsmBinaryExpr::Mul:  Res = LHS * RHS; break;
-    case AsmBinaryExpr::NE:   Res = LHS != RHS; break;
-    case AsmBinaryExpr::Or:   Res = LHS | RHS; break;
-    case AsmBinaryExpr::Shl:  Res = LHS << RHS; break;
-    case AsmBinaryExpr::Shr:  Res = LHS >> RHS; break;
-    case AsmBinaryExpr::Sub:  Res = LHS - RHS; break;
-    case AsmBinaryExpr::Xor:  Res = LHS ^ RHS; break;
+    case AsmBinaryExpr::Add:  Result = LHS + RHS; break;
+    case AsmBinaryExpr::And:  Result = LHS & RHS; break;
+    case AsmBinaryExpr::Div:  Result = LHS / RHS; break;
+    case AsmBinaryExpr::EQ:   Result = LHS == RHS; break;
+    case AsmBinaryExpr::GT:   Result = LHS > RHS; break;
+    case AsmBinaryExpr::GTE:  Result = LHS >= RHS; break;
+    case AsmBinaryExpr::LAnd: Result = LHS && RHS; break;
+    case AsmBinaryExpr::LOr:  Result = LHS || RHS; break;
+    case AsmBinaryExpr::LT:   Result = LHS < RHS; break;
+    case AsmBinaryExpr::LTE:  Result = LHS <= RHS; break;
+    case AsmBinaryExpr::Mod:  Result = LHS % RHS; break;
+    case AsmBinaryExpr::Mul:  Result = LHS * RHS; break;
+    case AsmBinaryExpr::NE:   Result = LHS != RHS; break;
+    case AsmBinaryExpr::Or:   Result = LHS | RHS; break;
+    case AsmBinaryExpr::Shl:  Result = LHS << RHS; break;
+    case AsmBinaryExpr::Shr:  Result = LHS >> RHS; break;
+    case AsmBinaryExpr::Sub:  Result = LHS - RHS; break;
+    case AsmBinaryExpr::Xor:  Result = LHS ^ RHS; break;
     }
 
+    Res = MCValue::get(Result);
     return true;
   }
   }

Modified: llvm/trunk/tools/llvm-mc/AsmExpr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmExpr.h?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmExpr.h (original)
+++ llvm/trunk/tools/llvm-mc/AsmExpr.h Mon Jun 29 20:49:52 2009
@@ -16,6 +16,7 @@
 namespace llvm {
 class MCContext;
 class MCSymbol;
+class MCValue;
 
 class AsmExpr {
 public:
@@ -39,10 +40,17 @@
 
   /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value.
   ///
-  /// @param Res - The absolute value if evaluation succeeds.
+  /// @param Res - The absolute value, if evaluation succeeds.
   /// @result - True on success.
   bool EvaluateAsAbsolute(MCContext &Ctx, int64_t &Res) const;
 
+  /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable
+  /// value.
+  ///
+  /// @param Res - The relocatable value, if evaluation succeeds.
+  /// @result - True on success.
+  bool EvaluateAsRelocatable(MCContext &Ctx, MCValue &Res) const;
+
   static bool classof(const AsmExpr *) { return true; }
 };
 

Modified: llvm/trunk/tools/llvm-mc/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmParser.cpp?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmParser.cpp (original)
+++ llvm/trunk/tools/llvm-mc/AsmParser.cpp Mon Jun 29 20:49:52 2009
@@ -153,6 +153,18 @@
   return false;
 }
 
+bool AsmParser::ParseRelocatableExpression(MCValue &Res) {
+  AsmExpr *Expr;
+  
+  if (ParseExpression(Expr))
+    return true;
+
+  if (!Expr->EvaluateAsRelocatable(Ctx, Res))
+    return TokError("expected relocatable expression");
+
+  return false;
+}
+
 static unsigned getBinOpPrecedence(asmtok::TokKind K, 
                                    AsmBinaryExpr::Opcode &Kind) {
   switch (K) {

Modified: llvm/trunk/tools/llvm-mc/AsmParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmParser.h?rev=74496&r1=74495&r2=74496&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmParser.h (original)
+++ llvm/trunk/tools/llvm-mc/AsmParser.h Mon Jun 29 20:49:52 2009
@@ -22,7 +22,8 @@
 class MCContext;
 class MCInst;
 class MCStreamer;
-  
+class MCValue;
+
 class AsmParser {
   AsmLexer Lexer;
   MCContext &Ctx;
@@ -53,15 +54,23 @@
   /// @param Res - The resulting expression. The pointer value is null on error.
   /// @result - False on success.
   bool ParseExpression(AsmExpr *&Res);
-  
-  /// ParseAbsoluteExpr - Parse an expression which must evaluate to an absolute
-  /// value.
+
+  /// ParseAbsoluteExpression - Parse an expression which must evaluate to an
+  /// absolute value.
   ///
   /// @param Res - The value of the absolute expression. The result is undefined
   /// on error.
   /// @result - False on success.
   bool ParseAbsoluteExpression(int64_t &Res);
 
+  /// ParseRelocatableExpression - Parse an expression which must be
+  /// relocatable.
+  ///
+  /// @param Res - The relocatable expression value. The result is undefined on
+  /// error.  
+  /// @result - False on success.
+  bool ParseRelocatableExpression(MCValue &Res);
+
   bool ParsePrimaryExpr(AsmExpr *&Res);
   bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
   bool ParseParenExpr(AsmExpr *&Res);





More information about the llvm-commits mailing list