DwarfWriter reading basic type information from llvm-gcc4 code.
[oota-llvm.git] / lib / VMCore / Constants.cpp
index 6728fc4080ff070400dbfc28682d6d38739645de..c8a5f356bc032d91cf36a09461feb2bd4fe37061 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 {
@@ -513,14 +542,24 @@ namespace llvm {
 }
 
 namespace {
-  template<class ValType, class TypeClass, class ConstantClass>
+  template<class ValType, class TypeClass, class ConstantClass,
+           bool HasLargeKey = false  /*true for arrays and structs*/ >
   class ValueMap : public AbstractTypeUser {
   public:
     typedef std::pair<const TypeClass*, ValType> MapKey;
     typedef std::map<MapKey, ConstantClass *> MapTy;
     typedef typename MapTy::iterator MapIterator;
   private:
+    /// Map - This is the main map from the element descriptor to the Constants.
+    /// This is the primary way we avoid creating two of the same shape
+    /// constant.
     MapTy Map;
+    
+    /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping
+    /// from the constants to their element in Map.  This is important for
+    /// removal of constants from the array, which would otherwise have to scan
+    /// through the map with very large keys.
+    std::map<ConstantClass*, MapIterator> InverseMap;
 
     typedef std::map<const TypeClass*, MapIterator> AbstractTypeMapTy;
     AbstractTypeMapTy AbstractTypeMap;
@@ -532,6 +571,7 @@ namespace {
         Constants.push_back(I->second);
       Map.clear();
       AbstractTypeMap.clear();
+      InverseMap.clear();
     }
 
   public:
@@ -548,7 +588,30 @@ namespace {
       Exists = !IP.second;
       return IP.first;
     }
+    
+private:
+    MapIterator FindExistingElement(ConstantClass *CP) {
+      if (HasLargeKey) {
+        typename std::map<ConstantClass*, MapIterator>::iterator
+            IMI = InverseMap.find(CP);
+        assert(IMI != InverseMap.end() && IMI->second != Map.end() &&
+               IMI->second->second == CP &&
+               "InverseMap corrupt!");
+        return IMI->second;
+      }
       
+      MapIterator I =
+        Map.find(MapKey((TypeClass*)CP->getRawType(), getValType(CP)));
+      if (I == Map.end() || I->second != CP) {
+        // FIXME: This should not use a linear scan.  If this gets to be a
+        // performance problem, someone should look at this.
+        for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
+          /* empty */;
+      }
+      return I;
+    }
+public:
+    
     /// getOrCreate - Return the specified constant from the map, creating it if
     /// necessary.
     ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) {
@@ -565,6 +628,9 @@ namespace {
       //assert(Result->getType() == Ty && "Type specified is not correct!");
       I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result));
 
+      if (HasLargeKey)  // Remember the reverse mapping if needed.
+        InverseMap.insert(std::make_pair(Result, I));
+      
       // If the type of the constant is abstract, make sure that an entry exists
       // for it in the AbstractTypeMap.
       if (Ty->isAbstract()) {
@@ -582,18 +648,13 @@ namespace {
     }
 
     void remove(ConstantClass *CP) {
-      MapIterator I = Map.find(MapKey((TypeClass*)CP->getRawType(),
-                                      getValType(CP)));
-      if (I == Map.end() || I->second != CP) {
-        // FIXME: This should not use a linear scan.  If this gets to be a
-        // performance problem, someone should look at this.
-        for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
-          /* empty */;
-      }
-
+      MapIterator I = FindExistingElement(CP);
       assert(I != Map.end() && "Constant not found in constant table!");
       assert(I->second == CP && "Didn't find correct element?");
 
+      if (HasLargeKey)  // Remember the reverse mapping if needed.
+        InverseMap.erase(CP);
+      
       // Now that we found the entry, make sure this isn't the entry that
       // the AbstractTypeMap points to.
       const TypeClass *Ty = I->first.first;
@@ -636,6 +697,38 @@ namespace {
       Map.erase(I);
     }
 
+    
+    /// MoveConstantToNewSlot - If we are about to change C to be the element
+    /// specified by I, update our internal data structures to reflect this
+    /// fact.
+    void MoveConstantToNewSlot(ConstantClass *C, MapIterator I) {
+      // First, remove the old location of the specified constant in the map.
+      MapIterator OldI = FindExistingElement(C);
+      assert(OldI != Map.end() && "Constant not found in constant table!");
+      assert(OldI->second == C && "Didn't find correct element?");
+      
+      // If this constant is the representative element for its abstract type,
+      // update the AbstractTypeMap so that the representative element is I.
+      if (C->getType()->isAbstract()) {
+        typename AbstractTypeMapTy::iterator ATI =
+            AbstractTypeMap.find(C->getType());
+        assert(ATI != AbstractTypeMap.end() &&
+               "Abstract type not in AbstractTypeMap?");
+        if (ATI->second == OldI)
+          ATI->second = I;
+      }
+      
+      // Remove the old entry from the map.
+      Map.erase(OldI);
+      
+      // Update the inverse map so that we know that this constant is now
+      // located at descriptor I.
+      if (HasLargeKey) {
+        assert(I->second == C && "Bad inversemap entry!");
+        InverseMap[C] = I;
+      }
+    }
+    
     void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
       typename AbstractTypeMapTy::iterator I =
         AbstractTypeMap.find(cast<TypeClass>(OldTy));
@@ -765,14 +858,6 @@ void ConstantAggregateZero::destroyConstant() {
   destroyConstantImpl();
 }
 
-void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To,
-                                                        bool DisableChecking) {
-  assert(0 && "No uses!");
-  abort();
-}
-
-
-
 //---- ConstantArray::get() implementation...
 //
 namespace llvm {
@@ -800,7 +885,7 @@ static std::vector<Constant*> getValType(ConstantArray *CA) {
 }
 
 typedef ValueMap<std::vector<Constant*>, ArrayType, 
-                 ConstantArray> ArrayConstantsTy;
+                 ConstantArray, true /*largekey*/> ArrayConstantsTy;
 static ArrayConstantsTy ArrayConstants;
 
 Constant *ConstantArray::get(const ArrayType *Ty,
@@ -889,8 +974,9 @@ namespace llvm {
   };
 }
 
-static ValueMap<std::vector<Constant*>, StructType,
-                ConstantStruct> StructConstants;
+typedef ValueMap<std::vector<Constant*>, StructType,
+                 ConstantStruct, true /*largekey*/> StructConstantsTy;
+static StructConstantsTy StructConstants;
 
 static std::vector<Constant*> getValType(ConstantStruct *CS) {
   std::vector<Constant*> Elements;
@@ -1084,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!");
 
@@ -1220,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:
@@ -1237,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:
@@ -1328,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...
 //
@@ -1344,22 +1479,35 @@ const char *ConstantExpr::getOpcodeName() const {
 //                replaceUsesOfWithOnConstant implementations
 
 void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
-                                                bool DisableChecking) {
+                                                Use *U) {
   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
-  
+  Constant *ToC = cast<Constant>(To);
+
+  unsigned OperandToUpdate = U-OperandList;
+  assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
+
   std::pair<ArrayConstantsTy::MapKey, ConstantArray*> Lookup;
   Lookup.first.first = getType();
   Lookup.second = this;
+
   std::vector<Constant*> &Values = Lookup.first.second;
   Values.reserve(getNumOperands());  // Build replacement array.
-  
-  bool isAllZeros = false;   // Does this turn into an all-zeros array?
-  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
-    Constant *Val = getOperand(i);
-    if (Val == From) Val = cast<Constant>(To);
-    Values.push_back(Val);
-    if (isAllZeros) isAllZeros = Val->isNullValue();
+
+  // Fill values with the modified operands of the constant array.  Also, 
+  // compute whether this turns into an all-zeros array.
+  bool isAllZeros = false;
+  if (!ToC->isNullValue()) {
+    for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O)
+      Values.push_back(cast<Constant>(O->get()));
+  } else {
+    isAllZeros = true;
+    for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
+      Constant *Val = cast<Constant>(O->get());
+      Values.push_back(Val);
+      if (isAllZeros) isAllZeros = Val->isNullValue();
+    }
   }
+  Values[OperandToUpdate] = ToC;
   
   Constant *Replacement = 0;
   if (isAllZeros) {
@@ -1377,14 +1525,10 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
       // creating a new constant array, inserting it, replaceallusesof'ing the
       // old with the new, then deleting the old... just update the current one
       // in place!
-      if (I != ArrayConstants.map_end() && I->second == this)
-        ++I;    // Do not invalidate iterator!
-      ArrayConstants.remove(this);   // Remove old shape from the map.
+      ArrayConstants.MoveConstantToNewSlot(this, I);
       
-      // Update to the new values.
-      for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
-        if (getOperand(i) == From)
-          setOperand(i, cast<Constant>(To));
+      // Update to the new value.
+      setOperand(OperandToUpdate, ToC);
       return;
     }
   }
@@ -1392,43 +1536,79 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
   // Otherwise, I do need to replace this with an existing value.
   assert(Replacement != this && "I didn't contain From!");
   
-  // Everyone using this now uses the replacement...
-  if (DisableChecking)
-    uncheckedReplaceAllUsesWith(Replacement);
-  else
-    replaceAllUsesWith(Replacement);
+  // Everyone using this now uses the replacement.
+  uncheckedReplaceAllUsesWith(Replacement);
   
   // Delete the old constant!
   destroyConstant();
 }
 
 void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
-                                                 bool DisableChecking) {
+                                                 Use *U) {
   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+  Constant *ToC = cast<Constant>(To);
+
+  unsigned OperandToUpdate = U-OperandList;
+  assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
+
+  std::pair<StructConstantsTy::MapKey, ConstantStruct*> Lookup;
+  Lookup.first.first = getType();
+  Lookup.second = this;
+  std::vector<Constant*> &Values = Lookup.first.second;
+  Values.reserve(getNumOperands());  // Build replacement struct.
   
-  std::vector<Constant*> Values;
-  Values.reserve(getNumOperands());  // Build replacement array...
-  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
-    Constant *Val = getOperand(i);
-    if (Val == From) Val = cast<Constant>(To);
-    Values.push_back(Val);
+  
+  // Fill values with the modified operands of the constant struct.  Also, 
+  // compute whether this turns into an all-zeros struct.
+  bool isAllZeros = false;
+  if (!ToC->isNullValue()) {
+    for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O)
+      Values.push_back(cast<Constant>(O->get()));
+  } else {
+    isAllZeros = true;
+    for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) {
+      Constant *Val = cast<Constant>(O->get());
+      Values.push_back(Val);
+      if (isAllZeros) isAllZeros = Val->isNullValue();
+    }
+  }
+  Values[OperandToUpdate] = ToC;
+  
+  Constant *Replacement = 0;
+  if (isAllZeros) {
+    Replacement = ConstantAggregateZero::get(getType());
+  } else {
+    // Check to see if we have this array type already.
+    bool Exists;
+    StructConstantsTy::MapIterator I =
+      StructConstants.InsertOrGetItem(Lookup, Exists);
+    
+    if (Exists) {
+      Replacement = I->second;
+    } else {
+      // Okay, the new shape doesn't exist in the system yet.  Instead of
+      // creating a new constant struct, inserting it, replaceallusesof'ing the
+      // old with the new, then deleting the old... just update the current one
+      // in place!
+      StructConstants.MoveConstantToNewSlot(this, I);
+      
+      // Update to the new value.
+      setOperand(OperandToUpdate, ToC);
+      return;
+    }
   }
   
