Implement aliases. This fixes PR1017 and it's dependent bugs. CFE part

will follow.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36435 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov 2007-04-25 14:27:10 +00:00
parent 24a3cc4c83
commit 8b0a8c84da
22 changed files with 552 additions and 52 deletions

View 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> target triple specified, i.e. a platform-independent module).</td>
</tr> </tr>
<tr> <tr>
<td><a href="#string">string</a></td> <td><a href="#string">string</a></td>
<td class="td_left">The data layout string describing the endianness, <td class="td_left">The data layout string describing the endianness,
pointer size, and type alignments for which the module was written pointer size, and type alignments for which the module was written
(blank means no data layout specified, i.e. a platform-independent (blank means no data layout specified, i.e. a platform-independent
module).</td> module).</td>
</tr> </tr>
<tr> <tr>
<td><a href="#llist">llist</a>(<a href="#string">string</a>)</td> <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><a href="#string">string</a></td>
<td class="td_left">The inline asm block for this module.</td> <td class="td_left">The inline asm block for this module.</td>
</tr> </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> </tbody>
</table> </table>
</div> </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><a href="#bit">bit(5-30)</a></td>
<td class="td_left">Type slot number of type for the function.</td> <td class="td_left">Type slot number of type for the function.</td>
</tr> </tr>
<tr> <tr>
<td><a href="#bit">bit(31)</a></td> <td><a href="#bit">bit(31)</a></td>
<td class="td_left">Indicates whether an extension word follows.</td> <td class="td_left">Indicates whether an extension word follows.</td>
</tr> </tr>
@ -1185,6 +1190,56 @@ follows with the following fields:</p>
</div> </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_subsection"><a name="constantpool">Constant Pool</a> </div>
<div class="doc_text"> <div class="doc_text">

View File

@ -498,7 +498,8 @@ outside of the current module.</p>
<p>It is illegal for a function <i>declaration</i> <p>It is illegal for a function <i>declaration</i>
to have any linkage type other than "externally visible", <tt>dllimport</tt>, to have any linkage type other than "externally visible", <tt>dllimport</tt>,
or <tt>extern_weak</tt>.</p> or <tt>extern_weak</tt>.</p>
<p>Aliases can have only <tt>external</tt>, <tt>internal</tt> and <tt>weak</tt>
linkages.
</div> </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 <p>Global variables define regions of memory allocated at compilation time
instead of run-time. Global variables may optionally be initialized, may have instead of run-time. Global variables may optionally be initialized, may have
an explicit section to be placed in, and may an explicit section to be placed in, and may have an optional explicit alignment
have an optional explicit alignment specified. A variable may be defined as specified. A variable may be defined as "thread_local", which means that it
"thread_local", which means that it will not be shared by threads (each thread will not be shared by threads (each thread will have a separated copy of the
will have a separated copy of the variable). variable). A variable may be defined as a global "constant," which indicates
A variable may be defined as a global "constant," which indicates that the that the contents of the variable will <b>never</b> be modified (enabling better
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 optimization, allowing the global data to be placed in the read-only section of
an executable, etc). Note that variables that need runtime initialization an executable, etc). Note that variables that need runtime initialization
cannot be marked "constant" as there is a store to the variable.</p> cannot be marked "constant" as there is a store to the variable.</p>
@ -698,6 +698,27 @@ a power of 2.</p>
</div> </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_subsection"><a name="paramattrs">Parameter Attributes</a></div>
<div class="doc_text"> <div class="doc_text">

View File

