summaryrefslogtreecommitdiffstats
path: root/lib/VMCore
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2011-07-17 15:36:56 +0000
committerdim <dim@FreeBSD.org>2011-07-17 15:36:56 +0000
commit1176aa52646fe641a4243a246aa7f960c708a274 (patch)
treec8086addb211fa670a9d2b1038d8c2e453229755 /lib/VMCore
parentece02cd5829cea836e9365b0845a8ef042d17b0a (diff)
downloadFreeBSD-src-1176aa52646fe641a4243a246aa7f960c708a274.zip
FreeBSD-src-1176aa52646fe641a4243a246aa7f960c708a274.tar.gz
Vendor import of llvm trunk r135360:
http://llvm.org/svn/llvm-project/llvm/trunk@135360
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/AsmWriter.cpp535
-rw-r--r--lib/VMCore/Attributes.cpp2
-rw-r--r--lib/VMCore/AutoUpgrade.cpp1286
-rw-r--r--lib/VMCore/BasicBlock.cpp40
-rw-r--r--lib/VMCore/CMakeLists.txt1
-rw-r--r--lib/VMCore/ConstantFold.cpp91
-rw-r--r--lib/VMCore/ConstantFold.h8
-rw-r--r--lib/VMCore/Constants.cpp476
-rw-r--r--lib/VMCore/ConstantsContext.h146
-rw-r--r--lib/VMCore/Core.cpp113
-rw-r--r--lib/VMCore/DebugLoc.cpp32
-rw-r--r--lib/VMCore/Function.cpp27
-rw-r--r--lib/VMCore/Globals.cpp58
-rw-r--r--lib/VMCore/IRBuilder.cpp30
-rw-r--r--lib/VMCore/InlineAsm.cpp4
-rw-r--r--lib/VMCore/Instruction.cpp44
-rw-r--r--lib/VMCore/Instructions.cpp305
-rw-r--r--lib/VMCore/LLVMContext.cpp4
-rw-r--r--lib/VMCore/LLVMContextImpl.cpp41
-rw-r--r--lib/VMCore/LLVMContextImpl.h86
-rw-r--r--lib/VMCore/Metadata.cpp1
-rw-r--r--lib/VMCore/Module.cpp186
-rw-r--r--lib/VMCore/Type.cpp1239
-rw-r--r--lib/VMCore/TypeSymbolTable.cpp169
-rw-r--r--lib/VMCore/TypesContext.h426
-rw-r--r--lib/VMCore/Use.cpp8
-rw-r--r--lib/VMCore/User.cpp12
-rw-r--r--lib/VMCore/Value.cpp44
-rw-r--r--lib/VMCore/ValueSymbolTable.cpp2
-rw-r--r--lib/VMCore/ValueTypes.cpp1
-rw-r--r--lib/VMCore/Verifier.cpp148
31 files changed, 1372 insertions, 4193 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 844284d..94794c3 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -26,13 +26,11 @@
#include "llvm/Operator.h"
#include "llvm/Module.h"
#include "llvm/ValueSymbolTable.h"
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CFG.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
@@ -42,11 +40,6 @@
#include <cctype>
using namespace llvm;
-static cl::opt<bool>
-EnableDebugInfoComment("enable-debug-info-comment", cl::Hidden,
- cl::desc("Enable debug info comments"));
-
-
// Make virtual table appear in this compilation unit.
AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {}
@@ -140,60 +133,60 @@ static void PrintLLVMName(raw_ostream &OS, const Value *V) {
// TypePrinting Class: Type printing machinery
//===----------------------------------------------------------------------===//
-static DenseMap<const Type *, std::string> &getTypeNamesMap(void *M) {
- return *static_cast<DenseMap<const Type *, std::string>*>(M);
-}
-
-void TypePrinting::clear() {
- getTypeNamesMap(TypeNames).clear();
-}
+/// TypePrinting - Type printing machinery.
+namespace {
+class TypePrinting {
+ TypePrinting(const TypePrinting &); // DO NOT IMPLEMENT
+ void operator=(const TypePrinting&); // DO NOT IMPLEMENT
+public:
-bool TypePrinting::hasTypeName(const Type *Ty) const {
- return getTypeNamesMap(TypeNames).count(Ty);
-}
+ /// NamedTypes - The named types that are used by the current module.
+ std::vector<StructType*> NamedTypes;
+
+ /// NumberedTypes - The numbered types, along with their value.
+ DenseMap<StructType*, unsigned> NumberedTypes;
+
-void TypePrinting::addTypeName(const Type *Ty, const std::string &N) {
- getTypeNamesMap(TypeNames).insert(std::make_pair(Ty, N));
-}
+ TypePrinting() {}
+ ~TypePrinting() {}
+
+ void incorporateTypes(const Module &M);
+
+ void print(Type *Ty, raw_ostream &OS);
+
+ void printStructBody(StructType *Ty, raw_ostream &OS);
+};
+} // end anonymous namespace.
-TypePrinting::TypePrinting() {
- TypeNames = new DenseMap<const Type *, std::string>();
+void TypePrinting::incorporateTypes(const Module &M) {
+ M.findUsedStructTypes(NamedTypes);
+
+ // The list of struct types we got back includes all the struct types, split
+ // the unnamed ones out to a numbering and remove the anonymous structs.
+ unsigned NextNumber = 0;
+
+ std::vector<StructType*>::iterator NextToUse = NamedTypes.begin(), I, E;
+ for (I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) {
+ StructType *STy = *I;
+
+ // Ignore anonymous types.
+ if (STy->isAnonymous())
+ continue;
+
+ if (STy->getName().empty())
+ NumberedTypes[STy] = NextNumber++;
+ else
+ *NextToUse++ = STy;
+ }
+
+ NamedTypes.erase(NextToUse, NamedTypes.end());
}
-TypePrinting::~TypePrinting() {
- delete &getTypeNamesMap(TypeNames);
-}
/// CalcTypeName - Write the specified type to the specified raw_ostream, making
/// use of type names or up references to shorten the type name where possible.
-void TypePrinting::CalcTypeName(const Type *Ty,
- SmallVectorImpl<const Type *> &TypeStack,
- raw_ostream &OS, bool IgnoreTopLevelName) {
- // Check to see if the type is named.
- if (!IgnoreTopLevelName) {
- DenseMap<const Type *, std::string> &TM = getTypeNamesMap(TypeNames);
- DenseMap<const Type *, std::string>::iterator I = TM.find(Ty);
- if (I != TM.end()) {
- OS << I->second;
- return;
- }
- }
-
- // Check to see if the Type is already on the stack...
- unsigned Slot = 0, CurSize = TypeStack.size();
- while (Slot < CurSize && TypeStack[Slot] != Ty) ++Slot; // Scan for type
-
- // 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) {
- OS << '\\' << unsigned(CurSize-Slot); // Here's the upreference
- return;
- }
-
- TypeStack.push_back(Ty); // Recursive case: Add us to the stack..
-
+void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; break;
case Type::FloatTyID: OS << "float"; break;
@@ -206,259 +199,96 @@ void TypePrinting::CalcTypeName(const Type *Ty,
case Type::X86_MMXTyID: OS << "x86_mmx"; break;
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
- break;
+ return;
case Type::FunctionTyID: {
- const FunctionType *FTy = cast<FunctionType>(Ty);
- CalcTypeName(FTy->getReturnType(), TypeStack, OS);
+ FunctionType *FTy = cast<FunctionType>(Ty);
+ print(FTy->getReturnType(), OS);
OS << " (";
for (FunctionType::param_iterator I = FTy->param_begin(),
E = FTy->param_end(); I != E; ++I) {
if (I != FTy->param_begin())
OS << ", ";
- CalcTypeName(*I, TypeStack, OS);
+ print(*I, OS);
}
if (FTy->isVarArg()) {
if (FTy->getNumParams()) OS << ", ";
OS << "...";
}
OS << ')';
- break;
+ return;
}
case Type::StructTyID: {
- const StructType *STy = cast<StructType>(Ty);
- if (STy->isPacked())
- OS << '<';
- OS << '{';
- for (StructType::element_iterator I = STy->element_begin(),
- E = STy->element_end(); I != E; ++I) {
- OS << ' ';
- CalcTypeName(*I, TypeStack, OS);
- if (llvm::next(I) == STy->element_end())
- OS << ' ';
- else
- OS << ',';
- }
- OS << '}';
- if (STy->isPacked())
- OS << '>';
- break;
+ StructType *STy = cast<StructType>(Ty);
+
+ if (STy->isAnonymous())
+ return printStructBody(STy, OS);
+
+ if (!STy->getName().empty())
+ return PrintLLVMName(OS, STy->getName(), LocalPrefix);
+
+ DenseMap<StructType*, unsigned>::iterator I = NumberedTypes.find(STy);
+ if (I != NumberedTypes.end())
+ OS << '%' << I->second;
+ else // Not enumerated, print the hex address.
+ OS << "%\"type 0x" << STy << '\"';
+ return;
}
case Type::PointerTyID: {
- const PointerType *PTy = cast<PointerType>(Ty);
- CalcTypeName(PTy->getElementType(), TypeStack, OS);
+ PointerType *PTy = cast<PointerType>(Ty);
+ print(PTy->getElementType(), OS);
if (unsigned AddressSpace = PTy->getAddressSpace())
OS << " addrspace(" << AddressSpace << ')';
OS << '*';
- break;
+ return;
}
case Type::ArrayTyID: {
- const ArrayType *ATy = cast<ArrayType>(Ty);
+ ArrayType *ATy = cast<ArrayType>(Ty);
OS << '[' << ATy->getNumElements() << " x ";
- CalcTypeName(ATy->getElementType(), TypeStack, OS);
+ print(ATy->getElementType(), OS);
OS << ']';
- break;
+ return;
}
case Type::VectorTyID: {
- const VectorType *PTy = cast<VectorType>(Ty);
+ VectorType *PTy = cast<VectorType>(Ty);
OS << "<" << PTy->getNumElements() << " x ";
- CalcTypeName(PTy->getElementType(), TypeStack, OS);
+ print(PTy->getElementType(), OS);
OS << '>';
- break;
+ return;
}
- case Type::OpaqueTyID:
- OS << "opaque";
- break;
default:
OS << "<unrecognized-type>";
- break;
+ return;
}
-
- TypeStack.pop_back(); // Remove self from stack.
}
-/// printTypeInt - The internal guts of printing out a type that has a
-/// potentially named portion.
-///
-void TypePrinting::print(const Type *Ty, raw_ostream &OS,
- bool IgnoreTopLevelName) {
- // Check to see if the type is named.
- DenseMap<const Type*, std::string> &TM = getTypeNamesMap(TypeNames);
- if (!IgnoreTopLevelName) {
- DenseMap<const Type*, std::string>::iterator I = TM.find(Ty);
- if (I != TM.end()) {
- OS << I->second;
- return;
- }
+void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
+ if (STy->isOpaque()) {
+ OS << "opaque";
+ return;
}
-
- // Otherwise we have a type that has not been named but is a derived type.
- // Carefully recurse the type hierarchy to print out any contained symbolic
- // names.
- SmallVector<const Type *, 16> TypeStack;
- std::string TypeName;
-
- raw_string_ostream TypeOS(TypeName);
- CalcTypeName(Ty, TypeStack, TypeOS, IgnoreTopLevelName);
- OS << TypeOS.str();
-
- // Cache type name for later use.
- if (!IgnoreTopLevelName)
- TM.insert(std::make_pair(Ty, TypeOS.str()));
-}
-
-namespace {
- class TypeFinder {
- // To avoid walking constant expressions multiple times and other IR
- // objects, we keep several helper maps.
- DenseSet<const Value*> VisitedConstants;
- DenseSet<const Type*> VisitedTypes;
-
- TypePrinting &TP;
- std::vector<const Type*> &NumberedTypes;
- public:
- TypeFinder(TypePrinting &tp, std::vector<const Type*> &numberedTypes)
- : TP(tp), NumberedTypes(numberedTypes) {}
-
- void Run(const Module &M) {
- // Get types from the type symbol table. This gets opaque types referened
- // only through derived named types.
- const TypeSymbolTable &ST = M.getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
- TI != E; ++TI)
- IncorporateType(TI->second);
-
- // Get types from global variables.
- for (Module::const_global_iterator I = M.global_begin(),
- E = M.global_end(); I != E; ++I) {
- IncorporateType(I->getType());
- if (I->hasInitializer())
- IncorporateValue(I->getInitializer());
- }
-
- // Get types from aliases.
- for (Module::const_alias_iterator I = M.alias_begin(),
- E = M.alias_end(); I != E; ++I) {
- IncorporateType(I->getType());
- IncorporateValue(I->getAliasee());
- }
-
- // Get types from functions.
- for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
- IncorporateType(FI->getType());
-
- for (Function::const_iterator BB = FI->begin(), E = FI->end();
- BB != E;++BB)
- for (BasicBlock::const_iterator II = BB->begin(),
- E = BB->end(); II != E; ++II) {
- const Instruction &I = *II;
- // Incorporate the type of the instruction and all its operands.
- IncorporateType(I.getType());
- for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
- OI != OE; ++OI)
- IncorporateValue(*OI);
- }
- }
- }
-
- private:
- void IncorporateType(const Type *Ty) {
- // Check to see if we're already visited this type.
- if (!VisitedTypes.insert(Ty).second)
- return;
-
- // If this is a structure or opaque type, add a name for the type.
- if (((Ty->isStructTy() && cast<StructType>(Ty)->getNumElements())
- || Ty->isOpaqueTy()) && !TP.hasTypeName(Ty)) {
- TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
- NumberedTypes.push_back(Ty);
- }
-
- // Recursively walk all contained types.
- for (Type::subtype_iterator I = Ty->subtype_begin(),
- E = Ty->subtype_end(); I != E; ++I)
- IncorporateType(*I);
- }
-
- /// IncorporateValue - This method is used to walk operand lists finding
- /// types hiding in constant expressions and other operands that won't be
- /// walked in other ways. GlobalValues, basic blocks, instructions, and
- /// inst operands are all explicitly enumerated.
- void IncorporateValue(const Value *V) {
- if (V == 0 || !isa<Constant>(V) || isa<GlobalValue>(V)) return;
-
- // Already visited?
- if (!VisitedConstants.insert(V).second)
- return;
-
- // Check this type.
- IncorporateType(V->getType());
-
- // Look in operands for types.
- const Constant *C = cast<Constant>(V);
- for (Constant::const_op_iterator I = C->op_begin(),
- E = C->op_end(); I != E;++I)
- IncorporateValue(*I);
- }
- };
-} // end anonymous namespace
-
-
-/// AddModuleTypesToPrinter - Add all of the symbolic type names for types in
-/// the specified module to the TypePrinter and all numbered types to it and the
-/// NumberedTypes table.
-static void AddModuleTypesToPrinter(TypePrinting &TP,
- std::vector<const Type*> &NumberedTypes,
- const Module *M) {
- if (M == 0) return;
-
- // If the module has a symbol table, take all global types and stuff their
- // names into the TypeNames map.
- const TypeSymbolTable &ST = M->getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = ST.begin(), E = ST.end();
- TI != E; ++TI) {
- const Type *Ty = cast<Type>(TI->second);
-
- // As a heuristic, don't insert pointer to primitive types, because
- // they are used too often to have a single useful name.
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- const Type *PETy = PTy->getElementType();
- if ((PETy->isPrimitiveType() || PETy->isIntegerTy()) &&
- !PETy->isOpaqueTy())
- continue;
+
+ if (STy->isPacked())
+ OS << '<';
+
+ if (STy->getNumElements() == 0) {
+ OS << "{}";
+ } else {
+ StructType::element_iterator I = STy->element_begin();
+ OS << "{ ";
+ print(*I++, OS);
+ for (StructType::element_iterator E = STy->element_end(); I != E; ++I) {
+ OS << ", ";
+ print(*I, OS);
}
-
- // Likewise don't insert primitives either.
- if (Ty->isIntegerTy() || Ty->isPrimitiveType())
- continue;
-
- // Get the name as a string and insert it into TypeNames.
- std::string NameStr;
- raw_string_ostream NameROS(NameStr);
- formatted_raw_ostream NameOS(NameROS);
- PrintLLVMName(NameOS, TI->first, LocalPrefix);
- NameOS.flush();
- TP.addTypeName(Ty, NameStr);
+
+ OS << " }";
}
-
- // Walk the entire module to find references to unnamed structure and opaque
- // types. This is required for correctness by opaque types (because multiple
- // uses of an unnamed opaque type needs to be referred to by the same ID) and
- // it shrinks complex recursive structure types substantially in some cases.
- TypeFinder(TP, NumberedTypes).Run(*M);
+ if (STy->isPacked())
+ OS << '>';
}
-/// 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.
-///
-void llvm::WriteTypeSymbolic(raw_ostream &OS, const Type *Ty, const Module *M) {
- TypePrinting Printer;
- std::vector<const Type*> NumberedTypes;
- AddModuleTypesToPrinter(Printer, NumberedTypes, M);
- Printer.print(Ty, OS);
-}
//===----------------------------------------------------------------------===//
// SlotTracker Class: Enumerate slot numbers for unnamed values
@@ -481,11 +311,11 @@ private:
const Function* TheFunction;
bool FunctionProcessed;
- /// mMap - The TypePlanes map for the module level data.
+ /// mMap - The slot map for the module level data.
ValueMap mMap;
unsigned mNext;
- /// fMap - The TypePlanes map for the function level data.
+ /// fMap - The slot map for the function level data.
ValueMap fMap;
unsigned fNext;
@@ -706,7 +536,7 @@ int SlotTracker::getGlobalSlot(const GlobalValue *V) {
// Check for uninitialized state and do lazy initialization.
initialize();
- // Find the type plane in the module map
+ // Find the value in the module map
ValueMap::iterator MI = mMap.find(V);
return MI == mMap.end() ? -1 : (int)MI->second;
}
@@ -716,7 +546,7 @@ int SlotTracker::getMetadataSlot(const MDNode *N) {
// Check for uninitialized state and do lazy initialization.
initialize();
- // Find the type plane in the module map
+ // Find the MDNode in the module map
mdn_iterator MI = mdnMap.find(N);
return MI == mdnMap.end() ? -1 : (int)MI->second;
}
@@ -978,7 +808,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// As a special case, print the array as a string if it is an array of
// i8 with ConstantInt values.
//
- const Type *ETy = CA->getType()->getElementType();
+ Type *ETy = CA->getType()->getElementType();
if (CA->isString()) {
Out << "c\"";
PrintEscapedString(CA->getAsString(), Out);
@@ -1035,7 +865,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
}
if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
- const Type *ETy = CP->getType()->getElementType();
+ Type *ETy = CP->getType()->getElementType();
assert(CP->getNumOperands() > 0 &&
"Number of operands for a PackedConst must be > 0");
Out << '<';
@@ -1233,8 +1063,8 @@ void llvm::WriteAsOperand(raw_ostream &Out, const Value *V,
if (Context == 0) Context = getModuleFromVal(V);
TypePrinting TypePrinter;
- std::vector<const Type*> NumberedTypes;
- AddModuleTypesToPrinter(TypePrinter, NumberedTypes, Context);
+ if (Context)
+ TypePrinter.incorporateTypes(*Context);
if (PrintType) {
TypePrinter.print(V->getType(), Out);
Out << ' ';
@@ -1251,14 +1081,14 @@ class AssemblyWriter {
const Module *TheModule;
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
- std::vector<const Type*> NumberedTypes;
public:
inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
const Module *M,
AssemblyAnnotationWriter *AAW)
: Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) {
- AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M);
+ if (M)
+ TypePrinter.incorporateTypes(*M);
}
void printMDNodeBody(const MDNode *MD);
@@ -1271,7 +1101,7 @@ public:
void writeAllMDNodes();
- void printTypeSymbolTable(const TypeSymbolTable &ST);
+ void printTypeIdentities();
void printGlobal(const GlobalVariable *GV);
void printAlias(const GlobalAlias *GV);
void printFunction(const Function *F);
@@ -1366,9 +1196,7 @@ void AssemblyWriter::printModule(const Module *M) {
Out << " ]";
}
- // Loop over the symbol table, emitting all id'd types.
- if (!M->getTypeSymbolTable().empty() || !NumberedTypes.empty()) Out << '\n';
- printTypeSymbolTable(M->getTypeSymbolTable());
+ printTypeIdentities();
// Output all globals.
if (!M->global_empty()) Out << '\n';
@@ -1401,7 +1229,25 @@ void AssemblyWriter::printModule(const Module *M) {
}
void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
- Out << "!" << NMD->getName() << " = !{";
+ Out << '!';
+ StringRef Name = NMD->getName();
+ if (Name.empty()) {
+ Out << "<empty name> ";
+ } else {
+ if (isalpha(Name[0]) || Name[0] == '-' || Name[0] == '$' ||
+ Name[0] == '.' || Name[0] == '_')
+ Out << Name[0];
+ else
+ Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F);
+ for (unsigned i = 1, e = Name.size(); i != e; ++i) {
+ unsigned char C = Name[i];
+ if (isalnum(C) || C == '-' || C == '$' || C == '.' || C == '_')
+ Out << C;
+ else
+ Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
+ }
+ }
+ Out << " = !{";
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
if (i) Out << ", ";
int Slot = Machine.getMetadataSlot(NMD->getOperand(i));
@@ -1508,7 +1354,10 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
const Constant *Aliasee = GA->getAliasee();
- if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
+ if (Aliasee == 0) {
+ TypePrinter.print(GA->getType(), Out);
+ Out << " <<NULL ALIASEE>>";
+ } else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
TypePrinter.print(GV->getType(), Out);
Out << ' ';
PrintLLVMName(Out, GV);
@@ -1534,26 +1383,40 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
Out << '\n';
}
-void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) {
+void AssemblyWriter::printTypeIdentities() {
+ if (TypePrinter.NumberedTypes.empty() &&
+ TypePrinter.NamedTypes.empty())
+ return;
+
+ Out << '\n';
+
+ // We know all the numbers that each type is used and we know that it is a
+ // dense assignment. Convert the map to an index table.
+ std::vector<StructType*> NumberedTypes(TypePrinter.NumberedTypes.size());
+ for (DenseMap<StructType*, unsigned>::iterator I =
+ TypePrinter.NumberedTypes.begin(), E = TypePrinter.NumberedTypes.end();
+ I != E; ++I) {
+ assert(I->second < NumberedTypes.size() && "Didn't get a dense numbering?");
+ NumberedTypes[I->second] = I->first;
+ }
+
// Emit all numbered types.
for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) {
Out << '%' << i << " = type ";
-
+
// Make sure we print out at least one level of the type structure, so
// that we do not get %2 = type %2
- TypePrinter.printAtLeastOneLevel(NumberedTypes[i], Out);
+ TypePrinter.printStructBody(NumberedTypes[i], Out);
Out << '\n';
}
-
- // Print the named types.
- for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end();
- TI != TE; ++TI) {
- PrintLLVMName(Out, TI->first, LocalPrefix);
+
+ for (unsigned i = 0, e = TypePrinter.NamedTypes.size(); i != e; ++i) {
+ PrintLLVMName(Out, TypePrinter.NamedTypes[i]->getName(), LocalPrefix);
Out << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %FILE = type %FILE
- TypePrinter.printAtLeastOneLevel(TI->second, Out);
+ TypePrinter.printStructBody(TypePrinter.NamedTypes[i], Out);
Out << '\n';
}
}
@@ -1735,18 +1598,6 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) {
if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out);
}
-/// printDebugLoc - Print DebugLoc.
-static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
- OS << DL.getLine() << ":" << DL.getCol();
- if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
- DebugLoc IDL = DebugLoc::getFromDILocation(N);
- if (!IDL.isUnknown()) {
- OS << "@";
- printDebugLoc(IDL,OS);
- }
- }
-}
-
/// printInfoComment - Print a little comment after the instruction indicating
/// which slot it occupies.
///
@@ -1754,43 +1605,6 @@ void AssemblyWriter::printInfoComment(const Value &V) {
if (AnnotationWriter) {
AnnotationWriter->printInfoComment(V, Out);
return;
- } else if (EnableDebugInfoComment) {
- bool Padded = false;
- if (const Instruction *I = dyn_cast<Instruction>(&V)) {
- const DebugLoc &DL = I->getDebugLoc();
- if (!DL.isUnknown()) {
- if (!Padded) {
- Out.PadToColumn(50);
- Padded = true;
- Out << ";";
- }
- Out << " [debug line = ";
- printDebugLoc(DL,Out);
- Out << "]";
- }
- if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
- const MDNode *Var = DDI->getVariable();
- if (!Padded) {
- Out.PadToColumn(50);
- Padded = true;
- Out << ";";
- }
- if (Var && Var->getNumOperands() >= 2)
- if (MDString *MDS = dyn_cast_or_null<MDString>(Var->getOperand(2)))
- Out << " [debug variable = " << MDS->getString() << "]";
- }
- else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
- const MDNode *Var = DVI->getVariable();
- if (!Padded) {
- Out.PadToColumn(50);
- Padded = true;
- Out << ";";
- }
- if (Var && Var->getNumOperands() >= 2)
- if (MDString *MDS = dyn_cast_or_null<MDString>(Var->getOperand(2)))
- Out << " [debug variable = " << MDS->getString() << "]";
- }
- }
}
}
@@ -1873,16 +1687,16 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
writeOperand(I.getOperand(i), true);
}
Out << ']';
- } else if (isa<PHINode>(I)) {
+ } else if (const PHINode *PN = dyn_cast<PHINode>(&I)) {
Out << ' ';
TypePrinter.print(I.getType(), Out);
Out << ' ';
- for (unsigned op = 0, Eop = I.getNumOperands(); op < Eop; op += 2) {
+ for (unsigned op = 0, Eop = PN->getNumIncomingValues(); op < Eop; ++op) {
if (op) Out << ", ";
Out << "[ ";
- writeOperand(I.getOperand(op ), false); Out << ", ";
- writeOperand(I.getOperand(op+1), false); Out << " ]";
+ writeOperand(PN->getIncomingValue(op), false); Out << ", ";
+ writeOperand(PN->getIncomingBlock(op), false); Out << " ]";
}
} else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&I)) {
Out << ' ';
@@ -1916,9 +1730,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
}
Operand = CI->getCalledValue();
- const PointerType *PTy = cast<PointerType>(Operand->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
- const Type *RetTy = FTy->getReturnType();
+ PointerType *PTy = cast<PointerType>(Operand->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ Type *RetTy = FTy->getReturnType();
const AttrListPtr &PAL = CI->getAttributes();
if (PAL.getRetAttributes() != Attribute::None)
@@ -1949,9 +1763,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << ' ' << Attribute::getAsString(PAL.getFnAttributes());
} else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
Operand = II->getCalledValue();
- const PointerType *PTy = cast<PointerType>(Operand->getType());
- const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
- const Type *RetTy = FTy->getReturnType();
+ PointerType *PTy = cast<PointerType>(Operand->getType());
+ FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ Type *RetTy = FTy->getReturnType();
const AttrListPtr &PAL = II->getAttributes();
// Print the calling convention being used.
@@ -2034,7 +1848,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
// omit the type from all but the first operand. If the instruction has
// different type operands (for example br), then they are all printed.
bool PrintAllTypes = false;
- const Type *TheType = Operand->getType();
+ Type *TheType = Operand->getType();
// Select, Store and ShuffleVector always print all types.
if (isa<SelectInst>(I) || isa<StoreInst>(I) || isa<ShuffleVectorInst>(I)
@@ -2154,7 +1968,15 @@ void Type::print(raw_ostream &OS) const {
OS << "<null Type>";
return;
}
- TypePrinting().print(this, OS);
+ TypePrinting TP;
+ TP.print(const_cast<Type*>(this), OS);
+
+ // If the type is a named struct type, print the body as well.
+ if (StructType *STy = dyn_cast<StructType>(const_cast<Type*>(this)))
+ if (!STy->isAnonymous()) {
+ OS << " = type ";
+ TP.printStructBody(STy, OS);
+ }
}
void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
@@ -2210,14 +2032,7 @@ void Value::printCustom(raw_ostream &OS) const {
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
-// This one uses type names from the given context module
-void Type::dump(const Module *Context) const {
- WriteTypeSymbolic(dbgs(), this, Context);
- dbgs() << '\n';
-}
-
-// Type::dump - allow easy printing of Types from the debugger.
-void Type::dump() const { dump(0); }
+void Type::dump() const { print(dbgs()); }
// Module::dump() - Allow printing of Modules from the debugger.
void Module::dump() const { print(dbgs(), 0); }
diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp
index ee257db..bf6efa1 100644
--- a/lib/VMCore/Attributes.cpp
+++ b/lib/VMCore/Attributes.cpp
@@ -74,6 +74,8 @@ std::string Attribute::getAsString(Attributes Attrs) {
Result += "naked ";
if (Attrs & Attribute::Hotpatch)
Result += "hotpatch ";
+ if (Attrs & Attribute::NonLazyBind)
+ Result += "nonlazybind ";
if (Attrs & Attribute::StackAlignment) {
Result += "alignstack(";
Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs));
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp
index f8f15ca..9e93ff3 100644
--- a/lib/VMCore/AutoUpgrade.cpp
+++ b/lib/VMCore/AutoUpgrade.cpp
@@ -28,558 +28,77 @@ using namespace llvm;
static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
assert(F && "Illegal to upgrade a non-existent Function.");
- // Get the Function's name.
- const std::string& Name = F->getName();
-
- // Convenience
- const FunctionType *FTy = F->getFunctionType();
-
// Quickly eliminate it, if it's not a candidate.
- if (Name.length() <= 8 || Name[0] != 'l' || Name[1] != 'l' ||
- Name[2] != 'v' || Name[3] != 'm' || Name[4] != '.')
+ StringRef Name = F->getName();
+ if (Name.size() <= 8 || !Name.startswith("llvm."))
return false;
+ Name = Name.substr(5); // Strip off "llvm."
+ const FunctionType *FTy = F->getFunctionType();
Module *M = F->getParent();
- switch (Name[5]) {
+
+ switch (Name[0]) {
default: break;
- case 'a':
- // This upgrades the llvm.atomic.lcs, llvm.atomic.las, llvm.atomic.lss,
- // and atomics with default address spaces to their new names to their new
- // function name (e.g. llvm.atomic.add.i32 => llvm.atomic.add.i32.p0i32)
- if (Name.compare(5,7,"atomic.",7) == 0) {
- if (Name.compare(12,3,"lcs",3) == 0) {
- std::string::size_type delim = Name.find('.',12);
- F->setName("llvm.atomic.cmp.swap" + Name.substr(delim) +
- ".p0" + Name.substr(delim+1));
- NewFn = F;
- return true;
- }
- else if (Name.compare(12,3,"las",3) == 0) {
- std::string::size_type delim = Name.find('.',12);
- F->setName("llvm.atomic.load.add"+Name.substr(delim)
- + ".p0" + Name.substr(delim+1));
- NewFn = F;
- return true;
- }
- else if (Name.compare(12,3,"lss",3) == 0) {
- std::string::size_type delim = Name.find('.',12);
- F->setName("llvm.atomic.load.sub"+Name.substr(delim)
- + ".p0" + Name.substr(delim+1));
- NewFn = F;
- return true;
- }
- else if (Name.rfind(".p") == std::string::npos) {
- // We don't have an address space qualifier so this has be upgraded
- // to the new name. Copy the type name at the end of the intrinsic
- // and add to it
- std::string::size_type delim = Name.find_last_of('.');
- assert(delim != std::string::npos && "can not find type");
- F->setName(Name + ".p0" + Name.substr(delim+1));
- NewFn = F;
- return true;
- }
- } else if (Name.compare(5, 9, "arm.neon.", 9) == 0) {
- if (((Name.compare(14, 5, "vmovl", 5) == 0 ||
- Name.compare(14, 5, "vaddl", 5) == 0 ||
- Name.compare(14, 5, "vsubl", 5) == 0 ||
- Name.compare(14, 5, "vaddw", 5) == 0 ||
- Name.compare(14, 5, "vsubw", 5) == 0 ||
- Name.compare(14, 5, "vmlal", 5) == 0 ||
- Name.compare(14, 5, "vmlsl", 5) == 0 ||
- Name.compare(14, 5, "vabdl", 5) == 0 ||
- Name.compare(14, 5, "vabal", 5) == 0) &&
- (Name.compare(19, 2, "s.", 2) == 0 ||
- Name.compare(19, 2, "u.", 2) == 0)) ||
-
- (Name.compare(14, 4, "vaba", 4) == 0 &&
- (Name.compare(18, 2, "s.", 2) == 0 ||
- Name.compare(18, 2, "u.", 2) == 0)) ||
-
- (Name.compare(14, 6, "vmovn.", 6) == 0)) {
-
- // Calls to these are transformed into IR without intrinsics.
- NewFn = 0;
- return true;
- }
- // Old versions of NEON ld/st intrinsics are missing alignment arguments.
- bool isVLd = (Name.compare(14, 3, "vld", 3) == 0);
- bool isVSt = (Name.compare(14, 3, "vst", 3) == 0);
- if (isVLd || isVSt) {
- unsigned NumVecs = Name.at(17) - '0';
- if (NumVecs == 0 || NumVecs > 4)
- return false;
- bool isLaneOp = (Name.compare(18, 5, "lane.", 5) == 0);
- if (!isLaneOp && Name.at(18) != '.')
- return false;
- unsigned ExpectedArgs = 2; // for the address and alignment
- if (isVSt || isLaneOp)
- ExpectedArgs += NumVecs;
- if (isLaneOp)
- ExpectedArgs += 1; // for the lane number
- unsigned NumP = FTy->getNumParams();
- if (NumP != ExpectedArgs - 1)
- return false;
-
- // Change the name of the old (bad) intrinsic, because
- // its type is incorrect, but we cannot overload that name.
- F->setName("");
-
- // One argument is missing: add the alignment argument.
- std::vector<const Type*> NewParams;
- for (unsigned p = 0; p < NumP; ++p)
- NewParams.push_back(FTy->getParamType(p));
- NewParams.push_back(Type::getInt32Ty(F->getContext()));
- FunctionType *NewFTy = FunctionType::get(FTy->getReturnType(),
- NewParams, false);
- NewFn = cast<Function>(M->getOrInsertFunction(Name, NewFTy));
- return true;
- }
- }
- break;
- case 'b':
- // This upgrades the name of the llvm.bswap intrinsic function to only use
- // a single type name for overloading. We only care about the old format
- // 'llvm.bswap.i*.i*', so check for 'bswap.' and then for there being
- // a '.' after 'bswap.'
- if (Name.compare(5,6,"bswap.",6) == 0) {
- std::string::size_type delim = Name.find('.',11);
-
- if (delim != std::string::npos) {
- // Construct the new name as 'llvm.bswap' + '.i*'
- F->setName(Name.substr(0,10)+Name.substr(delim));
- NewFn = F;
- return true;
- }
- }
- break;
+ case 'p':
+ // This upgrades the llvm.prefetch intrinsic to accept one more parameter,
+ // which is a instruction / data cache identifier. The old version only
+ // implicitly accepted the data version.
+ if (Name == "prefetch") {
+ // Don't do anything if it has the correct number of arguments already
+ if (FTy->getNumParams() == 4)
+ break;
- case 'c':
- // We only want to fix the 'llvm.ct*' intrinsics which do not have the
- // correct return type, so we check for the name, and then check if the
- // return type does not match the parameter type.
- if ( (Name.compare(5,5,"ctpop",5) == 0 ||
- Name.compare(5,4,"ctlz",4) == 0 ||
- Name.compare(5,4,"cttz",4) == 0) &&
- FTy->getReturnType() != FTy->getParamType(0)) {
- // We first need to change the name of the old (bad) intrinsic, because
- // its type is incorrect, but we cannot overload that name. We
- // arbitrarily unique it here allowing us to construct a correctly named
+ assert(FTy->getNumParams() == 3 && "old prefetch takes 3 args!");
+ // We first need to change the name of the old (bad) intrinsic, because
+ // its type is incorrect, but we cannot overload that name. We
+ // arbitrarily unique it here allowing us to construct a correctly named
// and typed function below.
+ std::string NameTmp = F->getName();
F->setName("");
-
- // Now construct the new intrinsic with the correct name and type. We
- // leave the old function around in order to query its type, whatever it
- // may be, and correctly convert up to the new type.
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
+ NewFn = cast<Function>(M->getOrInsertFunction(NameTmp,
+ FTy->getReturnType(),
FTy->getParamType(0),
- FTy->getParamType(0),
- (Type *)0));
+ FTy->getParamType(1),
+ FTy->getParamType(2),
+ FTy->getParamType(2),
+ (Type*)0));
return true;
}
- break;
- case 'e':
- // The old llvm.eh.selector.i32 is equivalent to the new llvm.eh.selector.
- if (Name.compare("llvm.eh.selector.i32") == 0) {
- F->setName("llvm.eh.selector");
- NewFn = F;
- return true;
- }
- // The old llvm.eh.typeid.for.i32 is equivalent to llvm.eh.typeid.for.
- if (Name.compare("llvm.eh.typeid.for.i32") == 0) {
- F->setName("llvm.eh.typeid.for");
- NewFn = F;
- return true;
- }
- // Convert the old llvm.eh.selector.i64 to a call to llvm.eh.selector.
- if (Name.compare("llvm.eh.selector.i64") == 0) {
- NewFn = Intrinsic::getDeclaration(M, Intrinsic::eh_selector);
- return true;
- }
- // Convert the old llvm.eh.typeid.for.i64 to a call to llvm.eh.typeid.for.
- if (Name.compare("llvm.eh.typeid.for.i64") == 0) {
- NewFn = Intrinsic::getDeclaration(M, Intrinsic::eh_typeid_for);
- return true;
- }
break;
-
- case 'm': {
- // This upgrades the llvm.memcpy, llvm.memmove, and llvm.memset to the
- // new format that allows overloading the pointer for different address
- // space (e.g., llvm.memcpy.i16 => llvm.memcpy.p0i8.p0i8.i16)
- const char* NewFnName = NULL;
- if (Name.compare(5,8,"memcpy.i",8) == 0) {
- if (Name[13] == '8')
- NewFnName = "llvm.memcpy.p0i8.p0i8.i8";
- else if (Name.compare(13,2,"16") == 0)
- NewFnName = "llvm.memcpy.p0i8.p0i8.i16";
- else if (Name.compare(13,2,"32") == 0)
- NewFnName = "llvm.memcpy.p0i8.p0i8.i32";
- else if (Name.compare(13,2,"64") == 0)
- NewFnName = "llvm.memcpy.p0i8.p0i8.i64";
- } else if (Name.compare(5,9,"memmove.i",9) == 0) {
- if (Name[14] == '8')
- NewFnName = "llvm.memmove.p0i8.p0i8.i8";
- else if (Name.compare(14,2,"16") == 0)
- NewFnName = "llvm.memmove.p0i8.p0i8.i16";
- else if (Name.compare(14,2,"32") == 0)
- NewFnName = "llvm.memmove.p0i8.p0i8.i32";
- else if (Name.compare(14,2,"64") == 0)
- NewFnName = "llvm.memmove.p0i8.p0i8.i64";
- }
- else if (Name.compare(5,8,"memset.i",8) == 0) {
- if (Name[13] == '8')
- NewFnName = "llvm.memset.p0i8.i8";
- else if (Name.compare(13,2,"16") == 0)
- NewFnName = "llvm.memset.p0i8.i16";
- else if (Name.compare(13,2,"32") == 0)
- NewFnName = "llvm.memset.p0i8.i32";
- else if (Name.compare(13,2,"64") == 0)
- NewFnName = "llvm.memset.p0i8.i64";
- }
+ case 'x': {
+ const char *NewFnName = NULL;
+ // This fixes the poorly named crc32 intrinsics.
+ if (Name == "x86.sse42.crc32.8")
+ NewFnName = "llvm.x86.sse42.crc32.32.8";
+ else if (Name == "x86.sse42.crc32.16")
+ NewFnName = "llvm.x86.sse42.crc32.32.16";
+ else if (Name == "x86.sse42.crc32.32")
+ NewFnName = "llvm.x86.sse42.crc32.32.32";
+ else if (Name == "x86.sse42.crc64.8")
+ NewFnName = "llvm.x86.sse42.crc32.64.8";
+ else if (Name == "x86.sse42.crc64.64")
+ NewFnName = "llvm.x86.sse42.crc32.64.64";
+
if (NewFnName) {
- NewFn = cast<Function>(M->getOrInsertFunction(NewFnName,
- FTy->getReturnType(),
- FTy->getParamType(0),
- FTy->getParamType(1),
- FTy->getParamType(2),
- FTy->getParamType(3),
- Type::getInt1Ty(F->getContext()),
- (Type *)0));
+ F->setName(NewFnName);
+ NewFn = F;
return true;
}
- break;
- }
- case 'p':
- // This upgrades the llvm.part.select overloaded intrinsic names to only
- // use one type specifier in the name. We only care about the old format
- // 'llvm.part.select.i*.i*', and solve as above with bswap.
- if (Name.compare(5,12,"part.select.",12) == 0) {
- std::string::size_type delim = Name.find('.',17);
-
- if (delim != std::string::npos) {
- // Construct a new name as 'llvm.part.select' + '.i*'
- F->setName(Name.substr(0,16)+Name.substr(delim));
- NewFn = F;
- return true;
- }
- break;
- }
- // This upgrades the llvm.part.set intrinsics similarly as above, however
- // we care about 'llvm.part.set.i*.i*.i*', but only the first two types
- // must match. There is an additional type specifier after these two
- // matching types that we must retain when upgrading. Thus, we require
- // finding 2 periods, not just one, after the intrinsic name.
- if (Name.compare(5,9,"part.set.",9) == 0) {
- std::string::size_type delim = Name.find('.',14);
-
- if (delim != std::string::npos &&
- Name.find('.',delim+1) != std::string::npos) {
- // Construct a new name as 'llvm.part.select' + '.i*.i*'
- F->setName(Name.substr(0,13)+Name.substr(delim));
- NewFn = F;
- return true;
- }
- break;
- }
-
- break;
- case 'x':
- // This fixes the poorly named crc32 intrinsics
- if (Name.compare(5, 13, "x86.sse42.crc", 13) == 0) {
- const char* NewFnName = NULL;
- if (Name.compare(18, 2, "32", 2) == 0) {
- if (Name.compare(20, 2, ".8") == 0 && Name.length() == 22) {
- NewFnName = "llvm.x86.sse42.crc32.32.8";
- } else if (Name.compare(20, 3, ".16") == 0 && Name.length() == 23) {
- NewFnName = "llvm.x86.sse42.crc32.32.16";
- } else if (Name.compare(20, 3, ".32") == 0 && Name.length() == 23) {
- NewFnName = "llvm.x86.sse42.crc32.32.32";
- }
- }
- else if (Name.compare(18, 2, "64", 2) == 0) {
- if (Name.compare(20, 2, ".8") == 0 && Name.length() == 22) {
- NewFnName = "llvm.x86.sse42.crc32.64.8";
- } else if (Name.compare(20, 3, ".64") == 0 && Name.length() == 23) {
- NewFnName = "llvm.x86.sse42.crc32.64.64";
- }
- }
- if (NewFnName) {
- F->setName(NewFnName);
- NewFn = F;
- return true;
- }
- }
-
- // This fixes all MMX shift intrinsic instructions to take a
- // x86_mmx instead of a v1i64, v2i32, v4i16, or v8i8.
- if (Name.compare(5, 8, "x86.mmx.", 8) == 0) {
- const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext());
-
- if (Name.compare(13, 4, "padd", 4) == 0 ||
- Name.compare(13, 4, "psub", 4) == 0 ||
- Name.compare(13, 4, "pmul", 4) == 0 ||
- Name.compare(13, 5, "pmadd", 5) == 0 ||
- Name.compare(13, 4, "pand", 4) == 0 ||
- Name.compare(13, 3, "por", 3) == 0 ||
- Name.compare(13, 4, "pxor", 4) == 0 ||
- Name.compare(13, 4, "pavg", 4) == 0 ||
- Name.compare(13, 4, "pmax", 4) == 0 ||
- Name.compare(13, 4, "pmin", 4) == 0 ||
- Name.compare(13, 4, "psad", 4) == 0 ||
- Name.compare(13, 4, "psll", 4) == 0 ||
- Name.compare(13, 4, "psrl", 4) == 0 ||
- Name.compare(13, 4, "psra", 4) == 0 ||
- Name.compare(13, 4, "pack", 4) == 0 ||
- Name.compare(13, 6, "punpck", 6) == 0 ||
- Name.compare(13, 4, "pcmp", 4) == 0) {
- assert(FTy->getNumParams() == 2 && "MMX intrinsic takes 2 args!");
- const Type *SecondParamTy = X86_MMXTy;
-
- if (Name.compare(13, 5, "pslli", 5) == 0 ||
- Name.compare(13, 5, "psrli", 5) == 0 ||
- Name.compare(13, 5, "psrai", 5) == 0)
- SecondParamTy = FTy->getParamType(1);
-
- // Don't do anything if it has the correct types.
- if (FTy->getReturnType() == X86_MMXTy &&
- FTy->getParamType(0) == X86_MMXTy &&
- FTy->getParamType(1) == SecondParamTy)
- break;
-
- // We first need to change the name of the old (bad) intrinsic, because
- // its type is incorrect, but we cannot overload that name. We
- // arbitrarily unique it here allowing us to construct a correctly named
- // and typed function below.
- F->setName("");
-
- // Now construct the new intrinsic with the correct name and type. We
- // leave the old function around in order to query its type, whatever it
- // may be, and correctly convert up to the new type.
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy, X86_MMXTy,
- SecondParamTy, (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 8, "maskmovq", 8) == 0) {
- // Don't do anything if it has the correct types.
- if (FTy->getParamType(0) == X86_MMXTy &&
- FTy->getParamType(1) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- FTy->getReturnType(),
- X86_MMXTy,
- X86_MMXTy,
- FTy->getParamType(2),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 8, "pmovmskb", 8) == 0) {
- if (FTy->getParamType(0) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- FTy->getReturnType(),
- X86_MMXTy,
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 5, "movnt", 5) == 0) {
- if (FTy->getParamType(1) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- FTy->getReturnType(),
- FTy->getParamType(0),
- X86_MMXTy,
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 7, "palignr", 7) == 0) {
- if (FTy->getReturnType() == X86_MMXTy &&
- FTy->getParamType(0) == X86_MMXTy &&
- FTy->getParamType(1) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- X86_MMXTy,
- X86_MMXTy,
- FTy->getParamType(2),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 5, "pextr", 5) == 0) {
- if (FTy->getParamType(0) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- FTy->getReturnType(),
- X86_MMXTy,
- FTy->getParamType(1),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 5, "pinsr", 5) == 0) {
- if (FTy->getReturnType() == X86_MMXTy &&
- FTy->getParamType(0) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- X86_MMXTy,
- FTy->getParamType(1),
- FTy->getParamType(2),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 12, "cvtsi32.si64", 12) == 0) {
- if (FTy->getReturnType() == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- FTy->getParamType(0),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 12, "cvtsi64.si32", 12) == 0) {
- if (FTy->getParamType(0) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- FTy->getReturnType(),
- X86_MMXTy,
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 8, "vec.init", 8) == 0) {
- if (FTy->getReturnType() == X86_MMXTy)
- break;
-
- F->setName("");
-
- if (Name.compare(21, 2, ".b", 2) == 0)
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- FTy->getParamType(0),
- FTy->getParamType(1),
- FTy->getParamType(2),
- FTy->getParamType(3),
- FTy->getParamType(4),
- FTy->getParamType(5),
- FTy->getParamType(6),
- FTy->getParamType(7),
- (Type*)0));
- else if (Name.compare(21, 2, ".w", 2) == 0)
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- FTy->getParamType(0),
- FTy->getParamType(1),
- FTy->getParamType(2),
- FTy->getParamType(3),
- (Type*)0));
- else if (Name.compare(21, 2, ".d", 2) == 0)
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- FTy->getParamType(0),
- FTy->getParamType(1),
- (Type*)0));
- return true;
- }
-
-
- if (Name.compare(13, 9, "vec.ext.d", 9) == 0) {
- if (FTy->getReturnType() == X86_MMXTy &&
- FTy->getParamType(0) == X86_MMXTy)
- break;
-
- F->setName("");
- NewFn = cast<Function>(M->getOrInsertFunction(Name,
- X86_MMXTy,
- X86_MMXTy,
- FTy->getParamType(1),
- (Type*)0));
- return true;
- }
-
- if (Name.compare(13, 9, "emms", 4) == 0 ||
- Name.compare(13, 9, "femms", 5) == 0) {
- NewFn = 0;
- break;
- }
-
- // We really shouldn't get here ever.
- assert(0 && "Invalid MMX intrinsic!");
- break;
- } else if (Name.compare(5,17,"x86.sse2.loadh.pd",17) == 0 ||
- Name.compare(5,17,"x86.sse2.loadl.pd",17) == 0 ||
- Name.compare(5,16,"x86.sse2.movl.dq",16) == 0 ||
- Name.compare(5,15,"x86.sse2.movs.d",15) == 0 ||
- Name.compare(5,16,"x86.sse2.shuf.pd",16) == 0 ||
- Name.compare(5,18,"x86.sse2.unpckh.pd",18) == 0 ||
- Name.compare(5,18,"x86.sse2.unpckl.pd",18) == 0 ||
- Name.compare(5,20,"x86.sse2.punpckh.qdq",20) == 0 ||
- Name.compare(5,20,"x86.sse2.punpckl.qdq",20) == 0) {
- // Calls to these intrinsics are transformed into ShuffleVector's.
- NewFn = 0;
- return true;
- } else if (Name.compare(5, 16, "x86.sse41.pmulld", 16) == 0) {
- // Calls to these intrinsics are transformed into vector multiplies.
- NewFn = 0;
+ // Calls to these instructions are transformed into unaligned loads.
+ if (Name == "x86.sse.loadu.ps" || Name == "x86.sse2.loadu.dq" ||
+ Name == "x86.sse2.loadu.pd")
return true;
- } else if (Name.compare(5, 18, "x86.ssse3.palign.r", 18) == 0 ||
- Name.compare(5, 22, "x86.ssse3.palign.r.128", 22) == 0) {
- // Calls to these intrinsics are transformed into vector shuffles, shifts,
- // or 0.
- NewFn = 0;
- return true;
- } else if (Name.compare(5, 16, "x86.sse.loadu.ps", 16) == 0 ||
- Name.compare(5, 17, "x86.sse2.loadu.dq", 17) == 0 ||
- Name.compare(5, 17, "x86.sse2.loadu.pd", 17) == 0) {
- // Calls to these instructions are transformed into unaligned loads.
- NewFn = 0;
- return true;
- } else if (Name.compare(5, 16, "x86.sse.movnt.ps", 16) == 0 ||
- Name.compare(5, 17, "x86.sse2.movnt.dq", 17) == 0 ||
- Name.compare(5, 17, "x86.sse2.movnt.pd", 17) == 0 ||
- Name.compare(5, 17, "x86.sse2.movnt.i", 16) == 0) {
- // Calls to these instructions are transformed into nontemporal stores.
- NewFn = 0;
- return true;
- } else if (Name.compare(5, 17, "x86.ssse3.pshuf.w", 17) == 0) {
- // This is an SSE/MMX instruction.
- const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext());
- NewFn =
- cast<Function>(M->getOrInsertFunction("llvm.x86.sse.pshuf.w",
- X86_MMXTy,
- X86_MMXTy,
- Type::getInt8Ty(F->getContext()),
- (Type*)0));
+
+ // Calls to these instructions are transformed into nontemporal stores.
+ if (Name == "x86.sse.movnt.ps" || Name == "x86.sse2.movnt.dq" ||
+ Name == "x86.sse2.movnt.pd" || Name == "x86.sse2.movnt.i")
return true;
- }
break;
}
+ }
// This may not belong here. This function is effectively being overloaded
// to both detect an intrinsic which needs upgrading, and to provide the
@@ -601,105 +120,10 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
}
bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
- StringRef Name(GV->getName());
-
- // We are only upgrading one symbol here.
- if (Name == ".llvm.eh.catch.all.value") {
- GV->setName("llvm.eh.catch.all.value");
- return true;
- }
-
+ // Nothing to do yet.
return false;
}
-/// ExtendNEONArgs - For NEON "long" and "wide" operations, where the results
-/// have vector elements twice as big as one or both source operands, do the
-/// sign- or zero-extension that used to be handled by intrinsics. The
-/// extended values are returned via V0 and V1.
-static void ExtendNEONArgs(CallInst *CI, Value *Arg0, Value *Arg1,
- Value *&V0, Value *&V1) {
- Function *F = CI->getCalledFunction();
- const std::string& Name = F->getName();
- bool isLong = (Name.at(18) == 'l');
- bool isSigned = (Name.at(19) == 's');
-
- if (isSigned) {
- if (isLong)
- V0 = new SExtInst(Arg0, CI->getType(), "", CI);
- else
- V0 = Arg0;
- V1 = new SExtInst(Arg1, CI->getType(), "", CI);
- } else {
- if (isLong)
- V0 = new ZExtInst(Arg0, CI->getType(), "", CI);
- else
- V0 = Arg0;
- V1 = new ZExtInst(Arg1, CI->getType(), "", CI);
- }
-}
-
-/// CallVABD - As part of expanding a call to one of the old NEON vabdl, vaba,
-/// or vabal intrinsics, construct a call to a vabd intrinsic. Examine the
-/// name of the old intrinsic to determine whether to use a signed or unsigned
-/// vabd intrinsic. Get the type from the old call instruction, adjusted for
-/// half-size vector elements if the old intrinsic was vabdl or vabal.
-static Instruction *CallVABD(CallInst *CI, Value *Arg0, Value *Arg1) {
- Function *F = CI->getCalledFunction();
- const std::string& Name = F->getName();
- bool isLong = (Name.at(18) == 'l');
- bool isSigned = (Name.at(isLong ? 19 : 18) == 's');
-
- Intrinsic::ID intID;
- if (isSigned)
- intID = Intrinsic::arm_neon_vabds;
- else
- intID = Intrinsic::arm_neon_vabdu;
-
- const Type *Ty = CI->getType();
- if (isLong)
- Ty = VectorType::getTruncatedElementVectorType(cast<const VectorType>(Ty));
-
- Function *VABD = Intrinsic::getDeclaration(F->getParent(), intID, &Ty, 1);
- Value *Operands[2];
- Operands[0] = Arg0;
- Operands[1] = Arg1;
- return CallInst::Create(VABD, Operands, Operands+2,
- "upgraded."+CI->getName(), CI);
-}
-
-/// ConstructNewCallInst - Construct a new CallInst with the signature of NewFn.
-static void ConstructNewCallInst(Function *NewFn, CallInst *OldCI,
- Value **Operands, unsigned NumOps,
- bool AssignName = true) {
- // Construct a new CallInst.
- CallInst *NewCI =
- CallInst::Create(NewFn, Operands, Operands + NumOps,
- AssignName ? "upgraded." + OldCI->getName() : "", OldCI);
-
- NewCI->setTailCall(OldCI->isTailCall());
- NewCI->setCallingConv(OldCI->getCallingConv());
-
- // Handle any uses of the old CallInst. If the type has changed, add a cast.
- if (!OldCI->use_empty()) {
- if (OldCI->getType() != NewCI->getType()) {
- Function *OldFn = OldCI->getCalledFunction();
- CastInst *RetCast =
- CastInst::Create(CastInst::getCastOpcode(NewCI, true,
- OldFn->getReturnType(), true),
- NewCI, OldFn->getReturnType(), NewCI->getName(),OldCI);
-
- // Replace all uses of the old call with the new cast which has the
- // correct type.
- OldCI->replaceAllUsesWith(RetCast);
- } else {
- OldCI->replaceAllUsesWith(NewCI);
- }
- }
-
- // Clean up the old call now that it has been completely upgraded.
- OldCI->eraseFromParent();
-}
-
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
// upgraded intrinsic. All argument and return casting must be provided in
// order to seamlessly integrate with existing context.
@@ -711,284 +135,9 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
assert(F && "CallInst has no function associated with it.");
if (!NewFn) {
- // Get the Function's name.
- const std::string& Name = F->getName();
-
- // Upgrade ARM NEON intrinsics.
- if (Name.compare(5, 9, "arm.neon.", 9) == 0) {
- Instruction *NewI;
- Value *V0, *V1;
- if (Name.compare(14, 7, "vmovls.", 7) == 0) {
- NewI = new SExtInst(CI->getArgOperand(0), CI->getType(),
- "upgraded." + CI->getName(), CI);
- } else if (Name.compare(14, 7, "vmovlu.", 7) == 0) {
- NewI = new ZExtInst(CI->getArgOperand(0), CI->getType(),
- "upgraded." + CI->getName(), CI);
- } else if (Name.compare(14, 4, "vadd", 4) == 0) {
- ExtendNEONArgs(CI, CI->getArgOperand(0), CI->getArgOperand(1), V0, V1);
- NewI = BinaryOperator::CreateAdd(V0, V1, "upgraded."+CI->getName(), CI);
- } else if (Name.compare(14, 4, "vsub", 4) == 0) {
- ExtendNEONArgs(CI, CI->getArgOperand(0), CI->getArgOperand(1), V0, V1);
- NewI = BinaryOperator::CreateSub(V0, V1,"upgraded."+CI->getName(),CI);
- } else if (Name.compare(14, 4, "vmul", 4) == 0) {
- ExtendNEONArgs(CI, CI->getArgOperand(0), CI->getArgOperand(1), V0, V1);
- NewI = BinaryOperator::CreateMul(V0, V1,"upgraded."+CI->getName(),CI);
- } else if (Name.compare(14, 4, "vmla", 4) == 0) {
- ExtendNEONArgs(CI, CI->getArgOperand(1), CI->getArgOperand(2), V0, V1);
- Instruction *MulI = BinaryOperator::CreateMul(V0, V1, "", CI);
- NewI = BinaryOperator::CreateAdd(CI->getArgOperand(0), MulI,
- "upgraded."+CI->getName(), CI);
- } else if (Name.compare(14, 4, "vmls", 4) == 0) {
- ExtendNEONArgs(CI, CI->getArgOperand(1), CI->getArgOperand(2), V0, V1);
- Instruction *MulI = BinaryOperator::CreateMul(V0, V1, "", CI);
- NewI = BinaryOperator::CreateSub(CI->getArgOperand(0), MulI,
- "upgraded."+CI->getName(), CI);
- } else if (Name.compare(14, 4, "vabd", 4) == 0) {
- NewI = CallVABD(CI, CI->getArgOperand(0), CI->getArgOperand(1));
- NewI = new ZExtInst(NewI, CI->getType(), "upgraded."+CI->getName(), CI);
- } else if (Name.compare(14, 4, "vaba", 4) == 0) {
- NewI = CallVABD(CI, CI->getArgOperand(1), CI->getArgOperand(2));
- if (Name.at(18) == 'l')
- NewI = new ZExtInst(NewI, CI->getType(), "", CI);
- NewI = BinaryOperator::CreateAdd(CI->getArgOperand(0), NewI,
- "upgraded."+CI->getName(), CI);
- } else if (Name.compare(14, 6, "vmovn.", 6) == 0) {
- NewI = new TruncInst(CI->getArgOperand(0), CI->getType(),
- "upgraded." + CI->getName(), CI);
- } else {
- llvm_unreachable("Unknown arm.neon function for CallInst upgrade.");
- }
- // Replace any uses of the old CallInst.
- if (!CI->use_empty())
- CI->replaceAllUsesWith(NewI);
- CI->eraseFromParent();
- return;
- }
-
- bool isLoadH = false, isLoadL = false, isMovL = false;
- bool isMovSD = false, isShufPD = false;
- bool isUnpckhPD = false, isUnpcklPD = false;
- bool isPunpckhQPD = false, isPunpcklQPD = false;
- if (F->getName() == "llvm.x86.sse2.loadh.pd")
- isLoadH = true;
- else if (F->getName() == "llvm.x86.sse2.loadl.pd")
- isLoadL = true;
- else if (F->getName() == "llvm.x86.sse2.movl.dq")
- isMovL = true;
- else if (F->getName() == "llvm.x86.sse2.movs.d")
- isMovSD = true;
- else if (F->getName() == "llvm.x86.sse2.shuf.pd")
- isShufPD = true;
- else if (F->getName() == "llvm.x86.sse2.unpckh.pd")
- isUnpckhPD = true;
- else if (F->getName() == "llvm.x86.sse2.unpckl.pd")
- isUnpcklPD = true;
- else if (F->getName() == "llvm.x86.sse2.punpckh.qdq")
- isPunpckhQPD = true;
- else if (F->getName() == "llvm.x86.sse2.punpckl.qdq")
- isPunpcklQPD = true;
-
- if (isLoadH || isLoadL || isMovL || isMovSD || isShufPD ||
- isUnpckhPD || isUnpcklPD || isPunpckhQPD || isPunpcklQPD) {
- std::vector<Constant*> Idxs;
- Value *Op0 = CI->getArgOperand(0);
- ShuffleVectorInst *SI = NULL;
- if (isLoadH || isLoadL) {
- Value *Op1 = UndefValue::get(Op0->getType());
- Value *Addr = new BitCastInst(CI->getArgOperand(1),
- Type::getDoublePtrTy(C),
- "upgraded.", CI);
- Value *Load = new LoadInst(Addr, "upgraded.", false, 8, CI);
- Value *Idx = ConstantInt::get(Type::getInt32Ty(C), 0);
- Op1 = InsertElementInst::Create(Op1, Load, Idx, "upgraded.", CI);
-
- if (isLoadH) {
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 0));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 2));
- } else {
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 2));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
- }
- Value *Mask = ConstantVector::get(Idxs);
- SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI);
- } else if (isMovL) {
- Constant *Zero = ConstantInt::get(Type::getInt32Ty(C), 0);
- Idxs.push_back(Zero);
- Idxs.push_back(Zero);
- Idxs.push_back(Zero);
- Idxs.push_back(Zero);
- Value *ZeroV = ConstantVector::get(Idxs);
-
- Idxs.clear();
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 4));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 5));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 2));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 3));
- Value *Mask = ConstantVector::get(Idxs);
- SI = new ShuffleVectorInst(ZeroV, Op0, Mask, "upgraded.", CI);
- } else if (isMovSD ||
- isUnpckhPD || isUnpcklPD || isPunpckhQPD || isPunpcklQPD) {
- Value *Op1 = CI->getArgOperand(1);
- if (isMovSD) {
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 2));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
- } else if (isUnpckhPD || isPunpckhQPD) {
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 3));
- } else {
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 0));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), 2));
- }
- Value *Mask = ConstantVector::get(Idxs);
- SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI);
- } else if (isShufPD) {
- Value *Op1 = CI->getArgOperand(1);
- unsigned MaskVal =
- cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C), MaskVal & 1));
- Idxs.push_back(ConstantInt::get(Type::getInt32Ty(C),
- ((MaskVal >> 1) & 1)+2));
- Value *Mask = ConstantVector::get(Idxs);
- SI = new ShuffleVectorInst(Op0, Op1, Mask, "upgraded.", CI);
- }
-
- assert(SI && "Unexpected!");
-
- // Handle any uses of the old CallInst.
- if (!CI->use_empty())
- // Replace all uses of the old call with the new cast which has the
- // correct type.
- CI->replaceAllUsesWith(SI);
-
- // Clean up the old call now that it has been completely upgraded.
- CI->eraseFromParent();
- } else if (F->getName() == "llvm.x86.sse41.pmulld") {
- // Upgrade this set of intrinsics into vector multiplies.
- Instruction *Mul = BinaryOperator::CreateMul(CI->getArgOperand(0),
- CI->getArgOperand(1),
- CI->getName(),
- CI);
- // Fix up all the uses with our new multiply.
- if (!CI->use_empty())
- CI->replaceAllUsesWith(Mul);
-
- // Remove upgraded multiply.
- CI->eraseFromParent();
- } else if (F->getName() == "llvm.x86.ssse3.palign.r") {
- Value *Op1 = CI->getArgOperand(0);
- Value *Op2 = CI->getArgOperand(1);
- Value *Op3 = CI->getArgOperand(2);
- unsigned shiftVal = cast<ConstantInt>(Op3)->getZExtValue();
- Value *Rep;
- IRBuilder<> Builder(C);
- Builder.SetInsertPoint(CI->getParent(), CI);
-
- // If palignr is shifting the pair of input vectors less than 9 bytes,
- // emit a shuffle instruction.
- if (shiftVal <= 8) {
- const Type *IntTy = Type::getInt32Ty(C);
- const Type *EltTy = Type::getInt8Ty(C);
- const Type *VecTy = VectorType::get(EltTy, 8);
-
- Op2 = Builder.CreateBitCast(Op2, VecTy);
- Op1 = Builder.CreateBitCast(Op1, VecTy);
-
- llvm::SmallVector<llvm::Constant*, 8> Indices;
- for (unsigned i = 0; i != 8; ++i)
- Indices.push_back(ConstantInt::get(IntTy, shiftVal + i));
-
- Value *SV = ConstantVector::get(Indices);
- Rep = Builder.CreateShuffleVector(Op2, Op1, SV, "palignr");
- Rep = Builder.CreateBitCast(Rep, F->getReturnType());
- }
-
- // If palignr is shifting the pair of input vectors more than 8 but less
- // than 16 bytes, emit a logical right shift of the destination.
- else if (shiftVal < 16) {
- // MMX has these as 1 x i64 vectors for some odd optimization reasons.
- const Type *EltTy = Type::getInt64Ty(C);
- const Type *VecTy = VectorType::get(EltTy, 1);
-
- Op1 = Builder.CreateBitCast(Op1, VecTy, "cast");
- Op2 = ConstantInt::get(VecTy, (shiftVal-8) * 8);
-
- // create i32 constant
- Function *I =
- Intrinsic::getDeclaration(F->getParent(), Intrinsic::x86_mmx_psrl_q);
- Rep = Builder.CreateCall2(I, Op1, Op2, "palignr");
- }
-
- // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
- else {
- Rep = Constant::getNullValue(F->getReturnType());
- }
-
- // Replace any uses with our new instruction.
- if (!CI->use_empty())
- CI->replaceAllUsesWith(Rep);
-
- // Remove upgraded instruction.
- CI->eraseFromParent();
-
- } else if (F->getName() == "llvm.x86.ssse3.palign.r.128") {
- Value *Op1 = CI->getArgOperand(0);
- Value *Op2 = CI->getArgOperand(1);
- Value *Op3 = CI->getArgOperand(2);
- unsigned shiftVal = cast<ConstantInt>(Op3)->getZExtValue();
- Value *Rep;
- IRBuilder<> Builder(C);
- Builder.SetInsertPoint(CI->getParent(), CI);
-
- // If palignr is shifting the pair of input vectors less than 17 bytes,
- // emit a shuffle instruction.
- if (shiftVal <= 16) {
- const Type *IntTy = Type::getInt32Ty(C);
- const Type *EltTy = Type::getInt8Ty(C);
- const Type *VecTy = VectorType::get(EltTy, 16);
-
- Op2 = Builder.CreateBitCast(Op2, VecTy);
- Op1 = Builder.CreateBitCast(Op1, VecTy);
-
- llvm::SmallVector<llvm::Constant*, 16> Indices;
- for (unsigned i = 0; i != 16; ++i)
- Indices.push_back(ConstantInt::get(IntTy, shiftVal + i));
-
- Value *SV = ConstantVector::get(Indices);
- Rep = Builder.CreateShuffleVector(Op2, Op1, SV, "palignr");
- Rep = Builder.CreateBitCast(Rep, F->getReturnType());
- }
-
- // If palignr is shifting the pair of input vectors more than 16 but less
- // than 32 bytes, emit a logical right shift of the destination.
- else if (shiftVal < 32) {
- const Type *EltTy = Type::getInt64Ty(C);
- const Type *VecTy = VectorType::get(EltTy, 2);
- const Type *IntTy = Type::getInt32Ty(C);
-
- Op1 = Builder.CreateBitCast(Op1, VecTy, "cast");
- Op2 = ConstantInt::get(IntTy, (shiftVal-16) * 8);
-
- // create i32 constant
- Function *I =
- Intrinsic::getDeclaration(F->getParent(), Intrinsic::x86_sse2_psrl_dq);
- Rep = Builder.CreateCall2(I, Op1, Op2, "palignr");
- }
-
- // If palignr is shifting the pair of vectors more than 32 bytes, emit zero.
- else {
- Rep = Constant::getNullValue(F->getReturnType());
- }
-
- // Replace any uses with our new instruction.
- if (!CI->use_empty())
- CI->replaceAllUsesWith(Rep);
-
- // Remove upgraded instruction.
- CI->eraseFromParent();
-
- } else if (F->getName() == "llvm.x86.sse.loadu.ps" ||
- F->getName() == "llvm.x86.sse2.loadu.dq" ||
- F->getName() == "llvm.x86.sse2.loadu.pd") {
+ if (F->getName() == "llvm.x86.sse.loadu.ps" ||
+ F->getName() == "llvm.x86.sse2.loadu.dq" ||
+ F->getName() == "llvm.x86.sse2.loadu.pd") {
// Convert to a native, unaligned load.
const Type *VecTy = CI->getType();
const Type *IntTy = IntegerType::get(C, 128);
@@ -1040,306 +189,25 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
}
switch (NewFn->getIntrinsicID()) {
- default: llvm_unreachable("Unknown function for CallInst upgrade.");
- case Intrinsic::arm_neon_vld1:
- case Intrinsic::arm_neon_vld2:
- case Intrinsic::arm_neon_vld3:
- case Intrinsic::arm_neon_vld4:
- case Intrinsic::arm_neon_vst1:
- case Intrinsic::arm_neon_vst2:
- case Intrinsic::arm_neon_vst3:
- case Intrinsic::arm_neon_vst4:
- case Intrinsic::arm_neon_vld2lane:
- case Intrinsic::arm_neon_vld3lane:
- case Intrinsic::arm_neon_vld4lane:
- case Intrinsic::arm_neon_vst2lane:
- case Intrinsic::arm_neon_vst3lane:
- case Intrinsic::arm_neon_vst4lane: {
- // Add a default alignment argument of 1.
- SmallVector<Value*, 8> Operands(CS.arg_begin(), CS.arg_end());
- Operands.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
- CallInst *NewCI = CallInst::Create(NewFn, Operands.begin(), Operands.end(),
- CI->getName(), CI);
- NewCI->setTailCall(CI->isTailCall());
- NewCI->setCallingConv(CI->getCallingConv());
-
- // Handle any uses of the old CallInst.
- if (!CI->use_empty())
- // Replace all uses of the old call with the new cast which has the
- // correct type.
- CI->replaceAllUsesWith(NewCI);
-
- // Clean up the old call now that it has been completely upgraded.
- CI->eraseFromParent();
- break;
- }
-
- case Intrinsic::x86_mmx_padd_b:
- case Intrinsic::x86_mmx_padd_w:
- case Intrinsic::x86_mmx_padd_d:
- case Intrinsic::x86_mmx_padd_q:
- case Intrinsic::x86_mmx_padds_b:
- case Intrinsic::x86_mmx_padds_w:
- case Intrinsic::x86_mmx_paddus_b:
- case Intrinsic::x86_mmx_paddus_w:
- case Intrinsic::x86_mmx_psub_b:
- case Intrinsic::x86_mmx_psub_w:
- case Intrinsic::x86_mmx_psub_d:
- case Intrinsic::x86_mmx_psub_q:
- case Intrinsic::x86_mmx_psubs_b:
- case Intrinsic::x86_mmx_psubs_w:
- case Intrinsic::x86_mmx_psubus_b:
- case Intrinsic::x86_mmx_psubus_w:
- case Intrinsic::x86_mmx_pmulh_w:
- case Intrinsic::x86_mmx_pmull_w:
- case Intrinsic::x86_mmx_pmulhu_w:
- case Intrinsic::x86_mmx_pmulu_dq:
- case Intrinsic::x86_mmx_pmadd_wd:
- case Intrinsic::x86_mmx_pand:
- case Intrinsic::x86_mmx_pandn:
- case Intrinsic::x86_mmx_por:
- case Intrinsic::x86_mmx_pxor:
- case Intrinsic::x86_mmx_pavg_b:
- case Intrinsic::x86_mmx_pavg_w:
- case Intrinsic::x86_mmx_pmaxu_b:
- case Intrinsic::x86_mmx_pmaxs_w:
- case Intrinsic::x86_mmx_pminu_b:
- case Intrinsic::x86_mmx_pmins_w:
- case Intrinsic::x86_mmx_psad_bw:
- case Intrinsic::x86_mmx_psll_w:
- case Intrinsic::x86_mmx_psll_d:
- case Intrinsic::x86_mmx_psll_q:
- case Intrinsic::x86_mmx_pslli_w:
- case Intrinsic::x86_mmx_pslli_d:
- case Intrinsic::x86_mmx_pslli_q:
- case Intrinsic::x86_mmx_psrl_w:
- case Intrinsic::x86_mmx_psrl_d:
- case Intrinsic::x86_mmx_psrl_q:
- case Intrinsic::x86_mmx_psrli_w:
- case Intrinsic::x86_mmx_psrli_d:
- case Intrinsic::x86_mmx_psrli_q:
- case Intrinsic::x86_mmx_psra_w:
- case Intrinsic::x86_mmx_psra_d:
- case Intrinsic::x86_mmx_psrai_w:
- case Intrinsic::x86_mmx_psrai_d:
- case Intrinsic::x86_mmx_packsswb:
- case Intrinsic::x86_mmx_packssdw:
- case Intrinsic::x86_mmx_packuswb:
- case Intrinsic::x86_mmx_punpckhbw:
- case Intrinsic::x86_mmx_punpckhwd:
- case Intrinsic::x86_mmx_punpckhdq:
- case Intrinsic::x86_mmx_punpcklbw:
- case Intrinsic::x86_mmx_punpcklwd:
- case Intrinsic::x86_mmx_punpckldq:
- case Intrinsic::x86_mmx_pcmpeq_b:
- case Intrinsic::x86_mmx_pcmpeq_w:
- case Intrinsic::x86_mmx_pcmpeq_d:
- case Intrinsic::x86_mmx_pcmpgt_b:
- case Intrinsic::x86_mmx_pcmpgt_w:
- case Intrinsic::x86_mmx_pcmpgt_d: {
- Value *Operands[2];
-
- // Cast the operand to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
-
- switch (NewFn->getIntrinsicID()) {
- default:
- // Cast to the X86 MMX type.
- Operands[1] = new BitCastInst(CI->getArgOperand(1),
- NewFn->getFunctionType()->getParamType(1),
- "upgraded.", CI);
- break;
- case Intrinsic::x86_mmx_pslli_w:
- case Intrinsic::x86_mmx_pslli_d:
- case Intrinsic::x86_mmx_pslli_q:
- case Intrinsic::x86_mmx_psrli_w:
- case Intrinsic::x86_mmx_psrli_d:
- case Intrinsic::x86_mmx_psrli_q:
- case Intrinsic::x86_mmx_psrai_w:
- case Intrinsic::x86_mmx_psrai_d:
- // These take an i32 as their second parameter.
- Operands[1] = CI->getArgOperand(1);
- break;
- }
-
- ConstructNewCallInst(NewFn, CI, Operands, 2);
- break;
- }
- case Intrinsic::x86_mmx_maskmovq: {
- Value *Operands[3];
-
- // Cast the operands to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
- Operands[1] = new BitCastInst(CI->getArgOperand(1),
- NewFn->getFunctionType()->getParamType(1),
- "upgraded.", CI);
- Operands[2] = CI->getArgOperand(2);
-
- ConstructNewCallInst(NewFn, CI, Operands, 3, false);
- break;
- }
- case Intrinsic::x86_mmx_pmovmskb: {
- Value *Operands[1];
-
- // Cast the operand to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
-
- ConstructNewCallInst(NewFn, CI, Operands, 1);
- break;
- }
- case Intrinsic::x86_mmx_movnt_dq: {
- Value *Operands[2];
-
- Operands[0] = CI->getArgOperand(0);
-
- // Cast the operand to the X86 MMX type.
- Operands[1] = new BitCastInst(CI->getArgOperand(1),
- NewFn->getFunctionType()->getParamType(1),
- "upgraded.", CI);
-
- ConstructNewCallInst(NewFn, CI, Operands, 2, false);
- break;
- }
- case Intrinsic::x86_mmx_palignr_b: {
- Value *Operands[3];
-
- // Cast the operands to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
- Operands[1] = new BitCastInst(CI->getArgOperand(1),
- NewFn->getFunctionType()->getParamType(1),
- "upgraded.", CI);
- Operands[2] = CI->getArgOperand(2);
-
- ConstructNewCallInst(NewFn, CI, Operands, 3);
- break;
- }
- case Intrinsic::x86_mmx_pextr_w: {
- Value *Operands[2];
-
- // Cast the operands to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
- Operands[1] = CI->getArgOperand(1);
-
- ConstructNewCallInst(NewFn, CI, Operands, 2);
- break;
- }
- case Intrinsic::x86_mmx_pinsr_w: {
- Value *Operands[3];
-
- // Cast the operands to the X86 MMX type.
- Operands[0] = new BitCastInst(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.", CI);
- Operands[1] = CI->getArgOperand(1);
- Operands[2] = CI->getArgOperand(2);
-
- ConstructNewCallInst(NewFn, CI, Operands, 3);
- break;
- }
- case Intrinsic::x86_sse_pshuf_w: {
+ case Intrinsic::prefetch: {
IRBuilder<> Builder(C);
Builder.SetInsertPoint(CI->getParent(), CI);
+ const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext());
- // Cast the operand to the X86 MMX type.
- Value *Operands[2];
- Operands[0] =
- Builder.CreateBitCast(CI->getArgOperand(0),
- NewFn->getFunctionType()->getParamType(0),
- "upgraded.");
- Operands[1] =
- Builder.CreateTrunc(CI->getArgOperand(1),
- Type::getInt8Ty(C),
- "upgraded.");
-
- ConstructNewCallInst(NewFn, CI, Operands, 2);
- break;
- }
-
- case Intrinsic::ctlz:
- case Intrinsic::ctpop:
- case Intrinsic::cttz: {
- // Build a small vector of the original arguments.
- SmallVector<Value*, 8> Operands(CS.arg_begin(), CS.arg_end());
-
- // Construct a new CallInst
- CallInst *NewCI = CallInst::Create(NewFn, Operands.begin(), Operands.end(),
- "upgraded."+CI->getName(), CI);
- NewCI->setTailCall(CI->isTailCall());
- NewCI->setCallingConv(CI->getCallingConv());
-
- // Handle any uses of the old CallInst.
- if (!CI->use_empty()) {
- // Check for sign extend parameter attributes on the return values.
- bool SrcSExt = NewFn->getAttributes().paramHasAttr(0, Attribute::SExt);
- bool DestSExt = F->getAttributes().paramHasAttr(0, Attribute::SExt);
-
- // Construct an appropriate cast from the new return type to the old.
- CastInst *RetCast = CastInst::Create(
- CastInst::getCastOpcode(NewCI, SrcSExt,
- F->getReturnType(),
- DestSExt),
- NewCI, F->getReturnType(),
- NewCI->getName(), CI);
- NewCI->moveBefore(RetCast);
-
- // Replace all uses of the old call with the new cast which has the
- // correct type.
- CI->replaceAllUsesWith(RetCast);
- }
-
- // Clean up the old call now that it has been completely upgraded.
- CI->eraseFromParent();
- }
- break;
- case Intrinsic::eh_selector:
- case Intrinsic::eh_typeid_for: {
- // Only the return type changed.
- SmallVector<Value*, 8> Operands(CS.arg_begin(), CS.arg_end());
- CallInst *NewCI = CallInst::Create(NewFn, Operands.begin(), Operands.end(),
- "upgraded." + CI->getName(), CI);
- NewCI->setTailCall(CI->isTailCall());
- NewCI->setCallingConv(CI->getCallingConv());
-
- // Handle any uses of the old CallInst.
- if (!CI->use_empty()) {
- // Construct an appropriate cast from the new return type to the old.
- CastInst *RetCast =
- CastInst::Create(CastInst::getCastOpcode(NewCI, true,
- F->getReturnType(), true),
- NewCI, F->getReturnType(), NewCI->getName(), CI);
- CI->replaceAllUsesWith(RetCast);
- }
- CI->eraseFromParent();
- }
- break;
- case Intrinsic::memcpy:
- case Intrinsic::memmove:
- case Intrinsic::memset: {
- // Add isVolatile
- const llvm::Type *I1Ty = llvm::Type::getInt1Ty(CI->getContext());
- Value *Operands[5] = { CI->getArgOperand(0), CI->getArgOperand(1),
- CI->getArgOperand(2), CI->getArgOperand(3),
- llvm::ConstantInt::get(I1Ty, 0) };
- CallInst *NewCI = CallInst::Create(NewFn, Operands, Operands+5,
+ // Add the extra "data cache" argument
+ Value *Operands[4] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2),
+ llvm::ConstantInt::get(I32Ty, 1) };
+ CallInst *NewCI = CallInst::Create(NewFn, Operands,
CI->getName(), CI);
NewCI->setTailCall(CI->isTailCall());
NewCI->setCallingConv(CI->getCallingConv());
// Handle any uses of the old CallInst.
if (!CI->use_empty())
- // Replace all uses of the old call with the new cast which has the
+ // Replace all uses of the old call with the new cast which has the
// correct type.
CI->replaceAllUsesWith(NewCI);
-
+
// Clean up the old call now that it has been completely upgraded.
CI->eraseFromParent();
break;
@@ -1354,13 +222,13 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) {
assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
// Upgrade the function and check if it is a totaly new function.
- Function* NewFn;
+ Function *NewFn;
if (UpgradeIntrinsicFunction(F, NewFn)) {
if (NewFn != F) {
// Replace all uses to the old function with the new one if necessary.
for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
UI != UE; ) {
- if (CallInst* CI = dyn_cast<CallInst>(*UI++))
+ if (CallInst *CI = dyn_cast<CallInst>(*UI++))
UpgradeIntrinsicCall(CI, NewFn);
}
// Remove old function, no longer used, from the module.
@@ -1373,37 +241,27 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) {
/// If an llvm.dbg.declare intrinsic is invalid, then this function simply
/// strips that use.
void llvm::CheckDebugInfoIntrinsics(Module *M) {
-
-
if (Function *FuncStart = M->getFunction("llvm.dbg.func.start")) {
- while (!FuncStart->use_empty()) {
- CallInst *CI = cast<CallInst>(FuncStart->use_back());
- CI->eraseFromParent();
- }
+ while (!FuncStart->use_empty())
+ cast<CallInst>(FuncStart->use_back())->eraseFromParent();
FuncStart->eraseFromParent();
}
if (Function *StopPoint = M->getFunction("llvm.dbg.stoppoint")) {
- while (!StopPoint->use_empty()) {
- CallInst *CI = cast<CallInst>(StopPoint->use_back());
- CI->eraseFromParent();
- }
+ while (!StopPoint->use_empty())
+ cast<CallInst>(StopPoint->use_back())->eraseFromParent();
StopPoint->eraseFromParent();
}
if (Function *RegionStart = M->getFunction("llvm.dbg.region.start")) {
- while (!RegionStart->use_empty()) {
- CallInst *CI = cast<CallInst>(RegionStart->use_back());
- CI->eraseFromParent();
- }
+ while (!RegionStart->use_empty())
+ cast<CallInst>(RegionStart->use_back())->eraseFromParent();
RegionStart->eraseFromParent();
}
if (Function *RegionEnd = M->getFunction("llvm.dbg.region.end")) {
- while (!RegionEnd->use_empty()) {
- CallInst *CI = cast<CallInst>(RegionEnd->use_back());
- CI->eraseFromParent();
- }
+ while (!RegionEnd->use_empty())
+ cast<CallInst>(RegionEnd->use_back())->eraseFromParent();
RegionEnd->eraseFromParent();
}
diff --git a/lib/VMCore/BasicBlock.cpp b/lib/VMCore/BasicBlock.cpp
index 955a028..70265c8 100644
--- a/lib/VMCore/BasicBlock.cpp
+++ b/lib/VMCore/BasicBlock.cpp
@@ -147,6 +147,26 @@ Instruction* BasicBlock::getFirstNonPHIOrDbg() {
return &*i;
}
+Instruction* BasicBlock::getFirstNonPHIOrDbgOrLifetime() {
+ // All valid basic blocks should have a terminator,
+ // which is not a PHINode. If we have an invalid basic
+ // block we'll get an assertion failure when dereferencing
+ // a past-the-end iterator.
+ BasicBlock::iterator i = begin();
+ for (;; ++i) {
+ if (isa<PHINode>(i) || isa<DbgInfoIntrinsic>(i))
+ continue;
+
+ const IntrinsicInst *II = dyn_cast<IntrinsicInst>(i);
+ if (!II)
+ break;
+ if (II->getIntrinsicID() != Intrinsic::lifetime_start &&
+ II->getIntrinsicID() != Intrinsic::lifetime_end)
+ break;
+ }
+ return &*i;
+}
+
void BasicBlock::dropAllReferences() {
for(iterator I = begin(), E = end(); I != E; ++I)
I->dropAllReferences();
@@ -227,8 +247,8 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
// If the PHI _HAD_ two uses, replace PHI node with its now *single* value
if (max_idx == 2) {
- if (PN->getOperand(0) != PN)
- PN->replaceAllUsesWith(PN->getOperand(0));
+ if (PN->getIncomingValue(0) != PN)
+ PN->replaceAllUsesWith(PN->getIncomingValue(0));
else
// We are left with an infinite loop with no entries: kill the PHI.
PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
@@ -308,3 +328,19 @@ BasicBlock *BasicBlock::splitBasicBlock(iterator I, const Twine &BBName) {
return New;
}
+void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) {
+ TerminatorInst *TI = getTerminator();
+ if (!TI)
+ // Cope with being called on a BasicBlock that doesn't have a terminator
+ // yet. Clang's CodeGenFunction::EmitReturnBlock() likes to do this.
+ return;
+ for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
+ BasicBlock *Succ = TI->getSuccessor(i);
+ for (iterator II = Succ->begin(); PHINode *PN = dyn_cast<PHINode>(II);
+ ++II) {
+ int i;
+ while ((i = PN->getBasicBlockIndex(this)) >= 0)
+ PN->setIncomingBlock(i, New);
+ }
+ }
+}
diff --git a/lib/VMCore/CMakeLists.txt b/lib/VMCore/CMakeLists.txt
index 6bde263..f60dd06 100644
--- a/lib/VMCore/CMakeLists.txt
+++ b/lib/VMCore/CMakeLists.txt
@@ -29,7 +29,6 @@ add_llvm_library(LLVMCore
PassRegistry.cpp
PrintModulePass.cpp
Type.cpp
- TypeSymbolTable.cpp
Use.cpp
User.cpp
Value.cpp
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 9985ada..323e2a2 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -559,7 +559,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
res.push_back(ConstantExpr::getCast(opc,
CV->getOperand(i), DstEltTy));
- return ConstantVector::get(DestVecTy, res);
+ return ConstantVector::get(res);
}
// We actually have to do a cast now. Perform the cast according to the
@@ -730,9 +730,12 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
}
+ if (isa<UndefValue>(Cond)) {
+ if (isa<UndefValue>(V1)) return V1;
+ return V2;
+ }
if (isa<UndefValue>(V1)) return V2;
if (isa<UndefValue>(V2)) return V1;
- if (isa<UndefValue>(Cond)) return V1;
if (V1 == V2) return V1;
if (ConstantExpr *TrueVal = dyn_cast<ConstantExpr>(V1)) {
@@ -877,42 +880,38 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(Constant *V1,
}
Constant *llvm::ConstantFoldExtractValueInstruction(Constant *Agg,
- const unsigned *Idxs,
- unsigned NumIdx) {
+ ArrayRef<unsigned> Idxs) {
// Base case: no indices, so return the entire value.
- if (NumIdx == 0)
+ if (Idxs.empty())
return Agg;
if (isa<UndefValue>(Agg)) // ev(undef, x) -> undef
return UndefValue::get(ExtractValueInst::getIndexedType(Agg->getType(),
- Idxs,
- Idxs + NumIdx));
+ Idxs));
if (isa<ConstantAggregateZero>(Agg)) // ev(0, x) -> 0
return
Constant::getNullValue(ExtractValueInst::getIndexedType(Agg->getType(),
- Idxs,
- Idxs + NumIdx));
+ Idxs));
// Otherwise recurse.
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Agg))
- return ConstantFoldExtractValueInstruction(CS->getOperand(*Idxs),
- Idxs+1, NumIdx-1);
+ return ConstantFoldExtractValueInstruction(CS->getOperand(Idxs[0]),
+ Idxs.slice(1));
if (ConstantArray *CA = dyn_cast<ConstantArray>(Agg))
- return ConstantFoldExtractValueInstruction(CA->getOperand(*Idxs),
- Idxs+1, NumIdx-1);
+ return ConstantFoldExtractValueInstruction(CA->getOperand(Idxs[0]),
+ Idxs.slice(1));
ConstantVector *CV = cast<ConstantVector>(Agg);
- return ConstantFoldExtractValueInstruction(CV->getOperand(*Idxs),
- Idxs+1, NumIdx-1);
+ return ConstantFoldExtractValueInstruction(CV->getOperand(Idxs[0]),
+ Idxs.slice(1));
}
Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
Constant *Val,
- const unsigned *Idxs,
- unsigned NumIdx) {
+ ArrayRef<unsigned> Idxs) {
// Base case: no indices, so replace the entire value.
- if (NumIdx == 0)
+ if (Idxs.empty())
return Val;
if (isa<UndefValue>(Agg)) {
@@ -934,15 +933,15 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
for (unsigned i = 0; i < numOps; ++i) {
const Type *MemberTy = AggTy->getTypeAtIndex(i);
Constant *Op =
- (*Idxs == i) ?
+ (Idxs[0] == i) ?
ConstantFoldInsertValueInstruction(UndefValue::get(MemberTy),
- Val, Idxs+1, NumIdx-1) :
+ Val, Idxs.slice(1)) :
UndefValue::get(MemberTy);
Ops[i] = Op;
}
if (const StructType* ST = dyn_cast<StructType>(AggTy))
- return ConstantStruct::get(ST->getContext(), Ops, ST->isPacked());
+ return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(AggTy), Ops);
}
@@ -965,15 +964,15 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
for (unsigned i = 0; i < numOps; ++i) {
const Type *MemberTy = AggTy->getTypeAtIndex(i);
Constant *Op =
- (*Idxs == i) ?
+ (Idxs[0] == i) ?
ConstantFoldInsertValueInstruction(Constant::getNullValue(MemberTy),
- Val, Idxs+1, NumIdx-1) :
+ Val, Idxs.slice(1)) :
Constant::getNullValue(MemberTy);
Ops[i] = Op;
}
if (const StructType *ST = dyn_cast<StructType>(AggTy))
- return ConstantStruct::get(ST->getContext(), Ops, ST->isPacked());
+ return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(AggTy), Ops);
}
@@ -982,13 +981,13 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
std::vector<Constant*> Ops(Agg->getNumOperands());
for (unsigned i = 0; i < Agg->getNumOperands(); ++i) {
Constant *Op = cast<Constant>(Agg->getOperand(i));
- if (*Idxs == i)
- Op = ConstantFoldInsertValueInstruction(Op, Val, Idxs+1, NumIdx-1);
+ if (Idxs[0] == i)
+ Op = ConstantFoldInsertValueInstruction(Op, Val, Idxs.slice(1));
Ops[i] = Op;
}
if (const StructType* ST = dyn_cast<StructType>(Agg->getType()))
- return ConstantStruct::get(ST->getContext(), Ops, ST->isPacked());
+ return ConstantStruct::get(ST, Ops);
return ConstantArray::get(cast<ArrayType>(Agg->getType()), Ops);
}
@@ -1014,20 +1013,38 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::Add:
case Instruction::Sub:
return UndefValue::get(C1->getType());
- case Instruction::Mul:
case Instruction::And:
+ if (isa<UndefValue>(C1) && isa<UndefValue>(C2)) // undef & undef -> undef
+ return C1;
+ return Constant::getNullValue(C1->getType()); // undef & X -> 0
+ case Instruction::Mul: {
+ ConstantInt *CI;
+ // X * undef -> undef if X is odd or undef
+ if (((CI = dyn_cast<ConstantInt>(C1)) && CI->getValue()[0]) ||
+ ((CI = dyn_cast<ConstantInt>(C2)) && CI->getValue()[0]) ||
+ (isa<UndefValue>(C1) && isa<UndefValue>(C2)))
+ return UndefValue::get(C1->getType());
+
+ // X * undef -> 0 otherwise
return Constant::getNullValue(C1->getType());
+ }
case Instruction::UDiv:
case Instruction::SDiv:
+ // undef / 1 -> undef
+ if (Opcode == Instruction::UDiv || Opcode == Instruction::SDiv)
+ if (ConstantInt *CI2 = dyn_cast<ConstantInt>(C2))
+ if (CI2->isOne())
+ return C1;
+ // FALL THROUGH
case Instruction::URem:
case Instruction::SRem:
if (!isa<UndefValue>(C2)) // undef / X -> 0
return Constant::getNullValue(C1->getType());
return C2; // X / undef -> undef
case Instruction::Or: // X | undef -> -1
- if (const VectorType *PTy = dyn_cast<VectorType>(C1->getType()))
- return Constant::getAllOnesValue(PTy);
- return Constant::getAllOnesValue(C1->getType());
+ if (isa<UndefValue>(C1) && isa<UndefValue>(C2)) // undef | undef -> undef
+ return C1;
+ return Constant::getAllOnesValue(C1->getType()); // undef | X -> ~0
case Instruction::LShr:
if (isa<UndefValue>(C2) && isa<UndefValue>(C1))
return C1; // undef lshr undef -> undef
@@ -1041,6 +1058,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
else
return C1; // X ashr undef --> X
case Instruction::Shl:
+ if (isa<UndefValue>(C2) && isa<UndefValue>(C1))
+ return C1; // undef shl undef -> undef
// undef << X -> 0 or X << undef -> 0
return Constant::getNullValue(C1->getType());
}
@@ -1443,8 +1462,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
/// isZeroSizedType - This type is zero sized if its an array or structure of
/// zero sized types. The only leaf zero sized type is an empty structure.
static bool isMaybeZeroSizedType(const Type *Ty) {
- if (Ty->isOpaqueTy()) return true; // Can't say.
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ if (STy->isOpaque()) return true; // Can't say.
// If all of elements have zero size, this does too.
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
@@ -1831,7 +1850,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
// For EQ and NE, we can always pick a value for the undef to make the
// predicate pass or fail, so we can return undef.
- if (ICmpInst::isEquality(ICmpInst::Predicate(pred)))
+ // Also, if both operands are undef, we can return undef.
+ if (ICmpInst::isEquality(ICmpInst::Predicate(pred)) ||
+ (isa<UndefValue>(C1) && isa<UndefValue>(C2)))
return UndefValue::get(ResultTy);
// Otherwise, pick the same value as the non-undef operand, and fold
// it to true or false.
@@ -2147,9 +2168,9 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
bool inBounds,
IndexTy const *Idxs,
unsigned NumIdx) {
+ if (NumIdx == 0) return C;
Constant *Idx0 = cast<Constant>(Idxs[0]);
- if (NumIdx == 0 ||
- (NumIdx == 1 && Idx0->isNullValue()))
+ if ((NumIdx == 1 && Idx0->isNullValue()))
return C;
if (isa<UndefValue>(C)) {
diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h
index 0ecd7b4..653a1c3 100644
--- a/lib/VMCore/ConstantFold.h
+++ b/lib/VMCore/ConstantFold.h
@@ -19,6 +19,8 @@
#ifndef CONSTANTFOLDING_H
#define CONSTANTFOLDING_H
+#include "llvm/ADT/ArrayRef.h"
+
namespace llvm {
class Value;
class Constant;
@@ -38,11 +40,9 @@ namespace llvm {
Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2,
Constant *Mask);
Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
- const unsigned *Idxs,
- unsigned NumIdx);
+ ArrayRef<unsigned> Idxs);
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
- const unsigned *Idxs,
- unsigned NumIdx);
+ ArrayRef<unsigned> Idxs);
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,
Constant *V2);
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 15d7793..316c884 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -31,6 +31,7 @@
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <cstdarg>
using namespace llvm;
@@ -39,6 +40,28 @@ using namespace llvm;
// Constant Class
//===----------------------------------------------------------------------===//
+bool Constant::isNegativeZeroValue() const {
+ // Floating point values have an explicit -0.0 value.
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->isZero() && CFP->isNegative();
+
+ // Otherwise, just use +0.0.
+ return isNullValue();
+}
+
+bool Constant::isNullValue() const {
+ // 0 is null.
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
+ return CI->isZero();
+
+ // +0.0 is null.
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->isZero() && !CFP->isNegative();
+
+ // constant zero is zero for aggregates and cpnull is null for pointers.
+ return isa<ConstantAggregateZero>(this) || isa<ConstantPointerNull>(this);
+}
+
// Constructor to create a '0' constant of arbitrary type...
Constant *Constant::getNullValue(const Type *Ty) {
switch (Ty->getTypeID()) {
@@ -541,11 +564,7 @@ ConstantFP::ConstantFP(const Type *Ty, const APFloat& V)
"FP type Mismatch");
}
-bool ConstantFP::isNullValue() const {
- return Val.isZero() && !Val.isNegative();
-}
-
-bool ConstantFP::isExactlyValue(const APFloat& V) const {
+bool ConstantFP::isExactlyValue(const APFloat &V) const {
return Val.bitwiseIsEqual(V);
}
@@ -571,8 +590,7 @@ ConstantArray::ConstantArray(const ArrayType *T,
}
}
-Constant *ConstantArray::get(const ArrayType *Ty,
- const std::vector<Constant*> &V) {
+Constant *ConstantArray::get(const ArrayType *Ty, ArrayRef<Constant*> V) {
for (unsigned i = 0, e = V.size(); i != e; ++i) {
assert(V[i]->getType() == Ty->getElementType() &&
"Wrong type in array element initializer");
@@ -592,13 +610,6 @@ Constant *ConstantArray::get(const ArrayType *Ty,
return ConstantAggregateZero::get(Ty);
}
-
-Constant *ConstantArray::get(const ArrayType* T, Constant *const* Vals,
- unsigned NumVals) {
- // FIXME: make this the primary ctor method.
- return get(T, std::vector<Constant*>(Vals, Vals+NumVals));
-}
-
/// ConstantArray::get(const string&) - Return an array that is initialized to
/// contain the specified string. If length is zero then a null terminator is
/// added to the specified string so that it may be used in a natural way.
@@ -621,63 +632,64 @@ Constant *ConstantArray::get(LLVMContext &Context, StringRef Str,
return get(ATy, ElementVals);
}
+/// getTypeForElements - Return an anonymous struct type to use for a constant
+/// with the specified set of elements. The list must not be empty.
+StructType *ConstantStruct::getTypeForElements(LLVMContext &Context,
+ ArrayRef<Constant*> V,
+ bool Packed) {
+ SmallVector<Type*, 16> EltTypes;
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ EltTypes.push_back(V[i]->getType());
+
+ return StructType::get(Context, EltTypes, Packed);
+}
+
+
+StructType *ConstantStruct::getTypeForElements(ArrayRef<Constant*> V,
+ bool Packed) {
+ assert(!V.empty() &&
+ "ConstantStruct::getTypeForElements cannot be called on empty list");
+ return getTypeForElements(V[0]->getContext(), V, Packed);
+}
+
+
ConstantStruct::ConstantStruct(const StructType *T,
const std::vector<Constant*> &V)
: Constant(T, ConstantStructVal,
OperandTraits<ConstantStruct>::op_end(this) - V.size(),
V.size()) {
- assert(V.size() == T->getNumElements() &&
+ assert((T->isOpaque() || V.size() == T->getNumElements()) &&
"Invalid initializer vector for constant structure");
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
Constant *C = *I;
- assert(C->getType() == T->getElementType(I-V.begin()) &&
+ assert((T->isOpaque() || C->getType() == T->getElementType(I-V.begin())) &&
"Initializer for struct element doesn't match struct element type!");
*OL = C;
}
}
// ConstantStruct accessors.
-Constant *ConstantStruct::get(const StructType* T,
- const std::vector<Constant*>& V) {
- LLVMContextImpl* pImpl = T->getContext().pImpl;
-
- // Create a ConstantAggregateZero value if all elements are zeros...
+Constant *ConstantStruct::get(const StructType *ST, ArrayRef<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 pImpl->StructConstants.getOrCreate(T, V);
-
- return ConstantAggregateZero::get(T);
-}
-
-Constant *ConstantStruct::get(LLVMContext &Context,
- const std::vector<Constant*>& V, bool packed) {
- std::vector<const Type*> StructEls;
- StructEls.reserve(V.size());
- for (unsigned i = 0, e = V.size(); i != e; ++i)
- StructEls.push_back(V[i]->getType());
- return get(StructType::get(Context, StructEls, packed), V);
-}
+ return ST->getContext().pImpl->StructConstants.getOrCreate(ST, V);
-Constant *ConstantStruct::get(LLVMContext &Context,
- Constant *const *Vals, unsigned NumVals,
- bool Packed) {
- // FIXME: make this the primary ctor method.
- return get(Context, std::vector<Constant*>(Vals, Vals+NumVals), Packed);
+ assert((ST->isOpaque() || ST->getNumElements() == V.size()) &&
+ "Incorrect # elements specified to ConstantStruct::get");
+ return ConstantAggregateZero::get(ST);
}
-Constant* ConstantStruct::get(LLVMContext &Context, bool Packed,
- Constant * Val, ...) {
+Constant* ConstantStruct::get(const StructType *T, ...) {
va_list ap;
- std::vector<Constant*> Values;
- va_start(ap, Val);
- while (Val) {
+ SmallVector<Constant*, 8> Values;
+ va_start(ap, T);
+ while (Constant *Val = va_arg(ap, llvm::Constant*))
Values.push_back(Val);
- Val = va_arg(ap, llvm::Constant*);
- }
va_end(ap);
- return get(Context, Values, Packed);
+ return get(T, Values);
}
ConstantVector::ConstantVector(const VectorType *T,
@@ -696,9 +708,9 @@ ConstantVector::ConstantVector(const VectorType *T,
}
// ConstantVector accessors.
-Constant *ConstantVector::get(const VectorType *T,
- const std::vector<Constant*> &V) {
+Constant *ConstantVector::get(ArrayRef<Constant*> V) {
assert(!V.empty() && "Vectors can't be empty");
+ const VectorType *T = VectorType::get(V.front()->getType(), V.size());
LLVMContextImpl *pImpl = T->getContext().pImpl;
// If this is an all-undef or all-zero vector, return a
@@ -723,12 +735,6 @@ Constant *ConstantVector::get(const VectorType *T,
return pImpl->VectorConstants.getOrCreate(T, V);
}
-Constant *ConstantVector::get(ArrayRef<Constant*> V) {
- // FIXME: make this the primary ctor method.
- assert(!V.empty() && "Vectors cannot be empty");
- return get(VectorType::get(V.front()->getType(), V.size()), V.vec());
-}
-
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
// Constant.h
@@ -779,8 +785,7 @@ ArrayRef<unsigned> ConstantExpr::getIndices() const {
}
unsigned ConstantExpr::getPredicate() const {
- assert(getOpcode() == Instruction::FCmp ||
- getOpcode() == Instruction::ICmp);
+ assert(isCompare());
return ((const CompareConstantExpr*)this)->predicate;
}
@@ -851,17 +856,15 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
}
/// getWithOperands - This returns the current constant expression with the
-/// operands replaced with the specified values. The specified operands must
-/// match count and type with the existing ones.
+/// operands replaced with the specified values. The specified array must
+/// have the same number of operands as our current one.
Constant *ConstantExpr::
-getWithOperands(ArrayRef<Constant*> Ops) const {
+getWithOperands(ArrayRef<Constant*> Ops, const Type *Ty) const {
assert(Ops.size() == getNumOperands() && "Operand count mismatch!");
- bool AnyChange = false;
- for (unsigned i = 0; i != Ops.size(); ++i) {
- assert(Ops[i]->getType() == getOperand(i)->getType() &&
- "Operand type mismatch!");
+ bool AnyChange = Ty != getType();
+ for (unsigned i = 0; i != Ops.size(); ++i)
AnyChange |= Ops[i] != getOperand(i);
- }
+
if (!AnyChange) // No operands changed, return self.
return const_cast<ConstantExpr*>(this);
@@ -878,7 +881,7 @@ getWithOperands(ArrayRef<Constant*> Ops) const {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
- return ConstantExpr::getCast(getOpcode(), Ops[0], getType());
+ return ConstantExpr::getCast(getOpcode(), Ops[0], Ty);
case Instruction::Select:
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
case Instruction::InsertElement:
@@ -976,14 +979,14 @@ ConstantAggregateZero* ConstantAggregateZero::get(const Type* Ty) {
/// destroyConstant - Remove the constant from the constant table...
///
void ConstantAggregateZero::destroyConstant() {
- getRawType()->getContext().pImpl->AggZeroConstants.remove(this);
+ getType()->getContext().pImpl->AggZeroConstants.remove(this);
destroyConstantImpl();
}
/// destroyConstant - Remove the constant from the constant table...
///
void ConstantArray::destroyConstant() {
- getRawType()->getContext().pImpl->ArrayConstants.remove(this);
+ getType()->getContext().pImpl->ArrayConstants.remove(this);
destroyConstantImpl();
}
@@ -1023,44 +1026,54 @@ bool ConstantArray::isCString() const {
}
-/// getAsString - If the sub-element type of this array is i8
-/// then this method converts the array to an std::string and returns it.
-/// Otherwise, it asserts out.
+/// convertToString - Helper function for getAsString() and getAsCString().
+static std::string convertToString(const User *U, unsigned len) {
+ std::string Result;
+ Result.reserve(len);
+ for (unsigned i = 0; i != len; ++i)
+ Result.push_back((char)cast<ConstantInt>(U->getOperand(i))->getZExtValue());
+ return Result;
+}
+
+/// getAsString - If this array is isString(), then this method converts the
+/// array to an std::string and returns it. Otherwise, it asserts out.
///
std::string ConstantArray::getAsString() const {
assert(isString() && "Not a string!");
- std::string Result;
- Result.reserve(getNumOperands());
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- Result.push_back((char)cast<ConstantInt>(getOperand(i))->getZExtValue());
- return Result;
+ return convertToString(this, getNumOperands());
}
-//---- ConstantStruct::get() implementation...
-//
+/// getAsCString - If this array is isCString(), then this method converts the
+/// array (without the trailing null byte) to an std::string and returns it.
+/// Otherwise, it asserts out.
+///
+std::string ConstantArray::getAsCString() const {
+ assert(isCString() && "Not a string!");
+ return convertToString(this, getNumOperands() - 1);
+}
-namespace llvm {
-}
+//---- ConstantStruct::get() implementation...
+//
// destroyConstant - Remove the constant from the constant table...
//
void ConstantStruct::destroyConstant() {
- getRawType()->getContext().pImpl->StructConstants.remove(this);
+ getType()->getContext().pImpl->StructConstants.remove(this);
destroyConstantImpl();
}
// destroyConstant - Remove the constant from the constant table...
//
void ConstantVector::destroyConstant() {
- getRawType()->getContext().pImpl->VectorConstants.remove(this);
+ getType()->getContext().pImpl->VectorConstants.remove(this);
destroyConstantImpl();
}
/// This function will return true iff every element in this vector constant
/// is set to all ones.
-/// @returns true iff this constant's emements are all set to all ones.
+/// @returns true iff this constant's elements are all set to all ones.
/// @brief Determine if the value is all ones.
bool ConstantVector::isAllOnesValue() const {
// Check out first element.
@@ -1068,9 +1081,10 @@ bool ConstantVector::isAllOnesValue() const {
const ConstantInt *CI = dyn_cast<ConstantInt>(Elt);
if (!CI || !CI->isAllOnesValue()) return false;
// Then make sure all remaining elements point to the same value.
- for (unsigned I = 1, E = getNumOperands(); I < E; ++I) {
- if (getOperand(I) != Elt) return false;
- }
+ for (unsigned I = 1, E = getNumOperands(); I < E; ++I)
+ if (getOperand(I) != Elt)
+ return false;
+
return true;
}
@@ -1081,7 +1095,8 @@ Constant *ConstantVector::getSplatValue() const {
Constant *Elt = getOperand(0);
// Then make sure all remaining elements point to the same value.
for (unsigned I = 1, E = getNumOperands(); I < E; ++I)
- if (getOperand(I) != Elt) return 0;
+ if (getOperand(I) != Elt)
+ return 0;
return Elt;
}
@@ -1095,7 +1110,7 @@ ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) {
// destroyConstant - Remove the constant from the constant table...
//
void ConstantPointerNull::destroyConstant() {
- getRawType()->getContext().pImpl->NullPtrConstants.remove(this);
+ getType()->getContext().pImpl->NullPtrConstants.remove(this);
destroyConstantImpl();
}
@@ -1110,7 +1125,7 @@ UndefValue *UndefValue::get(const Type *Ty) {
// destroyConstant - Remove the constant from the constant table.
//
void UndefValue::destroyConstant() {
- getRawType()->getContext().pImpl->UndefValueConstants.remove(this);
+ getType()->getContext().pImpl->UndefValueConstants.remove(this);
destroyConstantImpl();
}
@@ -1144,7 +1159,7 @@ BlockAddress::BlockAddress(Function *F, BasicBlock *BB)
// destroyConstant - Remove the constant from the constant table.
//
void BlockAddress::destroyConstant() {
- getFunction()->getRawType()->getContext().pImpl
+ getFunction()->getType()->getContext().pImpl
->BlockAddresses.erase(std::make_pair(getFunction(), getBasicBlock()));
getBasicBlock()->AdjustBlockAddressRefCount(-1);
destroyConstantImpl();
@@ -1183,7 +1198,7 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
assert(NewBA != this && "I didn't contain From!");
// Everyone using this now uses the replacement.
- uncheckedReplaceAllUsesWith(NewBA);
+ replaceAllUsesWith(NewBA);
destroyConstant();
}
@@ -1420,49 +1435,15 @@ Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) {
return getFoldedCast(Instruction::BitCast, C, DstTy);
}
-Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
- Constant *C1, Constant *C2,
- unsigned Flags) {
- // Check the operands for consistency first
+Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
+ unsigned Flags) {
+ // Check the operands for consistency first.
assert(Opcode >= Instruction::BinaryOpsBegin &&
Opcode < Instruction::BinaryOpsEnd &&
"Invalid opcode in binary constant expression");
assert(C1->getType() == C2->getType() &&
"Operand types in binary constant expression should match");
-
- if (ReqTy == C1->getType() || ReqTy == Type::getInt1Ty(ReqTy->getContext()))
- if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
- return FC; // Fold a few common cases...
-
- std::vector<Constant*> argVec(1, C1); argVec.push_back(C2);
- ExprMapKeyType Key(Opcode, argVec, 0, Flags);
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
- return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
-}
-
-Constant *ConstantExpr::getCompareTy(unsigned short predicate,
- Constant *C1, Constant *C2) {
- switch (predicate) {
- default: llvm_unreachable("Invalid CmpInst predicate");
- case CmpInst::FCMP_FALSE: case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OGT:
- case CmpInst::FCMP_OGE: case CmpInst::FCMP_OLT: case CmpInst::FCMP_OLE:
- case CmpInst::FCMP_ONE: case CmpInst::FCMP_ORD: case CmpInst::FCMP_UNO:
- case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: case CmpInst::FCMP_UGE:
- case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE:
- case CmpInst::FCMP_TRUE:
- return getFCmp(predicate, C1, C2);
-
- case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT:
- case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE:
- case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT:
- case CmpInst::ICMP_SLE:
- return getICmp(predicate, C1, C2);
- }
-}
-
-Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags) {
#ifndef NDEBUG
switch (Opcode) {
case Instruction::Add:
@@ -1521,7 +1502,15 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
}
#endif
- return getTy(C1->getType(), Opcode, C1, C2, Flags);
+ if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
+ return FC; // Fold a few common cases.
+
+ std::vector<Constant*> argVec(1, C1);
+ argVec.push_back(C2);
+ ExprMapKeyType Key(Opcode, argVec, 0, Flags);
+
+ LLVMContextImpl *pImpl = C1->getContext().pImpl;
+ return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
}
Constant *ConstantExpr::getSizeOf(const Type* Ty) {
@@ -1537,8 +1526,8 @@ Constant *ConstantExpr::getSizeOf(const Type* Ty) {
Constant *ConstantExpr::getAlignOf(const Type* Ty) {
// alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
- const Type *AligningTy = StructType::get(Ty->getContext(),
- Type::getInt1Ty(Ty->getContext()), Ty, NULL);
+ const Type *AligningTy =
+ StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, NULL);
Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo());
Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0);
Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
@@ -1566,41 +1555,55 @@ Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) {
Type::getInt64Ty(Ty->getContext()));
}
-Constant *ConstantExpr::getCompare(unsigned short pred,
- Constant *C1, Constant *C2) {
+Constant *ConstantExpr::getCompare(unsigned short Predicate,
+ Constant *C1, Constant *C2) {
assert(C1->getType() == C2->getType() && "Op types should be identical!");
- return getCompareTy(pred, C1, C2);
+
+ switch (Predicate) {
+ default: llvm_unreachable("Invalid CmpInst predicate");
+ case CmpInst::FCMP_FALSE: case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OGT:
+ case CmpInst::FCMP_OGE: case CmpInst::FCMP_OLT: case CmpInst::FCMP_OLE:
+ case CmpInst::FCMP_ONE: case CmpInst::FCMP_ORD: case CmpInst::FCMP_UNO:
+ case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: case CmpInst::FCMP_UGE:
+ case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE:
+ case CmpInst::FCMP_TRUE:
+ return getFCmp(Predicate, C1, C2);
+
+ case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT:
+ case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE:
+ case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT:
+ case CmpInst::ICMP_SLE:
+ return getICmp(Predicate, C1, C2);
+ }
}
-Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C,
- Constant *V1, Constant *V2) {
+Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) {
assert(!SelectInst::areInvalidOperands(C, V1, V2)&&"Invalid select operands");
- if (ReqTy == V1->getType())
- if (Constant *SC = ConstantFoldSelectInstruction(C, V1, V2))
- return SC; // Fold common cases
+ if (Constant *SC = ConstantFoldSelectInstruction(C, V1, V2))
+ return SC; // Fold common cases
std::vector<Constant*> argVec(3, C);
argVec[1] = V1;
argVec[2] = V2;
ExprMapKeyType Key(Instruction::Select, argVec);
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
- return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
+ LLVMContextImpl *pImpl = C->getContext().pImpl;
+ return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
}
-template<typename IndexTy>
-Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
- IndexTy const *Idxs,
- unsigned NumIdx, bool InBounds) {
- assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs,
- Idxs+NumIdx) ==
- cast<PointerType>(ReqTy)->getElementType() &&
- "GEP indices invalid!");
-
+Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
+ unsigned NumIdx, bool InBounds) {
if (Constant *FC = ConstantFoldGetElementPtr(C, InBounds, Idxs, NumIdx))
return FC; // Fold a few common cases.
+ // Get the result type of the getelementptr!
+ const Type *Ty =
+ GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
+ assert(Ty && "GEP indices invalid!");
+ unsigned AS = cast<PointerType>(C->getType())->getAddressSpace();
+ Type *ReqTy = Ty->getPointerTo(AS);
+
assert(C->getType()->isPointerTy() &&
"Non-pointer type for constant GetElementPtr expression");
// Look up the constant in the table first to ensure uniqueness
@@ -1611,32 +1614,11 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
ArgVec.push_back(cast<Constant>(Idxs[i]));
const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
InBounds ? GEPOperator::IsInBounds : 0);
-
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
+
+ LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
-template<typename IndexTy>
-Constant *ConstantExpr::getGetElementPtrImpl(Constant *C, IndexTy const *Idxs,
- unsigned NumIdx, bool InBounds) {
- // Get the result type of the getelementptr!
- const Type *Ty =
- GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx);
- assert(Ty && "GEP indices invalid!");
- unsigned As = cast<PointerType>(C->getType())->getAddressSpace();
- return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx,InBounds);
-}
-
-Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs,
- unsigned NumIdx, bool InBounds) {
- return getGetElementPtrImpl(C, Idxs, NumIdx, InBounds);
-}
-
-Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant *const *Idxs,
- unsigned NumIdx, bool InBounds) {
- return getGetElementPtrImpl(C, Idxs, NumIdx, InBounds);
-}
-
Constant *
ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
assert(LHS->getType() == RHS->getType());
@@ -1684,39 +1666,22 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) {
return pImpl->ExprConstants.getOrCreate(ResultTy, Key);
}
-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(Instruction::ExtractElement,ArgVec);
-
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
- return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
-}
-
Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) {
assert(Val->getType()->isVectorTy() &&
"Tried to create extractelement operation on non-vector type!");
assert(Idx->getType()->isIntegerTy(32) &&
"Extractelement index must be i32 type!");
- return getExtractElementTy(cast<VectorType>(Val->getType())->getElementType(),
- Val, Idx);
-}
-
-Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val,
- Constant *Elt, Constant *Idx) {
- if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, 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(Elt);
ArgVec.push_back(Idx);
- const ExprMapKeyType Key(Instruction::InsertElement,ArgVec);
+ const ExprMapKeyType Key(Instruction::ExtractElement,ArgVec);
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
+ LLVMContextImpl *pImpl = Val->getContext().pImpl;
+ Type *ReqTy = cast<VectorType>(Val->getType())->getElementType();
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
@@ -1728,21 +1693,17 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
&& "Insertelement types must match!");
assert(Idx->getType()->isIntegerTy(32) &&
"Insertelement index must be i32 type!");
- return getInsertElementTy(Val->getType(), Val, Elt, Idx);
-}
-Constant *ConstantExpr::getShuffleVectorTy(const Type *ReqTy, Constant *V1,
- Constant *V2, Constant *Mask) {
- if (Constant *FC = ConstantFoldShuffleVectorInstruction(V1, V2, Mask))
- return FC; // Fold a few common cases...
+ 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, V1);
- ArgVec.push_back(V2);
- ArgVec.push_back(Mask);
- const ExprMapKeyType Key(Instruction::ShuffleVector,ArgVec);
+ std::vector<Constant*> ArgVec(1, Val);
+ ArgVec.push_back(Elt);
+ ArgVec.push_back(Idx);
+ const ExprMapKeyType Key(Instruction::InsertElement,ArgVec);
- LLVMContextImpl *pImpl = ReqTy->getContext().pImpl;
- return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
+ LLVMContextImpl *pImpl = Val->getContext().pImpl;
+ return pImpl->ExprConstants.getOrCreate(Val->getType(), Key);
}
Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
@@ -1750,62 +1711,49 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
assert(ShuffleVectorInst::isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector constant expr operands!");
+ if (Constant *FC = ConstantFoldShuffleVectorInstruction(V1, V2, Mask))
+ return FC; // Fold a few common cases.
+
unsigned NElts = cast<VectorType>(Mask->getType())->getNumElements();
const Type *EltTy = cast<VectorType>(V1->getType())->getElementType();
const Type *ShufTy = VectorType::get(EltTy, NElts);
- return getShuffleVectorTy(ShufTy, V1, V2, Mask);
-}
-Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg,
- Constant *Val,
- const unsigned *Idxs, unsigned NumIdx) {
- assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
- Idxs+NumIdx) == Val->getType() &&
- "insertvalue indices invalid!");
- assert(Agg->getType() == ReqTy &&
- "insertvalue type invalid!");
- assert(Agg->getType()->isFirstClassType() &&
- "Non-first-class type for constant InsertValue expression");
- Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs, NumIdx);
- assert(FC && "InsertValue constant expr couldn't be folded!");
- return FC;
+ // Look up the constant in the table first to ensure uniqueness
+ std::vector<Constant*> ArgVec(1, V1);
+ ArgVec.push_back(V2);
+ ArgVec.push_back(Mask);
+ const ExprMapKeyType Key(Instruction::ShuffleVector,ArgVec);
+
+ LLVMContextImpl *pImpl = ShufTy->getContext().pImpl;
+ return pImpl->ExprConstants.getOrCreate(ShufTy, Key);
}
Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
- const unsigned *IdxList, unsigned NumIdx) {
- assert(Agg->getType()->isFirstClassType() &&
- "Tried to create insertelement operation on non-first-class type!");
-
- const Type *ReqTy = Agg->getType();
-#ifndef NDEBUG
- const Type *ValTy =
- ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
-#endif
- assert(ValTy == Val->getType() && "insertvalue indices invalid!");
- return getInsertValueTy(ReqTy, Agg, Val, IdxList, NumIdx);
-}
-
-Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg,
- const unsigned *Idxs, unsigned NumIdx) {
- assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs,
- Idxs+NumIdx) == ReqTy &&
- "extractvalue indices invalid!");
+ ArrayRef<unsigned> Idxs) {
+ assert(ExtractValueInst::getIndexedType(Agg->getType(),
+ Idxs) == Val->getType() &&
+ "insertvalue indices invalid!");
assert(Agg->getType()->isFirstClassType() &&
- "Non-first-class type for constant extractvalue expression");
- Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs, NumIdx);
- assert(FC && "ExtractValue constant expr couldn't be folded!");
+ "Non-first-class type for constant insertvalue expression");
+ Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs);
+ assert(FC && "insertvalue constant expr couldn't be folded!");
return FC;
}
Constant *ConstantExpr::getExtractValue(Constant *Agg,
- const unsigned *IdxList, unsigned NumIdx) {
+ ArrayRef<unsigned> Idxs) {
assert(Agg->getType()->isFirstClassType() &&
"Tried to create extractelement operation on non-first-class type!");
- const Type *ReqTy =
- ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx);
+ const Type *ReqTy = ExtractValueInst::getIndexedType(Agg->getType(), Idxs);
+ (void)ReqTy;
assert(ReqTy && "extractvalue indices invalid!");
- return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx);
+
+ assert(Agg->getType()->isFirstClassType() &&
+ "Non-first-class type for constant extractvalue expression");
+ Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs);
+ assert(FC && "ExtractValue constant expr couldn't be folded!");
+ return FC;
}
Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) {
@@ -1918,7 +1866,7 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) {
// destroyConstant - Remove the constant from the constant table...
//
void ConstantExpr::destroyConstant() {
- getRawType()->getContext().pImpl->ExprConstants.remove(this);
+ getType()->getContext().pImpl->ExprConstants.remove(this);
destroyConstantImpl();
}
@@ -1959,10 +1907,10 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
- LLVMContextImpl *pImpl = getRawType()->getContext().pImpl;
+ LLVMContextImpl *pImpl = getType()->getContext().pImpl;
std::pair<LLVMContextImpl::ArrayConstantsTy::MapKey, ConstantArray*> Lookup;
- Lookup.first.first = cast<ArrayType>(getRawType());
+ Lookup.first.first = cast<ArrayType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
@@ -1996,7 +1944,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Constant *Replacement = 0;
if (isAllZeros) {
- Replacement = ConstantAggregateZero::get(getRawType());
+ Replacement = ConstantAggregateZero::get(getType());
} else {
// Check to see if we have this array type already.
bool Exists;
@@ -2032,7 +1980,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement.
- uncheckedReplaceAllUsesWith(Replacement);
+ replaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
@@ -2047,7 +1995,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
std::pair<LLVMContextImpl::StructConstantsTy::MapKey, ConstantStruct*> Lookup;
- Lookup.first.first = cast<StructType>(getRawType());
+ Lookup.first.first = cast<StructType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
Values.reserve(getNumOperands()); // Build replacement struct.
@@ -2069,11 +2017,11 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
}
Values[OperandToUpdate] = ToC;
- LLVMContextImpl *pImpl = getRawType()->getContext().pImpl;
+ LLVMContextImpl *pImpl = getContext().pImpl;
Constant *Replacement = 0;
if (isAllZeros) {
- Replacement = ConstantAggregateZero::get(getRawType());
+ Replacement = ConstantAggregateZero::get(getType());
} else {
// Check to see if we have this struct type already.
bool Exists;
@@ -2098,7 +2046,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement.
- uncheckedReplaceAllUsesWith(Replacement);
+ replaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
@@ -2116,11 +2064,11 @@ void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
Values.push_back(Val);
}
- Constant *Replacement = get(cast<VectorType>(getRawType()), Values);
+ Constant *Replacement = get(Values);
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement.
- uncheckedReplaceAllUsesWith(Replacement);
+ replaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
@@ -2151,8 +2099,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
if (Agg == From) Agg = To;
ArrayRef<unsigned> Indices = getIndices();
- Replacement = ConstantExpr::getExtractValue(Agg,
- &Indices[0], Indices.size());
+ Replacement = ConstantExpr::getExtractValue(Agg, Indices);
} else if (getOpcode() == Instruction::InsertValue) {
Constant *Agg = getOperand(0);
Constant *Val = getOperand(1);
@@ -2160,11 +2107,10 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
if (Val == From) Val = To;
ArrayRef<unsigned> Indices = getIndices();
- Replacement = ConstantExpr::getInsertValue(Agg, Val,
- &Indices[0], Indices.size());
+ Replacement = ConstantExpr::getInsertValue(Agg, Val, Indices);
} else if (isCast()) {
assert(getOperand(0) == From && "Cast only has one use!");
- Replacement = ConstantExpr::getCast(getOpcode(), To, getRawType());
+ Replacement = ConstantExpr::getCast(getOpcode(), To, getType());
} else if (getOpcode() == Instruction::Select) {
Constant *C1 = getOperand(0);
Constant *C2 = getOperand(1);
@@ -2220,7 +2166,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
assert(Replacement != this && "I didn't contain From!");
// Everyone using this now uses the replacement.
- uncheckedReplaceAllUsesWith(Replacement);
+ replaceAllUsesWith(Replacement);
// Delete the old constant!
destroyConstant();
diff --git a/lib/VMCore/ConstantsContext.h b/lib/VMCore/ConstantsContext.h
index 1395754..bd134d9 100644
--- a/lib/VMCore/ConstantsContext.h
+++ b/lib/VMCore/ConstantsContext.h
@@ -568,15 +568,13 @@ struct ConstantKeyData<InlineAsm> {
}
};
-template<class ValType, class TypeClass, class ConstantClass,
+template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
bool HasLargeKey = false /*true for arrays and structs*/ >
-class ConstantUniqueMap : public AbstractTypeUser {
+class ConstantUniqueMap {
public:
typedef std::pair<const TypeClass*, ValType> MapKey;
typedef std::map<MapKey, ConstantClass *> MapTy;
typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
- typedef std::map<const DerivedType*, typename MapTy::iterator>
- AbstractTypeMapTy;
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
@@ -589,10 +587,6 @@ private:
/// through the map with very large keys.
InverseMapTy InverseMap;
- /// AbstractTypeMap - Map for abstract type constants.
- ///
- AbstractTypeMapTy AbstractTypeMap;
-
public:
typename MapTy::iterator map_begin() { return Map.begin(); }
typename MapTy::iterator map_end() { return Map.end(); }
@@ -629,7 +623,7 @@ private:
}
typename MapTy::iterator I =
- Map.find(MapKey(static_cast<const TypeClass*>(CP->getRawType()),
+ Map.find(MapKey(static_cast<const TypeClass*>(CP->getType()),
ConstantKeyData<ConstantClass>::getValType(CP)));
if (I == Map.end() || I->second != CP) {
// FIXME: This should not use a linear scan. If this gets to be a
@@ -639,24 +633,8 @@ private:
}
return I;
}
-
- void AddAbstractTypeUser(const Type *Ty, typename MapTy::iterator I) {
- // If the type of the constant is abstract, make sure that an entry
- // exists for it in the AbstractTypeMap.
- if (Ty->isAbstract()) {
- const DerivedType *DTy = static_cast<const DerivedType *>(Ty);
- typename AbstractTypeMapTy::iterator TI = AbstractTypeMap.find(DTy);
-
- if (TI == AbstractTypeMap.end()) {
- // Add ourselves to the ATU list of the type.
- cast<DerivedType>(DTy)->addAbstractTypeUser(this);
-
- AbstractTypeMap.insert(TI, std::make_pair(DTy, I));
- }
- }
- }
- ConstantClass* Create(const TypeClass *Ty, const ValType &V,
+ ConstantClass *Create(const TypeClass *Ty, ValRefType V,
typename MapTy::iterator I) {
ConstantClass* Result =
ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
@@ -667,15 +645,13 @@ private:
if (HasLargeKey) // Remember the reverse mapping if needed.
InverseMap.insert(std::make_pair(Result, I));
- AddAbstractTypeUser(Ty, I);
-
return Result;
}
public:
/// getOrCreate - Return the specified constant from the map, creating it if
/// necessary.
- ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) {
+ ConstantClass *getOrCreate(const TypeClass *Ty, ValRefType V) {
MapKey Lookup(Ty, V);
ConstantClass* Result = 0;
@@ -692,43 +668,6 @@ public:
return Result;
}
- void UpdateAbstractTypeMap(const DerivedType *Ty,
- typename MapTy::iterator I) {
- assert(AbstractTypeMap.count(Ty) &&
- "Abstract type not in AbstractTypeMap?");
- typename MapTy::iterator &ATMEntryIt = AbstractTypeMap[Ty];
- if (ATMEntryIt == I) {
- // Yes, we are removing the representative entry for this type.
- // See if there are any other entries of the same type.
- typename MapTy::iterator TmpIt = ATMEntryIt;
-
- // First check the entry before this one...
- if (TmpIt != Map.begin()) {
- --TmpIt;
- if (TmpIt->first.first != Ty) // Not the same type, move back...
- ++TmpIt;
- }
-
- // If we didn't find the same type, try to move forward...
- if (TmpIt == ATMEntryIt) {
- ++TmpIt;
- if (TmpIt == Map.end() || TmpIt->first.first != Ty)
- --TmpIt; // No entry afterwards with the same type
- }
-
- // If there is another entry in the map of the same abstract type,
- // update the AbstractTypeMap entry now.
- if (TmpIt != ATMEntryIt) {
- ATMEntryIt = TmpIt;
- } else {
- // Otherwise, we are removing the last instance of this type
- // from the table. Remove from the ATM, and from user list.
- cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
- AbstractTypeMap.erase(Ty);
- }
- }
- }
-
void remove(ConstantClass *CP) {
typename MapTy::iterator I = FindExistingElement(CP);
assert(I != Map.end() && "Constant not found in constant table!");
@@ -736,12 +675,6 @@ public:
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;
- if (Ty->isAbstract())
- UpdateAbstractTypeMap(static_cast<const DerivedType *>(Ty), I);
Map.erase(I);
}
@@ -755,22 +688,7 @@ public:
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.
- //
- // This must use getRawType() because if the type is under refinement, we
- // will get the refineAbstractType callback below, and we don't want to
- // kick union find in on the constant.
- if (C->getRawType()->isAbstract()) {
- typename AbstractTypeMapTy::iterator ATI =
- AbstractTypeMap.find(cast<DerivedType>(C->getRawType()));
- assert(ATI != AbstractTypeMap.end() &&
- "Abstract type not in AbstractTypeMap?");
- if (ATI->second == OldI)
- ATI->second = I;
- }
-
- // Remove the old entry from the map.
+ // Remove the old entry from the map.
Map.erase(OldI);
// Update the inverse map so that we know that this constant is now
@@ -780,58 +698,6 @@ public:
InverseMap[C] = I;
}
}
-
- void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
- typename AbstractTypeMapTy::iterator I = AbstractTypeMap.find(OldTy);
-
- assert(I != AbstractTypeMap.end() &&
- "Abstract type not in AbstractTypeMap?");
-
- // Convert a constant at a time until the last one is gone. The last one
- // leaving will remove() itself, causing the AbstractTypeMapEntry to be
- // eliminated eventually.
- do {
- ConstantClass *C = I->second->second;
- MapKey Key(cast<TypeClass>(NewTy),
- ConstantKeyData<ConstantClass>::getValType(C));
-
- std::pair<typename MapTy::iterator, bool> IP =
- Map.insert(std::make_pair(Key, C));
- if (IP.second) {
- // The map didn't previously have an appropriate constant in the
- // new type.
-
- // Remove the old entry.
- typename MapTy::iterator OldI =
- Map.find(MapKey(cast<TypeClass>(OldTy), IP.first->first.second));
- assert(OldI != Map.end() && "Constant not in map!");
- UpdateAbstractTypeMap(OldTy, OldI);
- Map.erase(OldI);
-
- // Set the constant's type. This is done in place!
- setType(C, NewTy);
-
- // Update the inverse map so that we know that this constant is now
- // located at descriptor I.
- if (HasLargeKey)
- InverseMap[C] = IP.first;
-
- AddAbstractTypeUser(NewTy, IP.first);
- } else {
- // The map already had an appropriate constant in the new type, so
- // there's no longer a need for the old constant.
- C->uncheckedReplaceAllUsesWith(IP.first->second);
- C->destroyConstant(); // This constant is now dead, destroy it.
- }
- I = AbstractTypeMap.find(OldTy);
- } while (I != AbstractTypeMap.end());
- }
-
- // If the type became concrete without being refined to any other existing
- // type, we just remove ourselves from the ATU list.
- void typeBecameConcrete(const DerivedType *AbsTy) {
- AbsTy->removeAbstractTypeUser(this);
- }
void dump() const {
DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp
index 92f9440..2a816e1 100644
--- a/lib/VMCore/Core.cpp
+++ b/lib/VMCore/Core.cpp
@@ -19,7 +19,6 @@
#include "llvm/GlobalVariable.h"
#include "llvm/GlobalAlias.h"
#include "llvm/LLVMContext.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/InlineAsm.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/PassManager.h"
@@ -111,27 +110,6 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple) {
unwrap(M)->setTargetTriple(Triple);
}
-/*--.. Type names ..........................................................--*/
-LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
- return unwrap(M)->addTypeName(Name, unwrap(Ty));
-}
-
-void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name) {
- TypeSymbolTable &TST = unwrap(M)->getTypeSymbolTable();
-
- TypeSymbolTable::iterator I = TST.find(Name);
- if (I != TST.end())
- TST.remove(I);
-}
-
-LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name) {
- return wrap(unwrap(M)->getTypeByName(Name));
-}
-
-const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty) {
- return unwrap(M)->getTypeName(unwrap(Ty)).c_str();
-}
-
void LLVMDumpModule(LLVMModuleRef M) {
unwrap(M)->dump();
}
@@ -182,8 +160,6 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
return LLVMArrayTypeKind;
case Type::PointerTyID:
return LLVMPointerTypeKind;
- case Type::OpaqueTyID:
- return LLVMOpaqueTypeKind;
case Type::VectorTyID:
return LLVMVectorTypeKind;
case Type::X86_MMXTyID:
@@ -284,10 +260,7 @@ LLVMTypeRef LLVMX86MMXType(void) {
LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType,
LLVMTypeRef *ParamTypes, unsigned ParamCount,
LLVMBool IsVarArg) {
- std::vector<const Type*> Tys;
- for (LLVMTypeRef *I = ParamTypes, *E = ParamTypes + ParamCount; I != E; ++I)
- Tys.push_back(unwrap(*I));
-
+ ArrayRef<Type*> Tys(unwrap(ParamTypes), ParamCount);
return wrap(FunctionType::get(unwrap(ReturnType), Tys, IsVarArg != 0));
}
@@ -314,11 +287,7 @@ void LLVMGetParamTypes(LLVMTypeRef FunctionTy, LLVMTypeRef *Dest) {
LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes,
unsigned ElementCount, LLVMBool Packed) {
- std::vector<const Type*> Tys;
- for (LLVMTypeRef *I = ElementTypes,
- *E = ElementTypes + ElementCount; I != E; ++I)
- Tys.push_back(unwrap(*I));
-
+ ArrayRef<Type*> Tys(unwrap(ElementTypes), ElementCount);
return wrap(StructType::get(*unwrap(C), Tys, Packed != 0));
}
@@ -328,6 +297,16 @@ LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes,
ElementCount, Packed);
}
+LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name)
+{
+ return wrap(StructType::createNamed(*unwrap(C), Name));
+}
+
+void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes,
+ unsigned ElementCount, LLVMBool Packed) {
+ ArrayRef<Type*> Tys(unwrap(ElementTypes), ElementCount);
+ unwrap<StructType>(StructTy)->setBody(Tys, Packed != 0);
+}
unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy) {
return unwrap<StructType>(StructTy)->getNumElements();
@@ -344,6 +323,14 @@ LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy) {
return unwrap<StructType>(StructTy)->isPacked();
}
+LLVMBool LLVMIsOpaqueStruct(LLVMTypeRef StructTy) {
+ return unwrap<StructType>(StructTy)->isOpaque();
+}
+
+LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name) {
+ return wrap(unwrap(M)->getTypeByName(Name));
+}
+
/*--.. Operations on array, pointer, and vector types (sequence types) .....--*/
LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount) {
@@ -382,9 +369,6 @@ LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C) {
LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C) {
return wrap(Type::getLabelTy(*unwrap(C)));
}
-LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C) {
- return wrap(OpaqueType::get(*unwrap(C)));
-}
LLVMTypeRef LLVMVoidType(void) {
return LLVMVoidTypeInContext(LLVMGetGlobalContext());
@@ -392,28 +376,6 @@ LLVMTypeRef LLVMVoidType(void) {
LLVMTypeRef LLVMLabelType(void) {
return LLVMLabelTypeInContext(LLVMGetGlobalContext());
}
-LLVMTypeRef LLVMOpaqueType(void) {
- return LLVMOpaqueTypeInContext(LLVMGetGlobalContext());
-}
-
-/*--.. Operations on type handles ..........................................--*/
-
-LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy) {
- return wrap(new PATypeHolder(unwrap(PotentiallyAbstractTy)));
-}
-
-void LLVMDisposeTypeHandle(LLVMTypeHandleRef TypeHandle) {
- delete unwrap(TypeHandle);
-}
-
-LLVMTypeRef LLVMResolveTypeHandle(LLVMTypeHandleRef TypeHandle) {
- return wrap(unwrap(TypeHandle)->get());
-}
-
-void LLVMRefineType(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy) {
- unwrap<DerivedType>(AbstractTy)->refineAbstractTypeTo(unwrap(ConcreteTy));
-}
-
/*===-- Operations on values ----------------------------------------------===*/
@@ -612,9 +574,10 @@ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str,
LLVMValueRef LLVMConstStructInContext(LLVMContextRef C,
LLVMValueRef *ConstantVals,
unsigned Count, LLVMBool Packed) {
- return wrap(ConstantStruct::get(*unwrap(C),
- unwrap<Constant>(ConstantVals, Count),
- Count, Packed != 0));
+ Constant **Elements = unwrap<Constant>(ConstantVals, Count);
+ return wrap(ConstantStruct::getAnon(*unwrap(C),
+ ArrayRef<Constant*>(Elements, Count),
+ Packed != 0));
}
LLVMValueRef LLVMConstString(const char *Str, unsigned Length,
@@ -624,15 +587,24 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length,
}
LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy,
LLVMValueRef *ConstantVals, unsigned Length) {
- return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length),
- unwrap<Constant>(ConstantVals, Length),
- Length));
+ ArrayRef<Constant*> V(unwrap<Constant>(ConstantVals, Length), Length);
+ return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V));
}
LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count,
LLVMBool Packed) {
return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count,
Packed);
}
+
+LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy,
+ LLVMValueRef *ConstantVals,
+ unsigned Count) {
+ Constant **Elements = unwrap<Constant>(ConstantVals, Count);
+ const StructType *Ty = cast<StructType>(unwrap(StructTy));
+
+ return wrap(ConstantStruct::get(Ty, ArrayRef<Constant*>(Elements, Count)));
+}
+
LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size) {
return wrap(ConstantVector::get(ArrayRef<Constant*>(
unwrap<Constant>(ScalarConstantVals, Size), Size)));
@@ -962,7 +934,8 @@ LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant,
LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList,
unsigned NumIdx) {
return wrap(ConstantExpr::getExtractValue(unwrap<Constant>(AggConstant),
- IdxList, NumIdx));
+ ArrayRef<unsigned>(IdxList,
+ NumIdx)));
}
LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
@@ -970,7 +943,8 @@ LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant,
unsigned *IdxList, unsigned NumIdx) {
return wrap(ConstantExpr::getInsertValue(unwrap<Constant>(AggConstant),
unwrap<Constant>(ElementValueConstant),
- IdxList, NumIdx));
+ ArrayRef<unsigned>(IdxList,
+ NumIdx)));
}
LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, const char *AsmString,
@@ -1706,7 +1680,7 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name) {
return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
- unwrap(Args), unwrap(Args) + NumArgs,
+ ArrayRef<Value *>(unwrap(Args), NumArgs),
Name));
}
@@ -2089,8 +2063,9 @@ LLVMValueRef LLVMBuildPhi(LLVMBuilderRef B, LLVMTypeRef Ty, const char *Name) {
LLVMValueRef LLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name) {
- return wrap(unwrap(B)->CreateCall(unwrap(Fn), unwrap(Args),
- unwrap(Args) + NumArgs, Name));
+ return wrap(unwrap(B)->CreateCall(unwrap(Fn),
+ ArrayRef<Value *>(unwrap(Args), NumArgs),
+ Name));
}
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef B, LLVMValueRef If,
diff --git a/lib/VMCore/DebugLoc.cpp b/lib/VMCore/DebugLoc.cpp
index 520333c..4ff6b2c 100644
--- a/lib/VMCore/DebugLoc.cpp
+++ b/lib/VMCore/DebugLoc.cpp
@@ -128,6 +128,38 @@ DebugLoc DebugLoc::getFromDILocation(MDNode *N) {
return get(LineNo, ColNo, Scope, dyn_cast_or_null<MDNode>(N->getOperand(3)));
}
+/// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc.
+DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) {
+ if (N == 0 || N->getNumOperands() < 3) return DebugLoc();
+
+ MDNode *Scope = dyn_cast_or_null<MDNode>(N->getOperand(1));
+ if (Scope == 0) return DebugLoc();
+
+ unsigned LineNo = 0, ColNo = 0;
+ if (ConstantInt *Line = dyn_cast_or_null<ConstantInt>(N->getOperand(2)))
+ LineNo = Line->getZExtValue();
+ if (ConstantInt *Col = dyn_cast_or_null<ConstantInt>(N->getOperand(3)))
+ ColNo = Col->getZExtValue();
+
+ return get(LineNo, ColNo, Scope, NULL);
+}
+
+void DebugLoc::dump(const LLVMContext &Ctx) const {
+#ifndef NDEBUG
+ if (!isUnknown()) {
+ dbgs() << getLine();
+ if (getCol() != 0)
+ dbgs() << ',' << getCol();
+ DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx));
+ if (!InlinedAtDL.isUnknown()) {
+ dbgs() << " @ ";
+ InlinedAtDL.dump(Ctx);
+ } else
+ dbgs() << "\n";
+ }
+#endif
+}
+
//===----------------------------------------------------------------------===//
// DenseMap specialization
//===----------------------------------------------------------------------===//
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index 0ae0bdb..6536bcd 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -134,7 +134,7 @@ LLVMContext &Function::getContext() const {
return getType()->getContext();
}
-const FunctionType *Function::getFunctionType() const {
+FunctionType *Function::getFunctionType() const {
return cast<FunctionType>(getType()->getElementType());
}
@@ -142,7 +142,7 @@ bool Function::isVarArg() const {
return getFunctionType()->isVarArg();
}
-const Type *Function::getReturnType() const {
+Type *Function::getReturnType() const {
return getFunctionType()->getReturnType();
}
@@ -163,7 +163,7 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
: GlobalValue(PointerType::getUnqual(Ty),
Value::FunctionVal, 0, 0, Linkage, name) {
assert(FunctionType::isValidReturnType(getReturnType()) &&
- !getReturnType()->isOpaqueTy() && "invalid return type");
+ "invalid return type");
SymTab = new ValueSymbolTable();
// If the function has arguments, mark them as lazily built.
@@ -333,7 +333,7 @@ unsigned Function::getIntrinsicID() const {
return 0;
}
-std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) {
+std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
assert(id < num_intrinsics && "Invalid intrinsic ID!");
static const char * const Table[] = {
"not_intrinsic",
@@ -341,10 +341,10 @@ std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) {
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_NAME_TABLE
};
- if (numTys == 0)
+ if (Tys.empty())
return Table[id];
std::string Result(Table[id]);
- for (unsigned i = 0; i < numTys; ++i) {
+ for (unsigned i = 0; i < Tys.size(); ++i) {
if (const PointerType* PTyp = dyn_cast<PointerType>(Tys[i])) {
Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) +
EVT::getEVT(PTyp->getElementType()).getEVTString();
@@ -356,10 +356,9 @@ std::string Intrinsic::getName(ID id, const Type **Tys, unsigned numTys) {
}
const FunctionType *Intrinsic::getType(LLVMContext &Context,
- ID id, const Type **Tys,
- unsigned numTys) {
+ ID id, ArrayRef<Type*> Tys) {
const Type *ResultTy = NULL;
- std::vector<const Type*> ArgTys;
+ std::vector<Type*> ArgTys;
bool IsVarArg = false;
#define GET_INTRINSIC_GENERATOR
@@ -384,14 +383,12 @@ bool Intrinsic::isOverloaded(ID id) {
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_ATTRIBUTES
-Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
- unsigned numTys) {
+Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
// There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type.
return
- cast<Function>(M->getOrInsertFunction(getName(id, Tys, numTys),
- getType(M->getContext(),
- id, Tys, numTys)));
+ cast<Function>(M->getOrInsertFunction(getName(id, Tys),
+ getType(M->getContext(), id, Tys)));
}
// This defines the "Intrinsic::getIntrinsicForGCCBuiltin()" method.
@@ -417,7 +414,7 @@ bool Function::hasAddressTaken(const User* *PutOffender) const {
/// setjmp or other function that gcc recognizes as "returning twice".
///
/// FIXME: Remove after <rdar://problem/8031714> is fixed.
-/// FIXME: Is the obove FIXME valid?
+/// FIXME: Is the above FIXME valid?
bool Function::callsFunctionThatReturnsTwice() const {
const Module *M = this->getParent();
static const char *ReturnsTwiceFns[] = {
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index 60000ad..db008e0 100644
--- a/lib/VMCore/Globals.cpp
+++ b/lib/VMCore/Globals.cpp
@@ -51,6 +51,7 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {
setAlignment(Src->getAlignment());
setSection(Src->getSection());
setVisibility(Src->getVisibility());
+ setUnnamedAddr(Src->hasUnnamedAddr());
}
void GlobalValue::setAlignment(unsigned Align) {
@@ -60,6 +61,20 @@ void GlobalValue::setAlignment(unsigned Align) {
Alignment = Log2_32(Align) + 1;
assert(getAlignment() == Align && "Alignment representation error!");
}
+
+bool GlobalValue::isDeclaration() const {
+ // Globals are definitions if they have an initializer.
+ if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(this))
+ return GV->getNumOperands() == 0;
+
+ // Functions are definitions if they have a body.
+ if (const Function *F = dyn_cast<Function>(this))
+ return F->empty();
+
+ // Aliases are always definitions.
+ assert(isa<GlobalAlias>(this));
+ return false;
+}
//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
@@ -201,39 +216,26 @@ void GlobalAlias::eraseFromParent() {
getParent()->getAliasList().erase(this);
}
-bool GlobalAlias::isDeclaration() const {
- const GlobalValue* AV = getAliasedGlobal();
- if (AV)
- return AV->isDeclaration();
- else
- return false;
-}
-
-void GlobalAlias::setAliasee(Constant *Aliasee)
-{
- if (Aliasee)
- assert(Aliasee->getType() == getType() &&
- "Alias and aliasee types should match!");
+void GlobalAlias::setAliasee(Constant *Aliasee) {
+ assert((!Aliasee || Aliasee->getType() == getType()) &&
+ "Alias and aliasee types should match!");
setOperand(0, Aliasee);
}
const GlobalValue *GlobalAlias::getAliasedGlobal() const {
const Constant *C = getAliasee();
- if (C) {
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- return GV;
- else {
- const ConstantExpr *CE = 0;
- if ((CE = dyn_cast<ConstantExpr>(C)) &&
- (CE->getOpcode() == Instruction::BitCast ||
- CE->getOpcode() == Instruction::GetElementPtr))
- return dyn_cast<GlobalValue>(CE->getOperand(0));
- else
- llvm_unreachable("Unsupported aliasee");
- }
- }
- return 0;
+ if (C == 0) return 0;
+
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ return GV;
+
+ const ConstantExpr *CE = cast<ConstantExpr>(C);
+ assert((CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::GetElementPtr) &&
+ "Unsupported aliasee");
+
+ return dyn_cast<GlobalValue>(CE->getOperand(0));
}
const GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) const {
@@ -254,7 +256,7 @@ const GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) const {
GV = GA->getAliasedGlobal();
if (!Visited.insert(GV))
- return NULL;
+ return 0;
}
return GV;
diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp
index f2d469a..ffe961f 100644
--- a/lib/VMCore/IRBuilder.cpp
+++ b/lib/VMCore/IRBuilder.cpp
@@ -34,7 +34,7 @@ Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) {
return GV;
}
-const Type *IRBuilderBase::getCurrentFunctionReturnType() const {
+Type *IRBuilderBase::getCurrentFunctionReturnType() const {
assert(BB && BB->getParent() && "No current function!");
return BB->getParent()->getReturnType();
}
@@ -52,9 +52,9 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) {
return BCI;
}
-static CallInst *createCallHelper(Value *Callee, Value *const* Ops,
- unsigned NumOps, IRBuilderBase *Builder) {
- CallInst *CI = CallInst::Create(Callee, Ops, Ops + NumOps, "");
+static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops,
+ IRBuilderBase *Builder) {
+ CallInst *CI = CallInst::Create(Callee, Ops, "");
Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),CI);
Builder->SetInstDebugLocation(CI);
return CI;
@@ -65,11 +65,11 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
bool isVolatile, MDNode *TBAATag) {
Ptr = getCastedInt8PtrValue(Ptr);
Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) };
- const Type *Tys[] = { Ptr->getType(), Size->getType() };
+ Type *Tys[] = { Ptr->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
- Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 2);
+ Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys);
- CallInst *CI = createCallHelper(TheFn, Ops, 5, this);
+ CallInst *CI = createCallHelper(TheFn, Ops, this);
// Set the TBAA info if present.
if (TBAATag)
@@ -85,11 +85,11 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
Src = getCastedInt8PtrValue(Src);
Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) };
- const Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
+ Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
- Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys, 3);
+ Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys);
- CallInst *CI = createCallHelper(TheFn, Ops, 5, this);
+ CallInst *CI = createCallHelper(TheFn, Ops, this);
// Set the TBAA info if present.
if (TBAATag)
@@ -105,11 +105,11 @@ CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
Src = getCastedInt8PtrValue(Src);
Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) };
- const Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
+ Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
- Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys, 3);
+ Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys);
- CallInst *CI = createCallHelper(TheFn, Ops, 5, this);
+ CallInst *CI = createCallHelper(TheFn, Ops, this);
// Set the TBAA info if present.
if (TBAATag)
@@ -130,7 +130,7 @@ CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) {
Value *Ops[] = { Size, Ptr };
Module *M = BB->getParent()->getParent();
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_start);
- return createCallHelper(TheFn, Ops, 2, this);
+ return createCallHelper(TheFn, Ops, this);
}
CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) {
@@ -145,5 +145,5 @@ CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) {
Value *Ops[] = { Size, Ptr };
Module *M = BB->getParent()->getParent();
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end);
- return createCallHelper(TheFn, Ops, 2, this);
+ return createCallHelper(TheFn, Ops, this);
}
diff --git a/lib/VMCore/InlineAsm.cpp b/lib/VMCore/InlineAsm.cpp
index bd3667d..4a03b39 100644
--- a/lib/VMCore/InlineAsm.cpp
+++ b/lib/VMCore/InlineAsm.cpp
@@ -47,11 +47,11 @@ InlineAsm::InlineAsm(const PointerType *Ty, const std::string &asmString,
}
void InlineAsm::destroyConstant() {
- getRawType()->getContext().pImpl->InlineAsms.remove(this);
+ getType()->getContext().pImpl->InlineAsms.remove(this);
delete this;
}
-const FunctionType *InlineAsm::getFunctionType() const {
+FunctionType *InlineAsm::getFunctionType() const {
return cast<FunctionType>(getType()->getElementType());
}
diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp
index 2c8b8b2..02c0757 100644
--- a/lib/VMCore/Instruction.cpp
+++ b/lib/VMCore/Instruction.cpp
@@ -204,22 +204,10 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
if (const InvokeInst *CI = dyn_cast<InvokeInst>(this))
return CI->getCallingConv() == cast<InvokeInst>(I)->getCallingConv() &&
CI->getAttributes() == cast<InvokeInst>(I)->getAttributes();
- if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(this)) {
- if (IVI->getNumIndices() != cast<InsertValueInst>(I)->getNumIndices())
- return false;
- for (unsigned i = 0, e = IVI->getNumIndices(); i != e; ++i)
- if (IVI->idx_begin()[i] != cast<InsertValueInst>(I)->idx_begin()[i])
- return false;
- return true;
- }
- if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this)) {
- if (EVI->getNumIndices() != cast<ExtractValueInst>(I)->getNumIndices())
- return false;
- for (unsigned i = 0, e = EVI->getNumIndices(); i != e; ++i)
- if (EVI->idx_begin()[i] != cast<ExtractValueInst>(I)->idx_begin()[i])
- return false;
- return true;
- }
+ if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(this))
+ return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
+ if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
+ return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
return true;
}
@@ -256,22 +244,10 @@ bool Instruction::isSameOperationAs(const Instruction *I) const {
return CI->getCallingConv() == cast<InvokeInst>(I)->getCallingConv() &&
CI->getAttributes() ==
cast<InvokeInst>(I)->getAttributes();
- if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(this)) {
- if (IVI->getNumIndices() != cast<InsertValueInst>(I)->getNumIndices())
- return false;
- for (unsigned i = 0, e = IVI->getNumIndices(); i != e; ++i)
- if (IVI->idx_begin()[i] != cast<InsertValueInst>(I)->idx_begin()[i])
- return false;
- return true;
- }
- if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this)) {
- if (EVI->getNumIndices() != cast<ExtractValueInst>(I)->getNumIndices())
- return false;
- for (unsigned i = 0, e = EVI->getNumIndices(); i != e; ++i)
- if (EVI->idx_begin()[i] != cast<ExtractValueInst>(I)->idx_begin()[i])
- return false;
- return true;
- }
+ if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(this))
+ return IVI->getIndices() == cast<InsertValueInst>(I)->getIndices();
+ if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(this))
+ return EVI->getIndices() == cast<ExtractValueInst>(I)->getIndices();
return true;
}
@@ -429,8 +405,10 @@ Instruction *Instruction::clone() const {
// Otherwise, enumerate and copy over metadata from the old instruction to the
// new one.
SmallVector<std::pair<unsigned, MDNode*>, 4> TheMDs;
- getAllMetadata(TheMDs);
+ getAllMetadataOtherThanDebugLoc(TheMDs);
for (unsigned i = 0, e = TheMDs.size(); i != e; ++i)
New->setMetadata(TheMDs[i].first, TheMDs[i].second);
+
+ New->setDebugLoc(getDebugLoc());
return New;
}
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 8f4eabe..9baad09 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -87,11 +87,8 @@ PHINode::PHINode(const PHINode &PN)
: Instruction(PN.getType(), Instruction::PHI,
allocHungoffUses(PN.getNumOperands()), PN.getNumOperands()),
ReservedSpace(PN.getNumOperands()) {
- Use *OL = OperandList;
- for (unsigned i = 0, e = PN.getNumOperands(); i != e; i+=2) {
- OL[i] = PN.getOperand(i);
- OL[i+1] = PN.getOperand(i+1);
- }
+ std::copy(PN.op_begin(), PN.op_end(), op_begin());
+ std::copy(PN.block_begin(), PN.block_end(), block_begin());
SubclassOptionalData = PN.SubclassOptionalData;
}
@@ -99,31 +96,37 @@ PHINode::~PHINode() {
dropHungoffUses();
}
+Use *PHINode::allocHungoffUses(unsigned N) const {
+ // Allocate the array of Uses of the incoming values, followed by a pointer
+ // (with bottom bit set) to the User, followed by the array of pointers to
+ // the incoming basic blocks.
+ size_t size = N * sizeof(Use) + sizeof(Use::UserRef)
+ + N * sizeof(BasicBlock*);
+ Use *Begin = static_cast<Use*>(::operator new(size));
+ Use *End = Begin + N;
+ (void) new(End) Use::UserRef(const_cast<PHINode*>(this), 1);
+ return Use::initTags(Begin, End);
+}
+
// removeIncomingValue - Remove an incoming value. This is useful if a
// predecessor basic block is deleted.
Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) {
- unsigned NumOps = getNumOperands();
- Use *OL = OperandList;
- assert(Idx*2 < NumOps && "BB not in PHI node!");
- Value *Removed = OL[Idx*2];
+ Value *Removed = getIncomingValue(Idx);
// Move everything after this operand down.
//
// FIXME: we could just swap with the end of the list, then erase. However,
- // client might not expect this to happen. The code as it is thrashes the
+ // clients might not expect this to happen. The code as it is thrashes the
// use/def lists, which is kinda lame.
- for (unsigned i = (Idx+1)*2; i != NumOps; i += 2) {
- OL[i-2] = OL[i];
- OL[i-2+1] = OL[i+1];
- }
+ std::copy(op_begin() + Idx + 1, op_end(), op_begin() + Idx);
+ std::copy(block_begin() + Idx + 1, block_end(), block_begin() + Idx);
// Nuke the last value.
- OL[NumOps-2].set(0);
- OL[NumOps-2+1].set(0);
- NumOperands = NumOps-2;
+ Op<-1>().set(0);
+ --NumOperands;
// If the PHI node is dead, because it has zero entries, nuke it now.
- if (NumOps == 2 && DeletePHIIfEmpty) {
+ if (getNumOperands() == 0 && DeletePHIIfEmpty) {
// If anyone is using this PHI, make them use a dummy value instead...
replaceAllUsesWith(UndefValue::get(getType()));
eraseFromParent();
@@ -137,15 +140,18 @@ Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) {
///
void PHINode::growOperands() {
unsigned e = getNumOperands();
- // Multiply by 1.5 and round down so the result is still even.
- unsigned NumOps = e + e / 4 * 2;
- if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common.
+ unsigned NumOps = e + e / 2;
+ if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common.
+
+ Use *OldOps = op_begin();
+ BasicBlock **OldBlocks = block_begin();
ReservedSpace = NumOps;
- Use *OldOps = OperandList;
- Use *NewOps = allocHungoffUses(NumOps);
- std::copy(OldOps, OldOps + e, NewOps);
- OperandList = NewOps;
+ OperandList = allocHungoffUses(ReservedSpace);
+
+ std::copy(OldOps, OldOps + e, op_begin());
+ std::copy(OldBlocks, OldBlocks + e, block_begin());
+
Use::zap(OldOps, OldOps + e, true);
}
@@ -168,95 +174,42 @@ Value *PHINode::hasConstantValue() const {
CallInst::~CallInst() {
}
-void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
- assert(NumOperands == NumParams+1 && "NumOperands not set up?");
+void CallInst::init(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr) {
+ assert(NumOperands == Args.size() + 1 && "NumOperands not set up?");
Op<-1>() = Func;
+#ifndef NDEBUG
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- (void)FTy; // silence warning.
- assert((NumParams == FTy->getNumParams() ||
- (FTy->isVarArg() && NumParams > FTy->getNumParams())) &&
+ assert((Args.size() == FTy->getNumParams() ||
+ (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Calling a function with bad signature!");
- for (unsigned i = 0; i != NumParams; ++i) {
+
+ for (unsigned i = 0; i != Args.size(); ++i)
assert((i >= FTy->getNumParams() ||
- FTy->getParamType(i) == Params[i]->getType()) &&
+ FTy->getParamType(i) == Args[i]->getType()) &&
"Calling a function with a bad signature!");
- OperandList[i] = Params[i];
- }
-}
-
-void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) {
- assert(NumOperands == 3 && "NumOperands not set up?");
- Op<-1>() = Func;
- Op<0>() = Actual1;
- Op<1>() = Actual2;
-
- const FunctionType *FTy =
- cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- (void)FTy; // silence warning.
-
- assert((FTy->getNumParams() == 2 ||
- (FTy->isVarArg() && FTy->getNumParams() < 2)) &&
- "Calling a function with bad signature");
- assert((0 >= FTy->getNumParams() ||
- FTy->getParamType(0) == Actual1->getType()) &&
- "Calling a function with a bad signature!");
- assert((1 >= FTy->getNumParams() ||
- FTy->getParamType(1) == Actual2->getType()) &&
- "Calling a function with a bad signature!");
-}
-
-void CallInst::init(Value *Func, Value *Actual) {
- assert(NumOperands == 2 && "NumOperands not set up?");
- Op<-1>() = Func;
- Op<0>() = Actual;
-
- const FunctionType *FTy =
- cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- (void)FTy; // silence warning.
+#endif
- assert((FTy->getNumParams() == 1 ||
- (FTy->isVarArg() && FTy->getNumParams() == 0)) &&
- "Calling a function with bad signature");
- assert((0 == FTy->getNumParams() ||
- FTy->getParamType(0) == Actual->getType()) &&
- "Calling a function with a bad signature!");
+ std::copy(Args.begin(), Args.end(), op_begin());
+ setName(NameStr);
}
-void CallInst::init(Value *Func) {
+void CallInst::init(Value *Func, const Twine &NameStr) {
assert(NumOperands == 1 && "NumOperands not set up?");
Op<-1>() = Func;
+#ifndef NDEBUG
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- (void)FTy; // silence warning.
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
-}
+#endif
-CallInst::CallInst(Value *Func, Value* Actual, const Twine &Name,
- Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 2,
- 2, InsertBefore) {
- init(Func, Actual);
- setName(Name);
+ setName(NameStr);
}
-CallInst::CallInst(Value *Func, Value* Actual, const Twine &Name,
- BasicBlock *InsertAtEnd)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 2,
- 2, InsertAtEnd) {
- init(Func, Actual);
- setName(Name);
-}
CallInst::CallInst(Value *Func, const Twine &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
@@ -264,8 +217,7 @@ CallInst::CallInst(Value *Func, const Twine &Name,
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertBefore) {
- init(Func);
- setName(Name);
+ init(Func, Name);
}
CallInst::CallInst(Value *Func, const Twine &Name,
@@ -275,8 +227,7 @@ CallInst::CallInst(Value *Func, const Twine &Name,
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertAtEnd) {
- init(Func);
- setName(Name);
+ init(Func, Name);
}
CallInst::CallInst(const CallInst &CI)
@@ -287,10 +238,7 @@ CallInst::CallInst(const CallInst &CI)
setTailCall(CI.isTailCall());
setCallingConv(CI.getCallingConv());
- Use *OL = OperandList;
- Use *InOL = CI.OperandList;
- for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)
- OL[i] = InOL[i];
+ std::copy(CI.op_begin(), CI.op_end(), op_begin());
SubclassOptionalData = CI.SubclassOptionalData;
}
@@ -366,7 +314,7 @@ static Instruction *createMalloc(Instruction *InsertBefore,
// Create the call to Malloc.
BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
Module* M = BB->getParent()->getParent();
- const Type *BPTy = Type::getInt8PtrTy(BB->getContext());
+ Type *BPTy = Type::getInt8PtrTy(BB->getContext());
Value *MallocFunc = MallocF;
if (!MallocFunc)
// prototype malloc as "void *malloc(size_t)"
@@ -481,27 +429,28 @@ Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) {
//===----------------------------------------------------------------------===//
void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
- Value* const *Args, unsigned NumArgs) {
- assert(NumOperands == 3+NumArgs && "NumOperands not set up?");
+ ArrayRef<Value *> Args, const Twine &NameStr) {
+ assert(NumOperands == 3 + Args.size() && "NumOperands not set up?");
Op<-3>() = Fn;
Op<-2>() = IfNormal;
Op<-1>() = IfException;
+
+#ifndef NDEBUG
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType());
- (void)FTy; // silence warning.
- assert(((NumArgs == FTy->getNumParams()) ||
- (FTy->isVarArg() && NumArgs > FTy->getNumParams())) &&
+ assert(((Args.size() == FTy->getNumParams()) ||
+ (FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Invoking a function with bad signature");
- Use *OL = OperandList;
- for (unsigned i = 0, e = NumArgs; i != e; i++) {
+ for (unsigned i = 0, e = Args.size(); i != e; i++)
assert((i >= FTy->getNumParams() ||
FTy->getParamType(i) == Args[i]->getType()) &&
"Invoking a function with a bad signature!");
-
- OL[i] = Args[i];
- }
+#endif
+
+ std::copy(Args.begin(), Args.end(), op_begin());
+ setName(NameStr);
}
InvokeInst::InvokeInst(const InvokeInst &II)
@@ -511,9 +460,7 @@ InvokeInst::InvokeInst(const InvokeInst &II)
II.getNumOperands()) {
setAttributes(II.getAttributes());
setCallingConv(II.getCallingConv());
- Use *OL = OperandList, *InOL = II.OperandList;
- for (unsigned i = 0, e = II.getNumOperands(); i != e; ++i)
- OL[i] = InOL[i];
+ std::copy(II.op_begin(), II.op_end(), op_begin());
SubclassOptionalData = II.SubclassOptionalData;
}
@@ -817,7 +764,7 @@ bool AllocaInst::isArrayAllocation() const {
return true;
}
-const Type *AllocaInst::getAllocatedType() const {
+Type *AllocaInst::getAllocatedType() const {
return getType()->getElementType();
}
@@ -1092,7 +1039,7 @@ GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const Twine &Name, Instruction *InBe)
: Instruction(PointerType::get(
- checkType(getIndexedType(Ptr->getType(),Idx)), retrieveAddrSpace(Ptr)),
+ checkGEPType(getIndexedType(Ptr->getType(),Idx)), retrieveAddrSpace(Ptr)),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
2, InBe) {
@@ -1102,7 +1049,7 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const Twine &Name, BasicBlock *IAE)
: Instruction(PointerType::get(
- checkType(getIndexedType(Ptr->getType(),Idx)),
+ checkGEPType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
@@ -1120,60 +1067,50 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
/// pointer type.
///
template <typename IndexTy>
-static const Type* getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
- unsigned NumIdx) {
+static Type *getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs,
+ unsigned NumIdx) {
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
- const Type *Agg = PTy->getElementType();
+ Type *Agg = PTy->getElementType();
// Handle the special case of the empty set index set, which is always valid.
if (NumIdx == 0)
return Agg;
// If there is at least one index, the top level type must be sized, otherwise
- // it cannot be 'stepped over'. We explicitly allow abstract types (those
- // that contain opaque types) under the assumption that it will be resolved to
- // a sane type later.
- if (!Agg->isSized() && !Agg->isAbstract())
+ // it cannot be 'stepped over'.
+ if (!Agg->isSized())
return 0;
unsigned CurIdx = 1;
for (; CurIdx != NumIdx; ++CurIdx) {
- const CompositeType *CT = dyn_cast<CompositeType>(Agg);
+ CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || CT->isPointerTy()) return 0;
IndexTy Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0;
Agg = CT->getTypeAtIndex(Index);
-
- // If the new type forwards to another type, then it is in the middle
- // of being refined to another type (and hence, may have dropped all
- // references to what it was using before). So, use the new forwarded
- // type.
- if (const Type *Ty = Agg->getForwardedType())
- Agg = Ty;
}
return CurIdx == NumIdx ? Agg : 0;
}
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
- Value* const *Idxs,
- unsigned NumIdx) {
+Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value* const *Idxs,
+ unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
- Constant* const *Idxs,
- unsigned NumIdx) {
+Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
+ Constant* const *Idxs,
+ unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
- uint64_t const *Idxs,
- unsigned NumIdx) {
+Type *GetElementPtrInst::getIndexedType(const Type *Ptr,
+ uint64_t const *Idxs,
+ unsigned NumIdx) {
return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
+Type *GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
@@ -1390,27 +1327,22 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const {
// InsertValueInst Class
//===----------------------------------------------------------------------===//
-void InsertValueInst::init(Value *Agg, Value *Val, const unsigned *Idx,
- unsigned NumIdx, const Twine &Name) {
+void InsertValueInst::init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
+ const Twine &Name) {
assert(NumOperands == 2 && "NumOperands not initialized?");
- assert(ExtractValueInst::getIndexedType(Agg->getType(), Idx, Idx + NumIdx) ==
- Val->getType() && "Inserted value must match indexed type!");
- Op<0>() = Agg;
- Op<1>() = Val;
- Indices.append(Idx, Idx + NumIdx);
- setName(Name);
-}
+ // There's no fundamental reason why we require at least one index
+ // (other than weirdness with &*IdxBegin being invalid; see
+ // getelementptr's init routine for example). But there's no
+ // present need to support it.
+ assert(Idxs.size() > 0 && "InsertValueInst must have at least one index");
-void InsertValueInst::init(Value *Agg, Value *Val, unsigned Idx,
- const Twine &Name) {
- assert(NumOperands == 2 && "NumOperands not initialized?");
- assert(ExtractValueInst::getIndexedType(Agg->getType(), Idx) == Val->getType()
- && "Inserted value must match indexed type!");
+ assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs) ==
+ Val->getType() && "Inserted value must match indexed type!");
Op<0>() = Agg;
Op<1>() = Val;
- Indices.push_back(Idx);
+ Indices.append(Idxs.begin(), Idxs.end());
setName(Name);
}
@@ -1423,44 +1355,18 @@ InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
SubclassOptionalData = IVI.SubclassOptionalData;
}
-InsertValueInst::InsertValueInst(Value *Agg,
- Value *Val,
- unsigned Idx,
- const Twine &Name,
- Instruction *InsertBefore)
- : Instruction(Agg->getType(), InsertValue,
- OperandTraits<InsertValueInst>::op_begin(this),
- 2, InsertBefore) {
- init(Agg, Val, Idx, Name);
-}
-
-InsertValueInst::InsertValueInst(Value *Agg,
- Value *Val,
- unsigned Idx,
- const Twine &Name,
- BasicBlock *InsertAtEnd)
- : Instruction(Agg->getType(), InsertValue,
- OperandTraits<InsertValueInst>::op_begin(this),
- 2, InsertAtEnd) {
- init(Agg, Val, Idx, Name);
-}
-
//===----------------------------------------------------------------------===//
// ExtractValueInst Class
//===----------------------------------------------------------------------===//
-void ExtractValueInst::init(const unsigned *Idx, unsigned NumIdx,
- const Twine &Name) {
+void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) {
assert(NumOperands == 1 && "NumOperands not initialized?");
- Indices.append(Idx, Idx + NumIdx);
- setName(Name);
-}
-
-void ExtractValueInst::init(unsigned Idx, const Twine &Name) {
- assert(NumOperands == 1 && "NumOperands not initialized?");
+ // There's no fundamental reason why we require at least one index.
+ // But there's no present need to support it.
+ assert(Idxs.size() > 0 && "ExtractValueInst must have at least one index");
- Indices.push_back(Idx);
+ Indices.append(Idxs.begin(), Idxs.end());
setName(Name);
}
@@ -1476,10 +1382,9 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
// A null type is returned if the indices are invalid for the specified
// pointer type.
//
-const Type* ExtractValueInst::getIndexedType(const Type *Agg,
- const unsigned *Idxs,
- unsigned NumIdx) {
- for (unsigned CurIdx = 0; CurIdx != NumIdx; ++CurIdx) {
+Type *ExtractValueInst::getIndexedType(const Type *Agg,
+ ArrayRef<unsigned> Idxs) {
+ for (unsigned CurIdx = 0; CurIdx != Idxs.size(); ++CurIdx) {
unsigned Index = Idxs[CurIdx];
// We can't use CompositeType::indexValid(Index) here.
// indexValid() always returns true for arrays because getelementptr allows
@@ -1499,20 +1404,8 @@ const Type* ExtractValueInst::getIndexedType(const Type *Agg,
}
Agg = cast<CompositeType>(Agg)->getTypeAtIndex(Index);
-
- // If the new type forwards to another type, then it is in the middle
- // of being refined to another type (and hence, may have dropped all
- // references to what it was using before). So, use the new forwarded
- // type.
- if (const Type *Ty = Agg->getForwardedType())
- Agg = Ty;
}
- return Agg;
-}
-
-const Type* ExtractValueInst::getIndexedType(const Type *Agg,
- unsigned Idx) {
- return getIndexedType(Agg, &Idx, 1);
+ return const_cast<Type*>(Agg);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp
index 1bd497d..ebd1e0a 100644
--- a/lib/VMCore/LLVMContext.cpp
+++ b/lib/VMCore/LLVMContext.cpp
@@ -39,6 +39,10 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
// Create the 'tbaa' metadata kind.
unsigned TBAAID = getMDKindID("tbaa");
assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;
+
+ // Create the 'prof' metadata kind.
+ unsigned ProfID = getMDKindID("prof");
+ assert(ProfID == MD_prof && "prof kind id drifted"); (void)ProfID;
}
LLVMContext::~LLVMContext() { delete pImpl; }
diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp
index ccb8dc5..504b372 100644
--- a/lib/VMCore/LLVMContextImpl.cpp
+++ b/lib/VMCore/LLVMContextImpl.cpp
@@ -13,6 +13,7 @@
#include "LLVMContextImpl.h"
#include "llvm/Module.h"
+#include "llvm/ADT/STLExtras.h"
#include <algorithm>
using namespace llvm;
@@ -31,14 +32,10 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
Int8Ty(C, 8),
Int16Ty(C, 16),
Int32Ty(C, 32),
- Int64Ty(C, 64),
- AlwaysOpaqueTy(new OpaqueType(C)) {
+ Int64Ty(C, 64) {
InlineAsmDiagHandler = 0;
InlineAsmDiagContext = 0;
-
- // Make sure the AlwaysOpaqueTy stays alive as long as the Context.
- AlwaysOpaqueTy->addRef();
- OpaqueTypes.insert(AlwaysOpaqueTy);
+ NamedStructTypesUniqueID = 0;
}
namespace {
@@ -58,9 +55,7 @@ LLVMContextImpl::~LLVMContextImpl() {
// will try to remove itself from OwnedModules set. This would cause
// iterator invalidation if we iterated on the set directly.
std::vector<Module*> Modules(OwnedModules.begin(), OwnedModules.end());
- for (std::vector<Module*>::iterator I = Modules.begin(), E = Modules.end();
- I != E; ++I)
- delete *I;
+ DeleteContainerPointers(Modules);
std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
DropReferences());
@@ -78,38 +73,22 @@ LLVMContextImpl::~LLVMContextImpl() {
NullPtrConstants.freeConstants();
UndefValueConstants.freeConstants();
InlineAsms.freeConstants();
- for (IntMapTy::iterator I = IntConstants.begin(), E = IntConstants.end();
- I != E; ++I) {
- delete I->second;
- }
- for (FPMapTy::iterator I = FPConstants.begin(), E = FPConstants.end();
- I != E; ++I) {
- delete I->second;
- }
- AlwaysOpaqueTy->dropRef();
- for (OpaqueTypesTy::iterator I = OpaqueTypes.begin(), E = OpaqueTypes.end();
- I != E; ++I) {
- (*I)->AbstractTypeUsers.clear();
- delete *I;
- }
+ DeleteContainerSeconds(IntConstants);
+ DeleteContainerSeconds(FPConstants);
+
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet
// and the NonUniquedMDNodes sets, so copy the values out first.
SmallVector<MDNode*, 8> MDNodes;
MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size());
for (FoldingSetIterator<MDNode> I = MDNodeSet.begin(), E = MDNodeSet.end();
- I != E; ++I) {
+ I != E; ++I)
MDNodes.push_back(&*I);
- }
MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end());
for (SmallVectorImpl<MDNode *>::iterator I = MDNodes.begin(),
- E = MDNodes.end(); I != E; ++I) {
+ E = MDNodes.end(); I != E; ++I)
(*I)->destroy();
- }
assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() &&
"Destroying all MDNodes didn't empty the Context's sets.");
// Destroy MDStrings.
- for (StringMap<MDString*>::iterator I = MDStringCache.begin(),
- E = MDStringCache.end(); I != E; ++I) {
- delete I->second;
- }
+ DeleteContainerSeconds(MDStringCache);
}
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index 6ea4b48..06a6f2a 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -15,17 +15,16 @@
#ifndef LLVM_LLVMCONTEXT_IMPL_H
#define LLVM_LLVMCONTEXT_IMPL_H
+#include "llvm/LLVMContext.h"
#include "ConstantsContext.h"
#include "LeaksContext.h"
-#include "TypesContext.h"
-#include "llvm/LLVMContext.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Metadata.h"
-#include "llvm/Assembly/Writer.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -139,27 +138,30 @@ public:
// on Context destruction.
SmallPtrSet<MDNode*, 1> NonUniquedMDNodes;
- ConstantUniqueMap<char, Type, ConstantAggregateZero> AggZeroConstants;
+ ConstantUniqueMap<char, char, Type, ConstantAggregateZero> AggZeroConstants;
- typedef ConstantUniqueMap<std::vector<Constant*>, ArrayType,
- ConstantArray, true /*largekey*/> ArrayConstantsTy;
+ typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
+ ArrayType, ConstantArray, true /*largekey*/> ArrayConstantsTy;
ArrayConstantsTy ArrayConstants;
- typedef ConstantUniqueMap<std::vector<Constant*>, StructType,
- ConstantStruct, true /*largekey*/> StructConstantsTy;
+ typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
+ StructType, ConstantStruct, true /*largekey*/> StructConstantsTy;
StructConstantsTy StructConstants;
- typedef ConstantUniqueMap<std::vector<Constant*>, VectorType,
- ConstantVector> VectorConstantsTy;
+ typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
+ VectorType, ConstantVector> VectorConstantsTy;
VectorConstantsTy VectorConstants;
- ConstantUniqueMap<char, PointerType, ConstantPointerNull> NullPtrConstants;
- ConstantUniqueMap<char, Type, UndefValue> UndefValueConstants;
+ ConstantUniqueMap<char, char, PointerType, ConstantPointerNull>
+ NullPtrConstants;
+ ConstantUniqueMap<char, char, Type, UndefValue> UndefValueConstants;
DenseMap<std::pair<Function*, BasicBlock*> , BlockAddress*> BlockAddresses;
- ConstantUniqueMap<ExprMapKeyType, Type, ConstantExpr> ExprConstants;
+ ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr>
+ ExprConstants;
- ConstantUniqueMap<InlineAsmKeyType, PointerType, InlineAsm> InlineAsms;
+ ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType,
+ InlineAsm> InlineAsms;
ConstantInt *TheTrueVal;
ConstantInt *TheFalseVal;
@@ -167,41 +169,27 @@ public:
LeakDetectorImpl<Value> LLVMObjects;
// Basic type instances.
- const Type VoidTy;
- const Type LabelTy;
- const Type FloatTy;
- const Type DoubleTy;
- const Type MetadataTy;
- const Type X86_FP80Ty;
- const Type FP128Ty;
- const Type PPC_FP128Ty;
- const Type X86_MMXTy;
- const IntegerType Int1Ty;
- const IntegerType Int8Ty;
- const IntegerType Int16Ty;
- const IntegerType Int32Ty;
- const IntegerType Int64Ty;
-
- // Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions
- // for types as they are needed. Because resolution of types must invalidate
- // all of the abstract type descriptions, we keep them in a separate map to
- // make this easy.
- TypePrinting ConcreteTypeDescriptions;
- TypePrinting AbstractTypeDescriptions;
-
- TypeMap<ArrayValType, ArrayType> ArrayTypes;
- TypeMap<VectorValType, VectorType> VectorTypes;
- TypeMap<PointerValType, PointerType> PointerTypes;
- TypeMap<FunctionValType, FunctionType> FunctionTypes;
- TypeMap<StructValType, StructType> StructTypes;
- TypeMap<IntegerValType, IntegerType> IntegerTypes;
-
- // Opaque types are not structurally uniqued, so don't use TypeMap.
- typedef SmallPtrSet<const OpaqueType*, 8> OpaqueTypesTy;
- OpaqueTypesTy OpaqueTypes;
-
- /// Used as an abstract type that will never be resolved.
- OpaqueType *const AlwaysOpaqueTy;
+ Type VoidTy, LabelTy, FloatTy, DoubleTy, MetadataTy;
+ Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
+ IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty;
+
+
+ /// TypeAllocator - All dynamically allocated types are allocated from this.
+ /// They live forever until the context is torn down.
+ BumpPtrAllocator TypeAllocator;
+
+ DenseMap<unsigned, IntegerType*> IntegerTypes;
+
+ // TODO: Optimize FunctionTypes/AnonStructTypes!
+ std::map<std::vector<Type*>, FunctionType*> FunctionTypes;
+ std::map<std::vector<Type*>, StructType*> AnonStructTypes;
+ StringMap<StructType*> NamedStructTypes;
+ unsigned NamedStructTypesUniqueID;
+
+ DenseMap<std::pair<Type *, uint64_t>, ArrayType*> ArrayTypes;
+ DenseMap<std::pair<Type *, unsigned>, VectorType*> VectorTypes;
+ DenseMap<Type*, PointerType*> PointerTypes; // Pointers in AddrSpace = 0
+ DenseMap<std::pair<Type*, unsigned>, PointerType*> ASPointerTypes;
/// ValueHandles - This map keeps track of all of the value handles that are
diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp
index eb719e5..ace4dc2 100644
--- a/lib/VMCore/Metadata.cpp
+++ b/lib/VMCore/Metadata.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ValueHandle.h"
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index 341e527..be2fcb8 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -17,12 +17,12 @@
#include "llvm/DerivedTypes.h"
#include "llvm/GVMaterializer.h"
#include "llvm/LLVMContext.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LeakDetector.h"
#include "SymbolTableListTraitsImpl.h"
-#include "llvm/TypeSymbolTable.h"
#include <algorithm>
#include <cstdarg>
#include <cstdlib>
@@ -60,7 +60,6 @@ template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
Module::Module(StringRef MID, LLVMContext& C)
: Context(C), Materializer(NULL), ModuleID(MID) {
ValSymTab = new ValueSymbolTable();
- TypeSymTab = new TypeSymbolTable();
NamedMDSymTab = new StringMap<NamedMDNode *>();
Context.addModule(this);
}
@@ -74,11 +73,10 @@ Module::~Module() {
LibraryList.clear();
NamedMDList.clear();
delete ValSymTab;
- delete TypeSymTab;
delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab);
}
-/// Target endian information...
+/// Target endian information.
Module::Endianness Module::getEndianness() const {
StringRef temp = DataLayout;
Module::Endianness ret = AnyEndianness;
@@ -218,8 +216,8 @@ Constant *Module::getOrInsertFunction(StringRef Name,
va_start(Args, RetTy);
// Build the list of argument types...
- std::vector<const Type*> ArgTys;
- while (const Type *ArgTy = va_arg(Args, const Type*))
+ std::vector<Type*> ArgTys;
+ while (Type *ArgTy = va_arg(Args, Type*))
ArgTys.push_back(ArgTy);
va_end(Args);
@@ -236,8 +234,8 @@ Constant *Module::getOrInsertFunction(StringRef Name,
va_start(Args, RetTy);
// Build the list of argument types...
- std::vector<const Type*> ArgTys;
- while (const Type *ArgTy = va_arg(Args, const Type*))
+ std::vector<Type*> ArgTys;
+ while (Type *ArgTy = va_arg(Args, Type*))
ArgTys.push_back(ArgTy);
va_end(Args);
@@ -340,51 +338,6 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) {
NamedMDList.erase(NMD);
}
-//===----------------------------------------------------------------------===//
-// Methods for easy access to the types in the module.
-//
-
-
-// addTypeName - Insert an entry in the symbol table mapping Str to Type. If
-// there is already an entry for this name, true is returned and the symbol
-// table is not modified.
-//
-bool Module::addTypeName(StringRef Name, const Type *Ty) {
- TypeSymbolTable &ST = getTypeSymbolTable();
-
- if (ST.lookup(Name)) return true; // Already in symtab...
-
- // Not in symbol table? Set the name with the Symtab as an argument so the
- // type knows what to update...
- ST.insert(Name, Ty);
-
- return false;
-}
-
-/// getTypeByName - Return the type with the specified name in this module, or
-/// null if there is none by that name.
-const Type *Module::getTypeByName(StringRef Name) const {
- const TypeSymbolTable &ST = getTypeSymbolTable();
- return cast_or_null<Type>(ST.lookup(Name));
-}
-
-// getTypeName - If there is at least one entry in the symbol table for the
-// specified type, return it.
-//
-std::string Module::getTypeName(const Type *Ty) const {
- const TypeSymbolTable &ST = getTypeSymbolTable();
-
- TypeSymbolTable::const_iterator TI = ST.begin();
- TypeSymbolTable::const_iterator TE = ST.end();
- if ( TI == TE ) return ""; // No names for types
-
- while (TI != TE && TI->second != Ty)
- ++TI;
-
- if (TI != TE) // Must have found an entry!
- return TI->first;
- return ""; // Must not have found anything...
-}
//===----------------------------------------------------------------------===//
// Methods to control the materialization of GlobalValues in the Module.
@@ -471,3 +424,130 @@ void Module::removeLibrary(StringRef Lib) {
return;
}
}
+
+//===----------------------------------------------------------------------===//
+// Type finding functionality.
+//===----------------------------------------------------------------------===//
+
+namespace {
+ /// TypeFinder - Walk over a module, identifying all of the types that are
+ /// used by the module.
+ class TypeFinder {
+ // To avoid walking constant expressions multiple times and other IR
+ // objects, we keep several helper maps.
+ DenseSet<const Value*> VisitedConstants;
+ DenseSet<const Type*> VisitedTypes;
+
+ std::vector<StructType*> &StructTypes;
+ public:
+ TypeFinder(std::vector<StructType*> &structTypes)
+ : StructTypes(structTypes) {}
+
+ void run(const Module &M) {
+ // Get types from global variables.
+ for (Module::const_global_iterator I = M.global_begin(),
+ E = M.global_end(); I != E; ++I) {
+ incorporateType(I->getType());
+ if (I->hasInitializer())
+ incorporateValue(I->getInitializer());
+ }
+
+ // Get types from aliases.
+ for (Module::const_alias_iterator I = M.alias_begin(),
+ E = M.alias_end(); I != E; ++I) {
+ incorporateType(I->getType());
+ if (const Value *Aliasee = I->getAliasee())
+ incorporateValue(Aliasee);
+ }
+
+ SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
+
+ // Get types from functions.
+ for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
+ incorporateType(FI->getType());
+
+ for (Function::const_iterator BB = FI->begin(), E = FI->end();
+ BB != E;++BB)
+ for (BasicBlock::const_iterator II = BB->begin(),
+ E = BB->end(); II != E; ++II) {
+ const Instruction &I = *II;
+ // Incorporate the type of the instruction and all its operands.
+ incorporateType(I.getType());
+ for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
+ OI != OE; ++OI)
+ incorporateValue(*OI);
+
+ // Incorporate types hiding in metadata.
+ I.getAllMetadataOtherThanDebugLoc(MDForInst);
+ for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
+ incorporateMDNode(MDForInst[i].second);
+ MDForInst.clear();
+ }
+ }
+
+ for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
+ E = M.named_metadata_end(); I != E; ++I) {
+ const NamedMDNode *NMD = I;
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
+ incorporateMDNode(NMD->getOperand(i));
+ }
+ }
+
+ private:
+ void incorporateType(Type *Ty) {
+ // Check to see if we're already visited this type.
+ if (!VisitedTypes.insert(Ty).second)
+ return;
+
+ // If this is a structure or opaque type, add a name for the type.
+ if (StructType *STy = dyn_cast<StructType>(Ty))
+ StructTypes.push_back(STy);
+
+ // Recursively walk all contained types.
+ for (Type::subtype_iterator I = Ty->subtype_begin(),
+ E = Ty->subtype_end(); I != E; ++I)
+ incorporateType(*I);
+ }
+
+ /// incorporateValue - This method is used to walk operand lists finding
+ /// types hiding in constant expressions and other operands that won't be
+ /// walked in other ways. GlobalValues, basic blocks, instructions, and
+ /// inst operands are all explicitly enumerated.
+ void incorporateValue(const Value *V) {
+ if (const MDNode *M = dyn_cast<MDNode>(V))
+ return incorporateMDNode(M);
+ if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
+
+ // Already visited?
+ if (!VisitedConstants.insert(V).second)
+ return;
+
+ // Check this type.
+ incorporateType(V->getType());
+
+ // Look in operands for types.
+ const User *U = cast<User>(V);
+ for (Constant::const_op_iterator I = U->op_begin(),
+ E = U->op_end(); I != E;++I)
+ incorporateValue(*I);
+ }
+
+ void incorporateMDNode(const MDNode *V) {
+
+ // Already visited?
+ if (!VisitedConstants.insert(V).second)
+ return;
+
+ // Look in operands for types.
+ for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i)
+ if (Value *Op = V->getOperand(i))
+ incorporateValue(Op);
+ }
+ };
+} // end anonymous namespace
+
+void Module::findUsedStructTypes(std::vector<StructType*> &StructTypes) const {
+ TypeFinder(StructTypes).run(*this);
+}
+
+
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index e4496db..f874d1b 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -12,95 +12,17 @@
//===----------------------------------------------------------------------===//
#include "LLVMContextImpl.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Metadata.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/SCCIterator.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Threading.h"
+#include "llvm/Module.h"
#include <algorithm>
#include <cstdarg>
+#include "llvm/ADT/SmallString.h"
using namespace llvm;
-// DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are
-// created and later destroyed, all in an effort to make sure that there is only
-// a single canonical version of a type.
-//
-// #define DEBUG_MERGE_TYPES 1
-
-AbstractTypeUser::~AbstractTypeUser() {}
-
-void AbstractTypeUser::setType(Value *V, const Type *NewTy) {
- V->VTy = NewTy;
-}
-
//===----------------------------------------------------------------------===//
// Type Class Implementation
//===----------------------------------------------------------------------===//
-/// Because of the way Type subclasses are allocated, this function is necessary
-/// to use the correct kind of "delete" operator to deallocate the Type object.
-/// Some type objects (FunctionTy, StructTy) allocate additional space
-/// after the space for their derived type to hold the contained types array of
-/// PATypeHandles. Using this allocation scheme means all the PATypeHandles are
-/// allocated with the type object, decreasing allocations and eliminating the
-/// need for a std::vector to be used in the Type class itself.
-/// @brief Type destruction function
-void Type::destroy() const {
- // Nothing calls getForwardedType from here on.
- if (ForwardType && ForwardType->isAbstract()) {
- ForwardType->dropRef();
- ForwardType = NULL;
- }
-
- // Structures and Functions allocate their contained types past the end of
- // the type object itself. These need to be destroyed differently than the
- // other types.
- if (this->isFunctionTy() || this->isStructTy()) {
- // First, make sure we destruct any PATypeHandles allocated by these
- // subclasses. They must be manually destructed.
- for (unsigned i = 0; i < NumContainedTys; ++i)
- ContainedTys[i].PATypeHandle::~PATypeHandle();
-
- // Now call the destructor for the subclass directly because we're going
- // to delete this as an array of char.
- if (this->isFunctionTy())
- static_cast<const FunctionType*>(this)->FunctionType::~FunctionType();
- else {
- assert(isStructTy());
- static_cast<const StructType*>(this)->StructType::~StructType();
- }
-
- // Finally, remove the memory as an array deallocation of the chars it was
- // constructed from.
- operator delete(const_cast<Type *>(this));
-
- return;
- } else if (const OpaqueType *opaque_this = dyn_cast<OpaqueType>(this)) {
- LLVMContextImpl *pImpl = this->getContext().pImpl;
- pImpl->OpaqueTypes.erase(opaque_this);
- }
-
- // For all the other type subclasses, there is either no contained types or
- // just one (all Sequentials). For Sequentials, the PATypeHandle is not
- // allocated past the type object, its included directly in the SequentialType
- // class. This means we can safely just do "normal" delete of this object and
- // all the destructors that need to run will be run.
- delete this;
-}
-
-const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
+Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
switch (IDNumber) {
case VoidTyID : return getVoidTy(C);
case FloatTyID : return getFloatTy(C);
@@ -116,15 +38,6 @@ const Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) {
}
}
-const Type *Type::getVAArgsPromotedType(LLVMContext &C) const {
- if (ID == IntegerTyID && getSubclassData() < 32)
- return Type::getInt32Ty(C);
- else if (ID == FloatTyID)
- return Type::getDoubleTy(C);
- else
- return this;
-}
-
/// getScalarType - If this is a vector type, return the element type,
/// otherwise return this.
const Type *Type::getScalarType() const {
@@ -262,13 +175,17 @@ bool Type::isSizedDerivedType() const {
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType()->isSized();
- if (const VectorType *PTy = dyn_cast<VectorType>(this))
- return PTy->getElementType()->isSized();
+ if (const VectorType *VTy = dyn_cast<VectorType>(this))
+ return VTy->getElementType()->isSized();
if (!this->isStructTy())
return false;
- // Okay, our struct is sized if all of the elements are...
+ // Opaque structs have no size.
+ if (cast<StructType>(this)->isOpaque())
+ return false;
+
+ // Okay, our struct is sized if all of the elements are.
for (subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I)
if (!(*I)->isSized())
return false;
@@ -276,696 +193,335 @@ bool Type::isSizedDerivedType() const {
return true;
}
-/// getForwardedTypeInternal - This method is used to implement the union-find
-/// algorithm for when a type is being forwarded to another type.
-const Type *Type::getForwardedTypeInternal() const {
- assert(ForwardType && "This type is not being forwarded to another type!");
-
- // Check to see if the forwarded type has been forwarded on. If so, collapse
- // the forwarding links.
- const Type *RealForwardedType = ForwardType->getForwardedType();
- if (!RealForwardedType)
- return ForwardType; // No it's not forwarded again
-
- // Yes, it is forwarded again. First thing, add the reference to the new
- // forward type.
- if (RealForwardedType->isAbstract())
- RealForwardedType->addRef();
-
- // Now drop the old reference. This could cause ForwardType to get deleted.
- // ForwardType must be abstract because only abstract types can have their own
- // ForwardTypes.
- ForwardType->dropRef();
-
- // Return the updated type.
- ForwardType = RealForwardedType;
- return ForwardType;
-}
-
-void Type::refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
- llvm_unreachable("Attempting to refine a derived type!");
-}
-void Type::typeBecameConcrete(const DerivedType *AbsTy) {
- llvm_unreachable("DerivedType is already a concrete type!");
-}
-
-
-std::string Type::getDescription() const {
- LLVMContextImpl *pImpl = getContext().pImpl;
- TypePrinting &Map =
- isAbstract() ?
- pImpl->AbstractTypeDescriptions :
- pImpl->ConcreteTypeDescriptions;
-
- std::string DescStr;
- raw_string_ostream DescOS(DescStr);
- Map.print(this, DescOS);
- return DescOS.str();
-}
-
-
-bool StructType::indexValid(const Value *V) const {
- // Structure indexes require 32-bit integer constants.
- if (V->getType()->isIntegerTy(32))
- if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
- return indexValid(CU->getZExtValue());
- return false;
-}
-
-bool StructType::indexValid(unsigned V) const {
- return V < NumContainedTys;
-}
-
-// getTypeAtIndex - Given an index value into the type, return the type of the
-// element. For a structure type, this must be a constant value...
-//
-const Type *StructType::getTypeAtIndex(const Value *V) const {
- unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
- return getTypeAtIndex(Idx);
-}
-
-const Type *StructType::getTypeAtIndex(unsigned Idx) const {
- assert(indexValid(Idx) && "Invalid structure index!");
- return ContainedTys[Idx];
-}
-
-
//===----------------------------------------------------------------------===//
// Primitive 'Type' data
//===----------------------------------------------------------------------===//
-const Type *Type::getVoidTy(LLVMContext &C) {
- return &C.pImpl->VoidTy;
-}
-
-const Type *Type::getLabelTy(LLVMContext &C) {
- return &C.pImpl->LabelTy;
-}
-
-const Type *Type::getFloatTy(LLVMContext &C) {
- return &C.pImpl->FloatTy;
-}
-
-const Type *Type::getDoubleTy(LLVMContext &C) {
- return &C.pImpl->DoubleTy;
-}
-
-const Type *Type::getMetadataTy(LLVMContext &C) {
- return &C.pImpl->MetadataTy;
-}
-
-const Type *Type::getX86_FP80Ty(LLVMContext &C) {
- return &C.pImpl->X86_FP80Ty;
-}
-
-const Type *Type::getFP128Ty(LLVMContext &C) {
- return &C.pImpl->FP128Ty;
-}
-
-const Type *Type::getPPC_FP128Ty(LLVMContext &C) {
- return &C.pImpl->PPC_FP128Ty;
-}
-
-const Type *Type::getX86_MMXTy(LLVMContext &C) {
- return &C.pImpl->X86_MMXTy;
-}
-
-const IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
+Type *Type::getVoidTy(LLVMContext &C) { return &C.pImpl->VoidTy; }
+Type *Type::getLabelTy(LLVMContext &C) { return &C.pImpl->LabelTy; }
+Type *Type::getFloatTy(LLVMContext &C) { return &C.pImpl->FloatTy; }
+Type *Type::getDoubleTy(LLVMContext &C) { return &C.pImpl->DoubleTy; }
+Type *Type::getMetadataTy(LLVMContext &C) { return &C.pImpl->MetadataTy; }
+Type *Type::getX86_FP80Ty(LLVMContext &C) { return &C.pImpl->X86_FP80Ty; }
+Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; }
+Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; }
+Type *Type::getX86_MMXTy(LLVMContext &C) { return &C.pImpl->X86_MMXTy; }
+
+IntegerType *Type::getInt1Ty(LLVMContext &C) { return &C.pImpl->Int1Ty; }
+IntegerType *Type::getInt8Ty(LLVMContext &C) { return &C.pImpl->Int8Ty; }
+IntegerType *Type::getInt16Ty(LLVMContext &C) { return &C.pImpl->Int16Ty; }
+IntegerType *Type::getInt32Ty(LLVMContext &C) { return &C.pImpl->Int32Ty; }
+IntegerType *Type::getInt64Ty(LLVMContext &C) { return &C.pImpl->Int64Ty; }
+
+IntegerType *Type::getIntNTy(LLVMContext &C, unsigned N) {
return IntegerType::get(C, N);
}
-const IntegerType *Type::getInt1Ty(LLVMContext &C) {
- return &C.pImpl->Int1Ty;
-}
-
-const IntegerType *Type::getInt8Ty(LLVMContext &C) {
- return &C.pImpl->Int8Ty;
-}
-
-const IntegerType *Type::getInt16Ty(LLVMContext &C) {
- return &C.pImpl->Int16Ty;
-}
-
-const IntegerType *Type::getInt32Ty(LLVMContext &C) {
- return &C.pImpl->Int32Ty;
-}
-
-const IntegerType *Type::getInt64Ty(LLVMContext &C) {
- return &C.pImpl->Int64Ty;
-}
-
-const PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getFloatPtrTy(LLVMContext &C, unsigned AS) {
return getFloatTy(C)->getPointerTo(AS);
}
-const PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getDoublePtrTy(LLVMContext &C, unsigned AS) {
return getDoubleTy(C)->getPointerTo(AS);
}
-const PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getX86_FP80PtrTy(LLVMContext &C, unsigned AS) {
return getX86_FP80Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getFP128PtrTy(LLVMContext &C, unsigned AS) {
return getFP128Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getPPC_FP128PtrTy(LLVMContext &C, unsigned AS) {
return getPPC_FP128Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getX86_MMXPtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getX86_MMXPtrTy(LLVMContext &C, unsigned AS) {
return getX86_MMXTy(C)->getPointerTo(AS);
}
-const PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) {
+PointerType *Type::getIntNPtrTy(LLVMContext &C, unsigned N, unsigned AS) {
return getIntNTy(C, N)->getPointerTo(AS);
}
-const PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getInt1PtrTy(LLVMContext &C, unsigned AS) {
return getInt1Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getInt8PtrTy(LLVMContext &C, unsigned AS) {
return getInt8Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getInt16PtrTy(LLVMContext &C, unsigned AS) {
return getInt16Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getInt32PtrTy(LLVMContext &C, unsigned AS) {
return getInt32Ty(C)->getPointerTo(AS);
}
-const PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) {
+PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) {
return getInt64Ty(C)->getPointerTo(AS);
}
+
//===----------------------------------------------------------------------===//
-// Derived Type Constructors
+// IntegerType Implementation
//===----------------------------------------------------------------------===//
-/// isValidReturnType - Return true if the specified type is valid as a return
-/// type.
-bool FunctionType::isValidReturnType(const Type *RetTy) {
- return !RetTy->isFunctionTy() && !RetTy->isLabelTy() &&
- !RetTy->isMetadataTy();
+IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
+ assert(NumBits >= MIN_INT_BITS && "bitwidth too small");
+ assert(NumBits <= MAX_INT_BITS && "bitwidth too large");
+
+ // Check for the built-in integer types
+ switch (NumBits) {
+ case 1: return cast<IntegerType>(Type::getInt1Ty(C));
+ case 8: return cast<IntegerType>(Type::getInt8Ty(C));
+ case 16: return cast<IntegerType>(Type::getInt16Ty(C));
+ case 32: return cast<IntegerType>(Type::getInt32Ty(C));
+ case 64: return cast<IntegerType>(Type::getInt64Ty(C));
+ default:
+ break;
+ }
+
+ IntegerType *&Entry = C.pImpl->IntegerTypes[NumBits];
+
+ if (Entry == 0)
+ Entry = new (C.pImpl->TypeAllocator) IntegerType(C, NumBits);
+
+ return Entry;
}
-/// isValidArgumentType - Return true if the specified type is valid as an
-/// argument type.
-bool FunctionType::isValidArgumentType(const Type *ArgTy) {
- return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy();
+bool IntegerType::isPowerOf2ByteWidth() const {
+ unsigned BitWidth = getBitWidth();
+ return (BitWidth > 7) && isPowerOf2_32(BitWidth);
}
-FunctionType::FunctionType(const Type *Result,
- ArrayRef<const Type*> Params,
+APInt IntegerType::getMask() const {
+ return APInt::getAllOnesValue(getBitWidth());
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionType Implementation
+//===----------------------------------------------------------------------===//
+
+FunctionType::FunctionType(const Type *Result, ArrayRef<Type*> Params,
bool IsVarArgs)
- : DerivedType(Result->getContext(), FunctionTyID), isVarArgs(IsVarArgs) {
- ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
- NumContainedTys = Params.size() + 1; // + 1 for result type
+ : Type(Result->getContext(), FunctionTyID) {
+ Type **SubTys = reinterpret_cast<Type**>(this+1);
assert(isValidReturnType(Result) && "invalid return type for function");
+ setSubclassData(IsVarArgs);
+ SubTys[0] = const_cast<Type*>(Result);
- bool isAbstract = Result->isAbstract();
- new (&ContainedTys[0]) PATypeHandle(Result, this);
-
- for (unsigned i = 0; i != Params.size(); ++i) {
+ for (unsigned i = 0, e = Params.size(); i != e; ++i) {
assert(isValidArgumentType(Params[i]) &&
"Not a valid type for function argument!");
- new (&ContainedTys[i+1]) PATypeHandle(Params[i], this);
- isAbstract |= Params[i]->isAbstract();
+ SubTys[i+1] = Params[i];
}
- // Calculate whether or not this type is abstract
- setAbstract(isAbstract);
+ ContainedTys = SubTys;
+ NumContainedTys = Params.size() + 1; // + 1 for result type
}
-StructType::StructType(LLVMContext &C,
- ArrayRef<const Type*> Types, bool isPacked)
- : CompositeType(C, StructTyID) {
- ContainedTys = reinterpret_cast<PATypeHandle*>(this + 1);
- NumContainedTys = Types.size();
- setSubclassData(isPacked);
- bool isAbstract = false;
- for (unsigned i = 0; i < Types.size(); ++i) {
- assert(Types[i] && "<null> type for structure field!");
- assert(isValidElementType(Types[i]) &&
- "Invalid type for structure element!");
- new (&ContainedTys[i]) PATypeHandle(Types[i], this);
- isAbstract |= Types[i]->isAbstract();
+// FunctionType::get - The factory function for the FunctionType class.
+FunctionType *FunctionType::get(const Type *ReturnType,
+ ArrayRef<Type*> Params, bool isVarArg) {
+ // TODO: This is brutally slow.
+ std::vector<Type*> Key;
+ Key.reserve(Params.size()+2);
+ Key.push_back(const_cast<Type*>(ReturnType));
+ for (unsigned i = 0, e = Params.size(); i != e; ++i)
+ Key.push_back(const_cast<Type*>(Params[i]));
+ if (isVarArg)
+ Key.push_back(0);
+
+ LLVMContextImpl *pImpl = ReturnType->getContext().pImpl;
+ FunctionType *&FT = pImpl->FunctionTypes[Key];
+
+ if (FT == 0) {
+ FT = (FunctionType*) pImpl->TypeAllocator.
+ Allocate(sizeof(FunctionType) + sizeof(Type*)*(Params.size()+1),
+ AlignOf<FunctionType>::Alignment);
+ new (FT) FunctionType(ReturnType, Params, isVarArg);
}
- // Calculate whether or not this type is abstract
- setAbstract(isAbstract);
-}
-
-ArrayType::ArrayType(const Type *ElType, uint64_t NumEl)
- : SequentialType(ArrayTyID, ElType) {
- NumElements = NumEl;
-
- // Calculate whether or not this type is abstract
- setAbstract(ElType->isAbstract());
-}
-
-VectorType::VectorType(const Type *ElType, unsigned NumEl)
- : SequentialType(VectorTyID, ElType) {
- NumElements = NumEl;
- setAbstract(ElType->isAbstract());
- assert(NumEl > 0 && "NumEl of a VectorType must be greater than 0");
- assert(isValidElementType(ElType) &&
- "Elements of a VectorType must be a primitive type");
-
-}
-
-
-PointerType::PointerType(const Type *E, unsigned AddrSpace)
- : SequentialType(PointerTyID, E) {
- AddressSpace = AddrSpace;
- // Calculate whether or not this type is abstract
- setAbstract(E->isAbstract());
-}
-
-OpaqueType::OpaqueType(LLVMContext &C) : DerivedType(C, OpaqueTyID) {
- setAbstract(true);
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *this << "\n");
-#endif
+ return FT;
}
-void PATypeHolder::destroy() {
- Ty = 0;
-}
-// 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 (NumContainedTys != 0) {
- // 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.
- ContainedTys[0] = getContext().pImpl->AlwaysOpaqueTy;
-
- // Change the rest of the types to be Int32Ty's. It doesn't matter what we
- // pick so long as it doesn't point back to this type. We choose something
- // concrete to avoid overhead for adding to AbstractTypeUser lists and
- // stuff.
- const Type *ConcreteTy = Type::getInt32Ty(getContext());
- for (unsigned i = 1, e = NumContainedTys; i != e; ++i)
- ContainedTys[i] = ConcreteTy;
- }
+FunctionType *FunctionType::get(const Type *Result, bool isVarArg) {
+ return get(Result, ArrayRef<Type *>(), isVarArg);
}
-namespace {
-
-/// TypePromotionGraph and graph traits - this is designed to allow us to do
-/// efficient SCC processing of type graphs. This is the exact same as
-/// GraphTraits<Type*>, except that we pretend that concrete types have no
-/// children to avoid processing them.
-struct TypePromotionGraph {
- Type *Ty;
- TypePromotionGraph(Type *T) : Ty(T) {}
-};
-
-}
-
-namespace llvm {
- template <> struct GraphTraits<TypePromotionGraph> {
- typedef Type NodeType;
- typedef Type::subtype_iterator ChildIteratorType;
-
- static inline NodeType *getEntryNode(TypePromotionGraph G) { return G.Ty; }
- static inline ChildIteratorType child_begin(NodeType *N) {
- if (N->isAbstract())
- return N->subtype_begin();
- // No need to process children of concrete types.
- return N->subtype_end();
- }
- static inline ChildIteratorType child_end(NodeType *N) {
- return N->subtype_end();
- }
- };
+/// isValidReturnType - Return true if the specified type is valid as a return
+/// type.
+bool FunctionType::isValidReturnType(const Type *RetTy) {
+ return !RetTy->isFunctionTy() && !RetTy->isLabelTy() &&
+ !RetTy->isMetadataTy();
}
-
-// PromoteAbstractToConcrete - This is a recursive function that walks a type
-// graph calculating whether or not a type is abstract.
-//
-void Type::PromoteAbstractToConcrete() {
- if (!isAbstract()) return;
-
- scc_iterator<TypePromotionGraph> SI = scc_begin(TypePromotionGraph(this));
- scc_iterator<TypePromotionGraph> SE = scc_end (TypePromotionGraph(this));
-
- for (; SI != SE; ++SI) {
- std::vector<Type*> &SCC = *SI;
-
- // Concrete types are leaves in the tree. Since an SCC will either be all
- // abstract or all concrete, we only need to check one type.
- if (!SCC[0]->isAbstract()) continue;
-
- if (SCC[0]->isOpaqueTy())
- return; // Not going to be concrete, sorry.
-
- // If all of the children of all of the types in this SCC are concrete,
- // then this SCC is now concrete as well. If not, neither this SCC, nor
- // any parent SCCs will be concrete, so we might as well just exit.
- for (unsigned i = 0, e = SCC.size(); i != e; ++i)
- for (Type::subtype_iterator CI = SCC[i]->subtype_begin(),
- E = SCC[i]->subtype_end(); CI != E; ++CI)
- if ((*CI)->isAbstract())
- // If the child type is in our SCC, it doesn't make the entire SCC
- // abstract unless there is a non-SCC abstract type.
- if (std::find(SCC.begin(), SCC.end(), *CI) == SCC.end())
- return; // Not going to be concrete, sorry.
-
- // Okay, we just discovered this whole SCC is now concrete, mark it as
- // such!
- for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
- assert(SCC[i]->isAbstract() && "Why are we processing concrete types?");
-
- SCC[i]->setAbstract(false);
- }
-
- for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
- assert(!SCC[i]->isAbstract() && "Concrete type became abstract?");
- // The type just became concrete, notify all users!
- cast<DerivedType>(SCC[i])->notifyUsesThatTypeBecameConcrete();
- }
- }
+/// isValidArgumentType - Return true if the specified type is valid as an
+/// argument type.
+bool FunctionType::isValidArgumentType(const Type *ArgTy) {
+ return ArgTy->isFirstClassType();
}
-
//===----------------------------------------------------------------------===//
-// Type Structural Equality Testing
+// StructType Implementation
//===----------------------------------------------------------------------===//
-// TypesEqual - Two types are considered structurally equal if they have the
-// same "shape": Every level and element of the types have identical primitive
-// ID's, and the graphs have the same edges/nodes in them. Nodes do not have to
-// be pointer equals to be equivalent though. This uses an optimistic algorithm
-// that assumes that two graphs are the same until proven otherwise.
-//
-static bool TypesEqual(const Type *Ty, const Type *Ty2,
- std::map<const Type *, const Type *> &EqTypes) {
- if (Ty == Ty2) return true;
- if (Ty->getTypeID() != Ty2->getTypeID()) return false;
- if (Ty->isOpaqueTy())
- return false; // Two unequal opaque types are never equal
-
- std::map<const Type*, const Type*>::iterator It = EqTypes.find(Ty);
- if (It != EqTypes.end())
- return It->second == Ty2; // Looping back on a type, check for equality
-
- // Otherwise, add the mapping to the table to make sure we don't get
- // recursion on the types...
- EqTypes.insert(It, std::make_pair(Ty, Ty2));
-
- // Two really annoying special cases that breaks an otherwise nice simple
- // algorithm is the fact that arraytypes have sizes that differentiates types,
- // and that function types can be varargs or not. Consider this now.
- //
- if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
- const IntegerType *ITy2 = cast<IntegerType>(Ty2);
- return ITy->getBitWidth() == ITy2->getBitWidth();
- }
-
- if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- const PointerType *PTy2 = cast<PointerType>(Ty2);
- return PTy->getAddressSpace() == PTy2->getAddressSpace() &&
- TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes);
+// Primitive Constructors.
+
+StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes,
+ bool isPacked) {
+ // FIXME: std::vector is horribly inefficient for this probe.
+ std::vector<Type*> Key;
+ for (unsigned i = 0, e = ETypes.size(); i != e; ++i) {
+ assert(isValidElementType(ETypes[i]) &&
+ "Invalid type for structure element!");
+ Key.push_back(ETypes[i]);
}
+ if (isPacked)
+ Key.push_back(0);
- if (const StructType *STy = dyn_cast<StructType>(Ty)) {
- const StructType *STy2 = cast<StructType>(Ty2);
- if (STy->getNumElements() != STy2->getNumElements()) return false;
- if (STy->isPacked() != STy2->isPacked()) 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;
- }
+ StructType *&ST = Context.pImpl->AnonStructTypes[Key];
+ if (ST) return ST;
- if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
- const ArrayType *ATy2 = cast<ArrayType>(Ty2);
- return ATy->getNumElements() == ATy2->getNumElements() &&
- TypesEqual(ATy->getElementType(), ATy2->getElementType(), EqTypes);
- }
+ // Value not found. Create a new type!
+ ST = new (Context.pImpl->TypeAllocator) StructType(Context);
+ ST->setSubclassData(SCDB_IsAnonymous); // Anonymous struct.
+ ST->setBody(ETypes, isPacked);
+ return ST;
+}
+
+void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {
+ assert(isOpaque() && "Struct body already set!");
- if (const VectorType *PTy = dyn_cast<VectorType>(Ty)) {
- const VectorType *PTy2 = cast<VectorType>(Ty2);
- return PTy->getNumElements() == PTy2->getNumElements() &&
- TypesEqual(PTy->getElementType(), PTy2->getElementType(), EqTypes);
- }
+ setSubclassData(getSubclassData() | SCDB_HasBody);
+ if (isPacked)
+ setSubclassData(getSubclassData() | SCDB_Packed);
- if (const FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
- const FunctionType *FTy2 = cast<FunctionType>(Ty2);
- if (FTy->isVarArg() != FTy2->isVarArg() ||
- FTy->getNumParams() != FTy2->getNumParams() ||
- !TypesEqual(FTy->getReturnType(), FTy2->getReturnType(), EqTypes))
- return false;
- for (unsigned i = 0, e = FTy2->getNumParams(); i != e; ++i) {
- if (!TypesEqual(FTy->getParamType(i), FTy2->getParamType(i), EqTypes))
- return false;
- }
- return true;
- }
+ Type **Elts = getContext().pImpl->
+ TypeAllocator.Allocate<Type*>(Elements.size());
+ memcpy(Elts, Elements.data(), sizeof(Elements[0])*Elements.size());
- llvm_unreachable("Unknown derived type!");
- return false;
-}
-
-namespace llvm { // in namespace llvm so findable by ADL
-static bool TypesEqual(const Type *Ty, const Type *Ty2) {
- std::map<const Type *, const Type *> EqTypes;
- return ::TypesEqual(Ty, Ty2, EqTypes);
-}
-}
-
-// AbstractTypeHasCycleThrough - 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 AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy,
- SmallPtrSet<const Type*, 128> &VisitedTypes) {
- if (TargetTy == CurTy) return true;
- if (!CurTy->isAbstract()) return false;
-
- if (!VisitedTypes.insert(CurTy))
- return false; // Already been here.
-
- for (Type::subtype_iterator I = CurTy->subtype_begin(),
- E = CurTy->subtype_end(); I != E; ++I)
- if (AbstractTypeHasCycleThrough(TargetTy, *I, VisitedTypes))
- return true;
- return false;
+ ContainedTys = Elts;
+ NumContainedTys = Elements.size();
}
-static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy,
- SmallPtrSet<const Type*, 128> &VisitedTypes) {
- if (TargetTy == CurTy) return true;
-
- if (!VisitedTypes.insert(CurTy))
- return false; // Already been here.
-
- for (Type::subtype_iterator I = CurTy->subtype_begin(),
- E = CurTy->subtype_end(); I != E; ++I)
- if (ConcreteTypeHasCycleThrough(TargetTy, *I, VisitedTypes))
- return true;
- return false;
+StructType *StructType::createNamed(LLVMContext &Context, StringRef Name) {
+ StructType *ST = new (Context.pImpl->TypeAllocator) StructType(Context);
+ if (!Name.empty())
+ ST->setName(Name);
+ return ST;
}
-/// TypeHasCycleThroughItself - Return true if the specified type has
-/// a cycle back to itself.
+void StructType::setName(StringRef Name) {
+ if (Name == getName()) return;
-namespace llvm { // in namespace llvm so it's findable by ADL
-static bool TypeHasCycleThroughItself(const Type *Ty) {
- SmallPtrSet<const Type*, 128> VisitedTypes;
-
- if (Ty->isAbstract()) { // Optimized case for abstract types.
- for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
- I != E; ++I)
- if (AbstractTypeHasCycleThrough(Ty, *I, VisitedTypes))
- return true;
- } else {
- for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
- I != E; ++I)
- if (ConcreteTypeHasCycleThrough(Ty, *I, VisitedTypes))
- return true;
+ // If this struct already had a name, remove its symbol table entry.
+ if (SymbolTableEntry) {
+ getContext().pImpl->NamedStructTypes.erase(getName());
+ SymbolTableEntry = 0;
}
- return false;
-}
-}
-
-//===----------------------------------------------------------------------===//
-// Function Type Factory and Value Class...
-//
-const IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
- assert(NumBits >= MIN_INT_BITS && "bitwidth too small");
- assert(NumBits <= MAX_INT_BITS && "bitwidth too large");
-
- // Check for the built-in integer types
- switch (NumBits) {
- case 1: return cast<IntegerType>(Type::getInt1Ty(C));
- case 8: return cast<IntegerType>(Type::getInt8Ty(C));
- case 16: return cast<IntegerType>(Type::getInt16Ty(C));
- case 32: return cast<IntegerType>(Type::getInt32Ty(C));
- case 64: return cast<IntegerType>(Type::getInt64Ty(C));
- default:
- break;
- }
-
- LLVMContextImpl *pImpl = C.pImpl;
- IntegerValType IVT(NumBits);
- IntegerType *ITy = 0;
+ // If this is just removing the name, we're done.
+ if (Name.empty())
+ return;
- // First, see if the type is already in the table, for which
- // a reader lock suffices.
- ITy = pImpl->IntegerTypes.get(IVT);
-
- if (!ITy) {
- // Value not found. Derive a new type!
- ITy = new IntegerType(C, NumBits);
- pImpl->IntegerTypes.add(IVT, ITy);
+ // Look up the entry for the name.
+ StringMapEntry<StructType*> *Entry =
+ &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name);
+
+ // While we have a name collision, try a random rename.
+ if (Entry->getValue()) {
+ SmallString<64> TempStr(Name);
+ TempStr.push_back('.');
+ raw_svector_ostream TmpStream(TempStr);
+
+ do {
+ TempStr.resize(Name.size()+1);
+ TmpStream.resync();
+ TmpStream << getContext().pImpl->NamedStructTypesUniqueID++;
+
+ Entry = &getContext().pImpl->
+ NamedStructTypes.GetOrCreateValue(TmpStream.str());
+ } while (Entry->getValue());
}
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *ITy << "\n");
-#endif
- return ITy;
-}
-bool IntegerType::isPowerOf2ByteWidth() const {
- unsigned BitWidth = getBitWidth();
- return (BitWidth > 7) && isPowerOf2_32(BitWidth);
+ // Okay, we found an entry that isn't used. It's us!
+ Entry->setValue(this);
+
+ SymbolTableEntry = Entry;
}
-APInt IntegerType::getMask() const {
- return APInt::getAllOnesValue(getBitWidth());
-}
+//===----------------------------------------------------------------------===//
+// StructType Helper functions.
-FunctionValType FunctionValType::get(const FunctionType *FT) {
- // Build up a FunctionValType
- std::vector<const Type *> ParamTypes;
- 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());
+StructType *StructType::get(LLVMContext &Context, bool isPacked) {
+ return get(Context, llvm::ArrayRef<Type*>(), isPacked);
}
-
-// FunctionType::get - The factory function for the FunctionType class...
-FunctionType *FunctionType::get(const Type *ReturnType,
- ArrayRef<const Type*> Params,
- bool isVarArg) {
- FunctionValType VT(ReturnType, Params, isVarArg);
- FunctionType *FT = 0;
-
- LLVMContextImpl *pImpl = ReturnType->getContext().pImpl;
-
- FT = pImpl->FunctionTypes.get(VT);
-
- if (!FT) {
- FT = (FunctionType*) operator new(sizeof(FunctionType) +
- sizeof(PATypeHandle)*(Params.size()+1));
- new (FT) FunctionType(ReturnType, Params, isVarArg);
- pImpl->FunctionTypes.add(VT, FT);
+StructType *StructType::get(Type *type, ...) {
+ assert(type != 0 && "Cannot create a struct type with no elements with this");
+ LLVMContext &Ctx = type->getContext();
+ va_list ap;
+ SmallVector<llvm::Type*, 8> StructFields;
+ va_start(ap, type);
+ while (type) {
+ StructFields.push_back(type);
+ type = va_arg(ap, llvm::Type*);
}
-
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << FT << "\n");
-#endif
- return FT;
+ return llvm::StructType::get(Ctx, StructFields);
}
-ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) {
- assert(ElementType && "Can't get array of <null> types!");
- assert(isValidElementType(ElementType) && "Invalid type for array element!");
-
- ArrayValType AVT(ElementType, NumElements);
- ArrayType *AT = 0;
-
- LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
-
- AT = pImpl->ArrayTypes.get(AVT);
-
- if (!AT) {
- // Value not found. Derive a new type!
- pImpl->ArrayTypes.add(AVT, AT = new ArrayType(ElementType, NumElements));
- }
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *AT << "\n");
-#endif
- return AT;
+StructType *StructType::createNamed(LLVMContext &Context, StringRef Name,
+ ArrayRef<Type*> Elements, bool isPacked) {
+ StructType *ST = createNamed(Context, Name);
+ ST->setBody(Elements, isPacked);
+ return ST;
}
-bool ArrayType::isValidElementType(const Type *ElemTy) {
- return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
- !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
+StructType *StructType::createNamed(StringRef Name, ArrayRef<Type*> Elements,
+ bool isPacked) {
+ assert(!Elements.empty() &&
+ "This method may not be invoked with an empty list");
+ return createNamed(Elements[0]->getContext(), Name, Elements, isPacked);
}
-VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) {
- assert(ElementType && "Can't get vector of <null> types!");
-
- VectorValType PVT(ElementType, NumElements);
- VectorType *PT = 0;
-
- LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
-
- PT = pImpl->VectorTypes.get(PVT);
-
- if (!PT) {
- pImpl->VectorTypes.add(PVT, PT = new VectorType(ElementType, NumElements));
+StructType *StructType::createNamed(StringRef Name, Type *type, ...) {
+ assert(type != 0 && "Cannot create a struct type with no elements with this");
+ LLVMContext &Ctx = type->getContext();
+ va_list ap;
+ SmallVector<llvm::Type*, 8> StructFields;
+ va_start(ap, type);
+ while (type) {
+ StructFields.push_back(type);
+ type = va_arg(ap, llvm::Type*);
}
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *PT << "\n");
-#endif
- return PT;
-}
-
-bool VectorType::isValidElementType(const Type *ElemTy) {
- return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() ||
- ElemTy->isOpaqueTy();
+ return llvm::StructType::createNamed(Ctx, Name, StructFields);
}
-//===----------------------------------------------------------------------===//
-// Struct Type Factory...
-//
-
-StructType *StructType::get(LLVMContext &Context,
- ArrayRef<const Type*> ETypes,
- bool isPacked) {
- StructValType STV(ETypes, isPacked);
- StructType *ST = 0;
-
- LLVMContextImpl *pImpl = Context.pImpl;
+StringRef StructType::getName() const {
+ assert(!isAnonymous() && "Anonymous structs never have names");
+ if (SymbolTableEntry == 0) return StringRef();
- ST = pImpl->StructTypes.get(STV);
-
- if (!ST) {
- // Value not found. Derive a new type!
- ST = (StructType*) operator new(sizeof(StructType) +
- sizeof(PATypeHandle) * ETypes.size());
- new (ST) StructType(Context, ETypes, isPacked);
- pImpl->StructTypes.add(STV, ST);
- }
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *ST << "\n");
-#endif
- return ST;
+ return ((StringMapEntry<StructType*> *)SymbolTableEntry)->getKey();
}
-StructType *StructType::get(LLVMContext &Context, const Type *type, ...) {
+void StructType::setBody(Type *type, ...) {
+ assert(type != 0 && "Cannot create a struct type with no elements with this");
va_list ap;
- std::vector<const llvm::Type*> StructFields;
+ SmallVector<llvm::Type*, 8> StructFields;
va_start(ap, type);
while (type) {
StructFields.push_back(type);
type = va_arg(ap, llvm::Type*);
}
- return llvm::StructType::get(Context, StructFields);
+ setBody(StructFields);
}
bool StructType::isValidElementType(const Type *ElemTy) {
@@ -973,278 +529,159 @@ bool StructType::isValidElementType(const Type *ElemTy) {
!ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
}
-
-//===----------------------------------------------------------------------===//
-// Pointer Type Factory...
-//
-
-PointerType *PointerType::get(const Type *ValueType, unsigned AddressSpace) {
- assert(ValueType && "Can't get a pointer to <null> type!");
- assert(ValueType->getTypeID() != VoidTyID &&
- "Pointer to void is not valid, use i8* instead!");
- assert(isValidElementType(ValueType) && "Invalid type for pointer element!");
- PointerValType PVT(ValueType, AddressSpace);
-
- PointerType *PT = 0;
-
- LLVMContextImpl *pImpl = ValueType->getContext().pImpl;
+/// isLayoutIdentical - Return true if this is layout identical to the
+/// specified struct.
+bool StructType::isLayoutIdentical(const StructType *Other) const {
+ if (this == Other) return true;
- PT = pImpl->PointerTypes.get(PVT);
+ if (isPacked() != Other->isPacked() ||
+ getNumElements() != Other->getNumElements())
+ return false;
- if (!PT) {
- // Value not found. Derive a new type!
- pImpl->PointerTypes.add(PVT, PT = new PointerType(ValueType, AddressSpace));
- }
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "Derived new type: " << *PT << "\n");
-#endif
- return PT;
+ return std::equal(element_begin(), element_end(), Other->element_begin());
}
-const PointerType *Type::getPointerTo(unsigned addrs) const {
- return PointerType::get(this, addrs);
-}
-bool PointerType::isValidElementType(const Type *ElemTy) {
- return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
- !ElemTy->isMetadataTy();
+/// getTypeByName - Return the type with the specified name, or null if there
+/// is none by that name.
+StructType *Module::getTypeByName(StringRef Name) const {
+ StringMap<StructType*>::iterator I =
+ getContext().pImpl->NamedStructTypes.find(Name);
+ if (I != getContext().pImpl->NamedStructTypes.end())
+ return I->second;
+ return 0;
}
//===----------------------------------------------------------------------===//
-// Opaque Type Factory...
-//
+// CompositeType Implementation
+//===----------------------------------------------------------------------===//
-OpaqueType *OpaqueType::get(LLVMContext &C) {
- OpaqueType *OT = new OpaqueType(C); // All opaque types are distinct.
- LLVMContextImpl *pImpl = C.pImpl;
- pImpl->OpaqueTypes.insert(OT);
- return OT;
+Type *CompositeType::getTypeAtIndex(const Value *V) const {
+ if (const StructType *STy = dyn_cast<StructType>(this)) {
+ unsigned Idx = (unsigned)cast<ConstantInt>(V)->getZExtValue();
+ assert(indexValid(Idx) && "Invalid structure index!");
+ return STy->getElementType(Idx);
+ }
+
+ return cast<SequentialType>(this)->getElementType();
+}
+Type *CompositeType::getTypeAtIndex(unsigned Idx) const {
+ if (const StructType *STy = dyn_cast<StructType>(this)) {
+ assert(indexValid(Idx) && "Invalid structure index!");
+ return STy->getElementType(Idx);
+ }
+
+ return cast<SequentialType>(this)->getElementType();
+}
+bool CompositeType::indexValid(const Value *V) const {
+ if (const StructType *STy = dyn_cast<StructType>(this)) {
+ // Structure indexes require 32-bit integer constants.
+ if (V->getType()->isIntegerTy(32))
+ if (const ConstantInt *CU = dyn_cast<ConstantInt>(V))
+ return CU->getZExtValue() < STy->getNumElements();
+ return false;
+ }
+
+ // Sequential types can be indexed by any integer.
+ return V->getType()->isIntegerTy();
}
+bool CompositeType::indexValid(unsigned Idx) const {
+ if (const StructType *STy = dyn_cast<StructType>(this))
+ return Idx < STy->getNumElements();
+ // Sequential types can be indexed by any integer.
+ return true;
+}
//===----------------------------------------------------------------------===//
-// Derived Type Refinement Functions
+// ArrayType Implementation
//===----------------------------------------------------------------------===//
-// addAbstractTypeUser - Notify an abstract type that there is a new user of
-// it. This function is called primarily by the PATypeHandle class.
-void Type::addAbstractTypeUser(AbstractTypeUser *U) const {
- assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
- AbstractTypeUsers.push_back(U);
+ArrayType::ArrayType(Type *ElType, uint64_t NumEl)
+ : SequentialType(ArrayTyID, ElType) {
+ NumElements = NumEl;
}
-// removeAbstractTypeUser - Notify an abstract type that a user of the class
-// no longer has a handle to the type. This function is called primarily by
-// the PATypeHandle class. When there are no users of the abstract type, it
-// is annihilated, because there is no way to get a reference to it ever again.
-//
-void Type::removeAbstractTypeUser(AbstractTypeUser *U) const {
-
- // Search from back to front because we will notify users from back to
- // front. Also, it is likely that there will be a stack like behavior to
- // users that register and unregister users.
- //
- unsigned i;
- for (i = AbstractTypeUsers.size(); AbstractTypeUsers[i-1] != U; --i)
- assert(i != 0 && "AbstractTypeUser not in user list!");
-
- --i; // Convert to be in range 0 <= i < size()
- assert(i < AbstractTypeUsers.size() && "Index out of range!"); // Wraparound?
-
- AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i);
-
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << " remAbstractTypeUser[" << (void*)this << ", "
- << *this << "][" << i << "] User = " << U << "\n");
-#endif
-
- if (AbstractTypeUsers.empty() && getRefCount() == 0 && isAbstract()) {
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "DELETEing unused abstract type: <" << *this
- << ">[" << (void*)this << "]" << "\n");
-#endif
+ArrayType *ArrayType::get(const Type *elementType, uint64_t NumElements) {
+ Type *ElementType = const_cast<Type*>(elementType);
+ assert(isValidElementType(ElementType) && "Invalid type for array element!");
+
+ LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
+ ArrayType *&Entry =
+ pImpl->ArrayTypes[std::make_pair(ElementType, NumElements)];
- this->destroy();
- }
-}
-
-// refineAbstractTypeTo - This function is used when it is discovered
-// that the 'this' abstract type is actually equivalent to the NewType
-// specified. This causes all users of 'this' to switch to reference the more
-// concrete type NewType and for 'this' to be deleted. Only used for internal
-// callers.
-//
-void DerivedType::refineAbstractTypeTo(const Type *NewType) {
- assert(isAbstract() && "refineAbstractTypeTo: Current type is not abstract!");
- assert(this != NewType && "Can't refine to myself!");
- assert(ForwardType == 0 && "This type has already been refined!");
-
- LLVMContextImpl *pImpl = getContext().pImpl;
-
- // The descriptions may be out of date. Conservatively clear them all!
- pImpl->AbstractTypeDescriptions.clear();
-
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "REFINING abstract type [" << (void*)this << " "
- << *this << "] to [" << (void*)NewType << " "
- << *NewType << "]!\n");
-#endif
-
- // Make sure to put the type to be refined to into a holder so that if IT gets
- // refined, that we will not continue using a dead reference...
- //
- PATypeHolder NewTy(NewType);
- // Any PATypeHolders referring to this type will now automatically forward to
- // the type we are resolved to.
- ForwardType = NewType;
- if (ForwardType->isAbstract())
- ForwardType->addRef();
-
- // Add a self use of the current type so that we don't delete ourself until
- // after the function exits.
- //
- PATypeHolder CurrentTy(this);
-
- // To make the situation simpler, we ask the subclass to remove this type from
- // the type map, and to replace any type uses with uses of non-abstract types.
- // This dramatically limits the amount of recursive type trouble we can find
- // ourselves in.
- dropAllTypeUses();
-
- // Iterate over all of the uses of this type, invoking callback. Each user
- // should remove itself from our use list automatically. We have to check to
- // make sure that NewTy doesn't _become_ 'this'. If it does, resolving types
- // will not cause users to drop off of the use list. If we resolve to ourself
- // we succeed!
- //
- while (!AbstractTypeUsers.empty() && NewTy != this) {
- AbstractTypeUser *User = AbstractTypeUsers.back();
-
- unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize;
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << " REFINING user " << OldSize-1 << "[" << (void*)User
- << "] of abstract type [" << (void*)this << " "
- << *this << "] to [" << (void*)NewTy.get() << " "
- << *NewTy << "]!\n");
-#endif
- User->refineAbstractType(this, NewTy);
-
- assert(AbstractTypeUsers.size() != OldSize &&
- "AbsTyUser did not remove self from user list!");
- }
-
- // If we were successful removing all users from the type, 'this' will be
- // deleted when the last PATypeHolder is destroyed or updated from this type.
- // This may occur on exit of this function, as the CurrentTy object is
- // destroyed.
-}
-
-// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type that
-// the current type has transitioned from being abstract to being concrete.
-//
-void DerivedType::notifyUsesThatTypeBecameConcrete() {
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "typeIsREFINED type: " << (void*)this << " " << *this <<"\n");
-#endif
-
- unsigned OldSize = AbstractTypeUsers.size(); (void)OldSize;
- while (!AbstractTypeUsers.empty()) {
- AbstractTypeUser *ATU = AbstractTypeUsers.back();
- ATU->typeBecameConcrete(this);
-
- assert(AbstractTypeUsers.size() < OldSize-- &&
- "AbstractTypeUser did not remove itself from the use list!");
- }
-}
-
-// refineAbstractType - Called when a contained type is found to be more
-// concrete - this could potentially change us from an abstract type to a
-// concrete type.
-//
-void FunctionType::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- LLVMContextImpl *pImpl = OldType->getContext().pImpl;
- pImpl->FunctionTypes.RefineAbstractType(this, OldType, NewType);
+ if (Entry == 0)
+ Entry = new (pImpl->TypeAllocator) ArrayType(ElementType, NumElements);
+ return Entry;
}
-void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->FunctionTypes.TypeBecameConcrete(this, AbsTy);
+bool ArrayType::isValidElementType(const Type *ElemTy) {
+ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
+ !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
}
+//===----------------------------------------------------------------------===//
+// VectorType Implementation
+//===----------------------------------------------------------------------===//
-// refineAbstractType - Called when a contained type is found to be more
-// concrete - this could potentially change us from an abstract type to a
-// concrete type.
-//
-void ArrayType::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- LLVMContextImpl *pImpl = OldType->getContext().pImpl;
- pImpl->ArrayTypes.RefineAbstractType(this, OldType, NewType);
+VectorType::VectorType(Type *ElType, unsigned NumEl)
+ : SequentialType(VectorTyID, ElType) {
+ NumElements = NumEl;
}
-void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->ArrayTypes.TypeBecameConcrete(this, AbsTy);
+VectorType *VectorType::get(const Type *elementType, unsigned NumElements) {
+ Type *ElementType = const_cast<Type*>(elementType);
+ assert(NumElements > 0 && "#Elements of a VectorType must be greater than 0");
+ assert(isValidElementType(ElementType) &&
+ "Elements of a VectorType must be a primitive type");
+
+ LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
+ VectorType *&Entry = ElementType->getContext().pImpl
+ ->VectorTypes[std::make_pair(ElementType, NumElements)];
+
+ if (Entry == 0)
+ Entry = new (pImpl->TypeAllocator) VectorType(ElementType, NumElements);
+ return Entry;
}
-// refineAbstractType - Called when a contained type is found to be more
-// concrete - this could potentially change us from an abstract type to a
-// concrete type.
-//
-void VectorType::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- LLVMContextImpl *pImpl = OldType->getContext().pImpl;
- pImpl->VectorTypes.RefineAbstractType(this, OldType, NewType);
+bool VectorType::isValidElementType(const Type *ElemTy) {
+ return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy();
}
-void VectorType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->VectorTypes.TypeBecameConcrete(this, AbsTy);
-}
+//===----------------------------------------------------------------------===//
+// PointerType Implementation
+//===----------------------------------------------------------------------===//
-// refineAbstractType - Called when a contained type is found to be more
-// concrete - this could potentially change us from an abstract type to a
-// concrete type.
-//
-void StructType::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- LLVMContextImpl *pImpl = OldType->getContext().pImpl;
- pImpl->StructTypes.RefineAbstractType(this, OldType, NewType);
-}
+PointerType *PointerType::get(const Type *eltTy, unsigned AddressSpace) {
+ Type *EltTy = const_cast<Type*>(eltTy);
+ assert(EltTy && "Can't get a pointer to <null> type!");
+ assert(isValidElementType(EltTy) && "Invalid type for pointer element!");
+
+ LLVMContextImpl *CImpl = EltTy->getContext().pImpl;
+
+ // Since AddressSpace #0 is the common case, we special case it.
+ PointerType *&Entry = AddressSpace == 0 ? CImpl->PointerTypes[EltTy]
+ : CImpl->ASPointerTypes[std::make_pair(EltTy, AddressSpace)];
-void StructType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->StructTypes.TypeBecameConcrete(this, AbsTy);
+ if (Entry == 0)
+ Entry = new (CImpl->TypeAllocator) PointerType(EltTy, AddressSpace);
+ return Entry;
}
-// refineAbstractType - Called when a contained type is found to be more
-// concrete - this could potentially change us from an abstract type to a
-// concrete type.
-//
-void PointerType::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- LLVMContextImpl *pImpl = OldType->getContext().pImpl;
- pImpl->PointerTypes.RefineAbstractType(this, OldType, NewType);
-}
-void PointerType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->PointerTypes.TypeBecameConcrete(this, AbsTy);
+PointerType::PointerType(Type *E, unsigned AddrSpace)
+ : SequentialType(PointerTyID, E) {
+ setSubclassData(AddrSpace);
}
-bool SequentialType::indexValid(const Value *V) const {
- if (V->getType()->isIntegerTy())
- return true;
- return false;
+PointerType *Type::getPointerTo(unsigned addrs) const {
+ return PointerType::get(this, addrs);
}
-namespace llvm {
-raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
- T.print(OS);
- return OS;
-}
+bool PointerType::isValidElementType(const Type *ElemTy) {
+ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
+ !ElemTy->isMetadataTy();
}
diff --git a/lib/VMCore/TypeSymbolTable.cpp b/lib/VMCore/TypeSymbolTable.cpp
deleted file mode 100644
index d68a44b..0000000
--- a/lib/VMCore/TypeSymbolTable.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-//===-- TypeSymbolTable.cpp - Implement the TypeSymbolTable class ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the TypeSymbolTable class for the VMCore library.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-using namespace llvm;
-
-#define DEBUG_SYMBOL_TABLE 0
-#define DEBUG_ABSTYPE 0
-
-TypeSymbolTable::~TypeSymbolTable() {
- // Drop all abstract type references in the type plane...
- for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
- if (TI->second->isAbstract()) // If abstract, drop the reference...
- cast<DerivedType>(TI->second)->removeAbstractTypeUser(this);
- }
-}
-
-std::string TypeSymbolTable::getUniqueName(StringRef BaseName) const {
- std::string TryName = BaseName;
-
- const_iterator End = tmap.end();
-
- // See if the name exists
- while (tmap.find(TryName) != End) // Loop until we find a free
- TryName = BaseName.str() + utostr(++LastUnique); // name in the symbol table
- return TryName;
-}
-
-// lookup a type by name - returns null on failure
-Type* TypeSymbolTable::lookup(StringRef Name) const {
- const_iterator TI = tmap.find(Name);
- Type* result = 0;
- if (TI != tmap.end())
- result = const_cast<Type*>(TI->second);
- return result;
-}
-
-// remove - Remove a type from the symbol table...
-Type* TypeSymbolTable::remove(iterator Entry) {
- assert(Entry != tmap.end() && "Invalid entry to remove!");
- const Type* Result = Entry->second;
-
-#if DEBUG_SYMBOL_TABLE
- dump();
- dbgs() << " Removing Value: " << Result->getDescription() << "\n";
-#endif
-
- tmap.erase(Entry);
-
- // If we are removing an abstract type, remove the symbol table from it's use
- // list...
- if (Result->isAbstract()) {
-#if DEBUG_ABSTYPE
- dbgs() << "Removing abstract type from symtab"
- << Result->getDescription()
- << "\n";
-#endif
- cast<DerivedType>(Result)->removeAbstractTypeUser(this);
- }
-
- return const_cast<Type*>(Result);
-}
-
-
-// insert - Insert a type into the symbol table with the specified name...
-void TypeSymbolTable::insert(StringRef Name, const Type* T) {
- assert(T && "Can't insert null type into symbol table!");
-
- if (tmap.insert(std::make_pair(Name, T)).second) {
- // Type inserted fine with no conflict.
-
-#if DEBUG_SYMBOL_TABLE
- dump();
- dbgs() << " Inserted type: " << Name << ": " << T->getDescription() << "\n";
-#endif
- } else {
- // If there is a name conflict...
-
- // Check to see if there is a naming conflict. If so, rename this type!
- std::string UniqueName = Name;
- if (lookup(Name))
- UniqueName = getUniqueName(Name);
-
-#if DEBUG_SYMBOL_TABLE
- dump();
- dbgs() << " Inserting type: " << UniqueName << ": "
- << T->getDescription() << "\n";
-#endif
-
- // Insert the tmap entry
- tmap.insert(make_pair(UniqueName, T));
- }
-
- // If we are adding an abstract type, add the symbol table to it's use list.
- if (T->isAbstract()) {
- cast<DerivedType>(T)->addAbstractTypeUser(this);
-#if DEBUG_ABSTYPE
- dbgs() << "Added abstract type to ST: " << T->getDescription() << "\n";
-#endif
- }
-}
-
-// This function is called when one of the types in the type plane are refined
-void TypeSymbolTable::refineAbstractType(const DerivedType *OldType,
- const Type *NewType) {
- // Loop over all of the types in the symbol table, replacing any references
- // to OldType with references to NewType. Note that there may be multiple
- // occurrences, and although we only need to remove one at a time, it's
- // faster to remove them all in one pass.
- //
- for (iterator I = begin(), E = end(); I != E; ++I) {
- // FIXME when Types aren't const.
- if (I->second == const_cast<DerivedType *>(OldType)) {
-#if DEBUG_ABSTYPE
- dbgs() << "Removing type " << OldType->getDescription() << "\n";
-#endif
- OldType->removeAbstractTypeUser(this);
-
- // TODO FIXME when types aren't const
- I->second = const_cast<Type *>(NewType);
- if (NewType->isAbstract()) {
-#if DEBUG_ABSTYPE
- dbgs() << "Added type " << NewType->getDescription() << "\n";
-#endif
- cast<DerivedType>(NewType)->addAbstractTypeUser(this);
- }
- }
- }
-}
-
-
-// Handle situation where type becomes Concreate from Abstract
-void TypeSymbolTable::typeBecameConcrete(const DerivedType *AbsTy) {
- // Loop over all of the types in the symbol table, dropping any abstract
- // type user entries for AbsTy which occur because there are names for the
- // type.
- for (iterator TI = begin(), TE = end(); TI != TE; ++TI)
- if (TI->second == const_cast<Type*>(static_cast<const Type*>(AbsTy)))
- AbsTy->removeAbstractTypeUser(this);
-}
-
-static void DumpTypes(const std::pair<const std::string, const Type*>& T ) {
- dbgs() << " '" << T.first << "' = ";
- T.second->dump();
- dbgs() << "\n";
-}
-
-void TypeSymbolTable::dump() const {
- dbgs() << "TypeSymbolPlane: ";
- for_each(tmap.begin(), tmap.end(), DumpTypes);
-}
-
diff --git a/lib/VMCore/TypesContext.h b/lib/VMCore/TypesContext.h
deleted file mode 100644
index ad09478..0000000
--- a/lib/VMCore/TypesContext.h
+++ /dev/null
@@ -1,426 +0,0 @@
-//===-- TypesContext.h - Types-related Context Internals ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines various helper methods and classes used by
-// LLVMContextImpl for creating and managing types.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TYPESCONTEXT_H
-#define LLVM_TYPESCONTEXT_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include <map>
-
-
-//===----------------------------------------------------------------------===//
-// Derived Type Factory Functions
-//===----------------------------------------------------------------------===//
-namespace llvm {
-
-/// getSubElementHash - Generate a hash value for all of the SubType's of this
-/// type. The hash value is guaranteed to be zero if any of the subtypes are
-/// an opaque type. Otherwise we try to mix them in as well as possible, but do
-/// not look at the subtype's subtype's.
-static unsigned getSubElementHash(const Type *Ty) {
- unsigned HashVal = 0;
- for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
- I != E; ++I) {
- HashVal *= 32;
- const Type *SubTy = I->get();
- HashVal += SubTy->getTypeID();
- switch (SubTy->getTypeID()) {
- default: break;
- case Type::OpaqueTyID: return 0; // Opaque -> hash = 0 no matter what.
- case Type::IntegerTyID:
- HashVal ^= (cast<IntegerType>(SubTy)->getBitWidth() << 3);
- break;
- case Type::FunctionTyID:
- HashVal ^= cast<FunctionType>(SubTy)->getNumParams()*2 +
- cast<FunctionType>(SubTy)->isVarArg();
- break;
- case Type::ArrayTyID:
- HashVal ^= cast<ArrayType>(SubTy)->getNumElements();
- break;
- case Type::VectorTyID:
- HashVal ^= cast<VectorType>(SubTy)->getNumElements();
- break;
- case Type::StructTyID:
- HashVal ^= cast<StructType>(SubTy)->getNumElements();
- break;
- case Type::PointerTyID:
- HashVal ^= cast<PointerType>(SubTy)->getAddressSpace();
- break;
- }
- }
- return HashVal ? HashVal : 1; // Do not return zero unless opaque subty.
-}
-
-//===----------------------------------------------------------------------===//
-// Integer Type Factory...
-//
-class IntegerValType {
- uint32_t bits;
-public:
- IntegerValType(uint32_t numbits) : bits(numbits) {}
-
- static IntegerValType get(const IntegerType *Ty) {
- return IntegerValType(Ty->getBitWidth());
- }
-
- static unsigned hashTypeStructure(const IntegerType *Ty) {
- return (unsigned)Ty->getBitWidth();
- }
-
- inline bool operator<(const IntegerValType &IVT) const {
- return bits < IVT.bits;
- }
-};
-
-// PointerValType - Define a class to hold the key that goes into the TypeMap
-//
-class PointerValType {
- const Type *ValTy;
- unsigned AddressSpace;
-public:
- PointerValType(const Type *val, unsigned as) : ValTy(val), AddressSpace(as) {}
-
- static PointerValType get(const PointerType *PT) {
- return PointerValType(PT->getElementType(), PT->getAddressSpace());
- }
-
- static unsigned hashTypeStructure(const PointerType *PT) {
- return getSubElementHash(PT);
- }
-
- bool operator<(const PointerValType &MTV) const {
- if (AddressSpace < MTV.AddressSpace) return true;
- return AddressSpace == MTV.AddressSpace && ValTy < MTV.ValTy;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// Array Type Factory...
-//
-class ArrayValType {
- const Type *ValTy;
- uint64_t Size;
-public:
- ArrayValType(const Type *val, uint64_t sz) : ValTy(val), Size(sz) {}
-
- static ArrayValType get(const ArrayType *AT) {
- return ArrayValType(AT->getElementType(), AT->getNumElements());
- }
-
- static unsigned hashTypeStructure(const ArrayType *AT) {
- return (unsigned)AT->getNumElements();
- }
-
- inline bool operator<(const ArrayValType &MTV) const {
- if (Size < MTV.Size) return true;
- return Size == MTV.Size && ValTy < MTV.ValTy;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// Vector Type Factory...
-//
-class VectorValType {
- const Type *ValTy;
- unsigned Size;
-public:
- VectorValType(const Type *val, int sz) : ValTy(val), Size(sz) {}
-
- static VectorValType get(const VectorType *PT) {
- return VectorValType(PT->getElementType(), PT->getNumElements());
- }
-
- static unsigned hashTypeStructure(const VectorType *PT) {
- return PT->getNumElements();
- }
-
- inline bool operator<(const VectorValType &MTV) const {
- if (Size < MTV.Size) return true;
- return Size == MTV.Size && ValTy < MTV.ValTy;
- }
-};
-
-// StructValType - Define a class to hold the key that goes into the TypeMap
-//
-class StructValType {
- std::vector<const Type*> ElTypes;
- bool packed;
-public:
- StructValType(ArrayRef<const Type*> args, bool isPacked)
- : ElTypes(args.vec()), packed(isPacked) {}
-
- static StructValType get(const StructType *ST) {
- std::vector<const Type *> ElTypes;
- ElTypes.reserve(ST->getNumElements());
- for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
- ElTypes.push_back(ST->getElementType(i));
-
- return StructValType(ElTypes, ST->isPacked());
- }
-
- static unsigned hashTypeStructure(const StructType *ST) {
- return ST->getNumElements();
- }
-
- inline bool operator<(const StructValType &STV) const {
- if (ElTypes < STV.ElTypes) return true;
- else if (ElTypes > STV.ElTypes) return false;
- else return (int)packed < (int)STV.packed;
- }
-};
-
-// FunctionValType - Define a class to hold the key that goes into the TypeMap
-//
-class FunctionValType {
- const Type *RetTy;
- std::vector<const Type*> ArgTypes;
- bool isVarArg;
-public:
- FunctionValType(const Type *ret, ArrayRef<const Type*> args, bool isVA)
- : RetTy(ret), ArgTypes(args.vec()), isVarArg(isVA) {}
-
- static FunctionValType get(const FunctionType *FT);
-
- static unsigned hashTypeStructure(const FunctionType *FT) {
- unsigned Result = FT->getNumParams()*2 + FT->isVarArg();
- return Result;
- }
-
- inline bool operator<(const FunctionValType &MTV) const {
- if (RetTy < MTV.RetTy) return true;
- if (RetTy > MTV.RetTy) return false;
- if (isVarArg < MTV.isVarArg) return true;
- if (isVarArg > MTV.isVarArg) return false;
- if (ArgTypes < MTV.ArgTypes) return true;
- if (ArgTypes > MTV.ArgTypes) return false;
- return false;
- }
-};
-
-class TypeMapBase {
-protected:
- /// TypesByHash - Keep track of types by their structure hash value. Note
- /// that we only keep track of types that have cycles through themselves in
- /// this map.
- ///
- std::multimap<unsigned, PATypeHolder> TypesByHash;
-
- ~TypeMapBase() {
- // PATypeHolder won't destroy non-abstract types.
- // We can't destroy them by simply iterating, because
- // they may contain references to each-other.
- for (std::multimap<unsigned, PATypeHolder>::iterator I
- = TypesByHash.begin(), E = TypesByHash.end(); I != E; ++I) {
- Type *Ty = const_cast<Type*>(I->second.Ty);
- I->second.destroy();
- // We can't invoke destroy or delete, because the type may
- // contain references to already freed types.
- // So we have to destruct the object the ugly way.
- if (Ty) {
- Ty->AbstractTypeUsers.clear();
- static_cast<const Type*>(Ty)->Type::~Type();
- operator delete(Ty);
- }
- }
- }
-
-public:
- void RemoveFromTypesByHash(unsigned Hash, const Type *Ty) {
- std::multimap<unsigned, PATypeHolder>::iterator I =
- TypesByHash.lower_bound(Hash);
- for (; I != TypesByHash.end() && I->first == Hash; ++I) {
- if (I->second == Ty) {
- TypesByHash.erase(I);
- return;
- }
- }
-
- // This must be do to an opaque type that was resolved. Switch down to hash
- // code of zero.
- assert(Hash && "Didn't find type entry!");
- RemoveFromTypesByHash(0, Ty);
- }
-
- /// TypeBecameConcrete - When Ty gets a notification that TheType just became
- /// concrete, drop uses and make Ty non-abstract if we should.
- void TypeBecameConcrete(DerivedType *Ty, const DerivedType *TheType) {
- // If the element just became concrete, remove 'ty' from the abstract
- // type user list for the type. Do this for as many times as Ty uses
- // OldType.
- for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
- I != E; ++I)
- if (I->get() == TheType)
- TheType->removeAbstractTypeUser(Ty);
-
- // If the type is currently thought to be abstract, rescan all of our
- // subtypes to see if the type has just become concrete! Note that this
- // may send out notifications to AbstractTypeUsers that types become
- // concrete.
- if (Ty->isAbstract())
- Ty->PromoteAbstractToConcrete();
- }
-};
-
-// 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.
-//
-template<class ValType, class TypeClass>
-class TypeMap : public TypeMapBase {
- std::map<ValType, PATypeHolder> Map;
-public:
- typedef typename std::map<ValType, PATypeHolder>::iterator iterator;
-
- inline TypeClass *get(const ValType &V) {
- iterator I = Map.find(V);
- return I != Map.end() ? cast<TypeClass>((Type*)I->second.get()) : 0;
- }
-
- 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");
- }
-
- /// RefineAbstractType - This method is called after we have merged a type
- /// with another one. We must now either merge the type away with
- /// some other type or reinstall it in the map with it's new configuration.
- void RefineAbstractType(TypeClass *Ty, const DerivedType *OldType,
- const Type *NewType) {
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "RefineAbstractType(" << (void*)OldType << "[" << *OldType
- << "], " << (void*)NewType << " [" << *NewType << "])\n");
-#endif
-
- // Otherwise, we are changing one subelement type into another. Clearly the
- // OldType must have been abstract, making us abstract.
- assert(Ty->isAbstract() && "Refining a non-abstract type!");
- assert(OldType != NewType);
-
- // 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 = Ty;
-
- // The old record is now out-of-date, because one of the children has been
- // updated. Remove the obsolete entry from the map.
- unsigned NumErased = Map.erase(ValType::get(Ty));
- assert(NumErased && "Element not found!"); (void)NumErased;
-
- // Remember the structural hash for the type before we start hacking on it,
- // in case we need it later.
- unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
-
- // Find the type element we are refining... and change it now!
- for (unsigned i = 0, e = Ty->getNumContainedTypes(); i != e; ++i)
- if (Ty->ContainedTys[i] == OldType)
- Ty->ContainedTys[i] = NewType;
- unsigned NewTypeHash = 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 (!TypeHasCycleThroughItself(Ty)) {
- typename std::map<ValType, PATypeHolder>::iterator I;
- bool Inserted;
-
- tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
- if (!Inserted) {
- // Refined to a different type altogether?
- RemoveFromTypesByHash(OldTypeHash, Ty);
-
- // We already have this type in the table. Get rid of the newly refined
- // type.
- TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
- Ty->refineAbstractTypeTo(NewTy);
- return;
- }
- } else {
- // Now we check to see if there is an existing entry in the table which is
- // structurally identical to the newly refined type. If so, this type
- // gets refined to the pre-existing type.
- //
- std::multimap<unsigned, PATypeHolder>::iterator I, E, Entry;
- tie(I, E) = TypesByHash.equal_range(NewTypeHash);
- Entry = E;
- for (; I != E; ++I) {
- if (I->second == Ty) {
- // Remember the position of the old type if we see it in our scan.
- Entry = I;
- continue;
- }
-
- if (!TypesEqual(Ty, I->second))
- continue;
-
- TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
-
- // Remove the old entry form TypesByHash. If the hash values differ
- // now, remove it from the old place. Otherwise, continue scanning
- // within this hashcode to reduce work.
- if (NewTypeHash != OldTypeHash) {
- RemoveFromTypesByHash(OldTypeHash, Ty);
- } else {
- if (Entry == E) {
- // Find the location of Ty in the TypesByHash structure if we
- // haven't seen it already.
- while (I->second != Ty) {
- ++I;
- assert(I != E && "Structure doesn't contain type??");
- }
- Entry = I;
- }
- TypesByHash.erase(Entry);
- }
- Ty->refineAbstractTypeTo(NewTy);
- return;
- }
-
- // If there is no existing type of the same structure, we reinsert an
- // updated record into the map.
- Map.insert(std::make_pair(ValType::get(Ty), Ty));
- }
-
- // If the hash codes differ, update TypesByHash
- if (NewTypeHash != OldTypeHash) {
- RemoveFromTypesByHash(OldTypeHash, Ty);
- TypesByHash.insert(std::make_pair(NewTypeHash, Ty));
- }
-
- // If the type is currently thought to be abstract, rescan all of our
- // subtypes to see if the type has just become concrete! Note that this
- // may send out notifications to AbstractTypeUsers that types become
- // concrete.
- if (Ty->isAbstract())
- Ty->PromoteAbstractToConcrete();
- }
-
- void print(const char *Arg) const {
-#ifdef DEBUG_MERGE_TYPES
- DEBUG(dbgs() << "TypeMap<>::" << Arg << " table contents:\n");
- unsigned i = 0;
- for (typename std::map<ValType, PATypeHolder>::const_iterator I
- = Map.begin(), E = Map.end(); I != E; ++I)
- DEBUG(dbgs() << " " << (++i) << ". " << (void*)I->second.get() << " "
- << *I->second.get() << "\n");
-#endif
- }
-
- void dump() const { print("dump output"); }
-};
-}
-
-#endif
diff --git a/lib/VMCore/Use.cpp b/lib/VMCore/Use.cpp
index 2258b8d..359a151 100644
--- a/lib/VMCore/Use.cpp
+++ b/lib/VMCore/Use.cpp
@@ -135,11 +135,9 @@ void Use::zap(Use *Start, const Use *Stop, bool del) {
User *Use::getUser() const {
const Use *End = getImpliedUser();
- const PointerIntPair<User*, 1, unsigned>&
- ref(static_cast<const AugmentedUse*>(End - 1)->ref);
- User *She = ref.getPointer();
- return ref.getInt()
- ? She
+ const UserRef *ref = reinterpret_cast<const UserRef*>(End);
+ return ref->getInt()
+ ? ref->getPointer()
: (User*)End;
}
diff --git a/lib/VMCore/User.cpp b/lib/VMCore/User.cpp
index 2f4587d..f01fa34 100644
--- a/lib/VMCore/User.cpp
+++ b/lib/VMCore/User.cpp
@@ -40,14 +40,12 @@ void User::replaceUsesOfWith(Value *From, Value *To) {
//===----------------------------------------------------------------------===//
Use *User::allocHungoffUses(unsigned N) const {
- Use *Begin = static_cast<Use*>(::operator new(sizeof(Use) * N
- + sizeof(AugmentedUse)
- - sizeof(Use)));
+ // Allocate the array of Uses, followed by a pointer (with bottom bit set) to
+ // the User.
+ size_t size = N * sizeof(Use) + sizeof(Use::UserRef);
+ Use *Begin = static_cast<Use*>(::operator new(size));
Use *End = Begin + N;
- PointerIntPair<User*, 1, unsigned>&
- ref(static_cast<AugmentedUse&>(End[-1]).ref);
- ref.setPointer(const_cast<User*>(this));
- ref.setInt(1);
+ (void) new(End) Use::UserRef(const_cast<User*>(this), 1);
return Use::initTags(Begin, End);
}
diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp
index 29f6a80..f1815e3 100644
--- a/lib/VMCore/Value.cpp
+++ b/lib/VMCore/Value.cpp
@@ -35,22 +35,21 @@ using namespace llvm;
// Value Class
//===----------------------------------------------------------------------===//
-static inline const Type *checkType(const Type *Ty) {
+static inline Type *checkType(const Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
- return Ty;
+ return const_cast<Type*>(Ty);
}
Value::Value(const Type *ty, unsigned scid)
: SubclassID(scid), HasValueHandle(0),
- SubclassOptionalData(0), SubclassData(0), VTy(checkType(ty)),
+ SubclassOptionalData(0), SubclassData(0), VTy((Type*)checkType(ty)),
UseList(0), Name(0) {
+ // FIXME: Why isn't this in the subclass gunk??
if (isa<CallInst>(this) || isa<InvokeInst>(this))
- assert((VTy->isFirstClassType() || VTy->isVoidTy() ||
- ty->isOpaqueTy() || VTy->isStructTy()) &&
- "invalid CallInst type!");
+ assert((VTy->isFirstClassType() || VTy->isVoidTy() || VTy->isStructTy()) &&
+ "invalid CallInst type!");
else if (!isa<Constant>(this) && !isa<BasicBlock>(this))
- assert((VTy->isFirstClassType() || VTy->isVoidTy() ||
- ty->isOpaqueTy()) &&
+ assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
"Cannot create non-first-class values except for constants!");
}
@@ -281,17 +280,16 @@ void Value::takeName(Value *V) {
}
-// uncheckedReplaceAllUsesWith - This is exactly the same as replaceAllUsesWith,
-// except that it doesn't have all of the asserts. The asserts fail because we
-// are half-way done resolving types, which causes some types to exist as two
-// different Type*'s at the same time. This is a sledgehammer to work around
-// this problem.
-//
-void Value::uncheckedReplaceAllUsesWith(Value *New) {
+void Value::replaceAllUsesWith(Value *New) {
+ assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
+ assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!");
+ assert(New->getType() == getType() &&
+ "replaceAllUses of value with new value of different type!");
+
// Notify all ValueHandles (if present) that this value is going away.
if (HasValueHandle)
ValueHandleBase::ValueIsRAUWd(this, New);
-
+
while (!use_empty()) {
Use &U = *UseList;
// Must handle Constants specially, we cannot call replaceUsesOfWith on a
@@ -302,18 +300,12 @@ void Value::uncheckedReplaceAllUsesWith(Value *New) {
continue;
}
}
-
+
U.set(New);
}
-}
-
-void Value::replaceAllUsesWith(Value *New) {
- assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
- assert(New != this && "this->replaceAllUsesWith(this) is NOT valid!");
- assert(New->getType() == getType() &&
- "replaceAllUses of value with new value of different type!");
-
- uncheckedReplaceAllUsesWith(New);
+
+ if (BasicBlock *BB = dyn_cast<BasicBlock>(this))
+ BB->replaceSuccessorsPhiUsesWith(cast<BasicBlock>(New));
}
Value *Value::stripPointerCasts() {
diff --git a/lib/VMCore/ValueSymbolTable.cpp b/lib/VMCore/ValueSymbolTable.cpp
index 254bf06..f1c9703 100644
--- a/lib/VMCore/ValueSymbolTable.cpp
+++ b/lib/VMCore/ValueSymbolTable.cpp
@@ -25,7 +25,7 @@ ValueSymbolTable::~ValueSymbolTable() {
#ifndef NDEBUG // Only do this in -g mode...
for (iterator VI = vmap.begin(), VE = vmap.end(); VI != VE; ++VI)
dbgs() << "Value still in symbol table! Type = '"
- << VI->getValue()->getType()->getDescription() << "' Name = '"
+ << *VI->getValue()->getType() << "' Name = '"
<< VI->getKeyData() << "'\n";
assert(vmap.empty() && "Values remain in symbol table!");
#endif
diff --git a/lib/VMCore/ValueTypes.cpp b/lib/VMCore/ValueTypes.cpp
index c054ae4..21a1f03 100644
--- a/lib/VMCore/ValueTypes.cpp
+++ b/lib/VMCore/ValueTypes.cpp
@@ -133,6 +133,7 @@ std::string EVT::getEVTString() const {
case MVT::v2f64: return "v2f64";
case MVT::v4f64: return "v4f64";
case MVT::Metadata:return "Metadata";
+ case MVT::untyped: return "untyped";
}
}
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 139e035..b146b89 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -49,7 +49,6 @@
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/ValueTypes.h"
@@ -109,54 +108,6 @@ INITIALIZE_PASS(PreVerifier, "preverify", "Preliminary module verification",
static char &PreVerifyID = PreVerifier::ID;
namespace {
- class TypeSet : public AbstractTypeUser {
- public:
- TypeSet() {}
-
- /// Insert a type into the set of types.
- bool insert(const Type *Ty) {
- if (!Types.insert(Ty))
- return false;
- if (Ty->isAbstract())
- Ty->addAbstractTypeUser(this);
- return true;
- }
-
- // Remove ourselves as abstract type listeners for any types that remain
- // abstract when the TypeSet is destroyed.
- ~TypeSet() {
- for (SmallSetVector<const Type *, 16>::iterator I = Types.begin(),
- E = Types.end(); I != E; ++I) {
- const Type *Ty = *I;
- if (Ty->isAbstract())
- Ty->removeAbstractTypeUser(this);
- }
- }
-
- // Abstract type user interface.
-
- /// Remove types from the set when refined. Do not insert the type it was
- /// refined to because that type hasn't been verified yet.
- void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
- Types.remove(OldTy);
- OldTy->removeAbstractTypeUser(this);
- }
-
- /// Stop listening for changes to a type which is no longer abstract.
- void typeBecameConcrete(const DerivedType *AbsTy) {
- AbsTy->removeAbstractTypeUser(this);
- }
-
- void dump() const {}
-
- private:
- SmallSetVector<const Type *, 16> Types;
-
- // Disallow copying.
- TypeSet(const TypeSet &);
- TypeSet &operator=(const TypeSet &);
- };
-
struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
static char ID; // Pass ID, replacement for typeid
bool Broken; // Is this module found to be broken?
@@ -176,9 +127,6 @@ namespace {
/// an instruction in the same block.
SmallPtrSet<Instruction*, 16> InstsInThisBlock;
- /// Types - keep track of the types that have been checked already.
- TypeSet Types;
-
/// MDNodes - keep track of the metadata nodes that have been checked
/// already.
SmallPtrSet<MDNode *, 32> MDNodes;
@@ -199,7 +147,6 @@ namespace {
bool doInitialization(Module &M) {
Mod = &M;
Context = &M.getContext();
- verifyTypeSymbolTable(M.getTypeSymbolTable());
// If this is a real pass, in a pass manager, we must abort before
// returning back to the pass manager, or else the pass manager may try to
@@ -285,7 +232,6 @@ namespace {
// Verification methods...
- void verifyTypeSymbolTable(TypeSymbolTable &ST);
void visitGlobalValue(GlobalValue &GV);
void visitGlobalVariable(GlobalVariable &GV);
void visitGlobalAlias(GlobalAlias &GA);
@@ -345,7 +291,6 @@ namespace {
bool isReturnValue, const Value *V);
void VerifyFunctionAttrs(const FunctionType *FT, const AttrListPtr &Attrs,
const Value *V);
- void VerifyType(const Type *Ty);
void WriteValue(const Value *V) {
if (!V) return;
@@ -359,8 +304,7 @@ namespace {
void WriteType(const Type *T) {
if (!T) return;
- MessagesStr << ' ';
- WriteTypeSymbolic(MessagesStr, T, Mod);
+ MessagesStr << ' ' << *T;
}
@@ -568,11 +512,6 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
}
}
-void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) {
- for (TypeSymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
- VerifyType(I->second);
-}
-
// VerifyParameterAttrs - Check the given attributes for an argument or return
// value of the specified type. The value V is printed in error messages.
void Verifier::VerifyParameterAttrs(Attributes Attrs, const Type *Ty,
@@ -1139,9 +1078,6 @@ void Verifier::visitPHINode(PHINode &PN) {
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
Assert1(PN.getType() == PN.getIncomingValue(i)->getType(),
"PHI node operands are not the same type as the result!", &PN);
- Assert1(isa<BasicBlock>(PN.getOperand(
- PHINode::getOperandNumForIncomingBlock(i))),
- "PHI node incoming block is not a BasicBlock!", &PN);
}
// All other PHI node constraints are checked in the visitBasicBlock method.
@@ -1195,11 +1131,11 @@ void Verifier::VerifyCallSite(CallSite CS) {
}
// Verify that there's no metadata unless it's a direct call to an intrinsic.
- if (!CS.getCalledFunction() ||
+ if (CS.getCalledFunction() == 0 ||
!CS.getCalledFunction()->getName().startswith("llvm.")) {
for (FunctionType::param_iterator PI = FTy->param_begin(),
PE = FTy->param_end(); PI != PE; ++PI)
- Assert1(!PI->get()->isMetadataTy(),
+ Assert1(!(*PI)->isMetadataTy(),
"Function has metadata parameter but isn't an intrinsic", I);
}
@@ -1382,7 +1318,7 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
void Verifier::visitExtractValueInst(ExtractValueInst &EVI) {
Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),
- EVI.idx_begin(), EVI.idx_end()) ==
+ EVI.getIndices()) ==
EVI.getType(),
"Invalid ExtractValueInst operands!", &EVI);
@@ -1391,7 +1327,7 @@ void Verifier::visitExtractValueInst(ExtractValueInst &EVI) {
void Verifier::visitInsertValueInst(InsertValueInst &IVI) {
Assert1(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(),
- IVI.idx_begin(), IVI.idx_end()) ==
+ IVI.getIndices()) ==
IVI.getOperand(1)->getType(),
"Invalid InsertValueInst operands!", &IVI);
@@ -1482,8 +1418,10 @@ void Verifier::visitInstruction(Instruction &I) {
// PHI nodes differ from other nodes because they actually "use" the
// value in the predecessor basic blocks they correspond to.
BasicBlock *UseBlock = BB;
- if (isa<PHINode>(I))
- UseBlock = dyn_cast<BasicBlock>(I.getOperand(i+1));
+ if (PHINode *PN = dyn_cast<PHINode>(&I)) {
+ unsigned j = PHINode::getIncomingValueNumForOperand(i);
+ UseBlock = PN->getIncomingBlock(j);
+ }
Assert2(UseBlock, "Invoke operand is PHI node with bad incoming-BB",
Op, &I);
@@ -1515,10 +1453,11 @@ void Verifier::visitInstruction(Instruction &I) {
return;
}
}
- } else if (isa<PHINode>(I)) {
+ } else if (PHINode *PN = dyn_cast<PHINode>(&I)) {
// PHI nodes are more difficult than other nodes because they actually
// "use" the value in the predecessor basic blocks they correspond to.
- BasicBlock *PredBB = dyn_cast<BasicBlock>(I.getOperand(i+1));
+ unsigned j = PHINode::getIncomingValueNumForOperand(i);
+ BasicBlock *PredBB = PN->getIncomingBlock(j);
Assert2(PredBB && (DT->dominates(OpBlock, PredBB) ||
!DT->isReachableFromEntry(PredBB)),
"Instruction does not dominate all uses!", Op, &I);
@@ -1542,69 +1481,6 @@ void Verifier::visitInstruction(Instruction &I) {
}
}
InstsInThisBlock.insert(&I);
-
- VerifyType(I.getType());
-}
-
-/// VerifyType - Verify that a type is well formed.
-///
-void Verifier::VerifyType(const Type *Ty) {
- if (!Types.insert(Ty)) return;
-
- Assert1(Context == &Ty->getContext(),
- "Type context does not match Module context!", Ty);
-
- switch (Ty->getTypeID()) {
- case Type::FunctionTyID: {
- const FunctionType *FTy = cast<FunctionType>(Ty);
-
- const Type *RetTy = FTy->getReturnType();
- Assert2(FunctionType::isValidReturnType(RetTy),
- "Function type with invalid return type", RetTy, FTy);
- VerifyType(RetTy);
-
- for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
- const Type *ElTy = FTy->getParamType(i);
- Assert2(FunctionType::isValidArgumentType(ElTy),
- "Function type with invalid parameter type", ElTy, FTy);
- VerifyType(ElTy);
- }
- break;
- }
- case Type::StructTyID: {
- const StructType *STy = cast<StructType>(Ty);
- for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
- const Type *ElTy = STy->getElementType(i);
- Assert2(StructType::isValidElementType(ElTy),
- "Structure type with invalid element type", ElTy, STy);
- VerifyType(ElTy);
- }
- break;
- }
- case Type::ArrayTyID: {
- const ArrayType *ATy = cast<ArrayType>(Ty);
- Assert1(ArrayType::isValidElementType(ATy->getElementType()),
- "Array type with invalid element type", ATy);
- VerifyType(ATy->getElementType());
- break;
- }
- case Type::PointerTyID: {
- const PointerType *PTy = cast<PointerType>(Ty);
- Assert1(PointerType::isValidElementType(PTy->getElementType()),
- "Pointer type with invalid element type", PTy);
- VerifyType(PTy->getElementType());
- break;
- }
- case Type::VectorTyID: {
- const VectorType *VTy = cast<VectorType>(Ty);
- Assert1(VectorType::isValidElementType(VTy->getElementType()),
- "Vector type with invalid element type", VTy);
- VerifyType(VTy->getElementType());
- break;
- }
- default:
- break;
- }
}
// Flags used by TableGen to mark intrinsic parameters with the
OpenPOWER on IntegriCloud