Hello Everyone. This is LLVM part of patch, which enable function aliases for LLVM. The syntax is pretty simple: it just "mimics" the "section" keyword. I'm currently working on gcc part of the patch. Please note, that patch breaks bytecode format (llvm-dev message will follow).
Documentation updates & testcases will be added just after this patch landed. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
diff -r 958b34c32d47 include/llvm/CodeGen/AsmPrinter.h --- a/include/llvm/CodeGen/AsmPrinter.h Tue Apr 17 21:09:00 2007 +0400 +++ b/include/llvm/CodeGen/AsmPrinter.h Thu Apr 19 03:17:46 2007 +0400 @@ -24,6 +24,7 @@ namespace llvm { class Constant; class ConstantArray; class GlobalVariable; + class FunctionAlias; class MachineConstantPoolEntry; class MachineConstantPoolValue; class Mangler; @@ -43,6 +44,8 @@ namespace llvm { protected: // Necessary for external weak linkage support std::set<const GlobalValue*> ExtWeakSymbols; + // Necessary for aliases support + std::set<const FunctionAlias*> FunctionAliases; public: /// Output stream on which we're printing assembly code. diff -r 958b34c32d47 include/llvm/Function.h --- a/include/llvm/Function.h Tue Apr 17 21:09:00 2007 +0400 +++ b/include/llvm/Function.h Thu Apr 19 01:09:49 2007 +0400 @@ -87,7 +87,8 @@ public: /// the module. /// Function(const FunctionType *Ty, LinkageTypes Linkage, - const std::string &N = "", Module *M = 0); + const std::string &N = "", Module *M = 0, + ValueTy vty = Value::FunctionVal); ~Function(); const Type *getReturnType() const; // Return the type of the ret val @@ -227,7 +228,8 @@ public: /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Function *) { return true; } static inline bool classof(const Value *V) { - return V->getValueID() == Value::FunctionVal; + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::FunctionAliasVal; } /// dropAllReferences() - This method causes all the subinstructions to "let @@ -254,6 +256,27 @@ public: } }; +class FunctionAlias : public Function { +private: + std::string Target; +public: + FunctionAlias(const FunctionType *Ty, LinkageTypes Linkage, + const std::string &name, const std::string &target, + Module *ParentModule = 0, + ValueTy vty = Value::FunctionAliasVal): + Function(Ty, Linkage, name, ParentModule, vty), Target(target) { }; + + std::string getTarget() const { return Target; } + void setTarget(const std::string &T) { Target = T; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FunctionAlias *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionAliasVal; + } + +}; + inline ValueSymbolTable * ilist_traits<BasicBlock>::getSymTab(Function *F) { return F ? &F->getValueSymbolTable() : 0; diff -r 958b34c32d47 include/llvm/GlobalValue.h --- a/include/llvm/GlobalValue.h Tue Apr 17 21:09:00 2007 +0400 +++ b/include/llvm/GlobalValue.h Thu Apr 19 01:08:54 2007 +0400 @@ -134,7 +134,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::FunctionAliasVal; } }; diff -r 958b34c32d47 include/llvm/Value.h --- a/include/llvm/Value.h Tue Apr 17 21:09:00 2007 +0400 +++ b/include/llvm/Value.h Thu Apr 19 00:34:57 2007 +0400 @@ -29,6 +29,7 @@ class BasicBlock; class BasicBlock; class GlobalValue; class Function; +class FunctionAlias; class GlobalVariable; class InlineAsm; class ValueSymbolTable; @@ -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 + FunctionAliasVal, // This is an instance of FunctionAlias GlobalVariableVal, // This is an instance of GlobalVariable UndefValueVal, // This is an instance of UndefValue ConstantExprVal, // This is an instance of ConstantExpr @@ -248,8 +250,12 @@ template <> inline bool isa_impl<GlobalV template <> inline bool isa_impl<GlobalVariable, Value>(const Value &Val) { return Val.getValueID() == Value::GlobalVariableVal; } +template <> inline bool isa_impl<FunctionAlias, Value>(const Value &Val) { + return Val.getValueID() == Value::FunctionAliasVal; +} 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<FunctionAlias>(Val); } } // End llvm namespace diff -r 958b34c32d47 lib/AsmParser/Lexer.l --- a/lib/AsmParser/Lexer.l Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/AsmParser/Lexer.l Wed Apr 18 12:23:11 2007 +0400 @@ -222,6 +222,7 @@ volatile { return VOLATILE; } volatile { return VOLATILE; } align { return ALIGN; } section { return SECTION; } +alias { return ALIAS; } module { return MODULE; } asm { return ASM_TOK; } sideeffect { return SIDEEFFECT; } diff -r 958b34c32d47 lib/AsmParser/llvmAsmParser.y --- a/lib/AsmParser/llvmAsmParser.y Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/AsmParser/llvmAsmParser.y Thu Apr 19 01:10:20 2007 +0400 @@ -1038,6 +1038,7 @@ Module *llvm::RunVMAsmParser(const char %type <StrVal> GlobalName OptGlobalAssign %type <UIntVal> OptAlign OptCAlign %type <StrVal> OptSection SectionString +%type <StrVal> OptAlias AliasTargetString %token ZEROINITIALIZER TRUETOK FALSETOK BEGINTOK ENDTOK %token DECLARE DEFINE GLOBAL CONSTANT SECTION VOLATILE THREAD_LOCAL @@ -1046,7 +1047,7 @@ Module *llvm::RunVMAsmParser(const char %token OPAQUE EXTERNAL TARGET TRIPLE ALIGN %token DEPLIBS CALL TAIL ASM_TOK MODULE SIDEEFFECT %token CC_TOK CCC_TOK FASTCC_TOK COLDCC_TOK X86_STDCALLCC_TOK X86_FASTCALLCC_TOK -%token DATALAYOUT +%token DATALAYOUT ALIAS %type <UIntVal> OptCallingConv %type <ParamAttrs> OptParamAttrs ParamAttr %type <ParamAttrs> OptFuncAttrs FuncAttr @@ -1243,6 +1244,17 @@ OptSection : /*empty*/ { $$ = 0; } | OptSection : /*empty*/ { $$ = 0; } | SectionString { $$ = $1; }; +AliasTargetString : ALIAS STRINGCONSTANT { + for (unsigned i = 0, e = strlen($2); i != e; ++i) + if ($2[i] == '"' || $2[i] == '\\') + GEN_ERROR("Invalid character in alias name"); + $$ = $2; + CHECK_FOR_ERROR +}; + +OptAlias : /*empty*/ { $$ = 0; } | + AliasTargetString { $$ = $1; }; + // GlobalVarAttributes - Used to pass the attributes string on a global. CurGV // is set to be the global we are processing. // @@ -2124,7 +2136,7 @@ ArgList : ArgListH { }; FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' - OptFuncAttrs OptSection OptAlign { + OptFuncAttrs OptSection OptAlign OptAlias { UnEscapeLexed($3); std::string FunctionName($3); free($3); // Free strdup'd memory! @@ -2133,7 +2145,14 @@ FunctionHeaderH : OptCallingConv ResultT // have no abstract types at this point if (!CurFun.isDeclare && CurModule.TypeIsUnresolved($2)) GEN_ERROR("Reference to abstract result: "+ $2->get()->getDescription()); - + // Check for alias set. We should allow this only on declarations. + if (!CurFun.isDeclare && $10) { + std::string Message("Alias illegally set on function definition " + "(allowed only on declarations): "); + Message += $10; + GEN_ERROR(Message); + } + std::vector<const Type*> ParamTypeList; ParamAttrsList ParamAttrs; if ($7 != ParamAttr::None) @@ -2184,20 +2203,31 @@ FunctionHeaderH : OptCallingConv ResultT // The existing function doesn't have the same type. This is an overload // error. GEN_ERROR("Overload of function '" + FunctionName + "' not permitted."); - } else if (!CurFun.isDeclare && !Fn->isDeclaration()) { - // Neither the existing or the current function is a declaration and they - // have the same name and same type. Clearly this is a redefinition. - GEN_ERROR("Redefinition of function '" + FunctionName + "'"); - } if (Fn->isDeclaration()) { + } else if (!Fn->isDeclaration()) { + if (CurFun.isDeclare) { + if ($10) + GEN_ERROR("Alias-redefinition of function '" + FunctionName + "'"); + } else { + // Neither the existing or the current function is a declaration and they + // have the same name and same type. Clearly this is a redefinition. + GEN_ERROR("Redefinition of function '" + FunctionName + "'"); + } + } + if (Fn->isDeclaration()) { // Make sure to strip off any argument names so we can't get conflicts. for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end(); AI != AE; ++AI) AI->setName(""); } - } else { // Not already defined? - Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName, - CurModule.CurrentModule); - + } else { // Not already defined? + if ($10) { + Fn = new FunctionAlias(FT, GlobalValue::ExternalLinkage, FunctionName, + $10, CurModule.CurrentModule); + free($10); + } else + Fn = new Function(FT, GlobalValue::ExternalLinkage, FunctionName, + CurModule.CurrentModule); + InsertValue(Fn, CurModule.Values); } @@ -2266,7 +2296,7 @@ FunctionProto : FunctionDeclareLinkage G $$ = CurFun.CurrentFunction; CurFun.FunctionDone(); CHECK_FOR_ERROR - }; +}; //===----------------------------------------------------------------------===// // Rules to match Basic Blocks diff -r 958b34c32d47 lib/Bytecode/Reader/Reader.cpp --- a/lib/Bytecode/Reader/Reader.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/Bytecode/Reader/Reader.cpp Thu Apr 19 02:19:34 2007 +0400 @@ -1699,7 +1699,11 @@ void BytecodeReader::ParseModuleGlobalIn // SectionID - If a global has an explicit section specified, this map // remembers the ID until we can translate it into a string. std::map<GlobalValue*, unsigned> SectionID; - + + // AliasID - If a global has an explicit alias target specified, this map + // remembers the ID until we can translate it into a string. + std::map<GlobalValue*, unsigned> AliasID; + // Read global variables... unsigned VarType = read_vbr_uint(); while (VarType != Type::VoidTyID) { // List is terminated by Void @@ -1799,15 +1803,28 @@ void BytecodeReader::ParseModuleGlobalIn error("Function not a pointer to function type! Ty = " + Ty->getDescription()); } - + // Check for extension word early in order to distinguish functions and + // function aliases + unsigned ExtWord = 0; + bool hasExtWord = FnSignature & (1 << 31); // Has extension word? + bool isAlias = false; + if (hasExtWord) { + ExtWord = read_vbr_uint(); + isAlias = ((ExtWord >> 13) & 1); + } + // We create functions by passing the underlying FunctionType to create... const FunctionType* FTy = cast<FunctionType>(cast<PointerType>(Ty)->getElementType()); // Insert the place holder. - Function *Func = new Function(FTy, GlobalValue::ExternalLinkage, - "", TheModule); - + Function *Func; + if (!isAlias) + Func = new Function(FTy, GlobalValue::ExternalLinkage, "", TheModule); + else + Func = new FunctionAlias(FTy, GlobalValue::ExternalLinkage, "", "", + TheModule); + insertValue(Func, (FnSignature & (~0U >> 1)) >> 5, ModuleValues); // Flags are not used yet. @@ -1822,14 +1839,16 @@ void BytecodeReader::ParseModuleGlobalIn // Get the calling convention from the low bits. unsigned CC = Flags & 15; unsigned Alignment = 0; - if (FnSignature & (1 << 31)) { // Has extension word? - unsigned ExtWord = read_vbr_uint(); + if (hasExtWord) { // Has extension word? Alignment = (1 << (ExtWord & 31)) >> 1; CC |= ((ExtWord >> 5) & 15) << 4; if (ExtWord & (1 << 10)) // Has a section ID. SectionID[Func] = read_vbr_uint(); + if (isAlias) + AliasID[Func] = read_vbr_uint(); + // Parse external declaration linkage switch ((ExtWord >> 11) & 3) { case 0: break; @@ -1856,7 +1875,12 @@ void BytecodeReader::ParseModuleGlobalIn /// moduleinfoblock. Functions and globals with an explicit section index /// into this to get their section name. std::vector<std::string> SectionNames; - + + /// AliasesNames - This contains the list of alias targets encoded in the + /// moduleinfoblock. Functions with an explicit alias index into this to get + /// their alias target. + std::vector<std::string> AliasesNames; + // Read in the dependent library information. unsigned num_dep_libs = read_vbr_uint(); std::string dep_lib; @@ -1886,7 +1910,14 @@ void BytecodeReader::ParseModuleGlobalIn while (NumSections--) SectionNames.push_back(read_str()); } - + + if (At != BlockEnd) { + // If the file has aliases info in it, read the aliases now. + unsigned NumAliases = read_vbr_uint(); + while (NumAliases--) + AliasesNames.push_back(read_str()); + } + // If the file has module-level inline asm, read it now. if (At != BlockEnd) TheModule->setModuleInlineAsm(read_str()); @@ -1898,6 +1929,15 @@ void BytecodeReader::ParseModuleGlobalIn if (I->second > SectionID.size()) error("SectionID out of range for global!"); I->first->setSection(SectionNames[I->second-1]); + } + + // If any globals are in specified alias targets, assign them now. + for (std::map<GlobalValue*, unsigned>::iterator I = AliasID.begin(), E = + AliasID.end(); I != E; ++I) + if (I->second) { + if (I->second > AliasID.size()) + error("SectionID out of range for global!"); + cast<FunctionAlias>(I->first)->setTarget(AliasesNames[I->second-1]); } // This is for future proofing... in the future extra fields may be added that diff -r 958b34c32d47 lib/Bytecode/Writer/Writer.cpp --- a/lib/Bytecode/Writer/Writer.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/Bytecode/Writer/Writer.cpp Thu Apr 19 03:46:56 2007 +0400 @@ -941,6 +941,11 @@ void BytecodeWriter::outputModuleInfoBlo std::vector<std::string> SectionNames; std::map<std::string, unsigned> SectionID; + // Give numbers to aliases as we encounter them. + unsigned AliasIDCounter = 0; + std::vector<std::string> AliasesNames; + std::map<std::string, unsigned> AliasID; + // Output the types for the global variables in the module... for (Module::const_global_iterator I = M->global_begin(), End = M->global_end(); I != End; ++I) { @@ -1004,9 +1009,9 @@ void BytecodeWriter::outputModuleInfoBlo ID |= 1 << 4; if (I->getAlignment() || I->hasSection() || (CC & ~15) != 0 || + isa<FunctionAlias>(I) || (I->isDeclaration() && I->hasDLLImportLinkage()) || - (I->isDeclaration() && I->hasExternalWeakLinkage()) - ) + (I->isDeclaration() && I->hasExternalWeakLinkage())) ID |= 1 << 31; // Do we need an extension word? output_vbr(ID); @@ -1025,8 +1030,9 @@ void BytecodeWriter::outputModuleInfoBlo } ID = (Log2_32(I->getAlignment())+1) | ((CC >> 4) << 5) | - (I->hasSection() << 10) | - ((extLinkage & 3) << 11); + (I->hasSection() << 10) | + ((extLinkage & 3) << 11) | + (isa<FunctionAlias>(I) << 13); output_vbr(ID); // Give section names unique ID's. @@ -1038,6 +1044,17 @@ void BytecodeWriter::outputModuleInfoBlo } output_vbr(Entry); } + + // Give section names unique ID's. + if (const FunctionAlias *FA = dyn_cast<FunctionAlias>(I)) { + unsigned &Entry = AliasID[FA->getTarget()]; + if (Entry == 0) { + Entry = ++AliasIDCounter; + AliasesNames.push_back(FA->getTarget()); + } + output_vbr(Entry); + } + } } output_vbr(Table.getTypeSlot(Type::VoidTy) << 5); @@ -1059,7 +1076,12 @@ void BytecodeWriter::outputModuleInfoBlo output_vbr((unsigned)SectionNames.size()); for (unsigned i = 0, e = SectionNames.size(); i != e; ++i) output(SectionNames[i]); - + + // Emit the table of aliases names. + output_vbr((unsigned)AliasesNames.size()); + for (unsigned i = 0, e = AliasesNames.size(); i != e; ++i) + output(AliasesNames[i]); + // Output the inline asm string. output(M->getModuleInlineAsm()); } diff -r 958b34c32d47 lib/CodeGen/AsmPrinter.cpp --- a/lib/CodeGen/AsmPrinter.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/CodeGen/AsmPrinter.cpp Thu Apr 19 03:31:27 2007 +0400 @@ -114,6 +114,7 @@ bool AsmPrinter::doFinalization(Module & if (ExtWeakSymbols.begin() != ExtWeakSymbols.end()) SwitchToDataSection(""); + O << "\n"; for (std::set<const GlobalValue*>::iterator i = ExtWeakSymbols.begin(), e = ExtWeakSymbols.end(); i != e; ++i) { const GlobalValue *GV = *i; @@ -122,6 +123,25 @@ bool AsmPrinter::doFinalization(Module & } } + if (TAI->getSetDirective()) { + if (FunctionAliases.begin() != FunctionAliases.end()) + SwitchToDataSection(""); + + O << "\n"; + for (std::set<const FunctionAlias*>::iterator I = FunctionAliases.begin(), + E = FunctionAliases.end(); I != E; ++I) { + const FunctionAlias *FA = *I; + std::string Name = Mang->getValueName(FA); + std::string Target = Mang->makeNameProper(FA->getTarget(), ""); + + // Aliases with external weak linkage was emitted already + if (FA->hasExternalLinkage()) + O << "\t.globl\t" << Name << "\n"; + + O << TAI->getSetDirective() << Name << ", " << Target << "\n"; + } + } + delete Mang; Mang = 0; return false; } diff -r 958b34c32d47 lib/Linker/LinkModules.cpp --- a/lib/Linker/LinkModules.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/Linker/LinkModules.cpp Thu Apr 19 03:43:04 2007 +0400 @@ -376,6 +376,14 @@ static bool GetLinkageResult(GlobalValue LinkFromSrc = true; LT = Src->getLinkage(); } else if (Src->isDeclaration()) { + // We can link aliases only if they go to the same target + FunctionAlias* SA = dyn_cast<FunctionAlias>(Src); + if (SA) { + FunctionAlias* DA = dyn_cast<FunctionAlias>(Dest); + if (!DA || (DA->getTarget() != SA->getTarget())) + return Error(Err, "Linking globals named '" + Src->getName() + + "': can only link aliases with the same target!"); + } // If Src is external or if both Src & Drc are external.. Just link the // external globals, we aren't adding anything. if (Src->hasDLLImportLinkage()) { diff -r 958b34c32d47 lib/Target/X86/X86ATTAsmPrinter.cpp --- a/lib/Target/X86/X86ATTAsmPrinter.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp Thu Apr 19 03:30:02 2007 +0400 @@ -321,6 +321,11 @@ void X86ATTAsmPrinter::printOperand(cons if (GV->hasExternalWeakLinkage()) ExtWeakSymbols.insert(GV); + + const FunctionAlias *FA = dyn_cast<FunctionAlias>(GV); + // Handle aliases + if (FA && GV->isDeclaration()) + FunctionAliases.insert(FA); int Offset = MO.getOffset(); if (Offset > 0) diff -r 958b34c32d47 lib/Target/X86/X86TargetAsmInfo.cpp --- a/lib/Target/X86/X86TargetAsmInfo.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/Target/X86/X86TargetAsmInfo.cpp Thu Apr 19 03:27:29 2007 +0400 @@ -108,6 +108,7 @@ X86TargetAsmInfo::X86TargetAsmInfo(const 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 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 -r 958b34c32d47 lib/VMCore/AsmWriter.cpp --- a/lib/VMCore/AsmWriter.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/VMCore/AsmWriter.cpp Thu Apr 19 02:23:20 2007 +0400 @@ -993,6 +993,8 @@ void AssemblyWriter::printFunction(const Out << " align " << F->getAlignment(); if (F->isDeclaration()) { + if (const FunctionAlias *FA = dyn_cast<FunctionAlias>(F)) + Out << " alias \"" << FA->getTarget() << '"'; Out << "\n"; } else { Out << " {"; diff -r 958b34c32d47 lib/VMCore/Function.cpp --- a/lib/VMCore/Function.cpp Tue Apr 17 21:09:00 2007 +0400 +++ b/lib/VMCore/Function.cpp Thu Apr 19 01:15:56 2007 +0400 @@ -139,8 +139,8 @@ ParamAttrsList::removeAttributes(uint16_ //===----------------------------------------------------------------------===// Function::Function(const FunctionType *Ty, LinkageTypes Linkage, - const std::string &name, Module *ParentModule) - : GlobalValue(PointerType::get(Ty), Value::FunctionVal, 0, 0, Linkage, name) { + const std::string &name, Module *ParentModule, ValueTy vty) + : GlobalValue(PointerType::get(Ty), vty, 0, 0, Linkage, name) { ParamAttrs = 0; SymTab = new ValueSymbolTable();
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits