Fix indent.
[oota-llvm.git] / lib / VMCore / Constants.cpp
index 352e963eb441b2f01d3d93f8ca87b433b3af3ca4..55bc4aef04c071a321daf30af15a21c574497afa 100644 (file)
@@ -250,12 +250,12 @@ ConstantArray::ConstantArray(const ArrayType *T,
   Use *OL = OperandList;
   for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
        I != E; ++I, ++OL) {
-    Constant *E = *I;
-    assert((E->getType() == T->getElementType() ||
+    Constant *C = *I;
+    assert((C->getType() == T->getElementType() ||
             (T->isAbstract() &&
-             E->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
+             C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
            "Initializer for array element doesn't match array element type!");
-    OL->init(E, this);
+    OL->init(C, this);
   }
 }
 
@@ -271,14 +271,14 @@ ConstantStruct::ConstantStruct(const StructType *T,
   Use *OL = OperandList;
   for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
        I != E; ++I, ++OL) {
-    Constant *E = *I;
-    assert((E->getType() == T->getElementType(I-V.begin()) ||
+    Constant *C = *I;
+    assert((C->getType() == T->getElementType(I-V.begin()) ||
             ((T->getElementType(I-V.begin())->isAbstract() ||
-              E->getType()->isAbstract()) &&
+              C->getType()->isAbstract()) &&
              T->getElementType(I-V.begin())->getTypeID() == 
-                   E->getType()->getTypeID())) &&
+                   C->getType()->getTypeID())) &&
            "Initializer for struct element doesn't match struct element type!");
-    OL->init(E, this);
+    OL->init(C, this);
   }
 }
 
@@ -293,12 +293,12 @@ ConstantPacked::ConstantPacked(const PackedType *T,
   Use *OL = OperandList;
     for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
          I != E; ++I, ++OL) {
-      Constant *E = *I;
-      assert((E->getType() == T->getElementType() ||
+      Constant *C = *I;
+      assert((C->getType() == T->getElementType() ||
             (T->isAbstract() &&
-             E->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
+             C->getType()->getTypeID() == T->getElementType()->getTypeID())) &&
            "Initializer for packed element doesn't match packed element type!");
-    OL->init(E, this);
+    OL->init(C, this);
   }
 }
 
@@ -347,6 +347,35 @@ public:
   }
 };
 
+/// ExtractElementConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// extractelement constant exprs.
+class ExtractElementConstantExpr : public ConstantExpr {
+  Use Ops[2];
+public:
+  ExtractElementConstantExpr(Constant *C1, Constant *C2)
+    : ConstantExpr(cast<PackedType>(C1->getType())->getElementType(), 
+                   Instruction::ExtractElement, Ops, 2) {
+    Ops[0].init(C1, this);
+    Ops[1].init(C2, this);
+  }
+};
+
+/// InsertElementConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// insertelement constant exprs.
+class InsertElementConstantExpr : public ConstantExpr {
+  Use Ops[3];
+public:
+  InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
+    : ConstantExpr(C1->getType(), Instruction::InsertElement, 
+                   Ops, 3) {
+    Ops[0].init(C1, this);
+    Ops[1].init(C2, this);
+    Ops[2].init(C3, this);
+  }
+};
+
 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
 /// used behind the scenes to implement getelementpr constant exprs.
 struct GetElementPtrConstantExpr : public ConstantExpr {
@@ -1141,6 +1170,11 @@ namespace llvm {
         return new BinaryConstantExpr(V.first, V.second[0], V.second[1]);
       if (V.first == Instruction::Select)
         return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]);
+      if (V.first == Instruction::ExtractElement)
+        return new ExtractElementConstantExpr(V.second[0], V.second[1]);
+      if (V.first == Instruction::InsertElement)
+        return new InsertElementConstantExpr(V.second[0], V.second[1],
+                                             V.second[2]);
 
       assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
 
@@ -1277,14 +1311,15 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
   case Instruction::Mul: case Instruction::Div:
   case Instruction::Rem:
     assert(C1->getType() == C2->getType() && "Op types should be identical!");
-    assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint()) &&
+    assert((C1->getType()->isInteger() || C1->getType()->isFloatingPoint() ||
+            isa<PackedType>(C1->getType())) &&
            "Tried to create an arithmetic operation on a non-arithmetic type!");
     break;
   case Instruction::And:
   case Instruction::Or:
   case Instruction::Xor:
     assert(C1->getType() == C2->getType() && "Op types should be identical!");
