OSDN Git Service

Implement aliases. This fixes PR1017 and it's dependent bugs. CFE part
authorAnton Korobeynikov <asl@math.spbu.ru>
Wed, 25 Apr 2007 14:27:10 +0000 (14:27 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Wed, 25 Apr 2007 14:27:10 +0000 (14:27 +0000)
will follow.

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

22 files changed:
docs/BytecodeFormat.html
docs/LangRef.html
include/llvm/CodeGen/AsmPrinter.h
include/llvm/Function.h
include/llvm/GlobalValue.h
include/llvm/GlobalVariable.h
include/llvm/Module.h
include/llvm/Value.h
include/llvm/ValueSymbolTable.h
lib/AsmParser/Lexer.l
lib/AsmParser/llvmAsmParser.y
lib/Bytecode/Reader/Reader.cpp
lib/Bytecode/Writer/Writer.cpp
lib/CodeGen/AsmPrinter.cpp
lib/Target/X86/X86TargetAsmInfo.cpp
lib/Transforms/IPO/GlobalDCE.cpp
lib/VMCore/AsmWriter.cpp
lib/VMCore/Globals.cpp
lib/VMCore/Module.cpp
lib/VMCore/Verifier.cpp
test/CodeGen/X86/aliases.ll [new file with mode: 0644]
test/Feature/aliases.ll [new file with mode: 0644]

index 56fc0af..396bf2f 100644 (file)
@@ -943,11 +943,11 @@ all functions. The format is shown in the table below:</p>
         target triple specified, i.e. a platform-independent module).</td>
     </tr>
     <tr>
-         <td><a href="#string">string</a></td>
-          <td class="td_left">The data layout string describing the endianness,
-            pointer size, and type alignments for which the module was written 
-            (blank means no data layout specified, i.e. a platform-independent 
-            module).</td>
+      <td><a href="#string">string</a></td>
+      <td class="td_left">The data layout string describing the endianness,
+        pointer size, and type alignments for which the module was written 
+        (blank means no data layout specified, i.e. a platform-independent 
+        module).</td>
     </tr>
     <tr>
       <td><a href="#llist">llist</a>(<a href="#string">string</a>)</td>
@@ -959,6 +959,11 @@ all functions. The format is shown in the table below:</p>
       <td><a href="#string">string</a></td>
       <td class="td_left">The inline asm block for this module.</td>
     </tr>
+    <tr>
+      <td><a href="#zlist">zlist</a>(<a href="#alias">alias</a>)</td>
+      <td class="td_left">A zero terminated list of aliases occurring in the
+      module.</td>
+    </tr>
   </tbody>
 </table>
 </div>
@@ -1123,7 +1128,7 @@ href="#uint32_vbr">uint32_vbr</a> that describes the function.</p>
       <td><a href="#bit">bit(5-30)</a></td>
       <td class="td_left">Type slot number of type for the function.</td>
     </tr>
-                                      <tr>
+    <tr>
       <td><a href="#bit">bit(31)</a></td>
       <td class="td_left">Indicates whether an extension word follows.</td>
     </tr>
@@ -1186,6 +1191,56 @@ follows with the following fields:</p>
 </div>
 
 <!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"><a name="alias">Alias Field</a>
+</div>
+<div class="doc_text">
+<p>Aliases are written using 3 <a href="#uint32_vbr">uint32_vbr</a>
+that encode information about alias itself and aliasee.</p>
+
+<p>The table below provides the bit layout of
+the first <a href="#uint32_vbr">uint32_vbr</a> which describes alias itself.</p>
+
+<table>
+  <tbody>
+    <tr>
+      <th><b>Type</b></th>
+      <th class="td_left"><b>Description</b></th>
+    </tr>
+    <tr>
+      <td><a href="#bit">bit(0-1)</a></td>
+      <td class="td_left">Alias linkage. 0 - External linkage, 1 - Internal
+      linkage, 2 - Weak linkage.</td>
+    </tr>
+    <tr>
+      <td><a href="#bit">bit(2-31)</a></td>
+      <td class="td_left">Type slot number of type for the alias itself.</td>
+    </tr>
+  </tbody>
+</table>
+
+  <p>The next two <a href="#uint32_vbr">uint32_vbr's</a> describes the
+  aliasee. </p>
+
+<table>
+  <tbody>
+    <tr>
+      <th><b>Type</b></th>
+      <th class="td_left"><b>Description</b></th>
+    </tr>
+    <tr>
+      <td><a href="#uint32_vbr">uint32_vbr</a></td>
+      <td class="td_left">Type slot number of type for the aliasee.</td>
+    </tr>
+    <tr>
+      <td><a href="#uint32_vbr">uint32_vbr</a></td>
+      <td class="td_left">Slot number of the aliasee.</td>
+    </tr>
+  </tbody>
+</table>
+
+</div>
+
+<!-- _______________________________________________________________________ -->
 <div class="doc_subsection"><a name="constantpool">Constant Pool</a> </div>
 <div class="doc_text">
 <p>A constant pool defines as set of constant values. There are
index 2fb27f6..807d104 100644 (file)
@@ -498,7 +498,8 @@ outside of the current module.</p>
 <p>It is illegal for a function <i>declaration</i>
 to have any linkage type other than "externally visible", <tt>dllimport</tt>,
 or <tt>extern_weak</tt>.</p>
-
+<p>Aliases can have only <tt>external</tt>, <tt>internal</tt> and <tt>weak</tt>
+linkages.
 </div>
 
 <!-- ======================================================================= -->
@@ -602,12 +603,11 @@ All Global Variables and Functions have one of the following visibility styles:
 
 <p>Global variables define regions of memory allocated at compilation time
 instead of run-time.  Global variables may optionally be initialized, may have
