Skip to content

Commit 756bae5

Browse files
committed
[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.
1 parent fee71a3 commit 756bae5

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ Changes to the Python bindings
146146
Changes to the C API
147147
--------------------
148148

149+
* Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`.
150+
149151
Changes to the CodeGen infrastructure
150152
-------------------------------------
151153

llvm/include/llvm-c/Core.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,22 @@ LLVM_C_ABI unsigned LLVMGetDebugLocColumn(LLVMValueRef Val);
12061206
LLVM_C_ABI LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name,
12071207
LLVMTypeRef FunctionTy);
12081208

1209+
/**
1210+
* Obtain or insert a function into a module.
1211+
*
1212+
* If a function with the specified name already exists in the module, it
1213+
* is returned. Otherwise, a new function is created in the module with the
1214+
* specified name and type and is returned.
1215+
*
1216+
* The returned value corresponds to a llvm::Function instance.
1217+
*
1218+
* @see llvm::Module::getOrInsertFunction()
1219+
*/
1220+
LLVM_C_ABI LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
1221+
const char *Name,
1222+
size_t NameLen,
1223+
LLVMTypeRef FunctionTy);
1224+
12091225
/**
12101226
* Obtain a Function value from a Module by its name.
12111227
*

llvm/lib/IR/Core.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,6 +2403,14 @@ LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name,
24032403
GlobalValue::ExternalLinkage, Name, unwrap(M)));
24042404
}
24052405

2406+
LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M, const char *Name,
2407+
size_t NameLen, LLVMTypeRef FunctionTy) {
2408+
return wrap(unwrap(M)
2409+
->getOrInsertFunction(StringRef(Name, NameLen),
2410+
unwrap<FunctionType>(FunctionTy))
2411+
.getCallee());
2412+
}
2413+
24062414
LLVMValueRef LLVMGetNamedFunction(LLVMModuleRef M, const char *Name) {
24072415
return wrap(unwrap(M)->getFunction(Name));
24082416
}

llvm/unittests/IR/FunctionTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,4 +625,23 @@ TEST(FunctionTest, Personality) {
625625
EXPECT_FALSE(LLVMHasPersonalityFn(wrap(F)));
626626
}
627627

628+
TEST(FunctionTest, LLVMGetOrInsertFunction) {
629+
LLVMContext Ctx;
630+
Module M("test", Ctx);
631+
Type *Int8Ty = Type::getInt8Ty(Ctx);
632+
FunctionType *FTy = FunctionType::get(Int8Ty, false);
633+
634+
// Create the function using the C API
635+
LLVMValueRef FuncRef = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy));
636+
637+
// Verify that the returned value is a function and has the correct type
638+
Function *Func = unwrap<Function>(FuncRef);
639+
EXPECT_EQ(Func->getName(), "F");
640+
EXPECT_EQ(Func->getFunctionType(), FTy);
641+
642+
// Call LLVMGetOrInsertFunction again to ensure it returns the same function
643+
LLVMValueRef FuncRef2 = LLVMGetOrInsertFunction(wrap(&M), "F", 1, wrap(FTy));
644+
EXPECT_EQ(FuncRef, FuncRef2);
645+
}
646+
628647
} // end namespace

0 commit comments

Comments
 (0)