@ -24,6 +24,7 @@ namespace llvm {
class Constant; class Constant;
class ConstantArray; class ConstantArray;
class GlobalVariable; class GlobalVariable;
class GlobalAlias;
class MachineConstantPoolEntry; class MachineConstantPoolEntry;
class MachineConstantPoolValue; class MachineConstantPoolValue;
class Mangler; class Mangler;

View File

@ -141,12 +141,12 @@ public:
/// removeFromParent - This method unlinks 'this' from the containing module, /// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it. /// but does not delete it.
/// ///
void removeFromParent(); virtual void removeFromParent();
/// eraseFromParent - This method unlinks 'this' from the containing module /// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it. /// and deletes it.
/// ///
void eraseFromParent(); virtual void eraseFromParent();
/// Get the underlying elements of the Function... the basic block list is /// Get the underlying elements of the Function... the basic block list is

View File

@ -121,6 +121,16 @@ public:
/// value is outside of the current translation unit... /// value is outside of the current translation unit...
virtual bool isDeclaration() const = 0; 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 /// getParent - Get the module that this global value is contained inside
/// of... /// of...
inline Module *getParent() { return Parent; } inline Module *getParent() { return Parent; }
@ -136,7 +146,8 @@ public:
static inline bool classof(const GlobalValue *) { return true; } static inline bool classof(const GlobalValue *) { return true; }
static inline bool classof(const Value *V) { static inline bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal || return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal; V->getValueID() == Value::GlobalVariableVal ||
V->getValueID() == Value::GlobalAliasVal;
} }
}; };

View File

@ -107,12 +107,12 @@ public:
/// removeFromParent - This method unlinks 'this' from the containing module, /// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it. /// but does not delete it.
/// ///
void removeFromParent(); virtual void removeFromParent();
/// eraseFromParent - This method unlinks 'this' from the containing module /// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it. /// and deletes it.
/// ///
void eraseFromParent(); virtual void eraseFromParent();
/// Override Constant's implementation of this method so we can /// Override Constant's implementation of this method so we can
/// replace constant initializers. /// replace constant initializers.

View File

