diff --git a/docs/BytecodeFormat.html b/docs/BytecodeFormat.html index 56fc0afce9c..396bf2f1249 100644 --- a/docs/BytecodeFormat.html +++ b/docs/BytecodeFormat.html @@ -943,11 +943,11 @@ all functions. The format is shown in the table below:

target triple specified, i.e. a platform-independent module). - string - 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). + string + 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). llist(string) @@ -959,6 +959,11 @@ all functions. The format is shown in the table below:

string The inline asm block for this module. + + zlist(alias) + A zero terminated list of aliases occurring in the + module. + @@ -1123,7 +1128,7 @@ href="#uint32_vbr">uint32_vbr that describes the function.

bit(5-30) Type slot number of type for the function. - + bit(31) Indicates whether an extension word follows. @@ -1185,6 +1190,56 @@ follows with the following fields:

+ +
Alias Field +
+
+

Aliases are written using 3 uint32_vbr +that encode information about alias itself and aliasee.

+ +

The table below provides the bit layout of +the first uint32_vbr which describes alias itself.

+ + + + + + + + + + + + + + + + +
TypeDescription
bit(0-1)Alias linkage. 0 - External linkage, 1 - Internal + linkage, 2 - Weak linkage.
bit(2-31)Type slot number of type for the alias itself.
+ +

The next two uint32_vbr's describes the + aliasee.

+ + + + + + + + + + + + + + + + +
TypeDescription
uint32_vbrType slot number of type for the aliasee.
uint32_vbrSlot number of the aliasee.
+ +
+
Constant Pool
diff --git a/docs/LangRef.html b/docs/LangRef.html index 2fb27f6384a..807d1047f61 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -498,7 +498,8 @@ outside of the current module.

It is illegal for a function declaration to have any linkage type other than "externally visible", dllimport, or extern_weak.

- +

Aliases can have only external, internal and weak +linkages.

@@ -602,12 +603,11 @@ All Global Variables and Functions have one of the following visibility styles:

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 never 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 never 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.

@@ -698,6 +698,27 @@ a power of 2.

+ + +
+ Aliases +
+
+

Aliases act as "second name" for the aliasee value (which can be either + function or global variable). Aliases may have an + optional linkage type, and an + optional visibility style.