-an explicit section to be placed in, and may
-have an optional explicit alignment specified.  A variable may be defined as
-"thread_local", which means that it will not be shared by threads (each thread
-will have a separated copy of the variable).
-A variable may be defined as a global "constant," which indicates that the
-contents of the variable will <b>never</b> be modified (enabling better
+an explicit section to be placed in, and may have an optional explicit alignment
+specified.  A variable may be defined as "thread_local", which means that it
+will not be shared by threads (each thread will have a separated copy of the
+variable).  A variable may be defined as a global "constant," which indicates
+that the contents of the variable will <b>never</b> be modified (enabling better
 optimization, allowing the global data to be placed in the read-only section of
 an executable, etc).  Note that variables that need runtime initialization
 cannot be marked "constant" as there is a store to the variable.</p>
@@ -698,6 +698,27 @@ a power of 2.</p>
 
 </div>
 
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+  <a name="aliasstructure">Aliases</a>
+</div>
+<div class="doc_text">
+  <p>Aliases act as "second name" for the aliasee value (which can be either
+  function or global variable). Aliases may have an
+  optional <a href="#linkage">linkage type</a>, and an
+  optional <a href="#visibility">visibility style</a>.</p>
+
+  <h5>Syntax:</h5>
+
+  <pre>
+    @&lt;Name&gt; = [Linkage] [Visibility] alias &lt;AliaseeTy&gt; @&lt;Aliasee&gt;
+  </pre>
+
+</div>
+
+
+
 <!-- ======================================================================= -->
 <div class="doc_subsection"><a name="paramattrs">Parameter Attributes</a></div>
 <div class="doc_text">
index e3ca8aa..024001e 100644 (file)
@@ -24,6 +24,7 @@ namespace llvm {
   class Constant;
   class ConstantArray;
   class GlobalVariable;
+  class GlobalAlias;
   class MachineConstantPoolEntry;
   class MachineConstantPoolValue;
   class Mangler;
index a50601d..c0984f6 100644 (file)
@@ -141,12 +141,12 @@ public:
   /// removeFromParent - This method unlinks 'this' from the containing module,
   /// but does not delete it.
   ///
-  void removeFromParent();
+  virtual void removeFromParent();
 
   /// eraseFromParent - This method unlinks 'this' from the containing module
   /// and deletes it.
   ///
-  void eraseFromParent();
+  virtual void eraseFromParent();
 
 
   /// Get the underlying elements of the Function... the basic block list is
index a20c058..317aa48 100644 (file)
@@ -121,6 +121,16 @@ public:
   /// value is outside of the current translation unit...
   virtual bool isDeclaration() const = 0;
 
+  /// removeFromParent - This method unlinks 'this' from the containing module,
+  /// but does not delete it.
+  ///
+  virtual void removeFromParent() = 0;
+
+  /// eraseFromParent - This method unlinks 'this' from the containing module
+  /// and deletes it.
+  ///
+  virtual void eraseFromParent() = 0;
+
   /// getParent - Get the module that this global value is contained inside
   /// of...
   inline Module *getParent() { return Parent; }
@@ -136,7 +146,8 @@ public:
   static inline bool classof(const GlobalValue *) { return true; }
   static inline bool classof(const Value *V) {
     return V->getValueID() == Value::FunctionVal ||
-           V->getValueID() == Value::GlobalVariableVal;
+           V->getValueID() == Value::GlobalVariableVal ||
+           V->getValueID() == Value::GlobalAliasVal;
   }
 };
 
index 00d4acb..303e57f 100644 (file)
@@ -107,12 +107,12 @@ public:
   /// removeFromParent - This method unlinks 'this' from the containing module,
   /// but does not delete it.
   ///
-  void removeFromParent();
+  virtual void removeFromParent();
 
   /// eraseFromParent - This method unlinks 'this' from the containing module
   /// and deletes it.
   ///
-  void eraseFromParent();
+  virtual void eraseFromParent();
 
   /// Override Constant's implementation of this method so we can
   /// replace constant initializers.
index ecc9c0b..8cd35f2 100644 (file)
 
 #include "llvm/Function.h"
 #include "llvm/GlobalVariable.h"
+#include "llvm/GlobalAlias.h"
 #include "llvm/Support/DataTypes.h"
 #include <vector>
 
 namespace llvm {
 
-class GlobalVariable;
 class GlobalValueRefMap;   // Used by ConstantVals.cpp
 class FunctionType;
 
@@ -43,6 +43,15 @@ template<> struct ilist_traits<GlobalVariable>
   static inline ValueSymbolTable *getSymTab(Module *M);
   static int getListOffset();
 };
+template<> struct ilist_traits<GlobalAlias>
+  : public SymbolTableListTraits<GlobalAlias, Module> {
+  // createSentinel is used to create a node that marks the end of the list.
+  static GlobalAlias *createSentinel();
+  static void destroySentinel(GlobalAlias *GA) { delete GA; }
+  static iplist<GlobalAlias> &getList(Module *M);
+  static inline ValueSymbolTable *getSymTab(Module *M);
+  static int getListOffset();
+};
 
 /// A Module instance is used to store all the information related to an
 /// LLVM module. Modules are the top level container of all other LLVM 
@@ -63,6 +72,8 @@ public:
   typedef iplist<GlobalVariable> GlobalListType;
   /// The type for the list of functions.
   typedef iplist<Function> FunctionListType;
+  /// The type for the list of aliases.
+  typedef iplist<GlobalAlias> AliasListType;
 
   /// The type for the list of dependent libraries.
   typedef std::vector<std::string> LibraryListType;
@@ -77,6 +88,11 @@ public:
   /// The Function constant iterator
   typedef FunctionListType::const_iterator              const_iterator;
 
+  /// The Global Alias iterators.
+  typedef AliasListType::iterator                       alias_iterator;
+  /// The Global Alias constant iterator
+  typedef AliasListType::const_iterator           const_alias_iterator;
+
   /// The Library list iterator.
   typedef LibraryListType::const_iterator lib_iterator;
 
@@ -92,6 +108,7 @@ public:
 private:
   GlobalListType GlobalList;     ///< The Global Variables in the module
   FunctionListType FunctionList; ///< The Functions in the module
+  AliasListType AliasList;       ///< The Aliases in the module  
   LibraryListType LibraryList;   ///< The Libraries needed by the module
   std::string GlobalScopeAsm;    ///< Inline Asm at global scope.
   ValueSymbolTable *ValSymTab;   ///< Symbol table for values
@@ -175,10 +192,10 @@ public:
   /// getOrInsertFunction - Look up the specified function in the module symbol
   /// table.  If it does not exist, add a prototype for the function and return
   /// it.  This function guarantees to return a constant of pointer to the
-  /// specified function type or a ConstantExpr BitCast of that type if the 
-  /// named /// function has a different type.  This version of the method 
-  /// takes a null terminated list of function arguments, which makes it 
-  /// easier for clients to use.
+  /// specified function type or a ConstantExpr BitCast of that type if the
+  /// named function has a different type.  This version of the method takes a
+  /// null terminated list of function arguments, which makes it easier for
+  /// clients to use.
   Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy,...)
     END_WITH_NULL;
 
