From: Chris Lattner Date: Sun, 7 Jan 2007 08:09:25 +0000 (+0000) Subject: Change the interface to Module::getOrInsertFunction to be easier to use, X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=70d130516a38013ef6262dd2da5accbea7932e30;p=oota-llvm.git Change the interface to Module::getOrInsertFunction to be easier to use, to resolve PR1088, and to help PR411. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32988 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Module.h b/include/llvm/Module.h index e5c157be954..85fdb868edb 100644 --- a/include/llvm/Module.h +++ b/include/llvm/Module.h @@ -166,15 +166,21 @@ public: /// @{ public: /// getOrInsertFunction - Look up the specified function in the module symbol - /// table. If it does not exist, add a prototype for the function and return - /// it. - Function *getOrInsertFunction(const std::string &Name, const FunctionType *T); + /// table. Four possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. If it exists, and has internal linkage, the existing function is + /// renamed and a new one is inserted. + /// 3. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 4. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + Constant *getOrInsertFunction(const std::string &Name, const FunctionType *T); /// getOrInsertFunction - Look up the specified function in the module symbol /// table. If it does not exist, add a prototype for the function and return /// it. This version of the method takes a null terminated list of function /// arguments, which makes it easier for clients to use. - Function *getOrInsertFunction(const std::string &Name, const Type *RetTy,...) + Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy,...) END_WITH_NULL; /// getFunction - Look up the specified function in the module symbol table. diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp index 98faff1d332..30935dd4ce6 100644 --- a/lib/VMCore/Module.cpp +++ b/lib/VMCore/Module.cpp @@ -152,23 +152,35 @@ void Module::setPointerSize(PointerSize PS) { // Methods for easy access to the functions in the module. // -// getOrInsertFunction - Look up the specified function in the module symbol -// table. If it does not exist, add a prototype for the function and return -// it. This is nice because it allows most passes to get away with not handling -// the symbol table directly for this common task. -// -Function *Module::getOrInsertFunction(const std::string &Name, +Constant *Module::getOrInsertFunction(const std::string &Name, const FunctionType *Ty) { SymbolTable &SymTab = getValueSymbolTable(); - // See if we have a definitions for the specified function already... - if (Value *V = SymTab.lookup(PointerType::get(Ty), Name)) { - return cast(V); // Yup, got it - } else { // Nope, add one + // See if we have a definitions for the specified function already. + Function *F = + dyn_cast_or_null(SymTab.lookup(PointerType::get(Ty), Name)); + if (F == 0) { + // Nope, add it. Function *New = new Function(Ty, GlobalVariable::ExternalLinkage, Name); FunctionList.push_back(New); - return New; // Return the new prototype... + return New; // Return the new prototype. + } + + // Okay, the function exists. Does it have externally visible linkage? + if (F->hasInternalLinkage()) { + // Rename the function. + F->setName(SymTab.getUniqueName(F->getType(), F->getName())); + // Retry, now there won't be a conflict. + return getOrInsertFunction(Name, Ty); } + + // If the function exists but has the wrong type, return a bitcast to the + // right type. + if (F->getFunctionType() != Ty) + return ConstantExpr::getBitCast(F, PointerType::get(Ty)); + + // Otherwise, we just found the existing function or a prototype. + return F; } // getOrInsertFunction - Look up the specified function in the module symbol @@ -176,7 +188,7 @@ Function *Module::getOrInsertFunction(const std::string &Name, // This version of the method takes a null terminated list of function // arguments, which makes it easier for clients to use. // -Function *Module::getOrInsertFunction(const std::string &Name, +Constant *Module::getOrInsertFunction(const std::string &Name, const Type *RetTy, ...) { va_list Args; va_start(Args, RetTy);