diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index 85c16b9c33f10..78c8f6ec153a4 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -146,6 +146,8 @@ Changes to the Python bindings Changes to the C API -------------------- +* Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`. + Changes to the CodeGen infrastructure ------------------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index d02cf984167c9..3d22f85911e78 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -1206,6 +1206,22 @@ LLVM_C_ABI unsigned LLVMGetDebugLocColumn(LLVMValueRef Val); LLVM_C_ABI LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy); +/** + * Obtain or insert a function into a module. + * + * If a function with the specified name already exists in the module, it + * is returned. Otherwise, a new function is created in the module with the + * specified name and type and is returned. + * + * The returned value corresponds to a llvm::Function instance. + * + * @see llvm::Module::getOrInsertFunction() + */ +LLVM_C_ABI LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, + const char *Name, + size_t NameLen, + LLVMTypeRef FunctionTy); + /** * Obtain a Function value from a Module by its name. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index df0c85b87ba60..3f1cc1e4e6d0e 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2403,6 +2403,14 @@ LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, GlobalValue::ExternalLinkage, Name, unwrap(M))); } +LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, const char *Name, + size_t NameLen, LLVMTypeRef FunctionTy) { + return wrap(unwrap(M) + ->getOrInsertFunction(StringRef(Name, NameLen), + unwrap(FunctionTy)) + .getCallee()); +} + LLVMValueRef LLVMGetNamedFunction(LLVMModuleRef M, const char *Name) { return wrap(unwrap(M)->getFunction(Name)); } diff --git a/llvm/unittests/IR/FunctionTest.cpp b/llvm/unittests/IR/FunctionTest.cpp index 7ba7584e22976..8ed76999dc13d 100644 --- a/llvm/unittests/IR/FunctionTest.cpp +++ b/llvm/unittests/IR/FunctionTest.cpp @@ -625,4 +625,23 @@ TEST(FunctionTest, Personality) { EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F))); } +TEST(FunctionTest, LLVMGetOrInsertFunction) { + LLVMContext Ctx; + Module M("test", Ctx); + Type *Int8Ty = Type::getInt8Ty(Ctx); + FunctionType *FTy = FunctionType::get(Int8Ty, false); + + // Create the function using the C API + LLVMValueRef FuncRef = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy)); + + // Verify that the returned value is a function and has the correct type + Function *Func = unwrap(FuncRef); + EXPECT_EQ(Func->getName(), "F"); + EXPECT_EQ(Func->getFunctionType(), FTy); + + // Call LLVMGetOrInsertFunction again to ensure it returns the same function + LLVMValueRef FuncRef2 = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy)); + EXPECT_EQ(FuncRef, FuncRef2); +} + } // end namespace