[LLVM-C] Add Bindings to GlobalIFunc

Summary:
Adds the standard gauntlet of accessors for global indirect functions and updates the echo test.

Now it would be nice to have a target abstraction so one could know if they have access to a suitable ELF linker and runtime.

Reviewers: whitequark, deadalnix

Reviewed By: whitequark

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D56177

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353193 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Robert Widmann 2019-02-05 18:05:44 +00:00
parent abae4d3487
commit 005e630f24
4 changed files with 245 additions and 2 deletions

View File

@ -2607,6 +2607,103 @@ LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg);
*/
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned Align);
/**
* @}
*/
/**
* @defgroup LLVMCCoreValueGlobalIFunc IFuncs
*
* Functions in this group relate to indirect functions.
*
* Functions in this group expect LLVMValueRef instances that correspond
* to llvm::GlobalIFunc instances.
*
* @{
*/
/**
* Add a global indirect function to a module under a specified name.
*
* @see llvm::GlobalIFunc::create()
*/
LLVMValueRef LLVMAddGlobalIFunc(LLVMModuleRef M,
const char *Name, size_t NameLen,
LLVMTypeRef Ty, unsigned AddrSpace,
LLVMValueRef Resolver);
/**
* Obtain a GlobalIFunc value from a Module by its name.
*
* The returned value corresponds to a llvm::GlobalIFunc value.
*
* @see llvm::Module::getNamedIFunc()
*/
LLVMValueRef LLVMGetNamedGlobalIFunc(LLVMModuleRef M,
const char *Name, size_t NameLen);
/**
* Obtain an iterator to the first GlobalIFunc in a Module.
*
* @see llvm::Module::ifunc_begin()
*/
LLVMValueRef LLVMGetFirstGlobalIFunc(LLVMModuleRef M);
/**
* Obtain an iterator to the last GlobalIFunc in a Module.
*
* @see llvm::Module::ifunc_end()
*/
LLVMValueRef LLVMGetLastGlobalIFunc(LLVMModuleRef M);
/**
* Advance a GlobalIFunc iterator to the next GlobalIFunc.
*
* Returns NULL if the iterator was already at the end and there are no more
* global aliases.
*/
LLVMValueRef LLVMGetNextGlobalIFunc(LLVMValueRef IFunc);
/**
* Decrement a GlobalIFunc iterator to the previous GlobalIFunc.
*
* Returns NULL if the iterator was already at the beginning and there are
* no previous global aliases.
*/
LLVMValueRef LLVMGetPreviousGlobalIFunc(LLVMValueRef IFunc);
/**
* Retrieves the resolver function associated with this indirect function, or
* NULL if it doesn't not exist.
*
* @see llvm::GlobalIFunc::getResolver()
*/
LLVMValueRef LLVMGetGlobalIFuncResolver(LLVMValueRef IFunc);
/**
* Sets the resolver function associated with this indirect function.
*
* @see llvm::GlobalIFunc::setResolver()
*/
void LLVMSetGlobalIFuncResolver(LLVMValueRef IFunc, LLVMValueRef Resolver);
/**
* Remove a global indirect function from its parent module and delete it.
*
* @see llvm::GlobalIFunc::eraseFromParent()
*/
void LLVMEraseGlobalIFunc(LLVMValueRef IFunc);
/**
* Remove a global indirect function from its parent module.
*
* This unlinks the global indirect function from its containing module but
* keeps it alive.
*
* @see llvm::GlobalIFunc::removeFromParent()
*/
void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc);
/**
* @}
*/

View File

