//===- lib/Linker/LinkModules.cpp - Module Linker Implementation ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Instructions.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Path.h"
#include <sstream>
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 std::string &Message) {
if (E) *E = Message;
return true;
}
// ToStr - Simple wrapper function to convert a type to a string.
static std::string ToStr(const Type *Ty, const Module *M) {
std::ostringstream OS;
WriteTypeSymbolic(OS, Ty, M);
return OS.str();
}
//
// 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.
// Name - The name of the type.
//
// 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,
TypeSymbolTable *DestST, const std::string &Name) {
if (DestTy == SrcTy) return false; // If already equal, noop
// Does the type already exist in the module?
if (DestTy && !isa<OpaqueType>(DestTy)) { // Yup, the type already exists...
if (const OpaqueType *OT = dyn_cast<OpaqueType>(SrcTy)) {
const_cast<OpaqueType*>(OT)->refineAbstractTypeTo(DestTy);
} else {
return true; // Cannot link types... neither is opaque and not-equal
}
} else { // Type not in dest module. Add it now.
if (DestTy) // Type _is_ in module, just opaque...
const_cast<OpaqueType*>(cast<OpaqueType>(DestTy))
->refineAbstractTypeTo(SrcTy);
else if (!Name.empty())
DestST->insert(Name, const_cast<Type*>(SrcTy));
}
return false;
}
static const FunctionType *getFT(const PATypeHolder &TH) {
return cast<FunctionType>(TH.get());
}
static const StructType *getST(const PATypeHolder &TH) {
return cast<StructType>(TH.get());
}
// 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 PATypeHolder &DestTy,
const PATypeHolder &SrcTy,
TypeSymbolTable *DestST,
const std::string &Name,
std::vector<std::pair<PATypeHolder, PATypeHolder> > &Pointers) {
const Type *SrcTyT = SrcTy.get();
const Type *DestTyT = DestTy.get();
if (DestTyT == SrcTyT) return false; // If already equal, noop
// If we found our opaque type, resolve it now!
if (isa<OpaqueType>(DestTyT) || isa<OpaqueType>(SrcTyT))
return ResolveTypes(DestTyT, SrcTyT, DestST, Name);
// Two types cannot be resolved together if they are of different primitive
// type. For example, we cannot resolve an int to a float.
if (DestTyT->getTypeID() != SrcTyT->getTypeID()) return true;
// Otherwise, resolve the used type used by this derived type...
switch (DestTyT->getTypeID()) {
case Type::IntegerTyID: {
if (cast<IntegerType>(DestTyT)->getBitWidth() !=
cast<IntegerType>(SrcTyT)->getBitWidth())
return true;
return false;
}
case Type::FunctionTyID: {
if (cast<FunctionType>(DestTyT)->isVarArg() !=
cast<FunctionType>(SrcTyT)->isVarArg() ||
cast<FunctionType>(DestTyT)->getNumContainedTypes() !=
cast<FunctionType>(SrcTyT)->getNumContainedTypes())
return true;
for (unsigned i = 0, e = getFT(DestTy)->getNumContainedTypes(); i != e; ++i)
if (RecursiveResolveTypesI(getFT(DestTy)->getContainedType(i),