@ -16,12 +16,12 @@
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/GlobalVariable.h" #include "llvm/GlobalVariable.h"
#include "llvm/GlobalAlias.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include <vector> #include <vector>
namespace llvm { namespace llvm {
class GlobalVariable;
class GlobalValueRefMap; // Used by ConstantVals.cpp class GlobalValueRefMap; // Used by ConstantVals.cpp
class FunctionType; class FunctionType;
@ -43,6 +43,15 @@ template<> struct ilist_traits<GlobalVariable>
static inline ValueSymbolTable *getSymTab(Module *M); static inline ValueSymbolTable *getSymTab(Module *M);
static int getListOffset(); 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 /// 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 /// LLVM module. Modules are the top level container of all other LLVM
@ -63,6 +72,8 @@ public:
typedef iplist<GlobalVariable> GlobalListType; typedef iplist<GlobalVariable> GlobalListType;
/// The type for the list of functions. /// The type for the list of functions.
typedef iplist<Function> FunctionListType; typedef iplist<Function> FunctionListType;
/// The type for the list of aliases.
typedef iplist<GlobalAlias> AliasListType;
/// The type for the list of dependent libraries. /// The type for the list of dependent libraries.
typedef std::vector<std::string> LibraryListType; typedef std::vector<std::string> LibraryListType;
@ -77,6 +88,11 @@ public:
/// The Function constant iterator /// The Function constant iterator
typedef FunctionListType::const_iterator const_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. /// The Library list iterator.
typedef LibraryListType::const_iterator lib_iterator; typedef LibraryListType::const_iterator lib_iterator;
@ -92,6 +108,7 @@ public:
private: private:
GlobalListType GlobalList; ///< The Global Variables in the module GlobalListType GlobalList; ///< The Global Variables in the module
FunctionListType FunctionList; ///< The Functions 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 LibraryListType LibraryList; ///< The Libraries needed by the module
std::string GlobalScopeAsm; ///< Inline Asm at global scope. std::string GlobalScopeAsm; ///< Inline Asm at global scope.
ValueSymbolTable *ValSymTab; ///< Symbol table for values ValueSymbolTable *ValSymTab; ///< Symbol table for values
@ -175,10 +192,10 @@ public:
/// getOrInsertFunction - Look up the specified function in the module symbol /// getOrInsertFunction - Look up the specified function in the module symbol
/// table. If it does not exist, add a prototype for the function and return /// 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 /// it. This function guarantees to return a constant of pointer to the
/// specified function type or a ConstantExpr BitCast of that type if the /// specified function type or a ConstantExpr BitCast of that type if the
/// named /// function has a different type. This version of the method /// named function has a different type. This version of the method takes a
/// takes a null terminated list of function arguments, which makes it /// null terminated list of function arguments, which makes it easier for
/// easier for clients to use. /// clients to use.
Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy,...) Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy,...)
END_WITH_NULL; END_WITH_NULL;
@ -205,6 +222,15 @@ public:
GlobalVariable *getNamedGlobal(const std::string &Name) const { GlobalVariable *getNamedGlobal(const std::string &Name) const {
return getGlobalVariable(Name, true); 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 /// @name Type Accessors
@ -235,14 +261,18 @@ public:
const FunctionListType &getFunctionList() const { return FunctionList; } const FunctionListType &getFunctionList() const { return FunctionList; }
/// Get the Module's list of functions. /// Get the Module's list of functions.
FunctionListType &getFunctionList() { return FunctionList; } 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 /// Get the symbol table of global variable and function identifiers
const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; }
/// Get the Module's symbol table of global variable and function identifiers. /// Get the Module's symbol table of global variable and function identifiers.
ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; }
/// Get the symbol table of types /// 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 /// Get the Module's symbol table of types
TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; } TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; }
/// @} /// @}
/// @name Global Variable Iteration /// @name Global Variable Iteration
@ -272,7 +302,7 @@ public:
/// Get a constant iterator to the last function. /// Get a constant iterator to the last function.
const_iterator end () const { return FunctionList.end(); } const_iterator end () const { return FunctionList.end(); }
/// Determine how many functions are in the Module's list of functions. /// 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. /// Determine if the list of functions is empty.
bool empty() const { return FunctionList.empty(); } bool empty() const { return FunctionList.empty(); }
@ -283,9 +313,9 @@ public:
/// @brief Get a constant iterator to beginning of dependent library list. /// @brief Get a constant iterator to beginning of dependent library list.
inline lib_iterator lib_begin() const { return LibraryList.begin(); } inline lib_iterator lib_begin() const { return LibraryList.begin(); }
/// @brief Get a constant iterator to end of dependent library list. /// @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. /// @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 /// @brief Add a library to the list of dependent libraries
void addLibrary(const std::string& Lib); void addLibrary(const std::string& Lib);
/// @brief Remove a library from the list of dependent libraries /// @brief Remove a library from the list of dependent libraries
@ -293,6 +323,23 @@ public:
/// @brief Get all the libraries /// @brief Get all the libraries
inline const LibraryListType& getLibraries() const { return LibraryList; } 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 /// @name Utility functions for printing and dumping Module objects
/// @{ /// @{
@ -324,6 +371,10 @@ public:
Module *Obj = 0; Module *Obj = 0;
return unsigned(reinterpret_cast<uintptr_t>(&Obj->GlobalList)); 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. /// An iostream inserter for modules.
@ -342,6 +393,11 @@ ilist_traits<GlobalVariable>::getSymTab(Module *M) {
return M ? &M->getValueSymbolTable() : 0; return M ? &M->getValueSymbolTable() : 0;
} }
inline ValueSymbolTable *
ilist_traits<GlobalAlias>::getSymTab(Module *M) {
return M ? &M->getValueSymbolTable() : 0;
}
inline int inline int
ilist_traits<Function>::getListOffset() { ilist_traits<Function>::getListOffset() {
return Module::getFunctionListOffset(); return Module::getFunctionListOffset();
@ -352,6 +408,11 @@ ilist_traits<GlobalVariable>::getListOffset() {
return Module::getGlobalVariableListOffset(); return Module::getGlobalVariableListOffset();
} }
inline int
ilist_traits<GlobalAlias>::getListOffset() {
return Module::getAliasListOffset();
}
} // End llvm namespace } // End llvm namespace
#endif #endif

View File