@@ -205,6 +222,15 @@ public:
   GlobalVariable *getNamedGlobal(const std::string &Name) const {
     return getGlobalVariable(Name, true);
   }
+
+/// @}
+/// @name Global Variable Accessors 
+/// @{
+public:
+  /// getNamedGlobal - Return the first global alias in the module with the
+  /// specified name, of arbitrary type.  This method returns null if a global
+  /// with the specified name is not found.
+  GlobalAlias *getNamedAlias(const std::string &Name) const;
   
 /// @}
 /// @name Type Accessors
@@ -235,14 +261,18 @@ public:
   const FunctionListType &getFunctionList() const     { return FunctionList; }
   /// Get the Module's list of functions.
   FunctionListType       &getFunctionList()           { return FunctionList; }
+  /// Get the Module's list of aliases (constant).
+  const AliasListType    &getAliasList() const        { return AliasList; }
+  /// Get the Module's list of aliases.
+  AliasListType          &getAliasList()              { return AliasList; }
   /// Get the symbol table of global variable and function identifiers
   const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; }
   /// Get the Module's symbol table of global variable and function identifiers.
   ValueSymbolTable       &getValueSymbolTable()       { return *ValSymTab; }
   /// Get the symbol table of types
-  const TypeSymbolTable   &getTypeSymbolTable() const { return *TypeSymTab; }
+  const TypeSymbolTable  &getTypeSymbolTable() const  { return *TypeSymTab; }
   /// Get the Module's symbol table of types
-  TypeSymbolTable         &getTypeSymbolTable()       { return *TypeSymTab; }
+  TypeSymbolTable        &getTypeSymbolTable()        { return *TypeSymTab; }
 
 /// @}
 /// @name Global Variable Iteration
@@ -272,7 +302,7 @@ public:
   /// Get a constant iterator to the last function.
   const_iterator          end  () const { return FunctionList.end();   }
   /// Determine how many functions are in the Module's list of functions.
-  size_t                   size() const { return FunctionList.size(); }
+  size_t                  size() const  { return FunctionList.size(); }
   /// Determine if the list of functions is empty.
   bool                    empty() const { return FunctionList.empty(); }
 
@@ -283,9 +313,9 @@ public:
   /// @brief Get a constant iterator to beginning of dependent library list.
   inline lib_iterator lib_begin() const { return LibraryList.begin(); }
   /// @brief Get a constant iterator to end of dependent library list.
-  inline lib_iterator lib_end() const { return LibraryList.end(); }
+  inline lib_iterator lib_end()   const { return LibraryList.end();   }
   /// @brief Returns the number of items in the list of libraries.
-  inline size_t lib_size() const { return LibraryList.size(); }
+  inline size_t       lib_size()  const { return LibraryList.size();  }
   /// @brief Add a library to the list of dependent libraries
   void addLibrary(const std::string& Lib);
   /// @brief Remove a library from the list of dependent libraries
@@ -294,6 +324,23 @@ public:
   inline const LibraryListType& getLibraries() const { return LibraryList; }
 
 /// @}
+/// @name Alias Iteration
+/// @{
+public:
+  /// Get an iterator to the first alias.
+  alias_iterator       alias_begin()            { return AliasList.begin(); }
+  /// Get a constant iterator to the first alias.
+  const_alias_iterator alias_begin() const      { return AliasList.begin(); }
+  /// Get an iterator to the last alias.
+  alias_iterator       alias_end  ()            { return AliasList.end();   }
+  /// Get a constant iterator to the last alias.
+  const_alias_iterator alias_end  () const      { return AliasList.end();   }
+  /// Determine how many functions are in the Module's list of aliases.
+  size_t               alias_size () const      { return AliasList.size();  }
+  /// Determine if the list of aliases is empty.
+  bool                 alias_empty() const      { return AliasList.empty(); }
+
+/// @}
 /// @name Utility functions for printing and dumping Module objects
 /// @{
 public:
@@ -324,6 +371,10 @@ public:
     Module *Obj = 0;
     return unsigned(reinterpret_cast<uintptr_t>(&Obj->GlobalList));
   }
+  static unsigned getAliasListOffset() {
+    Module *Obj = 0;
+    return unsigned(reinterpret_cast<uintptr_t>(&Obj->AliasList));
+  }
 };
 
 /// An iostream inserter for modules.
@@ -342,6 +393,11 @@ ilist_traits<GlobalVariable>::getSymTab(Module *M) {
   return M ? &M->getValueSymbolTable() : 0;
 }
 
+inline ValueSymbolTable *
+ilist_traits<GlobalAlias>::getSymTab(Module *M) {
+  return M ? &M->getValueSymbolTable() : 0;
+}
+
 inline int 
 ilist_traits<Function>::getListOffset() {
   return Module::getFunctionListOffset();
@@ -352,6 +408,11 @@ ilist_traits<GlobalVariable>::getListOffset() {
   return Module::getGlobalVariableListOffset();
 }
 
+inline int 
+ilist_traits<GlobalAlias>::getListOffset() {
+  return Module::getAliasListOffset();
+}
+
 } // End llvm namespace
 
 #endif
