OSDN Git Service

[LLVM-C] Improve Bindings For Aliases
authorRobert Widmann <devteam.codafi@gmail.com>
Sun, 20 May 2018 23:49:08 +0000 (23:49 +0000)
committerRobert Widmann <devteam.codafi@gmail.com>
Sun, 20 May 2018 23:49:08 +0000 (23:49 +0000)
Summary: Add wrappers for a module's alias iterators and a getter and setter for the aliasee value.

Reviewers: whitequark, deadalnix

Reviewed By: whitequark

Subscribers: llvm-commits, harlanhaskins

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332826 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm-c/Core.h
lib/IR/Core.cpp
test/Bindings/llvm-c/echo.ll
tools/llvm-c-test/echo.cpp

index 6f1db31..6792219 100644 (file)
@@ -2118,6 +2118,56 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
                           const char *Name);
 
 /**
+ * Obtain a GlobalAlias value from a Module by its name.
+ *
+ * The returned value corresponds to a llvm::GlobalAlias value.
+ *
+ * @see llvm::Module::getNamedAlias()
+ */
+LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M,
+                                     const char *Name, size_t NameLen);
+
+/**
+ * Obtain an iterator to the first GlobalAlias in a Module.
+ *
+ * @see llvm::Module::alias_begin()
+ */
+LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M);
+
+/**
+ * Obtain an iterator to the last GlobalAlias in a Module.
+ *
+ * @see llvm::Module::alias_end()
+ */
+LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M);
+
+/**
+ * Advance a GlobalAlias iterator to the next GlobalAlias.
+ *
+ * Returns NULL if the iterator was already at the end and there are no more
+ * global aliases.
+ */
+LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA);
+
+/**
+ * Decrement a GlobalAlias iterator to the previous GlobalAlias.
+ *
+ * Returns NULL if the iterator was already at the beginning and there are
+ * no previous global aliases.
+ */
+LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA);
+
+/**
+ * Retrieve the target value of an alias.
+ */
+LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias);
+
+/**
+ * Set the target value of an alias.
+ */
+void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee);
+
+/**
  * @}
  */
 
index 33dbf4a..bea4dee 100644 (file)
@@ -1965,6 +1965,51 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
                                   unwrap<Constant>(Aliasee), unwrap(M)));
 }
 
+LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M,
+                                     const char *Name, size_t NameLen) {
+  return wrap(unwrap(M)->getNamedAlias(Name));
+}
+
+LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M) {
+  Module *Mod = unwrap(M);
+  Module::alias_iterator I = Mod->alias_begin();
+  if (I == Mod->alias_end())
+    return nullptr;
+  return wrap(&*I);
+}
+
+LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M) {
+  Module *Mod = unwrap(M);
+  Module::alias_iterator I = Mod->alias_end();
+  if (I == Mod->alias_begin())
+    return nullptr;
+  return wrap(&*--I);
+}
+
+LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA) {
+  GlobalAlias *Alias = unwrap<GlobalAlias>(GA);
+  Module::alias_iterator I(Alias);
+  if (++I == Alias->getParent()->alias_end())
+    return nullptr;
+  return wrap(&*I);
+}
+
+LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA) {
+  GlobalAlias *Alias = unwrap<GlobalAlias>(GA);
+  Module::alias_iterator I(Alias);
+  if (I == Alias->getParent()->alias_begin())
+    return nullptr;
+  return wrap(&*--I);
+}
+
+LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias) {
+  return wrap(unwrap<GlobalAlias>(Alias)->getAliasee());
+}
+
+void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee) {
+  unwrap<GlobalAlias>(Alias)->setAliasee(unwrap<Constant>(Aliasee));
+}
+
 /*--.. Operations on functions .............................................--*/
 
 LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name,
index 071cbe8..e105259 100644 (file)
@@ -22,6 +22,12 @@ module asm "classical GAS"
 @section = global i32 27, section ".custom"
 @align = global i32 31, align 4
 
