From 38f68c5a2e3993a3ae51421d82e57ccca8f6ec38 Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Tue, 14 Jan 2014 15:22:47 +0000 Subject: Decouple dllexport/dllimport from linkage Representing dllexport/dllimport as distinct linkage types prevents using these attributes on templates and inline functions. Instead of introducing further mixed linkage types to include linkonce and weak ODR, the old import/export linkage types are replaced with a new separate visibility-like specifier: define available_externally dllimport void @f() {} @Var = dllexport global i32 1, align 4 Linkage for dllexported globals and functions is now equal to their linkage without dllexport. Imported globals and functions must be either declarations with external linkage, or definitions with AvailableExternallyLinkage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199218 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AsmParser/LLParser.cpp | 93 ++++++++++++++++++++++++++++------------------ lib/AsmParser/LLParser.h | 7 +++- 2 files changed, 62 insertions(+), 38 deletions(-) (limited to 'lib/AsmParser') diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index a5b2aa586e..d4d6f7cee1 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -242,8 +242,8 @@ bool LLParser::ParseTopLevelEntities() { // The Global variable production with no name can have many different // optional leading prefixes, the production is: - // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalThreadLocal - // OptionalAddrSpace OptionalUnNammedAddr + // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass + // OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr // ('constant'|'global') ... case lltok::kw_private: // OptionalLinkage case lltok::kw_linker_private: // OptionalLinkage @@ -254,24 +254,24 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_linkonce: // OptionalLinkage case lltok::kw_linkonce_odr: // OptionalLinkage case lltok::kw_appending: // OptionalLinkage - case lltok::kw_dllexport: // OptionalLinkage case lltok::kw_common: // OptionalLinkage - case lltok::kw_dllimport: // OptionalLinkage case lltok::kw_extern_weak: // OptionalLinkage case lltok::kw_external: { // OptionalLinkage - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseOptionalLinkage(Linkage) || ParseOptionalVisibility(Visibility) || - ParseGlobal("", SMLoc(), Linkage, true, Visibility)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseGlobal("", SMLoc(), Linkage, true, Visibility, DLLStorageClass)) return true; break; } case lltok::kw_default: // OptionalVisibility case lltok::kw_hidden: // OptionalVisibility case lltok::kw_protected: { // OptionalVisibility - unsigned Visibility; + unsigned Visibility, DLLStorageClass; if (ParseOptionalVisibility(Visibility) || - ParseGlobal("", SMLoc(), 0, false, Visibility)) + ParseOptionalDLLStorageClass(DLLStorageClass) || + ParseGlobal("", SMLoc(), 0, false, Visibility, DLLStorageClass)) return true; break; } @@ -280,7 +280,7 @@ bool LLParser::ParseTopLevelEntities() { case lltok::kw_addrspace: // OptionalAddrSpace case lltok::kw_constant: // GlobalType case lltok::kw_global: // GlobalType - if (ParseGlobal("", SMLoc(), 0, false, 0)) return true; + if (ParseGlobal("", SMLoc(), 0, false, 0, 0)) return true; break; case lltok::kw_attributes: if (ParseUnnamedAttrGrp()) return true; break; @@ -446,9 +446,11 @@ bool LLParser::ParseGlobalType(bool &IsConstant) { /// ParseUnnamedGlobal: /// OptionalVisibility ALIAS ... -/// OptionalLinkage OptionalVisibility ... -> global variable +/// OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable /// GlobalID '=' OptionalVisibility ALIAS ... -/// GlobalID '=' OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalID '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable bool LLParser::ParseUnnamedGlobal() { unsigned VarID = NumberedVals.size(); std::string Name; @@ -466,19 +468,22 @@ bool LLParser::ParseUnnamedGlobal() { } bool HasLinkage; - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseOptionalLinkage(Linkage, HasLinkage) || - ParseOptionalVisibility(Visibility)) + ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) - return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); - return ParseAlias(Name, NameLoc, Visibility); + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, + DLLStorageClass); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); } /// ParseNamedGlobal: /// GlobalVar '=' OptionalVisibility ALIAS ... -/// GlobalVar '=' OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable bool LLParser::ParseNamedGlobal() { assert(Lex.getKind() == lltok::GlobalVar); LocTy NameLoc = Lex.getLoc(); @@ -486,15 +491,17 @@ bool LLParser::ParseNamedGlobal() { Lex.Lex(); bool HasLinkage; - unsigned Linkage, Visibility; + unsigned Linkage, Visibility, DLLStorageClass; if (ParseToken(lltok::equal, "expected '=' in global variable") || ParseOptionalLinkage(Linkage, HasLinkage) || - ParseOptionalVisibility(Visibility)) + ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass)) return true; if (HasLinkage || Lex.getKind() != lltok::kw_alias) - return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); - return ParseAlias(Name, NameLoc, Visibility); + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, + DLLStorageClass); + return ParseAlias(Name, NameLoc, Visibility, DLLStorageClass); } // MDString: @@ -615,16 +622,17 @@ bool LLParser::ParseStandaloneMetadata() { } /// ParseAlias: -/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee +/// ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass 'alias' +/// OptionalLinkage Aliasee /// Aliasee /// ::= TypeAndValue /// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' /// ::= 'getelementptr' 'inbounds'? '(' ... ')' /// -/// Everything through visibility has already been parsed. +/// Everything through DLL storage class has already been parsed. /// bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, - unsigned Visibility) { + unsigned Visibility, unsigned DLLStorageClass) { assert(Lex.getKind() == lltok::kw_alias); Lex.Lex(); LocTy LinkageLoc = Lex.getLoc(); @@ -659,6 +667,7 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); // See if this value already exists in the symbol table. If so, it is either // a redefinition or a definition of a forward reference. @@ -691,18 +700,18 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, } /// ParseGlobal -/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr +/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr /// OptionalExternallyInitialized GlobalType Type Const -/// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal -/// OptionalAddrSpace OptionalUnNammedAddr +/// ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalAddrSpace OptionalUnNammedAddr /// OptionalExternallyInitialized GlobalType Type Const /// /// Everything through visibility has been parsed already. /// bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, bool HasLinkage, - unsigned Visibility) { + unsigned Visibility, unsigned DLLStorageClass) { unsigned AddrSpace; bool IsConstant, UnnamedAddr, IsExternallyInitialized; GlobalVariable::ThreadLocalMode TLM; @@ -725,8 +734,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, // If the linkage is specified and is external, then no initializer is // present. Constant *Init = 0; - if (!HasLinkage || (Linkage != GlobalValue::DLLImportLinkage && - Linkage != GlobalValue::ExternalWeakLinkage && + if (!HasLinkage || (Linkage != GlobalValue::ExternalWeakLinkage && Linkage != GlobalValue::ExternalLinkage)) { if (ParseGlobalValue(Ty, Init)) return true; @@ -775,6 +783,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, GV->setConstant(IsConstant); GV->setLinkage((GlobalValue::LinkageTypes)Linkage); GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); GV->setExternallyInitialized(IsExternallyInitialized); GV->setThreadLocalMode(TLM); GV->setUnnamedAddr(UnnamedAddr); @@ -1277,9 +1286,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { /// ::= 'linkonce_odr' /// ::= 'available_externally' /// ::= 'appending' -/// ::= 'dllexport' /// ::= 'common' -/// ::= 'dllimport' /// ::= 'extern_weak' /// ::= 'external' bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { @@ -1300,9 +1307,7 @@ bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { Res = GlobalValue::AvailableExternallyLinkage; break; case lltok::kw_appending: Res = GlobalValue::AppendingLinkage; break; - case lltok::kw_dllexport: Res = GlobalValue::DLLExportLinkage; break; case lltok::kw_common: Res = GlobalValue::CommonLinkage; break; - case lltok::kw_dllimport: Res = GlobalValue::DLLImportLinkage; break; case lltok::kw_extern_weak: Res = GlobalValue::ExternalWeakLinkage; break; case lltok::kw_external: Res = GlobalValue::ExternalLinkage; break; } @@ -1328,6 +1333,21 @@ bool LLParser::ParseOptionalVisibility(unsigned &Res) { return false; } +/// ParseOptionalDLLStorageClass +/// ::= /*empty*/ +/// ::= 'dllimport' +/// ::= 'dllexport' +/// +bool LLParser::ParseOptionalDLLStorageClass(unsigned &Res) { + switch (Lex.getKind()) { + default: Res = GlobalValue::DefaultStorageClass; return false; + case lltok::kw_dllimport: Res = GlobalValue::DLLImportStorageClass; break; + case lltok::kw_dllexport: Res = GlobalValue::DLLExportStorageClass; break; + } + Lex.Lex(); + return false; +} + /// ParseOptionalCallingConv /// ::= /*empty*/ /// ::= 'ccc' @@ -2934,12 +2954,14 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { unsigned Linkage; unsigned Visibility; + unsigned DLLStorageClass; AttrBuilder RetAttrs; CallingConv::ID CC; Type *RetType = 0; LocTy RetTypeLoc = Lex.getLoc(); if (ParseOptionalLinkage(Linkage) || ParseOptionalVisibility(Visibility) || + ParseOptionalDLLStorageClass(DLLStorageClass) || ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) || ParseType(RetType, RetTypeLoc, true /*void allowed*/)) @@ -2949,7 +2971,6 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { switch ((GlobalValue::LinkageTypes)Linkage) { case GlobalValue::ExternalLinkage: break; // always ok. - case GlobalValue::DLLImportLinkage: case GlobalValue::ExternalWeakLinkage: if (isDefine) return Error(LinkageLoc, "invalid linkage for function definition"); @@ -2963,7 +2984,6 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: - case GlobalValue::DLLExportLinkage: if (!isDefine) return Error(LinkageLoc, "invalid linkage for function declaration"); break; @@ -3110,6 +3130,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); + Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); Fn->setCallingConv(CC); Fn->setAttributes(PAL); Fn->setUnnamedAddr(UnnamedAddr); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index ded776c398..c62979e6f2 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -204,6 +204,7 @@ namespace llvm { bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage); } bool ParseOptionalVisibility(unsigned &Visibility); + bool ParseOptionalDLLStorageClass(unsigned &DLLStorageClass); bool ParseOptionalCallingConv(CallingConv::ID &CC); bool ParseOptionalAlignment(unsigned &Alignment); bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, @@ -234,8 +235,10 @@ namespace llvm { bool ParseUnnamedGlobal(); bool ParseNamedGlobal(); bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, - bool HasLinkage, unsigned Visibility); - bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); + bool HasLinkage, unsigned Visibility, + unsigned DLLStorageClass); + bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility, + unsigned DLLStorageClass); bool ParseStandaloneMetadata(); bool ParseNamedMetadata(); bool ParseMDString(MDString *&Result); -- cgit v1.2.3