index fc65e74..44c4453 100644 (file)
@@ -30,6 +30,7 @@ class BasicBlock;
 class GlobalValue;
 class Function;
 class GlobalVariable;
+class GlobalAlias;
 class InlineAsm;
 class ValueSymbolTable;
 class TypeSymbolTable;
@@ -160,6 +161,7 @@ public:
     ArgumentVal,              // This is an instance of Argument
     BasicBlockVal,            // This is an instance of BasicBlock
     FunctionVal,              // This is an instance of Function
+    GlobalAliasVal,           // This is an instance of GlobalAlias
     GlobalVariableVal,        // This is an instance of GlobalVariable
     UndefValueVal,            // This is an instance of UndefValue
     ConstantExprVal,          // This is an instance of ConstantExpr
@@ -248,8 +250,11 @@ template <> inline bool isa_impl<Function, Value>(const Value &Val) {
 template <> inline bool isa_impl<GlobalVariable, Value>(const Value &Val) {
   return Val.getValueID() == Value::GlobalVariableVal;
 }
+template <> inline bool isa_impl<GlobalAlias, Value>(const Value &Val) {
+  return Val.getValueID() == Value::GlobalAliasVal;
+}
 template <> inline bool isa_impl<GlobalValue, Value>(const Value &Val) {
-  return isa<GlobalVariable>(Val) || isa<Function>(Val);
+  return isa<GlobalVariable>(Val) || isa<Function>(Val) || isa<GlobalAlias>(Val);
 }
 
 } // End llvm namespace
index 679fd86..8f007b9 100644 (file)
@@ -35,6 +35,7 @@ class ValueSymbolTable {
   friend class SymbolTableListTraits<Instruction, BasicBlock>;
   friend class SymbolTableListTraits<Function, Module>;
   friend class SymbolTableListTraits<GlobalVariable, Module>;
+  friend class SymbolTableListTraits<GlobalAlias, Module>;
 /// @name Types
 /// @{
 public:
index d75d070..382ce24 100644 (file)
@@ -222,6 +222,7 @@ datalayout      { return DATALAYOUT; }
 volatile        { return VOLATILE; }
 align           { return ALIGN;  }
 section         { return SECTION; }
+alias           { return ALIAS; }
 module          { return MODULE; }
 asm             { return ASM_TOK; }
 sideeffect      { return SIDEEFFECT; }
index 2b08d3a..17ca06f 100644 (file)
@@ -1004,6 +1004,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 %type <BoolVal>       OptSideEffect               // 'sideeffect' or not.
 %type <Linkage>       GVInternalLinkage GVExternalLinkage
 %type <Linkage>       FunctionDefineLinkage FunctionDeclareLinkage
+%type <Linkage>       AliasLinkage
 %type <Visibility>    GVVisibilityStyle
 
 // ValueRef - Unresolved reference to a definition or BB
@@ -1035,12 +1036,12 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
 
 %token<StrVal> LOCALVAR GLOBALVAR LABELSTR STRINGCONSTANT ATSTRINGCONSTANT
 %type <StrVal> LocalName OptLocalName OptLocalAssign
-%type <StrVal> GlobalName OptGlobalAssign
+%type <StrVal> GlobalName OptGlobalAssign GlobalAssign
 %type <UIntVal> OptAlign OptCAlign
 %type <StrVal> OptSection SectionString
 
 %token ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK
-%token DECLARE DEFINE GLOBAL CONSTANT SECTION VOLATILE THREAD_LOCAL
+%token DECLARE DEFINE GLOBAL CONSTANT SECTION ALIAS VOLATILE THREAD_LOCAL
 %token TO DOTDOTDOT NULL_TOK UNDEF INTERNAL LINKONCE WEAK APPENDING
 %token DLLIMPORT DLLEXPORT EXTERN_WEAK
 %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN
@@ -1136,15 +1137,17 @@ OptLocalAssign : LocalName '=' {
 
 GlobalName : GLOBALVAR | ATSTRINGCONSTANT;
 
-OptGlobalAssign : GlobalName '=' {
-    $$ = $1;
-    CHECK_FOR_ERROR
-  }
+OptGlobalAssign : GlobalAssign
   | /*empty*/ {
     $$ = 0;
     CHECK_FOR_ERROR
   };
 
+GlobalAssign : GlobalName '=' {
+    $$ = $1;
+    CHECK_FOR_ERROR
+  }
+
 GVInternalLinkage 
   : INTERNAL    { $$ = GlobalValue::InternalLinkage; } 
   | WEAK        { $$ = GlobalValue::WeakLinkage; } 
@@ -1161,6 +1164,7 @@ GVExternalLinkage
 
 GVVisibilityStyle
   : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
+  | DEFAULT   { $$ = GlobalValue::DefaultVisibility; }
   | HIDDEN    { $$ = GlobalValue::HiddenVisibility;  }
   ;
 
@@ -1170,7 +1174,7 @@ FunctionDeclareLinkage
   | EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; }
   ;
   
-FunctionDefineLinkage 
+FunctionDefineLinkage
   : /*empty*/   { $$ = GlobalValue::ExternalLinkage; }
   | INTERNAL    { $$ = GlobalValue::InternalLinkage; }
   | LINKONCE    { $$ = GlobalValue::LinkOnceLinkage; }
@@ -1178,6 +1182,12 @@ FunctionDefineLinkage
   | DLLEXPORT   { $$ = GlobalValue::DLLExportLinkage; } 
   ; 
 
+AliasLinkage
+  : /*empty*/   { $$ = GlobalValue::ExternalLinkage; }
+  | WEAK        { $$ = GlobalValue::WeakLinkage; }
+  | INTERNAL    { $$ = GlobalValue::InternalLinkage; }
+  ;
+
 OptCallingConv : /*empty*/          { $$ = CallingConv::C; } |
                  CCC_TOK            { $$ = CallingConv::C; } |
                  FASTCC_TOK         { $$ = CallingConv::Fast; } |
@@ -2031,6 +2041,34 @@ Definition
     CurGV = 0;
     CHECK_FOR_ERROR
   }
