[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