[llvm-commits] [126685] Add alias support to llvm-gcc

clattner at apple.com clattner at apple.com
Sat Apr 28 21:24:22 PDT 2007


Revision: 126685
Author:   clattner
Date:     2007-04-28 21:24:20 -0700 (Sat, 28 Apr 2007)

Log Message:
-----------
Add alias support to llvm-gcc

Patch by Anton K!

Modified Paths:
--------------
    apple-local/branches/llvm/gcc/llvm-backend.cpp
    apple-local/branches/llvm/gcc/llvm.h
    apple-local/branches/llvm/gcc/varasm.c

Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-backend.cpp	2007-04-28 17:04:47 UTC (rev 126684)
+++ apple-local/branches/llvm/gcc/llvm-backend.cpp	2007-04-29 04:24:20 UTC (rev 126685)
@@ -28,6 +28,7 @@
 #include "llvm/Module.h"
 #include "llvm/ModuleProvider.h"
 #include "llvm/PassManager.h"
+#include "llvm/ValueSymbolTable.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/Assembly/Writer.h"
@@ -57,6 +58,7 @@
 #include "coretypes.h"
 #include "flags.h"
 #include "tree.h"
+#include "c-tree.h" // For aliases
 #include "diagnostic.h"
 #include "output.h"
 #include "toplev.h"
@@ -532,6 +534,86 @@
   timevar_pop(TV_LLVM_FUNCS);
 }
 
+// emit_alias_to_llvm - Given decl and target emit alias to target. gcc is
+// little bit insane, it can ask us for alias emission in many places. Such
+// places are divided into two stages: it's allowed to have unresolved target at
+// stage 0 (hence result code -1), but not on stage 1 (error). Zero is returned
+// if alias was emitted.
+int emit_alias_to_llvm(tree decl, tree target, unsigned stage) {
+  if (errorcount || sorrycount) return -2;
+    
+  timevar_push(TV_LLVM_GLOBALS);
+
+  // Get or create LLVM global for our alias.
+  GlobalValue *V = cast<GlobalValue>(DECL_LLVM(decl));
+  
+  // Try to grab decl from IDENTIFIER_NODE
+  GlobalValue *Aliasee = 0;
+  if (tree c_decl = lookup_name(target))
+    Aliasee = cast<GlobalValue>(DECL_LLVM(c_decl));
+
+  // Query SymTab for aliasee
+  const char* AliaseeName = IDENTIFIER_POINTER(target);
+  if (!Aliasee) {
+    Aliasee =
+      dyn_cast_or_null<GlobalValue>(TheModule->
+                                    getValueSymbolTable().lookup(AliaseeName));
+  }
+
+  // Last resort. Query for name set via __asm__
+  if (!Aliasee) {
+    std::string starred = std::string("\001") + AliaseeName;
+    Aliasee =
+      dyn_cast_or_null<GlobalValue>(TheModule->
+                                    getValueSymbolTable().lookup(starred));
+  }
+  
+  if (!Aliasee) {
+    if (stage)
+      error ("%J%qD aliased to undefined symbol %qE",
+             decl, decl, target);
+    timevar_pop(TV_LLVM_GLOBALS);
+    return -1;
+  }  
+    
+  GlobalValue::LinkageTypes Linkage;
+  GlobalValue::VisibilityTypes Visibility;
+
+  // Check for external weak linkage
+  if (DECL_EXTERNAL(decl) && DECL_WEAK(decl))
+    Linkage = GlobalValue::WeakLinkage;
+  else if (!TREE_PUBLIC(decl))
+    Linkage = GlobalValue::InternalLinkage;
+  else
+    Linkage = GlobalValue::ExternalLinkage;
+
+  GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), Linkage, "",
+                                    Aliasee, TheModule);
+  // Handle visibility style
+  if (TREE_PUBLIC(decl) && DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN)
+    GA->setVisibility(GlobalValue::HiddenVisibility);
+
+  if (V->getType() == GA->getType())
+    V->replaceAllUsesWith(GA);
+  else if (!V->use_empty())
+    error ("%J% Alias %qD used with invalid type!", decl, decl);
+    
+  changeLLVMValue(V, GA);
+  GA->takeName(V);
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+    GV->eraseFromParent();
+  else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
+    GA->eraseFromParent();
+  else if (Function *F = dyn_cast<Function>(V))
+    F->eraseFromParent();
+  else
+    assert(0 && "Unsuported global value");
+  
+  timevar_pop(TV_LLVM_GLOBALS);
+  return 0;
+}
+
+  
 /// emit_global_to_llvm - Emit the specified VAR_DECL or aggregate CONST_DECL to
 /// LLVM as a global variable.  This function implements the end of
 /// assemble_variable.