+  | OptGlobalAssign GVVisibilityStyle ALIAS AliasLinkage ResultTypes SymbolicValueRef {
+    std::string Name($1);
+    if (Name.empty())
+      GEN_ERROR("Alias name cannot be empty")
+    const PointerType *PFTy = 0;
+    const FunctionType *Ty = 0;
+    Value* V = 0;
+    const Type* VTy = 0;
+    if (!(PFTy = dyn_cast<PointerType>($5->get())) ||
+        !(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
+      VTy = $5->get();
+      V = getExistingVal(VTy, $6);
+    } else {
+      VTy = PFTy;
+      V = getExistingVal(PFTy, $6);
+    }
+    if (V == 0)
+      GEN_ERROR(std::string("Invalid aliasee for alias: ") + $1);
+    GlobalValue* Aliasee;
+    if (Aliasee = dyn_cast<GlobalValue>(V)) {
+      GlobalAlias* GA = new GlobalAlias(VTy, $4, Name, Aliasee, CurModule.CurrentModule);
+      GA->setVisibility($2);
+      InsertValue(GA, CurModule.Values);
+    } else
+      GEN_ERROR("Aliases can be created only to global values");
+    CHECK_FOR_ERROR
+    delete $5;
+  }
   | TARGET TargetDefinition { 
     CHECK_FOR_ERROR
   }
index ee6d9e6..f7606c6 100644 (file)
@@ -348,7 +348,7 @@ Constant* BytecodeReader::getConstantValue(unsigned TypeSlot, unsigned Slot) {
 /// with this method. The ValueTable argument must be one of ModuleValues
 /// or FunctionValues data members of this class.
 unsigned BytecodeReader::insertValue(Value *Val, unsigned type,
-                                      ValueTable &ValueTab) {
+                                     ValueTable &ValueTab) {
   if (ValueTab.size() <= type)
     ValueTab.resize(type+1);
 
@@ -1855,7 +1855,7 @@ void BytecodeReader::ParseModuleGlobalInfo() {
        case 1: Func->setLinkage(Function::DLLImportLinkage); break;
        case 2: Func->setLinkage(Function::ExternalWeakLinkage); break;        
        default: assert(0 && "Unsupported external linkage");        
-      }      
+      }
     }
     
     Func->setCallingConv(CC-1);
@@ -1919,6 +1919,53 @@ void BytecodeReader::ParseModuleGlobalInfo() {
       I->first->setSection(SectionNames[I->second-1]);
     }
 
+  if (At != BlockEnd) {
+    // Read aliases...
+    unsigned VarType = read_vbr_uint();
+    while (VarType != Type::VoidTyID) { // List is terminated by Void
+      unsigned TypeSlotNo = VarType >> 2;
+      unsigned EncodedLinkage = VarType & 3;
+      unsigned AliaseeTypeSlotNo, AliaseeSlotNo;
+
+      AliaseeTypeSlotNo = read_vbr_uint();
+      AliaseeSlotNo = read_vbr_uint();
+
+      const Type *Ty = getType(TypeSlotNo);
+      if (!Ty)
+        error("Alias has no type! SlotNo=" + utostr(TypeSlotNo));
+
+      if (!isa<PointerType>(Ty))
+        error("Alias not a pointer type! Ty= " + Ty->getDescription());
+      
+      Value* V = getValue(AliaseeTypeSlotNo, AliaseeSlotNo, false);
+      if (!V)
+        error("Invalid aliasee! TypeSlotNo=" + utostr(AliaseeTypeSlotNo) +
+              " SlotNo=" + utostr(AliaseeSlotNo));
+      if (!isa<GlobalValue>(V))
+        error("Aliasee is not global value! SlotNo=" + utostr(AliaseeSlotNo));
+
+      GlobalValue::LinkageTypes Linkage;
+      switch (EncodedLinkage) {
+      case 0:
+        Linkage = GlobalValue::ExternalLinkage;
+        break;
+      case 1:
+        Linkage = GlobalValue::InternalLinkage;
+        break;
+      case 2:
+        Linkage = GlobalValue::WeakLinkage;
+        break;
+      default:
+       assert(0 && "Unsupported encoded alias linkage");
+      }
+      
+      GlobalAlias *GA = new GlobalAlias(Ty, Linkage, "",
+                                        dyn_cast<GlobalValue>(V), TheModule);
+      insertValue(GA, TypeSlotNo, ModuleValues);
+      VarType = read_vbr_uint();
+    }
+  }  
+
   // This is for future proofing... in the future extra fields may be added that
   // we don't understand, so we transparently ignore them.
   //
index 12724dd..7295239 100644 (file)
@@ -1088,9 +1088,34 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
   output_vbr((unsigned)SectionNames.size());
   for (unsigned i = 0, e = SectionNames.size(); i != e; ++i)
     output(SectionNames[i]);
-  
+
   // Output the inline asm string.
   output(M->getModuleInlineAsm());
+
+  // Output aliases
+  for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
+       I != E; ++I) {
+    unsigned Slot = Table.getTypeSlot(I->getType());
+    assert(((Slot << 2) >> 2) == Slot && "Slot # too big!");
+    unsigned aliasLinkage = 0;
+    switch (I->getLinkage()) {
+     case GlobalValue::ExternalLinkage:
+      aliasLinkage = 0;
+      break;
+     case GlobalValue::InternalLinkage:
+      aliasLinkage = 1;
+      break;
+     case GlobalValue::WeakLinkage:
+      aliasLinkage = 2;
+      break;
+     default:
+      assert(0 && "Invalid alias linkage");
+    }    
+    output_vbr((Slot << 2) | aliasLinkage);
+    output_vbr(Table.getTypeSlot(I->getAliasee()->getType()));
+    output_vbr(Table.getSlot(I->getAliasee()));
+  }
+  output_typeid(Table.getTypeSlot(Type::VoidTy));
 }
 
 void BytecodeWriter::outputInstructions(const Function *F) {
index 16c478d..90a98cb 100644 (file)
@@ -111,7 +111,7 @@ bool AsmPrinter::doInitialization(Module &M) {
 
 bool AsmPrinter::doFinalization(Module &M) {
   if (TAI->getWeakRefDirective()) {
-    if (ExtWeakSymbols.begin() != ExtWeakSymbols.end())
+    if (!ExtWeakSymbols.empty())
       SwitchToDataSection("");
 
     for (std::set<const GlobalValue*>::iterator i = ExtWeakSymbols.begin(),
@@ -122,6 +122,30 @@ bool AsmPrinter::doFinalization(Module &M) {
     }
   }
 
+  if (TAI->getSetDirective()) {
+    if (M.alias_size())
+      SwitchToTextSection(TAI->getTextSection());
+
+    O << "\n";
+    for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
+         I!=E; ++I) {
+      const GlobalValue *Aliasee = I->getAliasee();
+      assert(Aliasee && "Aliasee cannot be null!");
+      std::string Target   = Mang->getValueName(Aliasee);
+      std::string Name     = Mang->getValueName(I);
+
+      // Aliases with external weak linkage was emitted already
+      if (I->hasExternalLinkage())
+        O << "\t.globl\t" << Name << "\n";
+      else if (I->hasWeakLinkage())
+        O << TAI->getWeakRefDirective() << Name << "\n";
+      else if (!I->hasInternalLinkage())
+        assert(0 && "Invalid alias linkage");
+      
+      O << TAI->getSetDirective() << Name << ", " << Target << "\n";
+    }
+  }
+
   delete Mang; Mang = 0;
   return false;
 }
index 8b0ad03..fd8af4f 100644 (file)
@@ -108,6 +108,7 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
     ReadOnlySection = "\t.section\t.rodata\n";
     PrivateGlobalPrefix = ".L";
     WeakRefDirective = "\t.weak\t";
+    SetDirective = "\t.set\t";
     DwarfRequiresFrameSection = false;
     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"\",@progbits";
     DwarfInfoSection =    "\t.section\t.debug_info,\"\",@progbits";
@@ -137,6 +138,7 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
     AbsoluteSectionOffsets = true;
     PrivateGlobalPrefix = "L";  // Prefix for private global symbols
     WeakRefDirective = "\t.weak\t";
+    SetDirective = "\t.set\t";
     DwarfRequiresFrameSection = false;
     DwarfSectionOffsetDirective = "\t.secrel32\t";
     DwarfAbbrevSection =  "\t.section\t.debug_abbrev,\"dr\"";
index 7fd1102..560bcb5 100644 (file)
@@ -62,7 +62,8 @@ bool GlobalDCE::runOnModule(Module &M) {
       GlobalIsNeeded(I);
   }
 
-  for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) {
+  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+       I != E; ++I) {
     Changed |= RemoveUnusedGlobalValue(*I);
     // Externally visible & appending globals are needed, if they have an
     // initializer.
@@ -72,6 +73,13 @@ bool GlobalDCE::runOnModule(Module &M) {
   }
 
 
+  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
+       I != E; ++I) {
+    Changed |= RemoveUnusedGlobalValue(*I);
+    // Aliases are always needed even if they are not used.
+    GlobalIsNeeded(I);
+  }
+
   // Now that all globals which are needed are in the AliveGlobals set, we loop
   // through the program, deleting those which are not alive.
   //
@@ -135,6 +143,9 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
     // referenced by the initializer to the alive set.
     if (GV->hasInitializer())
       MarkUsedGlobalsAsNeeded(GV->getInitializer());
+  } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) {
+    // If this is a global alias we also need it's aliasee
+    GlobalIsNeeded(const_cast<GlobalValue*>(GA->getAliasee()));
   } else {
     // Otherwise this must be a function object.  We have to scan the body of
     // the function looking for constants and global values which are used as
index 90f0198..ec9a553 100644 (file)
@@ -166,6 +166,8 @@ static SlotMachine *createSlotMachine(const Value *V) {
     return new SlotMachine(BB->getParent());
   } else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)){
     return new SlotMachine(GV->getParent());
+  } else if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V)){
+    return new SlotMachine(GA->getParent());    
   } else if (const Function *Func = dyn_cast<Function>(V)) {
     return new SlotMachine(Func);
   }
