//===- lib/Linker/LinkModules.cpp - Module Linker Implementation ----------===//
//
// 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 LLVM module linker.
//
//===----------------------------------------------------------------------===//
#include "llvm/Linker.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Path.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// TypeMap implementation.
//===----------------------------------------------------------------------===//
namespace {
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:
/// 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);
};
}
void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) {
Type *&Entry = MappedTypes[SrcTy];
if (Entry) return;
if (DstTy == SrcTy) {
Entry = DstTy;
return;
}
// 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();
}
/// 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;
}
// 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;
}
// 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;
}
}
// 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))
retur