mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-07 12:30:57 +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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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));
|
||||
}
|
||||
|
||||
/*--.. 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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user