@@ -683,12 +685,13 @@ public:
     fillTypeNameTable(M, TypeNames);
   }
 
-  inline void write(const Module *M)         { printModule(M);      }
-  inline void write(const GlobalVariable *G) { printGlobal(G);      }
-  inline void write(const Function *F)       { printFunction(F);    }
-  inline void write(const BasicBlock *BB)    { printBasicBlock(BB); }
+  inline void write(const Module *M)         { printModule(M);       }
+  inline void write(const GlobalVariable *G) { printGlobal(G);       }
+  inline void write(const GlobalAlias *G)    { printAlias(G);        }
+  inline void write(const Function *F)       { printFunction(F);     }
+  inline void write(const BasicBlock *BB)    { printBasicBlock(BB);  }
   inline void write(const Instruction *I)    { printInstruction(*I); }
-  inline void write(const Type *Ty)          { printType(Ty);       }
+  inline void write(const Type *Ty)          { printType(Ty);        }
 
   void writeOperand(const Value *Op, bool PrintType);
 
@@ -698,6 +701,7 @@ private:
   void printModule(const Module *M);
   void printTypeSymbolTable(const TypeSymbolTable &ST);
   void printGlobal(const GlobalVariable *GV);
+  void printAlias(const GlobalAlias *GV);
   void printFunction(const Function *F);
   void printArgument(const Argument *FA, uint16_t ParamAttrs);
   void printBasicBlock(const BasicBlock *BB);
@@ -848,6 +852,11 @@ void AssemblyWriter::printModule(const Module *M) {
   // Output all of the functions.
   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
     printFunction(I);
+
+  // Output all aliases
+  for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
+       I != E; ++I)
+    printAlias(I);
 }
 
 void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
