From 756bae5844677d36446e321ce226cca66548f209 Mon Sep 17 00:00:00 2001 From: AMS21 Date: Tue, 7 Oct 2025 09:19:57 +0200 Subject: [PATCH] [LLVM-C] Upstream `LLVMGetOrInsertFunction` from rustc Add `LLVMGetOrInsertFunction` to the C API as a thin wrapper over `Module::getOrInsertFunction`, upstreamed from rustc (https://github.com/rust-lang/rust/blob/d773bd07d63a74adcf25ea5f4aae986be94cac5e/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp#L203) It provides a single-call way to get or create a function declaration, avoiding `LLVMGetNamedFunction` + `LLVMAddFunction` and is more idiomatic. --- llvm/docs/ReleaseNotes.md | 2 ++ llvm/include/llvm-c/Core.h | 16 ++++++++++++++++ llvm/lib/IR/Core.cpp | 8 ++++++++ llvm/unittests/IR/FunctionTest.cpp | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+) 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