[llvm] r353193 - [LLVM-C] Add Bindings to GlobalIFunc
Robert Widmann via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 5 10:05:44 PST 2019
Author: codafi
Date: Tue Feb 5 10:05:44 2019
New Revision: 353193
URL: http://llvm.org/viewvc/llvm-project?rev=353193&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm-c/Core.h
llvm/trunk/lib/IR/Core.cpp
llvm/trunk/test/Bindings/llvm-c/echo.ll
llvm/trunk/tools/llvm-c-test/echo.cpp
Modified: llvm/trunk/include/llvm-c/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=353193&r1=353192&r2=353193&view=diff
==============================================================================
--- llvm/trunk/include/llvm-c/Core.h (original)
+++ llvm/trunk/include/llvm-c/Core.h Tue Feb 5 10:05:44 2019
@@ -2612,6 +2612,103 @@ void LLVMSetParamAlignment(LLVMValueRef
*/
/**
+ * @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);
+
+/**
+ * @}
+ */
+
+/**
* @}
*/
Modified: llvm/trunk/lib/IR/Core.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Core.cpp?rev=353193&r1=353192&r2=353193&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Core.cpp (original)
+++ llvm/trunk/lib/IR/Core.cpp Tue Feb 5 10:05:44 2019
@@ -2463,6 +2463,71 @@ void LLVMSetParamAlignment(LLVMValueRef
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) {
Modified: llvm/trunk/test/Bindings/llvm-c/echo.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/llvm-c/echo.ll?rev=353193&r1=353192&r2=353193&view=diff
==============================================================================
--- llvm/trunk/test/Bindings/llvm-c/echo.ll (original)
+++ llvm/trunk/test/Bindings/llvm-c/echo.ll Tue Feb 5 10:05:44 2019
@@ -28,6 +28,13 @@ module asm "classical GAS"
@aliased4 = weak alias i32, i32* @var
@aliased5 = weak_odr alias i32, i32* @var
+ at 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
Modified: llvm/trunk/tools/llvm-c-test/echo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-c-test/echo.cpp?rev=353193&r1=353192&r2=353193&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-c-test/echo.cpp (original)
+++ llvm/trunk/tools/llvm-c-test/echo.cpp Tue Feb 5 10:05:44 2019
@@ -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;
@@ -1144,6 +1179,45 @@ AliasClone:
if (Prev != Cur)
report_fatal_error("Next.Previous global alias is not Current");
+ 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;
}
More information about the llvm-commits
mailing list