@ -30,6 +30,7 @@ class BasicBlock;
class GlobalValue; class GlobalValue;
class Function; class Function;
class GlobalVariable; class GlobalVariable;
class GlobalAlias;
class InlineAsm; class InlineAsm;
class ValueSymbolTable; class ValueSymbolTable;
class TypeSymbolTable; class TypeSymbolTable;
@ -160,6 +161,7 @@ public:
ArgumentVal, // This is an instance of Argument ArgumentVal, // This is an instance of Argument
BasicBlockVal, // This is an instance of BasicBlock BasicBlockVal, // This is an instance of BasicBlock
FunctionVal, // This is an instance of Function FunctionVal, // This is an instance of Function
GlobalAliasVal, // This is an instance of GlobalAlias
GlobalVariableVal, // This is an instance of GlobalVariable GlobalVariableVal, // This is an instance of GlobalVariable
UndefValueVal, // This is an instance of UndefValue UndefValueVal, // This is an instance of UndefValue
ConstantExprVal, // This is an instance of ConstantExpr 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) { template <> inline bool isa_impl<GlobalVariable, Value>(const Value &Val) {
return Val.getValueID() == Value::GlobalVariableVal; 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) { 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 } // End llvm namespace

View File

@ -35,6 +35,7 @@ class ValueSymbolTable {
friend class SymbolTableListTraits<Instruction, BasicBlock>; friend class SymbolTableListTraits<Instruction, BasicBlock>;
friend class SymbolTableListTraits<Function, Module>; friend class SymbolTableListTraits<Function, Module>;
friend class SymbolTableListTraits<GlobalVariable, Module>; friend class SymbolTableListTraits<GlobalVariable, Module>;
friend class SymbolTableListTraits<GlobalAlias, Module>;
/// @name Types /// @name Types
/// @{ /// @{
public: public:

View File

@ -222,6 +222,7 @@ datalayout { return DATALAYOUT; }
volatile { return VOLATILE; } volatile { return VOLATILE; }
align { return ALIGN; } align { return ALIGN; }
section { return SECTION; } section { return SECTION; }
alias { return ALIAS; }
module { return MODULE; } module { return MODULE; }
asm { return ASM_TOK; } asm { return ASM_TOK; }
sideeffect { return SIDEEFFECT; } sideeffect { return SIDEEFFECT; }

View File

@ -1004,6 +1004,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%type <BoolVal> OptSideEffect // 'sideeffect' or not. %type <BoolVal> OptSideEffect // 'sideeffect' or not.
%type <Linkage> GVInternalLinkage GVExternalLinkage %type <Linkage> GVInternalLinkage GVExternalLinkage
%type <Linkage> FunctionDefineLinkage FunctionDeclareLinkage %type <Linkage> FunctionDefineLinkage FunctionDeclareLinkage
%type <Linkage> AliasLinkage
%type <Visibility> GVVisibilityStyle %type <Visibility> GVVisibilityStyle
// ValueRef - Unresolved reference to a definition or BB // 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 %token<StrVal> LOCALVAR GLOBALVAR LABELSTR STRINGCONSTANT ATSTRINGCONSTANT
%type <StrVal> LocalName OptLocalName OptLocalAssign %type <StrVal> LocalName OptLocalName OptLocalAssign
%type <StrVal> GlobalName OptGlobalAssign %type <StrVal> GlobalName OptGlobalAssign GlobalAssign
%type <UIntVal> OptAlign OptCAlign %type <UIntVal> OptAlign OptCAlign
%type <StrVal> OptSection SectionString %type <StrVal> OptSection SectionString
%token ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %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 TO DOTDOTDOT NULL_TOK UNDEF INTERNAL LINKONCE WEAK APPENDING
%token DLLIMPORT DLLEXPORT EXTERN_WEAK %token DLLIMPORT DLLEXPORT EXTERN_WEAK
%token OPAQUE EXTERNAL TARGET TRIPLE ALIGN %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN
@ -1136,15 +1137,17 @@ OptLocalAssign : LocalName '=' {
GlobalName : GLOBALVAR | ATSTRINGCONSTANT; GlobalName : GLOBALVAR | ATSTRINGCONSTANT;
OptGlobalAssign : GlobalName '=' { OptGlobalAssign : GlobalAssign
$$ = $1;
CHECK_FOR_ERROR
}
| /*empty*/ { | /*empty*/ {
$$ = 0; $$ = 0;
CHECK_FOR_ERROR CHECK_FOR_ERROR
}; };
GlobalAssign : GlobalName '=' {
$$ = $1;
CHECK_FOR_ERROR
}
GVInternalLinkage GVInternalLinkage
: INTERNAL { $$ = GlobalValue::InternalLinkage; } : INTERNAL { $$ = GlobalValue::InternalLinkage; }
| WEAK { $$ = GlobalValue::WeakLinkage; } | WEAK { $$ = GlobalValue::WeakLinkage; }
@ -1161,6 +1164,7 @@ GVExternalLinkage
GVVisibilityStyle GVVisibilityStyle
: /*empty*/ { $$ = GlobalValue::DefaultVisibility; } : /*empty*/ { $$ = GlobalValue::DefaultVisibility; }
| DEFAULT { $$ = GlobalValue::DefaultVisibility; }
| HIDDEN { $$ = GlobalValue::HiddenVisibility; } | HIDDEN { $$ = GlobalValue::HiddenVisibility; }
; ;
@ -1170,7 +1174,7 @@ FunctionDeclareLinkage
| EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; } | EXTERN_WEAK { $$ = GlobalValue::ExternalWeakLinkage; }
; ;
FunctionDefineLinkage FunctionDefineLinkage
: /*empty*/ { $$ = GlobalValue::ExternalLinkage; } : /*empty*/ { $$ = GlobalValue::ExternalLinkage; }
| INTERNAL { $$ = GlobalValue::InternalLinkage; } | INTERNAL { $$ = GlobalValue::InternalLinkage; }
| LINKONCE { $$ = GlobalValue::LinkOnceLinkage; } | LINKONCE { $$ = GlobalValue::LinkOnceLinkage; }
@ -1178,6 +1182,12 @@ FunctionDefineLinkage
| DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; } | DLLEXPORT { $$ = GlobalValue::DLLExportLinkage; }
; ;
AliasLinkage
: /*empty*/ { $$ = GlobalValue::ExternalLinkage; }
| WEAK { $$ = GlobalValue::WeakLinkage; }
| INTERNAL { $$ = GlobalValue::InternalLinkage; }
;
OptCallingConv : /*empty*/ { $$ = CallingConv::C; } | OptCallingConv : /*empty*/ { $$ = CallingConv::C; } |
CCC_TOK { $$ = CallingConv::C; } | CCC_TOK { $$ = CallingConv::C; } |
FASTCC_TOK { $$ = CallingConv::Fast; } | FASTCC_TOK { $$ = CallingConv::Fast; } |
@ -2031,6 +2041,34 @@ Definition
CurGV = 0; CurGV = 0;
CHECK_FOR_ERROR 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 { | TARGET TargetDefinition {
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }

View File

@ -348,7 +348,7 @@ Constant* BytecodeReader::getConstantValue(unsigned TypeSlot, unsigned Slot) {
/// with this method. The ValueTable argument must be one of ModuleValues /// with this method. The ValueTable argument must be one of ModuleValues
/// or FunctionValues data members of this class. /// or FunctionValues data members of this class.
unsigned BytecodeReader::insertValue(Value *Val, unsigned type, unsigned BytecodeReader::insertValue(Value *Val, unsigned type,
ValueTable &ValueTab) { ValueTable &ValueTab) {
if (ValueTab.size() <= type) if (ValueTab.size() <= type)
ValueTab.resize(type+1); ValueTab.resize(type+1);
@ -1855,7 +1855,7 @@ void BytecodeReader::ParseModuleGlobalInfo() {
case 1: Func->setLinkage(Function::DLLImportLinkage); break; case 1: Func->setLinkage(Function::DLLImportLinkage); break;
case 2: Func->setLinkage(Function::ExternalWeakLinkage); break; case 2: Func->setLinkage(Function::ExternalWeakLinkage); break;
default: assert(0 && "Unsupported external linkage"); default: assert(0 && "Unsupported external linkage");
} }
} }
Func->setCallingConv(CC-1); Func->setCallingConv(CC-1);
@ -1919,6 +1919,53 @@ void BytecodeReader::ParseModuleGlobalInfo() {
I->first->setSection(SectionNames[I->second-1]); 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 // This is for future proofing... in the future extra fields may be added that
// we don't understand, so we transparently ignore them. // we don't understand, so we transparently ignore them.
// //

View File

@ -1088,9 +1088,34 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
output_vbr((unsigned)SectionNames.size()); output_vbr((unsigned)SectionNames.size());
for (unsigned i = 0, e = SectionNames.size(); i != e; ++i) for (unsigned i = 0, e = SectionNames.size(); i != e; ++i)
output(SectionNames[i]); output(SectionNames[i]);
// Output the inline asm string. // Output the inline asm string.
output(M->getModuleInlineAsm()); 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) { void BytecodeWriter::outputInstructions(const Function *F) {

View File

@ -111,7 +111,7 @@ bool AsmPrinter::doInitialization(Module &M) {
bool AsmPrinter::doFinalization(Module &M) { bool AsmPrinter::doFinalization(Module &M) {
if (TAI->getWeakRefDirective()) { if (TAI->getWeakRefDirective()) {
if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) if (!ExtWeakSymbols.empty())
SwitchToDataSection(""); SwitchToDataSection("");
for (std::set<const GlobalValue*>::iterator i = ExtWeakSymbols.begin(), 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; delete Mang; Mang = 0;
return false; return false;
} }

View File

@ -108,6 +108,7 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
ReadOnlySection = "\t.section\t.rodata\n"; ReadOnlySection = "\t.section\t.rodata\n";
PrivateGlobalPrefix = ".L"; PrivateGlobalPrefix = ".L";
WeakRefDirective = "\t.weak\t"; WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
DwarfRequiresFrameSection = false; DwarfRequiresFrameSection = false;
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits"; DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits"; DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
@ -137,6 +138,7 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
AbsoluteSectionOffsets = true; AbsoluteSectionOffsets = true;
PrivateGlobalPrefix = "L"; // Prefix for private global symbols PrivateGlobalPrefix = "L"; // Prefix for private global symbols
WeakRefDirective = "\t.weak\t"; WeakRefDirective = "\t.weak\t";
SetDirective = "\t.set\t";
DwarfRequiresFrameSection = false; DwarfRequiresFrameSection = false;
DwarfSectionOffsetDirective = "\t.secrel32\t"; DwarfSectionOffsetDirective = "\t.secrel32\t";
DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"dr\""; DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"dr\"";

View File

@ -62,7 +62,8 @@ bool GlobalDCE::runOnModule(Module &M) {
GlobalIsNeeded(I); 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); Changed |= RemoveUnusedGlobalValue(*I);
// Externally visible & appending globals are needed, if they have an // Externally visible & appending globals are needed, if they have an
// initializer. // 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 // Now that all globals which are needed are in the AliveGlobals set, we loop
// through the program, deleting those which are not alive. // 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. // referenced by the initializer to the alive set.
if (GV->hasInitializer()) if (GV->hasInitializer())
MarkUsedGlobalsAsNeeded(GV->getInitializer()); 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 { } else {
// Otherwise this must be a function object. We have to scan the body of // 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 // the function looking for constants and global values which are used as

View File

@ -166,6 +166,8 @@ static SlotMachine *createSlotMachine(const Value *V) {
return new SlotMachine(BB->getParent()); return new SlotMachine(BB->getParent());
} else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)){ } else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)){
return new SlotMachine(GV->getParent()); 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)) { } else if (const Function *Func = dyn_cast<Function>(V)) {
return new SlotMachine(Func); return new SlotMachine(Func);
} }
@ -683,12 +685,13 @@ public:
fillTypeNameTable(M, TypeNames); fillTypeNameTable(M, TypeNames);
} }
inline void write(const Module *M) { printModule(M); } inline void write(const Module *M) { printModule(M); }
inline void write(const GlobalVariable *G) { printGlobal(G); } inline void write(const GlobalVariable *G) { printGlobal(G); }
inline void write(const Function *F) { printFunction(F); } inline void write(const GlobalAlias *G) { printAlias(G); }
inline void write(const BasicBlock *BB) { printBasicBlock(BB); } 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 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); void writeOperand(const Value *Op, bool PrintType);
@ -698,6 +701,7 @@ private:
void printModule(const Module *M); void printModule(const Module *M);
void printTypeSymbolTable(const TypeSymbolTable &ST); void printTypeSymbolTable(const TypeSymbolTable &ST);
void printGlobal(const GlobalVariable *GV); void printGlobal(const GlobalVariable *GV);
void printAlias(const GlobalAlias *GV);
void printFunction(const Function *F); void printFunction(const Function *F);
void printArgument(const Argument *FA, uint16_t ParamAttrs); void printArgument(const Argument *FA, uint16_t ParamAttrs);
void printBasicBlock(const BasicBlock *BB); void printBasicBlock(const BasicBlock *BB);
@ -848,6 +852,11 @@ void AssemblyWriter::printModule(const Module *M) {
// Output all of the functions. // Output all of the functions.
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(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) { void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
@ -888,16 +897,55 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
assert(C && "GlobalVar initializer isn't constant?"); assert(C && "GlobalVar initializer isn't constant?");
writeOperand(GV->getInitializer(), false); writeOperand(GV->getInitializer(), false);
} }
if (GV->hasSection()) if (GV->hasSection())
Out << ", section \"" << GV->getSection() << '"'; Out << ", section \"" << GV->getSection() << '"';
if (GV->getAlignment()) if (GV->getAlignment())
Out << ", align " << GV->getAlignment(); Out << ", align " << GV->getAlignment();
printInfoComment(*GV); printInfoComment(*GV);
Out << "\n"; 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) { void AssemblyWriter::printTypeSymbolTable(const TypeSymbolTable &ST) {
// Print the types. // Print the types.
for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end(); for (TypeSymbolTable::const_iterator TI = ST.begin(), TE = ST.end();
@ -1336,6 +1384,12 @@ void GlobalVariable::print(std::ostream &o) const {
W.write(this); 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 { void Function::print(std::ostream &o, AssemblyAnnotationWriter *AAW) const {
SlotMachine SlotTable(getParent()); SlotMachine SlotTable(getParent());
AssemblyWriter W(o, SlotTable, getParent(), AAW); AssemblyWriter W(o, SlotTable, getParent(), AAW);
@ -1538,8 +1592,10 @@ void SlotMachine::CreateModuleSlot(const GlobalValue *V) {
SC_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" << SC_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
DestSlot << " ["); DestSlot << " [");
// G = Global, F = Function, o = other // G = Global, F = Function, A = Alias, o = other
SC_DEBUG((isa<GlobalVariable>(V) ? 'G' : 'F') << "]\n"); SC_DEBUG((isa<GlobalVariable>(V) ? 'G' :
(isa<Function> ? 'F' :
(isa<GlobalAlias> ? 'A' : 'o'))) << "]\n");
} }

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/GlobalVariable.h" #include "llvm/GlobalVariable.h"
#include "llvm/GlobalAlias.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Support/LeakDetector.h" #include "llvm/Support/LeakDetector.h"
@ -76,6 +77,7 @@ void GlobalValue::destroyConstant() {
assert(0 && "You can't GV->destroyConstant()!"); assert(0 && "You can't GV->destroyConstant()!");
abort(); abort();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// GlobalVariable Implementation // GlobalVariable Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -120,7 +122,6 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
Before->getParent()->getGlobalList().insert(Before, this); Before->getParent()->getGlobalList().insert(Before, this);
} }
void GlobalVariable::setParent(Module *parent) { void GlobalVariable::setParent(Module *parent) {
if (getParent()) if (getParent())
LeakDetector::addGarbageObject(this); LeakDetector::addGarbageObject(this);
@ -156,3 +157,45 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To,
// Okay, preconditions out of the way, replace the constant initializer. // Okay, preconditions out of the way, replace the constant initializer.
this->setOperand(0, cast<Constant>(To)); 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;
}

View File

@ -45,6 +45,12 @@ GlobalVariable *ilist_traits<GlobalVariable>::createSentinel() {
LeakDetector::removeGarbageObject(Ret); LeakDetector::removeGarbageObject(Ret);
return 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) { iplist<Function> &ilist_traits<Function>::getList(Module *M) {
return M->getFunctionList(); return M->getFunctionList();
@ -52,11 +58,15 @@ iplist<Function> &ilist_traits<Function>::getList(Module *M) {
iplist<GlobalVariable> &ilist_traits<GlobalVariable>::getList(Module *M) { iplist<GlobalVariable> &ilist_traits<GlobalVariable>::getList(Module *M) {
return M->getGlobalList(); return M->getGlobalList();
} }
iplist<GlobalAlias> &ilist_traits<GlobalAlias>::getList(Module *M) {
return M->getAliasList();
}
// Explicit instantiations of SymbolTableListTraits since some of the methods // Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file. // are not in the public header file.
template class SymbolTableListTraits<GlobalVariable, Module>; template class SymbolTableListTraits<GlobalVariable, Module>;
template class SymbolTableListTraits<Function, Module>; template class SymbolTableListTraits<Function, Module>;
template class SymbolTableListTraits<GlobalAlias, Module>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Primitive Module methods. // Primitive Module methods.
@ -72,6 +82,7 @@ Module::~Module() {
dropAllReferences(); dropAllReferences();
GlobalList.clear(); GlobalList.clear();
FunctionList.clear(); FunctionList.clear();
AliasList.clear();
LibraryList.clear(); LibraryList.clear();
delete ValSymTab; delete ValSymTab;
delete TypeSymTab; delete TypeSymTab;
@ -211,6 +222,18 @@ GlobalVariable *Module::getGlobalVariable(const std::string &Name,
return 0; return 0;
} }
//===----------------------------------------------------------------------===//
// 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. // Methods for easy access to the types in the module.
// //

View File

@ -141,6 +141,10 @@ namespace { // Anonymous namespace for class
I != E; ++I) I != E; ++I)
visitGlobalVariable(*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. // If the module is broken, abort at this time.
return abortIfBroken(); return abortIfBroken();
} }
@ -179,6 +183,7 @@ namespace { // Anonymous namespace for class
void verifyTypeSymbolTable(TypeSymbolTable &ST); void verifyTypeSymbolTable(TypeSymbolTable &ST);
void visitGlobalValue(GlobalValue &GV); void visitGlobalValue(GlobalValue &GV);
void visitGlobalVariable(GlobalVariable &GV); void visitGlobalVariable(GlobalVariable &GV);
void visitGlobalAlias(GlobalAlias &GA);
void visitFunction(Function &F); void visitFunction(Function &F);
void visitBasicBlock(BasicBlock &BB); void visitBasicBlock(BasicBlock &BB);
void visitTruncInst(TruncInst &I); void visitTruncInst(TruncInst &I);
@ -277,7 +282,9 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
Assert1(!GV.isDeclaration() || Assert1(!GV.isDeclaration() ||
GV.hasExternalLinkage() || GV.hasExternalLinkage() ||
GV.hasDLLImportLinkage() || 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!", "Global is external, but doesn't have external or dllimport or weak linkage!",
&GV); &GV);
@ -303,6 +310,16 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
visitGlobalValue(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) { void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) {
} }

View File

@ -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
}

28
test/Feature/aliases.ll Normal file
View File

@ -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
}