+ +
Syntax:
+ +
+    @<Name> = [Linkage] [Visibility] alias <AliaseeTy> @<Aliasee>
+  
+ +
+ + +
Parameter Attributes
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e3ca8aa663e..024001e9d66 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 a50601d1bab..c0984f63678 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 a20c0580040..317aa486a40 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 00d4acb66da..303e57f99a5 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 ecc9c0b8e20..8cd35f25bec 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 namespace llvm { -class GlobalVariable; class GlobalValueRefMap; // Used by ConstantVals.cpp class FunctionType; @@ -43,6 +43,15 @@ template<> struct ilist_traits static inline ValueSymbolTable *getSymTab(Module *M); static int getListOffset(); }; +template<> struct ilist_traits + : public SymbolTableListTraits { + // 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 &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 GlobalListType; /// The type for the list of functions. typedef iplist FunctionListType; + /// The type for the list of aliases. + typedef iplist AliasListType; /// The type for the list of dependent libraries. typedef std::vector 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 @@ -293,6 +323,23 @@ public: /// @brief Get all the libraries 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 /// @{ @@ -324,6 +371,10 @@ public: Module *Obj = 0; return unsigned(reinterpret_cast(&Obj->GlobalList)); } + static unsigned getAliasListOffset() { + Module *Obj = 0; + return unsigned(reinterpret_cast(&Obj->AliasList)); + } }; /// An iostream inserter for modules. @@ -342,6 +393,11 @@ ilist_traits::getSymTab(Module *M) { return M ? &M->getValueSymbolTable() : 0; } +inline ValueSymbolTable * +ilist_traits::getSymTab(Module *M) { + return M ? &M->getValueSymbolTable() : 0; +} + inline int ilist_traits::getListOffset() { return Module::getFunctionListOffset(); @@ -352,6 +408,11 @@ ilist_traits::getListOffset() { return Module::getGlobalVariableListOffset(); } +inline int +ilist_traits::getListOffset() { + return Module::getAliasListOffset(); +} + } // End llvm namespace #endif diff --git a/include/llvm/Value.h b/include/llvm/Value.h index fc65e74c56e..44c4453b04a 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(const Value &Val) { template <> inline bool isa_impl(const Value &Val) { return Val.getValueID() == Value::GlobalVariableVal; } +template <> inline bool isa_impl(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; +} template <> inline bool isa_impl(const Value &Val) { - return isa(Val) || isa(Val); + return isa(Val) || isa(Val) || isa(Val); } } // End llvm namespace diff --git a/include/llvm/ValueSymbolTable.h b/include/llvm/ValueSymbolTable.h index 679fd8680e4..8f007b9559c 100644 --- a/include/llvm/ValueSymbolTable.h +++ b/include/llvm/ValueSymbolTable.h @@ -35,6 +35,7 @@ class ValueSymbolTable { friend class SymbolTableListTraits; friend class SymbolTableListTraits; friend class SymbolTableListTraits; + friend class SymbolTableListTraits; /// @name Types /// @{ public: diff --git a/lib/AsmParser/Lexer.l b/lib/AsmParser/Lexer.l index d75d07008b9..382ce24462a 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 2b08d3afa1b..17ca06f664c 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -1004,6 +1004,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %type OptSideEffect // 'sideeffect' or not. %type GVInternalLinkage GVExternalLinkage %type FunctionDefineLinkage FunctionDeclareLinkage +%type AliasLinkage %type GVVisibilityStyle // ValueRef - Unresolved reference to a definition or BB @@ -1035,12 +1036,12 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) { %token LOCALVAR GLOBALVAR LABELSTR STRINGCONSTANT ATSTRINGCONSTANT %type LocalName OptLocalName OptLocalAssign -%type GlobalName OptGlobalAssign +%type GlobalName OptGlobalAssign GlobalAssign %type OptAlign OptCAlign %type 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($5->get())) || + !(Ty = dyn_cast(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(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 ee6d9e6208c..f7606c6e5af 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(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(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(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 12724dd6bec..7295239fdd0 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 16c478dcdc1..90a98cb5a75 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::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 8b0ad03b0a0..fd8af4f69a7 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 7fd110208f7..560bcb56b0f 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(G)) { + // If this is a global alias we also need it's aliasee + GlobalIsNeeded(const_cast(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 90f0198b570..ec9a5539b9f 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(V)){ return new SlotMachine(GV->getParent()); + } else if (const GlobalAlias *GA = dyn_cast(V)){ + return new SlotMachine(GA->getParent()); } else if (const Function *Func = dyn_cast(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(Aliasee)) { + printType(GV->getType()); + Out << " " << getLLVMName(GV->getName(), GlobalPrefix); + } else if (const Function *F = dyn_cast(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(V) ? 'G' : 'F') << "]\n"); + // G = Global, F = Function, A = Alias, o = other + SC_DEBUG((isa(V) ? 'G' : + (isa ? 'F' : + (isa ? 'A' : 'o'))) << "]\n"); } diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp index 61d9de3a231..c64b719095d 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(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 ddd503dea1c..c66032388ba 100644 --- a/lib/VMCore/Module.cpp +++ b/lib/VMCore/Module.cpp @@ -45,6 +45,12 @@ GlobalVariable *ilist_traits::createSentinel() { LeakDetector::removeGarbageObject(Ret); return Ret; } +GlobalAlias *ilist_traits::createSentinel() { + GlobalAlias *Ret = new GlobalAlias(Type::Int32Ty, GlobalValue::ExternalLinkage); + // This should not be garbage monitored. + LeakDetector::removeGarbageObject(Ret); + return Ret; +} iplist &ilist_traits::getList(Module *M) { return M->getFunctionList(); @@ -52,11 +58,15 @@ iplist &ilist_traits::getList(Module *M) { iplist &ilist_traits::getList(Module *M) { return M->getGlobalList(); } +iplist &ilist_traits::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; template class SymbolTableListTraits; +template class SymbolTableListTraits; //===----------------------------------------------------------------------===// // Primitive Module methods. @@ -72,6 +82,7 @@ Module::~Module() { dropAllReferences(); GlobalList.clear(); FunctionList.clear(); + AliasList.clear(); LibraryList.clear(); delete ValSymTab; delete TypeSymTab; @@ -211,6 +222,18 @@ GlobalVariable *Module::getGlobalVariable(const std::string &Name, 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(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 19367662d22..1578c2ddd6d 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(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 00000000000..33d30db89f5 --- /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 00000000000..7a4aad03acb --- /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 +}