diff options
Diffstat (limited to 'lib/AsmParser')
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index e5813f0d21..b457672d77 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -630,10 +630,11 @@ static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { /// ParseAlias: /// ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass 'alias' /// OptionalLinkage Aliasee +/// ::= GlobalVar '=' OptionalVisibility OptionalDLLStorageClass 'alias' +/// OptionalLinkage OptionalAddrSpace Type, Aliasee +/// /// Aliasee /// ::= TypeAndValue -/// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' -/// ::= 'getelementptr' 'inbounds'? '(' ... ')' /// /// Everything through DLL storage class has already been parsed. /// @@ -655,28 +656,49 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, return Error(LinkageLoc, "symbol with local linkage must have default visibility"); - Constant *Aliasee; - LocTy AliaseeLoc = Lex.getLoc(); - if (Lex.getKind() != lltok::kw_bitcast && - Lex.getKind() != lltok::kw_getelementptr) { - if (ParseGlobalTypeAndValue(Aliasee)) return true; + bool HasAddrSpace = Lex.getKind() == lltok::kw_addrspace; + unsigned AddrSpace; + LocTy AddrSpaceLoc = Lex.getLoc(); + if (ParseOptionalAddrSpace(AddrSpace)) + return true; + + LocTy TyLoc = Lex.getLoc(); + Type *Ty = nullptr; + if (ParseType(Ty)) + return true; + + bool DifferentType = EatIfPresent(lltok::comma); + if (HasAddrSpace && !DifferentType) + return Error(AddrSpaceLoc, "A type is required if addrspace is given"); + + Type *AliaseeType = nullptr; + if (DifferentType) { + if (ParseType(AliaseeType)) + return true; } else { - // The bitcast dest type is not present, it is implied by the dest type. - ValID ID; - if (ParseValID(ID)) return true; - if (ID.Kind != ValID::t_Constant) - return Error(AliaseeLoc, "invalid aliasee"); - Aliasee = ID.ConstantVal; + AliaseeType = Ty; + auto *PTy = dyn_cast<PointerType>(Ty); + if (!PTy) + return Error(TyLoc, "An alias must have pointer type"); + Ty = PTy->getElementType(); + AddrSpace = PTy->getAddressSpace(); } - if (!Aliasee->getType()->isPointerTy()) - return Error(AliaseeLoc, "alias must have pointer type"); + LocTy AliaseeLoc = Lex.getLoc(); + Constant *C; + if (ParseGlobalValue(AliaseeType, C)) + return true; + + auto *Aliasee = dyn_cast<GlobalObject>(C); + if (!Aliasee) + return Error(AliaseeLoc, "Alias must point to function or variable"); + + assert(Aliasee->getType()->isPointerTy()); // Okay, create the alias but do not insert it into the module yet. - PointerType *PTy = cast<PointerType>(Aliasee->getType()); std::unique_ptr<GlobalAlias> GA( - new GlobalAlias(PTy->getElementType(), (GlobalValue::LinkageTypes)Linkage, - Name, Aliasee, nullptr, PTy->getAddressSpace())); + new GlobalAlias(Ty, (GlobalValue::LinkageTypes)Linkage, Name, Aliasee, + /*Parent*/ nullptr, AddrSpace)); GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); @@ -698,6 +720,11 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, // If they agree, just RAUW the old value with the alias and remove the // forward ref info. + for (auto *User : Val->users()) { + if (auto *GA = dyn_cast<GlobalAlias>(User)) + return Error(NameLoc, "Alias is pointed by alias " + GA->getName()); + } + Val->replaceAllUsesWith(GA.get()); Val->eraseFromParent(); ForwardRefVals.erase(I); |