-    assert(C1->getType()->isIntegral() &&
+    assert((C1->getType()->isIntegral() || isa<PackedType>(C1->getType())) &&
            "Tried to create a logical operation on a non-integral type!");
     break;
   case Instruction::SetLT: case Instruction::SetGT: case Instruction::SetLE:
@@ -1294,7 +1329,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) {
   case Instruction::Shl:
   case Instruction::Shr:
     assert(C2->getType() == Type::UByteTy && "Shift should be by ubyte!");
-    assert(C1->getType()->isInteger() &&
+    assert((C1->getType()->isInteger() || isa<PackedType>(C1->getType())) &&
            "Tried to create a shift operation on a non-integer type!");
     break;
   default:
@@ -1385,6 +1420,49 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C,
   return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
 }
 
+Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val,
+                                            Constant *Idx) {
+  if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx))
+    return FC;          // Fold a few common cases...
+  // Look up the constant in the table first to ensure uniqueness
+  std::vector<Constant*> ArgVec(1, Val);
+  ArgVec.push_back(Idx);
+  const ExprMapKeyType &Key = std::make_pair(Instruction::ExtractElement,ArgVec);
+  return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) {
+  assert(isa<PackedType>(Val->getType()) &&
+         "Tried to create extractelement operation on non-packed type!");
+  assert(Idx->getType() == Type::UIntTy &&
+         "Extractelement index must be uint type!");
+  return getExtractElementTy(cast<PackedType>(Val->getType())->getElementType(),
+                             Val, Idx);
+}
+
+Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val,
+                                           Constant *Elt, Constant *Idx) {
+  if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx))
+    return FC;          // Fold a few common cases...
+  // Look up the constant in the table first to ensure uniqueness
+  std::vector<Constant*> ArgVec(1, Val);
+  ArgVec.push_back(Elt);
+  ArgVec.push_back(Idx);
+  const ExprMapKeyType &Key = std::make_pair(Instruction::InsertElement,ArgVec);
+  return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, 
+                                         Constant *Idx) {
+  assert(isa<PackedType>(Val->getType()) &&
+         "Tried to create insertelement operation on non-packed type!");
+  assert(Elt->getType() == cast<PackedType>(Val->getType())->getElementType()
+         && "Insertelement types must match!");
+  assert(Idx->getType() == Type::UIntTy &&
+         "Insertelement index must be uint type!");
+  return getInsertElementTy(cast<PackedType>(Val->getType())->getElementType(),
+                            Val, Elt, Idx);
+}
 
 // destroyConstant - Remove the constant from the constant table...
 //
@@ -1580,6 +1658,12 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
     if (C2 == From) C2 = To;
     if (C3 == From) C3 = To;
     Replacement = ConstantExpr::getSelect(C1, C2, C3);
+  } else if (getOpcode() == Instruction::ExtractElement) {
+    Constant *C1 = getOperand(0);
+    Constant *C2 = getOperand(1);
+    if (C1 == From) C1 = To;
+    if (C2 == From) C2 = To;
+    Replacement = ConstantExpr::getExtractElement(C1, C2);
   } else if (getNumOperands() == 2) {
     Constant *C1 = getOperand(0);
     Constant *C2 = getOperand(1);
@@ -1628,3 +1712,47 @@ void Constant::clearAllValueMaps() {
     (*I)->destroyConstantImpl();
   Constants.clear();
 }
+
+/// getStringValue - Turn an LLVM constant pointer that eventually points to a
+/// global into a string value.  Return an empty string if we can't do it.
+/// Parameter Chop determines if the result is chopped at the first null
+/// terminator.
+///
+std::string Constant::getStringValue(bool Chop, unsigned Offset) {
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(this)) {
+    if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
+      ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
+      if (Init->isString()) {
+        std::string Result = Init->getAsString();
+        if (Offset < Result.size()) {
+          // If we are pointing INTO The string, erase the beginning...
+          Result.erase(Result.begin(), Result.begin()+Offset);
+
+          // Take off the null terminator, and any string fragments after it.
+          if (Chop) {
+            std::string::size_type NullPos = Result.find_first_of((char)0);
+            if (NullPos != std::string::npos)
+              Result.erase(Result.begin()+NullPos, Result.end());
+          }
+          return Result;
+        }
+      }
+    }
+  } else if (Constant *C = dyn_cast<Constant>(this)) {
+    if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
+      return GV->getStringValue(Chop, Offset);
+    else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+      if (CE->getOpcode() == Instruction::GetElementPtr) {
+        // Turn a gep into the specified offset.
+        if (CE->getNumOperands() == 3 &&
+            cast<Constant>(CE->getOperand(1))->isNullValue() &&
+            isa<ConstantInt>(CE->getOperand(2))) {
+          Offset += cast<ConstantInt>(CE->getOperand(2))->getRawValue();
+          return CE->getOperand(0)->getStringValue(Chop, Offset);
+        }
+      }
+    }
+  }
+  return "";
+}
+