aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/BytecodeFormat.html67
-rw-r--r--docs/LangRef.html35
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h1
-rw-r--r--include/llvm/Function.h4
-rw-r--r--include/llvm/GlobalValue.h13
-rw-r--r--include/llvm/GlobalVariable.h4
-rw-r--r--include/llvm/Module.h81
-rw-r--r--include/llvm/Value.h7
-rw-r--r--include/llvm/ValueSymbolTable.h1
-rw-r--r--lib/AsmParser/Lexer.l1
-rw-r--r--lib/AsmParser/llvmAsmParser.y52
-rw-r--r--lib/Bytecode/Reader/Reader.cpp51
-rw-r--r--lib/Bytecode/Writer/Writer.cpp27
-rw-r--r--lib/CodeGen/AsmPrinter.cpp26
-rw-r--r--lib/Target/X86/X86TargetAsmInfo.cpp2
-rw-r--r--lib/Transforms/IPO/GlobalDCE.cpp13
-rw-r--r--lib/VMCore/AsmWriter.cpp74
-rw-r--r--lib/VMCore/Globals.cpp45
-rw-r--r--lib/VMCore/Module.cpp23
-rw-r--r--lib/VMCore/Verifier.cpp19
-rw-r--r--test/CodeGen/X86/aliases.ll30
-rw-r--r--test/Feature/aliases.ll28
22 files changed, 552 insertions, 52 deletions
diff --git a/docs/BytecodeFormat.html b/docs/BytecodeFormat.html
index 56fc0af..396bf2f 100644
--- a/docs/BytecodeFormat.html
+++ b/docs/BytecodeFormat.html
@@ -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
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 2fb27f6..807d104 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -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">
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index e3ca8aa..024001e 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -24,6 +24,7 @@ namespace llvm {
class Constant;
class ConstantArray;
class GlobalVariable;
+ class GlobalAlias;
class MachineConstantPoolEntry;
class MachineConstantPoolValue;
class Mangler;
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index a50601d..c0984f6 100644
--- a/include/llvm/Function.h
+++ b/include/llvm/Function.h
@@ -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
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index a20c058..317aa48 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -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;
}
};
diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h
index 00d4acb..303e57f 100644
--- a/include/llvm/GlobalVariable.h
+++ b/include/llvm/GlobalVariable.h
@@ -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.
diff --git a/include/llvm/Module.h b/include/llvm/Module.h
index ecc9c0b..8cd35f2 100644
--- a/include/llvm/Module.h
+++ b/include/llvm/Module.h
@@ -16,12 +16,12 @@
#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
diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index fc65e74..44c4453 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -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
diff --git a/include/llvm/ValueSymbolTable.h b/include/llvm/ValueSymbolTable.h
index 679fd86..8f007b9 100644
--- a/include/llvm/ValueSymbolTable.h
+++ b/include/llvm/ValueSymbolTable.h
@@ -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:
diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l
index d75d070..382ce24 100644
--- a/lib/AsmParser/Lexer.l
+++ b/lib/AsmParser/Lexer.l
@@ -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; }
diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y
index 2b08d3a..17ca06f 100644
--- a/lib/AsmParser/llvmAsmParser.y
+++ b/lib/AsmParser/llvmAsmParser.y
@@ -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
}
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index ee6d9e6..f7606c6 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -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.
//
diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp
index 12724dd..7295239 100644
--- a/lib/Bytecode/Writer/Writer.cpp
+++ b/lib/Bytecode/Writer/Writer.cpp
@@ -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) {
diff --git a/lib/CodeGen/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter.cpp
index 16c478d..90a98cb 100644
--- a/lib/CodeGen/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter.cpp
@@ -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;
}
diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp
index 8b0ad03..fd8af4f 100644
--- a/lib/Target/X86/X86TargetAsmInfo.cpp
+++ b/lib/Target/X86/X86TargetAsmInfo.cpp
@@ -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\"";
diff --git a/lib/Transforms/IPO/GlobalDCE.cpp b/lib/Transforms/IPO/GlobalDCE.cpp
index 7fd1102..560bcb5 100644
--- a/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/lib/Transforms/IPO/GlobalDCE.cpp
@@ -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
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 90f0198..ec9a553 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -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");
}
diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp
index 61d9de3..c64b719 100644
--- a/lib/VMCore/Globals.cpp
+++ b/lib/VMCore/Globals.cpp
@@ -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;
+}
+
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index ddd503d..c660323 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -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.
//
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 1936766..1578c2d 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -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
index 0000000..33d30db
--- /dev/null
+++ b/test/CodeGen/X86/aliases.ll
@@ -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
index 0000000..7a4aad0
--- /dev/null
+++ b/test/Feature/aliases.ll
@@ -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
+}