-  Constant *Replacement = ConstantStruct::get(getType(), Values);
   assert(Replacement != this && "I didn't contain From!");
   
-  // Everyone using this now uses the replacement...
-  if (DisableChecking)
-    uncheckedReplaceAllUsesWith(Replacement);
-  else
-    replaceAllUsesWith(Replacement);
+  // Everyone using this now uses the replacement.
+  uncheckedReplaceAllUsesWith(Replacement);
   
   // Delete the old constant!
   destroyConstant();
 }
 
 void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To,
-                                                 bool DisableChecking) {
+                                                 Use *U) {
   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
   
   std::vector<Constant*> Values;
@@ -1442,18 +1622,15 @@ void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To,
   Constant *Replacement = ConstantPacked::get(getType(), Values);
   assert(Replacement != this && "I didn't contain From!");
   
-  // Everyone using this now uses the replacement...
-  if (DisableChecking)
-    uncheckedReplaceAllUsesWith(Replacement);
-  else
-    replaceAllUsesWith(Replacement);
+  // Everyone using this now uses the replacement.
+  uncheckedReplaceAllUsesWith(Replacement);
   
   // Delete the old constant!
   destroyConstant();
 }
 
 void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
-                                               bool DisableChecking) {
+                                               Use *U) {
   assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");
   Constant *To = cast<Constant>(ToV);
   
@@ -1481,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);
@@ -1494,11 +1677,8 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
   
   assert(Replacement != this && "I didn't contain From!");
   
-  // Everyone using this now uses the replacement...
-  if (DisableChecking)
-    uncheckedReplaceAllUsesWith(Replacement);
-  else
-    replaceAllUsesWith(Replacement);
+  // Everyone using this now uses the replacement.
+  uncheckedReplaceAllUsesWith(Replacement);
   
   // Delete the old constant!
   destroyConstant();