summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AsmParser/LLLexer.h4
-rw-r--r--lib/AsmParser/LLParser.cpp575
-rw-r--r--lib/AsmParser/LLParser.h87
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp390
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h10
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp113
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp114
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.h3
-rw-r--r--lib/CodeGen/ShadowStackGC.cpp49
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp1
-rw-r--r--lib/Linker/LinkModules.cpp1816
-rw-r--r--lib/Target/CBackend/CBackend.cpp217
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp88
-rw-r--r--lib/Target/TargetData.cpp51
-rw-r--r--lib/Transforms/IPO/CMakeLists.txt1
-rw-r--r--lib/Transforms/IPO/DeadTypeElimination.cpp112
-rw-r--r--lib/Transforms/IPO/IPO.cpp5
-rw-r--r--lib/Transforms/IPO/MergeFunctions.cpp1
-rw-r--r--lib/Transforms/IPO/StripSymbols.cpp24
-rw-r--r--lib/Transforms/Utils/CloneModule.cpp24
-rw-r--r--lib/Transforms/Utils/LowerInvoke.cpp22
-rw-r--r--lib/Transforms/Utils/ValueMapper.cpp107
-rw-r--r--lib/VMCore/AsmWriter.cpp441
-rw-r--r--lib/VMCore/CMakeLists.txt1
-rw-r--r--lib/VMCore/ConstantFold.cpp2
-rw-r--r--lib/VMCore/Constants.cpp56
-rw-r--r--lib/VMCore/ConstantsContext.h142
-rw-r--r--lib/VMCore/Core.cpp49
-rw-r--r--lib/VMCore/Function.cpp6
-rw-r--r--lib/VMCore/Globals.cpp1
-rw-r--r--lib/VMCore/InlineAsm.cpp2
-rw-r--r--lib/VMCore/Instructions.cpp66
-rw-r--r--lib/VMCore/LLVMContextImpl.cpp18
-rw-r--r--lib/VMCore/LLVMContextImpl.h47
-rw-r--r--lib/VMCore/Metadata.cpp1
-rw-r--r--lib/VMCore/Module.cpp178
-rw-r--r--lib/VMCore/Type.cpp1205
-rw-r--r--lib/VMCore/TypeSymbolTable.cpp168
-rw-r--r--lib/VMCore/TypesContext.h426
-rw-r--r--lib/VMCore/Value.cpp15
-rw-r--r--lib/VMCore/Verifier.cpp130
41 files changed, 2365 insertions, 4403 deletions
diff --git a/lib/AsmParser/LLLexer.h b/lib/AsmParser/LLLexer.h
index 4fe705e1a5..33b9135723 100644
--- a/lib/AsmParser/LLLexer.h
+++ b/lib/AsmParser/LLLexer.h
@@ -38,7 +38,7 @@ namespace llvm {
lltok::Kind CurKind;
std::string StrVal;
unsigned UIntVal;
- const Type *TyVal;
+ Type *TyVal;
APFloat APFloatVal;
APSInt APSIntVal;
@@ -56,7 +56,7 @@ namespace llvm {
LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); }
lltok::Kind getKind() const { return CurKind; }
const std::string &getStrVal() const { return StrVal; }
- const Type *getTyVal() const { return TyVal; }
+ Type *getTyVal() const { return TyVal; }
unsigned getUIntVal() const { return UIntVal; }
const APSInt &getAPSIntVal() const { return APSIntVal; }
const APFloat &getAPFloatVal() const { return APFloatVal; }
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index d9858514be..881b3e943b 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -89,15 +89,16 @@ bool LLParser::ValidateEndOfModule() {
ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin());
}
-
- if (!ForwardRefTypes.empty())
- return Error(ForwardRefTypes.begin()->second.second,
- "use of undefined type named '" +
- ForwardRefTypes.begin()->first + "'");
- if (!ForwardRefTypeIDs.empty())
- return Error(ForwardRefTypeIDs.begin()->second.second,
- "use of undefined type '%" +
- Twine(ForwardRefTypeIDs.begin()->first) + "'");
+ for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i)
+ if (NumberedTypes[i].second.isValid())
+ return Error(NumberedTypes[i].second,
+ "use of undefined type '%" + Twine(i) + "'");
+
+ for (StringMap<std::pair<Type*, LocTy> >::iterator I =
+ NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I)
+ if (I->second.second.isValid())
+ return Error(I->second.second,
+ "use of undefined type named '" + I->getKey() + "'");
if (!ForwardRefVals.empty())
return Error(ForwardRefVals.begin()->second.second,
@@ -293,36 +294,32 @@ bool LLParser::ParseDepLibs() {
/// ::= LocalVarID '=' 'type' type
bool LLParser::ParseUnnamedType() {
LocTy TypeLoc = Lex.getLoc();
- unsigned TypeID = NumberedTypes.size();
- if (Lex.getUIntVal() != TypeID)
- return Error(Lex.getLoc(), "type expected to be numbered '%" +
- Twine(TypeID) + "'");
+ unsigned TypeID = Lex.getUIntVal();
Lex.Lex(); // eat LocalVarID;
if (ParseToken(lltok::equal, "expected '=' after name") ||
ParseToken(lltok::kw_type, "expected 'type' after '='"))
return true;
- PATypeHolder Ty(Type::getVoidTy(Context));
- if (ParseType(Ty)) return true;
-
- // See if this type was previously referenced.
- std::map<unsigned, std::pair<PATypeHolder, LocTy> >::iterator
- FI = ForwardRefTypeIDs.find(TypeID);
- if (FI != ForwardRefTypeIDs.end()) {
- if (FI->second.first.get() == Ty)
- return Error(TypeLoc, "self referential type is invalid");
-
- cast<DerivedType>(FI->second.first.get())->refineAbstractTypeTo(Ty);
- Ty = FI->second.first.get();
- ForwardRefTypeIDs.erase(FI);
+ if (TypeID >= NumberedTypes.size())
+ NumberedTypes.resize(TypeID+1);
+
+ Type *Result = 0;
+ if (ParseStructDefinition(TypeLoc, "",
+ NumberedTypes[TypeID], Result)) return true;
+
+ if (!isa<StructType>(Result)) {
+ std::pair<Type*, LocTy> &Entry = NumberedTypes[TypeID];
+ if (Entry.first)
+ return Error(TypeLoc, "non-struct types may not be recursive");
+ Entry.first = Result;
+ Entry.second = SMLoc();
}
- NumberedTypes.push_back(Ty);
-
return false;
}
+
/// toplevelentity
/// ::= LocalVar '=' 'type' type
bool LLParser::ParseNamedType() {
@@ -330,37 +327,23 @@ bool LLParser::ParseNamedType() {
LocTy NameLoc = Lex.getLoc();
Lex.Lex(); // eat LocalVar.
- PATypeHolder Ty(Type::getVoidTy(Context));
-
if (ParseToken(lltok::equal, "expected '=' after name") ||
- ParseToken(lltok::kw_type, "expected 'type' after name") ||
- ParseType(Ty))
+ ParseToken(lltok::kw_type, "expected 'type' after name"))
return true;
-
- // Set the type name, checking for conflicts as we do so.
- bool AlreadyExists = M->addTypeName(Name, Ty);
- if (!AlreadyExists) return false;
-
- // See if this type is a forward reference. We need to eagerly resolve
- // types to allow recursive type redefinitions below.
- std::map<std::string, std::pair<PATypeHolder, LocTy> >::iterator
- FI = ForwardRefTypes.find(Name);
- if (FI != ForwardRefTypes.end()) {
- if (FI->second.first.get() == Ty)
- return Error(NameLoc, "self referential type is invalid");
-
- cast<DerivedType>(FI->second.first.get())->refineAbstractTypeTo(Ty);
- Ty = FI->second.first.get();
- ForwardRefTypes.erase(FI);
- return false;
+
+ Type *Result = 0;
+ if (ParseStructDefinition(NameLoc, Name,
+ NamedTypes[Name], Result)) return true;
+
+ if (!isa<StructType>(Result)) {
+ std::pair<Type*, LocTy> &Entry = NamedTypes[Name];
+ if (Entry.first)
+ return Error(NameLoc, "non-struct types may not be recursive");
+ Entry.first = Result;
+ Entry.second = SMLoc();
}
-
- // Inserting a name that is already defined, get the existing name.
- assert(M->getTypeByName(Name) && "Conflict but no matching type?!");
-
- // Otherwise, this is an attempt to redefine a type, report the error.
- return Error(NameLoc, "redefinition of type named '" + Name + "' of type '" +
- getTypeString(Ty) + "'");
+
+ return false;
}
@@ -536,7 +519,7 @@ bool LLParser::ParseStandaloneMetadata() {
unsigned MetadataID = 0;
LocTy TyLoc;
- PATypeHolder Ty(Type::getVoidTy(Context));
+ Type *Ty = 0;
SmallVector<Value *, 16> Elts;
if (ParseUInt32(MetadataID) ||
ParseToken(lltok::equal, "expected '=' here") ||
@@ -668,7 +651,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
LocTy UnnamedAddrLoc;
LocTy TyLoc;
- PATypeHolder Ty(Type::getVoidTy(Context));
+ Type *Ty = 0;
if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) ||
ParseOptionalAddrSpace(AddrSpace) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
@@ -792,18 +775,11 @@ GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty,
// Otherwise, create a new forward reference for this value and remember it.
GlobalValue *FwdVal;
- if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType())) {
- // Function types can return opaque but functions can't.
- if (FT->getReturnType()->isOpaqueTy()) {
- Error(Loc, "function may not return opaque type");
- return 0;
- }
-
+ if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType()))
FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, Name, M);
- } else {
+ else
FwdVal = new GlobalVariable(*M, PTy->getElementType(), false,
GlobalValue::ExternalWeakLinkage, 0, Name);
- }
ForwardRefVals[Name] = std::make_pair(FwdVal, Loc);
return FwdVal;
@@ -837,17 +813,11 @@ GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) {
// Otherwise, create a new forward reference for this value and remember it.
GlobalValue *FwdVal;
- if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType())) {
- // Function types can return opaque but functions can't.
- if (FT->getReturnType()->isOpaqueTy()) {
- Error(Loc, "function may not return opaque type");
- return 0;
- }
+ if (const FunctionType *FT = dyn_cast<FunctionType>(PTy->getElementType()))
FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, "", M);
- } else {
+ else
FwdVal = new GlobalVariable(*M, PTy->getElementType(), false,
GlobalValue::ExternalWeakLinkage, 0, "");
- }
ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc);
return FwdVal;
@@ -1228,165 +1198,68 @@ bool LLParser::ParseIndexList(SmallVectorImpl<unsigned> &Indices,
// Type Parsing.
//===----------------------------------------------------------------------===//
-/// ParseType - Parse and resolve a full type.
-bool LLParser::ParseType(PATypeHolder &Result, bool AllowVoid) {
- LocTy TypeLoc = Lex.getLoc();
- if (ParseTypeRec(Result)) return true;
-
- // Verify no unresolved uprefs.
- if (!UpRefs.empty())
- return Error(UpRefs.back().Loc, "invalid unresolved type up reference");
-
- if (!AllowVoid && Result.get()->isVoidTy())
- return Error(TypeLoc, "void type only allowed for function results");
-
- return false;
-}
-
-/// HandleUpRefs - Every time we finish a new layer of types, this function is
-/// called. It loops through the UpRefs vector, which is a list of the
-/// currently active types. For each type, if the up-reference is contained in
-/// the newly completed type, we decrement the level count. When the level
-/// count reaches zero, the up-referenced type is the type that is passed in:
-/// thus we can complete the cycle.
-///
-PATypeHolder LLParser::HandleUpRefs(const Type *ty) {
- // If Ty isn't abstract, or if there are no up-references in it, then there is
- // nothing to resolve here.
- if (!ty->isAbstract() || UpRefs.empty()) return ty;
-
- PATypeHolder Ty(ty);
-#if 0
- dbgs() << "Type '" << *Ty
- << "' newly formed. Resolving upreferences.\n"
- << UpRefs.size() << " upreferences active!\n";
-#endif
-
- // If we find any resolvable upreferences (i.e., those whose NestingLevel goes
- // to zero), we resolve them all together before we resolve them to Ty. At
- // the end of the loop, if there is anything to resolve to Ty, it will be in
- // this variable.
- OpaqueType *TypeToResolve = 0;
-
- for (unsigned i = 0; i != UpRefs.size(); ++i) {
- // Determine if 'Ty' directly contains this up-references 'LastContainedTy'.
- bool ContainsType =
- std::find(Ty->subtype_begin(), Ty->subtype_end(),
- UpRefs[i].LastContainedTy) != Ty->subtype_end();
-
-#if 0
- dbgs() << " UR#" << i << " - TypeContains(" << *Ty << ", "
- << *UpRefs[i].LastContainedTy << ") = "
- << (ContainsType ? "true" : "false")
- << " level=" << UpRefs[i].NestingLevel << "\n";
-#endif
- if (!ContainsType)
- continue;
-
- // Decrement level of upreference
- unsigned Level = --UpRefs[i].NestingLevel;
- UpRefs[i].LastContainedTy = Ty;
-
- // If the Up-reference has a non-zero level, it shouldn't be resolved yet.
- if (Level != 0)
- continue;
-
-#if 0
- dbgs() << " * Resolving upreference for " << UpRefs[i].UpRefTy << "\n";
-#endif
- if (!TypeToResolve)
- TypeToResolve = UpRefs[i].UpRefTy;
- else
- UpRefs[i].UpRefTy->refineAbstractTypeTo(TypeToResolve);
- UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list.
- --i; // Do not skip the next element.
- }
-
- if (TypeToResolve)
- TypeToResolve->refineAbstractTypeTo(Ty);
-
- return Ty;
-}
-
-
-/// ParseTypeRec - The recursive function used to process the internal
-/// implementation details of types.
-bool LLParser::ParseTypeRec(PATypeHolder &Result) {
+/// ParseType - Parse a type.
+bool LLParser::ParseType(Type *&Result, bool AllowVoid) {
+ SMLoc TypeLoc = Lex.getLoc();
switch (Lex.getKind()) {
default:
return TokError("expected type");
case lltok::Type:
- // TypeRec ::= 'float' | 'void' (etc)
+ // Type ::= 'float' | 'void' (etc)
Result = Lex.getTyVal();
Lex.Lex();
break;
- case lltok::kw_opaque:
- // TypeRec ::= 'opaque'
- Result = OpaqueType::get(Context);
- Lex.Lex();
- break;
case lltok::lbrace:
- // TypeRec ::= '{' ... '}'
- if (ParseStructType(Result, false))
+ // Type ::= StructType
+ if (ParseAnonStructType(Result, false))
return true;
break;
case lltok::lsquare:
- // TypeRec ::= '[' ... ']'
+ // Type ::= '[' ... ']'
Lex.Lex(); // eat the lsquare.
if (ParseArrayVectorType(Result, false))
return true;
break;
case lltok::less: // Either vector or packed struct.
- // TypeRec ::= '<' ... '>'
+ // Type ::= '<' ... '>'
Lex.Lex();
if (Lex.getKind() == lltok::lbrace) {
- if (ParseStructType(Result, true) ||
+ if (ParseAnonStructType(Result, true) ||
ParseToken(lltok::greater, "expected '>' at end of packed struct"))
return true;
} else if (ParseArrayVectorType(Result, true))
return true;
break;
- case lltok::LocalVar:
- // TypeRec ::= %foo
- if (const Type *T = M->getTypeByName(Lex.getStrVal())) {
- Result = T;
- } else {
- Result = OpaqueType::get(Context);
- ForwardRefTypes.insert(std::make_pair(Lex.getStrVal(),
- std::make_pair(Result,
- Lex.getLoc())));
- M->addTypeName(Lex.getStrVal(), Result.get());
+ case lltok::LocalVar: {
+ // Type ::= %foo
+ std::pair<Type*, LocTy> &Entry = NamedTypes[Lex.getStrVal()];
+
+ // If the type hasn't been defined yet, create a forward definition and
+ // remember where that forward def'n was seen (in case it never is defined).
+ if (Entry.first == 0) {
+ Entry.first = StructType::createNamed(Context, Lex.getStrVal());
+ Entry.second = Lex.getLoc();
}
+ Result = Entry.first;
Lex.Lex();
break;
+ }
- case lltok::LocalVarID:
- // TypeRec ::= %4
- if (Lex.getUIntVal() < NumberedTypes.size())
- Result = NumberedTypes[Lex.getUIntVal()];
- else {
- std::map<unsigned, std::pair<PATypeHolder, LocTy> >::iterator
- I = ForwardRefTypeIDs.find(Lex.getUIntVal());
- if (I != ForwardRefTypeIDs.end())
- Result = I->second.first;
- else {
- Result = OpaqueType::get(Context);
- ForwardRefTypeIDs.insert(std::make_pair(Lex.getUIntVal(),
- std::make_pair(Result,
- Lex.getLoc())));
- }
+ case lltok::LocalVarID: {
+ // Type ::= %4
+ if (Lex.getUIntVal() >= NumberedTypes.size())
+ NumberedTypes.resize(Lex.getUIntVal()+1);
+ std::pair<Type*, LocTy> &Entry = NumberedTypes[Lex.getUIntVal()];
+
+ // If the type hasn't been defined yet, create a forward definition and
+ // remember where that forward def'n was seen (in case it never is defined).
+ if (Entry.first == 0) {
+ Entry.first = StructType::createNamed(Context, "");
+ Entry.second = Lex.getLoc();
}
+ Result = Entry.first;
Lex.Lex();
break;
- case lltok::backslash: {
- // TypeRec ::= '\' 4
- Lex.Lex();
- unsigned Val;
- if (ParseUInt32(Val)) return true;
- OpaqueType *OT = OpaqueType::get(Context); //Use temporary placeholder.
- UpRefs.push_back(UpRefRecord(Lex.getLoc(), Val, OT));
- Result = OT;
- break;
}
}
@@ -1394,34 +1267,37 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) {
while (1) {
switch (Lex.getKind()) {
// End of type.
- default: return false;
+ default:
+ if (!AllowVoid && Result->isVoidTy())
+ return Error(TypeLoc, "void type only allowed for function results");
+ return false;
- // TypeRec ::= TypeRec '*'
+ // Type ::= Type '*'
case lltok::star:
- if (Result.get()->isLabelTy())
+ if (Result->isLabelTy())
return TokError("basic block pointers are invalid");
- if (Result.get()->isVoidTy())
- return TokError("pointers to void are invalid; use i8* instead");
- if (!PointerType::isValidElementType(Result.get()))
+ if (Result->isVoidTy())
+ return TokError("pointers to void are invalid - use i8* instead");
+ if (!PointerType::isValidElementType(Result))
return TokError("pointer to this type is invalid");
- Result = HandleUpRefs(PointerType::getUnqual(Result.get()));
+ Result = PointerType::getUnqual(Result);
Lex.Lex();
break;
- // TypeRec ::= TypeRec 'addrspace' '(' uint32 ')' '*'
+ // Type ::= Type 'addrspace' '(' uint32 ')' '*'
case lltok::kw_addrspace: {
- if (Result.get()->isLabelTy())
+ if (Result->isLabelTy())
return TokError("basic block pointers are invalid");
- if (Result.get()->isVoidTy())
+ if (Result->isVoidTy())
return TokError("pointers to void are invalid; use i8* instead");
- if (!PointerType::isValidElementType(Result.get()))
+ if (!PointerType::isValidElementType(Result))
return TokError("pointer to this type is invalid");
unsigned AddrSpace;
if (ParseOptionalAddrSpace(AddrSpace) ||
ParseToken(lltok::star, "expected '*' in address space"))
return true;
- Result = HandleUpRefs(PointerType::get(Result.get(), AddrSpace));
+ Result = PointerType::get(Result, AddrSpace);
break;
}
@@ -1452,7 +1328,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
// Parse the argument.
LocTy ArgLoc;
- PATypeHolder ArgTy(Type::getVoidTy(Context));
+ Type *ArgTy = 0;
unsigned ArgAttrs1 = Attribute::None;
unsigned ArgAttrs2 = Attribute::None;
Value *V;
@@ -1472,7 +1348,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
/// ParseArgumentList - Parse the argument list for a function type or function
-/// prototype. If 'inType' is true then we are parsing a FunctionType.
+/// prototype.
/// ::= '(' ArgTypeListI ')'
/// ArgTypeListI
/// ::= /*empty*/
@@ -1480,8 +1356,8 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
/// ::= ArgTypeList ',' '...'
/// ::= ArgType (',' ArgType)*
///
-bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
- bool &isVarArg, bool inType) {
+bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
+ bool &isVarArg){
isVarArg = false;
assert(Lex.getKind() == lltok::lparen);
Lex.Lex(); // eat the (.
@@ -1493,14 +1369,11 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
Lex.Lex();
} else {
LocTy TypeLoc = Lex.getLoc();
- PATypeHolder ArgTy(Type::getVoidTy(Context));
+ Type *ArgTy = 0;
unsigned Attrs;
std::string Name;
- // If we're parsing a type, use ParseTypeRec, because we allow recursive
- // types (such as a function returning a pointer to itself). If parsing a
- // function prototype, we require fully resolved types.
- if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
+ if (ParseType(ArgTy) ||
ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy->isVoidTy())
@@ -1525,8 +1398,7 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
// Otherwise must be an argument type.
TypeLoc = Lex.getLoc();
- if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) ||
- ParseOptionalAttrs(Attrs, 0)) return true;
+ if (ParseType(ArgTy) || ParseOptionalAttrs(Attrs, 0)) return true;
if (ArgTy->isVoidTy())
return Error(TypeLoc, "argument can not have void type");
@@ -1538,7 +1410,7 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
Name = "";
}
- if (!ArgTy->isFirstClassType() && !ArgTy->isOpaqueTy())
+ if (!ArgTy->isFirstClassType())
return Error(TypeLoc, "invalid type for function argument");
ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name));
@@ -1550,15 +1422,15 @@ bool LLParser::ParseArgumentList(std::vector<ArgInfo> &ArgList,
/// ParseFunctionType
/// ::= Type ArgumentList OptionalAttrs
-bool LLParser::ParseFunctionType(PATypeHolder &Result) {
+bool LLParser::ParseFunctionType(Type *&Result) {
assert(Lex.getKind() == lltok::lparen);
if (!FunctionType::isValidReturnType(Result))
return TokError("invalid function return type");
- std::vector<ArgInfo> ArgList;
+ SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
- if (ParseArgumentList(ArgList, isVarArg, true))
+ if (ParseArgumentList(ArgList, isVarArg))
return true;
// Reject names on the arguments lists.
@@ -1570,68 +1442,122 @@ bool LLParser::ParseFunctionType(PATypeHolder &Result) {
"argument attributes invalid in function type");
}
- std::vector<const Type*> ArgListTy;
+ SmallVector<const Type*, 16> ArgListTy;
for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
- ArgListTy.push_back(ArgList[i].Type);
+ ArgListTy.push_back(ArgList[i].Ty);
+
+ Result = FunctionType::get(Result, ArgListTy, isVarArg);
+ return false;
+}
- Result = HandleUpRefs(FunctionType::get(Result.get(),
- ArgListTy, isVarArg));
+/// ParseAnonStructType - Parse an anonymous struct type, which is inlined into
+/// other structs.
+bool LLParser::ParseAnonStructType(Type *&Result, bool Packed) {
+ SmallVector<Type*, 8> Elts;
+ if (ParseStructBody(Elts)) return true;
+
+ Result = StructType::get(Context, Elts, Packed);
+ return false;
+}
+
+/// ParseStructDefinition - Parse a struct in a 'type' definition.
+bool LLParser::ParseStructDefinition(SMLoc TypeLoc, StringRef Name,
+ std::pair<Type*, LocTy> &Entry,
+ Type *&ResultTy) {
+ // If the type was already defined, diagnose the redefinition.
+ if (Entry.first && !Entry.second.isValid())
+ return Error(TypeLoc, "redefinition of type");
+
+ // If we have opaque, just return without filling in the definition for the
+ // struct. This counts as a definition as far as the .ll file goes.
+ if (EatIfPresent(lltok::kw_opaque)) {
+ // This type is being defined, so clear the location to indicate this.
+ Entry.second = SMLoc();
+
+ // If this type number has never been uttered, create it.
+ if (Entry.first == 0)
+ Entry.first = StructType::createNamed(Context, Name);
+ ResultTy = Entry.first;
+ return false;
+ }
+
+ // If the type starts with '<', then it is either a packed struct or a vector.
+ bool isPacked = EatIfPresent(lltok::less);
+
+ // If we don't have a struct, then we have a random type alias, which we
+ // accept for compatibility with old files. These types are not allowed to be
+ // forward referenced and not allowed to be recursive.
+ if (Lex.getKind() != lltok::lbrace) {
+ if (Entry.first)
+ return Error(TypeLoc, "forward references to non-struct type");
+
+ ResultTy = 0;
+ if (isPacked)
+ return ParseArrayVectorType(ResultTy, true);
+ return ParseType(ResultTy);
+ }
+
+ // This type is being defined, so clear the location to indicate this.
+ Entry.second = SMLoc();
+
+ // If this type number has never been uttered, create it.
+ if (Entry.first == 0)
+ Entry.first = StructType::createNamed(Context, Name);
+
+ StructType *STy = cast<StructType>(Entry.first);
+
+ SmallVector<Type*, 8> Body;
+ if (ParseStructBody(Body) ||
+ (isPacked && ParseToken(lltok::greater, "expected '>' in packed struct")))
+ return true;
+
+ STy->setBody(Body, isPacked);
+ ResultTy = STy;
return false;
}
+
/// ParseStructType: Handles packed and unpacked types. </> parsed elsewhere.
-/// TypeRec
+/// StructType
/// ::= '{' '}'
-/// ::= '{' TypeRec (',' TypeRec)* '}'
+/// ::= '{' Type (',' Type)* '}'
/// ::= '<' '{' '}' '>'
-/// ::= '<' '{' TypeRec (',' TypeRec)* '}' '>'
-bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) {
+/// ::= '<' '{' Type (',' Type)* '}' '>'
+bool LLParser::ParseStructBody(SmallVectorImpl<Type*> &Body) {
assert(Lex.getKind() == lltok::lbrace);
Lex.Lex(); // Consume the '{'
- if (EatIfPresent(lltok::rbrace)) {
- Result = StructType::get(Context, Packed);
+ // Handle the empty struct.
+ if (EatIfPresent(lltok::rbrace))
return false;
- }
- std::vector<PATypeHolder> ParamsList;
LocTy EltTyLoc = Lex.getLoc();
- if (ParseTypeRec(Result)) return true;
- ParamsList.push_back(Result);
+ Type *Ty = 0;
+ if (ParseType(Ty)) return true;
+ Body.push_back(Ty);
- if (Result->isVoidTy())
- return Error(EltTyLoc, "struct element can not have void type");
- if (!StructType::isValidElementType(Result))
+ if (!StructType::isValidElementType(Ty))
return Error(EltTyLoc, "invalid element type for struct");
while (EatIfPresent(lltok::comma)) {
EltTyLoc = Lex.getLoc();
- if (ParseTypeRec(Result)) return true;
+ if (ParseType(Ty)) return true;
- if (Result->isVoidTy())
- return Error(EltTyLoc, "struct element can not have void type");
- if (!StructType::isValidElementType(Result))
+ if (!StructType::isValidElementType(Ty))
return Error(EltTyLoc, "invalid element type for struct");
- ParamsList.push_back(Result);
+ Body.push_back(Ty);
}
- if (ParseToken(lltok::rbrace, "expected '}' at end of struct"))
- return true;
-
- std::vector<const Type*> ParamsListTy;
- for (unsigned i = 0, e = ParamsList.size(); i != e; ++i)
- ParamsListTy.push_back(ParamsList[i].get());
- Result = HandleUpRefs(StructType::get(Context, ParamsListTy, Packed));
- return false;
+ return ParseToken(lltok::rbrace, "expected '}' at end of struct");
}
/// ParseArrayVectorType - Parse an array or vector type, assuming the first
/// token has already been consumed.
-/// TypeRec
+/// Type
/// ::= '[' APSINTVAL 'x' Types ']'
/// ::= '<' APSINTVAL 'x' Types '>'
-bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
+bool LLParser::ParseArrayVectorType(Type *&Result, bool isVector) {
if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() ||
Lex.getAPSIntVal().getBitWidth() > 64)
return TokError("expected number in address space");
@@ -1644,11 +1570,8 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
return true;
LocTy TypeLoc = Lex.getLoc();
- PATypeHolder EltTy(Type::getVoidTy(Context));
- if (ParseTypeRec(EltTy)) return true;
-
- if (EltTy->isVoidTy())
- return Error(TypeLoc, "array and vector element type cannot be void");
+ Type *EltTy = 0;
+ if (ParseType(EltTy)) return true;
if (ParseToken(isVector ? lltok::greater : lltok::rsquare,
"expected end of sequential type"))
@@ -1665,7 +1588,7 @@ bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) {
} else {
if (!ArrayType::isValidElementType(EltTy))
return Error(TypeLoc, "invalid array element type");
- Result = HandleUpRefs(ArrayType::get(EltTy, Size));
+ Result = ArrayType::get(EltTy, Size);
}
return false;
}
@@ -1770,7 +1693,7 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name,
}
// Don't make placeholders with invalid type.
- if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) {
+ if (!Ty->isFirstClassType() && !Ty->isLabelTy()) {
P.Error(Loc, "invalid use of a non-first-class type");
return 0;
}
@@ -1811,7 +1734,7 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty,
return 0;
}
- if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) {
+ if (!Ty->isFirstClassType() && !Ty->isLabelTy()) {
P.Error(Loc, "invalid use of a non-first-class type");
return 0;
}
@@ -1987,9 +1910,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
ParseToken(lltok::rbrace, "expected end of struct constant"))
return true;
- // FIXME: Get this type from context instead of reconstructing it!
- ID.ConstantVal = ConstantStruct::getAnon(Context, Elts);
- ID.Kind = ValID::t_Constant;
+ ID.ConstantStructElts = new Constant*[Elts.size()];
+ ID.UIntVal = Elts.size();
+ memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
+ ID.Kind = ValID::t_ConstantStruct;
return false;
}
case lltok::less: {
@@ -2007,9 +1931,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
return true;
if (isPackedStruct) {
- // FIXME: Get this type from context instead of reconstructing it!
- ID.ConstantVal = ConstantStruct::getAnon(Context, Elts, true);
- ID.Kind = ValID::t_Constant;
+ ID.ConstantStructElts = new Constant*[Elts.size()];
+ memcpy(ID.ConstantStructElts, Elts.data(), Elts.size()*sizeof(Elts[0]));
+ ID.UIntVal = Elts.size();
+ ID.Kind = ValID::t_PackedConstantStruct;
return false;
}
@@ -2131,7 +2056,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
case lltok::kw_inttoptr:
case lltok::kw_ptrtoint: {
unsigned Opc = Lex.getUIntVal();
- PATypeHolder DestTy(Type::getVoidTy(Context));
+ Type *DestTy = 0;
Constant *SrcVal;
Lex.Lex();
if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") ||
@@ -2414,9 +2339,9 @@ bool LLParser::ParseGlobalValue(const Type *Ty, Constant *&C) {
}
bool LLParser::ParseGlobalTypeAndValue(Constant *&V) {
- PATypeHolder Type(Type::getVoidTy(Context));
- return ParseType(Type) ||
- ParseGlobalValue(Type, V);
+ Type *Ty = 0;
+ return ParseType(Ty) ||
+ ParseGlobalValue(Ty, V);
}
/// ParseGlobalValueVector
@@ -2562,8 +2487,7 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
return false;
case ValID::t_Undef:
// FIXME: LabelTy should not be a first-class type.
- if ((!Ty->isFirstClassType() || Ty->isLabelTy()) &&
- !Ty->isOpaqueTy())
+ if (!Ty->isFirstClassType() || Ty->isLabelTy())
return Error(ID.Loc, "invalid type for undef constant");
V = UndefValue::get(Ty);
return false;
@@ -2584,20 +2508,40 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
V = ID.ConstantVal;
return false;
+ case ValID::t_ConstantStruct:
+ case ValID::t_PackedConstantStruct:
+ if (const StructType *ST = dyn_cast<StructType>(Ty)) {
+ if (ST->getNumElements() != ID.UIntVal)
+ return Error(ID.Loc,
+ "initializer with struct type has wrong # elements");
+ if (ST->isPacked() != (ID.Kind == ValID::t_PackedConstantStruct))
+ return Error(ID.Loc, "packed'ness of initializer and type don't match");
+
+ // Verify that the elements are compatible with the structtype.
+ for (unsigned i = 0, e = ID.UIntVal; i != e; ++i)
+ if (ID.ConstantStructElts[i]->getType() != ST->getElementType(i))
+ return Error(ID.Loc, "element " + Twine(i) +
+ " of struct initializer doesn't match struct element type");
+
+ V = ConstantStruct::get(ST, ArrayRef<Constant*>(ID.ConstantStructElts,
+ ID.UIntVal));
+ } else
+ return Error(ID.Loc, "constant expression type mismatch");
+ return false;
}
}
-bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) {
+bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS) {
V = 0;
ValID ID;
- return ParseValID(ID, &PFS) ||
- ConvertValIDToValue(Ty, ID, V, &PFS);
+ return ParseValID(ID, PFS) ||
+ ConvertValIDToValue(Ty, ID, V, PFS);
}
-bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
- PATypeHolder T(Type::getVoidTy(Context));
- return ParseType(T) ||
- ParseValue(T, V, PFS);
+bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState *PFS) {
+ Type *Ty = 0;
+ return ParseType(Ty) ||
+ ParseValue(Ty, V, PFS);
}
bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc,
@@ -2623,7 +2567,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
unsigned Visibility, RetAttrs;
CallingConv::ID CC;
- PATypeHolder RetType(Type::getVoidTy(Context));
+ Type *RetType = 0;
LocTy RetTypeLoc = Lex.getLoc();
if (ParseOptionalLinkage(Linkage) ||
ParseOptionalVisibility(Visibility) ||
@@ -2660,8 +2604,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
return Error(LinkageLoc, "invalid function linkage type");
}
- if (!FunctionType::isValidReturnType(RetType) ||
- RetType->isOpaqueTy())
+ if (!FunctionType::isValidReturnType(RetType))
return Error(RetTypeLoc, "invalid function return type");
LocTy NameLoc = Lex.getLoc();
@@ -2684,7 +2627,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
if (Lex.getKind() != lltok::lparen)
return TokError("expected '(' in function argument list");
- std::vector<ArgInfo> ArgList;
+ SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
unsigned FuncAttrs;
std::string Section;
@@ -2693,7 +2636,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
bool UnnamedAddr;
LocTy UnnamedAddrLoc;
- if (ParseArgumentList(ArgList, isVarArg, false) ||
+ if (ParseArgumentList(ArgList, isVarArg) ||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
&UnnamedAddrLoc) ||
ParseOptionalAttrs(FuncAttrs, 2) ||
@@ -2719,7 +2662,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
Attrs.push_back(AttributeWithIndex::get(0, RetAttrs));
for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
- ParamTypeList.push_back(ArgList[i].Type);
+ ParamTypeList.push_back(ArgList[i].Ty);
if (ArgList[i].Attrs != Attribute::None)
Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs));
}
@@ -3052,11 +2995,18 @@ bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) {
/// ::= 'ret' void (',' !dbg, !1)*
/// ::= 'ret' TypeAndValue (',' !dbg, !1)*
bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
- PerFunctionState &PFS) {
- PATypeHolder Ty(Type::getVoidTy(Context));
+ PerFunctionState &PFS) {
+ SMLoc TypeLoc = Lex.getLoc();
+ Type *Ty = 0;
if (ParseType(Ty, true /*void allowed*/)) return true;
+ Type *ResType = PFS.getFunction().getReturnType();
+
if (Ty->isVoidTy()) {
+ if (!ResType->isVoidTy())
+ return Error(TypeLoc, "value doesn't match function result type '" +
+ getTypeString(ResType) + "'");
+
Inst = ReturnInst::Create(Context);
return false;
}
@@ -3064,6 +3014,10 @@ bool LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB,
Value *RV;
if (ParseValue(Ty, RV, PFS)) return true;
+ if (ResType != RV->getType())
+ return Error(TypeLoc, "value doesn't match function result type '" +
+ getTypeString(ResType) + "'");
+
Inst = ReturnInst::Create(Context, RV);
return false;
}
@@ -3191,7 +3145,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
LocTy CallLoc = Lex.getLoc();
unsigned RetAttrs, FnAttrs;
CallingConv::ID CC;
- PATypeHolder RetType(Type::getVoidTy(Context));
+ Type *RetType = 0;
LocTy RetTypeLoc;
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
@@ -3369,8 +3323,9 @@ bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS,
/// ::= CastOpc TypeAndValue 'to' Type
bool LLParser::ParseCast(Instruction *&Inst, PerFunctionState &PFS,
unsigned Opc) {
- LocTy Loc; Value *Op;
- PATypeHolder DestTy(Type::getVoidTy(Context));
+ LocTy Loc;
+ Value *Op;
+ Type *DestTy = 0;
if (ParseTypeAndValue(Op, Loc, PFS) ||
ParseToken(lltok::kw_to, "expected 'to' after cast value") ||
ParseType(DestTy))
@@ -3409,7 +3364,7 @@ bool LLParser::ParseSelect(Instruction *&Inst, PerFunctionState &PFS) {
/// ::= 'va_arg' TypeAndValue ',' Type
bool LLParser::ParseVA_Arg(Instruction *&Inst, PerFunctionState &PFS) {
Value *Op;
- PATypeHolder EltTy(Type::getVoidTy(Context));
+ Type *EltTy = 0;
LocTy TypeLoc;
if (ParseTypeAndValue(Op, PFS) ||
ParseToken(lltok::comma, "expected ',' after vaarg operand") ||
@@ -3481,11 +3436,10 @@ bool LLParser::ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) {
/// ParsePHI
/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')*
int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) {
- PATypeHolder Ty(Type::getVoidTy(Context));
+ Type *Ty = 0; LocTy TypeLoc;
Value *Op0, *Op1;
- LocTy TypeLoc = Lex.getLoc();
- if (ParseType(Ty) ||
+ if (ParseType(Ty, TypeLoc) ||
ParseToken(lltok::lsquare, "expected '[' in phi value list") ||
ParseValue(Ty, Op0, PFS) ||
ParseToken(lltok::comma, "expected ',' after insertelement value") ||
@@ -3531,7 +3485,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
bool isTail) {
unsigned RetAttrs, FnAttrs;
CallingConv::ID CC;
- PATypeHolder RetType(Type::getVoidTy(Context));
+ Type *RetType = 0;
LocTy RetTypeLoc;
ValID CalleeID;
SmallVector<ParamInfo, 16> ArgList;
@@ -3620,10 +3574,10 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
/// ParseAlloc
/// ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)?
int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS) {
- PATypeHolder Ty(Type::getVoidTy(Context));
Value *Size = 0;
LocTy SizeLoc;
unsigned Alignment = 0;
+ Type *Ty = 0;
if (ParseType(Ty)) return true;
bool AteExtraComma = false;
@@ -3787,12 +3741,7 @@ bool LLParser::ParseMDNodeVector(SmallVectorImpl<Value*> &Elts,
}
Value *V = 0;
- PATypeHolder Ty(Type::getVoidTy(Context));
- ValID ID;
- if (ParseType(Ty) || ParseValID(ID, PFS) ||
- ConvertValIDToValue(Ty, ID, V, PFS))
- return true;
-
+ if (ParseTypeAndValue(V, PFS)) return true;
Elts.push_back(V);
} while (EatIfPresent(lltok::comma));
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index c486799f29..9630657850 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -18,6 +18,7 @@
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/ValueHandle.h"
#include <map>
@@ -32,6 +33,7 @@ namespace llvm {
class GlobalValue;
class MDString;
class MDNode;
+ class StructType;
/// ValID - Represents a reference of a definition of some sort with no type.
/// There are several cases where we have to parse the value but where the
@@ -47,7 +49,9 @@ namespace llvm {
t_Constant, // Value in ConstantVal.
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
t_MDNode, // Value in MDNodeVal.
- t_MDString // Value in MDStringVal.
+ t_MDString, // Value in MDStringVal.
+ t_ConstantStruct, // Value in ConstantStructElts.
+ t_PackedConstantStruct // Value in ConstantStructElts.
} Kind;
LLLexer::LocTy Loc;
@@ -58,12 +62,19 @@ namespace llvm {
Constant *ConstantVal;
MDNode *MDNodeVal;
MDString *MDStringVal;
- ValID() : APFloatVal(0.0) {}
+ Constant **ConstantStructElts;
+
+ ValID() : Kind(t_LocalID), APFloatVal(0.0) {}
+ ~ValID() {
+ if (Kind == t_ConstantStruct || Kind == t_PackedConstantStruct)
+ delete [] ConstantStructElts;
+ }
bool operator<(const ValID &RHS) const {
if (Kind == t_LocalID || Kind == t_GlobalID)
return UIntVal < RHS.UIntVal;
- assert((Kind == t_LocalName || Kind == t_GlobalName) &&
+ assert((Kind == t_LocalName || Kind == t_GlobalName ||
+ Kind == t_ConstantStruct || Kind == t_PackedConstantStruct) &&
"Ordering not defined for this ValID kind yet");
return StrVal < RHS.StrVal;
}
@@ -93,33 +104,13 @@ namespace llvm {
};
DenseMap<Instruction*, std::vector<MDRef> > ForwardRefInstMetadata;
- // Type resolution handling data structures.
- std::map<std::string, std::pair<PATypeHolder, LocTy> > ForwardRefTypes;
- std::map<unsigned, std::pair<PATypeHolder, LocTy> > ForwardRefTypeIDs;
- std::vector<PATypeHolder> NumberedTypes;
+ // Type resolution handling data structures. The location is set when we
+ // have processed a use of the type but not a definition yet.
+ StringMap<std::pair<Type*, LocTy> > NamedTypes;
+ std::vector<std::pair<Type*, LocTy> > NumberedTypes;
+
std::vector<TrackingVH<MDNode> > NumberedMetadata;
std::map<unsigned, std::pair<TrackingVH<MDNode>, LocTy> > ForwardRefMDNodes;
- struct UpRefRecord {
- /// Loc - This is the location of the upref.
- LocTy Loc;
-
- /// NestingLevel - The number of nesting levels that need to be popped
- /// before this type is resolved.
- unsigned NestingLevel;
-
- /// LastContainedTy - This is the type at the current binding level for
- /// the type. Every time we reduce the nesting level, this gets updated.
- const Type *LastContainedTy;
-
- /// UpRefTy - This is the actual opaque type that the upreference is
- /// represented with.
- OpaqueType *UpRefTy;
-
- UpRefRecord(LocTy L, unsigned NL, OpaqueType *URTy)
- : Loc(L), NestingLevel(NL), LastContainedTy((Type*)URTy),
- UpRefTy(URTy) {}
- };
- std::vector<UpRefRecord> UpRefs;
// Global Value reference information.
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
@@ -137,7 +128,7 @@ namespace llvm {
M(m) {}
bool Run();
- LLVMContext& getContext() { return Context; }
+ LLVMContext &getContext() { return Context; }
private:
@@ -222,16 +213,19 @@ namespace llvm {
bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo);
// Type Parsing.
- bool ParseType(PATypeHolder &Result, bool AllowVoid = false);
- bool ParseType(PATypeHolder &Result, LocTy &Loc, bool AllowVoid = false) {
+ bool ParseType(Type *&Result, bool AllowVoid = false);
+ bool ParseType(Type *&Result, LocTy &Loc, bool AllowVoid = false) {
Loc = Lex.getLoc();
return ParseType(Result, AllowVoid);
}
- bool ParseTypeRec(PATypeHolder &H);
- bool ParseStructType(PATypeHolder &H, bool Packed);
- bool ParseArrayVectorType(PATypeHolder &H, bool isVector);
- bool ParseFunctionType(PATypeHolder &Result);
- PATypeHolder HandleUpRefs(const Type *Ty);
+ bool ParseAnonStructType(Type *&Result, bool Packed);
+ bool ParseStructBody(SmallVectorImpl<Type*> &Body);
+ bool ParseStructDefinition(SMLoc TypeLoc, StringRef Name,
+ std::pair<Type*, LocTy> &Entry,
+ Type *&ResultTy);
+
+ bool ParseArrayVectorType(Type *&Result, bool isVector);
+ bool ParseFunctionType(Type *&Result);
// Function Semantic Analysis.
class PerFunctionState {
@@ -278,14 +272,20 @@ namespace llvm {
bool ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V,
PerFunctionState *PFS);
- bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS);
+ bool ParseValue(const Type *Ty, Value *&V, PerFunctionState *PFS);
+ bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) {
+ return ParseValue(Ty, V, &PFS);
+ }
bool ParseValue(const Type *Ty, Value *&V, LocTy &Loc,
PerFunctionState &PFS) {
Loc = Lex.getLoc();
- return ParseValue(Ty, V, PFS);
+ return ParseValue(Ty, V, &PFS);
}
- bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS);
+ bool ParseTypeAndValue(Value *&V, PerFunctionState *PFS);
+ bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS) {
+ return ParseTypeAndValue(V, &PFS);
+ }
bool ParseTypeAndValue(Value *&V, LocTy &Loc, PerFunctionState &PFS) {
Loc = Lex.getLoc();
return ParseTypeAndValue(V, PFS);
@@ -321,14 +321,13 @@ namespace llvm {
// Function Parsing.
struct ArgInfo {
LocTy Loc;
- PATypeHolder Type;
+ Type *Ty;
unsigned Attrs;
std::string Name;
- ArgInfo(LocTy L, PATypeHolder Ty, unsigned Attr, const std::string &N)
- : Loc(L), Type(Ty), Attrs(Attr), Name(N) {}
+ ArgInfo(LocTy L, Type *ty, unsigned Attr, const std::string &N)
+ : Loc(L), Ty(ty), Attrs(Attr), Name(N) {}
};
- bool ParseArgumentList(std::vector<ArgInfo> &ArgList,
- bool &isVarArg, bool inType);
+ bool ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &isVarArg);
bool ParseFunctionHeader(Function *&Fn, bool isDefine);
bool ParseFunctionBody(Function &Fn);
bool ParseBasicBlock(PerFunctionState &PFS);
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 963791f5d6..1bdcfe98d4 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -31,7 +31,7 @@ void BitcodeReader::FreeState() {
if (BufferOwned)
delete Buffer;
Buffer = 0;
- std::vector<PATypeHolder>().swap(TypeList);
+ std::vector<Type*>().swap(TypeList);
ValueList.clear();
MDValueList.clear();
@@ -352,19 +352,28 @@ Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
return V;
}
-const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
- // If the TypeID is in range, return it.
- if (ID < TypeList.size())
- return TypeList[ID].get();
- if (!isTypeTable) return 0;
-
- // The type table allows forward references. Push as many Opaque types as
- // needed to get up to ID.
- while (TypeList.size() <= ID)
- TypeList.push_back(OpaqueType::get(Context));
- return TypeList.back().get();
+Type *BitcodeReader::getTypeByID(unsigned ID) {
+ // The type table size is always specified correctly.
+ if (ID >= TypeList.size())
+ return 0;
+
+ if (Type *Ty = TypeList[ID])
+ return Ty;
+
+ // If we have a forward reference, the only possible case is when it is to a
+ // named struct. Just create a placeholder for now.
+ return TypeList[ID] = StructType::createNamed(Context, "");
+}
+
+/// FIXME: Remove in LLVM 3.1, only used by ParseOldTypeTable.
+Type *BitcodeReader::getTypeByIDOrNull(unsigned ID) {
+ if (ID >= TypeList.size())
+ TypeList.resize(ID+1);
+
+ return TypeList[ID];
}
+
//===----------------------------------------------------------------------===//
// Functions for parsing blocks from the bitcode file
//===----------------------------------------------------------------------===//
@@ -471,17 +480,22 @@ bool BitcodeReader::ParseAttributeBlock() {
}
}
-
bool BitcodeReader::ParseTypeTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID))
+ if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
return Error("Malformed block record");
+
+ return ParseTypeTableBody();
+}
+bool BitcodeReader::ParseTypeTableBody() {
if (!TypeList.empty())
return Error("Multiple TYPE_BLOCKs found!");
SmallVector<uint64_t, 64> Record;
unsigned NumRecords = 0;
+ SmallString<64> TypeName;
+
// Read all the records for this type table.
while (1) {
unsigned Code = Stream.ReadCode();
@@ -508,17 +522,15 @@ bool BitcodeReader::ParseTypeTable() {
// Read a record.
Record.clear();
- const Type *ResultTy = 0;
+ Type *ResultTy = 0;
switch (Stream.ReadRecord(Code, Record)) {
- default: // Default behavior: unknown type.
- ResultTy = 0;
- break;
+ default: return Error("unknown type in type table");
case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
// TYPE_CODE_NUMENTRY contains a count of the number of types in the
// type list. This allows us to reserve space.
if (Record.size() < 1)
return Error("Invalid TYPE_CODE_NUMENTRY record");
- TypeList.reserve(Record[0]);
+ TypeList.resize(Record[0]);
continue;
case bitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
@@ -541,9 +553,6 @@ bool BitcodeReader::ParseTypeTable() {
case bitc::TYPE_CODE_LABEL: // LABEL
ResultTy = Type::getLabelTy(Context);
break;
- case bitc::TYPE_CODE_OPAQUE: // OPAQUE
- ResultTy = 0;
- break;
case bitc::TYPE_CODE_METADATA: // METADATA
ResultTy = Type::getMetadataTy(Context);
break;
@@ -563,8 +572,9 @@ bool BitcodeReader::ParseTypeTable() {
unsigned AddressSpace = 0;
if (Record.size() == 2)
AddressSpace = Record[1];
- ResultTy = PointerType::get(getTypeByID(Record[0], true),
- AddressSpace);
+ ResultTy = getTypeByID(Record[0]);
+ if (ResultTy == 0) return Error("invalid element type in pointer type");
+ ResultTy = PointerType::get(ResultTy, AddressSpace);
break;
}
case bitc::TYPE_CODE_FUNCTION: {
@@ -573,68 +583,305 @@ bool BitcodeReader::ParseTypeTable() {
if (Record.size() < 3)
return Error("Invalid FUNCTION type record");
std::vector<const Type*> ArgTys;
- for (unsigned i = 3, e = Record.size(); i != e; ++i)
- ArgTys.push_back(getTypeByID(Record[i], true));
+ for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ ArgTys.push_back(T);
+ else
+ break;
+ }
+
+ ResultTy = getTypeByID(Record[2]);
+ if (ResultTy == 0 || ArgTys.size() < Record.size()-3)
+ return Error("invalid type in function type");
- ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys,
- Record[0]);
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
break;
}
- case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N]
+ case bitc::TYPE_CODE_STRUCT_ANON: { // STRUCT: [ispacked, eltty x N]
if (Record.size() < 1)
return Error("Invalid STRUCT type record");
- std::vector<const Type*> EltTys;
- for (unsigned i = 1, e = Record.size(); i != e; ++i)
- EltTys.push_back(getTypeByID(Record[i], true));
+ std::vector<Type*> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid type in struct type");
ResultTy = StructType::get(Context, EltTys, Record[0]);
break;
}
+ case bitc::TYPE_CODE_STRUCT_NAME: // STRUCT_NAME: [strchr x N]
+ if (ConvertToString(Record, 0, TypeName))
+ return Error("Invalid STRUCT_NAME record");
+ continue;
+
+ case bitc::TYPE_CODE_STRUCT_NAMED: { // STRUCT: [ispacked, eltty x N]
+ if (Record.size() < 1)
+ return Error("Invalid STRUCT type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct.
+ Res = StructType::createNamed(Context, TypeName);
+ TypeName.clear();
+
+ SmallVector<Type*, 8> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *T = getTypeByID(Record[i]))
+ EltTys.push_back(T);
+ else
+ break;
+ }
+ if (EltTys.size() != Record.size()-1)
+ return Error("invalid STRUCT type record");
+ Res->setBody(EltTys, Record[0]);
+ ResultTy = Res;
+ break;
+ }
+ case bitc::TYPE_CODE_OPAQUE: { // OPAQUE: []
+ if (Record.size() != 1)
+ return Error("Invalid OPAQUE type record");
+
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ // Check to see if this was forward referenced, if so fill in the temp.
+ StructType *Res = cast_or_null<StructType>(TypeList[NumRecords]);
+ if (Res) {
+ Res->setName(TypeName);
+ TypeList[NumRecords] = 0;
+ } else // Otherwise, create a new struct with no body.
+ Res = StructType::createNamed(Context, TypeName);
+ TypeName.clear();
+ ResultTy = Res;
+ break;
+ }
case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid ARRAY type record");
- ResultTy = ArrayType::get(getTypeByID(Record[1], true), Record[0]);
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = ArrayType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
break;
case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
if (Record.size() < 2)
return Error("Invalid VECTOR type record");
- ResultTy = VectorType::get(getTypeByID(Record[1], true), Record[0]);
+ if ((ResultTy = getTypeByID(Record[1])))
+ ResultTy = VectorType::get(ResultTy, Record[0]);
+ else
+ return Error("Invalid ARRAY type element");
break;
}
- if (NumRecords == TypeList.size()) {
- // If this is a new type slot, just append it.
- TypeList.push_back(ResultTy ? ResultTy : OpaqueType::get(Context));
- ++NumRecords;
- } else if (ResultTy == 0) {
- // Otherwise, this was forward referenced, so an opaque type was created,
- // but the result type is actually just an opaque. Leave the one we
- // created previously.
- ++NumRecords;
- } else {
- // Otherwise, this was forward referenced, so an opaque type was created.
- // Resolve the opaque type to the real type now.
- assert(NumRecords < TypeList.size() && "Typelist imbalance");
- const OpaqueType *OldTy = cast<OpaqueType>(TypeList[NumRecords++].get());
-
- // Don't directly push the new type on the Tab. Instead we want to replace
- // the opaque type we previously inserted with the new concrete value. The
- // refinement from the abstract (opaque) type to the new type causes all
- // uses of the abstract type to use the concrete type (NewTy). This will
- // also cause the opaque type to be deleted.
- const_cast<OpaqueType*>(OldTy)->refineAbstractTypeTo(ResultTy);
-
- // This should have replaced the old opaque type with the new type in the
- // value table... or with a preexisting type that was already in the
- // system. Let's just make sure it did.
- assert(TypeList[NumRecords-1].get() != OldTy &&
- "refineAbstractType didn't work!");
+ if (NumRecords >= TypeList.size())
+ return Error("invalid TYPE table");
+ assert(ResultTy && "Didn't read a type?");
+ assert(TypeList[NumRecords] == 0 && "Already read type?");
+ TypeList[NumRecords++] = ResultTy;
+ }
+}
+
+// FIXME: Remove in LLVM 3.1
+bool BitcodeReader::ParseOldTypeTable() {
+ if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_OLD))
+ return Error("Malformed block record");
+
+ if (!TypeList.empty())
+ return Error("Multiple TYPE_BLOCKs found!");
+
+
+ // While horrible, we have no good ordering of types in the bc file. Just
+ // iteratively parse types out of the bc file in multiple passes until we get
+ // them all. Do this by saving a cursor for the start of the type block.
+ BitstreamCursor StartOfTypeBlockCursor(Stream);
+
+ unsigned NumTypesRead = 0;
+
+ SmallVector<uint64_t, 64> Record;
+RestartScan:
+ unsigned NextTypeID = 0;
+ bool ReadAnyTypes = false;
+
+ // Read all the records for this type table.
+ while (1) {
+ unsigned Code = Stream.ReadCode();
+ if (Code == bitc::END_BLOCK) {
+ if (NextTypeID != TypeList.size())
+ return Error("Invalid type forward reference in TYPE_BLOCK_ID_OLD");
+
+ // If we haven't read all of the types yet, iterate again.
+ if (NumTypesRead != TypeList.size()) {
+ // If we didn't successfully read any types in this pass, then we must
+ // have an unhandled forward reference.
+ if (!ReadAnyTypes)
+ return Error("Obsolete bitcode contains unhandled recursive type");
+
+ Stream = StartOfTypeBlockCursor;
+ goto RestartScan;
+ }
+
+ if (Stream.ReadBlockEnd())
+ return Error("Error at end of type table block");
+ return false;
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Stream.ReadSubBlockID();
+ if (Stream.SkipBlock())
+ return Error("Malformed block record");
+ continue;
}
+
+ if (Code == bitc::DEFINE_ABBREV) {
+ Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ Record.clear();
+ Type *ResultTy = 0;
+ switch (Stream.ReadRecord(Code, Record)) {
+ default: return Error("unknown type in type table");
+ case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
+ // TYPE_CODE_NUMENTRY contains a count of the number of types in the
+ // type list. This allows us to reserve space.
+ if (Record.size() < 1)
+ return Error("Invalid TYPE_CODE_NUMENTRY record");
+ TypeList.resize(Record[0]);
+ continue;
+ case bitc::TYPE_CODE_VOID: // VOID
+ ResultTy = Type::getVoidTy(Context);
+ break;
+ case bitc::TYPE_CODE_FLOAT: // FLOAT
+ ResultTy = Type::getFloatTy(Context);
+ break;
+ case bitc::TYPE_CODE_DOUBLE: // DOUBLE
+ ResultTy = Type::getDoubleTy(Context);
+ break;
+ case bitc::TYPE_CODE_X86_FP80: // X86_FP80
+ ResultTy = Type::getX86_FP80Ty(Context);
+ break;
+ case bitc::TYPE_CODE_FP128: // FP128
+ ResultTy = Type::getFP128Ty(Context);
+ break;
+ case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128
+ ResultTy = Type::getPPC_FP128Ty(Context);
+ break;
+ case bitc::TYPE_CODE_LABEL: // LABEL
+ ResultTy = Type::getLabelTy(Context);
+ break;
+ case bitc::TYPE_CODE_METADATA: // METADATA
+ ResultTy = Type::getMetadataTy(Context);
+ break;
+ case bitc::TYPE_CODE_X86_MMX: // X86_MMX
+ ResultTy = Type::getX86_MMXTy(Context);
+ break;
+ case bitc::TYPE_CODE_INTEGER: // INTEGER: [width]
+ if (Record.size() < 1)
+ return Error("Invalid Integer type record");
+ ResultTy = IntegerType::get(Context, Record[0]);
+ break;
+ case bitc::TYPE_CODE_OPAQUE: // OPAQUE
+ if (NextTypeID < TypeList.size() && TypeList[NextTypeID] == 0)
+ ResultTy = StructType::createNamed(Context, "");
+ break;
+ case bitc::TYPE_CODE_STRUCT_OLD: {// STRUCT_OLD
+ if (NextTypeID >= TypeList.size()) break;
+ // If we already read it, don't reprocess.
+ if (TypeList[NextTypeID] &&
+ !cast<StructType>(TypeList[NextTypeID])->isOpaque())
+ break;
+
+ // Set a type.
+ if (TypeList[NextTypeID] == 0)
+ TypeList[NextTypeID] = StructType::createNamed(Context, "");
+
+ std::vector<Type*> EltTys;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i) {
+ if (Type *Elt = getTypeByIDOrNull(Record[i]))
+ EltTys.push_back(Elt);
+ else
+ break;
+ }
+
+ if (EltTys.size() != Record.size()-1)
+ break; // Not all elements are ready.
+
+ cast<StructType>(TypeList[NextTypeID])->setBody(EltTys, Record[0]);
+ ResultTy = TypeList[NextTypeID];
+ TypeList[NextTypeID] = 0;
+ break;
+ }
+ case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or
+ // [pointee type, address space]
+ if (Record.size() < 1)
+ return Error("Invalid POINTER type record");
+ unsigned AddressSpace = 0;
+ if (Record.size() == 2)
+ AddressSpace = Record[1];
+ if ((ResultTy = getTypeByIDOrNull(Record[0])))
+ ResultTy = PointerType::get(ResultTy, AddressSpace);
+ break;
+ }
+ case bitc::TYPE_CODE_FUNCTION: {
+ // FIXME: attrid is dead, remove it in LLVM 3.0
+ // FUNCTION: [vararg, attrid, retty, paramty x N]
+ if (Record.size() < 3)
+ return Error("Invalid FUNCTION type record");
+ std::vector<const Type*> ArgTys;
+ for (unsigned i = 3, e = Record.size(); i != e; ++i) {
+ if (Type *Elt = getTypeByIDOrNull(Record[i]))
+ ArgTys.push_back(Elt);
+ else
+ break;
+ }
+ if (ArgTys.size()+3 != Record.size())
+ break; // Something was null.
+ if ((ResultTy = getTypeByIDOrNull(Record[2])))
+ ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
+ break;
+ }
+ case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid ARRAY type record");
+ if ((ResultTy = getTypeByIDOrNull(Record[1])))
+ ResultTy = ArrayType::get(ResultTy, Record[0]);
+ break;
+ case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
+ if (Record.size() < 2)
+ return Error("Invalid VECTOR type record");
+ if ((ResultTy = getTypeByIDOrNull(Record[1])))
+ ResultTy = VectorType::get(ResultTy, Record[0]);
+ break;
+ }
+
+ if (NextTypeID >= TypeList.size())
+ return Error("invalid TYPE table");
+
+ if (ResultTy && TypeList[NextTypeID] == 0) {
+ ++NumTypesRead;
+ ReadAnyTypes = true;
+
+ TypeList[NextTypeID] = ResultTy;
+ }
+
+ ++NextTypeID;
}
}
-bool BitcodeReader::ParseTypeSymbolTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID))
+bool BitcodeReader::ParseOldTypeSymbolTable() {
+ if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID_OLD))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
@@ -674,7 +921,10 @@ bool BitcodeReader::ParseTypeSymbolTable() {
if (TypeID >= TypeList.size())
return Error("Invalid Type ID in TST_ENTRY record");
- TheModule->addTypeName(TypeName, TypeList[TypeID].get());
+ // Only apply the type name to a struct type with no name.
+ if (StructType *STy = dyn_cast<StructType>(TypeList[TypeID]))
+ if (!STy->isAnonymous() && !STy->hasName())
+ STy->setName(TypeName);
TypeName.clear();
break;
}
@@ -1310,12 +1560,16 @@ bool BitcodeReader::ParseModule() {
if (ParseAttributeBlock())
return true;
break;
- case bitc::TYPE_BLOCK_ID:
+ case bitc::TYPE_BLOCK_ID_NEW:
if (ParseTypeTable())
return true;
break;
- case bitc::TYPE_SYMTAB_BLOCK_ID:
- if (ParseTypeSymbolTable())
+ case bitc::TYPE_BLOCK_ID_OLD:
+ if (ParseOldTypeTable())
+ return true;
+ break;
+ case bitc::TYPE_SYMTAB_BLOCK_ID_OLD:
+ if (ParseOldTypeSymbolTable())
return true;
break;
case bitc::VALUE_SYMTAB_BLOCK_ID:
@@ -2307,7 +2561,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
SmallVector<Value*, 16> Args;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
- if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID)
+ if (FTy->getParamType(i)->isLabelTy())
Args.push_back(getBasicBlock(Record[OpNum]));
else
Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index 14033b095c..1b3bf1a185 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -131,7 +131,7 @@ class BitcodeReader : public GVMaterializer {
const char *ErrorString;
- std::vector<PATypeHolder> TypeList;
+ std::vector<Type*> TypeList;
BitcodeReaderValueList ValueList;
BitcodeReaderMDValueList MDValueList;
SmallVector<Instruction *, 64> InstructionList;
@@ -210,7 +210,8 @@ public:
/// @returns true if an error occurred.
bool ParseTriple(std::string &Triple);
private:
- const Type *getTypeByID(unsigned ID, bool isTypeTable = false);
+ Type *getTypeByID(unsigned ID);
+ Type *getTypeByIDOrNull(unsigned ID);
Value *getFnValueByID(unsigned ID, const Type *Ty) {
if (Ty && Ty->isMetadataTy())
return MDValueList.getValueFwdRef(ID);
@@ -258,7 +259,10 @@ private:
bool ParseModule();
bool ParseAttributeBlock();
bool ParseTypeTable();
- bool ParseTypeSymbolTable();
+ bool ParseOldTypeTable(); // FIXME: Remove in LLVM 3.1
+ bool ParseTypeTableBody();
+
+ bool ParseOldTypeSymbolTable(); // FIXME: Remove in LLVM 3.1
bool ParseValueSymbolTable();
bool ParseConstants();
bool RememberAndSkipFunctionBody();
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 24b5e2d52a..85d67ce62b 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -21,7 +21,6 @@
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Operator.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
@@ -29,6 +28,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Program.h"
#include <cctype>
+#include <map>
using namespace llvm;
/// These are manifest constants used by the bitcode writer. They do not need to
@@ -101,13 +101,16 @@ static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
}
}
-static void WriteStringRecord(unsigned Code, const std::string &Str,
+static void WriteStringRecord(unsigned Code, StringRef Str,
unsigned AbbrevToUse, BitstreamWriter &Stream) {
SmallVector<unsigned, 64> Vals;
// Code: [strchar x N]
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+ if (AbbrevToUse && !BitCodeAbbrevOp::isChar6(Str[i]))
+ AbbrevToUse = 0;
Vals.push_back(Str[i]);
+ }
// Emit the finished record.
Stream.EmitRecord(Code, Vals, AbbrevToUse);
@@ -151,7 +154,7 @@ static void WriteAttributeTable(const ValueEnumerator &VE,
static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
const ValueEnumerator::TypeList &TypeList = VE.getTypes();
- Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */);
+ Stream.EnterSubblock(bitc::TYPE_BLOCK_ID_NEW, 4 /*count from # abbrevs */);
SmallVector<uint64_t, 64> TypeVals;
// Abbrev for TYPE_CODE_POINTER.
@@ -172,15 +175,32 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
Log2_32_Ceil(VE.getTypes().size()+1)));
unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv);
- // Abbrev for TYPE_CODE_STRUCT.
+ // Abbrev for TYPE_CODE_STRUCT_ANON.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_ANON));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
+ Log2_32_Ceil(VE.getTypes().size()+1)));
+ unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv);
+
+ // Abbrev for TYPE_CODE_STRUCT_NAME.
+ Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
+ unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv);
+
+ // Abbrev for TYPE_CODE_STRUCT_NAMED.
Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT));
+ Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAMED));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
Log2_32_Ceil(VE.getTypes().size()+1)));
- unsigned StructAbbrev = Stream.EmitAbbrev(Abbv);
+ unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv);
+
// Abbrev for TYPE_CODE_ARRAY.
Abbv = new BitCodeAbbrev();
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));
@@ -202,16 +222,15 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
switch (T->getTypeID()) {
default: llvm_unreachable("Unknown type!");
- case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
- case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
- case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
- case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
- case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
+ case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
+ case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
+ case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
+ case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
+ case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
- case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
- case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break;
- case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
- case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
+ case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
+ case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
+ case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break;
case Type::IntegerTyID:
// INTEGER: [width]
Code = bitc::TYPE_CODE_INTEGER;
@@ -242,13 +261,28 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
case Type::StructTyID: {
const StructType *ST = cast<StructType>(T);
// STRUCT: [ispacked, eltty x N]
- Code = bitc::TYPE_CODE_STRUCT;
TypeVals.push_back(ST->isPacked());
// Output all of the element types.
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I)
TypeVals.push_back(VE.getTypeID(*I));
- AbbrevToUse = StructAbbrev;
+
+ if (ST->isAnonymous()) {
+ Code = bitc::TYPE_CODE_STRUCT_ANON;
+ AbbrevToUse = StructAnonAbbrev;
+ } else {
+ if (ST->isOpaque()) {
+ Code = bitc::TYPE_CODE_OPAQUE;
+ } else {
+ Code = bitc::TYPE_CODE_STRUCT_NAMED;
+ AbbrevToUse = StructNamedAbbrev;
+ }
+
+ // Emit the name if it is present.
+ if (!ST->getName().empty())
+ WriteStringRecord(bitc::TYPE_CODE_STRUCT_NAME, ST->getName(),
+ StructNameAbbrev, Stream);
+ }
break;
}
case Type::ArrayTyID: {
@@ -1278,46 +1312,6 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE,
Stream.ExitBlock();
}
-/// WriteTypeSymbolTable - Emit a block for the specified type symtab.
-static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- if (TST.empty()) return;
-
- Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3);
-
- // 7-bit fixed width VST_CODE_ENTRY strings.
- BitCodeAbbrev *Abbv = new BitCodeAbbrev();
- Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
- Log2_32_Ceil(VE.getTypes().size()+1)));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
- Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
- unsigned V7Abbrev = Stream.EmitAbbrev(Abbv);
-
- SmallVector<unsigned, 64> NameVals;
-
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI) {
- // TST_ENTRY: [typeid, namechar x N]
- NameVals.push_back(VE.getTypeID(TI->second));
-
- const std::string &Str = TI->first;
- bool is7Bit = true;
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- NameVals.push_back((unsigned char)Str[i]);
- if (Str[i] & 128)
- is7Bit = false;
- }
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0);
- NameVals.clear();
- }
-
- Stream.ExitBlock();
-}
-
// Emit blockinfo, which defines the standard abbreviations etc.
static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
// We only want to emit block info records for blocks that have multiple
@@ -1521,9 +1515,6 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
// Emit metadata.
WriteModuleMetadataStore(M, Stream);
- // Emit the type symbol table information.
- WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
-
// Emit names for globals/functions etc.
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream);
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index 5138c3c984..b68bf92d51 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -17,7 +17,6 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Instructions.h"
#include <algorithm>
@@ -59,9 +58,6 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
I != E; ++I)
EnumerateValue(I->getAliasee());
- // Enumerate types used by the type symbol table.
- EnumerateTypeSymbolTable(M->getTypeSymbolTable());
-
// Insert constants and metadata that are named at module level into the slot
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M->getValueSymbolTable());
@@ -109,78 +105,12 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
// Optimize constant ordering.
OptimizeConstants(FirstConstant, Values.size());
-
- OptimizeTypes();
-
- // Now that we rearranged the type table, rebuild TypeMap.
- for (unsigned i = 0, e = Types.size(); i != e; ++i)
- TypeMap[Types[i]] = i+1;
-}
-
-struct TypeAndDeps {
- const Type *Ty;
- unsigned NumDeps;
-};
-
-static int CompareByDeps(const void *a, const void *b) {
- const TypeAndDeps &ta = *(const TypeAndDeps*) a;
- const TypeAndDeps &tb = *(const TypeAndDeps*) b;
- return ta.NumDeps - tb.NumDeps;
-}
-
-static void VisitType(const Type *Ty, SmallPtrSet<const Type*, 16> &Visited,
- std::vector<const Type*> &Out) {
- if (Visited.count(Ty))
- return;
-
- Visited.insert(Ty);
-
- for (Type::subtype_iterator I2 = Ty->subtype_begin(),
- E2 = Ty->subtype_end(); I2 != E2; ++I2) {
- const Type *InnerType = I2->get();
- VisitType(InnerType, Visited, Out);
- }
-
- Out.push_back(Ty);
}
-void ValueEnumerator::OptimizeTypes(void) {
- // If the types form a DAG, this will compute a topological sort and
- // no forward references will be needed when reading them in.
- // If there are cycles, this is a simple but reasonable heuristic for
- // the minimum feedback arc set problem.
- const unsigned NumTypes = Types.size();
- std::vector<TypeAndDeps> TypeDeps;
- TypeDeps.resize(NumTypes);
-
- for (unsigned I = 0; I < NumTypes; ++I) {
- const Type *Ty = Types[I];
- TypeDeps[I].Ty = Ty;
- TypeDeps[I].NumDeps = 0;
- }
-
- for (unsigned I = 0; I < NumTypes; ++I) {
- const Type *Ty = TypeDeps[I].Ty;
- for (Type::subtype_iterator I2 = Ty->subtype_begin(),
- E2 = Ty->subtype_end(); I2 != E2; ++I2) {
- const Type *InnerType = I2->get();
- unsigned InnerIndex = TypeMap.lookup(InnerType) - 1;
- TypeDeps[InnerIndex].NumDeps++;
- }
- }
- array_pod_sort(TypeDeps.begin(), TypeDeps.end(), CompareByDeps);
-
- SmallPtrSet<const Type*, 16> Visited;
- Types.clear();
- Types.reserve(NumTypes);
- for (unsigned I = 0; I < NumTypes; ++I) {
- VisitType(TypeDeps[I].Ty, Visited, Types);
- }
-}
unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const {
InstructionMapType::const_iterator I = InstructionMap.find(Inst);
- assert (I != InstructionMap.end() && "Instruction is not mapped!");
+ assert(I != InstructionMap.end() && "Instruction is not mapped!");
return I->second;
}
@@ -235,14 +165,6 @@ void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) {
}
-/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol
-/// table.
-void ValueEnumerator::EnumerateTypeSymbolTable(const TypeSymbolTable &TST) {
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI)
- EnumerateType(TI->second);
-}
-
/// EnumerateValueSymbolTable - Insert all of the values in the specified symbol
/// table into the values table.
void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) {
@@ -394,20 +316,40 @@ void ValueEnumerator::EnumerateValue(const Value *V) {
void ValueEnumerator::EnumerateType(const Type *Ty) {
- unsigned &TypeID = TypeMap[Ty];
+ unsigned *TypeID = &TypeMap[Ty];
// We've already seen this type.
- if (TypeID)
+ if (*TypeID)
return;
- // First time we saw this type, add it.
- Types.push_back(Ty);
- TypeID = Types.size();
-
- // Enumerate subtypes.
+ // If it is a non-anonymous struct, mark the type as being visited so that we
+ // don't recursively visit it. This is safe because we allow forward
+ // references of these in the bitcode reader.
+ if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (!STy->isAnonymous())
+ *TypeID = ~0U;
+
+ // Enumerate all of the subtypes before we enumerate this type. This ensures
+ // that the type will be enumerated in an order that can be directly built.
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I)
EnumerateType(*I);
+
+ // Refresh the TypeID pointer in case the table rehashed.
+ TypeID = &TypeMap[Ty];
+
+ // Check to see if we got the pointer another way. This can happen when
+ // enumerating recursive types that hit the base case deeper than they start.
+ //
+ // If this is actually a struct that we are treating as forward ref'able,
+ // then emit the definition now that all of its contents are available.
+ if (*TypeID && *TypeID != ~0U)
+ return;
+
+ // Add this type now that its contents are all happily enumerated.
+ Types.push_back(Ty);
+
+ *TypeID = Types.size();
}
// Enumerate the types for the specified value. If the value is a constant,
diff --git a/lib/Bitcode/Writer/ValueEnumerator.h b/lib/Bitcode/Writer/ValueEnumerator.h
index 1e42a26676..6617b60deb 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.h
+++ b/lib/Bitcode/Writer/ValueEnumerator.h
@@ -30,7 +30,6 @@ class Module;
class MDNode;
class NamedMDNode;
class AttrListPtr;
-class TypeSymbolTable;
class ValueSymbolTable;
class MDSymbolTable;
@@ -135,7 +134,6 @@ public:
private:
void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
- void OptimizeTypes();
void EnumerateMDNodeOperands(const MDNode *N);
void EnumerateMetadata(const Value *MD);
@@ -146,7 +144,6 @@ private:
void EnumerateOperandType(const Value *V);
void EnumerateAttributes(const AttrListPtr &PAL);
- void EnumerateTypeSymbolTable(const TypeSymbolTable &ST);
void EnumerateValueSymbolTable(const ValueSymbolTable &ST);
void EnumerateNamedMetadata(const Module *M);
};
diff --git a/lib/CodeGen/ShadowStackGC.cpp b/lib/CodeGen/ShadowStackGC.cpp
index ff58b221cb..d7c9adad7f 100644
--- a/lib/CodeGen/ShadowStackGC.cpp
+++ b/lib/CodeGen/ShadowStackGC.cpp
@@ -45,7 +45,8 @@ namespace {
/// StackEntryTy - Abstract type of a link in the shadow stack.
///
- const StructType *StackEntryTy;
+ StructType *StackEntryTy;
+ StructType *FrameMapTy;
/// Roots - GC roots in the current function. Each is a pair of the
/// intrinsic call and its corresponding alloca.
@@ -211,18 +212,14 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
};
Constant *DescriptorElts[] = {
- ConstantStruct::get(StructType::get(Int32Ty, Int32Ty, NULL), BaseElts),
+ ConstantStruct::get(FrameMapTy, BaseElts),
ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata)
};
- Constant *FrameMap =
- ConstantStruct::get(StructType::get(DescriptorElts[0]->getType(),
- DescriptorElts[1]->getType(), NULL),
- DescriptorElts);
-
- std::string TypeName("gc_map.");
- TypeName += utostr(NumMeta);
- F.getParent()->addTypeName(TypeName, FrameMap->getType());
+ Type *EltTys[] = { DescriptorElts[0]->getType(),DescriptorElts[1]->getType()};
+ StructType *STy = StructType::createNamed("gc_map."+utostr(NumMeta), EltTys);
+
+ Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts);
// FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems
// that, short of multithreaded LLVM, it should be safe; all that is
@@ -250,17 +247,12 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) {
// doInitialization creates the generic version of this type.
- std::vector<const Type*> EltTys;
+ std::vector<Type*> EltTys;
EltTys.push_back(StackEntryTy);
for (size_t I = 0; I != Roots.size(); I++)
EltTys.push_back(Roots[I].second->getAllocatedType());
- Type *Ty = StructType::get(F.getContext(), EltTys);
-
- std::string TypeName("gc_stackentry.");
- TypeName += F.getName();
- F.getParent()->addTypeName(TypeName, Ty);
-
- return Ty;
+
+ return StructType::createNamed("gc_stackentry."+F.getName().str(), EltTys);
}
/// doInitialization - If this module uses the GC intrinsics, find them now. If
@@ -271,13 +263,12 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
// int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots.
// void *Meta[]; // May be absent for roots without metadata.
// };
- std::vector<const Type*> EltTys;
+ std::vector<Type*> EltTys;
// 32 bits is ok up to a 32GB stack frame. :)
EltTys.push_back(Type::getInt32Ty(M.getContext()));
// Specifies length of variable length array.
EltTys.push_back(Type::getInt32Ty(M.getContext()));
- StructType *FrameMapTy = StructType::get(M.getContext(), EltTys);
- M.addTypeName("gc_map", FrameMapTy);
+ FrameMapTy = StructType::createNamed("gc_map", EltTys);
PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
// struct StackEntry {
@@ -285,18 +276,14 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
// FrameMap *Map; // Pointer to constant FrameMap.
// void *Roots[]; // Stack roots (in-place array, so we pretend).
// };
- OpaqueType *RecursiveTy = OpaqueType::get(M.getContext());
-
+
+ StackEntryTy = StructType::createNamed(M.getContext(), "gc_stackentry");
+
EltTys.clear();
- EltTys.push_back(PointerType::getUnqual(RecursiveTy));
+ EltTys.push_back(PointerType::getUnqual(StackEntryTy));
EltTys.push_back(FrameMapPtrTy);
- PATypeHolder LinkTyH = StructType::get(M.getContext(), EltTys);
-
- RecursiveTy->refineAbstractTypeTo(LinkTyH.get());
- StackEntryTy = cast<StructType>(LinkTyH.get());
+ StackEntryTy->setBody(EltTys);
const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
- M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from
- // a FunctionPass?
// Get the root chain if it already exists.
Head = M.getGlobalVariable("llvm_gc_root_chain");
@@ -403,7 +390,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead");
Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, StackEntry,
0,1,"gc_frame.map");
- AtEntry.CreateStore(FrameMap, EntryMapPtr);
+ AtEntry.CreateStore(FrameMap, EntryMapPtr);
// After all the allocas...
for (unsigned I = 0, E = Roots.size(); I != E; ++I) {
diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
index fe1f7fc938..f7e2a4df95 100644
--- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
+++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
@@ -78,7 +78,6 @@ static char getTypeID(const Type *Ty) {
case Type::FunctionTyID:return 'M';
case Type::StructTyID: return 'T';
case Type::ArrayTyID: return 'A';
- case Type::OpaqueTyID: return 'O';
default: return 'U';
}
}
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index f372db2403..d77062772e 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -9,337 +9,404 @@
//
// This file implements the LLVM module linker.
//
-// Specifically, this:
-// * Merges global variables between the two modules
-// * Uninit + Uninit = Init, Init + Uninit = Init, Init + Init = Error if !=
-// * Merges functions between two modules
-//
//===----------------------------------------------------------------------===//
#include "llvm/Linker.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/ValueSymbolTable.h"
-#include "llvm/Instructions.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
-#include "llvm/ADT/DenseMap.h"
using namespace llvm;
-// Error - Simple wrapper function to conditionally assign to E and return true.
-// This just makes error return conditions a little bit simpler...
-static inline bool Error(std::string *E, const Twine &Message) {
- if (E) *E = Message.str();
- return true;
-}
-
-// Function: ResolveTypes()
-//
-// Description:
-// Attempt to link the two specified types together.
-//
-// Inputs:
-// DestTy - The type to which we wish to resolve.
-// SrcTy - The original type which we want to resolve.
-//
-// Outputs:
-// DestST - The symbol table in which the new type should be placed.
-//
-// Return value:
-// true - There is an error and the types cannot yet be linked.
-// false - No errors.
-//
-static bool ResolveTypes(const Type *DestTy, const Type *SrcTy) {
- if (DestTy == SrcTy) return false; // If already equal, noop
- assert(DestTy && SrcTy && "Can't handle null types");
-
- if (const OpaqueType *OT = dyn_cast<OpaqueType>(DestTy)) {
- // Type _is_ in module, just opaque...
- const_cast<OpaqueType*>(OT)->refineAbstractTypeTo(SrcTy);
- } else if (const OpaqueType *OT = dyn_cast<OpaqueType>(SrcTy)) {
- const_cast<OpaqueType*>(OT)->refineAbstractTypeTo(DestTy);
- } else {
- return true; // Cannot link types... not-equal and neither is opaque.
- }
- return false;
-}
+//===----------------------------------------------------------------------===//
+// TypeMap implementation.
+//===----------------------------------------------------------------------===//
-/// LinkerTypeMap - This implements a map of types that is stable
-/// even if types are resolved/refined to other types. This is not a general
-/// purpose map, it is specific to the linker's use.
namespace {
-class LinkerTypeMap : public AbstractTypeUser {
- typedef DenseMap<const Type*, PATypeHolder> TheMapTy;
- TheMapTy TheMap;
-
- LinkerTypeMap(const LinkerTypeMap&); // DO NOT IMPLEMENT
- void operator=(const LinkerTypeMap&); // DO NOT IMPLEMENT
+class TypeMapTy : public ValueMapTypeRemapper {
+ /// MappedTypes - This is a mapping from a source type to a destination type
+ /// to use.
+ DenseMap<Type*, Type*> MappedTypes;
+
+ /// SpeculativeTypes - When checking to see if two subgraphs are isomorphic,
+ /// we speculatively add types to MappedTypes, but keep track of them here in
+ /// case we need to roll back.
+ SmallVector<Type*, 16> SpeculativeTypes;
+
+ /// DefinitionsToResolve - This is a list of non-opaque structs in the source
+ /// module that are mapped to an opaque struct in the destination module.
+ SmallVector<StructType*, 16> DefinitionsToResolve;
public:
- LinkerTypeMap() {}
- ~LinkerTypeMap() {
- for (DenseMap<const Type*, PATypeHolder>::iterator I = TheMap.begin(),
- E = TheMap.end(); I != E; ++I)
- I->first->removeAbstractTypeUser(this);
- }
-
- /// lookup - Return the value for the specified type or null if it doesn't
- /// exist.
- const Type *lookup(const Type *Ty) const {
- TheMapTy::const_iterator I = TheMap.find(Ty);
- if (I != TheMap.end()) return I->second;
- return 0;
- }
-
- /// insert - This returns true if the pointer was new to the set, false if it
- /// was already in the set.
- bool insert(const Type *Src, const Type *Dst) {
- if (!TheMap.insert(std::make_pair(Src, PATypeHolder(Dst))).second)
- return false; // Already in map.
- if (Src->isAbstract())
- Src->addAbstractTypeUser(this);
- return true;
- }
-
-protected:
- /// refineAbstractType - The callback method invoked when an abstract type is
- /// resolved to another type. An object must override this method to update
- /// its internal state to reference NewType instead of OldType.
- ///
- virtual void refineAbstractType(const DerivedType *OldTy,
- const Type *NewTy) {
- TheMapTy::iterator I = TheMap.find(OldTy);
- const Type *DstTy = I->second;
-
- TheMap.erase(I);
- if (OldTy->isAbstract())
- OldTy->removeAbstractTypeUser(this);
-
- // Don't reinsert into the map if the key is concrete now.
- if (NewTy->isAbstract())
- insert(NewTy, DstTy);
+
+ /// addTypeMapping - Indicate that the specified type in the destination
+ /// module is conceptually equivalent to the specified type in the source
+ /// module.
+ void addTypeMapping(Type *DstTy, Type *SrcTy);
+
+ /// linkDefinedTypeBodies - Produce a body for an opaque type in the dest
+ /// module from a type definition in the source module.
+ void linkDefinedTypeBodies();
+
+ /// get - Return the mapped type to use for the specified input type from the
+ /// source module.
+ Type *get(Type *SrcTy);
+
+ FunctionType *get(FunctionType *T) {return cast<FunctionType>(get((Type*)T));}
+
+private:
+ Type *getImpl(Type *T);
+ /// remapType - Implement the ValueMapTypeRemapper interface.
+ Type *remapType(Type *SrcTy) {
+ return get(SrcTy);
}
+
+ bool areTypesIsomorphic(Type *DstTy, Type *SrcTy);
+};
+}
- /// The other case which AbstractTypeUsers must be aware of is when a type
- /// makes the transition from being abstract (where it has clients on it's
- /// AbstractTypeUsers list) to concrete (where it does not). This method
- /// notifies ATU's when this occurs for a type.
- virtual void typeBecameConcrete(const DerivedType *AbsTy) {
- TheMap.erase(AbsTy);
- AbsTy->removeAbstractTypeUser(this);
+void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) {
+ Type *&Entry = MappedTypes[SrcTy];
+ if (Entry) return;
+
+ if (DstTy == SrcTy) {
+ Entry = DstTy;
+ return;
}
-
- // for debugging...
- virtual void dump() const {
- dbgs() << "AbstractTypeSet!\n";
+
+ // Check to see if these types are recursively isomorphic and establish a
+ // mapping between them if so.
+ if (!areTypesIsomorphic(DstTy, SrcTy)) {
+ // Oops, they aren't isomorphic. Just discard this request by rolling out
+ // any speculative mappings we've established.
+ for (unsigned i = 0, e = SpeculativeTypes.size(); i != e; ++i)
+ MappedTypes.erase(SpeculativeTypes[i]);
}
-};
+ SpeculativeTypes.clear();
}
-
-// RecursiveResolveTypes - This is just like ResolveTypes, except that it
-// recurses down into derived types, merging the used types if the parent types
-// are compatible.
-static bool RecursiveResolveTypesI(const Type *DstTy, const Type *SrcTy,
- LinkerTypeMap &Pointers) {
- if (DstTy == SrcTy) return false; // If already equal, noop
-
- // If we found our opaque type, resolve it now!
- if (DstTy->isOpaqueTy() || SrcTy->isOpaqueTy())
- return ResolveTypes(DstTy, SrcTy);
-
- // Two types cannot be resolved together if they are of different primitive
- // type. For example, we cannot resolve an int to a float.
- if (DstTy->getTypeID() != SrcTy->getTypeID()) return true;
-
- // If neither type is abstract, then they really are just different types.
- if (!DstTy->isAbstract() && !SrcTy->isAbstract())
+/// areTypesIsomorphic - Recursively walk this pair of types, returning true
+/// if they are isomorphic, false if they are not.
+bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) {
+ // Two types with differing kinds are clearly not isomorphic.
+ if (DstTy->getTypeID() != SrcTy->getTypeID()) return false;
+
+ // If we have an entry in the MappedTypes table, then we have our answer.
+ Type *&Entry = MappedTypes[SrcTy];
+ if (Entry)
+ return Entry == DstTy;
+
+ // Two identical types are clearly isomorphic. Remember this
+ // non-speculatively.
+ if (DstTy == SrcTy) {
+ Entry = DstTy;
return true;
-
- // Otherwise, resolve the used type used by this derived type...
- switch (DstTy->getTypeID()) {
- default:
- return true;
- case Type::FunctionTyID: {
- const FunctionType *DstFT = cast<FunctionType>(DstTy);
- const FunctionType *SrcFT = cast<FunctionType>(SrcTy);
- if (DstFT->isVarArg() != SrcFT->isVarArg() ||
- DstFT->getNumContainedTypes() != SrcFT->getNumContainedTypes())
- return true;
-
- // Use TypeHolder's so recursive resolution won't break us.
- PATypeHolder ST(SrcFT), DT(DstFT);
- for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) {
- const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i);
- if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers))
- return true;
- }
- return false;
}
- case Type::StructTyID: {
- const StructType *DstST = cast<StructType>(DstTy);
- const StructType *SrcST = cast<StructType>(SrcTy);
- if (DstST->getNumContainedTypes() != SrcST->getNumContainedTypes())
+
+ // Okay, we have two types with identical kinds that we haven't seen before.
+
+ // If this is an opaque struct type, special case it.
+ if (StructType *SSTy = dyn_cast<StructType>(SrcTy)) {
+ // Mapping an opaque type to any struct, just keep the dest struct.
+ if (SSTy->isOpaque()) {
+ Entry = DstTy;
+ SpeculativeTypes.push_back(SrcTy);
return true;
+ }
- PATypeHolder ST(SrcST), DT(DstST);
- for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) {
- const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i);
- if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers))
- return true;
+ // Mapping a non-opaque source type to an opaque dest. Keep the dest, but
+ // fill it in later. This doesn't need to be speculative.
+ if (cast<StructType>(DstTy)->isOpaque()) {
+ Entry = DstTy;
+ DefinitionsToResolve.push_back(SSTy);
+ return true;
}
- return false;
- }
- case Type::ArrayTyID: {
- const ArrayType *DAT = cast<ArrayType>(DstTy);
- const ArrayType *SAT = cast<ArrayType>(SrcTy);
- if (DAT->getNumElements() != SAT->getNumElements()) return true;
- return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(),
- Pointers);
}
- case Type::VectorTyID: {
- const VectorType *DVT = cast<VectorType>(DstTy);
- const VectorType *SVT = cast<VectorType>(SrcTy);
- if (DVT->getNumElements() != SVT->getNumElements()) return true;
- return RecursiveResolveTypesI(DVT->getElementType(), SVT->getElementType(),
- Pointers);
+
+ // If the number of subtypes disagree between the two types, then we fail.
+ if (SrcTy->getNumContainedTypes() != DstTy->getNumContainedTypes())
+ return false;
+
+ // Fail if any of the extra properties (e.g. array size) of the type disagree.
+ if (isa<IntegerType>(DstTy))
+ return false; // bitwidth disagrees.
+ if (PointerType *PT = dyn_cast<PointerType>(DstTy)) {
+ if (PT->getAddressSpace() != cast<PointerType>(SrcTy)->getAddressSpace())
+ return false;
+ } else if (FunctionType *FT = dyn_cast<FunctionType>(DstTy)) {
+ if (FT->isVarArg() != cast<FunctionType>(SrcTy)->isVarArg())
+ return false;
+ } else if (StructType *DSTy = dyn_cast<StructType>(DstTy)) {
+ StructType *SSTy = cast<StructType>(SrcTy);
+ if (DSTy->isAnonymous() != SSTy->isAnonymous() ||
+ DSTy->isPacked() != SSTy->isPacked())
+ return false;
+ } else if (ArrayType *DATy = dyn_cast<ArrayType>(DstTy)) {
+ if (DATy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements())
+ return false;
+ } else if (VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
+ if (DVTy->getNumElements() != cast<ArrayType>(SrcTy)->getNumElements())
+ return false;
}
- case Type::PointerTyID: {
- const PointerType *DstPT = cast<PointerType>(DstTy);
- const PointerType *SrcPT = cast<PointerType>(SrcTy);
- if (DstPT->getAddressSpace() != SrcPT->getAddressSpace())
- return true;
+ // Otherwise, we speculate that these two types will line up and recursively
+ // check the subelements.
+ Entry = DstTy;
+ SpeculativeTypes.push_back(SrcTy);
+
+ for (unsigned i = 0, e = SrcTy->getNumContainedTypes(); i != e; ++i)
+ if (!areTypesIsomorphic(DstTy->getContainedType(i),
+ SrcTy->getContainedType(i)))
+ return false;
+
+ // If everything seems to have lined up, then everything is great.
+ return true;
+}
- // If this is a pointer type, check to see if we have already seen it. If
- // so, we are in a recursive branch. Cut off the search now. We cannot use
- // an associative container for this search, because the type pointers (keys
- // in the container) change whenever types get resolved.
- if (SrcPT->isAbstract())
- if (const Type *ExistingDestTy = Pointers.lookup(SrcPT))
- return ExistingDestTy != DstPT;
-
- if (DstPT->isAbstract())
- if (const Type *ExistingSrcTy = Pointers.lookup(DstPT))
- return ExistingSrcTy != SrcPT;
- // Otherwise, add the current pointers to the vector to stop recursion on
- // this pair.
- if (DstPT->isAbstract())
- Pointers.insert(DstPT, SrcPT);
- if (SrcPT->isAbstract())
- Pointers.insert(SrcPT, DstPT);
-
- return RecursiveResolveTypesI(DstPT->getElementType(),
- SrcPT->getElementType(), Pointers);
- }
+/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest
+/// module from a type definition in the source module.
+void TypeMapTy::linkDefinedTypeBodies() {
+ SmallVector<Type*, 16> Elements;
+ SmallString<16> TmpName;
+
+ // Note that processing entries in this loop (calling 'get') can add new
+ // entries to the DefinitionsToResolve vector.
+ while (!DefinitionsToResolve.empty()) {
+ StructType *SrcSTy = DefinitionsToResolve.pop_back_val();
+ StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]);
+
+ // TypeMap is a many-to-one mapping, if there were multiple types that
+ // provide a body for DstSTy then previous iterations of this loop may have
+ // already handled it. Just ignore this case.
+ if (!DstSTy->isOpaque()) continue;
+ assert(!SrcSTy->isOpaque() && "Not resolving a definition?");
+
+ // Map the body of the source type over to a new body for the dest type.
+ Elements.resize(SrcSTy->getNumElements());
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+ Elements[i] = getImpl(SrcSTy->getElementType(i));
+
+ DstSTy->setBody(Elements, SrcSTy->isPacked());
+
+ // If DstSTy has no name or has a longer name than STy, then viciously steal
+ // STy's name.
+ if (!SrcSTy->hasName()) continue;
+ StringRef SrcName = SrcSTy->getName();
+
+ if (!DstSTy->hasName() || DstSTy->getName().size() > SrcName.size()) {
+ TmpName.insert(TmpName.end(), SrcName.begin(), SrcName.end());
+ SrcSTy->setName("");
+ DstSTy->setName(TmpName.str());
+ TmpName.clear();
+ }
}
}
-static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy) {
- LinkerTypeMap PointerTypes;
- return RecursiveResolveTypesI(DestTy, SrcTy, PointerTypes);
-}
+/// get - Return the mapped type to use for the specified input type from the
+/// source module.
+Type *TypeMapTy::get(Type *Ty) {
+ Type *Result = getImpl(Ty);
+
+ // If this caused a reference to any struct type, resolve it before returning.
+ if (!DefinitionsToResolve.empty())
+ linkDefinedTypeBodies();
+ return Result;
+}
-// LinkTypes - Go through the symbol table of the Src module and see if any
-// types are named in the src module that are not named in the Dst module.
-// Make sure there are no type name conflicts.
-static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) {
- TypeSymbolTable *DestST = &Dest->getTypeSymbolTable();
- const TypeSymbolTable *SrcST = &Src->getTypeSymbolTable();
-
- // Look for a type plane for Type's...
- TypeSymbolTable::const_iterator TI = SrcST->begin();
- TypeSymbolTable::const_iterator TE = SrcST->end();
- if (TI == TE) return false; // No named types, do nothing.
-
- // Some types cannot be resolved immediately because they depend on other
- // types being resolved to each other first. This contains a list of types we
- // are waiting to recheck.
- std::vector<std::string> DelayedTypesToResolve;
-
- for ( ; TI != TE; ++TI ) {
- const std::string &Name = TI->first;
- const Type *RHS = TI->second;
-
- // Check to see if this type name is already in the dest module.
- Type *Entry = DestST->lookup(Name);
-
- // If the name is just in the source module, bring it over to the dest.
- if (Entry == 0) {
- if (!Name.empty())
- DestST->insert(Name, const_cast<Type*>(RHS));
- } else if (ResolveTypes(Entry, RHS)) {
- // They look different, save the types 'till later to resolve.
- DelayedTypesToResolve.push_back(Name);
+/// getImpl - This is the recursive version of get().
+Type *TypeMapTy::getImpl(Type *Ty) {
+ // If we already have an entry for this type, return it.
+ Type **Entry = &MappedTypes[Ty];
+ if (*Entry) return *Entry;
+
+ // If this is not a named struct type, then just map all of the elements and
+ // then rebuild the type from inside out.
+ if (!isa<StructType>(Ty) || cast<StructType>(Ty)->isAnonymous()) {
+ // If there are no element types to map, then the type is itself. This is
+ // true for the anonymous {} struct, things like 'float', integers, etc.
+ if (Ty->getNumContainedTypes() == 0)
+ return *Entry = Ty;
+
+ // Remap all of the elements, keeping track of whether any of them change.
+ bool AnyChange = false;
+ SmallVector<Type*, 4> ElementTypes;
+ ElementTypes.resize(Ty->getNumContainedTypes());
+ for (unsigned i = 0, e = Ty->getNumContainedTypes(); i != e; ++i) {
+ ElementTypes[i] = getImpl(Ty->getContainedType(i));
+ AnyChange |= ElementTypes[i] != Ty->getContainedType(i);
+ }
+
+ // If we found our type while recursively processing stuff, just use it.
+ Entry = &MappedTypes[Ty];
+ if (*Entry) return *Entry;
+
+ // If all of the element types mapped directly over, then the type is usable
+ // as-is.
+ if (!AnyChange)
+ return *Entry = Ty;
+
+ // Otherwise, rebuild a modified type.
+ switch (Ty->getTypeID()) {
+ default: assert(0 && "unknown derived type to remap");
+ case Type::ArrayTyID:
+ return *Entry = ArrayType::get(ElementTypes[0],
+ cast<ArrayType>(Ty)->getNumElements());
+ case Type::VectorTyID:
+ return *Entry = VectorType::get(ElementTypes[0],
+ cast<VectorType>(Ty)->getNumElements());
+ case Type::PointerTyID:
+ return *Entry = PointerType::get(ElementTypes[0],
+ cast<PointerType>(Ty)->getAddressSpace());
+ case Type::FunctionTyID:
+ return *Entry = FunctionType::get(ElementTypes[0],
+ ArrayRef<Type*>(ElementTypes).slice(1),
+ cast<FunctionType>(Ty)->isVarArg());
+ case Type::StructTyID:
+ // Note that this is only reached for anonymous structs.
+ return *Entry = StructType::get(Ty->getContext(), ElementTypes,
+ cast<StructType>(Ty)->isPacked());
}
}
- // Iteratively resolve types while we can...
- while (!DelayedTypesToResolve.empty()) {
- // Loop over all of the types, attempting to resolve them if possible...
- unsigned OldSize = DelayedTypesToResolve.size();
-
- // Try direct resolution by name...
- for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) {
- const std::string &Name = DelayedTypesToResolve[i];
- Type *T1 = SrcST->lookup(Name);
- Type *T2 = DestST->lookup(Name);
- if (!ResolveTypes(T2, T1)) {
- // We are making progress!
- DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i);
- --i;
- }
- }
+ // Otherwise, this is an unmapped named struct. If the struct can be directly
+ // mapped over, just use it as-is. This happens in a case when the linked-in
+ // module has something like:
+ // %T = type {%T*, i32}
+ // @GV = global %T* null
+ // where T does not exist at all in the destination module.
+ //
+ // The other case we watch for is when the type is not in the destination
+ // module, but that it has to be rebuilt because it refers to something that
+ // is already mapped. For example, if the destination module has:
+ // %A = type { i32 }
+ // and the source module has something like
+ // %A' = type { i32 }
+ // %B = type { %A'* }
+ // @GV = global %B* null
+ // then we want to create a new type: "%B = type { %A*}" and have it take the
+ // pristine "%B" name from the source module.
+ //
+ // To determine which case this is, we have to recursively walk the type graph
+ // speculating that we'll be able to reuse it unmodified. Only if this is
+ // safe would we map the entire thing over. Because this is an optimization,
+ // and is not required for the prettiness of the linked module, we just skip
+ // it and always rebuild a type here.
+ StructType *STy = cast<StructType>(Ty);
+
+ // If the type is opaque, we can just use it directly.
+ if (STy->isOpaque())
+ return *Entry = STy;
+
+ // Otherwise we create a new type and resolve its body later. This will be
+ // resolved by the top level of get().
+ DefinitionsToResolve.push_back(STy);
+ return *Entry = StructType::createNamed(STy->getContext(), "");
+}
- // Did we not eliminate any types?
- if (DelayedTypesToResolve.size() == OldSize) {
- // Attempt to resolve subelements of types. This allows us to merge these
- // two types: { int* } and { opaque* }
- for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) {
- const std::string &Name = DelayedTypesToResolve[i];
- if (!RecursiveResolveTypes(SrcST->lookup(Name), DestST->lookup(Name))) {
- // We are making progress!
- DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i);
-
- // Go back to the main loop, perhaps we can resolve directly by name
- // now...
- break;
- }
- }
- // If we STILL cannot resolve the types, then there is something wrong.
- if (DelayedTypesToResolve.size() == OldSize) {
- // Remove the symbol name from the destination.
- DelayedTypesToResolve.pop_back();
- }
- }
- }
+//===----------------------------------------------------------------------===//
+// ModuleLinker implementation.
+//===----------------------------------------------------------------------===//
- return false;
+namespace {
+ /// ModuleLinker - This is an implementation class for the LinkModules
+ /// function, which is the entrypoint for this file.
+ class ModuleLinker {
+ Module *DstM, *SrcM;
+
+ TypeMapTy TypeMap;
+
+ /// ValueMap - Mapping of values from what they used to be in Src, to what
+ /// they are now in DstM. ValueToValueMapTy is a ValueMap, which involves
+ /// some overhead due to the use of Value handles which the Linker doesn't
+ /// actually need, but this allows us to reuse the ValueMapper code.
+ ValueToValueMapTy ValueMap;
+
+ struct AppendingVarInfo {
+ GlobalVariable *NewGV; // New aggregate global in dest module.
+ Constant *DstInit; // Old initializer from dest module.
+ Constant *SrcInit; // Old initializer from src module.
+ };
+
+ std::vector<AppendingVarInfo> AppendingVars;
+
+ public:
+ std::string ErrorMsg;
+
+ ModuleLinker(Module *dstM, Module *srcM) : DstM(dstM), SrcM(srcM) { }
+
+ bool run();
+
+ private:
+ /// emitError - Helper method for setting a message and returning an error
+ /// code.
+ bool emitError(const Twine &Message) {
+ ErrorMsg = Message.str();
+ return true;
+ }
+
+ /// getLinkageResult - This analyzes the two global values and determines
+ /// what the result will look like in the destination module.
+ bool getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
+ GlobalValue::LinkageTypes &LT, bool &LinkFromSrc);
+
+ /// getLinkedToGlobal - Given a global in the source module, return the
+ /// global in the destination module that is being linked to, if any.
+ GlobalValue *getLinkedToGlobal(GlobalValue *SrcGV) {
+ // If the source has no name it can't link. If it has local linkage,
+ // there is no name match-up going on.
+ if (!SrcGV->hasName() || SrcGV->hasLocalLinkage())
+ return 0;
+
+ // Otherwise see if we have a match in the destination module's symtab.
+ GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName());
+ if (DGV == 0) return 0;
+
+ // If we found a global with the same name in the dest module, but it has
+ // internal linkage, we are really not doing any linkage here.
+ if (DGV->hasLocalLinkage())
+ return 0;
+
+ // Otherwise, we do in fact link to the destination global.
+ return DGV;
+ }
+
+ void computeTypeMapping();
+
+ bool linkAppendingVarProto(GlobalVariable *DstGV, GlobalVariable *SrcGV);
+ bool linkGlobalProto(GlobalVariable *SrcGV);
+ bool linkFunctionProto(Function *SrcF);
+ bool linkAliasProto(GlobalAlias *SrcA);
+
+ void linkAppendingVarInit(const AppendingVarInfo &AVI);
+ void linkGlobalInits();
+ void linkFunctionBody(Function *Dst, Function *Src);
+ void linkAliasBodies();
+ void linkNamedMDNodes();
+ };
}
-/// ForceRenaming - The LLVM SymbolTable class autorenames globals that conflict
+
+
+/// forceRenaming - The LLVM SymbolTable class autorenames globals that conflict
/// in the symbol table. This is good for all clients except for us. Go
/// through the trouble to force this back.
-static void ForceRenaming(GlobalValue *GV, const std::string &Name) {
- assert(GV->getName() != Name && "Can't force rename to self");
- ValueSymbolTable &ST = GV->getParent()->getValueSymbolTable();
+static void forceRenaming(GlobalValue *GV, StringRef Name) {
+ // If the global doesn't force its name or if it already has the right name,
+ // there is nothing for us to do.
+ if (GV->hasLocalLinkage() || GV->getName() == Name)
+ return;
+
+ Module *M = GV->getParent();
// If there is a conflict, rename the conflict.
- if (GlobalValue *ConflictGV = cast_or_null<GlobalValue>(ST.lookup(Name))) {
- assert(ConflictGV->hasLocalLinkage() &&
- "Not conflicting with a static global, should link instead!");
+ if (GlobalValue *ConflictGV = M->getNamedValue(Name)) {
GV->takeName(ConflictGV);
ConflictGV->setName(Name); // This will cause ConflictGV to get renamed
- assert(ConflictGV->getName() != Name && "ForceRenaming didn't work");
+ assert(ConflictGV->getName() != Name && "forceRenaming didn't work");
} else {
GV->setName(Name); // Force the name back
}
@@ -352,30 +419,35 @@ static void CopyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) {
unsigned Alignment = std::max(DestGV->getAlignment(), SrcGV->getAlignment());
DestGV->copyAttributesFrom(SrcGV);
DestGV->setAlignment(Alignment);
+
+ forceRenaming(DestGV, SrcGV->getName());
}
-/// GetLinkageResult - This analyzes the two global values and determines what
+/// getLinkageResult - This analyzes the two global values and determines what
/// the result will look like in the destination module. In particular, it
/// computes the resultant linkage type, computes whether the global in the
/// source should be copied over to the destination (replacing the existing
/// one), and computes whether this linkage is an error or not. It also performs
/// visibility checks: we cannot link together two symbols with different
/// visibilities.
-static bool GetLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
- GlobalValue::LinkageTypes &LT, bool &LinkFromSrc,
- std::string *Err) {
- assert((!Dest || !Src->hasLocalLinkage()) &&
+bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
+ GlobalValue::LinkageTypes &LT,
+ bool &LinkFromSrc) {
+ assert(Dest && "Must have two globals being queried");
+ assert(!Src->hasLocalLinkage() &&
"If Src has internal linkage, Dest shouldn't be set!");
- if (!Dest) {
- // Linking something to nothing.
- LinkFromSrc = true;
- LT = Src->getLinkage();
- } else if (Src->isDeclaration()) {
+
+ // FIXME: GlobalAlias::isDeclaration is broken, should always be
+ // false.
+ bool SrcIsDeclaration = Src->isDeclaration() && !isa<GlobalAlias>(Src);
+ bool DestIsDeclaration = Dest->isDeclaration() && !isa<GlobalAlias>(Dest);
+
+ if (SrcIsDeclaration) {
// If Src is external or if both Src & Dest are external.. Just link the
// external globals, we aren't adding anything.
if (Src->hasDLLImportLinkage()) {
// If one of GVs has DLLImport linkage, result should be dllimport'ed.
- if (Dest->isDeclaration()) {
+ if (DestIsDeclaration) {
LinkFromSrc = true;
LT = Src->getLinkage();
}
@@ -387,16 +459,10 @@ static bool GetLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
LinkFromSrc = false;
LT = Dest->getLinkage();
}
- } else if (Dest->isDeclaration() && !Dest->hasDLLImportLinkage()) {
+ } else if (DestIsDeclaration && !Dest->hasDLLImportLinkage()) {
// If Dest is external but Src is not:
LinkFromSrc = true;
LT = Src->getLinkage();
- } else if (Src->hasAppendingLinkage() || Dest->hasAppendingLinkage()) {
- if (Src->getLinkage() != Dest->getLinkage())
- return Error(Err, "Linking globals named '" + Src->getName() +
- "': can only link appending global with another appending global!");
- LinkFromSrc = true; // Special cased.
- LT = Src->getLinkage();
} else if (Src->isWeakForLinker()) {
// At this point we know that Dest has LinkOnce, External*, Weak, Common,
// or DLL* linkage.
@@ -420,883 +486,485 @@ static bool GetLinkageResult(GlobalValue *Dest, const GlobalValue *Src,
LT = GlobalValue::ExternalLinkage;
}
} else {
- assert((Dest->hasExternalLinkage() ||
- Dest->hasDLLImportLinkage() ||
- Dest->hasDLLExportLinkage() ||
- Dest->hasExternalWeakLinkage()) &&
- (Src->hasExternalLinkage() ||
- Src->hasDLLImportLinkage() ||
- Src->hasDLLExportLinkage() ||
- Src->hasExternalWeakLinkage()) &&
+ assert((Dest->hasExternalLinkage() || Dest->hasDLLImportLinkage() ||
+ Dest->hasDLLExportLinkage() || Dest->hasExternalWeakLinkage()) &&
+ (Src->hasExternalLinkage() || Src->hasDLLImportLinkage() ||
+ Src->hasDLLExportLinkage() || Src->hasExternalWeakLinkage()) &&
"Unexpected linkage type!");
- return Error(Err, "Linking globals named '" + Src->getName() +
+ return emitError("Linking globals named '" + Src->getName() +
"': symbol multiply defined!");
}
// Check visibility
- if (Dest && Src->getVisibility() != Dest->getVisibility() &&
- !Src->isDeclaration() && !Dest->isDeclaration() &&
+ if (Src->getVisibility() != Dest->getVisibility() &&
+ !SrcIsDeclaration && !DestIsDeclaration &&
!Src->hasAvailableExternallyLinkage() &&
!Dest->hasAvailableExternallyLinkage())
- return Error(Err, "Linking globals named '" + Src->getName() +
+ return emitError("Linking globals named '" + Src->getName() +
"': symbols have different visibilities!");
return false;
}
-// Insert all of the named mdnoes in Src into the Dest module.
-static void LinkNamedMDNodes(Module *Dest, Module *Src,
- ValueToValueMapTy &ValueMap) {
- for (Module::const_named_metadata_iterator I = Src->named_metadata_begin(),
- E = Src->named_metadata_end(); I != E; ++I) {
- const NamedMDNode *SrcNMD = I;
- NamedMDNode *DestNMD = Dest->getOrInsertNamedMetadata(SrcNMD->getName());
- // Add Src elements into Dest node.
- for (unsigned i = 0, e = SrcNMD->getNumOperands(); i != e; ++i)
- DestNMD->addOperand(cast<MDNode>(MapValue(SrcNMD->getOperand(i),
- ValueMap)));
+/// computeTypeMapping - Loop over all of the linked values to compute type
+/// mappings. For example, if we link "extern Foo *x" and "Foo *x = NULL", then
+/// we have two struct types 'Foo' but one got renamed when the module was
+/// loaded into the same LLVMContext.
+void ModuleLinker::computeTypeMapping() {
+ // Incorporate globals.
+ for (Module::global_iterator I = SrcM->global_begin(),
+ E = SrcM->global_end(); I != E; ++I) {
+ GlobalValue *DGV = getLinkedToGlobal(I);
+ if (DGV == 0) continue;
+
+ if (!DGV->hasAppendingLinkage() || !I->hasAppendingLinkage()) {
+ TypeMap.addTypeMapping(DGV->getType(), I->getType());
+ continue;
+ }
+
+ // Unify the element type of appending arrays.
+ ArrayType *DAT = cast<ArrayType>(DGV->getType()->getElementType());
+ ArrayType *SAT = cast<ArrayType>(I->getType()->getElementType());
+ TypeMap.addTypeMapping(DAT->getElementType(), SAT->getElementType());
}
+
+ // Incorporate functions.
+ for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I) {
+ if (GlobalValue *DGV = getLinkedToGlobal(I))
+ TypeMap.addTypeMapping(DGV->getType(), I->getType());
+ }
+
+ // Don't bother incorporating aliases, they aren't generally typed well.
+
+ // Now that we have discovered all of the type equivalences, get a body for
+ // any 'opaque' types in the dest module that are now resolved.
+ TypeMap.linkDefinedTypeBodies();
}
-// LinkGlobals - Loop through the global variables in the src module and merge
-// them into the dest module.
-static bool LinkGlobals(Module *Dest, const Module *Src,
- ValueToValueMapTy &ValueMap,
- std::multimap<std::string, GlobalVariable *> &AppendingVars,
- std::string *Err) {
- ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable();
-
- // Loop over all of the globals in the src module, mapping them over as we go
- for (Module::const_global_iterator I = Src->global_begin(),
- E = Src->global_end(); I != E; ++I) {
- const GlobalVariable *SGV = I;
- GlobalValue *DGV = 0;
-
- // Check to see if may have to link the global with the global, alias or
- // function.
- if (SGV->hasName() && !SGV->hasLocalLinkage())
- DGV = cast_or_null<GlobalValue>(DestSymTab.lookup(SGV->getName()));
-
- // If we found a global with the same name in the dest module, but it has
- // internal linkage, we are really not doing any linkage here.
- if (DGV && DGV->hasLocalLinkage())
- DGV = 0;
-
- // If types don't agree due to opaque types, try to resolve them.
- if (DGV && DGV->getType() != SGV->getType())
- RecursiveResolveTypes(SGV->getType(), DGV->getType());
-
- assert((SGV->hasInitializer() || SGV->hasExternalWeakLinkage() ||
- SGV->hasExternalLinkage() || SGV->hasDLLImportLinkage()) &&
- "Global must either be external or have an initializer!");
+/// linkAppendingVarProto - If there were any appending global variables, link
+/// them together now. Return true on error.
+bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV,
+ GlobalVariable *SrcGV) {
+
+ if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage())
+ return emitError("Linking globals named '" + SrcGV->getName() +
+ "': can only link appending global with another appending global!");
+
+ ArrayType *DstTy = cast<ArrayType>(DstGV->getType()->getElementType());
+ ArrayType *SrcTy =
+ cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
+ Type *EltTy = DstTy->getElementType();
+
+ // Check to see that they two arrays agree on type.
+ if (EltTy != SrcTy->getElementType())
+ return emitError("Appending variables with different element types!");
+ if (DstGV->isConstant() != SrcGV->isConstant())
+ return emitError("Appending variables linked with different const'ness!");
+
+ if (DstGV->getAlignment() != SrcGV->getAlignment())
+ return emitError(
+ "Appending variables with different alignment need to be linked!");
+
+ if (DstGV->getVisibility() != SrcGV->getVisibility())
+ return emitError(
+ "Appending variables with different visibility need to be linked!");
+
+ if (DstGV->getSection() != SrcGV->getSection())
+ return emitError(
+ "Appending variables with different section name need to be linked!");
+
+ uint64_t NewSize = DstTy->getNumElements() + SrcTy->getNumElements();
+ ArrayType *NewType = ArrayType::get(EltTy, NewSize);
+
+ // Create the new global variable.
+ GlobalVariable *NG =
+ new GlobalVariable(*DstGV->getParent(), NewType, SrcGV->isConstant(),
+ DstGV->getLinkage(), /*init*/0, /*name*/"", DstGV,
+ DstGV->isThreadLocal(),
+ DstGV->getType()->getAddressSpace());
+
+ // Propagate alignment, visibility and section info.
+ CopyGVAttributes(NG, DstGV);
+
+ AppendingVarInfo AVI;
+ AVI.NewGV = NG;
+ AVI.DstInit = DstGV->getInitializer();
+ AVI.SrcInit = SrcGV->getInitializer();
+ AppendingVars.push_back(AVI);
+
+ // Replace any uses of the two global variables with uses of the new
+ // global.
+ ValueMap[SrcGV] = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType()));
+
+ DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
+ DstGV->eraseFromParent();
+
+ // Zap the initializer in the source variable so we don't try to link it.
+ SrcGV->setInitializer(0);
+ SrcGV->setLinkage(GlobalValue::ExternalLinkage);
+ return false;
+}
+/// linkGlobalProto - Loop through the global variables in the src module and
+/// merge them into the dest module.
+bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
+ GlobalValue *DGV = getLinkedToGlobal(SGV);
+
+ if (DGV) {
+ // Concatenation of appending linkage variables is magic and handled later.
+ if (DGV->hasAppendingLinkage() || SGV->hasAppendingLinkage())
+ return linkAppendingVarProto(cast<GlobalVariable>(DGV), SGV);
+
+ // Determine whether linkage of these two globals follows the source
+ // module's definition or the destination module's definition.
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
bool LinkFromSrc = false;
- if (GetLinkageResult(DGV, SGV, NewLinkage, LinkFromSrc, Err))
+ if (getLinkageResult(DGV, SGV, NewLinkage, LinkFromSrc))
return true;
- if (DGV == 0) {
- // No linking to be performed, simply create an identical version of the
- // symbol over in the dest module... the initializer will be filled in
- // later by LinkGlobalInits.
- GlobalVariable *NewDGV =
- new GlobalVariable(*Dest, SGV->getType()->getElementType(),
- SGV->isConstant(), SGV->getLinkage(), /*init*/0,
- SGV->getName(), 0, false,
- SGV->getType()->getAddressSpace());
- // Propagate alignment, visibility and section info.
- CopyGVAttributes(NewDGV, SGV);
- NewDGV->setUnnamedAddr(SGV->hasUnnamedAddr());
-
- // If the LLVM runtime renamed the global, but it is an externally visible
- // symbol, DGV must be an existing global with internal linkage. Rename
- // it.
- if (!NewDGV->hasLocalLinkage() && NewDGV->getName() != SGV->getName())
- ForceRenaming(NewDGV, SGV->getName());
-
+ // If we're not linking from the source, then keep the definition that we
+ // have.
+ if (!LinkFromSrc) {
+ // Special case for const propagation.
+ if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV))
+ if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
+ DGVar->setConstant(true);
+
+ // Set calculated linkage.
+ DGV->setLinkage(NewLinkage);
+
// Make sure to remember this mapping.
- ValueMap[SGV] = NewDGV;
-
- // Keep track that this is an appending variable.
- if (SGV->hasAppendingLinkage())
- AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV));
- continue;
- }
-
- bool HasUnnamedAddr = SGV->hasUnnamedAddr() && DGV->hasUnnamedAddr();
-
- // If the visibilities of the symbols disagree and the destination is a
- // prototype, take the visibility of its input.
- if (DGV->isDeclaration())
- DGV->setVisibility(SGV->getVisibility());
-
- if (DGV->hasAppendingLinkage()) {
- // No linking is performed yet. Just insert a new copy of the global, and
- // keep track of the fact that it is an appending variable in the
- // AppendingVars map. The name is cleared out so that no linkage is
- // performed.
- GlobalVariable *NewDGV =
- new GlobalVariable(*Dest, SGV->getType()->getElementType(),
- SGV->isConstant(), SGV->getLinkage(), /*init*/0,
- "", 0, false,
- SGV->getType()->getAddressSpace());
-
- // Set alignment allowing CopyGVAttributes merge it with alignment of SGV.
- NewDGV->setAlignment(DGV->getAlignment());
- // Propagate alignment, section and visibility info.
- CopyGVAttributes(NewDGV, SGV);
-
- // Make sure to remember this mapping...
- ValueMap[SGV] = NewDGV;
-
- // Keep track that this is an appending variable...
- AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV));
- continue;
+ ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType()));
+
+ // Destroy the source global's initializer (and convert it to a prototype)
+ // so that we don't attempt to copy it over when processing global
+ // initializers.
+ SGV->setInitializer(0);
+ SGV->setLinkage(GlobalValue::ExternalLinkage);
+ return false;
}
-
- if (LinkFromSrc) {
- if (isa<GlobalAlias>(DGV))
- return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
- "': symbol multiple defined");
-
- // If the types don't match, and if we are to link from the source, nuke
- // DGV and create a new one of the appropriate type. Note that the thing
- // we are replacing may be a function (if a prototype, weak, etc) or a
- // global variable.
- GlobalVariable *NewDGV =
- new GlobalVariable(*Dest, SGV->getType()->getElementType(),
- SGV->isConstant(), NewLinkage, /*init*/0,
- DGV->getName(), 0, false,
- SGV->getType()->getAddressSpace());
-
- // Set the unnamed_addr.
- NewDGV->setUnnamedAddr(HasUnnamedAddr);
-
- // Propagate alignment, section, and visibility info.
- CopyGVAttributes(NewDGV, SGV);
- DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV,
- DGV->getType()));
-
- // DGV will conflict with NewDGV because they both had the same
- // name. We must erase this now so ForceRenaming doesn't assert
- // because DGV might not have internal linkage.
- if (GlobalVariable *Var = dyn_cast<GlobalVariable>(DGV))
- Var->eraseFromParent();
- else
- cast<Function>(DGV)->eraseFromParent();
-
- // If the symbol table renamed the global, but it is an externally visible
- // symbol, DGV must be an existing global with internal linkage. Rename.
- if (NewDGV->getName() != SGV->getName() && !NewDGV->hasLocalLinkage())
- ForceRenaming(NewDGV, SGV->getName());
-
- // Inherit const as appropriate.
- NewDGV->setConstant(SGV->isConstant());
-
- // Make sure to remember this mapping.
- ValueMap[SGV] = NewDGV;
- continue;
- }
-
- // Not "link from source", keep the one in the DestModule and remap the
- // input onto it.
-
- // Special case for const propagation.
- if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV))
- if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant())
- DGVar->setConstant(true);
-
- // SGV is global, but DGV is alias.
- if (isa<GlobalAlias>(DGV)) {
- // The only valid mappings are:
- // - SGV is external declaration, which is effectively a no-op.
- // - SGV is weak, when we just need to throw SGV out.
- if (!SGV->isDeclaration() && !SGV->isWeakForLinker())
- return Error(Err, "Global-Alias Collision on '" + SGV->getName() +
- "': symbol multiple defined");
- }
-
- // Set calculated linkage and unnamed_addr
- DGV->setLinkage(NewLinkage);
- DGV->setUnnamedAddr(HasUnnamedAddr);
-
- // Make sure to remember this mapping...
- ValueMap[SGV] = ConstantExpr::getBitCast(DGV, SGV->getType());
}
- return false;
-}
-
-static GlobalValue::LinkageTypes
-CalculateAliasLinkage(const GlobalValue *SGV, const GlobalValue *DGV) {
- GlobalValue::LinkageTypes SL = SGV->getLinkage();
- GlobalValue::LinkageTypes DL = DGV->getLinkage();
- if (SL == GlobalValue::ExternalLinkage || DL == GlobalValue::ExternalLinkage)
- return GlobalValue::ExternalLinkage;
- else if (SL == GlobalValue::WeakAnyLinkage ||
- DL == GlobalValue::WeakAnyLinkage)
- return GlobalValue::WeakAnyLinkage;
- else if (SL == GlobalValue::WeakODRLinkage ||
- DL == GlobalValue::WeakODRLinkage)
- return GlobalValue::WeakODRLinkage;
- else if (SL == GlobalValue::InternalLinkage &&
- DL == GlobalValue::InternalLinkage)
- return GlobalValue::InternalLinkage;
- else if (SL == GlobalValue::LinkerPrivateLinkage &&
- DL == GlobalValue::LinkerPrivateLinkage)
- return GlobalValue::LinkerPrivateLinkage;
- else if (SL == GlobalValue::LinkerPrivateWeakLinkage &&
- DL == GlobalValue::LinkerPrivateWeakLinkage)
- return GlobalValue::LinkerPrivateWeakLinkage;
- else if (SL == GlobalValue::LinkerPrivateWeakDefAutoLinkage &&
- DL == GlobalValue::LinkerPrivateWeakDefAutoLinkage)
- return GlobalValue::LinkerPrivateWeakDefAutoLinkage;
- else {
- assert (SL == GlobalValue::PrivateLinkage &&
- DL == GlobalValue::PrivateLinkage && "Unexpected linkage type");
- return GlobalValue::PrivateLinkage;
+
+ // No linking to be performed or linking from the source: simply create an
+ // identical version of the symbol over in the dest module... the
+ // initializer will be filled in later by LinkGlobalInits.
+ GlobalVariable *NewDGV =
+ new GlobalVariable(*DstM, TypeMap.get(SGV->getType()->getElementType()),
+ SGV->isConstant(), SGV->getLinkage(), /*init*/0,
+ SGV->getName(), /*insertbefore*/0,
+ SGV->isThreadLocal(),
+ SGV->getType()->getAddressSpace());
+ // Propagate alignment, visibility and section info.
+ CopyGVAttributes(NewDGV, SGV);
+
+ if (DGV) {
+ DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType()));
+ DGV->eraseFromParent();
}
-}
-
-// LinkAlias - Loop through the alias in the src module and link them into the
-// dest module. We're assuming, that all functions/global variables were already
-// linked in.
-static bool LinkAlias(Module *Dest, const Module *Src,
- ValueToValueMapTy &ValueMap,
- std::string *Err) {
- // Loop over all alias in the src module
- for (Module::const_alias_iterator I = Src->alias_begin(),
- E = Src->alias_end(); I != E; ++I) {
- const GlobalAlias *SGA = I;
- const GlobalValue *SAliasee = SGA->getAliasedGlobal();
- GlobalAlias *NewGA = NULL;
-
- // Globals were already linked, thus we can just query ValueMap for variant
- // of SAliasee in Dest.
- ValueToValueMapTy::const_iterator VMI = ValueMap.find(SAliasee);
- assert(VMI != ValueMap.end() && "Aliasee not linked");
- GlobalValue* DAliasee = cast<GlobalValue>(VMI->second);
- GlobalValue* DGV = NULL;
-
- // Fixup aliases to bitcasts. Note that aliases to GEPs are still broken
- // by this, but aliases to GEPs are broken to a lot of other things, so
- // it's less important.
- Constant *DAliaseeConst = DAliasee;
- if (SGA->getType() != DAliasee->getType())
- DAliaseeConst = ConstantExpr::getBitCast(DAliasee, SGA->getType());
-
- // Try to find something 'similar' to SGA in destination module.
- if (!DGV && !SGA->hasLocalLinkage()) {
- DGV = Dest->getNamedAlias(SGA->getName());
-
- // If types don't agree due to opaque types, try to resolve them.
- if (DGV && DGV->getType() != SGA->getType())
- RecursiveResolveTypes(SGA->getType(), DGV->getType());
- }
-
- if (!DGV && !SGA->hasLocalLinkage()) {
- DGV = Dest->getGlobalVariable(SGA->getName());
-
- // If types don't agree due to opaque types, try to resolve them.
- if (DGV && DGV->getType() != SGA->getType())
- RecursiveResolveTypes(SGA->getType(), DGV->getType());
- }
-
- if (!DGV && !SGA->hasLocalLinkage()) {
- DGV = Dest->getFunction(SGA->getName());
-
- // If types don't agree due to opaque types, try to resolve them.
- if (DGV && DGV->getType() != SGA->getType())
- RecursiveResolveTypes(SGA->getType(), DGV->getType());
- }
-
- // No linking to be performed on internal stuff.
- if (DGV && DGV->hasLocalLinkage())
- DGV = NULL;
-
- if (GlobalAlias *DGA = dyn_cast_or_null<GlobalAlias>(DGV)) {
- // Types are known to be the same, check whether aliasees equal. As
- // globals are already linked we just need query ValueMap to find the
- // mapping.
- if (DAliasee == DGA->getAliasedGlobal()) {
- // This is just two copies of the same alias. Propagate linkage, if
- // necessary.
- DGA->setLinkage(CalculateAliasLinkage(SGA, DGA));
-
- NewGA = DGA;
- // Proceed to 'common' steps
- } else
- return Error(Err, "Alias Collision on '" + SGA->getName()+
- "': aliases have different aliasees");
- } else if (GlobalVariable *DGVar = dyn_cast_or_null<GlobalVariable>(DGV)) {
- // The only allowed way is to link alias with external declaration or weak
- // symbol..
- if (DGVar->isDeclaration() || DGVar->isWeakForLinker()) {
- // But only if aliasee is global too...
- if (!isa<GlobalVariable>(DAliasee))
- return Error(Err, "Global-Alias Collision on '" + SGA->getName() +
- "': aliasee is not global variable");
-
- NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
- SGA->getName(), DAliaseeConst, Dest);
- CopyGVAttributes(NewGA, SGA);
-
- // Any uses of DGV need to change to NewGA, with cast, if needed.
- if (SGA->getType() != DGVar->getType())
- DGVar->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA,
- DGVar->getType()));
- else
- DGVar->replaceAllUsesWith(NewGA);
-
- // DGVar will conflict with NewGA because they both had the same
- // name. We must erase this now so ForceRenaming doesn't assert
- // because DGV might not have internal linkage.
- DGVar->eraseFromParent();
-
- // Proceed to 'common' steps
- } else
- return Error(Err, "Global-Alias Collision on '" + SGA->getName() +
- "': symbol multiple defined");
- } else if (Function *DF = dyn_cast_or_null<Function>(DGV)) {
- // The only allowed way is to link alias with external declaration or weak
- // symbol...
- if (DF->isDeclaration() || DF->isWeakForLinker()) {
- // But only if aliasee is function too...
- if (!isa<Function>(DAliasee))
- return Error(Err, "Function-Alias Collision on '" + SGA->getName() +
- "': aliasee is not function");
-
- NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
- SGA->getName(), DAliaseeConst, Dest);
- CopyGVAttributes(NewGA, SGA);
-
- // Any uses of DF need to change to NewGA, with cast, if needed.
- if (SGA->getType() != DF->getType())
- DF->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA,
- DF->getType()));
- else
- DF->replaceAllUsesWith(NewGA);
-
- // DF will conflict with NewGA because they both had the same
- // name. We must erase this now so ForceRenaming doesn't assert
- // because DF might not have internal linkage.
- DF->eraseFromParent();
-
- // Proceed to 'common' steps
- } else
- return Error(Err, "Function-Alias Collision on '" + SGA->getName() +
- "': symbol multiple defined");
- } else {
- // No linking to be performed, simply create an identical version of the
- // alias over in the dest module...
- NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(),
- SGA->getName(), DAliaseeConst, Dest);
- CopyGVAttributes(NewGA, SGA);
-
- // Proceed to 'common' steps
- }
-
- assert(NewGA && "No alias was created in destination module!");
-
- // If the symbol table renamed the alias, but it is an externally visible
- // symbol, DGA must be an global value with internal linkage. Rename it.
- if (NewGA->getName() != SGA->getName() &&
- !NewGA->hasLocalLinkage())
- ForceRenaming(NewGA, SGA->getName());
-
- // Remember this mapping so uses in the source module get remapped
- // later by MapValue.
- ValueMap[SGA] = NewGA;
- }
-
+
+ // Make sure to remember this mapping.
+ ValueMap[SGV] = NewDGV;
return false;
}
+/// linkFunctionProto - Link the function in the source module into the
+/// destination module if needed, setting up mapping information.
+bool ModuleLinker::linkFunctionProto(Function *SF) {
+ GlobalValue *DGV = getLinkedToGlobal(SF);
-// LinkGlobalInits - Update the initializers in the Dest module now that all
-// globals that may be referenced are in Dest.
-static bool LinkGlobalInits(Module *Dest, const Module *Src,
- ValueToValueMapTy &ValueMap,
- std::string *Err) {
- // Loop over all of the globals in the src module, mapping them over as we go
- for (Module::const_global_iterator I = Src->global_begin(),
- E = Src->global_end(); I != E; ++I) {
- const GlobalVariable *SGV = I;
-
- if (SGV->hasInitializer()) { // Only process initialized GV's
- // Figure out what the initializer looks like in the dest module.
- Constant *SInit =
- cast<Constant>(MapValue(SGV->getInitializer(), ValueMap));
- // Grab destination global variable or alias.
- GlobalValue *DGV = cast<GlobalValue>(ValueMap[SGV]->stripPointerCasts());
-
- // If dest if global variable, check that initializers match.
- if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV)) {
- if (DGVar->hasInitializer()) {
- if (SGV->hasExternalLinkage()) {
- if (DGVar->getInitializer() != SInit)
- return Error(Err, "Global Variable Collision on '" +
- SGV->getName() +
- "': global variables have different initializers");
- } else if (DGVar->isWeakForLinker()) {
- // Nothing is required, mapped values will take the new global
- // automatically.
- } else if (SGV->isWeakForLinker()) {
- // Nothing is required, mapped values will take the new global
- // automatically.
- } else if (DGVar->hasAppendingLinkage()) {
- llvm_unreachable("Appending linkage unimplemented!");
- } else {
- llvm_unreachable("Unknown linkage!");
- }
- } else {
- // Copy the initializer over now...
- DGVar->setInitializer(SInit);
- }
- } else {
- // Destination is alias, the only valid situation is when source is
- // weak. Also, note, that we already checked linkage in LinkGlobals(),
- // thus we assert here.
- // FIXME: Should we weaken this assumption, 'dereference' alias and
- // check for initializer of aliasee?
- assert(SGV->isWeakForLinker());
- }
+ if (DGV) {
+ GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
+ bool LinkFromSrc = false;
+ if (getLinkageResult(DGV, SF, NewLinkage, LinkFromSrc))
+ return true;
+
+ if (!LinkFromSrc) {
+ // Set calculated linkage
+ DGV->setLinkage(NewLinkage);
+
+ // Make sure to remember this mapping.
+ ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType()));
+
+ // Remove the body from the source module so we don't attempt to remap it.
+ SF->deleteBody();
+ return false;
}
}
+
+ // If there is no linkage to be performed or we are linking from the source,
+ // bring SF over.
+ Function *NewDF = Function::Create(TypeMap.get(SF->getFunctionType()),
+ SF->getLinkage(), SF->getName(), DstM);
+ CopyGVAttributes(NewDF, SF);
+
+ if (DGV) {
+ // Any uses of DF need to change to NewDF, with cast.
+ DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDF, DGV->getType()));
+ DGV->eraseFromParent();
+ }
+
+ ValueMap[SF] = NewDF;
return false;
}
-// LinkFunctionProtos - Link the functions together between the two modules,
-// without doing function bodies... this just adds external function prototypes
-// to the Dest function...
-//
-static bool LinkFunctionProtos(Module *Dest, const Module *Src,
- ValueToValueMapTy &ValueMap,
- std::string *Err) {
- ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable();
-
- // Loop over all of the functions in the src module, mapping them over
- for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) {
- const Function *SF = I; // SrcFunction
- GlobalValue *DGV = 0;
-
- // Check to see if may have to link the function with the global, alias or
- // function.
- if (SF->hasName() && !SF->hasLocalLinkage())
- DGV = cast_or_null<GlobalValue>(DestSymTab.lookup(SF->getName()));
-
- // If we found a global with the same name in the dest module, but it has
- // internal linkage, we are really not doing any linkage here.
- if (DGV && DGV->hasLocalLinkage())
- DGV = 0;
-
- // If types don't agree due to opaque types, try to resolve them.
- if (DGV && DGV->getType() != SF->getType())
- RecursiveResolveTypes(SF->getType(), DGV->getType());
-
+/// LinkAliasProto - Set up prototypes for any aliases that come over from the
+/// source module.
+bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) {
+ GlobalValue *DGV = getLinkedToGlobal(SGA);
+
+ if (DGV) {
GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage;
bool LinkFromSrc = false;
- if (GetLinkageResult(DGV, SF, NewLinkage, LinkFromSrc, Err))
+ if (getLinkageResult(DGV, SGA, NewLinkage, LinkFromSrc))
return true;
-
- // If there is no linkage to be performed, just bring over SF without
- // modifying it.
- if (DGV == 0) {
- // Function does not already exist, simply insert an function signature
- // identical to SF into the dest module.
- Function *NewDF = Function::Create(SF->getFunctionType(),
- SF->getLinkage(),
- SF->getName(), Dest);
- CopyGVAttributes(NewDF, SF);
-
- // If the LLVM runtime renamed the function, but it is an externally
- // visible symbol, DF must be an existing function with internal linkage.
- // Rename it.
- if (!NewDF->hasLocalLinkage() && NewDF->getName() != SF->getName())
- ForceRenaming(NewDF, SF->getName());
-
- // ... and remember this mapping...
- ValueMap[SF] = NewDF;
- continue;
- }
-
- // If the visibilities of the symbols disagree and the destination is a
- // prototype, take the visibility of its input.
- if (DGV->isDeclaration())
- DGV->setVisibility(SF->getVisibility());
-
- if (LinkFromSrc) {
- if (isa<GlobalAlias>(DGV))
- return Error(Err, "Function-Alias Collision on '" + SF->getName() +
- "': symbol multiple defined");
-
- // We have a definition of the same name but different type in the
- // source module. Copy the prototype to the destination and replace
- // uses of the destination's prototype with the new prototype.
- Function *NewDF = Function::Create(SF->getFunctionType(), NewLinkage,
- SF->getName(), Dest);
- CopyGVAttributes(NewDF, SF);
-
- // Any uses of DF need to change to NewDF, with cast
- DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDF,
- DGV->getType()));
-
- // DF will conflict with NewDF because they both had the same. We must
- // erase this now so ForceRenaming doesn't assert because DF might
- // not have internal linkage.
- if (GlobalVariable *Var = dyn_cast<GlobalVariable>(DGV))
- Var->eraseFromParent();
- else
- cast<Function>(DGV)->eraseFromParent();
-
- // If the symbol table renamed the function, but it is an externally
- // visible symbol, DF must be an existing function with internal
- // linkage. Rename it.
- if (NewDF->getName() != SF->getName() && !NewDF->hasLocalLinkage())
- ForceRenaming(NewDF, SF->getName());
-
- // Remember this mapping so uses in the source module get remapped
- // later by MapValue.
- ValueMap[SF] = NewDF;
- continue;
+
+ if (!LinkFromSrc) {
+ // Set calculated linkage.
+ DGV->setLinkage(NewLinkage);
+
+ // Make sure to remember this mapping.
+ ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType()));
+
+ // Remove the body from the source module so we don't attempt to remap it.
+ SGA->setAliasee(0);
+ return false;
}
+ }
+
+ // If there is no linkage to be performed or we're linking from the source,
+ // bring over SGA.
+ GlobalAlias *NewDA = new GlobalAlias(TypeMap.get(SGA->getType()),
+ SGA->getLinkage(), SGA->getName(),
+ /*aliasee*/0, DstM);
+ CopyGVAttributes(NewDA, SGA);
+
+ if (DGV) {
+ // Any uses of DGV need to change to NewDA, with cast.
+ DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDA, DGV->getType()));
+ DGV->eraseFromParent();
+ }
+
+ ValueMap[SGA] = NewDA;
+ return false;
+}
- // Not "link from source", keep the one in the DestModule and remap the
- // input onto it.
-
- if (isa<GlobalAlias>(DGV)) {
- // The only valid mappings are:
- // - SF is external declaration, which is effectively a no-op.
- // - SF is weak, when we just need to throw SF out.
- if (!SF->isDeclaration() && !SF->isWeakForLinker())
- return Error(Err, "Function-Alias Collision on '" + SF->getName() +
- "': symbol multiple defined");
- }
+void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) {
+ // Merge the initializer.
+ SmallVector<Constant*, 16> Elements;
+ if (ConstantArray *I = dyn_cast<ConstantArray>(AVI.DstInit)) {
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+ Elements.push_back(I->getOperand(i));
+ } else {
+ assert(isa<ConstantAggregateZero>(AVI.DstInit));
+ ArrayType *DstAT = cast<ArrayType>(AVI.DstInit->getType());
+ Type *EltTy = DstAT->getElementType();
+ Elements.append(DstAT->getNumElements(), Constant::getNullValue(EltTy));
+ }
+
+ Constant *SrcInit = MapValue(AVI.SrcInit, ValueMap, RF_None, &TypeMap);
+ if (const ConstantArray *I = dyn_cast<ConstantArray>(SrcInit)) {
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+ Elements.push_back(I->getOperand(i));
+ } else {
+ assert(isa<ConstantAggregateZero>(SrcInit));
+ ArrayType *SrcAT = cast<ArrayType>(SrcInit->getType());
+ Type *EltTy = SrcAT->getElementType();
+ Elements.append(SrcAT->getNumElements(), Constant::getNullValue(EltTy));
+ }
+ ArrayType *NewType = cast<ArrayType>(AVI.NewGV->getType()->getElementType());
+ AVI.NewGV->setInitializer(ConstantArray::get(NewType, Elements));
+}
- // Set calculated linkage
- DGV->setLinkage(NewLinkage);
- // Make sure to remember this mapping.
- ValueMap[SF] = ConstantExpr::getBitCast(DGV, SF->getType());
+// linkGlobalInits - Update the initializers in the Dest module now that all
+// globals that may be referenced are in Dest.
+void ModuleLinker::linkGlobalInits() {
+ // Loop over all of the globals in the src module, mapping them over as we go
+ for (Module::const_global_iterator I = SrcM->global_begin(),
+ E = SrcM->global_end(); I != E; ++I) {
+ if (!I->hasInitializer()) continue; // Only process initialized GV's.
+
+ // Grab destination global variable.
+ GlobalVariable *DGV = cast<GlobalVariable>(ValueMap[I]);
+ // Figure out what the initializer looks like in the dest module.
+ DGV->setInitializer(MapValue(I->getInitializer(), ValueMap,
+ RF_None, &TypeMap));
}
- return false;
}
-// LinkFunctionBody - Copy the source function over into the dest function and
+// linkFunctionBody - Copy the source function over into the dest function and
// fix up references to values. At this point we know that Dest is an external
// function, and that Src is not.
-static bool LinkFunctionBody(Function *Dest, Function *Src,
- ValueToValueMapTy &ValueMap,
- std::string *Err) {
- assert(Src && Dest && Dest->isDeclaration() && !Src->isDeclaration());
+void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) {
+ assert(Src && Dst && Dst->isDeclaration() && !Src->isDeclaration());
// Go through and convert function arguments over, remembering the mapping.
- Function::arg_iterator DI = Dest->arg_begin();
+ Function::arg_iterator DI = Dst->arg_begin();
for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end();
I != E; ++I, ++DI) {
- DI->setName(I->getName()); // Copy the name information over...
+ DI->setName(I->getName()); // Copy the name over.
- // Add a mapping to our local map
+ // Add a mapping to our mapping.
ValueMap[I] = DI;
}
// Splice the body of the source function into the dest function.
- Dest->getBasicBlockList().splice(Dest->end(), Src->getBasicBlockList());
+ Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList());
// At this point, all of the instructions and values of the function are now
// copied over. The only problem is that they are still referencing values in
// the Source function as operands. Loop through all of the operands of the
// functions and patch them up to point to the local versions.
- for (Function::iterator BB = Dest->begin(), BE = Dest->end(); BB != BE; ++BB)
+ for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB)
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
- RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries);
+ RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap);
// There is no need to map the arguments anymore.
for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end();
I != E; ++I)
ValueMap.erase(I);
-
- return false;
}
-// LinkFunctionBodies - Link in the function bodies that are defined in the
-// source module into the DestModule. This consists basically of copying the
-// function over and fixing up references to values.
-static bool LinkFunctionBodies(Module *Dest, Module *Src,
- ValueToValueMapTy &ValueMap,
- std::string *Err) {
-
- // Loop over all of the functions in the src module, mapping them over as we
- // go
- for (Module::iterator SF = Src->begin(), E = Src->end(); SF != E; ++SF) {
- if (!SF->isDeclaration()) { // No body if function is external
- Function *DF = dyn_cast<Function>(ValueMap[SF]); // Destination function
-
- // DF not external SF external?
- if (DF && DF->isDeclaration())
- // Only provide the function body if there isn't one already.
- if (LinkFunctionBody(DF, SF, ValueMap, Err))
- return true;
+void ModuleLinker::linkAliasBodies() {
+ for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end();
+ I != E; ++I)
+ if (Constant *Aliasee = I->getAliasee()) {
+ GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]);
+ DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, &TypeMap));
}
- }
- return false;
}
-// LinkAppendingVars - If there were any appending global variables, link them
-// together now. Return true on error.
-static bool LinkAppendingVars(Module *M,
- std::multimap<std::string, GlobalVariable *> &AppendingVars,
- std::string *ErrorMsg) {
- if (AppendingVars.empty()) return false; // Nothing to do.
-
- // Loop over the multimap of appending vars, processing any variables with the
- // same name, forming a new appending global variable with both of the
- // initializers merged together, then rewrite references to the old variables
- // and delete them.
- std::vector<Constant*> Inits;
- while (AppendingVars.size() > 1) {
- // Get the first two elements in the map...
- std::multimap<std::string,
- GlobalVariable*>::iterator Second = AppendingVars.begin(), First=Second++;
-
- // If the first two elements are for different names, there is no pair...
- // Otherwise there is a pair, so link them together...
- if (First->first == Second->first) {
- GlobalVariable *G1 = First->second, *G2 = Second->second;
- const ArrayType *T1 = cast<ArrayType>(G1->getType()->getElementType());
- const ArrayType *T2 = cast<ArrayType>(G2->getType()->getElementType());
-
- // Check to see that they two arrays agree on type...
- if (T1->getElementType() != T2->getElementType())
- return Error(ErrorMsg,
- "Appending variables with different element types need to be linked!");
- if (G1->isConstant() != G2->isConstant())
- return Error(ErrorMsg,
- "Appending variables linked with different const'ness!");
-
- if (G1->getAlignment() != G2->getAlignment())
- return Error(ErrorMsg,
- "Appending variables with different alignment need to be linked!");
-
- if (G1->getVisibility() != G2->getVisibility())
- return Error(ErrorMsg,
- "Appending variables with different visibility need to be linked!");
-
- if (G1->getSection() != G2->getSection())
- return Error(ErrorMsg,
- "Appending variables with different section name need to be linked!");
-
- unsigned NewSize = T1->getNumElements() + T2->getNumElements();
- ArrayType *NewType = ArrayType::get(T1->getElementType(),
- NewSize);
-
- G1->setName(""); // Clear G1's name in case of a conflict!
-
- // Create the new global variable...
- GlobalVariable *NG =
- new GlobalVariable(*M, NewType, G1->isConstant(), G1->getLinkage(),
- /*init*/0, First->first, 0, G1->isThreadLocal(),
- G1->getType()->getAddressSpace());
-
- // Propagate alignment, visibility and section info.
- CopyGVAttributes(NG, G1);
-
- // Merge the initializer...
- Inits.reserve(NewSize);
- if (ConstantArray *I = dyn_cast<ConstantArray>(G1->getInitializer())) {
- for (unsigned i = 0, e = T1->getNumElements(); i != e; ++i)
- Inits.push_back(I->getOperand(i));
- } else {
- assert(isa<ConstantAggregateZero>(G1->getInitializer()));
- Constant *CV = Constant::getNullValue(T1->getElementType());
- for (unsigned i = 0, e = T1->getNumElements(); i != e; ++i)
- Inits.push_back(CV);
- }
- if (ConstantArray *I = dyn_cast<ConstantArray>(G2->getInitializer())) {
- for (unsigned i = 0, e = T2->getNumElements(); i != e; ++i)
- Inits.push_back(I->getOperand(i));
- } else {
- assert(isa<ConstantAggregateZero>(G2->getInitializer()));
- Constant *CV = Constant::getNullValue(T2->getElementType());
- for (unsigned i = 0, e = T2->getNumElements(); i != e; ++i)
- Inits.push_back(CV);
- }
- NG->setInitializer(ConstantArray::get(NewType, Inits));
- Inits.clear();
-
- // Replace any uses of the two global variables with uses of the new
- // global...
-
- // FIXME: This should rewrite simple/straight-forward uses such as
- // getelementptr instructions to not use the Cast!
- G1->replaceAllUsesWith(ConstantExpr::getBitCast(NG,
- G1->getType()));
- G2->replaceAllUsesWith(ConstantExpr::getBitCast(NG,
- G2->getType()));
-
- // Remove the two globals from the module now...
- M->getGlobalList().erase(G1);
- M->getGlobalList().erase(G2);
-
- // Put the new global into the AppendingVars map so that we can handle
- // linking of more than two vars...
- Second->second = NG;
- }
- AppendingVars.erase(First);
+/// linkNamedMDNodes - Insert all of the named mdnodes in Src into the Dest
+/// module.
+void ModuleLinker::linkNamedMDNodes() {
+ for (Module::const_named_metadata_iterator I = SrcM->named_metadata_begin(),
+ E = SrcM->named_metadata_end(); I != E; ++I) {
+ NamedMDNode *DestNMD = DstM->getOrInsertNamedMetadata(I->getName());
+ // Add Src elements into Dest node.
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+ DestNMD->addOperand(MapValue(I->getOperand(i), ValueMap,
+ RF_None, &TypeMap));
}
-
- return false;
}
+
+bool ModuleLinker::run() {
+ assert(DstM && "Null Destination module");
+ assert(SrcM && "Null Source Module");
-static bool ResolveAliases(Module *Dest) {
- for (Module::alias_iterator I = Dest->alias_begin(), E = Dest->alias_end();
- I != E; ++I)
- // We can't sue resolveGlobalAlias here because we need to preserve
- // bitcasts and GEPs.
- if (const Constant *C = I->getAliasee()) {
- while (dyn_cast<GlobalAlias>(C))
- C = cast<GlobalAlias>(C)->getAliasee();
- const GlobalValue *GV = dyn_cast<GlobalValue>(C);
- if (C != I && !(GV && GV->isDeclaration()))
- I->replaceAllUsesWith(const_cast<Constant*>(C));
- }
-
- return false;
-}
-
-// LinkModules - This function links two modules together, with the resulting
-// left module modified to be the composite of the two input modules. If an
-// error occurs, true is returned and ErrorMsg (if not null) is set to indicate
-// the problem. Upon failure, the Dest module could be in a modified state, and
-// shouldn't be relied on to be consistent.
-bool
-Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) {
- assert(Dest != 0 && "Invalid Destination module");
- assert(Src != 0 && "Invalid Source Module");
-
- if (Dest->getDataLayout().empty()) {
- if (!Src->getDataLayout().empty()) {
- Dest->setDataLayout(Src->getDataLayout());
- } else {
- std::string DataLayout;
-
- if (Dest->getEndianness() == Module::AnyEndianness) {
- if (Src->getEndianness() == Module::BigEndian)
- DataLayout.append("E");
- else if (Src->getEndianness() == Module::LittleEndian)
- DataLayout.append("e");
- }
-
- if (Dest->getPointerSize() == Module::AnyPointerSize) {
- if (Src->getPointerSize() == Module::Pointer64)
- DataLayout.append(DataLayout.length() == 0 ? "p:64:64" : "-p:64:64");
- else if (Src->getPointerSize() == Module::Pointer32)
- DataLayout.append(DataLayout.length() == 0 ? "p:32:32" : "-p:32:32");
- }
- Dest->setDataLayout(DataLayout);
- }
- }
+ // Inherit the target data from the source module if the destination module
+ // doesn't have one already.
+ if (DstM->getDataLayout().empty() && !SrcM->getDataLayout().empty())
+ DstM->setDataLayout(SrcM->getDataLayout());
// Copy the target triple from the source to dest if the dest's is empty.
- if (Dest->getTargetTriple().empty() && !Src->getTargetTriple().empty())
- Dest->setTargetTriple(Src->getTargetTriple());
+ if (DstM->getTargetTriple().empty() && !SrcM->getTargetTriple().empty())
+ DstM->setTargetTriple(SrcM->getTargetTriple());
- if (!Src->getDataLayout().empty() && !Dest->getDataLayout().empty() &&
- Src->getDataLayout() != Dest->getDataLayout())
+ if (!SrcM->getDataLayout().empty() && !DstM->getDataLayout().empty() &&
+ SrcM->getDataLayout() != DstM->getDataLayout())
errs() << "WARNING: Linking two modules of different data layouts!\n";
- if (!Src->getTargetTriple().empty() &&
- Dest->getTargetTriple() != Src->getTargetTriple()) {
+ if (!SrcM->getTargetTriple().empty() &&
+ DstM->getTargetTriple() != SrcM->getTargetTriple()) {
errs() << "WARNING: Linking two modules of different target triples: ";
- if (!Src->getModuleIdentifier().empty())
- errs() << Src->getModuleIdentifier() << ": ";
- errs() << "'" << Src->getTargetTriple() << "' and '"
- << Dest->getTargetTriple() << "'\n";
+ if (!SrcM->getModuleIdentifier().empty())
+ errs() << SrcM->getModuleIdentifier() << ": ";
+ errs() << "'" << SrcM->getTargetTriple() << "' and '"
+ << DstM->getTargetTriple() << "'\n";
}
// Append the module inline asm string.
- if (!Src->getModuleInlineAsm().empty()) {
- if (Dest->getModuleInlineAsm().empty())
- Dest->setModuleInlineAsm(Src->getModuleInlineAsm());
+ if (!SrcM->getModuleInlineAsm().empty()) {
+ if (DstM->getModuleInlineAsm().empty())
+ DstM->setModuleInlineAsm(SrcM->getModuleInlineAsm());
else
- Dest->setModuleInlineAsm(Dest->getModuleInlineAsm()+"\n"+
- Src->getModuleInlineAsm());
+ DstM->setModuleInlineAsm(DstM->getModuleInlineAsm()+"\n"+
+ SrcM->getModuleInlineAsm());
}
// Update the destination module's dependent libraries list with the libraries
// from the source module. There's no opportunity for duplicates here as the
// Module ensures that duplicate insertions are discarded.
- for (Module::lib_iterator SI = Src->lib_begin(), SE = Src->lib_end();
+ for (Module::lib_iterator SI = SrcM->lib_begin(), SE = SrcM->lib_end();
SI != SE; ++SI)
- Dest->addLibrary(*SI);
+ DstM->addLibrary(*SI);
+
+ // If the source library's module id is in the dependent library list of the
+ // destination library, remove it since that module is now linked in.
+ StringRef ModuleId = SrcM->getModuleIdentifier();
+ if (!ModuleId.empty())
+ DstM->removeLibrary(sys::path::stem(ModuleId));
- // LinkTypes - Go through the symbol table of the Src module and see if any
- // types are named in the src module that are not named in the Dst module.
- // Make sure there are no type name conflicts.
- if (LinkTypes(Dest, Src, ErrorMsg))
- return true;
+
+ // Loop over all of the linked values to compute type mappings.
+ computeTypeMapping();
- // ValueMap - Mapping of values from what they used to be in Src, to what they
- // are now in Dest. ValueToValueMapTy is a ValueMap, which involves some
- // overhead due to the use of Value handles which the Linker doesn't actually
- // need, but this allows us to reuse the ValueMapper code.
- ValueToValueMapTy ValueMap;
-
- // AppendingVars - Keep track of global variables in the destination module
- // with appending linkage. After the module is linked together, they are
- // appended and the module is rewritten.
- std::multimap<std::string, GlobalVariable *> AppendingVars;
- for (Module::global_iterator I = Dest->global_begin(), E = Dest->global_end();
- I != E; ++I) {
- // Add all of the appending globals already in the Dest module to
- // AppendingVars.
- if (I->hasAppendingLinkage())
- AppendingVars.insert(std::make_pair(I->getName(), I));
- }
-
- // Insert all of the globals in src into the Dest module... without linking
+ // Insert all of the globals in src into the DstM module... without linking
// initializers (which could refer to functions not yet mapped over).
- if (LinkGlobals(Dest, Src, ValueMap, AppendingVars, ErrorMsg))
- return true;
+ for (Module::global_iterator I = SrcM->global_begin(),
+ E = SrcM->global_end(); I != E; ++I)
+ if (linkGlobalProto(I))
+ return true;
// Link the functions together between the two modules, without doing function
- // bodies... this just adds external function prototypes to the Dest
+ // bodies... this just adds external function prototypes to the DstM
// function... We do this so that when we begin processing function bodies,
// all of the global values that may be referenced are available in our
// ValueMap.
- if (LinkFunctionProtos(Dest, Src, ValueMap, ErrorMsg))
- return true;
-
- // If there were any alias, link them now. We really need to do this now,
- // because all of the aliases that may be referenced need to be available in
- // ValueMap
- if (LinkAlias(Dest, Src, ValueMap, ErrorMsg)) return true;
-
- // Update the initializers in the Dest module now that all globals that may
- // be referenced are in Dest.
- if (LinkGlobalInits(Dest, Src, ValueMap, ErrorMsg)) return true;
+ for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I)
+ if (linkFunctionProto(I))
+ return true;
- // Link in the function bodies that are defined in the source module into the
- // DestModule. This consists basically of copying the function over and
- // fixing up references to values.
- if (LinkFunctionBodies(Dest, Src, ValueMap, ErrorMsg)) return true;
+ // If there were any aliases, link them now.
+ for (Module::alias_iterator I = SrcM->alias_begin(),
+ E = SrcM->alias_end(); I != E; ++I)
+ if (linkAliasProto(I))
+ return true;
- // If there were any appending global variables, link them together now.
- if (LinkAppendingVars(Dest, AppendingVars, ErrorMsg)) return true;
+ for (unsigned i = 0, e = AppendingVars.size(); i != e; ++i)
+ linkAppendingVarInit(AppendingVars[i]);
+
+ // Update the initializers in the DstM module now that all globals that may
+ // be referenced are in DstM.
+ linkGlobalInits();
+
+ // Link in the function bodies that are defined in the source module into
+ // DstM.
+ for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) {
+ if (SF->isDeclaration()) continue; // No body if function is external.
+
+ linkFunctionBody(cast<Function>(ValueMap[SF]), SF);
+ }
- // Resolve all uses of aliases with aliasees
- if (ResolveAliases(Dest)) return true;
+ // Resolve all uses of aliases with aliasees.
+ linkAliasBodies();
- // Remap all of the named mdnoes in Src into the Dest module. We do this
+ // Remap all of the named mdnoes in Src into the DstM module. We do this
// after linking GlobalValues so that MDNodes that reference GlobalValues
// are properly remapped.
- LinkNamedMDNodes(Dest, Src, ValueMap);
-
- // If the source library's module id is in the dependent library list of the
- // destination library, remove it since that module is now linked in.
- const std::string &modId = Src->getModuleIdentifier();
- if (!modId.empty())
- Dest->removeLibrary(sys::path::stem(modId));
+ linkNamedMDNodes();
+ // Now that all of the types from the source are used, resolve any structs
+ // copied over to the dest that didn't exist there.
+ TypeMap.linkDefinedTypeBodies();
+
return false;
}
-// vim: sw=2
+//===----------------------------------------------------------------------===//
+// LinkModules entrypoint.
+//===----------------------------------------------------------------------===//
+
+// LinkModules - This function links two modules together, with the resulting
+// left module modified to be the composite of the two input modules. If an
+// error occurs, true is returned and ErrorMsg (if not null) is set to indicate
+// the problem. Upon failure, the Dest module could be in a modified state, and
+// shouldn't be relied on to be consistent.
+bool Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) {
+ ModuleLinker TheLinker(Dest, Src);
+ if (TheLinker.run()) {
+ if (ErrorMsg) *ErrorMsg = TheLinker.ErrorMsg;
+ return true;
+ }
+
+ return false;
+}
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index c59497efc2..54072b2f8d 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -20,7 +20,6 @@
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/InlineAsm.h"
@@ -74,29 +73,6 @@ namespace {
PrivateGlobalPrefix = "";
}
};
- /// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
- /// any unnamed structure types that are used by the program, and merges
- /// external functions with the same name.
- ///
- class CBackendNameAllUsedStructsAndMergeFunctions : public ModulePass {
- public:
- static char ID;
- CBackendNameAllUsedStructsAndMergeFunctions()
- : ModulePass(ID) {
- initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
- }
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<FindUsedTypes>();
- }
-
- virtual const char *getPassName() const {
- return "C backend type canonicalizer";
- }
-
- virtual bool runOnModule(Module &M);
- };
-
- char CBackendNameAllUsedStructsAndMergeFunctions::ID = 0;
/// CWriter - This class is the main chunk of code that converts an LLVM
/// module to a C translation unit.
@@ -109,7 +85,7 @@ namespace {
const MCAsmInfo* TAsm;
MCContext *TCtx;
const TargetData* TD;
- std::map<const Type *, std::string> TypeNames;
+
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> intrinsicPrototypesAlreadyGenerated;
std::set<const Argument*> ByValParams;
@@ -118,6 +94,10 @@ namespace {
DenseMap<const Value*, unsigned> AnonValueNumbers;
unsigned NextAnonValueNumber;
+ /// UnnamedStructIDs - This contains a unique ID for each struct that is
+ /// either anonymous or has no name.
+ DenseMap<const StructType*, unsigned> UnnamedStructIDs;
+
public:
static char ID;
explicit CWriter(formatted_raw_ostream &o)
@@ -163,9 +143,9 @@ namespace {
delete TCtx;
delete TAsm;
FPConstantMap.clear();
- TypeNames.clear();
ByValParams.clear();
intrinsicPrototypesAlreadyGenerated.clear();
+ UnnamedStructIDs.clear();
return false;
}
@@ -182,6 +162,8 @@ namespace {
const AttrListPtr &PAL,
const PointerType *Ty);
+ std::string getStructName(const StructType *ST);
+
/// writeOperandDeref - Print the result of dereferencing the specified
/// operand with '*'. This is equivalent to printing '*' then using
/// writeOperand, but avoids excess syntax in some cases.
@@ -214,8 +196,8 @@ namespace {
/// intrinsics which need to be explicitly defined in the CBackend.
void printIntrinsicDefinition(const Function &F, raw_ostream &Out);
- void printModuleTypes(const TypeSymbolTable &ST);
- void printContainedStructs(const Type *Ty, std::set<const Type *> &);
+ void printModuleTypes();
+ void printContainedStructs(const Type *Ty, SmallPtrSet<const Type *, 16> &);
void printFloatingPointConstants(Function &F);
void printFloatingPointConstants(const Constant *C);
void printFunctionSignature(const Function *F, bool Prototype);
@@ -359,6 +341,7 @@ namespace {
char CWriter::ID = 0;
+
static std::string CBEMangle(const std::string &S) {
std::string Result;
@@ -374,90 +357,14 @@ static std::string CBEMangle(const std::string &S) {
return Result;
}
-
-/// This method inserts names for any unnamed structure types that are used by
-/// the program, and removes names from structure types that are not used by the
-/// program.
-///
-bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) {
- // Get a set of types that are used by the program...
- SetVector<const Type *> UT = getAnalysis<FindUsedTypes>().getTypes();
-
- // Loop over the module symbol table, removing types from UT that are
- // already named, and removing names for types that are not used.
- //
- TypeSymbolTable &TST = M.getTypeSymbolTable();
- for (TypeSymbolTable::iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ) {
- TypeSymbolTable::iterator I = TI++;
-
- // If this isn't a struct or array type, remove it from our set of types
- // to name. This simplifies emission later.
- if (!I->second->isStructTy() && !I->second->isOpaqueTy() &&
- !I->second->isArrayTy()) {
- TST.remove(I);
- } else {
- // If this is not used, remove it from the symbol table.
- if (!UT.count(I->second))
- TST.remove(I);
- else
- UT.remove(I->second); // Only keep one name for this type.
- }
- }
-
- // UT now contains types that are not named. Loop over it, naming
- // structure types.
- //
- bool Changed = false;
- unsigned RenameCounter = 0;
- for (SetVector<const Type *>::const_iterator I = UT.begin(), E = UT.end();
- I != E; ++I)
- if ((*I)->isStructTy() || (*I)->isArrayTy()) {
- while (M.addTypeName("unnamed"+utostr(RenameCounter), *I))
- ++RenameCounter;
- Changed = true;
- }
-
-
- // Loop over all external functions and globals. If we have two with
- // identical names, merge them.
- // FIXME: This code should disappear when we don't allow values with the same
- // names when they have different types!
- std::map<std::string, GlobalValue*> ExtSymbols;
- for (Module::iterator I = M.begin(), E = M.end(); I != E;) {
- Function *GV = I++;
- if (GV->isDeclaration() && GV->hasName()) {
- std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
- = ExtSymbols.insert(std::make_pair(GV->getName(), GV));
- if (!X.second) {
- // Found a conflict, replace this global with the previous one.
- GlobalValue *OldGV = X.first->second;
- GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
- GV->eraseFromParent();
- Changed = true;
- }
- }
- }
- // Do the same for globals.
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E;) {
- GlobalVariable *GV = I++;
- if (GV->isDeclaration() && GV->hasName()) {
- std::pair<std::map<std::string, GlobalValue*>::iterator, bool> X
- = ExtSymbols.insert(std::make_pair(GV->getName(), GV));
- if (!X.second) {
- // Found a conflict, replace this global with the previous one.
- GlobalValue *OldGV = X.first->second;
- GV->replaceAllUsesWith(ConstantExpr::getBitCast(OldGV, GV->getType()));
- GV->eraseFromParent();
- Changed = true;
- }
- }
- }
-
- return Changed;
+std::string CWriter::getStructName(const StructType *ST) {
+ if (!ST->isAnonymous() && !ST->getName().empty())
+ return CBEMangle("l_"+ST->getName().str());
+
+ return "l_unnamed_" + utostr(UnnamedStructIDs[ST]);
}
+
/// printStructReturnPointerFunctionType - This is like printType for a struct
/// return type, except, instead of printing the type as void (*)(Struct*, ...)
/// print it as "Struct (*)(...)", for struct return functions.
@@ -471,7 +378,7 @@ void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out,
bool PrintedType = false;
FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end();
- const Type *RetTy = cast<PointerType>(I->get())->getElementType();
+ const Type *RetTy = cast<PointerType>(*I)->getElementType();
unsigned Idx = 1;
for (++I, ++Idx; I != E; ++I, ++Idx) {
if (PrintedType)
@@ -559,12 +466,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
return Out;
}
- // Check to see if the type is named.
- if (!IgnoreName || Ty->isOpaqueTy()) {
- std::map<const Type *, std::string>::iterator I = TypeNames.find(Ty);
- if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar;
- }
-
switch (Ty->getTypeID()) {
case Type::FunctionTyID: {
const FunctionType *FTy = cast<FunctionType>(Ty);
@@ -599,6 +500,11 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
}
case Type::StructTyID: {
const StructType *STy = cast<StructType>(Ty);
+
+ // Check to see if the type is named.
+ if (!IgnoreName)
+ return Out << getStructName(STy) << ' ' << NameSoFar;
+
Out << NameSoFar + " {\n";
unsigned Idx = 0;
for (StructType::element_iterator I = STy->element_begin(),
@@ -639,12 +545,6 @@ raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty,
return Out << "; }";
}
- case Type::OpaqueTyID: {
- std::string TyName = "struct opaque_" + itostr(OpaqueCounter++);
- assert(TypeNames.find(Ty) == TypeNames.end());
- TypeNames[Ty] = TyName;
- return Out << TyName << ' ' << NameSoFar;
- }
default:
llvm_unreachable("Unhandled case in getTypeProps!");
}
@@ -1829,8 +1729,8 @@ bool CWriter::doInitialization(Module &M) {
<< "/* End Module asm statements */\n";
}
- // Loop over the symbol table, emitting all named constants...
- printModuleTypes(M.getTypeSymbolTable());
+ // Loop over the symbol table, emitting all named constants.
+ printModuleTypes();
// Global variable declarations...
if (!M.global_empty()) {
@@ -2119,11 +2019,10 @@ void CWriter::printFloatingPointConstants(const Constant *C) {
}
-
/// printSymbolTable - Run through symbol table looking for type names. If a
/// type name is found, emit its declaration...
///
-void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
+void CWriter::printModuleTypes() {
Out << "/* Helper union for bitcasts */\n";
Out << "typedef union {\n";
Out << " unsigned int Int32;\n";
@@ -2132,46 +2031,42 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
Out << " double Double;\n";
Out << "} llvmBitCastUnion;\n";
- // We are only interested in the type plane of the symbol table.
- TypeSymbolTable::const_iterator I = TST.begin();
- TypeSymbolTable::const_iterator End = TST.end();
+ // Get all of the struct types used in the module.
+ std::vector<StructType*> StructTypes;
+ TheModule->findUsedStructTypes(StructTypes);
- // If there are no type names, exit early.
- if (I == End) return;
+ if (StructTypes.empty()) return;
- // Print out forward declarations for structure types before anything else!
Out << "/* Structure forward decls */\n";
- for (; I != End; ++I) {
- std::string Name = "struct " + CBEMangle("l_"+I->first);
- Out << Name << ";\n";
- TypeNames.insert(std::make_pair(I->second, Name));
- }
- Out << '\n';
+ unsigned NextTypeID = 0;
+
+ // If any of them are missing names, add a unique ID to UnnamedStructIDs.
+ // Print out forward declarations for structure types.
+ for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
+ StructType *ST = StructTypes[i];
- // Now we can print out typedefs. Above, we guaranteed that this can only be
- // for struct or opaque types.
- Out << "/* Typedefs */\n";
- for (I = TST.begin(); I != End; ++I) {
- std::string Name = CBEMangle("l_"+I->first);
- Out << "typedef ";
- printType(Out, I->second, false, Name);
- Out << ";\n";
+ if (ST->isAnonymous() || ST->getName().empty())
+ UnnamedStructIDs[ST] = NextTypeID++;
+
+ std::string Name = getStructName(ST);
+
+ Out << "typedef struct " << Name << ' ' << Name << ";\n";
}
Out << '\n';
- // Keep track of which structures have been printed so far...
- std::set<const Type *> StructPrinted;
+ // Keep track of which structures have been printed so far.
+ SmallPtrSet<const Type *, 16> StructPrinted;
// Loop over all structures then push them into the stack so they are
// printed in the correct order.
//
Out << "/* Structure contents */\n";
- for (I = TST.begin(); I != End; ++I)
- if (I->second->isStructTy() || I->second->isArrayTy())
+ for (unsigned i = 0, e = StructTypes.size(); i != e; ++i)
+ if (StructTypes[i]->isStructTy())
// Only print out used types!
- printContainedStructs(I->second, StructPrinted);
+ printContainedStructs(StructTypes[i], StructPrinted);
}
// Push the struct onto the stack and recursively push all structs
@@ -2180,7 +2075,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) {
// TODO: Make this work properly with vector types
//
void CWriter::printContainedStructs(const Type *Ty,
- std::set<const Type*> &StructPrinted) {
+ SmallPtrSet<const Type *, 16> &StructPrinted) {
// Don't walk through pointers.
if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy())
return;
@@ -2190,14 +2085,13 @@ void CWriter::printContainedStructs(const Type *Ty,
E = Ty->subtype_end(); I != E; ++I)
printContainedStructs(*I, StructPrinted);
- if (Ty->isStructTy() || Ty->isArrayTy()) {
+ if (const StructType *ST = dyn_cast<StructType>(Ty)) {
// Check to see if we have already printed this struct.
- if (StructPrinted.insert(Ty).second) {
- // Print structure type out.
- std::string Name = TypeNames[Ty];
- printType(Out, Ty, false, Name, true);
- Out << ";\n\n";
- }
+ if (!StructPrinted.insert(Ty)) return;
+
+ // Print structure type out.
+ printType(Out, ST, false, getStructName(ST), true);
+ Out << ";\n\n";
}
}
@@ -2847,10 +2741,12 @@ static void printLimitValue(const IntegerType &Ty, bool isSigned, bool isMax,
Out << "U" << type << (isMax ? "_MAX" : "0");
}
+#ifndef NDEBUG
static bool isSupportedIntegerSize(const IntegerType &T) {
return T.getBitWidth() == 8 || T.getBitWidth() == 16 ||
T.getBitWidth() == 32 || T.getBitWidth() == 64;
}
+#endif
void CWriter::printIntrinsicDefinition(const Function &F, raw_ostream &Out) {
const FunctionType *funT = F.getFunctionType();
@@ -3704,7 +3600,6 @@ bool CTargetMachine::addPassesToEmitFile(PassManagerBase &PM,
PM.add(createGCLoweringPass());
PM.add(createLowerInvokePass());
PM.add(createCFGSimplificationPass()); // clean up after lower invoke.
- PM.add(new CBackendNameAllUsedStructsAndMergeFunctions());
PM.add(new CWriter(o));
PM.add(createGCInfoDeleter());
return false;
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 351f12225c..c4280ef5a2 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -22,7 +22,7 @@
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
-#include "llvm/TypeSymbolTable.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/CommandLine.h"
@@ -33,7 +33,7 @@
#include "llvm/Config/config.h"
#include <algorithm>
#include <set>
-
+#include <map>
using namespace llvm;
static cl::opt<std::string>
@@ -193,26 +193,11 @@ static std::string getTypePrefix(const Type *Ty) {
case Type::ArrayTyID: return "array_";
case Type::PointerTyID: return "ptr_";
case Type::VectorTyID: return "packed_";
- case Type::OpaqueTyID: return "opaque_";
default: return "other_";
}
return "unknown_";
}
-// Looks up the type in the symbol table and returns a pointer to its name or
-// a null pointer if it wasn't found. Note that this isn't the same as the
-// Mode::getTypeName function which will return an empty string, not a null
-// pointer if the name is not found.
-static const std::string *
-findTypeName(const TypeSymbolTable& ST, const Type* Ty) {
- TypeSymbolTable::const_iterator TI = ST.begin();
- TypeSymbolTable::const_iterator TE = ST.end();
- for (;TI != TE; ++TI)
- if (TI->second == Ty)
- return &(TI->first);
- return 0;
-}
-
void CppWriter::error(const std::string& msg) {
report_fatal_error(msg);
}
@@ -384,18 +369,20 @@ std::string CppWriter::getCppName(const Type* Ty) {
case Type::StructTyID: prefix = "StructTy_"; break;
case Type::ArrayTyID: prefix = "ArrayTy_"; break;
case Type::PointerTyID: prefix = "PointerTy_"; break;
- case Type::OpaqueTyID: prefix = "OpaqueTy_"; break;
case Type::VectorTyID: prefix = "VectorTy_"; break;
default: prefix = "OtherTy_"; break; // prevent breakage
}
// See if the type has a name in the symboltable and build accordingly
- const std::string* tName = findTypeName(TheModule->getTypeSymbolTable(), Ty);
std::string name;
- if (tName)
- name = std::string(prefix) + *tName;
- else
- name = std::string(prefix) + utostr(uniqueNum++);
+ if (const StructType *STy = dyn_cast<StructType>(Ty))
+ if (STy->hasName())
+ name = STy->getName();
+
+ if (name.empty())
+ name = utostr(uniqueNum++);
+
+ name = std::string(prefix) + name;
sanitize(name);
// Save the name
@@ -590,8 +577,18 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
Out << ");";
nl(Out);
}
- Out << "StructType* " << typeName << " = StructType::get("
- << typeName << "_fields, /*isPacked=*/"
+
+ Out << "StructType *" << typeName << " = ";
+ if (ST->isAnonymous()) {
+ Out << "StructType::get(" << "mod->getContext(), ";
+ } else {
+ Out << "StructType::createNamed(mod->getContext(), \"";
+ printEscapedString(ST->getName());
+ Out << "\");";
+ nl(Out);
+ Out << typeName << "->setBody(";
+ }
+ Out << typeName << "_fields, /*isPacked=*/"
<< (ST->isPacked() ? "true" : "false") << ");";
nl(Out);
break;
@@ -629,25 +626,10 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
nl(Out);
break;
}
- case Type::OpaqueTyID: {
- Out << "OpaqueType* " << typeName;
- Out << " = OpaqueType::get(mod->getContext());";
- nl(Out);
- break;
- }
default:
error("Invalid TypeID");
}
- // If the type had a name, make sure we recreate it.
- const std::string* progTypeName =
- findTypeName(TheModule->getTypeSymbolTable(),Ty);
- if (progTypeName) {
- Out << "mod->addTypeName(\"" << *progTypeName << "\", "
- << typeName << ");";
- nl(Out);
- }
-
// Pop us off the type stack
TypeStack.pop_back();
@@ -670,7 +652,6 @@ bool CppWriter::printTypeInternal(const Type* Ty) {
case Type::StructTyID: Out << "StructType"; break;
case Type::VectorTyID: Out << "VectorType"; break;
case Type::PointerTyID: Out << "PointerType"; break;
- case Type::OpaqueTyID: Out << "OpaqueType"; break;
default: Out << "NoSuchDerivedType"; break;
}
Out << ">(" << I->second << "_fwd.get());";
@@ -695,26 +676,7 @@ void CppWriter::printType(const Type* Ty) {
}
void CppWriter::printTypes(const Module* M) {
- // Walk the symbol table and print out all its types
- const TypeSymbolTable& symtab = M->getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = symtab.begin(), TE = symtab.end();
- TI != TE; ++TI) {
-
- // For primitive types and types already defined, just add a name
- TypeMap::const_iterator TNI = TypeNames.find(TI->second);
- if (TI->second->isIntegerTy() || TI->second->isPrimitiveType() ||
- TNI != TypeNames.end()) {
- Out << "mod->addTypeName(\"";
- printEscapedString(TI->first);
- Out << "\", " << getCppName(TI->second) << ");";
- nl(Out);
- // For everything else, define the type
- } else {
- printType(TI->second);
- }
- }
-
- // Add all of the global variables to the value table...
+ // Add all of the global variables to the value table.
for (Module::const_global_iterator I = TheModule->global_begin(),
E = TheModule->global_end(); I != E; ++I) {
if (I->hasInitializer())
@@ -1959,8 +1921,8 @@ void CppWriter::printVariable(const std::string& fname,
Out << "}\n";
}
-void CppWriter::printType(const std::string& fname,
- const std::string& typeName) {
+void CppWriter::printType(const std::string &fname,
+ const std::string &typeName) {
const Type* Ty = TheModule->getTypeByName(typeName);
if (!Ty) {
error(std::string("Type '") + typeName + "' not found in input module");
diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp
index 1990bc7b92..6309a1572c 100644
--- a/lib/Target/TargetData.cpp
+++ b/lib/Target/TargetData.cpp
@@ -42,6 +42,7 @@ char TargetData::ID = 0;
//===----------------------------------------------------------------------===//
StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
+ assert(!ST->isOpaque() && "Cannot get layout of opaque structs");
StructAlignment = 0;
StructSize = 0;
NumElements = ST->getNumElements();
@@ -313,52 +314,16 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType,
namespace {
-class StructLayoutMap : public AbstractTypeUser {
+class StructLayoutMap {
typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy;
LayoutInfoTy LayoutInfo;
- void RemoveEntry(LayoutInfoTy::iterator I, bool WasAbstract) {
- I->second->~StructLayout();
- free(I->second);
- if (WasAbstract)
- I->first->removeAbstractTypeUser(this);
- LayoutInfo.erase(I);
- }
-
-
- /// refineAbstractType - The callback method invoked when an abstract type is
- /// resolved to another type. An object must override this method to update
- /// its internal state to reference NewType instead of OldType.
- ///
- virtual void refineAbstractType(const DerivedType *OldTy,
- const Type *) {
- LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(OldTy));
- assert(I != LayoutInfo.end() && "Using type but not in map?");
- RemoveEntry(I, true);
- }
-
- /// typeBecameConcrete - The other case which AbstractTypeUsers must be aware
- /// of is when a type makes the transition from being abstract (where it has
- /// clients on its AbstractTypeUsers list) to concrete (where it does not).
- /// This method notifies ATU's when this occurs for a type.
- ///
- virtual void typeBecameConcrete(const DerivedType *AbsTy) {
- LayoutInfoTy::iterator I = LayoutInfo.find(cast<const StructType>(AbsTy));
- assert(I != LayoutInfo.end() && "Using type but not in map?");
- RemoveEntry(I, true);
- }
-
public:
virtual ~StructLayoutMap() {
// Remove any layouts.
- for (LayoutInfoTy::iterator
- I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) {
- const Type *Key = I->first;
+ for (LayoutInfoTy::iterator I = LayoutInfo.begin(), E = LayoutInfo.end();
+ I != E; ++I) {
StructLayout *Value = I->second;
-
- if (Key->isAbstract())
- Key->removeAbstractTypeUser(this);
-
Value->~StructLayout();
free(Value);
}
@@ -367,7 +332,10 @@ public:
void InvalidateEntry(const StructType *Ty) {
LayoutInfoTy::iterator I = LayoutInfo.find(Ty);
if (I == LayoutInfo.end()) return;
- RemoveEntry(I, Ty->isAbstract());
+
+ I->second->~StructLayout();
+ free(I->second);
+ LayoutInfo.erase(I);
}
StructLayout *&operator[](const StructType *STy) {
@@ -404,9 +372,6 @@ const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
new (L) StructLayout(Ty, *this);
- if (Ty->isAbstract())
- Ty->addAbstractTypeUser(STM);
-
return L;
}
diff --git a/lib/Transforms/IPO/CMakeLists.txt b/lib/Transforms/IPO/CMakeLists.txt
index 179b150c14..3de7bfceed 100644
--- a/lib/Transforms/IPO/CMakeLists.txt
+++ b/lib/Transforms/IPO/CMakeLists.txt
@@ -2,7 +2,6 @@ add_llvm_library(LLVMipo
ArgumentPromotion.cpp
ConstantMerge.cpp
DeadArgumentElimination.cpp
- DeadTypeElimination.cpp
ExtractGV.cpp
FunctionAttrs.cpp
GlobalDCE.cpp
diff --git a/lib/Transforms/IPO/DeadTypeElimination.cpp b/lib/Transforms/IPO/DeadTypeElimination.cpp
deleted file mode 100644
index d3d4963b63..0000000000
--- a/lib/Transforms/IPO/DeadTypeElimination.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//===- DeadTypeElimination.cpp - Eliminate unused types for symbol table --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass is used to cleanup the output of GCC. It eliminate names for types
-// that are unused in the entire translation unit, using the FindUsedTypes pass.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "deadtypeelim"
-#include "llvm/Transforms/IPO.h"
-#include "llvm/Analysis/FindUsedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/ADT/Statistic.h"
-using namespace llvm;
-
-STATISTIC(NumKilled, "Number of unused typenames removed from symtab");
-
-namespace {
- struct DTE : public ModulePass {
- static char ID; // Pass identification, replacement for typeid
- DTE() : ModulePass(ID) {
- initializeDTEPass(*PassRegistry::getPassRegistry());
- }
-
- // doPassInitialization - For this pass, it removes global symbol table
- // entries for primitive types. These are never used for linking in GCC and
- // they make the output uglier to look at, so we nuke them.
- //
- // Also, initialize instance variables.
- //
- bool runOnModule(Module &M);
-
- // getAnalysisUsage - This function needs FindUsedTypes to do its job...
- //
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<FindUsedTypes>();
- }
- };
-}
-
-char DTE::ID = 0;
-INITIALIZE_PASS_BEGIN(DTE, "deadtypeelim", "Dead Type Elimination",
- false, false)
-INITIALIZE_PASS_DEPENDENCY(FindUsedTypes)
-INITIALIZE_PASS_END(DTE, "deadtypeelim", "Dead Type Elimination", false, false)
-
-ModulePass *llvm::createDeadTypeEliminationPass() {
- return new DTE();
-}
-
-
-// ShouldNukeSymtabEntry - Return true if this module level symbol table entry
-// should be eliminated.
-//
-static inline bool ShouldNukeSymtabEntry(const Type *Ty){
- // Nuke all names for primitive types!
- if (Ty->isPrimitiveType() || Ty->isIntegerTy())
- return true;
-
- // Nuke all pointers to primitive types as well...
- if (const PointerType *PT = dyn_cast<PointerType>(Ty))
- if (PT->getElementType()->isPrimitiveType() ||
- PT->getElementType()->isIntegerTy())
- return true;
-
- return false;
-}
-
-// run - For this pass, it removes global symbol table entries for primitive
-// types. These are never used for linking in GCC and they make the output
-// uglier to look at, so we nuke them. Also eliminate types that are never used
-// in the entire program as indicated by FindUsedTypes.
-//
-bool DTE::runOnModule(Module &M) {
- bool Changed = false;
-
- TypeSymbolTable &ST = M.getTypeSymbolTable();
- const SetVector<const Type*> &T = getAnalysis<FindUsedTypes>().getTypes();
- std::set<const Type*> UsedTypes(T.begin(), T.end());
-
- // Check the symbol table for superfluous type entries...
- //
- // Grab the 'type' plane of the module symbol...
- TypeSymbolTable::iterator TI = ST.begin();
- TypeSymbolTable::iterator TE = ST.end();
- while ( TI != TE ) {
- // If this entry should be unconditionally removed, or if we detect that
- // the type is not used, remove it.
- const Type *RHS = TI->second;
- if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) {
- ST.remove(TI++);
- ++NumKilled;
- Changed = true;
- } else {
- ++TI;
- // We only need to leave one name for each type.
- UsedTypes.erase(RHS);
- }
- }
-
- return Changed;
-}
-
-// vim: sw=2
diff --git a/lib/Transforms/IPO/IPO.cpp b/lib/Transforms/IPO/IPO.cpp
index 21dcb519d9..31ce95f53d 100644
--- a/lib/Transforms/IPO/IPO.cpp
+++ b/lib/Transforms/IPO/IPO.cpp
@@ -25,7 +25,6 @@ void llvm::initializeIPO(PassRegistry &Registry) {
initializeConstantMergePass(Registry);
initializeDAEPass(Registry);
initializeDAHPass(Registry);
- initializeDTEPass(Registry);
initializeFunctionAttrsPass(Registry);
initializeGlobalDCEPass(Registry);
initializeGlobalOptPass(Registry);
@@ -63,10 +62,6 @@ void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createDeadArgEliminationPass());
}
-void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM) {
- unwrap(PM)->add(createDeadTypeEliminationPass());
-}
-
void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
unwrap(PM)->add(createFunctionAttrsPass());
}
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp
index f74144338a..183ba63e9f 100644
--- a/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/lib/Transforms/IPO/MergeFunctions.cpp
@@ -218,7 +218,6 @@ bool FunctionComparator::isEquivalentType(const Type *Ty1,
llvm_unreachable("Unknown type!");
// Fall through in Release mode.
case Type::IntegerTyID:
- case Type::OpaqueTyID:
case Type::VectorTyID:
// Ty1 == Ty2 would have returned true earlier.
return false;
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp
index a690765108..5bacdf57fc 100644
--- a/lib/Transforms/IPO/StripSymbols.cpp
+++ b/lib/Transforms/IPO/StripSymbols.cpp
@@ -28,8 +28,8 @@
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
@@ -174,13 +174,19 @@ static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
}
}
-// Strip the symbol table of its names.
-static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
- for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
- if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
- ++TI;
- else
- ST.remove(TI++);
+// Strip any named types of their names.
+static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
+ std::vector<StructType*> StructTypes;
+ M.findUsedStructTypes(StructTypes);
+
+ for (unsigned i = 0, e = StructTypes.size(); i != e; ++i) {
+ StructType *STy = StructTypes[i];
+ if (STy->isAnonymous() || STy->getName().empty()) continue;
+
+ if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg"))
+ continue;
+
+ STy->setName("");
}
}
@@ -221,7 +227,7 @@ static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
}
// Remove all names from types.
- StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);
+ StripTypeNames(M, PreserveDbgInfo);
return true;
}
diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp
index 1046c38ec0..a08fa35065 100644
--- a/lib/Transforms/Utils/CloneModule.cpp
+++ b/lib/Transforms/Utils/CloneModule.cpp
@@ -15,7 +15,6 @@
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/TypeSymbolTable.h"
#include "llvm/Constant.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;
@@ -32,20 +31,13 @@ Module *llvm::CloneModule(const Module *M) {
return CloneModule(M, VMap);
}
-Module *llvm::CloneModule(const Module *M,
- ValueToValueMapTy &VMap) {
- // First off, we need to create the new module...
+Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) {
+ // First off, we need to create the new module.
Module *New = new Module(M->getModuleIdentifier(), M->getContext());
New->setDataLayout(M->getDataLayout());
New->setTargetTriple(M->getTargetTriple());
New->setModuleInlineAsm(M->getModuleInlineAsm());
-
- // Copy all of the type symbol table entries over.
- const TypeSymbolTable &TST = M->getTypeSymbolTable();
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI)
- New->addTypeName(TI->first, TI->second);
-
+
// Copy all of the dependent libraries over.
for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I)
New->addLibrary(*I);
@@ -88,8 +80,7 @@ Module *llvm::CloneModule(const Module *M,
I != E; ++I) {
GlobalVariable *GV = cast<GlobalVariable>(VMap[I]);
if (I->hasInitializer())
- GV->setInitializer(cast<Constant>(MapValue(I->getInitializer(),
- VMap, RF_None)));
+ GV->setInitializer(MapValue(I->getInitializer(), VMap));
GV->setLinkage(I->getLinkage());
GV->setThreadLocal(I->isThreadLocal());
GV->setConstant(I->isConstant());
@@ -119,8 +110,8 @@ Module *llvm::CloneModule(const Module *M,
I != E; ++I) {
GlobalAlias *GA = cast<GlobalAlias>(VMap[I]);
GA->setLinkage(I->getLinkage());
- if (const Constant* C = I->getAliasee())
- GA->setAliasee(cast<Constant>(MapValue(C, VMap, RF_None)));
+ if (const Constant *C = I->getAliasee())
+ GA->setAliasee(MapValue(C, VMap));
}
// And named metadata....
@@ -129,8 +120,7 @@ Module *llvm::CloneModule(const Module *M,
const NamedMDNode &NMD = *I;
NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
- NewNMD->addOperand(cast<MDNode>(MapValue(NMD.getOperand(i), VMap,
- RF_None)));
+ NewNMD->addOperand(MapValue(NMD.getOperand(i), VMap));
}
return New;
diff --git a/lib/Transforms/Utils/LowerInvoke.cpp b/lib/Transforms/Utils/LowerInvoke.cpp
index 025ae0d616..3450316721 100644
--- a/lib/Transforms/Utils/LowerInvoke.cpp
+++ b/lib/Transforms/Utils/LowerInvoke.cpp
@@ -66,7 +66,7 @@ namespace {
Constant *AbortFn;
// Used for expensive EH support.
- const Type *JBLinkTy;
+ StructType *JBLinkTy;
GlobalVariable *JBListHead;
Constant *SetJmpFn, *LongJmpFn, *StackSaveFn, *StackRestoreFn;
bool useExpensiveEHSupport;
@@ -120,24 +120,16 @@ FunctionPass *llvm::createLowerInvokePass(const TargetLowering *TLI,
// doInitialization - Make sure that there is a prototype for abort in the
// current module.
bool LowerInvoke::doInitialization(Module &M) {
- const Type *VoidPtrTy =
- Type::getInt8PtrTy(M.getContext());
+ const Type *VoidPtrTy = Type::getInt8PtrTy(M.getContext());
if (useExpensiveEHSupport) {
// Insert a type for the linked list of jump buffers.
unsigned JBSize = TLI ? TLI->getJumpBufSize() : 0;
JBSize = JBSize ? JBSize : 200;
- const Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
-
- { // The type is recursive, so use a type holder.
- std::vector<const Type*> Elements;
- Elements.push_back(JmpBufTy);
- OpaqueType *OT = OpaqueType::get(M.getContext());
- Elements.push_back(PointerType::getUnqual(OT));
- PATypeHolder JBLType(StructType::get(M.getContext(), Elements));
- OT->refineAbstractTypeTo(JBLType.get()); // Complete the cycle.
- JBLinkTy = JBLType.get();
- M.addTypeName("llvm.sjljeh.jmpbufty", JBLinkTy);
- }
+ Type *JmpBufTy = ArrayType::get(VoidPtrTy, JBSize);
+
+ JBLinkTy = StructType::createNamed(M.getContext(), "llvm.sjljeh.jmpbufty");
+ Type *Elts[] = { JmpBufTy, PointerType::getUnqual(JBLinkTy) };
+ JBLinkTy->setBody(Elts);
const Type *PtrJBList = PointerType::getUnqual(JBLinkTy);
diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp
index de6cbdc92d..30fc60081d 100644
--- a/lib/Transforms/Utils/ValueMapper.cpp
+++ b/lib/Transforms/Utils/ValueMapper.cpp
@@ -13,16 +13,17 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/ValueMapper.h"
-#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Metadata.h"
-#include "llvm/ADT/SmallVector.h"
using namespace llvm;
-Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
- RemapFlags Flags) {
+// Out of line method to get vtable etc for class.
+void ValueMapTypeRemapper::Anchor() {}
+
+Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags,
+ ValueMapTypeRemapper *TypeMapper) {
ValueToValueMapTy::iterator I = VM.find(V);
// If the value already exists in the map, use it.
@@ -46,14 +47,14 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
// Check all operands to see if any need to be remapped.
for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) {
Value *OP = MD->getOperand(i);
- if (OP == 0 || MapValue(OP, VM, Flags) == OP) continue;
+ if (OP == 0 || MapValue(OP, VM, Flags, TypeMapper) == OP) continue;
// Ok, at least one operand needs remapping.
SmallVector<Value*, 4> Elts;
Elts.reserve(MD->getNumOperands());
for (i = 0; i != e; ++i) {
Value *Op = MD->getOperand(i);
- Elts.push_back(Op ? MapValue(Op, VM, Flags) : 0);
+ Elts.push_back(Op ? MapValue(Op, VM, Flags, TypeMapper) : 0);
}
MDNode *NewMD = MDNode::get(V->getContext(), Elts);
Dummy->replaceAllUsesWith(NewMD);
@@ -76,51 +77,75 @@ Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM,
return 0;
if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
- Function *F = cast<Function>(MapValue(BA->getFunction(), VM, Flags));
+ Function *F =
+ cast<Function>(MapValue(BA->getFunction(), VM, Flags, TypeMapper));
BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(), VM,
- Flags));
+ Flags, TypeMapper));
return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
}
- for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
- Value *Op = C->getOperand(i);
- Value *Mapped = MapValue(Op, VM, Flags);
- if (Mapped == C) continue;
-
- // Okay, the operands don't all match. We've already processed some or all
- // of the operands, set them up now.
- std::vector<Constant*> Ops;
- Ops.reserve(C->getNumOperands());
- for (unsigned j = 0; j != i; ++j)
- Ops.push_back(cast<Constant>(C->getOperand(i)));
+ // Otherwise, we have some other constant to remap. Start by checking to see
+ // if all operands have an identity remapping.
+ unsigned OpNo = 0, NumOperands = C->getNumOperands();
+ Value *Mapped = 0;
+ for (; OpNo != NumOperands; ++OpNo) {
+ Value *Op = C->getOperand(OpNo);
+ Mapped = MapValue(Op, VM, Flags, TypeMapper);
+ if (Mapped != C) break;
+ }
+
+ // See if the type mapper wants to remap the type as well.
+ Type *NewTy = C->getType();
+ if (TypeMapper)
+ NewTy = TypeMapper->remapType(NewTy);
+
+ // If the result type and all operands match up, then just insert an identity
+ // mapping.
+ if (OpNo == NumOperands && NewTy == C->getType())
+ return VM[V] = C;
+
+ // Okay, we need to create a new constant. We've already processed some or
+ // all of the operands, set them all up now.
+ SmallVector<Constant*, 8> Ops;
+ Ops.reserve(NumOperands);
+ for (unsigned j = 0; j != OpNo; ++j)
+ Ops.push_back(cast<Constant>(C->getOperand(j)));
+
+ // If one of the operands mismatch, push it and the other mapped operands.
+ if (OpNo != NumOperands) {
Ops.push_back(cast<Constant>(Mapped));
-
+
// Map the rest of the operands that aren't processed yet.
- for (++i; i != e; ++i)
- Ops.push_back(cast<Constant>(MapValue(C->getOperand(i), VM, Flags)));
-
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
- return VM[V] = CE->getWithOperands(Ops);
- if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
- return VM[V] = ConstantArray::get(CA->getType(), Ops);
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C))
- return VM[V] = ConstantStruct::get(CS->getType(), Ops);
- assert(isa<ConstantVector>(C) && "Unknown mapped constant type");
- return VM[V] = ConstantVector::get(Ops);
+ for (++OpNo; OpNo != NumOperands; ++OpNo)
+ Ops.push_back(MapValue(cast<Constant>(C->getOperand(OpNo)), VM,
+ Flags, TypeMapper));
}
-
- // If we reach here, all of the operands of the constant match.
- return VM[V] = C;
+
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
+ return VM[V] = CE->getWithOperands(Ops, NewTy);
+ if (isa<ConstantArray>(C))
+ return VM[V] = ConstantArray::get(cast<ArrayType>(NewTy), Ops);
+ if (isa<ConstantStruct>(C))
+ return VM[V] = ConstantStruct::get(cast<StructType>(NewTy), Ops);
+ if (isa<ConstantVector>(C))
+ return VM[V] = ConstantVector::get(Ops);
+ // If this is a no-operand constant, it must be because the type was remapped.
+ if (isa<UndefValue>(C))
+ return VM[V] = UndefValue::get(NewTy);
+ if (isa<ConstantAggregateZero>(C))
+ return VM[V] = ConstantAggregateZero::get(NewTy);
+ assert(isa<ConstantPointerNull>(C));
+ return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy));
}
/// RemapInstruction - Convert the instruction operands from referencing the
/// current values into those specified by VMap.
///
void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
- RemapFlags Flags) {
+ RemapFlags Flags, ValueMapTypeRemapper *TypeMapper){
// Remap operands.
for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
- Value *V = MapValue(*op, VMap, Flags);
+ Value *V = MapValue(*op, VMap, Flags, TypeMapper);
// If we aren't ignoring missing entries, assert that something happened.
if (V != 0)
*op = V;
@@ -147,9 +172,13 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap,
I->getAllMetadata(MDs);
for (SmallVectorImpl<std::pair<unsigned, MDNode *> >::iterator
MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) {
- Value *Old = MI->second;
- Value *New = MapValue(Old, VMap, Flags);
+ MDNode *Old = MI->second;
+ MDNode *New = MapValue(Old, VMap, Flags, TypeMapper);
if (New != Old)
- I->setMetadata(MI->first, cast<MDNode>(New));
+ I->setMetadata(MI->first, New);
}
+
+ // If the instruction's type is being remapped, do so now.
+ if (TypeMapper)
+ I->mutateType(TypeMapper->remapType(I->getType()));
}
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 496f500367..18776dd5a0 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -26,8 +26,7 @@
#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"
@@ -137,72 +136,57 @@ static void PrintLLVMName(raw_ostream &OS, const Value *V) {
/// TypePrinting - Type printing machinery.
namespace {
class TypePrinting {
- DenseMap<const Type *, std::string> TypeNames;
TypePrinting(const TypePrinting &); // DO NOT IMPLEMENT
void operator=(const TypePrinting&); // DO NOT IMPLEMENT
public:
- TypePrinting() {}
- ~TypePrinting() {}
-
- void clear() {
- TypeNames.clear();
- }
-
- void print(const Type *Ty, raw_ostream &OS, bool IgnoreTopLevelName = false);
+
+ /// NamedTypes - The named types that are used by the current module.
+ std::vector<StructType*> NamedTypes;
- void printAtLeastOneLevel(const Type *Ty, raw_ostream &OS) {
- print(Ty, OS, true);
- }
+ /// NumberedTypes - The numbered types, along with their value.
+ DenseMap<StructType*, unsigned> NumberedTypes;
- /// hasTypeName - Return true if the type has a name in TypeNames, false
- /// otherwise.
- bool hasTypeName(const Type *Ty) const {
- return TypeNames.count(Ty);
- }
+ TypePrinting() {}
+ ~TypePrinting() {}
- /// addTypeName - Add a name for the specified type if it doesn't already have
- /// one. This name will be printed instead of the structural version of the
- /// type in order to make the output more concise.
- void addTypeName(const Type *Ty, const std::string &N) {
- TypeNames.insert(std::make_pair(Ty, N));
- }
+ void incorporateTypes(const Module &M);
-private:
- void CalcTypeName(const Type *Ty, SmallVectorImpl<const Type *> &TypeStack,
- raw_ostream &OS, bool IgnoreTopLevelName = false);
+ void print(Type *Ty, raw_ostream &OS);
+
+ void printStructBody(StructType *Ty, raw_ostream &OS);
};
} // end anonymous namespace.
-/// 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 = 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;
+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());
+}
- TypeStack.push_back(Ty); // Recursive case: Add us to the stack..
+/// 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::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; break;
case Type::FloatTyID: OS << "float"; break;
@@ -215,257 +199,100 @@ 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.
- if (!IgnoreTopLevelName) {
- DenseMap<const Type*, std::string>::iterator I = TypeNames.find(Ty);
- if (I != TypeNames.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)
- TypeNames.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);
+ // FIXME: remove this function.
+ OS << *Ty;
}
//===----------------------------------------------------------------------===//
@@ -986,7 +813,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);
@@ -1043,7 +870,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 << '<';
@@ -1241,8 +1068,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 << ' ';
@@ -1259,14 +1086,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);
@@ -1279,7 +1106,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);
@@ -1374,9 +1201,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';
@@ -1534,7 +1359,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);
@@ -1560,26 +1388,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';
}
}
@@ -1893,9 +1735,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)
@@ -1926,9 +1768,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.
@@ -2011,7 +1853,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)
@@ -2131,7 +1973,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 {
@@ -2187,14 +2037,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/CMakeLists.txt b/lib/VMCore/CMakeLists.txt
index 6bde263ce6..f60dd06c98 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 b7a1350ff5..2c8f430176 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -1466,8 +1466,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)
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index 4e6e64d192..d3361ccfc4 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;
@@ -639,13 +640,13 @@ ConstantStruct::ConstantStruct(const StructType *T,
: 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;
}
@@ -653,14 +654,13 @@ ConstantStruct::ConstantStruct(const StructType *T,
// ConstantStruct accessors.
Constant *ConstantStruct::get(const StructType *ST, ArrayRef<Constant*> V) {
- assert(ST->getNumElements() == V.size() &&
- "Incorrect # elements specified to ConstantStruct::get");
-
// Create a ConstantAggregateZero value if all elements are zeros.
for (unsigned i = 0, e = V.size(); i != e; ++i)
if (!V[i]->isNullValue())
return ST->getContext().pImpl->StructConstants.getOrCreate(ST, V);
+ assert((ST->isOpaque() || ST->getNumElements() == V.size()) &&
+ "Incorrect # elements specified to ConstantStruct::get");
return ConstantAggregateZero::get(ST);
}
@@ -839,17 +839,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);
@@ -866,7 +864,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:
@@ -964,14 +962,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();
}
@@ -1050,14 +1048,14 @@ namespace llvm {
// 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();
}
@@ -1098,7 +1096,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();
}
@@ -1113,7 +1111,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();
}
@@ -1147,7 +1145,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();
@@ -1921,7 +1919,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();
}
@@ -1962,10 +1960,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;
@@ -1999,7 +1997,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;
@@ -2050,7 +2048,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.
@@ -2072,11 +2070,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;
@@ -2167,7 +2165,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
&Indices[0], Indices.size());
} 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);
diff --git a/lib/VMCore/ConstantsContext.h b/lib/VMCore/ConstantsContext.h
index ea6ebe9eaa..bd134d9b89 100644
--- a/lib/VMCore/ConstantsContext.h
+++ b/lib/VMCore/ConstantsContext.h
@@ -570,13 +570,11 @@ struct ConstantKeyData<InlineAsm> {
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, ValRefType V,
+ ConstantClass *Create(const TypeClass *Ty, ValRefType V,
typename MapTy::iterator I) {
ConstantClass* Result =
ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
@@ -667,8 +645,6 @@ private:
if (HasLargeKey) // Remember the reverse mapping if needed.
InverseMap.insert(std::make_pair(Result, I));
- AddAbstractTypeUser(Ty, I);
-
return Result;
}
public:
@@ -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 bdd988e7b0..d9ced94134 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:
@@ -382,9 +358,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 +365,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 ----------------------------------------------===*/
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index b8fa60a26d..972319e740 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.
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index 60000ad1b5..8f2d88740a 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) {
diff --git a/lib/VMCore/InlineAsm.cpp b/lib/VMCore/InlineAsm.cpp
index bd3667db76..5ae4a1bb94 100644
--- a/lib/VMCore/InlineAsm.cpp
+++ b/lib/VMCore/InlineAsm.cpp
@@ -47,7 +47,7 @@ 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;
}
diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp
index 0eddd5ada7..ecb3229693 100644
--- a/lib/VMCore/Instructions.cpp
+++ b/lib/VMCore/Instructions.cpp
@@ -372,7 +372,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)"
@@ -823,7 +823,7 @@ bool AllocaInst::isArrayAllocation() const {
return true;
}
-const Type *AllocaInst::getAllocatedType() const {
+Type *AllocaInst::getAllocatedType() const {
return getType()->getElementType();
}
@@ -1098,7 +1098,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) {
@@ -1108,7 +1108,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,
@@ -1126,60 +1126,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!
@@ -1482,9 +1472,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) {
+Type *ExtractValueInst::getIndexedType(const Type *Agg,
+ const unsigned *Idxs,
+ unsigned NumIdx) {
for (unsigned CurIdx = 0; CurIdx != NumIdx; ++CurIdx) {
unsigned Index = Idxs[CurIdx];
// We can't use CompositeType::indexValid(Index) here.
@@ -1505,19 +1495,11 @@ 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;
+ return const_cast<Type*>(Agg);
}
-const Type* ExtractValueInst::getIndexedType(const Type *Agg,
- unsigned Idx) {
+Type *ExtractValueInst::getIndexedType(const Type *Agg, unsigned Idx) {
return getIndexedType(Agg, &Idx, 1);
}
diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp
index ccb8dc500f..0b7ae6c927 100644
--- a/lib/VMCore/LLVMContextImpl.cpp
+++ b/lib/VMCore/LLVMContextImpl.cpp
@@ -31,14 +31,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 {
@@ -86,12 +82,7 @@ LLVMContextImpl::~LLVMContextImpl() {
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;
- }
+
// 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;
@@ -109,7 +100,6 @@ LLVMContextImpl::~LLVMContextImpl() {
"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) {
+ E = MDStringCache.end(); I != E; ++I)
delete I->second;
- }
}
diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h
index d8808b0ab8..e36864b27b 100644
--- a/lib/VMCore/LLVMContextImpl.h
+++ b/lib/VMCore/LLVMContextImpl.h
@@ -15,10 +15,9 @@
#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"
@@ -170,34 +169,22 @@ 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;
-
- 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;
+
+ 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 eb719e54b2..ace4dc2de2 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 341e527acb..1ca70161d6 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;
@@ -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.getAllMetadata(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 9299070920..734d43a017 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -12,81 +12,17 @@
//===----------------------------------------------------------------------===//
#include "LLVMContextImpl.h"
-#include "llvm/ADT/SCCIterator.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;
- }
-
- 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);
@@ -245,7 +181,11 @@ bool Type::isSizedDerivedType() const {
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;
@@ -253,703 +193,346 @@ 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!");
-}
-
-const 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();
-}
-const 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;
-}
-
-
//===----------------------------------------------------------------------===//
// 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 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);
+}
+
+APInt IntegerType::getMask() const {
+ return APInt::getAllOnesValue(getBitWidth());
}
-FunctionType::FunctionType(const Type *Result,
- ArrayRef<const Type*> Params,
+//===----------------------------------------------------------------------===//
+// FunctionType Implementation
+//===----------------------------------------------------------------------===//
+
+FunctionType::FunctionType(const Type *Result, ArrayRef<Type*> Params,
bool IsVarArgs)
: DerivedType(Result->getContext(), FunctionTyID) {
- ContainedTys = reinterpret_cast<PATypeHandle*>(this+1);
- NumContainedTys = Params.size() + 1; // + 1 for result type
+ Type **SubTys = reinterpret_cast<Type**>(this+1);
assert(isValidReturnType(Result) && "invalid return type for function");
setSubclassData(IsVarArgs);
- bool isAbstract = Result->isAbstract();
- new (&ContainedTys[0]) PATypeHandle(Result, this);
+ SubTys[0] = const_cast<Type*>(Result);
- 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();
- }
-
- // Calculate whether or not this type is abstract
- setAbstract(isAbstract);
-}
-
-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();
+ SubTys[i+1] = Params[i];
}
- // 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());
+ ContainedTys = SubTys;
+ NumContainedTys = Params.size() + 1; // + 1 for result type
}
-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");
-
+// FIXME: Remove this version.
+FunctionType *FunctionType::get(const Type *ReturnType,
+ ArrayRef<const Type*> Params, bool isVarArg) {
+ return get(ReturnType, ArrayRef<Type*>(const_cast<Type**>(Params.data()),
+ Params.size()), isVarArg);
}
+// 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);
+
+ FunctionType *&FT = ReturnType->getContext().pImpl->FunctionTypes[Key];
+
+ if (FT == 0) {
+ FT = (FunctionType*) operator new(sizeof(FunctionType) +
+ sizeof(Type*)*(Params.size()+1));
+ new (FT) FunctionType(ReturnType, Params, isVarArg);
+ }
-PointerType::PointerType(const Type *E, unsigned AddrSpace)
- : SequentialType(PointerTyID, E) {
- setSubclassData(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<const 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 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 = new 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;
-}
-
-/// TypeHasCycleThroughItself - Return true if the specified type has
-/// a cycle back to itself.
-
-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;
- }
- return false;
-}
+StructType *StructType::createNamed(LLVMContext &Context, StringRef Name) {
+ StructType *ST = new StructType(Context);
+ ST->setName(Name);
+ return ST;
}
-//===----------------------------------------------------------------------===//
-// 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");
+void StructType::setName(StringRef Name) {
+ if (Name == getName()) return;
- // 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;
+ // If this struct already had a name, remove its symbol table entry.
+ if (SymbolTableEntry) {
+ getContext().pImpl->NamedStructTypes.erase(getName());
+ SymbolTableEntry = 0;
}
-
- 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());
+// FIXME: Remove this version.
+StructType *StructType::get(LLVMContext &Context, ArrayRef<const Type*>Elements,
+ bool isPacked) {
+ return get(Context, ArrayRef<Type*>(const_cast<Type**>(Elements.data()),
+ Elements.size()), isPacked);
}
-FunctionType *FunctionType::get(const Type *Result, bool isVarArg) {
- return get(Result, ArrayRef<const Type *>(), isVarArg);
+StructType *StructType::get(LLVMContext &Context, bool isPacked) {
+ return get(Context, llvm::ArrayRef<const 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(const Type *type, ...) {
+ assert(type != 0 && "Cannot create a struct type with no elements with this");
+ LLVMContext &Ctx = type->getContext();
+ va_list ap;
+ SmallVector<const 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();
-}
-
-//===----------------------------------------------------------------------===//
-// Struct Type Factory.
-//
-
-StructType *StructType::get(LLVMContext &Context, bool isPacked) {
- return get(Context, llvm::ArrayRef<const Type*>(), isPacked);
+ return llvm::StructType::createNamed(Ctx, Name, StructFields);
}
-
-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(const Type *type, ...) {
+void StructType::setBody(Type *type, ...) {
assert(type != 0 && "Cannot create a struct type with no elements with this");
- LLVMContext &Ctx = type->getContext();
va_list ap;
- SmallVector<const llvm::Type*, 8> 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(Ctx, StructFields);
+ setBody(StructFields);
}
bool StructType::isValidElementType(const Type *ElemTy) {
@@ -957,267 +540,157 @@ 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!");
+
+ ArrayType *&Entry = ElementType->getContext().pImpl
+ ->ArrayTypes[std::make_pair(ElementType, NumElements)];
- this->destroy();
- }
+ if (Entry == 0)
+ Entry = new ArrayType(ElementType, NumElements);
+ return Entry;
}
-// 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!");
-
-#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!");
- }
+bool ArrayType::isValidElementType(const Type *ElemTy) {
+ return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() &&
+ !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy();
}
-// 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);
-}
+//===----------------------------------------------------------------------===//
+// VectorType Implementation
+//===----------------------------------------------------------------------===//
-void FunctionType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->FunctionTypes.TypeBecameConcrete(this, AbsTy);
+VectorType::VectorType(Type *ElType, unsigned NumEl)
+ : SequentialType(VectorTyID, ElType) {
+ NumElements = NumEl;
}
-
-// 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::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");
+
+ VectorType *&Entry = ElementType->getContext().pImpl
+ ->VectorTypes[std::make_pair(ElementType, NumElements)];
+
+ if (Entry == 0)
+ Entry = new VectorType(ElementType, NumElements);
+ return Entry;
}
-void ArrayType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->ArrayTypes.TypeBecameConcrete(this, AbsTy);
+bool VectorType::isValidElementType(const Type *ElemTy) {
+ return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy();
}
-// 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);
-}
+//===----------------------------------------------------------------------===//
+// PointerType Implementation
+//===----------------------------------------------------------------------===//
-void VectorType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->VectorTypes.TypeBecameConcrete(this, AbsTy);
-}
+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)];
-// 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);
+ if (Entry == 0)
+ Entry = new PointerType(EltTy, AddressSpace);
+ return Entry;
}
-void StructType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->StructTypes.TypeBecameConcrete(this, AbsTy);
-}
-// 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);
+PointerType::PointerType(Type *E, unsigned AddrSpace)
+ : SequentialType(PointerTyID, E) {
+ setSubclassData(AddrSpace);
}
-void PointerType::typeBecameConcrete(const DerivedType *AbsTy) {
- LLVMContextImpl *pImpl = AbsTy->getContext().pImpl;
- pImpl->PointerTypes.TypeBecameConcrete(this, AbsTy);
+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 80c6a74790..0000000000
--- a/lib/VMCore/TypeSymbolTable.cpp
+++ /dev/null
@@ -1,168 +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 << "\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 << "\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 << "\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 << "\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 << "\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 << "\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 << "\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 ad09478bbc..0000000000
--- 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/Value.cpp b/lib/VMCore/Value.cpp
index a03cddc9d5..c7a4212614 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!");
}
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 18de67155f..c35d5ad2b6 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,
@@ -1192,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);
}
@@ -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