@@ -888,16 +897,55 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
     assert(C &&  "GlobalVar initializer isn't constant?");
     writeOperand(GV->getInitializer(), false);
   }
-  
+
   if (GV->hasSection())
     Out << ", section \"" << GV->getSection() << '"';
   if (GV->getAlignment())
     Out << ", align " << GV->getAlignment();
-  
+
   printInfoComment(*GV);
   Out << "\n";
 }
 
+void AssemblyWriter::printAlias(const GlobalAlias *GA) {
+  Out << getLLVMName(GA->getName(), GlobalPrefix) << " = ";
+  switch (GA->getVisibility()) {
+  default: assert(0 && "Invalid visibility style!");
+  case GlobalValue::DefaultVisibility: break;
+  case GlobalValue::HiddenVisibility: Out << "hidden "; break;
+  }
+
+  Out << "alias ";
+
+  switch (GA->getLinkage()) {
+  case GlobalValue::WeakLinkage: Out << "weak "; break;
+  case GlobalValue::InternalLinkage: Out << "internal "; break;
+  case GlobalValue::ExternalLinkage: break;
+  default:
+   assert(0 && "Invalid alias linkage");
+  }
+  
+  const GlobalValue *Aliasee = GA->getAliasee();
+  assert(Aliasee && "Aliasee cannot be null");
+    
+  if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
+    printType(GV->getType());
+    Out << " " << getLLVMName(GV->getName(), GlobalPrefix);
+  } else if (const Function *F = dyn_cast<Function>(Aliasee)) {
+    printType(F->getFunctionType());
+    Out << "* ";
+
+    if (!F->getName().empty())
+      Out << getLLVMName(F->getName(), GlobalPrefix);
+    else
+      Out << "@\"\"";
+  } else
+    assert(0 && "Unsupported aliasee");
+
+  printInfoComment(*GA);
+  Out << "\n";
+}
+
 void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) {
   // Print the types.
   for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end();
@@ -1336,6 +1384,12 @@ void GlobalVariable::print(std::ostream &o) const {
   W.write(this);
 }
 
+void GlobalAlias::print(std::ostream &o) const {
+  SlotMachine SlotTable(getParent());
+  AssemblyWriter W(o, SlotTable, getParent(), 0);
+  W.write(this);
+}
+
 void Function::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const {
   SlotMachine SlotTable(getParent());
   AssemblyWriter W(o, SlotTable, getParent(), AAW);
@@ -1538,8 +1592,10 @@ void SlotMachine::CreateModuleSlot(const GlobalValue *V) {
   
   SC_DEBUG("  Inserting value [" << V->getType() << "] = " << V << " slot=" <<
            DestSlot << " [");
-  // G = Global, F = Function, o = other
-  SC_DEBUG((isa<GlobalVariable>(V) ? 'G' : 'F') << "]\n");
+  // G = Global, F = Function, A = Alias, o = other
+  SC_DEBUG((isa<GlobalVariable>(V) ? 'G' :
+            (isa<Function> ? 'F' :
+             (isa<GlobalAlias> ? 'A' : 'o'))) << "]\n");
 }
 
 
index 61d9de3..c64b719 100644 (file)
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/GlobalVariable.h"
+#include "llvm/GlobalAlias.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Module.h"
 #include "llvm/Support/LeakDetector.h"
@@ -76,6 +77,7 @@ void GlobalValue::destroyConstant() {
   assert(0 && "You can't GV->destroyConstant()!");
   abort();
 }
+  
 //===----------------------------------------------------------------------===//
 // GlobalVariable Implementation
 //===----------------------------------------------------------------------===//
@@ -120,7 +122,6 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
     Before->getParent()->getGlobalList().insert(Before, this);
 }
 
-
 void GlobalVariable::setParent(Module *parent) {
   if (getParent())
     LeakDetector::addGarbageObject(this);
@@ -156,3 +157,45 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To,
   // Okay, preconditions out of the way, replace the constant initializer.
   this->setOperand(0, cast<Constant>(To));
 }
+
+//===----------------------------------------------------------------------===//
+// GlobalAlias Implementation
+//===----------------------------------------------------------------------===//
+
+GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link,
+                         const std::string &Name, const GlobalValue* aliasee,
+                         Module *ParentModule)
+  : GlobalValue(Ty, Value::GlobalAliasVal, 0, 0,
+                Link, Name), Aliasee(aliasee) {
+  LeakDetector::addGarbageObject(this);
+
+  if (ParentModule)
+    ParentModule->getAliasList().push_back(this);
+}
+
+void GlobalAlias::setParent(Module *parent) {
+  if (getParent())
+    LeakDetector::addGarbageObject(this);
+  Parent = parent;
+  if (getParent())
+    LeakDetector::removeGarbageObject(this);
+}
+
+void GlobalAlias::removeFromParent() {
+  getParent()->getAliasList().remove(this);
+}
+
+void GlobalAlias::eraseFromParent() {
+  getParent()->getAliasList().erase(this);
+}
+
+bool GlobalAlias::isDeclaration() const {
+  return (Aliasee && Aliasee->isDeclaration());
+}
+
+void GlobalAlias::setAliasee(const GlobalValue *GV) 
+{
+  // FIXME: Some checks?
+  Aliasee = GV;
+}
+
index ddd503d..c660323 100644 (file)
@@ -45,6 +45,12 @@ GlobalVariable *ilist_traits<GlobalVariable>::createSentinel() {
   LeakDetector::removeGarbageObject(Ret);
   return Ret;
 }
