diff options
42 files changed, 267 insertions, 316 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 650012e7f9..d76fc0d3af 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -679,11 +679,15 @@ Syntax:: Aliases ------- -Aliases act as "second name" for the aliasee value (which can be either -function, global variable, another alias or bitcast of global value). +Aliases, unlike function or variables, don't create any new data. They +are just a new symbol and metadata for an existing position. + +Aliases have a name and an aliasee that is either a global value or a +constant expression. + Aliases may have an optional :ref:`linkage type <linkage>`, an optional -:ref:`visibility style <visibility>`, and an optional :ref:`DLL storage class -<dllstorageclass>`. +:ref:`visibility style <visibility>`, an optional :ref:`DLL storage class +<dllstorageclass>` and an optional :ref:`tls model <tls_model>`. Syntax:: @@ -691,17 +695,23 @@ Syntax:: The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``, ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers -might not correctly handle dropping a weak symbol that is aliased by a non-weak -alias. +might not correctly handle dropping a weak symbol that is aliased. Alias that are not ``unnamed_addr`` are guaranteed to have the same address as the aliasee. -The aliasee must be a definition. +Since aliases are only a second name, some restrictions apply, of which +some can only be checked when producing an object file: + +* The expression defining the aliasee must be computable at assembly + time. Since it is just a name, no relocations can be used. + +* No alias in the expression can be weak as the possibility of the + intermediate alias being overridden cannot be represented in an + object file. -Aliases are not allowed to point to aliases with linkages that can be -overridden. Since they are only a second name, the possibility of the -intermediate alias being overridden cannot be represented in an object file. +* No global value in the expression can be a declaration, since that + would require a relocation, which is not possible. .. _namedmetadatastructure: diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index d9f0b4a89b..a77d1630f4 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -34,7 +34,7 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { void setParent(Module *parent); GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, GlobalObject *Aliasee, Module *Parent); + const Twine &Name, Constant *Aliasee, Module *Parent); public: // allocate space for exactly one operand @@ -46,7 +46,7 @@ public: /// the end of the specified module's alias list. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee, Module *Parent); + Constant *Aliasee, Module *Parent); // Without the Aliasee. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, @@ -56,14 +56,14 @@ public: // The module is taken from the Aliasee. static GlobalAlias *create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee); + GlobalValue *Aliasee); // Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee); + GlobalValue *Aliasee); // Linkage, Type, Parent and AddressSpace taken from the Aliasee. - static GlobalAlias *create(const Twine &Name, GlobalObject *Aliasee); + static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -78,14 +78,13 @@ public: /// void eraseFromParent() override; - /// set/getAliasee - These methods retrive and set alias target. - void setAliasee(GlobalObject *GO); - const GlobalObject *getAliasee() const { + /// These methods retrive and set alias target. + void setAliasee(Constant *Aliasee); + const Constant *getAliasee() const { return const_cast<GlobalAlias *>(this)->getAliasee(); } - - GlobalObject *getAliasee() { - return cast_or_null<GlobalObject>(getOperand(0)); + Constant *getAliasee() { + return getOperand(0); } static bool isValidLinkage(LinkageTypes L) { diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 3bc8b8531d..74cc18eeb1 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -40,8 +40,8 @@ public: } void setAlignment(unsigned Align); - bool hasSection() const { return !getSection().empty(); } - const std::string &getSection() const { return Section; } + bool hasSection() const { return !StringRef(getSection()).empty(); } + const char *getSection() const { return Section.c_str(); } void setSection(StringRef S); void copyAttributesFrom(const GlobalValue *Src) override; diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 04c97a01d6..5e99886a5f 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -146,8 +146,14 @@ public: } void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } - bool hasSection() const { return !getSection().empty(); } - const std::string &getSection() const; + bool hasSection() const { return !StringRef(getSection()).empty(); } + // It is unfortunate that we have to use "char *" in here since this is + // always non NULL, but: + // * The C API expects a null terminated string, so we cannot use StringRef. + // * The C API expects us to own it, so we cannot use a std:string. + // * For GlobalAliases we can fail to find the section and we have to + // return "", so we cannot use a "const std::string &". + const char *getSection() const; /// Global values are always pointers. inline PointerType *getType() const { diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index f0efa9414d..dc151f2bf9 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -674,44 +674,30 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, return Error(LinkageLoc, "symbol with local linkage must have default visibility"); - 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)) + Constant *Aliasee; + LocTy AliaseeLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::kw_bitcast && + Lex.getKind() != lltok::kw_getelementptr && + Lex.getKind() != lltok::kw_addrspacecast && + Lex.getKind() != lltok::kw_inttoptr) { + if (ParseGlobalTypeAndValue(Aliasee)) return true; } else { - 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(); + // 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; } - 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()); + Type *AliaseeType = Aliasee->getType(); + auto *PTy = dyn_cast<PointerType>(AliaseeType); + if (!PTy) + return Error(AliaseeLoc, "An alias must have pointer type"); + Type *Ty = PTy->getElementType(); + unsigned AddrSpace = PTy->getAddressSpace(); // Okay, create the alias but do not insert it into the module yet. std::unique_ptr<GlobalAlias> GA( @@ -739,11 +725,6 @@ 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 3d4ae84dbd..322879b566 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1094,28 +1094,6 @@ 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() { @@ -1141,30 +1119,19 @@ 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])) - AliasInit.insert(std::make_pair(AliasInitWorklist.back().first, C)); + AliasInitWorklist.back().first->setAliasee(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/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7de9c6d616..6c6d0dae9e 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -870,6 +870,8 @@ void AsmPrinter::EmitFunctionBody() { OutStreamer.AddBlankLine(); } +static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP); + bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (const auto &G : M.globals()) @@ -932,10 +934,6 @@ bool AsmPrinter::doFinalization(Module &M) { for (const auto &Alias : M.aliases()) { MCSymbol *Name = getSymbol(&Alias); - const GlobalValue *GV = Alias.getAliasee(); - assert(!GV->isDeclaration()); - MCSymbol *Target = getSymbol(GV); - if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective()) OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage()) @@ -947,7 +945,7 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit the directives as assignments aka .set: OutStreamer.EmitAssignment(Name, - MCSymbolRefExpr::Create(Target, OutContext)); + lowerConstant(Alias.getAliasee(), *this)); } } @@ -1248,7 +1246,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { } // Ignore debug and non-emitted data. This handles llvm.compiler.used. - if (GV->getSection() == "llvm.metadata" || + if (StringRef(GV->getSection()) == "llvm.metadata" || GV->hasAvailableExternallyLinkage()) return true; diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index cd7a500f51..f1c3bb274e 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueMap.h" #include "llvm/Support/Debug.h" @@ -684,13 +685,23 @@ void *JITResolver::JITCompilerFn(void *Stub) { //===----------------------------------------------------------------------===// // JITEmitter code. // + +static GlobalObject *getSimpleAliasee(Constant *C) { + C = cast<Constant>(C->stripPointerCasts()); + return dyn_cast<GlobalObject>(C); +} + void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, bool MayNeedFarStub) { if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) return TheJIT->getOrEmitGlobalVariable(GV); - if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) - return TheJIT->getPointerToGlobal(GA->getAliasee()); + if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { + // We can only handle simple cases. + if (GlobalValue *GV = getSimpleAliasee(GA->getAliasee())) + return TheJIT->getPointerToGlobal(GV); + return nullptr; + } // If we have already compiled the function, return a pointer to its body. Function *F = cast<Function>(V); diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 8aee77ac07..14467137aa 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1494,16 +1494,10 @@ 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 27ce503e1c..aa373f602a 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -1286,7 +1286,7 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) { } const char *LLVMGetSection(LLVMValueRef Global) { - return unwrap<GlobalValue>(Global)->getSection().c_str(); + return unwrap<GlobalValue>(Global)->getSection(); } void LLVMSetSection(LLVMValueRef Global, const char *Section) { diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 344a08d8f3..d5723c226a 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -58,10 +59,22 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { setDLLStorageClass(Src->getDLLStorageClass()); } -unsigned GlobalValue::getAlignment() const { - if (auto *GA = dyn_cast<GlobalAlias>(this)) - return GA->getAliasee()->getAlignment(); +const GlobalObject *getBaseObject(const Constant &C) { + // FIXME: We should probably return a base + offset pair for non-zero GEPs. + return dyn_cast<GlobalObject>(C.stripPointerCasts()); +} +unsigned GlobalValue::getAlignment() const { + if (auto *GA = dyn_cast<GlobalAlias>(this)) { + // In general we cannot compute this at the IR level, but we try. + if (const GlobalObject *GO = getBaseObject(*GA->getAliasee())) + return GO->getAlignment(); + + // FIXME: we should also be able to handle: + // Alias = Global + Offset + // Alias = Absolute + return 0; + } return cast<GlobalObject>(this)->getAlignment(); } @@ -80,9 +93,13 @@ void GlobalObject::copyAttributesFrom(const GlobalValue *Src) { setSection(GV->getSection()); } -const std::string &GlobalValue::getSection() const { - if (auto *GA = dyn_cast<GlobalAlias>(this)) - return GA->getAliasee()->getSection(); +const char *GlobalValue::getSection() const { + if (auto *GA = dyn_cast<GlobalAlias>(this)) { + // In general we cannot compute this at the IR level, but we try. + if (const GlobalObject *GO = getBaseObject(*GA->getAliasee())) + return GO->getSection(); + return ""; + } return cast<GlobalObject>(this)->getSection(); } @@ -216,7 +233,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { //===----------------------------------------------------------------------===// GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, - const Twine &Name, GlobalObject *Aliasee, + const Twine &Name, Constant *Aliasee, Module *ParentModule) : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { @@ -229,7 +246,7 @@ GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, LinkageTypes Link, const Twine &Name, - GlobalObject *Aliasee, Module *ParentModule) { + Constant *Aliasee, Module *ParentModule) { return new GlobalAlias(Ty, AddressSpace, Link, Name, Aliasee, ParentModule); } @@ -241,18 +258,18 @@ GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, GlobalAlias *GlobalAlias::create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - GlobalObject *Aliasee) { + GlobalValue *Aliasee) { return create(Ty, AddressSpace, Linkage, Name, Aliasee, Aliasee->getParent()); } GlobalAlias *GlobalAlias::create(LinkageTypes Link, const Twine &Name, - GlobalObject *Aliasee) { + GlobalValue *Aliasee) { PointerType *PTy = Aliasee->getType(); return create(PTy->getElementType(), PTy->getAddressSpace(), Link, Name, Aliasee); } -GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalObject *Aliasee) { +GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { return create(Aliasee->getLinkage(), Name, Aliasee); } @@ -272,4 +289,8 @@ void GlobalAlias::eraseFromParent() { getParent()->getAliasList().erase(this); } -void GlobalAlias::setAliasee(GlobalObject *Aliasee) { setOperand(0, Aliasee); } +void GlobalAlias::setAliasee(Constant *Aliasee) { + assert(!Aliasee || Aliasee->getType() == getType() && + "Alias and aliasee types should match!"); + setOperand(0, Aliasee); +} diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index d734e4ea81..cc599745d5 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -301,27 +301,6 @@ 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); - assert(&cast<GlobalObject>(*U) != &Replacement && - "replaceAliasUseWith cannot form an alias cycle"); - U.set(&Replacement); -} - #ifndef NDEBUG static bool contains(SmallPtrSet<ConstantExpr *, 4> &Cache, ConstantExpr *Expr, Constant *C) { @@ -373,10 +352,6 @@ void Value::replaceAllUsesWith(Value *New) { // Must handle Constants specially, we cannot call replaceUsesOfWith on a // constant because they are uniqued. 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 bcc38c1ad5..1719cb2759 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -241,6 +241,9 @@ private: void visitGlobalValue(const GlobalValue &GV); void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); + void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); + void visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited, + const GlobalAlias &A, const Constant &C); void visitNamedMDNode(const NamedMDNode &NMD); void visitMDNode(MDNode &MD, Function *F); void visitModuleIdents(const Module &M); @@ -474,36 +477,52 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { visitGlobalValue(GV); } +void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { + SmallPtrSet<const GlobalAlias*, 4> Visited; + Visited.insert(&GA); + visitAliaseeSubExpr(Visited, GA, C); +} + +void Verifier::visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited, + const GlobalAlias &GA, const Constant &C) { + if (const auto *GV = dyn_cast<GlobalValue>(&C)) { + Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA); + + if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { + Assert1(Visited.insert(GA2), "Aliases cannot form a cycle", &GA); + + Assert1(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", + &GA); + } + } + + if (const auto *CE = dyn_cast<ConstantExpr>(&C)) + VerifyConstantExprBitcastType(CE); + + for (const Use &U : C.operands()) { + Value *V = &*U; + if (const auto *GA2 = dyn_cast<GlobalAlias>(V)) + visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee()); + else if (const auto *C2 = dyn_cast<Constant>(V)) + visitAliaseeSubExpr(Visited, GA, *C2); + } +} + void Verifier::visitGlobalAlias(const GlobalAlias &GA) { Assert1(!GA.getName().empty(), "Alias name cannot be empty!", &GA); Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()), "Alias should have external or external weak linkage!", &GA); - Assert1(GA.getAliasee(), - "Aliasee cannot be NULL!", &GA); - Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); - const Constant *Aliasee = GA.getAliasee(); - const GlobalValue *GV = dyn_cast<GlobalValue>(Aliasee); - - if (!GV) { - const ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee); - if (CE && (CE->getOpcode() == Instruction::BitCast || - CE->getOpcode() == Instruction::AddrSpaceCast || - CE->getOpcode() == Instruction::GetElementPtr)) - GV = dyn_cast<GlobalValue>(CE->getOperand(0)); + Assert1(Aliasee, "Aliasee cannot be NULL!", &GA); + Assert1(GA.getType() == Aliasee->getType(), + "Alias and aliasee types should match!", &GA); + Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA); - Assert1(GV, "Aliasee should be either GlobalValue, bitcast or " - "addrspacecast of GlobalValue", - &GA); + Assert1(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee), + "Aliasee should be either GlobalValue or ConstantExpr", &GA); - VerifyConstantExprBitcastType(CE); - } - Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA); - if (const GlobalAlias *GAAliasee = dyn_cast<GlobalAlias>(GV)) { - Assert1(!GAAliasee->mayBeOverridden(), "Alias cannot point to a weak alias", - &GA); - } + visitAliaseeSubExpr(GA, *Aliasee); visitGlobalValue(GA); } diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index d117514265..f7f6a3c4b8 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -334,21 +334,22 @@ void LTOModule::addDefinedDataSymbol(const GlobalValue *v) { // from the ObjC data structures generated by the front end. // special case if this data blob is an ObjC class definition - if (v->getSection().compare(0, 15, "__OBJC,__class,") == 0) { + std::string Section = v->getSection(); + if (Section.compare(0, 15, "__OBJC,__class,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClass(gv); } } // special case if this data blob is an ObjC category definition - else if (v->getSection().compare(0, 18, "__OBJC,__category,") == 0) { + else if (Section.compare(0, 18, "__OBJC,__category,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCCategory(gv); } } // special case if this data blob is the list of referenced classes - else if (v->getSection().compare(0, 18, "__OBJC,__cls_refs,") == 0) { + else if (Section.compare(0, 18, "__OBJC,__cls_refs,") == 0) { if (const GlobalVariable *gv = dyn_cast<GlobalVariable>(v)) { addObjCClassRef(gv); } diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 45f2d4e03a..ad8e01dc1b 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -389,8 +389,6 @@ 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. @@ -723,7 +721,7 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, return emitError( "Appending variables with different unnamed_addr need to be linked!"); - if (DstGV->getSection() != SrcGV->getSection()) + if (StringRef(DstGV->getSection()) != SrcGV->getSection()) return emitError( "Appending variables with different section name need to be linked!"); @@ -929,8 +927,11 @@ bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) { if (NewVisibility) NewDA->setVisibility(*NewVisibility); - if (DGV) - ReplaceWithAlias.push_back(std::make_pair(DGV, NewDA)); + if (DGV) { + // Any uses of DGV need to change to NewDA, with cast. + DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDA, DGV->getType())); + DGV->eraseFromParent(); + } ValueMap[SGA] = NewDA; return false; @@ -1016,19 +1017,6 @@ 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(); @@ -1039,25 +1027,9 @@ void ModuleLinker::linkAliasBodies() { GlobalAlias *DA = cast<GlobalAlias>(ValueMap[I]); Constant *Val = MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer); - DA->setAliasee(&getGlobalObjectInExpr(*Val)); + DA->setAliasee(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/Target/NVPTX/NVPTXAsmPrinter.cpp b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index 4ec575ff34..e6cbf64359 100644 --- a/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -1356,7 +1356,7 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, // Skip meta data if (GVar->hasSection()) { - if (GVar->getSection() == "llvm.metadata") + if (GVar->getSection() == StringRef("llvm.metadata")) return; } diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 9d78586495..e9db2a8fa4 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -273,18 +273,16 @@ SDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA, SelectionDAG &DAG) const { // FIXME there is no actual debug info here SDLoc dl(GA); - const GlobalValue *UnderlyingGV = GV; - // If GV is an alias then use the aliasee to determine the wrapper type - if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) - UnderlyingGV = GA->getAliasee(); - if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(UnderlyingGV)) { - if ((GVar->isConstant() && GV->hasLocalLinkage()) || - (GVar->hasSection() && - StringRef(GVar->getSection()).startswith(".cp."))) - return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); - return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); - } - return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); + + if (GV->getType()->getElementType()->isFunctionTy()) + return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); + + const auto *GVar = dyn_cast<GlobalVariable>(GV); + if ((GV->hasSection() && StringRef(GV->getSection()).startswith(".cp.")) || + (GVar && GVar->isConstant() && GV->hasLocalLinkage())) + return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); + + return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); } static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) { diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp index eb67db1f85..3f75b3e677 100644 --- a/lib/Transforms/Utils/CloneModule.cpp +++ b/lib/Transforms/Utils/CloneModule.cpp @@ -107,7 +107,7 @@ 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 GlobalObject *C = I->getAliasee()) + if (const Constant *C = I->getAliasee()) GA->setAliasee(cast<GlobalObject>(MapValue(C, VMap))); } diff --git a/test/Assembler/addrspacecast-alias.ll b/test/Assembler/addrspacecast-alias.ll index 052a1414ea..7d00ac4f8f 100644 --- a/test/Assembler/addrspacecast-alias.ll +++ b/test/Assembler/addrspacecast-alias.ll @@ -3,5 +3,5 @@ ; Test that global aliases are allowed to be constant addrspacecast @i = internal addrspace(1) global i8 42 -@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 +@ia = alias internal addrspacecast (i8 addrspace(1)* @i to i8 addrspace(2)* addrspace(3)*) +; CHECK: @ia = alias internal addrspacecast (i8 addrspace(1)* @i to i8 addrspace(2)* addrspace(3)*) diff --git a/test/Assembler/alias-addrspace.ll b/test/Assembler/alias-addrspace.ll deleted file mode 100644 index 6d378e45fa..0000000000 --- a/test/Assembler/alias-addrspace.ll +++ /dev/null @@ -1,6 +0,0 @@ -; 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 deleted file mode 100644 index 1ea99bbb69..0000000000 --- a/test/Assembler/alias-to-alias.ll +++ /dev/null @@ -1,5 +0,0 @@ -; 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 deleted file mode 100644 index a8a0196f43..0000000000 --- a/test/Assembler/alias-to-alias2.ll +++ /dev/null @@ -1,7 +0,0 @@ -; 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 deleted file mode 100644 index ead3e95243..0000000000 --- a/test/Assembler/alias-type.ll +++ /dev/null @@ -1,6 +0,0 @@ -; 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 index 4ef47c03dd..7a0eea2f3f 100644 --- a/test/Bitcode/old-aliases.ll +++ b/test/Bitcode/old-aliases.ll @@ -10,13 +10,13 @@ ; CHECK: @v2 = global [1 x i32] zeroinitializer @v3 = alias bitcast (i32* @v1 to i16*) -; CHECK: @v3 = alias i16, i32* @v1 +; CHECK: @v3 = alias bitcast (i32* @v1 to i16*) @v4 = alias getelementptr ([1 x i32]* @v2, i32 0, i32 0) -; CHECK: @v4 = alias i32, [1 x i32]* @v2 +; CHECK: @v4 = alias getelementptr inbounds ([1 x i32]* @v2, i32 0, i32 0) @v5 = alias i32 addrspace(2)* addrspacecast (i32 addrspace(0)* @v1 to i32 addrspace(2)*) -; CHECK: @v5 = alias addrspace(2) i32, i32* @v1 +; CHECK: @v5 = alias addrspacecast (i32* @v1 to i32 addrspace(2)*) @v6 = alias i16* @v3 -; CHECK: @v6 = alias i16, i32* @v1 +; CHECK: @v6 = alias i16* @v3 diff --git a/test/CodeGen/ARM/aliases.ll b/test/CodeGen/ARM/aliases.ll index 4de305b93b..f55ae10b24 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 i64, i32* @bar +@A = alias bitcast (i32* @bar to i64*) define i32 @test() { entry: diff --git a/test/CodeGen/X86/aliases.ll b/test/CodeGen/X86/aliases.ll index d207880d66..bf55644de4 100644 --- a/test/CodeGen/X86/aliases.ll +++ b/test/CodeGen/X86/aliases.ll @@ -38,7 +38,7 @@ define i32 @foo_f() { @bar_i = alias internal i32* @bar ; CHECK-DAG: .globl A -@A = alias i64, i32* @bar +@A = alias bitcast (i32* @bar to i64*) ; CHECK-DAG: .globl bar_h ; CHECK-DAG: .hidden bar_h @@ -48,6 +48,19 @@ define i32 @foo_f() { ; CHECK-DAG: .protected bar_p @bar_p = protected alias i32* @bar +; CHECK-DAG: test2 = bar+4 +@test2 = alias getelementptr(i32 *@bar, i32 1) + +; CHECK-DAG: test3 = 42 +@test3 = alias inttoptr(i32 42 to i32*) + +; CHECK-DAG: test4 = bar +@test4 = alias inttoptr(i64 ptrtoint (i32* @bar to i64) to i32*) + +; CHECK-DAG: test5 = test2-bar +@test5 = alias inttoptr(i32 sub (i32 ptrtoint (i32* @test2 to i32), + i32 ptrtoint (i32* @bar to i32)) to i32*) + ; CHECK-DAG: .globl test define i32 @test() { entry: diff --git a/test/CodeGen/X86/dllexport-x86_64.ll b/test/CodeGen/X86/dllexport-x86_64.ll index f4dec4ff59..0d5afa1b13 100644 --- a/test/CodeGen/X86/dllexport-x86_64.ll +++ b/test/CodeGen/X86/dllexport-x86_64.ll @@ -73,7 +73,7 @@ define weak_odr dllexport void @weak1() { @weak_alias = dllexport alias weak_odr void()* @f1 @blob = global [6 x i8] c"\B8*\00\00\00\C3", section ".text", align 16 -@blob_alias = dllexport alias i32 (), [6 x i8]* @blob +@blob_alias = dllexport alias bitcast ([6 x i8]* @blob to i32 ()*) ; CHECK: .section .drectve ; WIN32: " /EXPORT:Var1,DATA" diff --git a/test/Feature/alias2.ll b/test/Feature/alias2.ll index bc542ffd77..73c874f2b9 100644 --- a/test/Feature/alias2.ll +++ b/test/Feature/alias2.ll @@ -6,17 +6,23 @@ @v2 = global [1 x i32] zeroinitializer ; CHECK: @v2 = global [1 x i32] zeroinitializer -@a1 = alias i16, i32* @v1 -; CHECK: @a1 = alias i16, i32* @v1 +@v3 = global [2 x i16] zeroinitializer +; CHECK: @v3 = global [2 x i16] zeroinitializer -@a2 = alias i32, [1 x i32]* @v2 -; CHECK: @a2 = alias i32, [1 x i32]* @v2 +@a1 = alias bitcast (i32* @v1 to i16*) +; CHECK: @a1 = alias bitcast (i32* @v1 to i16*) -@a3 = alias addrspace(2) i32, i32* @v1 -; CHECK: @a3 = alias addrspace(2) i32, i32* @v1 +@a2 = alias bitcast([1 x i32]* @v2 to i32*) +; CHECK: @a2 = alias getelementptr inbounds ([1 x i32]* @v2, i32 0, i32 0) -@a4 = alias i16, i32* @v1 -; CHECK: @a4 = alias i16, i32* @v1 +@a3 = alias addrspacecast (i32* @v1 to i32 addrspace(2)*) +; CHECK: @a3 = alias addrspacecast (i32* @v1 to i32 addrspace(2)*) + +@a4 = alias bitcast (i32* @v1 to i16*) +; CHECK: @a4 = alias bitcast (i32* @v1 to i16*) @a5 = thread_local(localdynamic) alias i32* @v1 ; CHECK: @a5 = thread_local(localdynamic) alias i32* @v1 + +@a6 = alias getelementptr ([2 x i16]* @v3, i32 1, i32 1) +; CHECK: @a6 = alias getelementptr ([2 x i16]* @v3, i32 1, i32 1) diff --git a/test/Feature/aliases.ll b/test/Feature/aliases.ll index b2ce82a838..7fe9d0b374 100644 --- a/test/Feature/aliases.ll +++ b/test/Feature/aliases.ll @@ -7,6 +7,7 @@ @bar = global i32 0 @foo1 = alias i32* @bar @foo2 = alias i32* @bar +@foo3 = alias i32* @foo2 %FunTy = type i32() @@ -14,10 +15,11 @@ 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 i64, i32* @bar +@A = alias bitcast (i32* @bar to i64*) define i32 @test() { entry: diff --git a/test/Linker/Inputs/PR8300.b.ll b/test/Linker/Inputs/PR8300.b.ll index 362d309a19..9e538f5d28 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 void (%foo*), void (%bar*)* @xyz +@zed = alias bitcast (void (%bar*)* @xyz to void (%foo*)*) define void @xyz(%bar* %this) { entry: diff --git a/test/Linker/Inputs/alias.ll b/test/Linker/Inputs/alias.ll index b869cae71e..f379476e76 100644 --- a/test/Linker/Inputs/alias.ll +++ b/test/Linker/Inputs/alias.ll @@ -1,3 +1,3 @@ @zed = global i32 42 @foo = alias i32* @zed -@foo2 = alias i16, i32* @zed +@foo2 = alias bitcast (i32* @zed to i16*) diff --git a/test/Linker/Inputs/cycle.ll b/test/Linker/Inputs/cycle.ll deleted file mode 100644 index d0eddb6e7c..0000000000 --- a/test/Linker/Inputs/cycle.ll +++ /dev/null @@ -1,2 +0,0 @@ -@foo = alias i32* @bar -@bar = weak global i32 0 diff --git a/test/Linker/alias.ll b/test/Linker/alias.ll index 5809a15082..bce51ad983 100644 --- a/test/Linker/alias.ll +++ b/test/Linker/alias.ll @@ -5,12 +5,12 @@ ; CHECK-DAG: @foo = alias i32* @zed @bar = alias i32* @foo -; CHECK-DAG: @bar = alias i32* @zed +; CHECK-DAG: @bar = alias i32* @foo @foo2 = weak global i32 0 -; CHECK-DAG: @foo2 = alias i16, i32* @zed +; CHECK-DAG: @foo2 = alias bitcast (i32* @zed to i16*) @bar2 = alias i32* @foo2 -; CHECK-DAG: @bar2 = alias i32* @zed +; CHECK-DAG: @bar2 = alias bitcast (i16* @foo2 to i32*) ; CHECK-DAG: @zed = global i32 42 diff --git a/test/Linker/cycle.ll b/test/Linker/cycle.ll deleted file mode 100644 index 7d9ad2d9d6..0000000000 --- a/test/Linker/cycle.ll +++ /dev/null @@ -1,7 +0,0 @@ -; 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/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll b/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll index 4b967997ce..0bdced5114 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* @A -; DEAD-NOT: @L2 +@L2 = alias internal i32* @L1 +; CHECK: @L2 = alias internal i32* @L1 -@L3 = alias i32* @A -; CHECK: @L3 = alias i32* @A +@L3 = alias i32* @L2 +; CHECK: @L3 = alias i32* @L2 diff --git a/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll b/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll index 03d6ee4f8a..d6a565ad10 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 i8, i32* @g +@a = alias bitcast (i32* @g to i8*) define void @f() { %tmp = load i8* @a diff --git a/test/Transforms/GlobalOpt/alias-resolve.ll b/test/Transforms/GlobalOpt/alias-resolve.ll index bd07b31b23..2d5a956d14 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 ()* @bar2 +@foo1 = alias void ()* @foo2 ; CHECK: @foo1 = alias void ()* @bar2 -@foo2 = alias void()* @bar2 +@foo2 = alias void()* @bar1 ; 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 284960b113..a6b56f94ff 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 float (float), i32 (i32)* @func_i32 +@alias_i32_to_f32 = alias bitcast (i32 (i32)* @func_i32 to float (float)*) ; Test cast between vectors with same number of elements and bit sizes -@alias_v2i32_to_v2f32 = alias <2 x float> (<2 x float>), <2 x i32> (<2 x i32>)* @func_v2i32 +@alias_v2i32_to_v2f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <2 x float> (<2 x float>)*) ; Test cast from vector to scalar with same number of bits -@alias_v2f32_to_i64 = alias <2 x float> (<2 x float>), i64 (i64)* @func_i64 +@alias_v2f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <2 x float> (<2 x float>)*) ; Test cast from scalar to vector with same number of bits -@alias_i64_to_v2f32 = alias i64 (i64), <2 x float> (<2 x float>)* @func_v2f32 +@alias_i64_to_v2f32 = alias bitcast (<2 x float> (<2 x float>)* @func_v2f32 to i64 (i64)*) ; Test cast between vectors of pointers -@alias_v2i32p_to_v2i64p = alias <2 x i64*> (<2 x i64*>), <2 x i32*> (<2 x i32*>)* @func_v2i32p +@alias_v2i32p_to_v2i64p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to <2 x i64*> (<2 x i64*>)*) ; Cases that should be invalid and unchanged ; Test cast between scalars with different bit sizes -@alias_i64_to_f32 = alias float (float), i64 (i64)* @func_i64 +@alias_i64_to_f32 = alias bitcast (i64 (i64)* @func_i64 to float (float)*) ; Test cast between vectors with different bit sizes but the ; same number of elements -@alias_v2i64_to_v2f32 = alias <2 x float> (<2 x float>), <2 x i64> (<2 x i64>)* @func_v2i64 +@alias_v2i64_to_v2f32 = alias bitcast (<2 x i64> (<2 x i64>)* @func_v2i64 to <2 x float> (<2 x float>)*) ; Test cast between vectors with same number of bits and different ; numbers of elements -@alias_v2i32_to_v4f32 = alias <4 x float> (<4 x float>), <2 x i32> (<2 x i32>)* @func_v2i32 +@alias_v2i32_to_v4f32 = alias bitcast (<2 x i32> (<2 x i32>)* @func_v2i32 to <4 x float> (<4 x float>)*) ; Test cast between scalar and vector with different number of bits -@alias_i64_to_v4f32 = alias i64 (i64), <4 x float> (<4 x float>)* @func_v4f32 +@alias_i64_to_v4f32 = alias bitcast (<4 x float> (<4 x float>)* @func_v4f32 to i64 (i64)*) ; Test cast between vector and scalar with different number of bits -@alias_v4f32_to_i64 = alias <4 x float> (<4 x float>), i64 (i64)* @func_i64 +@alias_v4f32_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x float> (<4 x float>)*) ; 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 i64 (i64), <2 x i32*> (<2 x i32*>)* @func_v2i32p +@alias_i64_to_v2i32p = alias bitcast (<2 x i32*> (<2 x i32*>)* @func_v2i32p to i64 (i64)*) ; Test cast between vector of pointers and scalar with different number of bits -@alias_v4i32p_to_i64 = alias <4 x i32*> (<4 x i32*>), i64 (i64)* @func_i64 +@alias_v4i32p_to_i64 = alias bitcast (i64 (i64)* @func_i64 to <4 x i32*> (<4 x i32*>)*) diff --git a/test/Verifier/alias.ll b/test/Verifier/alias.ll index e3636bc701..ff02a37bab 100644 --- a/test/Verifier/alias.ll +++ b/test/Verifier/alias.ll @@ -10,3 +10,18 @@ declare void @f() @ga = alias i32* @g ; CHECK: Alias must point to a definition ; CHECK-NEXT: @ga + + +@test2_a = alias i32* @test2_b +@test2_b = alias i32* @test2_a +; CHECK: Aliases cannot form a cycle +; CHECK-NEXT: i32* @test2_a +; CHECK-NEXT: Aliases cannot form a cycle +; CHECK-NEXT: i32* @test2_b + + +@test3_a = global i32 42 +@test3_b = alias weak i32* @test3_a +@test3_c = alias i32* @test3_b +; CHECK: Alias cannot point to a weak alias +; CHECK-NEXT: i32* @test3_c diff --git a/test/Verifier/bitcast-alias-address-space.ll b/test/Verifier/bitcast-alias-address-space.ll new file mode 100644 index 0000000000..d9794d9e33 --- /dev/null +++ b/test/Verifier/bitcast-alias-address-space.ll @@ -0,0 +1,10 @@ +; 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/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp index d1cfefe6a3..476b49486a 100644 --- a/tools/llvm-nm/llvm-nm.cpp +++ b/tools/llvm-nm/llvm-nm.cpp @@ -415,15 +415,11 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { } static char getSymbolNMTypeChar(const GlobalValue &GV) { - if (isa<Function>(GV)) + if (GV.getType()->getElementType()->isFunctionTy()) return 't'; // FIXME: should we print 'b'? At the IR level we cannot be sure if this // will be in bss or not, but we could approximate. - if (isa<GlobalVariable>(GV)) - return 'd'; - const GlobalAlias *GA = cast<GlobalAlias>(&GV); - const GlobalValue *AliasedGV = GA->getAliasee(); - return getSymbolNMTypeChar(*AliasedGV); + return 'd'; } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index c11729c08f..0cd8549982 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -269,16 +269,6 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { "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 = GlobalAlias::create(GlobalValue::ExternalLinkage, "alias", Global); - EXPECT_DEATH(Global->replaceAllUsesWith(GA), - "replaceAliasUseWith cannot form an alias cycle"); -} - #endif #endif |