diff options
author | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
commit | c6a4f5e819217e1e12c458aed8e7b122e23a3a58 (patch) | |
tree | 81b7dd2bb4370a392f31d332a566c903b5744764 /lib/IR | |
parent | 19c6fbb3e8aaf74093afa08013134b61fa08f245 (diff) | |
download | external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.zip external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.gz external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.bz2 |
Update LLVM for rebase to r212749.
Includes a cherry-pick of:
r212948 - fixes a small issue with atomic calls
Change-Id: Ib97bd980b59f18142a69506400911a6009d9df18
Diffstat (limited to 'lib/IR')
-rw-r--r-- | lib/IR/Android.mk | 1 | ||||
-rw-r--r-- | lib/IR/AsmWriter.cpp | 87 | ||||
-rw-r--r-- | lib/IR/AsmWriter.h | 4 | ||||
-rw-r--r-- | lib/IR/Attributes.cpp | 5 | ||||
-rw-r--r-- | lib/IR/AutoUpgrade.cpp | 23 | ||||
-rw-r--r-- | lib/IR/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/IR/Comdat.cpp | 25 | ||||
-rw-r--r-- | lib/IR/ConstantFold.cpp | 34 | ||||
-rw-r--r-- | lib/IR/Constants.cpp | 88 | ||||
-rw-r--r-- | lib/IR/Core.cpp | 49 | ||||
-rw-r--r-- | lib/IR/DIBuilder.cpp | 38 | ||||
-rw-r--r-- | lib/IR/DebugInfo.cpp | 38 | ||||
-rw-r--r-- | lib/IR/DebugLoc.cpp | 2 | ||||
-rw-r--r-- | lib/IR/DiagnosticInfo.cpp | 2 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 5 | ||||
-rw-r--r-- | lib/IR/GCOV.cpp | 10 | ||||
-rw-r--r-- | lib/IR/Globals.cpp | 56 | ||||
-rw-r--r-- | lib/IR/Instruction.cpp | 17 | ||||
-rw-r--r-- | lib/IR/Instructions.cpp | 41 | ||||
-rw-r--r-- | lib/IR/Metadata.cpp | 2 | ||||
-rw-r--r-- | lib/IR/Module.cpp | 50 | ||||
-rw-r--r-- | lib/IR/Pass.cpp | 30 | ||||
-rw-r--r-- | lib/IR/PassRegistry.cpp | 114 | ||||
-rw-r--r-- | lib/IR/Value.cpp | 66 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 120 |
25 files changed, 586 insertions, 322 deletions
diff --git a/lib/IR/Android.mk b/lib/IR/Android.mk index 2ffc86c..c51b241 100644 --- a/lib/IR/Android.mk +++ b/lib/IR/Android.mk @@ -5,6 +5,7 @@ vmcore_SRC_FILES := \ Attributes.cpp \ AutoUpgrade.cpp \ BasicBlock.cpp \ + Comdat.cpp \ ConstantFold.cpp \ ConstantRange.cpp \ Constants.cpp \ diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 0fef0d0..a7499bc 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -106,6 +106,7 @@ static void PrintEscapedString(StringRef Name, raw_ostream &Out) { enum PrefixType { GlobalPrefix, + ComdatPrefix, LabelPrefix, LocalPrefix, NoPrefix @@ -119,6 +120,7 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { switch (Prefix) { case NoPrefix: break; case GlobalPrefix: OS << '@'; break; + case ComdatPrefix: OS << '$'; break; case LabelPrefix: break; case LocalPrefix: OS << '%'; break; } @@ -1165,8 +1167,15 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, } void AssemblyWriter::init() { - if (TheModule) - TypePrinter.incorporateTypes(*TheModule); + if (!TheModule) + return; + TypePrinter.incorporateTypes(*TheModule); + for (const Function &F : *TheModule) + if (const Comdat *C = F.getComdat()) + Comdats.insert(C); + for (const GlobalVariable &GV : TheModule->globals()) + if (const Comdat *C = GV.getComdat()) + Comdats.insert(C); } @@ -1308,6 +1317,15 @@ void AssemblyWriter::printModule(const Module *M) { printTypeIdentities(); + // Output all comdats. + if (!Comdats.empty()) + Out << '\n'; + for (const Comdat *C : Comdats) { + printComdat(C); + if (C != Comdats.back()) + Out << '\n'; + } + // Output all globals. if (!M->global_empty()) Out << '\n'; for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); @@ -1451,10 +1469,11 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintVisibility(GV->getVisibility(), Out); PrintDLLStorageClass(GV->getDLLStorageClass(), Out); PrintThreadLocalModel(GV->getThreadLocalMode(), Out); + if (GV->hasUnnamedAddr()) + Out << "unnamed_addr "; if (unsigned AddressSpace = GV->getType()->getAddressSpace()) Out << "addrspace(" << AddressSpace << ") "; - if (GV->hasUnnamedAddr()) Out << "unnamed_addr "; if (GV->isExternallyInitialized()) Out << "externally_initialized "; Out << (GV->isConstant() ? "constant " : "global "); TypePrinter.print(GV->getType()->getElementType(), Out); @@ -1469,6 +1488,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintEscapedString(GV->getSection(), Out); Out << '"'; } + if (GV->hasComdat()) { + Out << ", comdat "; + PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix); + } if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -1488,21 +1511,18 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { } PrintVisibility(GA->getVisibility(), Out); PrintDLLStorageClass(GA->getDLLStorageClass(), Out); + PrintThreadLocalModel(GA->getThreadLocalMode(), Out); + if (GA->hasUnnamedAddr()) + Out << "unnamed_addr "; Out << "alias "; 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)); @@ -1512,6 +1532,10 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { Out << '\n'; } +void AssemblyWriter::printComdat(const Comdat *C) { + C->print(Out); +} + void AssemblyWriter::printTypeIdentities() { if (TypePrinter.NumberedTypes.empty() && TypePrinter.NamedTypes.empty()) @@ -1649,6 +1673,10 @@ void AssemblyWriter::printFunction(const Function *F) { PrintEscapedString(F->getSection(), Out); Out << '"'; } + if (F->hasComdat()) { + Out << " comdat "; + PrintLLVMName(Out, F->getComdat()->getName(), ComdatPrefix); + } if (F->getAlignment()) Out << " align " << F->getAlignment(); if (F->hasGC()) @@ -1788,6 +1816,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { (isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic())) Out << " atomic"; + if (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isWeak()) + Out << " weak"; + // If this is a volatile operation, print out the volatile marker. if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) || (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) || @@ -2157,11 +2188,32 @@ void NamedMDNode::print(raw_ostream &ROS) const { W.printNamedMDNode(this); } -void Type::print(raw_ostream &OS) const { - if (!this) { - OS << "<null Type>"; - return; +void Comdat::print(raw_ostream &ROS) const { + PrintLLVMName(ROS, getName(), ComdatPrefix); + ROS << " = comdat "; + + switch (getSelectionKind()) { + case Comdat::Any: + ROS << "any"; + break; + case Comdat::ExactMatch: + ROS << "exactmatch"; + break; + case Comdat::Largest: + ROS << "largest"; + break; + case Comdat::NoDuplicates: + ROS << "noduplicates"; + break; + case Comdat::SameSize: + ROS << "samesize"; + break; } + + ROS << '\n'; +} + +void Type::print(raw_ostream &OS) const { TypePrinting TP; TP.print(const_cast<Type*>(this), OS); @@ -2174,10 +2226,6 @@ void Type::print(raw_ostream &OS) const { } void Value::print(raw_ostream &ROS) const { - if (!this) { - ROS << "printing a <null> value\n"; - return; - } formatted_raw_ostream OS(ROS); if (const Instruction *I = dyn_cast<Instruction>(this)) { const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr; @@ -2248,5 +2296,8 @@ void Type::dump() const { print(dbgs()); } // Module::dump() - Allow printing of Modules from the debugger. void Module::dump() const { print(dbgs(), nullptr); } +// \brief Allow printing of Comdats from the debugger. +void Comdat::dump() const { print(dbgs()); } + // NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger. void NamedMDNode::dump() const { print(dbgs()); } diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h index b4ce6de..aef9c8a 100644 --- a/lib/IR/AsmWriter.h +++ b/lib/IR/AsmWriter.h @@ -16,6 +16,7 @@ #define LLVM_IR_ASSEMBLYWRITER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/TypeFinder.h" @@ -26,6 +27,7 @@ namespace llvm { class BasicBlock; class Function; class GlobalValue; +class Comdat; class Module; class NamedMDNode; class Value; @@ -70,6 +72,7 @@ private: SlotTracker &Machine; TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; + SetVector<const Comdat *> Comdats; public: /// Construct an AssemblyWriter with an external SlotTracker @@ -101,6 +104,7 @@ public: void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); void printAlias(const GlobalAlias *GV); + void printComdat(const Comdat *C); void printFunction(const Function *F); void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); void printBasicBlock(const BasicBlock *BB); diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index a9074bb..48a2ce8 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -173,6 +173,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const { return "inlinehint"; if (hasAttribute(Attribute::InReg)) return "inreg"; + if (hasAttribute(Attribute::JumpTable)) + return "jumptable"; if (hasAttribute(Attribute::MinSize)) return "minsize"; if (hasAttribute(Attribute::Naked)) @@ -291,7 +293,7 @@ bool Attribute::operator<(Attribute A) const { // AttributeImpl Definition //===----------------------------------------------------------------------===// -// Pin the vtabels to this file. +// Pin the vtables to this file. AttributeImpl::~AttributeImpl() {} void EnumAttributeImpl::anchor() {} void AlignAttributeImpl::anchor() {} @@ -395,6 +397,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { case Attribute::OptimizeNone: return 1ULL << 42; case Attribute::InAlloca: return 1ULL << 43; case Attribute::NonNull: return 1ULL << 44; + case Attribute::JumpTable: return 1ULL << 45; } llvm_unreachable("Unsupported attribute type"); } diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index e255113..6554b3c 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -114,6 +114,9 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { Name == "x86.avx.movnt.pd.256" || Name == "x86.avx.movnt.ps.256" || Name == "x86.sse42.crc32.64.8" || + Name == "x86.avx.vbroadcast.ss" || + Name == "x86.avx.vbroadcast.ss.256" || + Name == "x86.avx.vbroadcast.sd.256" || (Name.startswith("x86.xop.vpcom") && F->arg_size() == 2)) { NewFn = nullptr; return true; @@ -335,6 +338,19 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C)); Rep = Builder.CreateCall2(CRC32, Trunc0, CI->getArgOperand(1)); Rep = Builder.CreateZExt(Rep, CI->getType(), ""); + } else if (Name.startswith("llvm.x86.avx.vbroadcast")) { + // Replace broadcasts with a series of insertelements. + Type *VecTy = CI->getType(); + Type *EltTy = VecTy->getVectorElementType(); + unsigned EltNum = VecTy->getVectorNumElements(); + Value *Cast = Builder.CreateBitCast(CI->getArgOperand(0), + EltTy->getPointerTo()); + Value *Load = Builder.CreateLoad(Cast); + Type *I32Ty = Type::getInt32Ty(C); + Rep = UndefValue::get(VecTy); + for (unsigned I = 0; I < EltNum; ++I) + Rep = Builder.CreateInsertElement(Rep, Load, + ConstantInt::get(I32Ty, I)); } else { bool PD128 = false, PD256 = false, PS128 = false, PS256 = false; if (Name == "llvm.x86.avx.vpermil.pd.256") @@ -561,3 +577,10 @@ bool llvm::UpgradeDebugInfo(Module &M) { } return RetCode; } + +void llvm::UpgradeMDStringConstant(std::string &String) { + const std::string OldPrefix = "llvm.vectorizer."; + if (String.find(OldPrefix) == 0) { + String.replace(0, OldPrefix.size(), "llvm.loop.vectorize."); + } +} diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index b027ae5..38a80b1 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMCore Attributes.cpp AutoUpgrade.cpp BasicBlock.cpp + Comdat.cpp ConstantFold.cpp ConstantRange.cpp Constants.cpp diff --git a/lib/IR/Comdat.cpp b/lib/IR/Comdat.cpp new file mode 100644 index 0000000..80715ff --- /dev/null +++ b/lib/IR/Comdat.cpp @@ -0,0 +1,25 @@ +//===-- Comdat.cpp - Implement Metadata classes --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Comdat class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Comdat.h" +#include "llvm/ADT/StringMap.h" +using namespace llvm; + +Comdat::Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name) + : Name(Name), SK(SK) {} + +Comdat::Comdat(Comdat &&C) : Name(C.Name), SK(C.SK) {} + +Comdat::Comdat() : Name(nullptr), SK(Comdat::Any) {} + +StringRef Comdat::getName() const { return Name->first(); } diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 706e66f..395ac39 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -529,7 +529,10 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, // Try hard to fold cast of cast because they are often eliminable. if (unsigned newOpc = foldConstantCastPair(opc, CE, DestTy)) return ConstantExpr::getCast(newOpc, CE->getOperand(0), DestTy); - } else if (CE->getOpcode() == Instruction::GetElementPtr) { + } else if (CE->getOpcode() == Instruction::GetElementPtr && + // Do not fold addrspacecast (gep 0, .., 0). It might make the + // addrspacecast uncanonicalized. + opc != Instruction::AddrSpaceCast) { // If all of the indexes in the GEP are null values, there is no pointer // adjustment going on. We might as well cast the source pointer. bool isAllNull = true; @@ -1331,6 +1334,15 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) { return FCmpInst::BAD_FCMP_PREDICATE; } +static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1, + const GlobalValue *GV2) { + // Don't try to decide equality of aliases. + if (!isa<GlobalAlias>(GV1) && !isa<GlobalAlias>(GV2)) + if (!GV1->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) + return ICmpInst::ICMP_NE; + return ICmpInst::BAD_ICMP_PREDICATE; +} + /// evaluateICmpRelation - This function determines if there is anything we can /// decide about the two constants provided. This doesn't need to handle simple /// things like integer comparisons, but should instead handle ConstantExprs @@ -1392,10 +1404,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // constant (which, since the types must match, means that it's a // ConstantPointerNull). if (const GlobalValue *GV2 = dyn_cast<GlobalValue>(V2)) { - // Don't try to decide equality of aliases. - if (!isa<GlobalAlias>(GV) && !isa<GlobalAlias>(GV2)) - if (!GV->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) - return ICmpInst::ICMP_NE; + return areGlobalsPotentiallyEqual(GV, GV2); } else if (isa<BlockAddress>(V2)) { return ICmpInst::ICMP_NE; // Globals never equal labels. } else { @@ -1460,7 +1469,8 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, } break; - case Instruction::GetElementPtr: + case Instruction::GetElementPtr: { + GEPOperator *CE1GEP = cast<GEPOperator>(CE1); // Ok, since this is a getelementptr, we know that the constant has a // pointer type. Check the various cases. if (isa<ConstantPointerNull>(V2)) { @@ -1507,7 +1517,8 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, "Surprising getelementptr!"); return isSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; } else { - // If they are different globals, we don't know what the value is. + if (CE1GEP->hasAllZeroIndices()) + return areGlobalsPotentiallyEqual(GV, GV2); return ICmpInst::BAD_ICMP_PREDICATE; } } @@ -1523,8 +1534,14 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // By far the most common case to handle is when the base pointers are // obviously to the same global. if (isa<GlobalValue>(CE1Op0) && isa<GlobalValue>(CE2Op0)) { - if (CE1Op0 != CE2Op0) // Don't know relative ordering. + // Don't know relative ordering, but check for inequality. + if (CE1Op0 != CE2Op0) { + GEPOperator *CE2GEP = cast<GEPOperator>(CE2); + if (CE1GEP->hasAllZeroIndices() && CE2GEP->hasAllZeroIndices()) + return areGlobalsPotentiallyEqual(cast<GlobalValue>(CE1Op0), + cast<GlobalValue>(CE2Op0)); return ICmpInst::BAD_ICMP_PREDICATE; + } // Ok, we know that both getelementptr instructions are based on the // same global. From this, we can precisely determine the relative // ordering of the resultant pointers. @@ -1570,6 +1587,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, } } } + } default: break; } diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index bb8d60b..b815936 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -107,6 +107,28 @@ bool Constant::isAllOnesValue() const { return false; } +bool Constant::isMinSignedValue() const { + // Check for INT_MIN integers + if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) + return CI->isMinValue(/*isSigned=*/true); + + // Check for FP which are bitcasted from INT_MIN integers + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) + return CFP->getValueAPF().bitcastToAPInt().isMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantVector *CV = dyn_cast<ConstantVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isMinSignedValue(); + + return false; +} + // Constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(Type *Ty) { switch (Ty->getTypeID()) { @@ -278,35 +300,48 @@ bool Constant::canTrap() const { return canTrapImpl(this, NonTrappingOps); } -/// isThreadDependent - Return true if the value can vary between threads. -bool Constant::isThreadDependent() const { - SmallPtrSet<const Constant*, 64> Visited; - SmallVector<const Constant*, 64> WorkList; - WorkList.push_back(this); - Visited.insert(this); +/// Check if C contains a GlobalValue for which Predicate is true. +static bool +ConstHasGlobalValuePredicate(const Constant *C, + bool (*Predicate)(const GlobalValue *)) { + SmallPtrSet<const Constant *, 8> Visited; + SmallVector<const Constant *, 8> WorkList; + WorkList.push_back(C); + Visited.insert(C); while (!WorkList.empty()) { - const Constant *C = WorkList.pop_back_val(); - - if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { - if (GV->isThreadLocal()) + const Constant *WorkItem = WorkList.pop_back_val(); + if (const auto *GV = dyn_cast<GlobalValue>(WorkItem)) + if (Predicate(GV)) return true; - } - - for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) { - const Constant *D = dyn_cast<Constant>(C->getOperand(I)); - if (!D) + for (const Value *Op : WorkItem->operands()) { + const Constant *ConstOp = dyn_cast<Constant>(Op); + if (!ConstOp) continue; - if (Visited.insert(D)) - WorkList.push_back(D); + if (Visited.insert(ConstOp)) + WorkList.push_back(ConstOp); } } - return false; } -/// isConstantUsed - Return true if the constant has users other than constant -/// exprs and other dangling things. +/// Return true if the value can vary between threads. +bool Constant::isThreadDependent() const { + auto DLLImportPredicate = [](const GlobalValue *GV) { + return GV->isThreadLocal(); + }; + return ConstHasGlobalValuePredicate(this, DLLImportPredicate); +} + +bool Constant::isDLLImportDependent() const { + auto DLLImportPredicate = [](const GlobalValue *GV) { + return GV->hasDLLImportStorageClass(); + }; + return ConstHasGlobalValuePredicate(this, DLLImportPredicate); +} + +/// Return true if the constant has users other than constant exprs and other +/// dangling things. bool Constant::isConstantUsed() const { for (const User *U : users()) { const Constant *UC = dyn_cast<Constant>(U); @@ -1698,6 +1733,19 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) { assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) && "Invalid constantexpr addrspacecast!"); + // Canonicalize addrspacecasts between different pointer types by first + // bitcasting the pointer type and then converting the address space. + PointerType *SrcScalarTy = cast<PointerType>(C->getType()->getScalarType()); + PointerType *DstScalarTy = cast<PointerType>(DstTy->getScalarType()); + Type *DstElemTy = DstScalarTy->getElementType(); + if (SrcScalarTy->getElementType() != DstElemTy) { + Type *MidTy = PointerType::get(DstElemTy, SrcScalarTy->getAddressSpace()); + if (VectorType *VT = dyn_cast<VectorType>(DstTy)) { + // Handle vectors of pointers. + MidTy = VectorType::get(MidTy, VT->getNumElements()); + } + C = getBitCast(C, MidTy); + } return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy); } diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 27ce503..87099a6 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -17,9 +17,9 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/IRBuilder.h" @@ -35,10 +35,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include <cassert> #include <cstdlib> #include <cstring> +#include <system_error> using namespace llvm; @@ -281,7 +281,11 @@ char *LLVMPrintTypeToString(LLVMTypeRef Ty) { std::string buf; raw_string_ostream os(buf); - unwrap(Ty)->print(os); + if (unwrap(Ty)) + unwrap(Ty)->print(os); + else + os << "Printing <null> Type"; + os.flush(); return strdup(buf.c_str()); @@ -531,7 +535,11 @@ char* LLVMPrintValueToString(LLVMValueRef Val) { std::string buf; raw_string_ostream os(buf); - unwrap(Val)->print(os); + if (unwrap(Val)) + unwrap(Val)->print(os); + else + os << "Printing <null> Value"; + os.flush(); return strdup(buf.c_str()); @@ -1286,7 +1294,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) { @@ -2598,28 +2606,24 @@ LLVMBool LLVMCreateMemoryBufferWithContentsOfFile( LLVMMemoryBufferRef *OutMemBuf, char **OutMessage) { - std::unique_ptr<MemoryBuffer> MB; - error_code ec; - if (!(ec = MemoryBuffer::getFile(Path, MB))) { - *OutMemBuf = wrap(MB.release()); - return 0; + ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path); + if (std::error_code EC = MBOrErr.getError()) { + *OutMessage = strdup(EC.message().c_str()); + return 1; } - - *OutMessage = strdup(ec.message().c_str()); - return 1; + *OutMemBuf = wrap(MBOrErr.get().release()); + return 0; } LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, char **OutMessage) { - std::unique_ptr<MemoryBuffer> MB; - error_code ec; - if (!(ec = MemoryBuffer::getSTDIN(MB))) { - *OutMemBuf = wrap(MB.release()); - return 0; + ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getSTDIN(); + if (std::error_code EC = MBOrErr.getError()) { + *OutMessage = strdup(EC.message().c_str()); + return 1; } - - *OutMessage = strdup(ec.message().c_str()); - return 1; + *OutMemBuf = wrap(MBOrErr.get().release()); + return 0; } LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange( @@ -2700,11 +2704,10 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM) { /*===-- Threading ------------------------------------------------------===*/ LLVMBool LLVMStartMultithreaded() { - return llvm_start_multithreaded(); + return LLVMIsMultithreaded(); } void LLVMStopMultithreaded() { - llvm_stop_multithreaded(); } LLVMBool LLVMIsMultithreaded() { diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 92edacc..218787c 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -102,7 +102,8 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, - DebugEmissionKind Kind) { + DebugEmissionKind Kind, + bool EmitDebugInfo) { assert(((Lang <= dwarf::DW_LANG_OCaml && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && @@ -140,8 +141,14 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, MDNode *CUNode = MDNode::get(VMContext, Elts); // Create a named metadata so that it is easier to find cu in a module. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); - NMD->addOperand(CUNode); + // Note that we only generate this when the caller wants to actually + // emit debug information. When we are only interested in tracking + // source line locations throughout the backend, we prevent codegen from + // emitting debug info in the final output by not generating llvm.dbg.cu. + if (EmitDebugInfo) { + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); + NMD->addOperand(CUNode); + } return DICompileUnit(CUNode); } @@ -1068,18 +1075,19 @@ DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, DITypeRef Ty, ArrayRef<Value *> Addr, unsigned ArgNo) { - SmallVector<Value *, 15> Elts; - Elts.push_back(GetTagConstant(VMContext, Tag)); - Elts.push_back(getNonCompileUnitScope(Scope)), - Elts.push_back(MDString::get(VMContext, Name)); - Elts.push_back(F); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), - (LineNo | (ArgNo << 24)))); - Elts.push_back(Ty); - Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); - Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); - Elts.append(Addr.begin(), Addr.end()); - + assert(Addr.size() > 0 && "complex address is empty"); + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), + (LineNo | (ArgNo << 24))), + Ty, + Constant::getNullValue(Type::getInt32Ty(VMContext)), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + MDNode::get(VMContext, Addr) + }; return DIVariable(MDNode::get(VMContext, Elts)); } diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index db9e56d..5e39b24 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -138,8 +138,14 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { } } -unsigned DIVariable::getNumAddrElements() const { - return DbgNode->getNumOperands() - 8; +uint64_t DIVariable::getAddrElement(unsigned Idx) const { + DIDescriptor ComplexExpr = getDescriptorField(8); + if (Idx < ComplexExpr->getNumOperands()) + if (auto *CI = dyn_cast_or_null<ConstantInt>(ComplexExpr->getOperand(Idx))) + return CI->getZExtValue(); + + assert(false && "non-existing complex address element requested"); + return 0; } /// getInlinedAt - If this variable is inlined then return inline location. @@ -566,7 +572,13 @@ bool DIVariable::Verify() const { // Make sure that type @ field 5 is a DITypeRef. if (!fieldIsTypeRef(DbgNode, 5)) return false; - return DbgNode->getNumOperands() >= 8; + + // Variable without a complex expression. + if (DbgNode->getNumOperands() == 8) + return true; + + // Make sure the complex expression is an MDNode. + return (DbgNode->getNumOperands() == 9 && fieldIsMDNode(DbgNode, 8)); } /// Verify - Verify that a location descriptor is well formed. @@ -1514,3 +1526,23 @@ unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { return 0; return cast<ConstantInt>(Val)->getZExtValue(); } + +llvm::DenseMap<const llvm::Function *, llvm::DISubprogram> +llvm::makeSubprogramMap(const Module &M) { + DenseMap<const Function *, DISubprogram> R; + + NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu"); + if (!CU_Nodes) + return R; + + for (MDNode *N : CU_Nodes->operands()) { + DICompileUnit CUNode(N); + DIArray SPs = CUNode.getSubprograms(); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { + DISubprogram SP(SPs.getElement(i)); + if (Function *F = SP.getFunction()) + R.insert(std::make_pair(F, SP)); + } + } + return R; +} diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index 43360d3..e8bdcce 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -76,7 +76,7 @@ MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const { return getScope(Ctx); } -DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) { +DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const { const MDNode *Scope = getScopeNode(Ctx); DISubprogram SP = getDISubprogram(Scope); if (SP.isSubprogram()) { diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 6eeb162..2727063 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -128,7 +128,7 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { } bool DiagnosticInfoOptimizationRemarkBase::isLocationAvailable() const { - return getFunction().getParent()->getNamedMetadata("llvm.dbg.cu") != nullptr; + return getDebugLoc().isUnknown() == false; } void DiagnosticInfoOptimizationRemarkBase::getLocation(StringRef *Filename, diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index fe32c46..1443571 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -735,6 +735,11 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) { #include "llvm/IR/Intrinsics.gen" #undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +// This defines the "Intrinsic::getIntrinsicForMSBuiltin()" method. +#define GET_LLVM_INTRINSIC_FOR_MS_BUILTIN +#include "llvm/IR/Intrinsics.gen" +#undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN + /// hasAddressTaken - returns true if there are any uses of this function /// other than direct calls or invokes to it. bool Function::hasAddressTaken(const User* *PutOffender) const { diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp index f2099d6..1667401 100644 --- a/lib/IR/GCOV.cpp +++ b/lib/IR/GCOV.cpp @@ -19,8 +19,8 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/Path.h" -#include "llvm/Support/system_error.h" #include <algorithm> +#include <system_error> using namespace llvm; //===----------------------------------------------------------------------===// @@ -438,11 +438,15 @@ class LineConsumer { StringRef Remaining; public: LineConsumer(StringRef Filename) { - if (error_code EC = MemoryBuffer::getFileOrSTDIN(Filename, Buffer)) { + ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = BufferOrErr.getError()) { errs() << Filename << ": " << EC.message() << "\n"; Remaining = ""; - } else + } else { + Buffer = std::move(BufferOrErr.get()); Remaining = Buffer->getBuffer(); + } } bool empty() { return Remaining.empty(); } void printNext(raw_ostream &OS, uint32_t LineNum) { diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index c905cfe..244e3e4 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; @@ -59,9 +60,16 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { } unsigned GlobalValue::getAlignment() const { - if (auto *GA = dyn_cast<GlobalAlias>(this)) - return GA->getAliasee()->getAlignment(); - + if (auto *GA = dyn_cast<GlobalAlias>(this)) { + // In general we cannot compute this at the IR level, but we try. + if (const GlobalObject *GO = GA->getBaseObject()) + return GO->getAlignment(); + + // FIXME: we should also be able to handle: + // Alias = Global + Offset + // Alias = Absolute + return 0; + } return cast<GlobalObject>(this)->getAlignment(); } @@ -80,12 +88,26 @@ 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 = GA->getBaseObject()) + return GO->getSection(); + return ""; + } return cast<GlobalObject>(this)->getSection(); } +Comdat *GlobalValue::getComdat() { + if (auto *GA = dyn_cast<GlobalAlias>(this)) { + // In general we cannot compute this at the IR level, but we try. + if (const GlobalObject *GO = GA->getBaseObject()) + return const_cast<GlobalObject *>(GO)->getComdat(); + return nullptr; + } + return cast<GlobalObject>(this)->getComdat(); +} + void GlobalObject::setSection(StringRef S) { Section = S; } bool GlobalValue::isDeclaration() const { @@ -113,8 +135,9 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, : GlobalObject(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != nullptr, Link, Name), - isConstantGlobal(constant), threadLocalMode(TLMode), + isConstantGlobal(constant), isExternallyInitializedConstant(isExternallyInitialized) { + setThreadLocalMode(TLMode); if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); @@ -132,8 +155,9 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, : GlobalObject(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != nullptr, Link, Name), - isConstantGlobal(constant), threadLocalMode(TLMode), + isConstantGlobal(constant), isExternallyInitializedConstant(isExternallyInitialized) { + setThreadLocalMode(TLMode); if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); @@ -214,7 +238,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) { @@ -227,7 +251,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); } @@ -239,18 +263,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); } @@ -270,4 +294,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/Instruction.cpp b/lib/IR/Instruction.cpp index 28cc4cb..86421c4 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -145,31 +145,31 @@ void Instruction::setFastMathFlags(FastMathFlags FMF) { /// Determine whether the unsafe-algebra flag is set. bool Instruction::hasUnsafeAlgebra() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasUnsafeAlgebra(); } /// Determine whether the no-NaNs flag is set. bool Instruction::hasNoNaNs() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoNaNs(); } /// Determine whether the no-infs flag is set. bool Instruction::hasNoInfs() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoInfs(); } /// Determine whether the no-signed-zeros flag is set. bool Instruction::hasNoSignedZeros() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoSignedZeros(); } /// Determine whether the allow-reciprocal flag is set. bool Instruction::hasAllowReciprocal() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasAllowReciprocal(); } @@ -177,7 +177,7 @@ bool Instruction::hasAllowReciprocal() const { /// operator which supports these flags. See LangRef.html for the meaning of /// these flats. FastMathFlags Instruction::getFastMathFlags() const { - assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->getFastMathFlags(); } @@ -300,6 +300,7 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2, FI->getSynchScope() == cast<FenceInst>(I2)->getSynchScope(); if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1)) return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I2)->isVolatile() && + CXI->isWeak() == cast<AtomicCmpXchgInst>(I2)->isWeak() && CXI->getSuccessOrdering() == cast<AtomicCmpXchgInst>(I2)->getSuccessOrdering() && CXI->getFailureOrdering() == @@ -331,6 +332,10 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const { getType() != I->getType()) return false; + // If both instructions have no operands, they are identical. + if (getNumOperands() == 0 && I->getNumOperands() == 0) + return haveSameSpecialState(this, I); + // We have two instructions of identical opcode and #operands. Check to see // if all operands are the same. if (!std::equal(op_begin(), op_end(), I->op_begin())) diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 13c51b8..a5ceacb 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -248,7 +248,7 @@ void LandingPadInst::growOperands(unsigned Size) { Use::zap(OldOps, OldOps + e, true); } -void LandingPadInst::addClause(Value *Val) { +void LandingPadInst::addClause(Constant *Val) { unsigned OpNo = getNumOperands(); growOperands(1); assert(OpNo < ReservedSpace && "Growing didn't work!"); @@ -1251,10 +1251,11 @@ AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope, Instruction *InsertBefore) - : Instruction(Cmp->getType(), AtomicCmpXchg, - OperandTraits<AtomicCmpXchgInst>::op_begin(this), - OperandTraits<AtomicCmpXchgInst>::operands(this), - InsertBefore) { + : Instruction( + StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext()), + nullptr), + AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this), + OperandTraits<AtomicCmpXchgInst>::operands(this), InsertBefore) { Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SynchScope); } @@ -1263,13 +1264,14 @@ AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope, BasicBlock *InsertAtEnd) - : Instruction(Cmp->getType(), AtomicCmpXchg, - OperandTraits<AtomicCmpXchgInst>::op_begin(this), - OperandTraits<AtomicCmpXchgInst>::operands(this), - InsertAtEnd) { + : Instruction( + StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext()), + nullptr), + AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this), + OperandTraits<AtomicCmpXchgInst>::operands(this), InsertAtEnd) { Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SynchScope); } - + //===----------------------------------------------------------------------===// // AtomicRMWInst Implementation //===----------------------------------------------------------------------===// @@ -2331,18 +2333,12 @@ unsigned CastInst::isEliminableCastPair( // Allowed, use first cast's opcode return firstOp; case 14: - // FIXME: this state can be merged with (2), but the following assert - // is useful to check the correcteness of the sequence due to semantic - // change of bitcast. - assert( - SrcTy->isPtrOrPtrVectorTy() && - MidTy->isPtrOrPtrVectorTy() && - DstTy->isPtrOrPtrVectorTy() && - SrcTy->getPointerAddressSpace() == MidTy->getPointerAddressSpace() && - MidTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace() && - "Illegal bitcast, addrspacecast sequence!"); - // Allowed, use second cast's opcode - return secondOp; + // bitcast, addrspacecast -> addrspacecast if the element type of + // bitcast's source is the same as that of addrspacecast's destination. + if (SrcTy->getPointerElementType() == DstTy->getPointerElementType()) + return Instruction::AddrSpaceCast; + return 0; + case 15: // FIXME: this state can be merged with (1), but the following assert // is useful to check the correcteness of the sequence due to semantic @@ -3610,6 +3606,7 @@ AtomicCmpXchgInst *AtomicCmpXchgInst::clone_impl() const { getSuccessOrdering(), getFailureOrdering(), getSynchScope()); Result->setVolatile(isVolatile()); + Result->setWeak(isWeak()); return Result; } diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 4d932d0..59137e4 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -663,7 +663,7 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Otherwise, we're removing metadata from an instruction. assert((hasMetadataHashEntry() == - getContext().pImpl->MetadataStore.count(this)) && + (getContext().pImpl->MetadataStore.count(this) > 0)) && "HasMetadata bit out of date!"); if (!hasMetadataHashEntry()) return; // Nothing to remove! diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 5dbed69..f1b1f9a 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -24,6 +24,8 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LeakDetector.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/RandomNumberGenerator.h" #include <algorithm> #include <cstdarg> #include <cstdlib> @@ -44,7 +46,7 @@ template class llvm::SymbolTableListTraits<GlobalAlias, Module>; // Module::Module(StringRef MID, LLVMContext &C) - : Context(C), Materializer(), ModuleID(MID), DL("") { + : Context(C), Materializer(), ModuleID(MID), RNG(nullptr), DL("") { ValSymTab = new ValueSymbolTable(); NamedMDSymTab = new StringMap<NamedMDNode *>(); Context.addModule(this); @@ -59,6 +61,7 @@ Module::~Module() { NamedMDList.clear(); delete ValSymTab; delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab); + delete RNG; } /// getNamedValue - Return the first global value in the module with @@ -355,6 +358,16 @@ const DataLayout *Module::getDataLayout() const { return &DL; } +// We want reproducible builds, but ModuleID may be a full path so we just use +// the filename to salt the RNG (although it is not guaranteed to be unique). +RandomNumberGenerator &Module::getRNG() const { + if (RNG == nullptr) { + StringRef Salt = sys::path::filename(ModuleID); + RNG = new RandomNumberGenerator(Salt); + } + return *RNG; +} + //===----------------------------------------------------------------------===// // Methods to control the materialization of GlobalValues in the Module. // @@ -381,7 +394,7 @@ bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) { if (!Materializer) return false; - error_code EC = Materializer->Materialize(GV); + std::error_code EC = Materializer->Materialize(GV); if (!EC) return false; if (ErrInfo) @@ -394,18 +407,21 @@ void Module::Dematerialize(GlobalValue *GV) { return Materializer->Dematerialize(GV); } -error_code Module::materializeAll() { +std::error_code Module::materializeAll() { if (!Materializer) - return error_code::success(); + return std::error_code(); return Materializer->MaterializeModule(this); } -error_code Module::materializeAllPermanently() { - if (error_code EC = materializeAll()) +std::error_code Module::materializeAllPermanently(bool ReleaseBuffer) { + if (std::error_code EC = materializeAll()) return EC; + if (ReleaseBuffer) + Materializer->releaseBuffer(); + Materializer.reset(); - return error_code::success(); + return std::error_code(); } //===----------------------------------------------------------------------===// @@ -421,14 +437,14 @@ error_code Module::materializeAllPermanently() { // has "dropped all references", except operator delete. // void Module::dropAllReferences() { - for(Module::iterator I = begin(), E = end(); I != E; ++I) - I->dropAllReferences(); + for (Function &F : *this) + F.dropAllReferences(); - for(Module::global_iterator I = global_begin(), E = global_end(); I != E; ++I) - I->dropAllReferences(); + for (GlobalVariable &GV : globals()) + GV.dropAllReferences(); - for(Module::alias_iterator I = alias_begin(), E = alias_end(); I != E; ++I) - I->dropAllReferences(); + for (GlobalAlias &GA : aliases()) + GA.dropAllReferences(); } unsigned Module::getDwarfVersion() const { @@ -437,3 +453,11 @@ unsigned Module::getDwarfVersion() const { return dwarf::DWARF_VERSION; return cast<ConstantInt>(Val)->getZExtValue(); } + +Comdat *Module::getOrInsertComdat(StringRef Name) { + Comdat C; + StringMapEntry<Comdat> &Entry = + ComdatSymTab.GetOrCreateValue(Name, std::move(C)); + Entry.second.Name = &Entry; + return &Entry.second; +} diff --git a/lib/IR/Pass.cpp b/lib/IR/Pass.cpp index bb55d2a..91d86ae 100644 --- a/lib/IR/Pass.cpp +++ b/lib/IR/Pass.cpp @@ -199,14 +199,6 @@ Pass *Pass::createPass(AnalysisID ID) { return PI->createPass(); } -Pass *PassInfo::createPass() const { - assert((!isAnalysisGroup() || NormalCtor) && - "No default implementation found for analysis group!"); - assert(NormalCtor && - "Cannot call createPass on PassInfo without default ctor!"); - return NormalCtor(); -} - //===----------------------------------------------------------------------===// // Analysis Group Implementation Code //===----------------------------------------------------------------------===// @@ -224,17 +216,6 @@ RegisterAGBase::RegisterAGBase(const char *Name, const void *InterfaceID, // PassRegistrationListener implementation // -// PassRegistrationListener ctor - Add the current object to the list of -// PassRegistrationListeners... -PassRegistrationListener::PassRegistrationListener() { - PassRegistry::getPassRegistry()->addRegistrationListener(this); -} - -// dtor - Remove object from list of listeners... -PassRegistrationListener::~PassRegistrationListener() { - PassRegistry::getPassRegistry()->removeRegistrationListener(this); -} - // enumeratePasses - Iterate over the registered passes, calling the // passEnumerate callback on each PassInfo object. // @@ -242,7 +223,16 @@ void PassRegistrationListener::enumeratePasses() { PassRegistry::getPassRegistry()->enumerateWith(this); } -PassNameParser::~PassNameParser() {} +PassNameParser::PassNameParser() + : Opt(nullptr) { + PassRegistry::getPassRegistry()->addRegistrationListener(this); +} + +PassNameParser::~PassNameParser() { + // This only gets called during static destruction, in which case the + // PassRegistry will have already been destroyed by llvm_shutdown(). So + // attempting to remove the registration listener is an error. +} //===----------------------------------------------------------------------===// // AnalysisUsage Class Implementation diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index 6a5bee2..91940a9 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -13,14 +13,10 @@ //===----------------------------------------------------------------------===// #include "llvm/PassRegistry.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringMap.h" #include "llvm/IR/Function.h" #include "llvm/PassSupport.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Mutex.h" #include "llvm/Support/RWMutex.h" #include <vector> @@ -36,62 +32,23 @@ PassRegistry *PassRegistry::getPassRegistry() { return &*PassRegistryObj; } -static ManagedStatic<sys::SmartRWMutex<true> > Lock; - -//===----------------------------------------------------------------------===// -// PassRegistryImpl -// - -namespace { -struct PassRegistryImpl { - /// PassInfoMap - Keep track of the PassInfo object for each registered pass. - typedef DenseMap<const void*, const PassInfo*> MapType; - MapType PassInfoMap; - - typedef StringMap<const PassInfo*> StringMapType; - StringMapType PassInfoStringMap; - - /// AnalysisGroupInfo - Keep track of information for each analysis group. - struct AnalysisGroupInfo { - SmallPtrSet<const PassInfo *, 8> Implementations; - }; - DenseMap<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap; - - std::vector<std::unique_ptr<const PassInfo>> ToFree; - std::vector<PassRegistrationListener*> Listeners; -}; -} // end anonymous namespace - -void *PassRegistry::getImpl() const { - if (!pImpl) - pImpl = new PassRegistryImpl(); - return pImpl; -} - //===----------------------------------------------------------------------===// // Accessors // PassRegistry::~PassRegistry() { - sys::SmartScopedWriter<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(pImpl); - delete Impl; - pImpl = nullptr; } const PassInfo *PassRegistry::getPassInfo(const void *TI) const { - sys::SmartScopedReader<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.find(TI); - return I != Impl->PassInfoMap.end() ? I->second : nullptr; + sys::SmartScopedReader<true> Guard(Lock); + MapType::const_iterator I = PassInfoMap.find(TI); + return I != PassInfoMap.end() ? I->second : nullptr; } const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { - sys::SmartScopedReader<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - PassRegistryImpl::StringMapType::const_iterator - I = Impl->PassInfoStringMap.find(Arg); - return I != Impl->PassInfoStringMap.end() ? I->second : nullptr; + sys::SmartScopedReader<true> Guard(Lock); + StringMapType::const_iterator I = PassInfoStringMap.find(Arg); + return I != PassInfoStringMap.end() ? I->second : nullptr; } //===----------------------------------------------------------------------===// @@ -99,39 +56,34 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { // void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { - sys::SmartScopedWriter<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); + sys::SmartScopedWriter<true> Guard(Lock); bool Inserted = - Impl->PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; + PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; assert(Inserted && "Pass registered multiple times!"); (void)Inserted; - Impl->PassInfoStringMap[PI.getPassArgument()] = &PI; + PassInfoStringMap[PI.getPassArgument()] = &PI; // Notify any listeners. for (std::vector<PassRegistrationListener*>::iterator - I = Impl->Listeners.begin(), E = Impl->Listeners.end(); I != E; ++I) + I = Listeners.begin(), E = Listeners.end(); I != E; ++I) (*I)->passRegistered(&PI); - if (ShouldFree) Impl->ToFree.push_back(std::unique_ptr<const PassInfo>(&PI)); + if (ShouldFree) ToFree.push_back(std::unique_ptr<const PassInfo>(&PI)); } void PassRegistry::unregisterPass(const PassInfo &PI) { - sys::SmartScopedWriter<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - PassRegistryImpl::MapType::iterator I = - Impl->PassInfoMap.find(PI.getTypeInfo()); - assert(I != Impl->PassInfoMap.end() && "Pass registered but not in map!"); + sys::SmartScopedWriter<true> Guard(Lock); + MapType::iterator I = PassInfoMap.find(PI.getTypeInfo()); + assert(I != PassInfoMap.end() && "Pass registered but not in map!"); // Remove pass from the map. - Impl->PassInfoMap.erase(I); - Impl->PassInfoStringMap.erase(PI.getPassArgument()); + PassInfoMap.erase(I); + PassInfoStringMap.erase(PI.getPassArgument()); } void PassRegistry::enumerateWith(PassRegistrationListener *L) { - sys::SmartScopedReader<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - for (PassRegistryImpl::MapType::const_iterator I = Impl->PassInfoMap.begin(), - E = Impl->PassInfoMap.end(); I != E; ++I) + sys::SmartScopedReader<true> Guard(Lock); + for (auto I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I) L->passEnumerate(I->second); } @@ -156,15 +108,13 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID, assert(ImplementationInfo && "Must register pass before adding to AnalysisGroup!"); - sys::SmartScopedWriter<true> Guard(*Lock); + sys::SmartScopedWriter<true> Guard(Lock); // Make sure we keep track of the fact that the implementation implements // the interface. ImplementationInfo->addInterfaceImplemented(InterfaceInfo); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - PassRegistryImpl::AnalysisGroupInfo &AGI = - Impl->AnalysisGroupInfoMap[InterfaceInfo]; + AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo]; assert(AGI.Implementations.count(ImplementationInfo) == 0 && "Cannot add a pass to the same analysis group more than once!"); AGI.Implementations.insert(ImplementationInfo); @@ -179,30 +129,18 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID, } } - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); if (ShouldFree) - Impl->ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree)); + ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree)); } void PassRegistry::addRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedWriter<true> Guard(*Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - Impl->Listeners.push_back(L); + sys::SmartScopedWriter<true> Guard(Lock); + Listeners.push_back(L); } void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) { - sys::SmartScopedWriter<true> Guard(*Lock); - - // NOTE: This is necessary, because removeRegistrationListener() can be called - // as part of the llvm_shutdown sequence. Since we have no control over the - // order of that sequence, we need to gracefully handle the case where the - // PassRegistry is destructed before the object that triggers this call. - if (!pImpl) return; + sys::SmartScopedWriter<true> Guard(Lock); - PassRegistryImpl *Impl = static_cast<PassRegistryImpl*>(getImpl()); - std::vector<PassRegistrationListener*>::iterator I = - std::find(Impl->Listeners.begin(), Impl->Listeners.end(), L); - assert(I != Impl->Listeners.end() && - "PassRegistrationListener not registered!"); - Impl->Listeners.erase(I); + auto I = std::find(Listeners.begin(), Listeners.end(), L); + Listeners.erase(I); } diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index d734e4e..35c241a 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/InstrTypes.h" @@ -38,13 +39,12 @@ using namespace llvm; static inline Type *checkType(Type *Ty) { assert(Ty && "Value defined with a null type: Error!"); - return const_cast<Type*>(Ty); + return Ty; } Value::Value(Type *ty, unsigned scid) - : SubclassID(scid), HasValueHandle(0), - SubclassOptionalData(0), SubclassData(0), VTy((Type*)checkType(ty)), - UseList(nullptr), Name(nullptr) { + : VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid), + HasValueHandle(0), SubclassOptionalData(0), SubclassData(0) { // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa<CallInst> before the CallInst has been // constructed. @@ -214,7 +214,7 @@ void Value::setName(const Twine &NewName) { // then reallocated. // Create the new name. - Name = ValueName::Create(NameRef.begin(), NameRef.end()); + Name = ValueName::Create(NameRef); Name->setValue(this); return; } @@ -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; @@ -498,18 +473,33 @@ Value *Value::stripInBoundsOffsets() { /// isDereferenceablePointer - Test if this value is always a pointer to /// allocated and suitably aligned memory for a simple load or store. -static bool isDereferenceablePointer(const Value *V, +static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, SmallPtrSet<const Value *, 32> &Visited) { // Note that it is not safe to speculate into a malloc'd region because // malloc may return null. - // It's also not always safe to follow a bitcast, for example: - // bitcast i8* (alloca i8) to i32* - // would result in a 4-byte load from a 1-byte alloca. Some cases could - // be handled using DataLayout to check sizes and alignments though. // These are obviously ok. if (isa<AllocaInst>(V)) return true; + // It's not always safe to follow a bitcast, for example: + // bitcast i8* (alloca i8) to i32* + // would result in a 4-byte load from a 1-byte alloca. However, + // if we're casting from a pointer from a type of larger size + // to a type of smaller size (or the same size), and the alignment + // is at least as large as for the resulting pointer type, then + // we can look through the bitcast. + if (DL) + if (const BitCastInst* BC = dyn_cast<BitCastInst>(V)) { + Type *STy = BC->getSrcTy()->getPointerElementType(), + *DTy = BC->getDestTy()->getPointerElementType(); + if (STy->isSized() && DTy->isSized() && + (DL->getTypeStoreSize(STy) >= + DL->getTypeStoreSize(DTy)) && + (DL->getABITypeAlignment(STy) >= + DL->getABITypeAlignment(DTy))) + return isDereferenceablePointer(BC->getOperand(0), DL, Visited); + } + // Global variables which can't collapse to null are ok. if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) return !GV->hasExternalWeakLinkage(); @@ -523,7 +513,7 @@ static bool isDereferenceablePointer(const Value *V, // Conservatively require that the base pointer be fully dereferenceable. if (!Visited.insert(GEP->getOperand(0))) return false; - if (!isDereferenceablePointer(GEP->getOperand(0), Visited)) + if (!isDereferenceablePointer(GEP->getOperand(0), DL, Visited)) return false; // Check the indices. gep_type_iterator GTI = gep_type_begin(GEP); @@ -559,9 +549,9 @@ static bool isDereferenceablePointer(const Value *V, /// isDereferenceablePointer - Test if this value is always a pointer to /// allocated and suitably aligned memory for a simple load or store. -bool Value::isDereferenceablePointer() const { +bool Value::isDereferenceablePointer(const DataLayout *DL) const { SmallPtrSet<const Value *, 32> Visited; - return ::isDereferenceablePointer(this, Visited); + return ::isDereferenceablePointer(this, DL, Visited); } /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index bcc38c1..314bad3 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -107,6 +107,12 @@ struct VerifierSupport { OS << ' ' << *T; } + void WriteComdat(const Comdat *C) { + if (!C) + return; + OS << *C; + } + // CheckFailed - A check failed, so print out the condition and the message // that failed. This provides a nice place to put a breakpoint if you want // to see why something is not correct. @@ -138,6 +144,12 @@ struct VerifierSupport { WriteType(T3); Broken = true; } + + void CheckFailed(const Twine &Message, const Comdat *C) { + OS << Message.str() << "\n"; + WriteComdat(C); + Broken = true; + } }; class Verifier : public InstVisitor<Verifier>, VerifierSupport { friend class InstVisitor<Verifier>; @@ -230,6 +242,9 @@ public: I != E; ++I) visitNamedMDNode(*I); + for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) + visitComdat(SMEC.getValue()); + visitModuleFlags(M); visitModuleIdents(M); @@ -241,8 +256,12 @@ 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 visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); void visitModuleFlags(const Module &M); void visitModuleFlag(const MDNode *Op, @@ -384,6 +403,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { "'common' global must have a zero initializer!", &GV); Assert1(!GV.isConstant(), "'common' global may not be marked constant!", &GV); + Assert1(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV); } } else { Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), @@ -474,36 +494,57 @@ 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); + } else { + // Only continue verifying subexpressions of GlobalAliases. + // Do not recurse into global initializers. + return; + } + } + + 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); - + "Alias should have private, internal, linkonce, weak, linkonce_odr, " + "weak_odr, or external linkage!", + &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(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); } @@ -556,6 +597,22 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) { } } +void Verifier::visitComdat(const Comdat &C) { + // All Comdat::SelectionKind values other than Comdat::Any require a + // GlobalValue with the same name as the Comdat. + const GlobalValue *GV = M->getNamedValue(C.getName()); + if (C.getSelectionKind() != Comdat::Any) + Assert1(GV, + "comdat selection kind requires a global value with the same name", + &C); + // The Module is invalid if the GlobalValue has local linkage. Allowing + // otherwise opens us up to seeing the underling global value get renamed if + // collisions occur. + if (GV) + Assert1(!GV->hasLocalLinkage(), "comdat global value has local linkage", + GV); +} + void Verifier::visitModuleIdents(const Module &M) { const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); if (!Idents) @@ -716,7 +773,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx, I->getKindAsEnum() == Attribute::Builtin || I->getKindAsEnum() == Attribute::NoBuiltin || I->getKindAsEnum() == Attribute::Cold || - I->getKindAsEnum() == Attribute::OptimizeNone) { + I->getKindAsEnum() == Attribute::OptimizeNone || + I->getKindAsEnum() == Attribute::JumpTable) { if (!isFunction) { CheckFailed("Attribute '" + I->getAsString() + "' only applies to functions!", V); @@ -890,6 +948,14 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, Attribute::MinSize), "Attributes 'minsize and optnone' are incompatible!", V); } + + if (Attrs.hasAttribute(AttributeSet::FunctionIndex, + Attribute::JumpTable)) { + const GlobalValue *GV = cast<GlobalValue>(V); + Assert1(GV->hasUnnamedAddr(), + "Attribute 'jumptable' requires 'unnamed_addr'", V); + + } } void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) { @@ -2058,8 +2124,7 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { Assert1(isa<Constant>(PersonalityFn), "Personality function is not constant!", &LPI); for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { - Value *Clause = LPI.getClause(i); - Assert1(isa<Constant>(Clause), "Clause is not constant!", &LPI); + Constant *Clause = LPI.getClause(i); if (LPI.isCatch(i)) { Assert1(isa<PointerType>(Clause->getType()), "Catch operand does not have pointer type!", &LPI); @@ -2203,7 +2268,8 @@ void Verifier::visitInstruction(Instruction &I) { } MDNode *MD = I.getMetadata(LLVMContext::MD_range); - Assert1(!MD || isa<LoadInst>(I), "Ranges are only for loads!", &I); + Assert1(!MD || isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I), + "Ranges are only for loads, calls and invokes!", &I); InstsInThisBlock.insert(&I); } |