diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index 0c4cd437dac0b..f1c6f6b2c3e8a 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -258,6 +258,10 @@ Changes to the C API * Added `LLVMAtomicRMWBinOpUSubCond` and `LLVMAtomicRMWBinOpUSubSat` to `LLVMAtomicRMWBinOp` enum for AtomicRMW instructions. +* Added `LLVMIntrinsicCopyName` and changed `LLVMIntrinsicCopyOverloadedName` + and `LLVMIntrinsicCopyOverloadedName2` to return `char *` instead of + `const char *`. + Changes to the CodeGen infrastructure ------------------------------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 55649d89a6b8f..a84a247c57200 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -2833,11 +2833,17 @@ LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, */ const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength); +/** + * Copies the name of an intrinsic. The caller is responsible for freeing the + * returned string. + * + * @see llvm::Intrinsic::getName() + */ +char *LLVMIntrinsicCopyName(unsigned ID, size_t *NameLength); + /** Deprecated: Use LLVMIntrinsicCopyOverloadedName2 instead. */ -const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, - LLVMTypeRef *ParamTypes, - size_t ParamCount, - size_t *NameLength); +char *LLVMIntrinsicCopyOverloadedName(unsigned ID, LLVMTypeRef *ParamTypes, + size_t ParamCount, size_t *NameLength); /** * Copies the name of an overloaded intrinsic identified by a given list of @@ -2850,10 +2856,9 @@ const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, * * @see llvm::Intrinsic::getName() */ -const char *LLVMIntrinsicCopyOverloadedName2(LLVMModuleRef Mod, unsigned ID, - LLVMTypeRef *ParamTypes, - size_t ParamCount, - size_t *NameLength); +char *LLVMIntrinsicCopyOverloadedName2(LLVMModuleRef Mod, unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount, size_t *NameLength); /** * Obtain if the intrinsic identified by the given ID is overloaded. diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 1cf998c685006..65572116e48ca 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2478,6 +2478,13 @@ const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength) { return Str.data(); } +char *LLVMIntrinsicCopyName(unsigned ID, size_t *NameLength) { + auto IID = llvm_map_to_intrinsic_id(ID); + auto Str = llvm::Intrinsic::getName(IID); + *NameLength = Str.size(); + return strdup(Str.data()); +} + LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, LLVMTypeRef *ParamTypes, size_t ParamCount) { auto IID = llvm_map_to_intrinsic_id(ID); @@ -2485,10 +2492,8 @@ LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, return wrap(llvm::Intrinsic::getType(*unwrap(Ctx), IID, Tys)); } -const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, - LLVMTypeRef *ParamTypes, - size_t ParamCount, - size_t *NameLength) { +char *LLVMIntrinsicCopyOverloadedName(unsigned ID, LLVMTypeRef *ParamTypes, + size_t ParamCount, size_t *NameLength) { auto IID = llvm_map_to_intrinsic_id(ID); ArrayRef Tys(unwrap(ParamTypes), ParamCount); auto Str = llvm::Intrinsic::getNameNoUnnamedTypes(IID, Tys); @@ -2496,10 +2501,9 @@ const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, return strdup(Str.c_str()); } -const char *LLVMIntrinsicCopyOverloadedName2(LLVMModuleRef Mod, unsigned ID, - LLVMTypeRef *ParamTypes, - size_t ParamCount, - size_t *NameLength) { +char *LLVMIntrinsicCopyOverloadedName2(LLVMModuleRef Mod, unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount, size_t *NameLength) { auto IID = llvm_map_to_intrinsic_id(ID); ArrayRef Tys(unwrap(ParamTypes), ParamCount); auto Str = llvm::Intrinsic::getName(IID, Tys, unwrap(Mod)); diff --git a/llvm/unittests/IR/IntrinsicsTest.cpp b/llvm/unittests/IR/IntrinsicsTest.cpp index b32a199144859..afba07a12e8ca 100644 --- a/llvm/unittests/IR/IntrinsicsTest.cpp +++ b/llvm/unittests/IR/IntrinsicsTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Intrinsics.h" +#include "llvm-c/Core.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Constant.h" #include "llvm/IR/IRBuilder.h" @@ -127,6 +128,50 @@ TEST(IntrinsicNameLookup, MSBuiltinLookup) { EXPECT_EQ(ID, getIntrinsicForMSBuiltin(Target, Builtin)); } +// Test C API to get/copy LLVM intrinsic name. +TEST(IntrinsicNameLookup, LLVMIntrinsicGetCopyNameSimple) { + static constexpr struct { + Intrinsic::ID ID; + const char *Name; + } Tests[] = {{Intrinsic::not_intrinsic, "not_intrinsic"}, + {Intrinsic::assume, "llvm.assume"}, + {Intrinsic::coro_free, "llvm.coro.free"}, + {Intrinsic::aarch64_break, "llvm.aarch64.break"}, + {Intrinsic::x86_int, "llvm.x86.int"}}; + + for (auto [ID, ExpectedName] : Tests) { + size_t NameSize = 0; + const char *CName = LLVMIntrinsicGetName(ID, &NameSize); + StringRef Name(CName, NameSize); + + // Verify we get correct name. + EXPECT_EQ(Name, ExpectedName); + const char *CName1 = LLVMIntrinsicGetName(ID, &NameSize); + + // Verify we get the same pointer and length the second time. + EXPECT_EQ(CName, CName1); + EXPECT_EQ(NameSize, Name.size()); + } + + // Now test the copy API. + for (auto [ID, ExpectedName] : Tests) { + size_t NameSize = 0; + char *CName = LLVMIntrinsicCopyName(ID, &NameSize); + StringRef Name(CName, NameSize); + + // Verify we get correct name. + EXPECT_EQ(Name, ExpectedName); + + // Verify we get the different pointer and same length the second time. + char *CName1 = LLVMIntrinsicCopyName(ID, &NameSize); + EXPECT_NE(CName, CName1); + EXPECT_EQ(NameSize, Name.size()); + + free(CName); + free(CName1); + } +} + TEST_F(IntrinsicsTest, InstrProfInheritance) { auto isInstrProfInstBase = [](const Instruction &I) { return isa(I);