From d36f3b0f92998a95acd43813557fd208909c7cff Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Tue, 6 Nov 2018 01:38:14 +0000 Subject: [PATCH] [LLVM-C] Improve Intrinsics Bindings Summary: Improve the intrinsic bindings with operations for - Retrieving and automatically inserting the declaration of an intrinsic by ID - Retrieving the name of a non-overloaded intrinsic by ID - Retrieving the name of an overloaded intrinsic by ID and overloaded parameter types Improve the echo test to copy non-overloaded intrinsics by ID. Reviewers: whitequark, deadalnix Reviewed By: whitequark Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D53626 llvm-svn: 346195 --- llvm/include/llvm-c/Core.h | 48 +++++++++++++++++++++++++++++++ llvm/lib/IR/Core.cpp | 44 ++++++++++++++++++++++++++++ llvm/test/Bindings/llvm-c/echo.ll | 16 +++++++++++ llvm/tools/llvm-c-test/echo.cpp | 12 +++++++- 4 files changed, 119 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index c905cfbb08d2..c093c0906ce3 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -2381,6 +2381,54 @@ void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn); */ unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); +/** + * Create or insert the declaration of an intrinsic. For overloaded intrinsics, + * parameter types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getDeclaration() + */ +LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod, + unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount); + +/** + * Retrieves the type of an intrinsic. For overloaded intrinsics, parameter + * types must be provided to uniquely identify an overload. + * + * @see llvm::Intrinsic::getType() + */ +LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, + LLVMTypeRef *ParamTypes, size_t ParamCount); + +/** + * Retrieves the name of an intrinsic. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength); + +/** + * Copies the name of an overloaded intrinsic identified by a given list of + * parameter types. + * + * Unlike LLVMIntrinsicGetName, the caller is responsible for freeing the + * returned string. + * + * @see llvm::Intrinsic::getName() + */ +const char *LLVMIntrinsicCopyOverloadedName(unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount, + size_t *NameLength); + +/** + * Obtain if the intrinsic identified by the given ID is overloaded. + * + * @see llvm::Intrinsic::isOverloaded() + */ +LLVMBool LLVMIntrinsicIsOverloaded(unsigned ID); + /** * Obtain the calling function of a function. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 028f9e6199da..f94b8a04738f 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2280,6 +2280,50 @@ unsigned LLVMGetIntrinsicID(LLVMValueRef Fn) { return 0; } +static Intrinsic::ID llvm_map_to_intrinsic_id(unsigned ID) { + assert(ID < llvm::Intrinsic::num_intrinsics && "Intrinsic ID out of range"); + return llvm::Intrinsic::ID(ID); +} + +LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod, + unsigned ID, + LLVMTypeRef *ParamTypes, + size_t ParamCount) { + ArrayRef Tys(unwrap(ParamTypes), ParamCount); + auto IID = llvm_map_to_intrinsic_id(ID); + return wrap(llvm::Intrinsic::getDeclaration(unwrap(Mod), IID, Tys)); +} + +const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength) { + auto IID = llvm_map_to_intrinsic_id(ID); + auto Str = llvm::Intrinsic::getName(IID); + *NameLength = Str.size(); + return Str.data(); +} + +LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID, + LLVMTypeRef *ParamTypes, size_t ParamCount) { + auto IID = llvm_map_to_intrinsic_id(ID); + ArrayRef Tys(unwrap(ParamTypes), ParamCount); + return wrap(llvm::Intrinsic::getType(*unwrap(Ctx), IID, Tys)); +} + +const 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::getName(IID, Tys); + *NameLength = Str.length(); + return strndup(Str.c_str(), Str.length()); +} + +LLVMBool LLVMIntrinsicIsOverloaded(unsigned ID) { + auto IID = llvm_map_to_intrinsic_id(ID); + return llvm::Intrinsic::isOverloaded(IID); +} + unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn) { return unwrap(Fn)->getCallingConv(); } diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index 580293b3d04e..118f822e432f 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -170,6 +170,22 @@ define void @with_debuginfo() !dbg !4 { ret void, !dbg !7 } +declare i8* @llvm.stacksave() +declare void @llvm.stackrestore(i8*) +declare void @llvm.lifetime.start.p0i8(i64, i8*) +declare void @llvm.lifetime.end.p0i8(i64, i8*) + +define void @test_intrinsics() { +entry: + %sp = call i8* @llvm.stacksave() + %x = alloca i32 + %0 = bitcast i32* %x to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) + call void @llvm.lifetime.end.p0i8(i64 4, i8* %0) + call void @llvm.stackrestore(i8* %sp) + ret void +} + !llvm.dbg.cu = !{!0, !2} !llvm.module.flags = !{!3} diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index d4c61e2d13c4..db926e8aceaa 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -240,7 +240,17 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) { // Try function if (LLVMIsAFunction(Cst)) { check_value_kind(Cst, LLVMFunctionValueKind); - LLVMValueRef Dst = LLVMGetNamedFunction(M, Name); + + LLVMValueRef Dst = nullptr; + // Try an intrinsic + unsigned ID = LLVMGetIntrinsicID(Cst); + if (ID > 0 && !LLVMIntrinsicIsOverloaded(ID)) { + Dst = LLVMGetIntrinsicDeclaration(M, ID, nullptr, 0); + } else { + // Try a normal function + Dst = LLVMGetNamedFunction(M, Name); + } + if (Dst) return Dst; report_fatal_error("Could not find function");