diff options
41 files changed, 308 insertions, 156 deletions
diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index da228471c9..4059891b96 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -41,7 +41,7 @@ public: /// If a parent module is specified, the alias is automatically inserted into /// the end of the specified module's alias list. GlobalAlias(Type *Ty, LinkageTypes Linkage, const Twine &Name = "", - Constant* Aliasee = nullptr, Module *Parent = nullptr, + GlobalObject *Aliasee = nullptr, Module *Parent = nullptr, unsigned AddressSpace = 0); /// Provide fast operand accessors @@ -58,18 +58,19 @@ public: void eraseFromParent() override; /// set/getAliasee - These methods retrive and set alias target. - void setAliasee(Constant *GV); - const Constant *getAliasee() const { - return getOperand(0); + void setAliasee(GlobalObject *GO); + const GlobalObject *getAliasee() const { + return const_cast<GlobalAlias *>(this)->getAliasee(); } - Constant *getAliasee() { - return getOperand(0); + + GlobalObject *getAliasee() { + return cast_or_null<GlobalObject>(getOperand(0)); + } + + GlobalObject *getAliasedGlobal() { + return getAliasee(); } - /// This method tries to ultimately resolve the alias by going through the - /// aliasing chain and trying to find the very last global. Returns NULL if a - /// cycle was found. - GlobalObject *getAliasedGlobal(); const GlobalObject *getAliasedGlobal() const { return const_cast<GlobalAlias *>(this)->getAliasedGlobal(); } 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); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index ea33578502..14546c0fe4 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1092,6 +1092,28 @@ uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) { return 1ULL << 63; } +// FIXME: Delete this in LLVM 4.0 and just assert that the aliasee is a +// GlobalObject. +static GlobalObject & +getGlobalObjectInExpr(const DenseMap<GlobalAlias *, Constant *> &Map, + Constant &C) { + auto *GO = dyn_cast<GlobalObject>(&C); + if (GO) + return *GO; + + auto *GA = dyn_cast<GlobalAlias>(&C); + if (GA) + return getGlobalObjectInExpr(Map, *Map.find(GA)->second); + + auto &CE = cast<ConstantExpr>(C); + assert(CE.getOpcode() == Instruction::BitCast || + CE.getOpcode() == Instruction::GetElementPtr || + CE.getOpcode() == Instruction::AddrSpaceCast); + if (CE.getOpcode() == Instruction::GetElementPtr) + assert(cast<GEPOperator>(CE).hasAllZeroIndices()); + return getGlobalObjectInExpr(Map, *CE.getOperand(0)); +} + /// ResolveGlobalAndAliasInits - Resolve all of the initializers for global /// values and aliases that we can. error_code BitcodeReader::ResolveGlobalAndAliasInits() { @@ -1117,19 +1139,30 @@ error_code BitcodeReader::ResolveGlobalAndAliasInits() { GlobalInitWorklist.pop_back(); } + // FIXME: Delete this in LLVM 4.0 + // Older versions of llvm could write an alias pointing to another. We cannot + // construct those aliases, so we first collect an alias to aliasee expression + // and then compute the actual aliasee. + DenseMap<GlobalAlias *, Constant *> AliasInit; + while (!AliasInitWorklist.empty()) { unsigned ValID = AliasInitWorklist.back().second; if (ValID >= ValueList.size()) { AliasInits.push_back(AliasInitWorklist.back()); } else { if (Constant *C = dyn_cast_or_null<Constant>(ValueList[ValID])) - AliasInitWorklist.back().first->setAliasee(C); + AliasInit.insert(std::make_pair(AliasInitWorklist.back().first, C)); else return Error(ExpectedConstant); } AliasInitWorklist.pop_back(); } + for (auto &Pair : AliasInit) { + auto &GO = getGlobalObjectInExpr(AliasInit, *Pair.second); + Pair.first->setAliasee(&GO); + } + while (!FunctionPrefixWorklist.empty()) { unsigned ValID = FunctionPrefixWorklist.back().second; if (ValID >= ValueList.size()) { diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 3cbb1d1049..0fef0d0a18 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1493,10 +1493,16 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { PrintLinkage(GA->getLinkage(), Out); + PointerType *Ty = GA->getType(); const Constant *Aliasee = GA->getAliasee(); + if (!Aliasee || Ty != Aliasee->getType()) { + if (unsigned AddressSpace = Ty->getAddressSpace()) + Out << "addrspace(" << AddressSpace << ") "; + TypePrinter.print(Ty->getElementType(), Out); + Out << ", "; + } if (!Aliasee) { - TypePrinter.print(GA->getType(), Out); Out << " <<NULL ALIASEE>>"; } else { writeOperand(Aliasee, !isa<ConstantExpr>(Aliasee)); diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 40c1c70257..100c9def18 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -1491,7 +1491,7 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, auto *PTy = cast<PointerType>(unwrap(Ty)); return wrap(new GlobalAlias( PTy->getElementType(), GlobalValue::ExternalLinkage, Name, - unwrap<Constant>(Aliasee), unwrap(M), PTy->getAddressSpace())); + unwrap<GlobalObject>(Aliasee), unwrap(M), PTy->getAddressSpace())); } /*--.. Operations on functions .............................................--*/ diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 8e7478496f..d4fcf58e98 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -214,15 +214,11 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { //===----------------------------------------------------------------------===// GlobalAlias::GlobalAlias(Type *Ty, LinkageTypes Link, const Twine &Name, - Constant *Aliasee, Module *ParentModule, + GlobalObject *Aliasee, Module *ParentModule, unsigned AddressSpace) : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { LeakDetector::addGarbageObject(this); - - if (Aliasee) - assert(Aliasee->getType() == getType() && - "Alias and aliasee types should match!"); Op<0>() = Aliasee; if (ParentModule) @@ -245,42 +241,4 @@ void GlobalAlias::eraseFromParent() { getParent()->getAliasList().erase(this); } -void GlobalAlias::setAliasee(Constant *Aliasee) { - assert((!Aliasee || Aliasee->getType() == getType()) && - "Alias and aliasee types should match!"); - - setOperand(0, Aliasee); -} - -static GlobalValue *getAliaseeGV(GlobalAlias *GA) { - Constant *C = GA->getAliasee(); - assert(C && "Must alias something"); - - if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) - return GV; - - ConstantExpr *CE = cast<ConstantExpr>(C); - assert((CE->getOpcode() == Instruction::BitCast || - CE->getOpcode() == Instruction::AddrSpaceCast || - CE->getOpcode() == Instruction::GetElementPtr) && - "Unsupported aliasee"); - - return cast<GlobalValue>(CE->getOperand(0)); -} - -GlobalObject *GlobalAlias::getAliasedGlobal() { - SmallPtrSet<GlobalValue*, 3> Visited; - - GlobalAlias *GA = this; - - for (;;) { - GlobalValue *GV = getAliaseeGV(GA); - if (!Visited.insert(GV)) - return nullptr; - - // Iterate over aliasing chain. - GA = dyn_cast<GlobalAlias>(GV); - if (!GA) - return cast<GlobalObject>(GV); - } -} +void GlobalAlias::setAliasee(GlobalObject *Aliasee) { setOperand(0, Aliasee); } diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 9a79e43359..a3c0286200 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -301,6 +301,28 @@ void Value::takeName(Value *V) { ST->reinsertValue(this); } +static GlobalObject &findReplacementForAliasUse(Value &C) { + if (auto *GO = dyn_cast<GlobalObject>(&C)) + return *GO; + if (auto *GA = dyn_cast<GlobalAlias>(&C)) + return *GA->getAliasee(); + auto *CE = cast<ConstantExpr>(&C); + assert(CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr || + CE->getOpcode() == Instruction::AddrSpaceCast); + if (CE->getOpcode() == Instruction::GetElementPtr) + assert(cast<GEPOperator>(CE)->hasAllZeroIndices()); + return findReplacementForAliasUse(*CE->getOperand(0)); +} + +static void replaceAliasUseWith(Use &U, Value *New) { + GlobalObject &Replacement = findReplacementForAliasUse(*New); + auto *Old = &cast<GlobalObject>(*U); + assert(Old != &Replacement && + "replaceAliasUseWith cannot form an alias cycle"); + U.set(&Replacement); +} + #ifndef NDEBUG static bool contains(SmallPtrSet<ConstantExpr *, 4> &Cache, ConstantExpr *Expr, Constant *C) { @@ -351,7 +373,11 @@ void Value::replaceAllUsesWith(Value *New) { Use &U = *UseList; // Must handle Constants specially, we cannot call replaceUsesOfWith on a // constant because they are uniqued. - if (Constant *C = dyn_cast<Constant>(U.getUser())) { + if (auto *C = dyn_cast<Constant>(U.getUser())) { + if (isa<GlobalAlias>(C)) { + replaceAliasUseWith(U, New); + continue; + } if (!isa<GlobalValue>(C)) { C->replaceUsesOfWithOnConstant(this, New, &U); continue; diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index ff9ca44f87..6ab5e58c4c 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -473,8 +473,6 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { "Alias should have external or external weak linkage!", &GA); Assert1(GA.getAliasee(), "Aliasee cannot be NULL!", &GA); - Assert1(GA.getType() == GA.getAliasee()->getType(), - "Alias and aliasee types should match!", &GA); Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); const Constant *Aliasee = GA.getAliasee(); @@ -506,10 +504,6 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { &GA); } - const GlobalValue *AG = GA.getAliasedGlobal(); - Assert1(AG, "Aliasing chain should end with function or global variable", - &GA); - visitGlobalValue(GA); } diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 0507c5acc9..cf49d3fd55 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -389,6 +389,8 @@ namespace { /// actually need, but this allows us to reuse the ValueMapper code. ValueToValueMapTy ValueMap; + std::vector<std::pair<GlobalValue *, GlobalAlias *>> ReplaceWithAlias; + struct AppendingVarInfo { GlobalVariable *NewGV; // New aggregate global in dest module. Constant *DstInit; // Old initializer from dest module. @@ -920,18 +922,15 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) { // If there is no linkage to be performed or we're linking from the source, // bring over SGA. auto *PTy = cast<PointerType>(TypeMap.get(SGA->getType())); - GlobalAlias *NewDA = + auto *NewDA = new GlobalAlias(PTy->getElementType(), SGA->getLinkage(), SGA->getName(), /*aliasee*/ nullptr, DstM, PTy->getAddressSpace()); copyGVAttributes(NewDA, SGA); if (NewVisibility) NewDA->setVisibility(*NewVisibility); - if (DGV) { - // Any uses of DGV need to change to NewDA, with cast. - DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDA, DGV->getType())); - DGV->eraseFromParent(); - } + if (DGV) + ReplaceWithAlias.push_back(std::make_pair(DGV, NewDA)); ValueMap[SGA] = NewDA; return false; @@ -1017,6 +1016,19 @@ void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) { } +static GlobalObject &getGlobalObjectInExpr(Constant &C) { + auto *GO = dyn_cast<GlobalObject>(&C); + if (GO) + return *GO; + auto *GA = dyn_cast<GlobalAlias>(&C); + if (GA) + return *GA->getAliasee(); + auto &CE = cast<ConstantExpr>(C); + assert(CE.getOpcode() == Instruction::BitCast || + CE.getOpcode() == Instruction::AddrSpaceCast); + return getGlobalObjectInExpr(*CE.getOperand(0)); +} + /// linkAliasBodies - Insert all of the aliases in Src into the Dest module. void ModuleLinker::linkAliasBodies() { for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end(); @@ -1025,10 +1037,27 @@ void ModuleLinker::linkAliasBodies() { continue; if (Constant *Aliasee = I->getAliasee()) { GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]); - DA->setAliasee(MapValue(Aliasee, ValueMap, RF_None, - &TypeMap, &ValMaterializer)); + Constant *Val = + MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer); + DA->setAliasee(&getGlobalObjectInExpr(*Val)); } } + + // Any uses of DGV need to change to NewDA, with cast. + for (auto &Pair : ReplaceWithAlias) { + GlobalValue *DGV = Pair.first; + GlobalAlias *NewDA = Pair.second; + + for (auto *User : DGV->users()) { + if (auto *GA = dyn_cast<GlobalAlias>(User)) { + if (GA == NewDA) + report_fatal_error("Linking these modules creates an alias cycle."); + } + } + + DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDA, DGV->getType())); + DGV->eraseFromParent(); + } } /// linkNamedMDNodes - Insert all of the named MDNodes in Src into the Dest diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index a8471bacb4..ae80c43764 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -2861,7 +2861,7 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) { if (!hasUsesToReplace(*J, Used, RenameTarget)) continue; - J->replaceAllUsesWith(Aliasee); + J->replaceAllUsesWith(ConstantExpr::getBitCast(Aliasee, J->getType())); ++NumAliasesResolved; Changed = true; diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index a8106e0c32..83d9a6f749 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -1327,11 +1327,9 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { // Replace G with an alias to F and delete G. void MergeFunctions::writeAlias(Function *F, Function *G) { - Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); PointerType *PTy = G->getType(); - GlobalAlias *GA = - new GlobalAlias(PTy->getElementType(), G->getLinkage(), "", BitcastF, - G->getParent(), PTy->getAddressSpace()); + auto *GA = new GlobalAlias(PTy->getElementType(), G->getLinkage(), "", F, + G->getParent(), PTy->getAddressSpace()); F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); GA->takeName(G); GA->setVisibility(G->getVisibility()); diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp index 1a3641452d..d4c4c1907a 100644 --- a/lib/Transforms/Utils/CloneModule.cpp +++ b/lib/Transforms/Utils/CloneModule.cpp @@ -107,8 +107,8 @@ Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) { for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) { GlobalAlias *GA = cast<GlobalAlias>(VMap[I]); - if (const Constant *C = I->getAliasee()) - GA->setAliasee(MapValue(C, VMap)); + if (const GlobalObject *C = I->getAliasee()) + GA->setAliasee(cast<GlobalObject>(MapValue(C, VMap))); } // And named metadata.... diff --git a/test/Assembler/2009-04-25-AliasGEP.ll b/test/Assembler/2009-04-25-AliasGEP.ll deleted file mode 100644 index 6d07208def..0000000000 --- a/test/Assembler/2009-04-25-AliasGEP.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis -; PR4066 -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -target triple = "i386-apple-darwin9" - %struct.i2c_device_id = type { } -@w83l785ts_id = internal constant [0 x %struct.i2c_device_id] zeroinitializer, align 1 ; <[0 x %struct.i2c_device_id]*> [#uses=1] - -@__mod_i2c_device_table = alias getelementptr ([0 x %struct.i2c_device_id]* @w83l785ts_id, i32 0, i32 0) ; <%struct.i2c_device_id*> [#uses=0] diff --git a/test/Assembler/addrspacecast-alias.ll b/test/Assembler/addrspacecast-alias.ll index 6623a25d18..052a1414ea 100644 --- a/test/Assembler/addrspacecast-alias.ll +++ b/test/Assembler/addrspacecast-alias.ll @@ -1,6 +1,7 @@ -; RUN: llvm-as -disable-output %s +; RUN: llvm-as < %s | llvm-dis | FileCheck %s ; Test that global aliases are allowed to be constant addrspacecast @i = internal addrspace(1) global i8 42 -@ia = alias internal i8 addrspace(2)* addrspacecast (i8 addrspace(1)* @i to i8 addrspace(2)*) +@ia = alias internal addrspace(2) i8 addrspace(3)*, i8 addrspace(1)* @i +; CHECK: @ia = alias internal addrspace(2) i8 addrspace(3)*, i8 addrspace(1)* @i diff --git a/test/Assembler/alias-addrspace.ll b/test/Assembler/alias-addrspace.ll new file mode 100644 index 0000000000..6d378e45fa --- /dev/null +++ b/test/Assembler/alias-addrspace.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +@foo = global i32 42 +@bar = alias internal addrspace(1) i32* @foo + +CHECK: error: A type is required if addrspace is given diff --git a/test/Assembler/alias-to-alias.ll b/test/Assembler/alias-to-alias.ll new file mode 100644 index 0000000000..1ea99bbb69 --- /dev/null +++ b/test/Assembler/alias-to-alias.ll @@ -0,0 +1,5 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s +; CHECK: Alias must point to function or variable + +@b1 = alias i32* @c1 +@c1 = alias i32* @b1 diff --git a/test/Assembler/alias-to-alias2.ll b/test/Assembler/alias-to-alias2.ll new file mode 100644 index 0000000000..a8a0196f43 --- /dev/null +++ b/test/Assembler/alias-to-alias2.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s +; CHECK: error: Alias is pointed by alias b1 + +@g = global i32 42 + +@b1 = alias i32* @c1 +@c1 = alias i32* @g diff --git a/test/Assembler/alias-type.ll b/test/Assembler/alias-type.ll new file mode 100644 index 0000000000..ead3e95243 --- /dev/null +++ b/test/Assembler/alias-type.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s 2>&1 | FileCheck %s + +@foo = global i32 42 +@bar = alias i32 @foo + +CHECK: error: An alias must have pointer type diff --git a/test/Bitcode/old-aliases.ll b/test/Bitcode/old-aliases.ll new file mode 100644 index 0000000000..4ef47c03dd --- /dev/null +++ b/test/Bitcode/old-aliases.ll @@ -0,0 +1,22 @@ +; RUN: llvm-dis < %s.bc | FileCheck %s + +; old-aliases.bc consist of this file assembled with an old llvm-as (3.5 trunk) +; from when aliases contained a ConstantExpr. + +@v1 = global i32 0 +; CHECK: @v1 = global i32 0 + +@v2 = global [1 x i32] zeroinitializer +; CHECK: @v2 = global [1 x i32] zeroinitializer + +@v3 = alias bitcast (i32* @v1 to i16*) +; CHECK: @v3 = alias i16, i32* @v1 + +@v4 = alias getelementptr ([1 x i32]* @v2, i32 0, i32 0) +; CHECK: @v4 = alias i32, [1 x i32]* @v2 + +@v5 = alias i32 addrspace(2)* addrspacecast (i32 addrspace(0)* @v1 to i32 addrspace(2)*) +; CHECK: @v5 = alias addrspace(2) i32, i32* @v1 + +@v6 = alias i16* @v3 +; CHECK: @v6 = alias i16, i32* @v1 diff --git a/test/Bitcode/old-aliases.ll.bc b/test/Bitcode/old-aliases.ll.bc Binary files differnew file mode 100644 index 0000000000..1f157b2a04 --- /dev/null +++ b/test/Bitcode/old-aliases.ll.bc diff --git a/test/CodeGen/ARM/aliases.ll b/test/CodeGen/ARM/aliases.ll index f55ae10b24..4de305b93b 100644 --- a/test/CodeGen/ARM/aliases.ll +++ b/test/CodeGen/ARM/aliases.ll @@ -29,7 +29,7 @@ define i32 @foo_f() { @bar_i = alias internal i32* @bar -@A = alias bitcast (i32* @bar to i64*) +@A = alias i64, i32* @bar define i32 @test() { entry: diff --git a/test/CodeGen/X86/aliases.ll b/test/CodeGen/X86/aliases.ll index d0a262d390..8487c6082b 100644 --- a/test/CodeGen/X86/aliases.ll +++ b/test/CodeGen/X86/aliases.ll @@ -22,7 +22,7 @@ define i32 @foo_f() { @bar_i = alias internal i32* @bar ; CHECK-DAG: .globl A -@A = alias bitcast (i32* @bar to i64*) +@A = alias i64, i32* @bar ; CHECK-DAG: .globl bar_h ; CHECK-DAG: .hidden bar_h diff --git a/test/CodeGen/X86/dllexport-x86_64.ll b/test/CodeGen/X86/dllexport-x86_64.ll index af0f85b00e..8bd882efee 100644 --- a/test/CodeGen/X86/dllexport-x86_64.ll +++ b/test/CodeGen/X86/dllexport-x86_64.ll @@ -66,7 +66,7 @@ define weak_odr dllexport void @weak1() { ; CHECK: .globl alias3 ; CHECK: alias3 = notExported -@alias3 = dllexport alias void()* @alias +@alias3 = dllexport alias void()* @notExported ; CHECK: .weak weak_alias ; CHECK: weak_alias = f1 diff --git a/test/CodeGen/X86/dllexport.ll b/test/CodeGen/X86/dllexport.ll index 6103a41211..b85df83e3e 100644 --- a/test/CodeGen/X86/dllexport.ll +++ b/test/CodeGen/X86/dllexport.ll @@ -85,7 +85,7 @@ define weak_odr dllexport void @weak1() { ; CHECK: .globl _alias3 ; CHECK: _alias3 = _notExported -@alias3 = dllexport alias void()* @alias +@alias3 = dllexport alias void()* @notExported ; CHECK: .weak _weak_alias ; CHECK: _weak_alias = _f1 diff --git a/test/Feature/alias2.ll b/test/Feature/alias2.ll new file mode 100644 index 0000000000..693ef7c9be --- /dev/null +++ b/test/Feature/alias2.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@v1 = global i32 0 +; CHECK: @v1 = global i32 0 + +@v2 = global [1 x i32] zeroinitializer +; CHECK: @v2 = global [1 x i32] zeroinitializer + +@v3 = alias i16, i32* @v1 +; CHECK: @v3 = alias i16, i32* @v1 + +@v4 = alias i32, [1 x i32]* @v2 +; CHECK: @v4 = alias i32, [1 x i32]* @v2 + +@v5 = alias addrspace(2) i32, i32* @v1 +; CHECK: @v5 = alias addrspace(2) i32, i32* @v1 + +@v6 = alias i16, i32* @v1 +; CHECK: @v6 = alias i16, i32* @v1 diff --git a/test/Feature/aliases.ll b/test/Feature/aliases.ll index 7fe9d0b374..b2ce82a838 100644 --- a/test/Feature/aliases.ll +++ b/test/Feature/aliases.ll @@ -7,7 +7,6 @@ @bar = global i32 0 @foo1 = alias i32* @bar @foo2 = alias i32* @bar -@foo3 = alias i32* @foo2 %FunTy = type i32() @@ -15,11 +14,10 @@ define i32 @foo_f() { ret i32 0 } @bar_f = alias weak_odr %FunTy* @foo_f -@bar_ff = alias i32()* @bar_f @bar_i = alias internal i32* @bar -@A = alias bitcast (i32* @bar to i64*) +@A = alias i64, i32* @bar define i32 @test() { entry: diff --git a/test/Linker/Inputs/PR8300.b.ll b/test/Linker/Inputs/PR8300.b.ll index 9e538f5d28..362d309a19 100644 --- a/test/Linker/Inputs/PR8300.b.ll +++ b/test/Linker/Inputs/PR8300.b.ll @@ -1,7 +1,7 @@ %foo = type { [8 x i8] } %bar = type { [9 x i8] } -@zed = alias bitcast (void (%bar*)* @xyz to void (%foo*)*) +@zed = alias void (%foo*), void (%bar*)* @xyz define void @xyz(%bar* %this) { entry: diff --git a/test/Linker/Inputs/alias.ll b/test/Linker/Inputs/alias.ll new file mode 100644 index 0000000000..b869cae71e --- /dev/null +++ b/test/Linker/Inputs/alias.ll @@ -0,0 +1,3 @@ +@zed = global i32 42 +@foo = alias i32* @zed +@foo2 = alias i16, i32* @zed diff --git a/test/Linker/Inputs/cycle.ll b/test/Linker/Inputs/cycle.ll new file mode 100644 index 0000000000..d0eddb6e7c --- /dev/null +++ b/test/Linker/Inputs/cycle.ll @@ -0,0 +1,2 @@ +@foo = alias i32* @bar +@bar = weak global i32 0 diff --git a/test/Linker/alias.ll b/test/Linker/alias.ll new file mode 100644 index 0000000000..5809a15082 --- /dev/null +++ b/test/Linker/alias.ll @@ -0,0 +1,16 @@ +; RUN: llvm-link %s %S/Inputs/alias.ll -S -o - | FileCheck %s +; RUN: llvm-link %S/Inputs/alias.ll %s -S -o - | FileCheck %s + +@foo = weak global i32 0 +; CHECK-DAG: @foo = alias i32* @zed + +@bar = alias i32* @foo +; CHECK-DAG: @bar = alias i32* @zed + +@foo2 = weak global i32 0 +; CHECK-DAG: @foo2 = alias i16, i32* @zed + +@bar2 = alias i32* @foo2 +; CHECK-DAG: @bar2 = alias i32* @zed + +; CHECK-DAG: @zed = global i32 42 diff --git a/test/Linker/cycle.ll b/test/Linker/cycle.ll new file mode 100644 index 0000000000..7d9ad2d9d6 --- /dev/null +++ b/test/Linker/cycle.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-link %s %S/Inputs/cycle.ll 2>&1 | FileCheck %s +; RUN: not llvm-link %S/Inputs/cycle.ll %s 2>&1 | FileCheck %s + +; CHECK: Linking these modules creates an alias cycle + +@foo = weak global i32 0 +@bar = alias i32* @foo diff --git a/test/Other/extract-alias.ll b/test/Other/extract-alias.ll index d1e4af5456..dbc650ec69 100644 --- a/test/Other/extract-alias.ll +++ b/test/Other/extract-alias.ll @@ -14,7 +14,7 @@ ; DELETE: @zed = global i32 0 ; DELETE: @zeda0 = alias i32* @zed ; DELETE-NEXT: @a0foo = alias i32* ()* @foo -; DELETE-NEXT: @a0a0bar = alias void ()* @a0bar +; DELETE-NEXT: @a0a0bar = alias void ()* @bar ; DELETE-NEXT: @a0bar = alias void ()* @bar ; DELETE: declare i32* @foo() ; DELETE: define void @bar() { @@ -25,7 +25,7 @@ ; ALIAS: @zed = external global i32 ; ALIAS: @zeda0 = alias i32* @zed -; ALIASRE: @a0a0bar = alias void ()* @a0bar +; ALIASRE: @a0a0bar = alias void ()* @bar ; ALIASRE: @a0bar = alias void ()* @bar ; ALIASRE: declare void @bar() @@ -39,7 +39,7 @@ define i32* @foo() { ret i32* @zeda0 } -@a0a0bar = alias void ()* @a0bar +@a0a0bar = alias void ()* @bar @a0bar = alias void ()* @bar diff --git a/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll b/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll index 0bdced5114..4b967997ce 100644 --- a/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll +++ b/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll @@ -11,8 +11,8 @@ @L1 = alias i32* @A ; CHECK: @L1 = alias i32* @A -@L2 = alias internal i32* @L1 -; CHECK: @L2 = alias internal i32* @L1 +@L2 = alias internal i32* @A +; DEAD-NOT: @L2 -@L3 = alias i32* @L2 -; CHECK: @L3 = alias i32* @L2 +@L3 = alias i32* @A +; CHECK: @L3 = alias i32* @A diff --git a/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll b/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll index d6a565ad10..03d6ee4f8a 100644 --- a/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll +++ b/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll @@ -2,7 +2,7 @@ @g = global i32 0 -@a = alias bitcast (i32* @g to i8*) +@a = alias i8, i32* @g define void @f() { %tmp = load i8* @a diff --git a/test/Transforms/GlobalOpt/alias-resolve.ll b/test/Transforms/GlobalOpt/alias-resolve.ll index 2d5a956d14..bd07b31b23 100644 --- a/test/Transforms/GlobalOpt/alias-resolve.ll +++ b/test/Transforms/GlobalOpt/alias-resolve.ll @@ -1,9 +1,9 @@ ; RUN: opt < %s -globalopt -S | FileCheck %s -@foo1 = alias void ()* @foo2 +@foo1 = alias void ()* @bar2 ; CHECK: @foo1 = alias void ()* @bar2 -@foo2 = alias void()* @bar1 +@foo2 = alias void()* @bar2 ; CHECK: @foo2 = alias void ()* @bar2 @bar1 = alias void ()* @bar2 diff --git a/test/Transforms/InstCombine/bitcast-alias-function.ll b/test/Transforms/InstCombine/bitcast-alias-function.ll index a6b56f94ff..284960b113 100644 --- a/test/Transforms/InstCombine/bitcast-alias-function.ll +++ b/test/Transforms/InstCombine/bitcast-alias-function.ll @@ -6,46 +6,46 @@ target datalayout = "e-p:32:32:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16 ; Cases that should be bitcast ; Test cast between scalars with same bit sizes -@alias_i32_to_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) +@alias_i32_to_f32 = alias float (float), i32 (i32)* @func_i32 ; Test cast between vectors with same number of elements and bit sizes -@alias_v2i32_to_v2f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <2 x float> (<2 x float>)*) +@alias_v2i32_to_v2f32 = alias <2 x float> (<2 x float>), <2 x i32> (<2 x i32>)* @func_v2i32 ; Test cast from vector to scalar with same number of bits -@alias_v2f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <2 x float> (<2 x float>)*) +@alias_v2f32_to_i64 = alias <2 x float> (<2 x float>), i64 (i64)* @func_i64 ; Test cast from scalar to vector with same number of bits -@alias_i64_to_v2f32 = alias bitcast (<2 x float> (<2 x float>)* @func_v2f32 to i64 (i64)*) +@alias_i64_to_v2f32 = alias i64 (i64), <2 x float> (<2 x float>)* @func_v2f32 ; Test cast between vectors of pointers -@alias_v2i32p_to_v2i64p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to <2 x i64*> (<2 x i64*>)*) +@alias_v2i32p_to_v2i64p = alias <2 x i64*> (<2 x i64*>), <2 x i32*> (<2 x i32*>)* @func_v2i32p ; Cases that should be invalid and unchanged ; Test cast between scalars with different bit sizes -@alias_i64_to_f32 = alias bitcast (i64 (i64)* @func_i64 to float (float)*) +@alias_i64_to_f32 = alias float (float), i64 (i64)* @func_i64 ; Test cast between vectors with different bit sizes but the ; same number of elements -@alias_v2i64_to_v2f32 = alias bitcast (<2 x i64> (<2 x i64>)* @func_v2i64 to <2 x float> (<2 x float>)*) +@alias_v2i64_to_v2f32 = alias <2 x float> (<2 x float>), <2 x i64> (<2 x i64>)* @func_v2i64 ; Test cast between vectors with same number of bits and different ; numbers of elements -@alias_v2i32_to_v4f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <4 x float> (<4 x float>)*) +@alias_v2i32_to_v4f32 = alias <4 x float> (<4 x float>), <2 x i32> (<2 x i32>)* @func_v2i32 ; Test cast between scalar and vector with different number of bits -@alias_i64_to_v4f32 = alias bitcast (<4 x float> (<4 x float>)* @func_v4f32 to i64 (i64)*) +@alias_i64_to_v4f32 = alias i64 (i64), <4 x float> (<4 x float>)* @func_v4f32 ; Test cast between vector and scalar with different number of bits -@alias_v4f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x float> (<4 x float>)*) +@alias_v4f32_to_i64 = alias <4 x float> (<4 x float>), i64 (i64)* @func_i64 ; Test cast from scalar to vector of pointers with same number of bits ; We don't know the pointer size at this point, so this can't be done -@alias_i64_to_v2i32p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to i64 (i64)*) +@alias_i64_to_v2i32p = alias i64 (i64), <2 x i32*> (<2 x i32*>)* @func_v2i32p ; Test cast between vector of pointers and scalar with different number of bits -@alias_v4i32p_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x i32*> (<4 x i32*>)*) +@alias_v4i32p_to_i64 = alias <4 x i32*> (<4 x i32*>), i64 (i64)* @func_i64 diff --git a/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll b/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll index c71dbb1fd8..16bfe2a460 100644 --- a/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll +++ b/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll @@ -6,8 +6,8 @@ @B = alias i32* @A ; CHECK: @B = alias internal i32* @A -@C = alias i32* @B -; CHECK: @C = alias internal i32* @B +@C = alias i32* @A +; CHECK: @C = alias internal i32* @A define i32 @main() { %tmp = load i32* @C diff --git a/test/Verifier/aliasing-chain.ll b/test/Verifier/aliasing-chain.ll deleted file mode 100644 index ae0b77fdc3..0000000000 --- a/test/Verifier/aliasing-chain.ll +++ /dev/null @@ -1,6 +0,0 @@ -; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s -; CHECK: Aliasing chain should end with function or global variable -; Test that alising chain does not create a cycle - -@b1 = alias i32* @c1 -@c1 = alias i32* @b1 diff --git a/test/Verifier/bitcast-alias-address-space.ll b/test/Verifier/bitcast-alias-address-space.ll deleted file mode 100644 index d9794d9e33..0000000000 --- a/test/Verifier/bitcast-alias-address-space.ll +++ /dev/null @@ -1,10 +0,0 @@ -; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s - -; CHECK: error: invalid cast opcode for cast from 'i32 addrspace(2)*' to 'i32 addrspace(1)*' - -target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n8:16:32" - - -@data = addrspace(2) global i32 27 - -@illegal_alias_data = alias bitcast (i32 addrspace(2)* @data to i32 addrspace(1)*) diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 59c9652e2e..b225ba923b 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -268,6 +268,18 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { EXPECT_DEATH(Global->replaceAllUsesWith(GEP), "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!"); } + +TEST(ConstantsTest, ReplaceInAliasTest) { + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); + + Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); + auto *Global = cast<GlobalObject>(M->getOrInsertGlobal("dummy", Int32Ty)); + auto *GA = new GlobalAlias(Int32Ty, GlobalValue::ExternalLinkage, "alias", + Global, M.get()); + EXPECT_DEATH(Global->replaceAllUsesWith(GA), + "replaceAliasUseWith cannot form an alias cycle"); +} + #endif #endif diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp index 6863ea5a60..ea8fb3962b 100644 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ b/unittests/Transforms/Utils/SpecialCaseList.cpp @@ -34,7 +34,7 @@ protected: M, ST, false, GlobalValue::ExternalLinkage, 0, Name); } - GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) { + GlobalAlias *makeAlias(StringRef Name, GlobalObject *Aliasee) { return new GlobalAlias(Aliasee->getType()->getElementType(), GlobalValue::ExternalLinkage, Name, Aliasee, Aliasee->getParent()); |