+@aliased1 = alias i32, i32* @var
+@aliased2 = internal alias i32, i32* @var
+@aliased3 = external alias i32, i32* @var
+@aliased4 = weak alias i32, i32* @var
+@aliased5 = weak_odr alias i32, i32* @var
+
 define { i64, %S* } @unpackrepack(%S %s) {
   %1 = extractvalue %S %s, 0
   %2 = extractvalue %S %s, 1
index ca3a1be..a9cd4cf 100644 (file)
@@ -248,10 +248,19 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
     // Try global variable
     if (LLVMIsAGlobalVariable(Cst)) {
       check_value_kind(Cst, LLVMGlobalVariableValueKind);
-      LLVMValueRef Dst  = LLVMGetNamedGlobal(M, Name);
+      LLVMValueRef Dst = LLVMGetNamedGlobal(M, Name);
       if (Dst)
         return Dst;
-      report_fatal_error("Could not find function");
+      report_fatal_error("Could not find variable");
+    }
+
+    // Try global alias
+    if (LLVMIsAGlobalAlias(Cst)) {
+      check_value_kind(Cst, LLVMGlobalAliasValueKind);
+      LLVMValueRef Dst = LLVMGetNamedGlobalAlias(M, Name, NameLen);
+      if (Dst)
+        return Dst;
+      report_fatal_error("Could not find alias");
     }
 
     fprintf(stderr, "Could not find @%s\n", Name);
@@ -822,6 +831,8 @@ struct FunCloner {
 };
 
 static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
+  auto Ctx = LLVMGetModuleContext(M);
+
   LLVMValueRef Begin = LLVMGetFirstGlobal(Src);
   LLVMValueRef End = LLVMGetLastGlobal(Src);
 
@@ -860,11 +871,9 @@ FunDecl:
   if (!Begin) {
     if (End != nullptr)
       report_fatal_error("Range has an end but no beginning");
-    return;
+    goto AliasDecl;
   }
 
-  auto Ctx = LLVMGetModuleContext(M);
-
   Cur = Begin;
   Next = nullptr;
   while (true) {
@@ -900,6 +909,40 @@ FunDecl:
 
     Cur = Next;
   }
+
+AliasDecl:
+  Begin = LLVMGetFirstGlobalAlias(Src);
+  End = LLVMGetLastGlobalAlias(Src);
+  if (!Begin) {
+    if (End != nullptr)
+      report_fatal_error("Range has an end but no beginning");
+    return;
+  }
+
+  Cur = Begin;
+  Next = nullptr;
+  while (true) {
+    size_t NameLen;
+    const char *Name = LLVMGetValueName2(Cur, &NameLen);
+    if (LLVMGetNamedGlobalAlias(M, Name, NameLen))
+      report_fatal_error("Global alias already cloned");
+    LLVMTypeRef CurType = TypeCloner(M).Clone(Cur);
+    // FIXME: Allow NULL aliasee.
+    LLVMAddAlias(M, CurType, LLVMGetUndef(CurType), Name);
+
+    Next = LLVMGetNextGlobalAlias(Cur);
+    if (Next == nullptr) {
+      if (Cur != End)
+        report_fatal_error("");
+      break;
+    }
+
+    LLVMValueRef Prev = LLVMGetPreviousGlobalAlias(Next);
+    if (Prev != Cur)
+      report_fatal_error("Next.Previous global is not Current");
+
+    Cur = Next;
+  }
 }
 
 static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
@@ -953,7 +996,7 @@ FunClone:
   if (!Begin) {
     if (End != nullptr)
       report_fatal_error("Range has an end but no beginning");
-    return;
+    goto AliasClone;
   }
 
   Cur = Begin;
@@ -991,6 +1034,45 @@ FunClone:
 
     Cur = Next;
   }
+
+AliasClone:
+  Begin = LLVMGetFirstGlobalAlias(Src);
+  End = LLVMGetLastGlobalAlias(Src);
+  if (!Begin) {
+    if (End != nullptr)
+      report_fatal_error("Range has an end but no beginning");
+    return;
+  }
+
+  Cur = Begin;
+  Next = nullptr;
+  while (true) {
+    size_t NameLen;
+    const char *Name = LLVMGetValueName2(Cur, &NameLen);
+    LLVMValueRef Alias = LLVMGetNamedGlobalAlias(M, Name, NameLen);
+    if (!Alias)
+      report_fatal_error("Global alias must have been declared already");
+
+    if (LLVMValueRef Aliasee = LLVMAliasGetAliasee(Cur)) {
+      LLVMAliasSetAliasee(Alias, clone_constant(Aliasee, M));
+    }
+
+    LLVMSetLinkage(Alias, LLVMGetLinkage(Cur));
+    LLVMSetUnnamedAddress(Alias, LLVMGetUnnamedAddress(Cur));
+
+    Next = LLVMGetNextGlobalAlias(Cur);
+    if (Next == nullptr) {
+      if (Cur != End)
+        report_fatal_error("Last global alias does not match End");
+      break;
+    }
+
+    LLVMValueRef Prev = LLVMGetPreviousGlobalAlias(Next);
+    if (Prev != Cur)
+      report_fatal_error("Next.Previous global alias is not Current");
+
+    Cur = Next;
+  }
 }
 
 int llvm_echo(void) {