@@ -845,12 +927,12 @@
           
           // Update the decl that points to F.
           changeLLVMValue(F, FInNewType);
+
+          // Now we can give GV the proper name.
+          GV->takeName(F);
           
           // F is now dead, nuke it.
           F->eraseFromParent();
-          
-          // Now we can give GV the proper name.
-          GV->setName(Name);
         }
         
       } else {

Modified: apple-local/branches/llvm/gcc/llvm.h
===================================================================
--- apple-local/branches/llvm/gcc/llvm.h	2007-04-28 17:04:47 UTC (rev 126684)
+++ apple-local/branches/llvm/gcc/llvm.h	2007-04-29 04:24:20 UTC (rev 126685)
@@ -49,6 +49,10 @@
  */
 void emit_global_to_llvm(union tree_node*);
 
+/* emit_global_to_llvm - Emit the specified alias to LLVM
+ */
+int emit_alias_to_llvm(union tree_node*, union tree_node*, unsigned);
+
 /* llvm_get_decl_name - Used by varasm.c, returns the specified declaration's
  * name.
  */

Modified: apple-local/branches/llvm/gcc/varasm.c
===================================================================
--- apple-local/branches/llvm/gcc/varasm.c	2007-04-28 17:04:47 UTC (rev 126684)
+++ apple-local/branches/llvm/gcc/varasm.c	2007-04-29 04:24:20 UTC (rev 126685)
@@ -4675,6 +4675,14 @@
 static void
 do_assemble_alias (tree decl, tree target)
 {
+/* APPLE LOCAL begin LLVM */
+#ifdef ENABLE_LLVM  
+  if (emit_alias_to_llvm(decl, target, 1) == -1)
+    error ("%J%qD aliased to undefined symbol %qE",
+           decl, decl, target);
+  return;
+#endif
+/* APPLE LOCAL end LLVM */
   if (TREE_ASM_WRITTEN (decl))
     return;
 
@@ -4725,6 +4733,11 @@
 void
 finish_aliases_1 (void)
 {
+/* APPLE LOCAL begin LLVM */
+#ifdef ENABLE_LLVM
+  return;
+#endif
+/* APPLE LOCAL end LLVM */
   unsigned i;
   alias_pair p;
 
@@ -4764,8 +4777,12 @@
 void
 assemble_alias (tree decl, tree target)
 {
+/* APPLE LOCAL begin LLVM */
+#ifndef ENABLE_LLVM
   tree target_decl;
-
+#endif  
+/* APPLE LOCAL end LLVM */
+  
 #if !defined (ASM_OUTPUT_DEF)
 # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
   error ("%Jalias definitions not supported in this configuration", decl);
@@ -4779,18 +4796,17 @@
 # endif
 #endif
   
-  /* APPLE LOCAL begin LLVM */
-#ifdef ENABLE_LLVM
-  inform ("%JLLVM does not support aliases yet", decl);
-  return;
-#endif
-  /* APPLE LOCAL end LLVM */
-
   /* We must force creation of DECL_RTL for debug info generation, even though
      we don't use it here.  */
+/* APPLE LOCAL begin LLVM */  
+#ifndef ENABLE_LLVM  
   make_decl_rtl (decl);
+#else
+  make_decl_llvm (decl);
+#endif
+/* APPLE LOCAL end LLVM */
   TREE_USED (decl) = 1;
-
+  
   /* A quirk of the initial implementation of aliases required that the user
      add "extern" to all of them.  Which is silly, but now historical.  Do
      note that the symbol is in fact locally defined.  */
@@ -4802,12 +4818,20 @@
   else
     cgraph_varpool_node (decl)->alias = true;
 
+/* APPLE LOCAL begin LLVM */
+#ifdef ENABLE_LLVM
+  /* Can we emit alias right now (usually true for C functions)? If yes - do it,
+   * otherwise save for late processing */
+  if (emit_alias_to_llvm(decl, target, 0) == -1)
+#else  
   /* If the target has already been emitted, we don't have to queue the
      alias.  This saves a tad o memory.  */
   target_decl = find_decl_and_mark_needed (decl, target);
   if (target_decl && TREE_ASM_WRITTEN (target_decl))
     do_assemble_alias (decl, target);
   else
+#endif
+/* APPLE LOCAL end LLVM */    
     {
       alias_pair p;
 





More information about the llvm-commits mailing list