+GlobalAlias *ilist_traits<GlobalAlias>::createSentinel() {
+  GlobalAlias *Ret = new GlobalAlias(Type::Int32Ty, GlobalValue::ExternalLinkage);
+  // This should not be garbage monitored.
+  LeakDetector::removeGarbageObject(Ret);
+  return Ret;
+}
 
 iplist<Function> &ilist_traits<Function>::getList(Module *M) {
   return M->getFunctionList();
@@ -52,11 +58,15 @@ iplist<Function> &ilist_traits<Function>::getList(Module *M) {
 iplist<GlobalVariable> &ilist_traits<GlobalVariable>::getList(Module *M) {
   return M->getGlobalList();
 }
+iplist<GlobalAlias> &ilist_traits<GlobalAlias>::getList(Module *M) {
+  return M->getAliasList();
+}
 
 // Explicit instantiations of SymbolTableListTraits since some of the methods
 // are not in the public header file.
 template class SymbolTableListTraits<GlobalVariable, Module>;
 template class SymbolTableListTraits<Function, Module>;
+template class SymbolTableListTraits<GlobalAlias, Module>;
 
 //===----------------------------------------------------------------------===//
 // Primitive Module methods.
@@ -72,6 +82,7 @@ Module::~Module() {
   dropAllReferences();
   GlobalList.clear();
   FunctionList.clear();
+  AliasList.clear();
   LibraryList.clear();
   delete ValSymTab;
   delete TypeSymTab;
@@ -212,6 +223,18 @@ GlobalVariable *Module::getGlobalVariable(const std::string &Name,
 }
 
 //===----------------------------------------------------------------------===//
+// Methods for easy access to the global variables in the module.
+//
+
+// getNamedAlias - Look up the specified global in the module symbol table.
+// If it does not exist, return null.
+//
+GlobalAlias *Module::getNamedAlias(const std::string &Name) const {
+  const ValueSymbolTable &SymTab = getValueSymbolTable();
+  return dyn_cast_or_null<GlobalAlias>(SymTab.lookup(Name));
+}
+
+//===----------------------------------------------------------------------===//
 // Methods for easy access to the types in the module.
 //
 
index 1936766..1578c2d 100644 (file)
@@ -141,6 +141,10 @@ namespace {  // Anonymous namespace for class
            I != E; ++I)
         visitGlobalVariable(*I);
 
+      for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 
+           I != E; ++I)
+        visitGlobalAlias(*I);
+
       // If the module is broken, abort at this time.
       return abortIfBroken();
     }
@@ -179,6 +183,7 @@ namespace {  // Anonymous namespace for class
     void verifyTypeSymbolTable(TypeSymbolTable &ST);
     void visitGlobalValue(GlobalValue &GV);
     void visitGlobalVariable(GlobalVariable &GV);
+    void visitGlobalAlias(GlobalAlias &GA);
     void visitFunction(Function &F);
     void visitBasicBlock(BasicBlock &BB);
     void visitTruncInst(TruncInst &I);
@@ -277,7 +282,9 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
   Assert1(!GV.isDeclaration() ||
           GV.hasExternalLinkage() ||
           GV.hasDLLImportLinkage() ||
-          GV.hasExternalWeakLinkage(),
+          GV.hasExternalWeakLinkage() ||
+          (isa<GlobalAlias>(GV) &&
+           (GV.hasInternalLinkage() || GV.hasWeakLinkage())),
   "Global is external, but doesn't have external or dllimport or weak linkage!",
           &GV);
 
@@ -303,6 +310,16 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
   visitGlobalValue(GV);
 }
 
+void Verifier::visitGlobalAlias(GlobalAlias &GA) {
+  Assert1(!GA.getName().empty(),
+          "Alias name cannot be empty!", &GA);
+  Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() ||
+          GA.hasWeakLinkage(),
+          "Alias should have external or external weak linkage!", &GA);
+
+  visitGlobalValue(GA);
+}
+
 void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) {
 }
 
diff --git a/test/CodeGen/X86/aliases.ll b/test/CodeGen/X86/aliases.ll
new file mode 100644 (file)
index 0000000..33d30db
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | \
+; RUN:   llc -mtriple=i686-pc-linux-gnu -o %t -f
+; RUN: grep -c set %t   | grep 4
+; RUN: grep -c globl %t | grep 3
+; RUN: grep -c weak %t  | grep 1
+
+@bar = external global i32
+@foo1 = alias i32* @bar
+@foo2 = alias i32* @bar
+
+%FunTy = type i32()
+
+declare i32 @foo_f()
+@bar_f = alias weak %FunTy* @foo_f
+
+@bar_i = alias internal i32* @bar
+
+define i32 @test() {
+entry:
+   %tmp = load i32* @foo1
+   %tmp1 = load i32* @foo2
+   %tmp0 = load i32* @bar_i
+   %tmp2 = call i32 @foo_f()
+   %tmp3 = add i32 %tmp, %tmp2
+   %tmp4 = call %FunTy* @bar_f()
+   %tmp5 = add i32 %tmp3, %tmp4
+   %tmp6 = add i32 %tmp1, %tmp5
+   %tmp7 = add i32 %tmp6, %tmp0
+   ret i32 %tmp7
+}
diff --git a/test/Feature/aliases.ll b/test/Feature/aliases.ll
new file mode 100644 (file)
index 0000000..7a4aad0
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llvm-as < %s | llvm-dis > %t1.ll
+; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
+; RUN: diff %t1.ll %t2.ll
+
+@bar = external global i32
+@foo1 = alias i32* @bar
+@foo2 = alias i32* @bar
+
+%FunTy = type i32()
+
+declare i32 @foo_f()
+@bar_f = alias weak %FunTy* @foo_f
+
+@bar_i = alias internal i32* @bar
+
+define i32 @test() {
+entry:
+   %tmp = load i32* @foo1
+   %tmp1 = load i32* @foo2
+   %tmp0 = load i32* @bar_i
+   %tmp2 = call i32 @foo_f()
+   %tmp3 = add i32 %tmp, %tmp2
+   %tmp4 = call %FunTy* @bar_f()
+   %tmp5 = add i32 %tmp3, %tmp4
+   %tmp6 = add i32 %tmp1, %tmp5
+   %tmp7 = add i32 %tmp6, %tmp0
+   ret i32 %tmp7
+}