@ -2463,6 +2463,71 @@ void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align) {
A->addAttr(Attribute::getWithAlignment(A->getContext(), align));
}
/*--.. Operations on ifuncs ................................................--*/
LLVMValueRef LLVMAddGlobalIFunc(LLVMModuleRef M,
const char *Name, size_t NameLen,
LLVMTypeRef Ty, unsigned AddrSpace,
LLVMValueRef Resolver) {
return wrap(GlobalIFunc::create(unwrap(Ty), AddrSpace,
GlobalValue::ExternalLinkage,
StringRef(Name, NameLen),
unwrap<Constant>(Resolver), unwrap(M)));
}
LLVMValueRef LLVMGetNamedGlobalIFunc(LLVMModuleRef M,
const char *Name, size_t NameLen) {
return wrap(unwrap(M)->getNamedIFunc(StringRef(Name, NameLen)));
}
LLVMValueRef LLVMGetFirstGlobalIFunc(LLVMModuleRef M) {
Module *Mod = unwrap(M);
Module::ifunc_iterator I = Mod->ifunc_begin();
if (I == Mod->ifunc_end())
return nullptr;
return wrap(&*I);
}
LLVMValueRef LLVMGetLastGlobalIFunc(LLVMModuleRef M) {
Module *Mod = unwrap(M);
Module::ifunc_iterator I = Mod->ifunc_end();
if (I == Mod->ifunc_begin())
return nullptr;
return wrap(&*--I);
}
LLVMValueRef LLVMGetNextGlobalIFunc(LLVMValueRef IFunc) {
GlobalIFunc *GIF = unwrap<GlobalIFunc>(IFunc);
Module::ifunc_iterator I(GIF);
if (++I == GIF->getParent()->ifunc_end())
return nullptr;
return wrap(&*I);
}
LLVMValueRef LLVMGetPreviousGlobalIFunc(LLVMValueRef IFunc) {
GlobalIFunc *GIF = unwrap<GlobalIFunc>(IFunc);
Module::ifunc_iterator I(GIF);
if (I == GIF->getParent()->ifunc_begin())
return nullptr;
return wrap(&*--I);
}
LLVMValueRef LLVMGetGlobalIFuncResolver(LLVMValueRef IFunc) {
return wrap(unwrap<GlobalIFunc>(IFunc)->getResolver());
}
void LLVMSetGlobalIFuncResolver(LLVMValueRef IFunc, LLVMValueRef Resolver) {
unwrap<GlobalIFunc>(IFunc)->setResolver(unwrap<Constant>(Resolver));
}
void LLVMEraseGlobalIFunc(LLVMValueRef IFunc) {
unwrap<GlobalIFunc>(IFunc)->eraseFromParent();
}
void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc) {
unwrap<GlobalIFunc>(IFunc)->removeFromParent();
}
/*--.. Operations on basic blocks ..........................................--*/
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB) {

View File

@ -28,6 +28,13 @@ module asm "classical GAS"
@aliased4 = weak alias i32, i32* @var
@aliased5 = weak_odr alias i32, i32* @var
@ifunc = ifunc i32 (i32), i64 ()* @ifunc_resolver
define i64 @ifunc_resolver() {
entry:
ret i64 0
}
define { i64, %S* } @unpackrepack(%S %s) {
%1 = extractvalue %S %s, 0
%2 = extractvalue %S %s, 1

View File

@ -939,7 +939,7 @@ AliasDecl:
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
goto NamedMDDecl;
goto GlobalIFuncDecl;
}
Cur = Begin;
@ -967,6 +967,41 @@ AliasDecl:
Cur = Next;
}
GlobalIFuncDecl:
Begin = LLVMGetFirstGlobalIFunc(Src);
End = LLVMGetLastGlobalIFunc(Src);
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
goto NamedMDDecl;
}
Cur = Begin;
Next = nullptr;
while (true) {
size_t NameLen;
const char *Name = LLVMGetValueName2(Cur, &NameLen);
if (LLVMGetNamedGlobalIFunc(M, Name, NameLen))
report_fatal_error("Global ifunc already cloned");
LLVMTypeRef CurType = TypeCloner(M).Clone(LLVMGlobalGetValueType(Cur));
// FIXME: Allow NULL resolver.
LLVMAddGlobalIFunc(M, Name, NameLen,
CurType, /*addressSpace*/ 0, LLVMGetUndef(CurType));
Next = LLVMGetNextGlobalIFunc(Cur);
if (Next == nullptr) {
if (Cur != End)
report_fatal_error("");
break;
}
LLVMValueRef Prev = LLVMGetPreviousGlobalIFunc(Next);
if (Prev != Cur)
report_fatal_error("Next.Previous global is not Current");
Cur = Next;
}
NamedMDDecl:
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
@ -1114,7 +1149,7 @@ AliasClone:
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
goto NamedMDClone;
goto GlobalIFuncClone;
}
Cur = Begin;
@ -1147,6 +1182,45 @@ AliasClone:
Cur = Next;
}
GlobalIFuncClone:
Begin = LLVMGetFirstGlobalIFunc(Src);
End = LLVMGetLastGlobalIFunc(Src);
if (!Begin) {
if (End != nullptr)
report_fatal_error("Range has an end but no beginning");
goto NamedMDClone;
}
Cur = Begin;
Next = nullptr;
while (true) {
size_t NameLen;
const char *Name = LLVMGetValueName2(Cur, &NameLen);
LLVMValueRef IFunc = LLVMGetNamedGlobalIFunc(M, Name, NameLen);
if (!IFunc)
report_fatal_error("Global ifunc must have been declared already");
if (LLVMValueRef Resolver = LLVMGetGlobalIFuncResolver(Cur)) {
LLVMSetGlobalIFuncResolver(IFunc, clone_constant(Resolver, M));
}
LLVMSetLinkage(IFunc, LLVMGetLinkage(Cur));
LLVMSetUnnamedAddress(IFunc, LLVMGetUnnamedAddress(Cur));
Next = LLVMGetNextGlobalIFunc(Cur);
if (Next == nullptr) {
if (Cur != End)
report_fatal_error("Last global alias does not match End");
break;
}
LLVMValueRef Prev = LLVMGetPreviousGlobalIFunc(Next);
if (Prev != Cur)
report_fatal_error("Next.Previous global alias is not Current");
Cur = Next;
}
NamedMDClone:
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);