[llvm-commits] [parallel] CVS: llvm/lib/VMCore/AsmWriter.cpp BasicBlock.cpp ConstantFolding.cpp Constants.cpp Function.cpp Instruction.cpp IntrinsicLowering.cpp ModuleProvider.cpp Pass.cpp PassManagerT.h SlotCalculator.cpp Type.cpp Verifier.cpp iCall.cpp iOperators.cpp
Misha Brukman
brukman at cs.uiuc.edu
Mon Mar 1 18:04:44 PST 2004
Changes in directory llvm/lib/VMCore:
AsmWriter.cpp updated: 1.116 -> 1.116.2.1
BasicBlock.cpp updated: 1.38 -> 1.38.4.1
ConstantFolding.cpp updated: 1.50 -> 1.50.2.1
Constants.cpp updated: 1.71 -> 1.71.2.1
Function.cpp updated: 1.62.2.1 -> 1.62.2.2
Instruction.cpp updated: 1.33.2.1 -> 1.33.2.2
IntrinsicLowering.cpp updated: 1.5.2.1 -> 1.5.2.2
ModuleProvider.cpp updated: 1.8 -> 1.8.4.1
Pass.cpp updated: 1.54 -> 1.54.4.1
PassManagerT.h updated: 1.46 -> 1.46.4.1
SlotCalculator.cpp updated: 1.50 -> 1.50.2.1
Type.cpp updated: 1.87 -> 1.87.2.1
Verifier.cpp updated: 1.78.2.2 -> 1.78.2.3
iCall.cpp updated: 1.22 -> 1.22.4.1
iOperators.cpp updated: 1.25 -> 1.25.4.1
---
Log message:
Merge from trunk
---
Diffs of the changes: (+583 -446)
Index: llvm/lib/VMCore/AsmWriter.cpp
diff -u llvm/lib/VMCore/AsmWriter.cpp:1.116 llvm/lib/VMCore/AsmWriter.cpp:1.116.2.1
--- llvm/lib/VMCore/AsmWriter.cpp:1.116 Tue Jan 20 13:50:22 2004
+++ llvm/lib/VMCore/AsmWriter.cpp Mon Mar 1 17:58:16 2004
@@ -142,7 +142,6 @@
// This is another base case for the recursion. In this case, we know
// that we have looped back to a type that we have previously visited.
// Generate the appropriate upreference to handle this.
- //
if (Slot < CurSize)
return "\\" + utostr(CurSize-Slot); // Here's the upreference
@@ -153,15 +152,14 @@
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
Result = calcTypeName(FTy->getReturnType(), TypeStack, TypeNames) + " (";
- for (FunctionType::ParamTypes::const_iterator
- I = FTy->getParamTypes().begin(),
- E = FTy->getParamTypes().end(); I != E; ++I) {
- if (I != FTy->getParamTypes().begin())
+ for (FunctionType::param_iterator I = FTy->param_begin(),
+ E = FTy->param_end(); I != E; ++I) {
+ if (I != FTy->param_begin())
Result += ", ";
Result += calcTypeName(*I, TypeStack, TypeNames);
}
if (FTy->isVarArg()) {
- if (!FTy->getParamTypes().empty()) Result += ", ";
+ if (FTy->getNumParams()) Result += ", ";
Result += "...";
}
Result += ")";
@@ -170,10 +168,9 @@
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
Result = "{ ";
- for (StructType::ElementTypes::const_iterator
- I = STy->getElementTypes().begin(),
- E = STy->getElementTypes().end(); I != E; ++I) {
- if (I != STy->getElementTypes().begin())
+ for (StructType::element_iterator I = STy->element_begin(),
+ E = STy->element_end(); I != E; ++I) {
+ if (I != STy->element_begin())
Result += ", ";
Result += calcTypeName(*I, TypeStack, TypeNames);
}
@@ -202,9 +199,9 @@
}
-// printTypeInt - The internal guts of printing out a type that has a
-// potentially named portion.
-//
+/// printTypeInt - The internal guts of printing out a type that has a
+/// potentially named portion.
+///
static std::ostream &printTypeInt(std::ostream &Out, const Type *Ty,
std::map<const Type *, std::string> &TypeNames) {
// Primitive types always print out their description, regardless of whether
@@ -228,10 +225,10 @@
}
-// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
-// type, iff there is an entry in the modules symbol table for the specified
-// type or one of it's component types. This is slower than a simple x << Type;
-//
+/// WriteTypeSymbolic - This attempts to write the specified type as a symbolic
+/// type, iff there is an entry in the modules symbol table for the specified
+/// type or one of it's component types. This is slower than a simple x << Type
+///
std::ostream &llvm::WriteTypeSymbolic(std::ostream &Out, const Type *Ty,
const Module *M) {
Out << " ";
@@ -290,12 +287,9 @@
"assuming that double is 64 bits!");
Out << "0x" << utohexstr(*(uint64_t*)Ptr);
+ } else if (isa<ConstantAggregateZero>(CV)) {
+ Out << "zeroinitializer";
} else if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
- if (CA->getNumOperands() > 5 && CA->isNullValue()) {
- Out << "zeroinitializer";
- return;
- }
-
// As a special case, print the array as a string if it is an array of
// ubytes or an array of sbytes with positive values.
//
@@ -341,11 +335,6 @@
Out << " ]";
}
} else if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
- if (CS->getNumOperands() > 5 && CS->isNullValue()) {
- Out << "zeroinitializer";
- return;
- }
-
Out << "{";
if (CS->getNumOperands()) {
Out << " ";
@@ -424,20 +413,23 @@
}
if (Slot >= 0) Out << "%" << Slot;
else if (PrintName)
- Out << "<badref>"; // Not embedded into a location?
+ if (V->hasName())
+ Out << "<badref: " << getLLVMName(V->getName()) << ">";
+ else
+ Out << "<badref>"; // Not embedded into a location?
}
}
}
-// WriteAsOperand - Write the name of the specified value out to the specified
-// ostream. This can be useful when you just want to print int %reg126, not the
-// whole instruction that generated it.
-//
+/// WriteAsOperand - Write the name of the specified value out to the specified
+/// ostream. This can be useful when you just want to print int %reg126, not
+/// the whole instruction that generated it.
+///
std::ostream &llvm::WriteAsOperand(std::ostream &Out, const Value *V,
- bool PrintType,
- bool PrintName, const Module *Context) {
+ bool PrintType, bool PrintName,
+ const Module *Context) {
std::map<const Type *, std::string> TypeNames;
if (Context == 0) Context = getModuleFromVal(V);
@@ -517,24 +509,22 @@
std::ostream &AssemblyWriter::printTypeAtLeastOneLevel(const Type *Ty) {
if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
printType(FTy->getReturnType()) << " (";
- for (FunctionType::ParamTypes::const_iterator
- I = FTy->getParamTypes().begin(),
- E = FTy->getParamTypes().end(); I != E; ++I) {
- if (I != FTy->getParamTypes().begin())
+ for (FunctionType::param_iterator I = FTy->param_begin(),
+ E = FTy->param_end(); I != E; ++I) {
+ if (I != FTy->param_begin())
Out << ", ";
printType(*I);
}
if (FTy->isVarArg()) {
- if (!FTy->getParamTypes().empty()) Out << ", ";
+ if (FTy->getNumParams()) Out << ", ";
Out << "...";
}
Out << ")";
} else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
Out << "{ ";
- for (StructType::ElementTypes::const_iterator
- I = STy->getElementTypes().begin(),
- E = STy->getElementTypes().end(); I != E; ++I) {
- if (I != STy->getElementTypes().begin())
+ for (StructType::element_iterator I = STy->element_begin(),
+ E = STy->element_end(); I != E; ++I) {
+ if (I != STy->element_begin())
Out << ", ";
printType(*I);
}
@@ -689,7 +679,7 @@
// Finish printing arguments...
if (FT->isVarArg()) {
- if (FT->getParamTypes().size()) Out << ", ";
+ if (FT->getNumParams()) Out << ", ";
Out << "..."; // Output varargs portion of signature!
}
Out << ")";
@@ -894,8 +884,8 @@
Out << " )\n\t\t\tto";
writeOperand(II->getNormalDest(), true);
- Out << " except";
- writeOperand(II->getExceptionalDest(), true);
+ Out << " unwind";
+ writeOperand(II->getUnwindDest(), true);
} else if (const AllocationInst *AI = dyn_cast<AllocationInst>(&I)) {
Out << " ";
Index: llvm/lib/VMCore/BasicBlock.cpp
diff -u llvm/lib/VMCore/BasicBlock.cpp:1.38 llvm/lib/VMCore/BasicBlock.cpp:1.38.4.1
--- llvm/lib/VMCore/BasicBlock.cpp:1.38 Fri Nov 21 10:52:05 2003
+++ llvm/lib/VMCore/BasicBlock.cpp Mon Mar 1 17:58:16 2004
@@ -61,25 +61,8 @@
template class SymbolTableListTraits<Instruction, BasicBlock, Function>;
-// BasicBlock ctor - If the function parameter is specified, the basic block is
-// automatically inserted at the end of the function.
-//
-BasicBlock::BasicBlock(const std::string &name, Function *Parent)
- : Value(Type::LabelTy, Value::BasicBlockVal, name) {
- // Initialize the instlist...
- InstList.setItemParent(this);
-
- // Make sure that we get added to a function
- LeakDetector::addGarbageObject(this);
-
- if (Parent)
- Parent->getBasicBlockList().push_back(this);
-}
-
-/// BasicBlock ctor - If the InsertBefore parameter is specified, the basic
-/// block is automatically inserted right before the specified block.
-///
-BasicBlock::BasicBlock(const std::string &Name, BasicBlock *InsertBefore)
+BasicBlock::BasicBlock(const std::string &Name, Function *Parent,
+ BasicBlock *InsertBefore)
: Value(Type::LabelTy, Value::BasicBlockVal, Name) {
// Initialize the instlist...
InstList.setItemParent(this);
@@ -88,10 +71,11 @@
LeakDetector::addGarbageObject(this);
if (InsertBefore) {
- assert(InsertBefore->getParent() &&
- "Cannot insert block before another block that is not embedded into"
- " a function yet!");
- InsertBefore->getParent()->getBasicBlockList().insert(InsertBefore, this);
+ assert(Parent &&
+ "Cannot insert block before another block with no function!");
+ Parent->getBasicBlockList().insert(InsertBefore, this);
+ } else if (Parent) {
+ Parent->getBasicBlockList().push_back(this);
}
}
@@ -136,19 +120,6 @@
I->dropAllReferences();
}
-// hasConstantReferences() - This predicate is true if there is a
-// reference to this basic block in the constant pool for this method. For
-// example, if a block is reached through a switch table, that table resides
-// in the constant pool, and the basic block is reference from it.
-//
-bool BasicBlock::hasConstantReferences() const {
- for (use_const_iterator I = use_begin(), E = use_end(); I != E; ++I)
- if (isa<Constant>((Value*)*I))
- return true;
-
- return false;
-}
-
// removePredecessor - This method is used to notify a BasicBlock that the
// specified Predecessor of the block is no longer able to reach it. This is
// actually not used to update the Predecessor list, but is actually used to
@@ -231,16 +202,11 @@
assert(I != InstList.end() &&
"Trying to get me to create degenerate basic block!");
- BasicBlock *New = new BasicBlock(BBName, getParent());
+ BasicBlock *New = new BasicBlock(BBName, getParent(), getNext());
- // Go from the end of the basic block through to the iterator pointer, moving
- // to the new basic block...
- Instruction *Inst = 0;
- do {
- iterator EndIt = end();
- Inst = InstList.remove(--EndIt); // Remove from end
- New->InstList.push_front(Inst); // Add to front
- } while (Inst != &*I); // Loop until we move the specified instruction.
+ // Move all of the specified instructions from the original basic block into
+ // the new basic block.
+ New->getInstList().splice(New->end(), this->getInstList(), I, end());
// Add a branch instruction to the newly formed basic block.
new BranchInst(New, this);
Index: llvm/lib/VMCore/ConstantFolding.cpp
diff -u llvm/lib/VMCore/ConstantFolding.cpp:1.50 llvm/lib/VMCore/ConstantFolding.cpp:1.50.2.1
--- llvm/lib/VMCore/ConstantFolding.cpp:1.50 Mon Jan 12 23:51:55 2004
+++ llvm/lib/VMCore/ConstantFolding.cpp Mon Mar 1 17:58:16 2004
@@ -20,9 +20,7 @@
#include "ConstantFolding.h"
#include "llvm/Constants.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iOperators.h"
-#include "llvm/InstrTypes.h"
+#include "llvm/Instructions.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include <cmath>
@@ -625,11 +623,18 @@
// If the first operand is simple, swap operands.
assert((isa<ConstantPointerRef>(V2) || isa<ConstantExpr>(V2)) &&
"Simple cases should have been handled by caller!");
- return SetCondInst::getSwappedCondition(evaluateRelation(V2, V1));
+ Instruction::BinaryOps SwappedRelation = evaluateRelation(V2, V1);
+ if (SwappedRelation != Instruction::BinaryOpsEnd)
+ return SetCondInst::getSwappedCondition(SwappedRelation);
} else if (const ConstantPointerRef *CPR1 = dyn_cast<ConstantPointerRef>(V1)){
- if (isa<ConstantExpr>(V2)) // Swap as necessary.
- return SetCondInst::getSwappedCondition(evaluateRelation(V2, V1));
+ if (isa<ConstantExpr>(V2)) { // Swap as necessary.
+ Instruction::BinaryOps SwappedRelation = evaluateRelation(V2, V1);
+ if (SwappedRelation != Instruction::BinaryOpsEnd)
+ return SetCondInst::getSwappedCondition(SwappedRelation);
+ else
+ return Instruction::BinaryOpsEnd;
+ }
// Now we know that the RHS is a ConstantPointerRef or simple constant,
// which (since the types must match) means that it's a ConstantPointerNull.
@@ -920,8 +925,21 @@
(IdxList.size() == 1 && IdxList[0]->isNullValue()))
return const_cast<Constant*>(C);
- // TODO If C is null and all idx's are null, return null of the right type.
-
+ if (C->isNullValue()) {
+ bool isNull = true;
+ for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
+ if (!IdxList[i]->isNullValue()) {
+ isNull = false;
+ break;
+ }
+ if (isNull) {
+ std::vector<Value*> VIdxList(IdxList.begin(), IdxList.end());
+ const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
+ true);
+ assert(Ty != 0 && "Invalid indices for GEP!");
+ return ConstantPointerNull::get(PointerType::get(Ty));
+ }
+ }
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(const_cast<Constant*>(C))) {
// Combine Indices - If the source pointer to this getelementptr instruction
Index: llvm/lib/VMCore/Constants.cpp
diff -u llvm/lib/VMCore/Constants.cpp:1.71 llvm/lib/VMCore/Constants.cpp:1.71.2.1
--- llvm/lib/VMCore/Constants.cpp:1.71 Wed Jan 14 11:51:53 2004
+++ llvm/lib/VMCore/Constants.cpp Mon Mar 1 17:58:16 2004
@@ -116,21 +116,9 @@
case Type::PointerTyID:
return ConstantPointerNull::get(cast<PointerType>(Ty));
- case Type::StructTyID: {
- const StructType *ST = cast<StructType>(Ty);
- const StructType::ElementTypes &ETs = ST->getElementTypes();
- std::vector<Constant*> Elements;
- Elements.resize(ETs.size());
- for (unsigned i = 0, e = ETs.size(); i != e; ++i)
- Elements[i] = Constant::getNullValue(ETs[i]);
- return ConstantStruct::get(ST, Elements);
- }
- case Type::ArrayTyID: {
- const ArrayType *AT = cast<ArrayType>(Ty);
- Constant *El = Constant::getNullValue(AT->getElementType());
- unsigned NumElements = AT->getNumElements();
- return ConstantArray::get(AT, std::vector<Constant*>(NumElements, El));
- }
+ case Type::StructTyID:
+ case Type::ArrayTyID:
+ return ConstantAggregateZero::get(Ty);
default:
// Function, Type, Label, or Opaque type?
assert(0 && "Cannot create a null constant of that type!");
@@ -263,14 +251,15 @@
ConstantStruct::ConstantStruct(const StructType *T,
const std::vector<Constant*> &V) : Constant(T) {
- const StructType::ElementTypes &ETypes = T->getElementTypes();
- assert(V.size() == ETypes.size() &&
+ assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
Operands.reserve(V.size());
for (unsigned i = 0, e = V.size(); i != e; ++i) {
- assert((V[i]->getType() == ETypes[i] ||
- ((ETypes[i]->isAbstract() || V[i]->getType()->isAbstract()) &&
- ETypes[i]->getPrimitiveID()==V[i]->getType()->getPrimitiveID())) &&
+ assert((V[i]->getType() == T->getElementType(i) ||
+ ((T->getElementType(i)->isAbstract() ||
+ V[i]->getType()->isAbstract()) &&
+ T->getElementType(i)->getPrimitiveID() ==
+ V[i]->getType()->getPrimitiveID())) &&
"Initializer for struct element doesn't match struct element type!");
Operands.push_back(Use(V[i], this));
}
@@ -330,11 +319,15 @@
return ((Ty == Type::FloatTy || Ty == Type::DoubleTy) &&
!isa<ConstantExpr>(CPV));
}
+bool ConstantAggregateZero::classof(const Constant *CPV) {
+ return (isa<ArrayType>(CPV->getType()) || isa<StructType>(CPV->getType())) &&
+ CPV->isNullValue();
+}
bool ConstantArray::classof(const Constant *CPV) {
- return isa<ArrayType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+ return isa<ArrayType>(CPV->getType()) && !CPV->isNullValue();
}
bool ConstantStruct::classof(const Constant *CPV) {
- return isa<StructType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+ return isa<StructType>(CPV->getType()) && !CPV->isNullValue();
}
bool ConstantPointerNull::classof(const Constant *CPV) {
@@ -417,7 +410,7 @@
Values.push_back(Val);
}
- ConstantArray *Replacement = ConstantArray::get(getType(), Values);
+ Constant *Replacement = ConstantArray::get(getType(), Values);
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement...
@@ -442,7 +435,7 @@
Values.push_back(Val);
}
- ConstantStruct *Replacement = ConstantStruct::get(getType(), Values);
+ Constant *Replacement = ConstantStruct::get(getType(), Values);
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement...
@@ -698,12 +691,100 @@
//---- ConstantFP::get() implementation...
//
-static ValueMap<double, Type, ConstantFP> FPConstants;
+namespace llvm {
+ template<>
+ struct ConstantCreator<ConstantFP, Type, uint64_t> {
+ static ConstantFP *create(const Type *Ty, uint64_t V) {
+ assert(Ty == Type::DoubleTy);
+ union {
+ double F;
+ uint64_t I;
+ } T;
+ T.I = V;
+ return new ConstantFP(Ty, T.F);
+ }
+ };
+ template<>
+ struct ConstantCreator<ConstantFP, Type, uint32_t> {
+ static ConstantFP *create(const Type *Ty, uint32_t V) {
+ assert(Ty == Type::FloatTy);
+ union {
+ float F;
+ uint32_t I;
+ } T;
+ T.I = V;
+ return new ConstantFP(Ty, T.F);
+ }
+ };
+}
+
+static ValueMap<uint64_t, Type, ConstantFP> DoubleConstants;
+static ValueMap<uint32_t, Type, ConstantFP> FloatConstants;
ConstantFP *ConstantFP::get(const Type *Ty, double V) {
- return FPConstants.getOrCreate(Ty, V);
+ if (Ty == Type::FloatTy) {
+ // Force the value through memory to normalize it.
+ union {
+ float F;
+ uint32_t I;
+ } T;
+ T.F = (float)V;
+ return FloatConstants.getOrCreate(Ty, T.I);
+ } else {
+ assert(Ty == Type::DoubleTy);
+ union {
+ double F;
+ uint64_t I;
+ } T;
+ T.F = V;
+ return DoubleConstants.getOrCreate(Ty, T.I);
+ }
+}
+
+//---- ConstantAggregateZero::get() implementation...
+//
+namespace llvm {
+ // ConstantAggregateZero does not take extra "value" argument...
+ template<class ValType>
+ struct ConstantCreator<ConstantAggregateZero, Type, ValType> {
+ static ConstantAggregateZero *create(const Type *Ty, const ValType &V){
+ return new ConstantAggregateZero(Ty);
+ }
+ };
+
+ template<>
+ struct ConvertConstantType<ConstantAggregateZero, Type> {
+ static void convert(ConstantAggregateZero *OldC, const Type *NewTy) {
+ // Make everyone now use a constant of the new type...
+ Constant *New = ConstantAggregateZero::get(NewTy);
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+ };
+}
+
+static ValueMap<char, Type, ConstantAggregateZero> AggZeroConstants;
+
+Constant *ConstantAggregateZero::get(const Type *Ty) {
+ return AggZeroConstants.getOrCreate(Ty, 0);
+}
+
+// destroyConstant - Remove the constant from the constant table...
+//
+void ConstantAggregateZero::destroyConstant() {
+ AggZeroConstants.remove(this);
+ destroyConstantImpl();
+}
+
+void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To,
+ bool DisableChecking) {
+ assert(0 && "No uses!");
+ abort();
}
+
+
//---- ConstantArray::get() implementation...
//
namespace llvm {
@@ -725,9 +806,18 @@
static ValueMap<std::vector<Constant*>, ArrayType,
ConstantArray> ArrayConstants;
-ConstantArray *ConstantArray::get(const ArrayType *Ty,
- const std::vector<Constant*> &V) {
- return ArrayConstants.getOrCreate(Ty, V);
+Constant *ConstantArray::get(const ArrayType *Ty,
+ const std::vector<Constant*> &V) {
+ // If this is an all-zero array, return a ConstantAggregateZero object
+ if (!V.empty()) {
+ Constant *C = V[0];
+ if (!C->isNullValue())
+ return ArrayConstants.getOrCreate(Ty, V);
+ for (unsigned i = 1, e = V.size(); i != e; ++i)
+ if (V[i] != C)
+ return ArrayConstants.getOrCreate(Ty, V);
+ }
+ return ConstantAggregateZero::get(Ty);
}
// destroyConstant - Remove the constant from the constant table...
@@ -741,7 +831,7 @@
// contain the specified string. A null terminator is added to the specified
// string so that it may be used in a natural way...
//
-ConstantArray *ConstantArray::get(const std::string &Str) {
+Constant *ConstantArray::get(const std::string &Str) {
std::vector<Constant*> ElementVals;
for (unsigned i = 0; i < Str.length(); ++i)
@@ -805,9 +895,14 @@
static ValueMap<std::vector<Constant*>, StructType,
ConstantStruct> StructConstants;
-ConstantStruct *ConstantStruct::get(const StructType *Ty,
- const std::vector<Constant*> &V) {
- return StructConstants.getOrCreate(Ty, V);
+Constant *ConstantStruct::get(const StructType *Ty,
+ const std::vector<Constant*> &V) {
+ // Create a ConstantAggregateZero value if all elements are zeros...
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (!V[i]->isNullValue())
+ return StructConstants.getOrCreate(Ty, V);
+
+ return ConstantAggregateZero::get(Ty);
}
// destroyConstant - Remove the constant from the constant table...
@@ -986,11 +1081,15 @@
Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
const std::vector<Constant*> &IdxList) {
+ assert(GetElementPtrInst::getIndexedType(C->getType(),
+ std::vector<Value*>(IdxList.begin(), IdxList.end()), true) &&
+ "GEP indices invalid!");
+
if (Constant *FC = ConstantFoldGetElementPtr(C, IdxList))
return FC; // Fold a few common cases...
+
assert(isa<PointerType>(C->getType()) &&
"Non-pointer type for constant GetElementPtr expression");
-
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> argVec(1, C);
argVec.insert(argVec.end(), IdxList.begin(), IdxList.end());
@@ -1006,17 +1105,6 @@
const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
true);
assert(Ty && "GEP indices invalid!");
-
- if (C->isNullValue()) {
- bool isNull = true;
- for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
- if (!IdxList[i]->isNullValue()) {
- isNull = false;
- break;
- }
- if (isNull) return ConstantPointerNull::get(PointerType::get(Ty));
- }
-
return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
}
Index: llvm/lib/VMCore/Function.cpp
diff -u llvm/lib/VMCore/Function.cpp:1.62.2.1 llvm/lib/VMCore/Function.cpp:1.62.2.2
--- llvm/lib/VMCore/Function.cpp:1.62.2.1 Mon Feb 2 16:33:06 2004
+++ llvm/lib/VMCore/Function.cpp Mon Mar 1 17:58:16 2004
@@ -214,11 +214,22 @@
if (getName() == "llvm.dbg.func.start") return Intrinsic::dbg_func_start;
if (getName() == "llvm.dbg.declare") return Intrinsic::dbg_declare;
break;
+ case 'f':
+ if (getName() == "llvm.frameaddress") return Intrinsic::frameaddress;
+ break;
case 'j':
if (getName() == "llvm.join") return Intrinsic::join;
break;
case 'l':
if (getName() == "llvm.longjmp") return Intrinsic::longjmp;
+ break;
+ case 'm':
+ if (getName() == "llvm.memcpy") return Intrinsic::memcpy;
+ if (getName() == "llvm.memmove") return Intrinsic::memmove;
+ if (getName() == "llvm.memset") return Intrinsic::memset;
+ break;
+ case 'r':
+ if (getName() == "llvm.returnaddress") return Intrinsic::returnaddress;
break;
case 's':
if (getName() == "llvm.setjmp") return Intrinsic::setjmp;
Index: llvm/lib/VMCore/Instruction.cpp
diff -u llvm/lib/VMCore/Instruction.cpp:1.33.2.1 llvm/lib/VMCore/Instruction.cpp:1.33.2.2
--- llvm/lib/VMCore/Instruction.cpp:1.33.2.1 Thu Jan 29 19:28:20 2004
+++ llvm/lib/VMCore/Instruction.cpp Mon Mar 1 17:58:16 2004
@@ -35,13 +35,13 @@
}
void Instruction::setParent(BasicBlock *P) {
- if (getParent())
- LeakDetector::addGarbageObject(this);
+ if (getParent()) {
+ if (!P) LeakDetector::addGarbageObject(this);
+ } else {
+ if (P) LeakDetector::removeGarbageObject(this);
+ }
Parent = P;
-
- if (getParent())
- LeakDetector::removeGarbageObject(this);
}
// Specialize setName to take care of symbol table majik
Index: llvm/lib/VMCore/IntrinsicLowering.cpp
diff -u llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.1 llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.2
--- llvm/lib/VMCore/IntrinsicLowering.cpp:1.5.2.1 Mon Feb 2 16:33:06 2004
+++ llvm/lib/VMCore/IntrinsicLowering.cpp Mon Mar 1 17:58:16 2004
@@ -12,12 +12,55 @@
//===----------------------------------------------------------------------===//
#include "llvm/IntrinsicLowering.h"
-#include "llvm/Constant.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
-#include "llvm/Type.h"
#include "llvm/iOther.h"
using namespace llvm;
+/// ReplaceCallWith - This function is used when we want to lower an intrinsic
+/// call to a call of an external function. This handles hard cases such as
+/// when there was already a prototype for the external function, and if that
+/// prototype doesn't match the arguments we expect to pass in.
+template <class ArgIt>
+static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
+ ArgIt ArgBegin, ArgIt ArgEnd,
+ const Type *RetTy, Function *&FCache) {
+ if (!FCache) {
+ // If we haven't already looked up this function, check to see if the
+ // program already contains a function with this name.
+ Module *M = CI->getParent()->getParent()->getParent();
+ FCache = M->getNamedFunction(NewFn);
+ if (!FCache) {
+ // It doesn't already exist in the program, insert a new definition now.
+ std::vector<const Type *> ParamTys;
+ for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
+ ParamTys.push_back((*I)->getType());
+ FCache = M->getOrInsertFunction(NewFn,
+ FunctionType::get(RetTy, ParamTys, false));
+ }
+ }
+
+ const FunctionType *FT = FCache->getFunctionType();
+ std::vector<Value*> Operands;
+ unsigned ArgNo = 0;
+ for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
+ ++I, ++ArgNo) {
+ Value *Arg = *I;
+ if (Arg->getType() != FT->getParamType(ArgNo))
+ Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
+ Operands.push_back(Arg);
+ }
+ // Pass nulls into any additional arguments...
+ for (; ArgNo != FT->getNumParams(); ++ArgNo)
+ Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
+
+ std::string Name = CI->getName(); CI->setName("");
+ if (FT->getReturnType() == Type::VoidTy) Name.clear();
+ return new CallInst(FCache, Operands, Name, CI);
+}
+
+
void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Function *Callee = CI->getCalledFunction();
assert(Callee && "Cannot lower an indirect call!");
@@ -34,19 +77,43 @@
<< Callee->getName() << "'!\n";
abort();
- // The default implementation of setjmp/longjmp transforms setjmp into a
- // noop that always returns zero and longjmp into a call to abort. This
- // allows code that never longjmps to work correctly.
- case Intrinsic::setjmp:
- case Intrinsic::sigsetjmp:
+ // The setjmp/longjmp intrinsics should only exist in the code if it was
+ // never optimized (ie, right out of the CFE), or if it has been hacked on
+ // by the lowerinvoke pass. In both cases, the right thing to do is to
+ // convert the call to an explicit setjmp or longjmp call.
+ case Intrinsic::setjmp: {
+ static Function *SetjmpFCache = 0;
+ Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
+ Type::IntTy, SetjmpFCache);
if (CI->getType() != Type::VoidTy)
- CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+ CI->replaceAllUsesWith(V);
break;
+ }
+ case Intrinsic::sigsetjmp:
+ if (CI->getType() != Type::VoidTy)
+ CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+ break;
case Intrinsic::longjmp:
+ static Function *LongjmpFCache = 0;
+ ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
+ Type::VoidTy, LongjmpFCache);
+ break;
+
case Intrinsic::siglongjmp:
// Insert the call to abort
- new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI);
+ static Function *AbortFCache = 0;
+ ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
+ AbortFCache);
+ break;
+
+ case Intrinsic::returnaddress:
+ case Intrinsic::frameaddress:
+ std::cerr << "WARNING: this target does not support the llvm."
+ << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
+ "return" : "frame") << "address intrinsic.\n";
+ CI->replaceAllUsesWith(ConstantPointerNull::get(
+ cast<PointerType>(CI->getType())));
break;
case Intrinsic::dbg_stoppoint:
@@ -62,8 +129,30 @@
// Insert the call to abort
new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI);
break;
- }
+ case Intrinsic::memcpy:
+ // The memcpy intrinsic take an extra alignment argument that the memcpy
+ // libc function does not.
+ static Function *MemcpyFCache = 0;
+ ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
+ (*(CI->op_begin()+1))->getType(), MemcpyFCache);
+ break;
+ case Intrinsic::memmove:
+ // The memmove intrinsic take an extra alignment argument that the memmove
+ // libc function does not.
+ static Function *MemmoveFCache = 0;
+ ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
+ (*(CI->op_begin()+1))->getType(), MemmoveFCache);
+ break;
+ case Intrinsic::memset:
+ // The memset intrinsic take an extra alignment argument that the memset
+ // libc function does not.
+ static Function *MemsetFCache = 0;
+ ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
+ (*(CI->op_begin()+1))->getType(), MemsetFCache);
+ break;
+ }
+
assert(CI->use_empty() &&
"Lowering should have eliminated any uses of the intrinsic call!");
CI->getParent()->getInstList().erase(CI);
Index: llvm/lib/VMCore/ModuleProvider.cpp
diff -u llvm/lib/VMCore/ModuleProvider.cpp:1.8 llvm/lib/VMCore/ModuleProvider.cpp:1.8.4.1
--- llvm/lib/VMCore/ModuleProvider.cpp:1.8 Fri Nov 21 14:23:48 2003
+++ llvm/lib/VMCore/ModuleProvider.cpp Mon Mar 1 17:58:16 2004
@@ -24,15 +24,3 @@
ModuleProvider::~ModuleProvider() {
delete TheModule;
}
-
-/// materializeFunction - make sure the given function is fully read.
-///
-Module* ModuleProvider::materializeModule() {
- assert(TheModule && "Attempting to materialize an invalid module!");
-
- for (Module::iterator i = TheModule->begin(), e = TheModule->end();
- i != e; ++i)
- materializeFunction(i);
-
- return TheModule;
-}
Index: llvm/lib/VMCore/Pass.cpp
diff -u llvm/lib/VMCore/Pass.cpp:1.54 llvm/lib/VMCore/Pass.cpp:1.54.4.1
--- llvm/lib/VMCore/Pass.cpp:1.54 Fri Nov 21 14:23:48 2003
+++ llvm/lib/VMCore/Pass.cpp Mon Mar 1 17:58:16 2004
@@ -91,8 +91,6 @@
void FunctionPassManager::add(FunctionPass *P) { PM->add(P); }
void FunctionPassManager::add(ImmutablePass *IP) { PM->add(IP); }
bool FunctionPassManager::run(Function &F) {
- Function *mF = MP->getModule()->getNamedFunction(F.getName());
- assert((&F == mF) && "ModuleProvider does not contain this function!");
MP->materializeFunction(&F);
return PM->run(F);
}
@@ -135,22 +133,31 @@
}
void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
- Pass *P, Annotable *V) {
+ Pass *P, Module *M) {
if (PassDebugging >= Executions) {
std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '"
<< P->getPassName();
- if (V) {
- std::cerr << "' on ";
+ if (M) std::cerr << "' on Module '" << M->getModuleIdentifier() << "'\n";
+ std::cerr << "'...\n";
+ }
+}
- if (dynamic_cast<Module*>(V)) {
- std::cerr << "Module\n"; return;
- } else if (Function *F = dynamic_cast<Function*>(V))
- std::cerr << "Function '" << F->getName();
- else if (BasicBlock *BB = dynamic_cast<BasicBlock*>(V))
- std::cerr << "BasicBlock '" << BB->getName();
- else if (Value *Val = dynamic_cast<Value*>(V))
- std::cerr << typeid(*Val).name() << " '" << Val->getName();
- }
+void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
+ Pass *P, Function *F) {
+ if (PassDebugging >= Executions) {
+ std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '"
+ << P->getPassName();
+ if (F) std::cerr << "' on Function '" << F->getName();
+ std::cerr << "'...\n";
+ }
+}
+
+void PMDebug::PrintPassInformation(unsigned Depth, const char *Action,
+ Pass *P, BasicBlock *BB) {
+ if (PassDebugging >= Executions) {
+ std::cerr << (void*)P << std::string(Depth*2+1, ' ') << Action << " '"
+ << P->getPassName();
+ if (BB) std::cerr << "' on BasicBlock '" << BB->getName();
std::cerr << "'...\n";
}
}
@@ -184,7 +191,7 @@
std::cerr << std::string(Offset*2, ' ') << getPassName() << "\n";
}
-// getPassName - Use C++ RTTI to get a SOMEWHAT intelligable name for the pass.
+// getPassName - Use C++ RTTI to get a SOMEWHAT intelligible name for the pass.
//
const char *Pass::getPassName() const {
if (const PassInfo *PI = getPassInfo())
Index: llvm/lib/VMCore/PassManagerT.h
diff -u llvm/lib/VMCore/PassManagerT.h:1.46 llvm/lib/VMCore/PassManagerT.h:1.46.4.1
--- llvm/lib/VMCore/PassManagerT.h:1.46 Tue Nov 11 16:41:34 2003
+++ llvm/lib/VMCore/PassManagerT.h Mon Mar 1 17:58:16 2004
@@ -31,8 +31,6 @@
namespace llvm {
-class Annotable;
-
//===----------------------------------------------------------------------===//
// Pass debugging information. Often it is useful to find out what pass is
// running when a crash occurs in a utility. When this library is compiled with
@@ -75,7 +73,9 @@
}
static void PrintArgumentInformation(const Pass *P);
- static void PrintPassInformation(unsigned,const char*,Pass *, Annotable *);
+ static void PrintPassInformation(unsigned,const char*,Pass *, Module *);
+ static void PrintPassInformation(unsigned,const char*,Pass *, Function *);
+ static void PrintPassInformation(unsigned,const char*,Pass *, BasicBlock *);
static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
const std::vector<AnalysisID> &);
};
@@ -216,8 +216,7 @@
for (unsigned i = 0, e = Passes.size(); i < e; ++i) {
PassClass *P = Passes[i];
- PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P,
- (Annotable*)M);
+ PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, M);
// Get information about what analyses the pass uses...
AnalysisUsage AnUsage;
@@ -259,8 +258,7 @@
P->getPassName() + "'");
if (Changed)
- PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P,
- (Annotable*)M);
+ PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P, M);
PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P,
AnUsage.getPreservedSet());
@@ -301,8 +299,7 @@
std::vector<Pass*> &DeadPass = LastUserOf[P];
for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end();
I != E; ++I) {
- PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I,
- (Annotable*)M);
+ PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, M);
(*I)->releaseMemory();
}
Index: llvm/lib/VMCore/SlotCalculator.cpp
diff -u llvm/lib/VMCore/SlotCalculator.cpp:1.50 llvm/lib/VMCore/SlotCalculator.cpp:1.50.2.1
--- llvm/lib/VMCore/SlotCalculator.cpp:1.50 Tue Jan 20 13:50:23 2004
+++ llvm/lib/VMCore/SlotCalculator.cpp Mon Mar 1 17:58:16 2004
@@ -146,7 +146,8 @@
TypePlane &Plane = Table[plane];
unsigned FirstNonStringID = 0;
for (unsigned i = 0, e = Plane.size(); i != e; ++i)
- if (cast<ConstantArray>(Plane[i])->isString()) {
+ if (isa<ConstantAggregateZero>(Plane[i]) ||
+ cast<ConstantArray>(Plane[i])->isString()) {
// Check to see if we have to shuffle this string around. If not,
// don't do anything.
if (i != FirstNonStringID) {
@@ -381,6 +382,8 @@
/// getOrCreateCompactionTableSlot - This method is used to build up the initial
/// approximation of the compaction table.
unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Value *V) {
+ if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(V))
+ V = CPR->getValue();
std::map<const Value*, unsigned>::iterator I =
CompactionNodeMap.lower_bound(V);
if (I != CompactionNodeMap.end() && I->first == V)
Index: llvm/lib/VMCore/Type.cpp
diff -u llvm/lib/VMCore/Type.cpp:1.87 llvm/lib/VMCore/Type.cpp:1.87.2.1
--- llvm/lib/VMCore/Type.cpp:1.87 Tue Dec 30 21:19:37 2003
+++ llvm/lib/VMCore/Type.cpp Mon Mar 1 17:58:16 2004
@@ -18,7 +18,6 @@
#include "Support/StringExtras.h"
#include "Support/STLExtras.h"
#include <algorithm>
-
using namespace llvm;
// DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are
@@ -27,6 +26,7 @@
//
//#define DEBUG_MERGE_TYPES 1
+AbstractTypeUser::~AbstractTypeUser() {}
//===----------------------------------------------------------------------===//
// Type Class Implementation
@@ -43,7 +43,7 @@
static std::map<const Type*, std::string> AbstractTypeDescriptions;
Type::Type(const std::string &name, PrimitiveID id)
- : Value(Type::TypeTy, Value::TypeVal), ForwardType(0) {
+ : Value(Type::TypeTy, Value::TypeVal), RefCount(0), ForwardType(0) {
if (!name.empty())
ConcreteTypeDescriptions[this] = name;
ID = id;
@@ -190,15 +190,14 @@
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
Result = getTypeDescription(FTy->getReturnType(), TypeStack) + " (";
- for (FunctionType::ParamTypes::const_iterator
- I = FTy->getParamTypes().begin(),
- E = FTy->getParamTypes().end(); I != E; ++I) {
- if (I != FTy->getParamTypes().begin())
+ for (FunctionType::param_iterator I = FTy->param_begin(),
+ E = FTy->param_end(); I != E; ++I) {
+ if (I != FTy->param_begin())
Result += ", ";
Result += getTypeDescription(*I, TypeStack);
}
if (FTy->isVarArg()) {
- if (!FTy->getParamTypes().empty()) Result += ", ";
+ if (FTy->getNumParams()) Result += ", ";
Result += "...";
}
Result += ")";
@@ -207,10 +206,9 @@
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
Result = "{ ";
- for (StructType::ElementTypes::const_iterator
- I = STy->getElementTypes().begin(),
- E = STy->getElementTypes().end(); I != E; ++I) {
- if (I != STy->getElementTypes().begin())
+ for (StructType::element_iterator I = STy->element_begin(),
+ E = STy->element_end(); I != E; ++I) {
+ if (I != STy->element_begin())
Result += ", ";
Result += getTypeDescription(*I, TypeStack);
}
@@ -263,7 +261,7 @@
bool StructType::indexValid(const Value *V) const {
// Structure indexes require unsigned integer constants.
if (const ConstantUInt *CU = dyn_cast<ConstantUInt>(V))
- return CU->getValue() < ETypes.size();
+ return CU->getValue() < ContainedTys.size();
return false;
}
@@ -273,9 +271,9 @@
const Type *StructType::getTypeAtIndex(const Value *V) const {
assert(isa<Constant>(V) && "Structure index must be a constant!!");
unsigned Idx = cast<ConstantUInt>(V)->getValue();
- assert(Idx < ETypes.size() && "Structure index out of range!");
+ assert(Idx < ContainedTys.size() && "Structure index out of range!");
assert(indexValid(V) && "Invalid structure index!"); // Duplicate check
- return ETypes[Idx];
+ return ContainedTys[Idx];
}
@@ -360,12 +358,13 @@
FunctionType::FunctionType(const Type *Result,
const std::vector<const Type*> &Params,
bool IsVarArgs) : DerivedType(FunctionTyID),
- ResultType(PATypeHandle(Result, this)),
- isVarArgs(IsVarArgs) {
+ isVarArgs(IsVarArgs) {
bool isAbstract = Result->isAbstract();
- ParamTys.reserve(Params.size());
- for (unsigned i = 0; i < Params.size(); ++i) {
- ParamTys.push_back(PATypeHandle(Params[i], this));
+ ContainedTys.reserve(Params.size()+1);
+ ContainedTys.push_back(PATypeHandle(Result, this));
+
+ for (unsigned i = 0; i != Params.size(); ++i) {
+ ContainedTys.push_back(PATypeHandle(Params[i], this));
isAbstract |= Params[i]->isAbstract();
}
@@ -375,11 +374,11 @@
StructType::StructType(const std::vector<const Type*> &Types)
: CompositeType(StructTyID) {
- ETypes.reserve(Types.size());
+ ContainedTys.reserve(Types.size());
bool isAbstract = false;
for (unsigned i = 0; i < Types.size(); ++i) {
assert(Types[i] != Type::VoidTy && "Void type in method prototype!!");
- ETypes.push_back(PATypeHandle(Types[i], this));
+ ContainedTys.push_back(PATypeHandle(Types[i], this));
isAbstract |= Types[i]->isAbstract();
}
@@ -407,44 +406,22 @@
#endif
}
-
-// getAlwaysOpaqueTy - This function returns an opaque type. It doesn't matter
-// _which_ opaque type it is, but the opaque type must never get resolved.
-//
-static Type *getAlwaysOpaqueTy() {
- static Type *AlwaysOpaqueTy = OpaqueType::get();
- static PATypeHolder Holder(AlwaysOpaqueTy);
- return AlwaysOpaqueTy;
-}
-
-
-//===----------------------------------------------------------------------===//
-// dropAllTypeUses methods - These methods eliminate any possibly recursive type
-// references from a derived type. The type must remain abstract, so we make
-// sure to use an always opaque type as an argument.
-//
-
-void FunctionType::dropAllTypeUses() {
- ResultType = getAlwaysOpaqueTy();
- ParamTys.clear();
-}
-
-void ArrayType::dropAllTypeUses() {
- ElementType = getAlwaysOpaqueTy();
-}
-
-void StructType::dropAllTypeUses() {
- ETypes.clear();
- ETypes.push_back(PATypeHandle(getAlwaysOpaqueTy(), this));
-}
-
-void PointerType::dropAllTypeUses() {
- ElementType = getAlwaysOpaqueTy();
+// dropAllTypeUses - When this (abstract) type is resolved to be equal to
+// another (more concrete) type, we must eliminate all references to other
+// types, to avoid some circular reference problems.
+void DerivedType::dropAllTypeUses() {
+ if (!ContainedTys.empty()) {
+ while (ContainedTys.size() > 1)
+ ContainedTys.pop_back();
+
+ // The type must stay abstract. To do this, we insert a pointer to a type
+ // that will never get resolved, thus will always be abstract.
+ static Type *AlwaysOpaqueTy = OpaqueType::get();
+ static PATypeHolder Holder(AlwaysOpaqueTy);
+ ContainedTys[0] = AlwaysOpaqueTy;
+ }
}
-
-
-
// isTypeAbstract - This is a recursive function that walks a type hierarchy
// calculating whether or not a type is abstract. Worst case it will have to do
// a lot of traversing if you have some whacko opaque types, but in most cases,
@@ -467,7 +444,7 @@
// one!
for (Type::subtype_iterator I = subtype_begin(), E = subtype_end();
I != E; ++I)
- if (const_cast<Type*>(*I)->isTypeAbstract()) {
+ if (const_cast<Type*>(I->get())->isTypeAbstract()) {
setAbstract(true); // Restore the abstract bit.
return true; // This type is abstract if subtype is abstract!
}
@@ -513,12 +490,10 @@
return TypesEqual(PTy->getElementType(),
cast<PointerType>(Ty2)->getElementType(), EqTypes);
} else if (const StructType *STy = dyn_cast<StructType>(Ty)) {
- const StructType::ElementTypes &STyE = STy->getElementTypes();
- const StructType::ElementTypes &STyE2 =
- cast<StructType>(Ty2)->getElementTypes();
- if (STyE.size() != STyE2.size()) return false;
- for (unsigned i = 0, e = STyE.size(); i != e; ++i)
- if (!TypesEqual(STyE[i], STyE2[i], EqTypes))
+ const StructType *STy2 = cast<StructType>(Ty2);
+ if (STy->getNumElements() != STy2->getNumElements()) return false;
+ for (unsigned i = 0, e = STy2->getNumElements(); i != e; ++i)
+ if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes))
return false;
return true;
} else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
@@ -528,13 +503,11 @@
} else if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
const FunctionType *FTy2 = cast<FunctionType>(Ty2);
if (FTy->isVarArg() != FTy2->isVarArg() ||
- FTy->getParamTypes().size() != FTy2->getParamTypes().size() ||
+ FTy->getNumParams() != FTy2->getNumParams() ||
!TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes))
return false;
- const FunctionType::ParamTypes &FTyP = FTy->getParamTypes();
- const FunctionType::ParamTypes &FTy2P = FTy2->getParamTypes();
- for (unsigned i = 0, e = FTyP.size(); i != e; ++i)
- if (!TypesEqual(FTyP[i], FTy2P[i], EqTypes))
+ for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i)
+ if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes))
return false;
return true;
} else {
@@ -548,6 +521,38 @@
return TypesEqual(Ty, Ty2, EqTypes);
}
+// TypeHasCycleThrough - Return true there is a path from CurTy to TargetTy in
+// the type graph. We know that Ty is an abstract type, so if we ever reach a
+// non-abstract type, we know that we don't need to search the subgraph.
+static bool TypeHasCycleThrough(const Type *TargetTy, const Type *CurTy,
+ std::set<const Type*> &VisitedTypes) {
+ if (TargetTy == CurTy) return true;
+ if (!CurTy->isAbstract()) return false;
+
+ std::set<const Type*>::iterator VTI = VisitedTypes.lower_bound(CurTy);
+ if (VTI != VisitedTypes.end() && *VTI == CurTy)
+ return false;
+ VisitedTypes.insert(VTI, CurTy);
+
+ for (Type::subtype_iterator I = CurTy->subtype_begin(),
+ E = CurTy->subtype_end(); I != E; ++I)
+ if (TypeHasCycleThrough(TargetTy, *I, VisitedTypes))
+ return true;
+ return false;
+}
+
+
+/// TypeHasCycleThroughItself - Return true if the specified type has a cycle
+/// back to itself.
+static bool TypeHasCycleThroughItself(const Type *Ty) {
+ assert(Ty->isAbstract() && "This code assumes that Ty was abstract!");
+ std::set<const Type*> VisitedTypes;
+ for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
+ I != E; ++I)
+ if (TypeHasCycleThrough(Ty, *I, VisitedTypes))
+ return true;
+ return false;
+}
//===----------------------------------------------------------------------===//
@@ -556,15 +561,18 @@
// TypeMap - Make sure that only one instance of a particular type may be
// created on any given run of the compiler... note that this involves updating
-// our map if an abstract type gets refined somehow...
+// our map if an abstract type gets refined somehow.
//
namespace llvm {
template<class ValType, class TypeClass>
class TypeMap {
- typedef std::map<ValType, PATypeHolder> MapTy;
- MapTy Map;
+ std::map<ValType, PATypeHolder> Map;
+
+ /// TypesByHash - Keep track of each type by its structure hash value.
+ ///
+ std::multimap<unsigned, PATypeHolder> TypesByHash;
public:
- typedef typename MapTy::iterator iterator;
+ typedef typename std::map<ValType, PATypeHolder>::iterator iterator;
~TypeMap() { print("ON EXIT"); }
inline TypeClass *get(const ValType &V) {
@@ -572,58 +580,65 @@
return I != Map.end() ? cast<TypeClass>((Type*)I->second.get()) : 0;
}
- inline void add(const ValType &V, TypeClass *T) {
- Map.insert(std::make_pair(V, T));
+ inline void add(const ValType &V, TypeClass *Ty) {
+ Map.insert(std::make_pair(V, Ty));
+
+ // If this type has a cycle, remember it.
+ TypesByHash.insert(std::make_pair(ValType::hashTypeStructure(Ty), Ty));
print("add");
}
- iterator getEntryForType(TypeClass *Ty) {
- iterator I = Map.find(ValType::get(Ty));
- if (I == Map.end()) print("ERROR!");
- assert(I != Map.end() && "Didn't find type entry!");
- assert(I->second.get() == (const Type*)Ty && "Type entry wrong?");
- return I;
+ void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
+ std::multimap<unsigned, PATypeHolder>::iterator I =
+ TypesByHash.lower_bound(Hash);
+ while (I->second != Ty) {
+ ++I;
+ assert(I != TypesByHash.end() && I->first == Hash);
+ }
+ TypesByHash.erase(I);
}
/// finishRefinement - This method is called after we have updated an existing
/// type with its new components. We must now either merge the type away with
/// some other type or reinstall it in the map with it's new configuration.
/// The specified iterator tells us what the type USED to look like.
- void finishRefinement(iterator TyIt) {
+ void finishRefinement(TypeClass *Ty, const DerivedType *OldType,
+ const Type *NewType) {
+ assert((Ty->isAbstract() || !OldType->isAbstract()) &&
+ "Refining a non-abstract type!");
+#ifdef DEBUG_MERGE_TYPES
+ std::cerr << "refineAbstractTy(" << (void*)OldType << "[" << *OldType
+ << "], " << (void*)NewType << " [" << *NewType << "])\n";
+#endif
+
// Make a temporary type holder for the type so that it doesn't disappear on
// us when we erase the entry from the map.
- PATypeHolder TyHolder = TyIt->second;
- TypeClass *Ty = cast<TypeClass>((Type*)TyHolder.get());
+ PATypeHolder TyHolder = Ty;
// The old record is now out-of-date, because one of the children has been
// updated. Remove the obsolete entry from the map.
- Map.erase(TyIt);
+ Map.erase(ValType::get(Ty));
- // Determine whether there is a cycle through the type graph which passes
- // back through this type. Other cycles are ok though.
- bool HasTypeCycle = false;
- {
- std::set<const Type*> VisitedTypes;
- for (Type::subtype_iterator I = Ty->subtype_begin(),
- E = Ty->subtype_end(); I != E; ++I) {
- for (df_ext_iterator<const Type *, std::set<const Type*> >
- DFI = df_ext_begin(*I, VisitedTypes),
- E = df_ext_end(*I, VisitedTypes); DFI != E; ++DFI)
- if (*DFI == Ty) {
- HasTypeCycle = true;
- goto FoundCycle;
- }
+ // Remember the structural hash for the type before we start hacking on it,
+ // in case we need it later. Also, check to see if the type HAD a cycle
+ // through it, if so, we know it will when we hack on it.
+ unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
+
+ // Find the type element we are refining... and change it now!
+ for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
+ if (Ty->ContainedTys[i] == OldType) {
+ Ty->ContainedTys[i].removeUserFromConcrete();
+ Ty->ContainedTys[i] = NewType;
}
- }
- FoundCycle:
-
- ValType Key = ValType::get(Ty);
+ unsigned TypeHash = ValType::hashTypeStructure(Ty);
+
// If there are no cycles going through this node, we can do a simple,
// efficient lookup in the map, instead of an inefficient nasty linear
// lookup.
- if (!HasTypeCycle) {
- iterator I = Map.find(Key);
+ bool TypeHasCycle = Ty->isAbstract() && TypeHasCycleThroughItself(Ty);
+ if (!TypeHasCycle) {
+ iterator I = Map.find(ValType::get(Ty));
if (I != Map.end()) {
// We already have this type in the table. Get rid of the newly refined
// type.
@@ -631,6 +646,7 @@
TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
// Refined to a different type altogether?
+ RemoveFromTypesByHash(TypeHash, Ty);
Ty->refineAbstractTypeTo(NewTy);
return;
}
@@ -640,20 +656,46 @@
// structurally identical to the newly refined type. If so, this type
// gets refined to the pre-existing type.
//
- for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
- if (TypesEqual(Ty, I->second)) {
- assert(Ty->isAbstract() && "Replacing a non-abstract type?");
- TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
-
- // Refined to a different type altogether?
- Ty->refineAbstractTypeTo(NewTy);
- return;
+ std::multimap<unsigned, PATypeHolder>::iterator I,E, Entry;
+ tie(I, E) = TypesByHash.equal_range(TypeHash);
+ Entry = E;
+ for (; I != E; ++I) {
+ if (I->second != Ty) {
+ if (TypesEqual(Ty, I->second)) {
+ assert(Ty->isAbstract() && "Replacing a non-abstract type?");
+ TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
+
+ if (Entry == E) {
+ // Find the location of Ty in the TypesByHash structure.
+ while (I->second != Ty) {
+ ++I;
+ assert(I != E && "Structure doesn't contain type??");
+ }
+ Entry = I;
+ }
+
+ TypesByHash.erase(Entry);
+ Ty->refineAbstractTypeTo(NewTy);
+ return;
+ }
+ } else {
+ // Remember the position of
+ Entry = I;
}
+ }
+ }
+
+ // If we succeeded, we need to insert the type into the cycletypes table.
+ // There are several cases here, depending on whether the original type
+ // had the same hash code and was itself cyclic.
+ if (TypeHash != OldTypeHash) {
+ RemoveFromTypesByHash(OldTypeHash, Ty);
+ TypesByHash.insert(std::make_pair(TypeHash, Ty));
}
// If there is no existing type of the same structure, we reinsert an
// updated record into the map.
- Map.insert(std::make_pair(Key, Ty));
+ Map.insert(std::make_pair(ValType::get(Ty), Ty));
// If the type is currently thought to be abstract, rescan all of our
// subtypes to see if the type has just become concrete!
@@ -666,23 +708,12 @@
}
}
- void remove(const ValType &OldVal) {
- iterator I = Map.find(OldVal);
- assert(I != Map.end() && "TypeMap::remove, element not found!");
- Map.erase(I);
- }
-
- void remove(iterator I) {
- assert(I != Map.end() && "Cannot remove invalid iterator pointer!");
- Map.erase(I);
- }
-
void print(const char *Arg) const {
#ifdef DEBUG_MERGE_TYPES
std::cerr << "TypeMap<>::" << Arg << " table contents:\n";
unsigned i = 0;
- for (typename MapTy::const_iterator I = Map.begin(), E = Map.end();
- I != E; ++I)
+ for (typename std::map<ValType, PATypeHolder>::const_iterator I
+ = Map.begin(), E = Map.end(); I != E; ++I)
std::cerr << " " << (++i) << ". " << (void*)I->second.get() << " "
<< *I->second.get() << "\n";
#endif
@@ -713,6 +744,10 @@
static FunctionValType get(const FunctionType *FT);
+ static unsigned hashTypeStructure(const FunctionType *FT) {
+ return FT->getNumParams()*2+FT->isVarArg();
+ }
+
// Subclass should override this... to update self as usual
void doRefinement(const DerivedType *OldType, const Type *NewType) {
if (RetTy == OldType) RetTy = NewType;
@@ -736,8 +771,8 @@
FunctionValType FunctionValType::get(const FunctionType *FT) {
// Build up a FunctionValType
std::vector<const Type *> ParamTypes;
- ParamTypes.reserve(FT->getParamTypes().size());
- for (unsigned i = 0, e = FT->getParamTypes().size(); i != e; ++i)
+ ParamTypes.reserve(FT->getNumParams());
+ for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
ParamTypes.push_back(FT->getParamType(i));
return FunctionValType(FT->getReturnType(), ParamTypes, FT->isVarArg());
}
@@ -773,6 +808,10 @@
return ArrayValType(AT->getElementType(), AT->getNumElements());
}
+ static unsigned hashTypeStructure(const ArrayType *AT) {
+ return AT->getNumElements();
+ }
+
// Subclass should override this... to update self as usual
void doRefinement(const DerivedType *OldType, const Type *NewType) {
assert(ValTy == OldType);
@@ -818,13 +857,17 @@
static StructValType get(const StructType *ST) {
std::vector<const Type *> ElTypes;
- ElTypes.reserve(ST->getElementTypes().size());
- for (unsigned i = 0, e = ST->getElementTypes().size(); i != e; ++i)
- ElTypes.push_back(ST->getElementTypes()[i]);
+ ElTypes.reserve(ST->getNumElements());
+ for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
+ ElTypes.push_back(ST->getElementType(i));
return StructValType(ElTypes);
}
+ static unsigned hashTypeStructure(const StructType *ST) {
+ return ST->getNumElements();
+ }
+
// Subclass should override this... to update self as usual
void doRefinement(const DerivedType *OldType, const Type *NewType) {
for (unsigned i = 0; i < ElTypes.size(); ++i)
@@ -871,6 +914,10 @@
return PointerValType(PT->getElementType());
}
+ static unsigned hashTypeStructure(const PointerType *PT) {
+ return 0;
+ }
+
// Subclass should override this... to update self as usual
void doRefinement(const DerivedType *OldType, const Type *NewType) {
assert(ValTy == OldType);
@@ -901,14 +948,6 @@
return PT;
}
-namespace llvm {
-void debug_type_tables() {
- FunctionTypes.dump();
- ArrayTypes.dump();
- StructTypes.dump();
- PointerTypes.dump();
-}
-}
//===----------------------------------------------------------------------===//
// Derived Type Refinement Functions
@@ -938,7 +977,7 @@
<< *this << "][" << i << "] User = " << U << "\n";
#endif
- if (AbstractTypeUsers.empty() && RefCount == 0 && isAbstract()) {
+ if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) {
#ifdef DEBUG_MERGE_TYPES
std::cerr << "DELETEing unused abstract type: <" << *this
<< ">[" << (void*)this << "]" << "\n";
@@ -1044,30 +1083,7 @@
//
void FunctionType::refineAbstractType(const DerivedType *OldType,
const Type *NewType) {
- assert((isAbstract() || !OldType->isAbstract()) &&
- "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
- std::cerr << "FunctionTy::refineAbstractTy(" << (void*)OldType << "["
- << *OldType << "], " << (void*)NewType << " ["
- << *NewType << "])\n";
-#endif
-
- // Look up our current type map entry..
- TypeMap<FunctionValType, FunctionType>::iterator TMI =
- FunctionTypes.getEntryForType(this);
-
- // Find the type element we are refining...
- if (ResultType == OldType) {
- ResultType.removeUserFromConcrete();
- ResultType = NewType;
- }
- for (unsigned i = 0, e = ParamTys.size(); i != e; ++i)
- if (ParamTys[i] == OldType) {
- ParamTys[i].removeUserFromConcrete();
- ParamTys[i] = NewType;
- }
-
- FunctionTypes.finishRefinement(TMI);
+ FunctionTypes.finishRefinement(this, OldType, NewType);
}
void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1081,23 +1097,7 @@
//
void ArrayType::refineAbstractType(const DerivedType *OldType,
const Type *NewType) {
- assert((isAbstract() || !OldType->isAbstract()) &&
- "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
- std::cerr << "ArrayTy::refineAbstractTy(" << (void*)OldType << "["
- << *OldType << "], " << (void*)NewType << " ["
- << *NewType << "])\n";
-#endif
-
- // Look up our current type map entry..
- TypeMap<ArrayValType, ArrayType>::iterator TMI =
- ArrayTypes.getEntryForType(this);
-
- assert(getElementType() == OldType);
- ElementType.removeUserFromConcrete();
- ElementType = NewType;
-
- ArrayTypes.finishRefinement(TMI);
+ ArrayTypes.finishRefinement(this, OldType, NewType);
}
void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1111,27 +1111,7 @@
//
void StructType::refineAbstractType(const DerivedType *OldType,
const Type *NewType) {
- assert((isAbstract() || !OldType->isAbstract()) &&
- "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
- std::cerr << "StructTy::refineAbstractTy(" << (void*)OldType << "["
- << *OldType << "], " << (void*)NewType << " ["
- << *NewType << "])\n";
-#endif
-
- // Look up our current type map entry..
- TypeMap<StructValType, StructType>::iterator TMI =
- StructTypes.getEntryForType(this);
-
- for (int i = ETypes.size()-1; i >= 0; --i)
- if (ETypes[i] == OldType) {
- ETypes[i].removeUserFromConcrete();
-
- // Update old type to new type in the array...
- ETypes[i] = NewType;
- }
-
- StructTypes.finishRefinement(TMI);
+ StructTypes.finishRefinement(this, OldType, NewType);
}
void StructType::typeBecameConcrete(const DerivedType *AbsTy) {
@@ -1144,23 +1124,7 @@
//
void PointerType::refineAbstractType(const DerivedType *OldType,
const Type *NewType) {
- assert((isAbstract() || !OldType->isAbstract()) &&
- "Refining a non-abstract type!");
-#ifdef DEBUG_MERGE_TYPES
- std::cerr << "PointerTy::refineAbstractTy(" << (void*)OldType << "["
- << *OldType << "], " << (void*)NewType << " ["
- << *NewType << "])\n";
-#endif
-
- // Look up our current type map entry..
- TypeMap<PointerValType, PointerType>::iterator TMI =
- PointerTypes.getEntryForType(this);
-
- assert(ElementType == OldType);
- ElementType.removeUserFromConcrete();
- ElementType = NewType;
-
- PointerTypes.finishRefinement(TMI);
+ PointerTypes.finishRefinement(this, OldType, NewType);
}
void PointerType::typeBecameConcrete(const DerivedType *AbsTy) {
Index: llvm/lib/VMCore/Verifier.cpp
diff -u llvm/lib/VMCore/Verifier.cpp:1.78.2.2 llvm/lib/VMCore/Verifier.cpp:1.78.2.3
--- llvm/lib/VMCore/Verifier.cpp:1.78.2.2 Sat Feb 7 17:55:02 2004
+++ llvm/lib/VMCore/Verifier.cpp Mon Mar 1 17:58:16 2004
@@ -41,17 +41,14 @@
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/Writer.h"
+#include "llvm/Constants.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOther.h"
-#include "llvm/iOperators.h"
-#include "llvm/iMemory.h"
-#include "llvm/SymbolTable.h"
-#include "llvm/PassManager.h"
+#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
+#include "llvm/PassManager.h"
+#include "llvm/SymbolTable.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/InstVisitor.h"
@@ -389,9 +386,9 @@
// Verify that all arguments to the call match the function type...
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
- Assert2(CI.getOperand(i+1)->getType() == FTy->getParamType(i),
+ Assert3(CI.getOperand(i+1)->getType() == FTy->getParamType(i),
"Call parameter type does not match function signature!",
- CI.getOperand(i+1), FTy->getParamType(i));
+ CI.getOperand(i+1), FTy->getParamType(i), &CI);
if (Function *F = CI.getCalledFunction())
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
@@ -477,7 +474,8 @@
if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential
for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
UI != UE; ++UI)
- Assert1(*UI != (User*)&I,
+ Assert1(*UI != (User*)&I ||
+ !DS->dominates(&BB->getParent()->getEntryBlock(), BB),
"Only PHI nodes may reference their own value!", &I);
}
@@ -551,6 +549,16 @@
case Intrinsic::va_end: NumArgs = 1; break;
case Intrinsic::va_copy: NumArgs = 1; break;
+ case Intrinsic::returnaddress:
+ case Intrinsic::frameaddress:
+ Assert1(isa<PointerType>(FT->getReturnType()),
+ "llvm.(frame|return)address must return pointers", IF);
+ Assert1(FT->getNumParams() == 1 && isa<ConstantInt>(CI.getOperand(1)),
+ "llvm.(frame|return)address require a single constant integer argument",
+ &CI);
+ NumArgs = 1;
+ break;
+
case Intrinsic::setjmp: NumArgs = 1; break;
case Intrinsic::longjmp: NumArgs = 2; break;
case Intrinsic::sigsetjmp: NumArgs = 2; break;
@@ -564,6 +572,10 @@
// Join takes a single parameter which is returned by pbr
case Intrinsic::join: NumArgs = 1; break;
+
+ case Intrinsic::memcpy: NumArgs = 4; break;
+ case Intrinsic::memmove: NumArgs = 4; break;
+ case Intrinsic::memset: NumArgs = 4; break;
case Intrinsic::alpha_ctlz: NumArgs = 1; break;
case Intrinsic::alpha_cttz: NumArgs = 1; break;
Index: llvm/lib/VMCore/iCall.cpp
diff -u llvm/lib/VMCore/iCall.cpp:1.22 llvm/lib/VMCore/iCall.cpp:1.22.4.1
--- llvm/lib/VMCore/iCall.cpp:1.22 Thu Nov 20 11:45:12 2003
+++ llvm/lib/VMCore/iCall.cpp Mon Mar 1 17:58:16 2004
@@ -31,14 +31,13 @@
Operands.reserve(1+params.size());
Operands.push_back(Use(Func, this));
- const FunctionType *MTy =
+ const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- const FunctionType::ParamTypes &PL = MTy->getParamTypes();
- assert(params.size() == PL.size() ||
- (MTy->isVarArg() && params.size() > PL.size()) &&
+ assert((params.size() == FTy->getNumParams() ||
+ (FTy->isVarArg() && params.size() > FTy->getNumParams())) &&
"Calling a function with bad signature");
- for (unsigned i = 0; i < params.size(); i++)
+ for (unsigned i = 0; i != params.size(); i++)
Operands.push_back(Use(params[i], this));
}
@@ -53,8 +52,7 @@
const FunctionType *MTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- const FunctionType::ParamTypes &PL = MTy->getParamTypes();
- assert(PL.empty() && "Calling a function with bad signature");
+ assert(MTy->getNumParams() == 0 && "Calling a function with bad signature");
}
CallInst::CallInst(Value *Func, Value* A, const std::string &Name,
@@ -68,8 +66,8 @@
const FunctionType *MTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- const FunctionType::ParamTypes &PL = MTy->getParamTypes();
- assert(PL.size() == 1 || (MTy->isVarArg() && PL.empty()) &&
+ assert((MTy->getNumParams() == 1 ||
+ (MTy->isVarArg() && MTy->getNumParams() == 0)) &&
"Calling a function with bad signature");
Operands.push_back(Use(A, this));
}
@@ -115,9 +113,8 @@
const FunctionType *MTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- const FunctionType::ParamTypes &PL = MTy->getParamTypes();
- assert((params.size() == PL.size()) ||
- (MTy->isVarArg() && params.size() > PL.size()) &&
+ assert((params.size() == MTy->getNumParams()) ||
+ (MTy->isVarArg() && params.size() > MTy->getNumParams()) &&
"Calling a function with bad signature");
for (unsigned i = 0; i < params.size(); i++)
@@ -138,9 +135,8 @@
const FunctionType *MTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- const FunctionType::ParamTypes &PL = MTy->getParamTypes();
- assert((params.size() == PL.size()) ||
- (MTy->isVarArg() && params.size() > PL.size()) &&
+ assert((params.size() == MTy->getNumParams()) ||
+ (MTy->isVarArg() && params.size() > MTy->getNumParams()) &&
"Calling a function with bad signature");
for (unsigned i = 0; i < params.size(); i++)
Index: llvm/lib/VMCore/iOperators.cpp
diff -u llvm/lib/VMCore/iOperators.cpp:1.25 llvm/lib/VMCore/iOperators.cpp:1.25.4.1
--- llvm/lib/VMCore/iOperators.cpp:1.25 Thu Nov 20 11:45:12 2003
+++ llvm/lib/VMCore/iOperators.cpp Mon Mar 1 17:58:16 2004
@@ -78,9 +78,14 @@
BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name,
Instruction *InsertBefore) {
- return new BinaryOperator(Instruction::Sub,
- Constant::getNullValue(Op->getType()), Op,
- Op->getType(), Name, InsertBefore);
+ if (!Op->getType()->isFloatingPoint())
+ return new BinaryOperator(Instruction::Sub,
+ Constant::getNullValue(Op->getType()), Op,
+ Op->getType(), Name, InsertBefore);
+ else
+ return new BinaryOperator(Instruction::Sub,
+ ConstantFP::get(Op->getType(), -0.0), Op,
+ Op->getType(), Name, InsertBefore);
}
BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name,
@@ -98,8 +103,11 @@
bool BinaryOperator::isNeg(const Value *V) {
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
- return Bop->getOpcode() == Instruction::Sub &&
- Bop->getOperand(0) == Constant::getNullValue(Bop->getType());
+ if (Bop->getOpcode() == Instruction::Sub)
+ if (!V->getType()->isFloatingPoint())
+ return Bop->getOperand(0) == Constant::getNullValue(Bop->getType());
+ else
+ return Bop->getOperand(0) == ConstantFP::get(Bop->getType(), -0.0);
return false;
}
More information about the llvm-commits
mailing list