[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
This commit is contained in:
Robert Widmann 2018-11-06 01:38:14 +00:00
parent 2e61186c42
commit d36f3b0f92
4 changed files with 119 additions and 1 deletions

View File

@ -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.
*

View File

@ -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<Type*> 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<Type*> 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<Type*> 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<Function>(Fn)->getCallingConv();
}

View File

@ -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}

View File

@ -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");