mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-08 13:00:50 +00:00
[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:
parent
abae4d3487
commit
005e630f24
@ -2607,6 +2607,103 @@ LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg);
|
|||||||
*/
|
*/
|
||||||
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned Align);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -2463,6 +2463,71 @@ void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align) {
|
|||||||
A->addAttr(Attribute::getWithAlignment(A->getContext(), 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 ..........................................--*/
|
/*--.. Operations on basic blocks ..........................................--*/
|
||||||
|
|
||||||
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB) {
|
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB) {
|
||||||
|
@ -28,6 +28,13 @@ module asm "classical GAS"
|
|||||||
@aliased4 = weak alias i32, i32* @var
|
@aliased4 = weak alias i32, i32* @var
|
||||||
@aliased5 = weak_odr 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) {
|
define { i64, %S* } @unpackrepack(%S %s) {
|
||||||
%1 = extractvalue %S %s, 0
|
%1 = extractvalue %S %s, 0
|
||||||
%2 = extractvalue %S %s, 1
|
%2 = extractvalue %S %s, 1
|
||||||
|
@ -939,7 +939,7 @@ AliasDecl:
|
|||||||
if (!Begin) {
|
if (!Begin) {
|
||||||
if (End != nullptr)
|
if (End != nullptr)
|
||||||
report_fatal_error("Range has an end but no beginning");
|
report_fatal_error("Range has an end but no beginning");
|
||||||
goto NamedMDDecl;
|
goto GlobalIFuncDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cur = Begin;
|
Cur = Begin;
|
||||||
@ -967,6 +967,41 @@ AliasDecl:
|
|||||||
Cur = Next;
|
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:
|
NamedMDDecl:
|
||||||
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
|
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
|
||||||
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
|
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
|
||||||
@ -1114,7 +1149,7 @@ AliasClone:
|
|||||||
if (!Begin) {
|
if (!Begin) {
|
||||||
if (End != nullptr)
|
if (End != nullptr)
|
||||||
report_fatal_error("Range has an end but no beginning");
|
report_fatal_error("Range has an end but no beginning");
|
||||||
goto NamedMDClone;
|
goto GlobalIFuncClone;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cur = Begin;
|
Cur = Begin;
|
||||||
@ -1147,6 +1182,45 @@ AliasClone:
|
|||||||
Cur = Next;
|
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:
|
NamedMDClone:
|
||||||
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
|
LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src);
|
||||||
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
|
LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src);
|
||||||
|
Loading…
Reference in New Issue
Block a user