diff options
author | dim <dim@FreeBSD.org> | 2012-08-15 19:34:23 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-08-15 19:34:23 +0000 |
commit | 721c201bd55ffb73cb2ba8d39e0570fa38c44e15 (patch) | |
tree | eacfc83d988e4b9d11114387ae7dc41243f2a363 /lib/VMCore | |
parent | 2b2816e083a455f7a656ae88b0fd059d1688bb36 (diff) | |
download | FreeBSD-src-721c201bd55ffb73cb2ba8d39e0570fa38c44e15.zip FreeBSD-src-721c201bd55ffb73cb2ba8d39e0570fa38c44e15.tar.gz |
Vendor import of llvm trunk r161861:
http://llvm.org/svn/llvm-project/llvm/trunk@161861
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 80 | ||||
-rw-r--r-- | lib/VMCore/Attributes.cpp | 32 | ||||
-rw-r--r-- | lib/VMCore/AutoUpgrade.cpp | 219 | ||||
-rw-r--r-- | lib/VMCore/CMakeLists.txt | 14 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 69 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 315 | ||||
-rw-r--r-- | lib/VMCore/Core.cpp | 21 | ||||
-rw-r--r-- | lib/VMCore/DIBuilder.cpp | 1019 | ||||
-rw-r--r-- | lib/VMCore/DebugInfo.cpp | 1168 | ||||
-rw-r--r-- | lib/VMCore/DebugLoc.cpp | 42 | ||||
-rw-r--r-- | lib/VMCore/Dominators.cpp | 83 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 243 | ||||
-rw-r--r-- | lib/VMCore/GCOV.cpp | 28 | ||||
-rw-r--r-- | lib/VMCore/Globals.cpp | 12 | ||||
-rw-r--r-- | lib/VMCore/IRBuilder.cpp | 14 | ||||
-rw-r--r-- | lib/VMCore/Instruction.cpp | 53 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 40 | ||||
-rw-r--r-- | lib/VMCore/Metadata.cpp | 165 | ||||
-rw-r--r-- | lib/VMCore/Module.cpp | 162 | ||||
-rw-r--r-- | lib/VMCore/PassManager.cpp | 23 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 30 | ||||
-rw-r--r-- | lib/VMCore/TypeFinder.cpp | 148 | ||||
-rw-r--r-- | lib/VMCore/Value.cpp | 9 | ||||
-rw-r--r-- | lib/VMCore/ValueTypes.cpp | 8 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 488 |
25 files changed, 3684 insertions, 801 deletions
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 7b39efb..7ef1131 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -20,11 +20,13 @@ #include "llvm/LLVMContext.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" +#include "llvm/DebugInfo.h" #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" #include "llvm/IntrinsicInst.h" #include "llvm/Operator.h" #include "llvm/Module.h" +#include "llvm/TypeFinder.h" #include "llvm/ValueSymbolTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" @@ -99,7 +101,11 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { bool NeedsQuotes = isdigit(Name[0]); if (!NeedsQuotes) { for (unsigned i = 0, e = Name.size(); i != e; ++i) { - char C = Name[i]; + // By making this unsigned, the value passed in to isalnum will always be + // in the range 0-255. This is important when building with MSVC because + // its implementation will assert. This situation can arise when dealing + // with UTF-8 multibyte characters. + unsigned char C = Name[i]; if (!isalnum(C) && C != '-' && C != '.' && C != '_') { NeedsQuotes = true; break; @@ -140,7 +146,7 @@ class TypePrinting { public: /// NamedTypes - The named types that are used by the current module. - std::vector<StructType*> NamedTypes; + TypeFinder NamedTypes; /// NumberedTypes - The numbered types, along with their value. DenseMap<StructType*, unsigned> NumberedTypes; @@ -159,7 +165,7 @@ public: void TypePrinting::incorporateTypes(const Module &M) { - M.findUsedStructTypes(NamedTypes); + NamedTypes.run(M, false); // The list of struct types we got back includes all the struct types, split // the unnamed ones out to a numbering and remove the anonymous structs. @@ -708,8 +714,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { - if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf || - &CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle || + if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEsingle || &CFP->getValueAPF().getSemantics() == &APFloat::IEEEdouble) { // We would like to output the FP constant value in exponential notation, // but we cannot do this if doing so will lose precision. Check here to @@ -759,16 +764,20 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, return; } - // Some form of long double. These appear as a magic letter identifying - // the type, then a fixed number of hex digits. + // Either half, or some form of long double. + // These appear as a magic letter identifying the type, then a + // fixed number of hex digits. Out << "0x"; + // Bit position, in the current word, of the next nibble to print. + int shiftcount; + if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) { Out << 'K'; // api needed to prevent premature destruction APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t* p = api.getRawData(); uint64_t word = p[1]; - int shiftcount=12; + shiftcount = 12; int width = api.getBitWidth(); for (int j=0; j<width; j+=4, shiftcount-=4) { unsigned int nibble = (word>>shiftcount) & 15; @@ -784,17 +793,21 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } } return; - } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad) { + shiftcount = 60; Out << 'L'; - else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) { + shiftcount = 60; Out << 'M'; - else + } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEhalf) { + shiftcount = 12; + Out << 'H'; + } else llvm_unreachable("Unsupported floating point type"); // api needed to prevent premature destruction APInt api = CFP->getValueAPF().bitcastToAPInt(); const uint64_t* p = api.getRawData(); uint64_t word = *p; - int shiftcount=60; int width = api.getBitWidth(); for (int j=0; j<width; j+=4, shiftcount-=4) { unsigned int nibble = (word>>shiftcount) & 15; @@ -1369,6 +1382,26 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis, } } +static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM, + formatted_raw_ostream &Out) { + switch (TLM) { + case GlobalVariable::NotThreadLocal: + break; + case GlobalVariable::GeneralDynamicTLSModel: + Out << "thread_local "; + break; + case GlobalVariable::LocalDynamicTLSModel: + Out << "thread_local(localdynamic) "; + break; + case GlobalVariable::InitialExecTLSModel: + Out << "thread_local(initialexec) "; + break; + case GlobalVariable::LocalExecTLSModel: + Out << "thread_local(localexec) "; + break; + } +} + void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->isMaterializable()) Out << "; Materializable\n"; @@ -1381,8 +1414,8 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintLinkage(GV->getLinkage(), Out); PrintVisibility(GV->getVisibility(), Out); + PrintThreadLocalModel(GV->getThreadLocalMode(), Out); - if (GV->isThreadLocal()) Out << "thread_local "; if (unsigned AddressSpace = GV->getType()->getAddressSpace()) Out << "addrspace(" << AddressSpace << ") "; if (GV->hasUnnamedAddr()) Out << "unnamed_addr "; @@ -2004,19 +2037,22 @@ static void WriteMDNodeComment(const MDNode *Node, formatted_raw_ostream &Out) { if (Node->getNumOperands() < 1) return; - ConstantInt *CI = dyn_cast_or_null<ConstantInt>(Node->getOperand(0)); - if (!CI) return; - APInt Val = CI->getValue(); - APInt Tag = Val & ~APInt(Val.getBitWidth(), LLVMDebugVersionMask); - if (Val.ult(LLVMDebugVersion11)) + + Value *Op = Node->getOperand(0); + if (!Op || !isa<ConstantInt>(Op) || cast<ConstantInt>(Op)->getBitWidth() < 32) + return; + + DIDescriptor Desc(Node); + if (Desc.getVersion() < LLVMDebugVersion11) return; + unsigned Tag = Desc.getTag(); Out.PadToColumn(50); - if (Tag == dwarf::DW_TAG_user_base) + if (dwarf::TagString(Tag)) { + Out << "; "; + Desc.print(Out); + } else if (Tag == dwarf::DW_TAG_user_base) { Out << "; [ DW_TAG_user_base ]"; - else if (Tag.isIntN(32)) { - if (const char *TagName = dwarf::TagString(Tag.getZExtValue())) - Out << "; [ " << TagName << " ]"; } } diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index c05132b..c8219eb 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -88,6 +88,9 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += utostr(Attribute::getAlignmentFromAttrs(Attrs)); Result += " "; } + if (Attrs & Attribute::IANSDialect) + Result += "ia_nsdialect "; + // Trim the trailing space. assert(!Result.empty() && "Unknown attribute!"); Result.erase(Result.end()-1); @@ -131,8 +134,8 @@ class AttributeListImpl : public FoldingSetNode { public: SmallVector<AttributeWithIndex, 4> Attrs; - AttributeListImpl(const AttributeWithIndex *Attr, unsigned NumAttrs) - : Attrs(Attr, Attr+NumAttrs) { + AttributeListImpl(ArrayRef<AttributeWithIndex> attrs) + : Attrs(attrs.begin(), attrs.end()) { RefCount = 0; } @@ -150,13 +153,12 @@ public: } void Profile(FoldingSetNodeID &ID) const { - Profile(ID, Attrs.data(), Attrs.size()); + Profile(ID, Attrs); } - static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr, - unsigned NumAttrs) { - for (unsigned i = 0; i != NumAttrs; ++i) { - ID.AddInteger(Attr[i].Attrs.Raw()); - ID.AddInteger(Attr[i].Index); + static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeWithIndex> Attrs){ + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { + ID.AddInteger(Attrs[i].Attrs.Raw()); + ID.AddInteger(Attrs[i].Index); } } }; @@ -168,13 +170,13 @@ AttributeListImpl::~AttributeListImpl() { } -AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) { +AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) { // If there are no attributes then return a null AttributesList pointer. - if (NumAttrs == 0) + if (Attrs.empty()) return AttrListPtr(); #ifndef NDEBUG - for (unsigned i = 0; i != NumAttrs; ++i) { + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { assert(Attrs[i].Attrs != Attribute::None && "Pointless attribute!"); assert((!i || Attrs[i-1].Index < Attrs[i].Index) && @@ -184,7 +186,7 @@ AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) // Otherwise, build a key to look up the existing attributes. FoldingSetNodeID ID; - AttributeListImpl::Profile(ID, Attrs, NumAttrs); + AttributeListImpl::Profile(ID, Attrs); void *InsertPos; sys::SmartScopedLock<true> Lock(*ALMutex); @@ -195,7 +197,7 @@ AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) // If we didn't find any existing attributes of the same shape then // create a new one and insert it. if (!PAL) { - PAL = new AttributeListImpl(Attrs, NumAttrs); + PAL = new AttributeListImpl(Attrs); AttributesLists->InsertNode(PAL, InsertPos); } @@ -308,7 +310,7 @@ AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { OldAttrList.begin()+i, OldAttrList.end()); } - return get(NewAttrList.data(), NewAttrList.size()); + return get(NewAttrList); } AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { @@ -343,7 +345,7 @@ AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { NewAttrList.insert(NewAttrList.end(), OldAttrList.begin()+i, OldAttrList.end()); - return get(NewAttrList.data(), NewAttrList.size()); + return get(NewAttrList); } void AttrListPtr::dump() const { diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index 2e16372..094ca75 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -14,17 +14,32 @@ #include "llvm/AutoUpgrade.h" #include "llvm/Constants.h" #include "llvm/Function.h" +#include "llvm/IRBuilder.h" #include "llvm/Instruction.h" +#include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/IRBuilder.h" #include <cstring> using namespace llvm; +// Upgrade the declarations of the SSE4.1 functions whose arguments have +// changed their type from v4f32 to v2i64. +static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID, + Function *&NewFn) { + // Check whether this is an old version of the function, which received + // v4f32 arguments. + Type *Arg0Type = F->getFunctionType()->getParamType(0); + if (Arg0Type != VectorType::get(Type::getFloatTy(F->getContext()), 4)) + return false; + + // Yes, it's old, replace it with new version. + F->setName(F->getName() + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), IID); + return true; +} static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { assert(F && "Illegal to upgrade a non-existent Function."); @@ -37,6 +52,27 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { switch (Name[0]) { default: break; + case 'a': { + if (Name.startswith("arm.neon.vclz")) { + Type* args[2] = { + F->arg_begin()->getType(), + Type::getInt1Ty(F->getContext()) + }; + // Can't use Intrinsic::getDeclaration here as it adds a ".i1" to + // the end of the name. Change name from llvm.arm.neon.vclz.* to + // llvm.ctlz.* + FunctionType* fType = FunctionType::get(F->getReturnType(), args, false); + NewFn = Function::Create(fType, F->getLinkage(), + "llvm.ctlz." + Name.substr(14), F->getParent()); + return true; + } + if (Name.startswith("arm.neon.vcnt")) { + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop, + F->arg_begin()->getType()); + return true; + } + break; + } case 'c': { if (Name.startswith("ctlz.") && F->arg_size() == 1) { F->setName(Name + ".old"); @@ -57,17 +93,49 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { Name.startswith("x86.sse2.pcmpgt.") || Name.startswith("x86.avx2.pcmpeq.") || Name.startswith("x86.avx2.pcmpgt.") || - Name.startswith("x86.avx.vpermil.")) { + Name.startswith("x86.avx.vpermil.") || + Name == "x86.avx.movnt.dq.256" || + Name == "x86.avx.movnt.pd.256" || + Name == "x86.avx.movnt.ps.256" || + (Name.startswith("x86.xop.vpcom") && F->arg_size() == 2)) { NewFn = 0; return true; } + // SSE4.1 ptest functions may have an old signature. + if (Name.startswith("x86.sse41.ptest")) { + if (Name == "x86.sse41.ptestc") + return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestc, NewFn); + if (Name == "x86.sse41.ptestz") + return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestz, NewFn); + if (Name == "x86.sse41.ptestnzc") + return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn); + } + // frcz.ss/sd may need to have an argument dropped + if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::x86_xop_vfrcz_ss); + return true; + } + if (Name.startswith("x86.xop.vfrcz.sd") && F->arg_size() == 2) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::x86_xop_vfrcz_sd); + return true; + } + // Fix the FMA4 intrinsics to remove the 4 + if (Name.startswith("x86.fma4.")) { + F->setName("llvm.x86.fma" + Name.substr(8)); + NewFn = F; + return true; + } break; } } - // This may not belong here. This function is effectively being overloaded - // to both detect an intrinsic which needs upgrading, and to provide the - // upgraded form of the intrinsic. We should perhaps have two separate + // This may not belong here. This function is effectively being overloaded + // to both detect an intrinsic which needs upgrading, and to provide the + // upgraded form of the intrinsic. We should perhaps have two separate // functions for this. return false; } @@ -89,8 +157,8 @@ bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { return false; } -// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the -// upgraded intrinsic. All argument and return casting must be provided in +// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the +// upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Function *F = CI->getCalledFunction(); @@ -118,15 +186,85 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { "pcmpgt"); // need to sign extend since icmp returns vector of i1 Rep = Builder.CreateSExt(Rep, CI->getType(), ""); + } else if (Name == "llvm.x86.avx.movnt.dq.256" || + Name == "llvm.x86.avx.movnt.ps.256" || + Name == "llvm.x86.avx.movnt.pd.256") { + IRBuilder<> Builder(C); + Builder.SetInsertPoint(CI->getParent(), CI); + + Module *M = F->getParent(); + SmallVector<Value *, 1> Elts; + Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); + MDNode *Node = MDNode::get(C, Elts); + + Value *Arg0 = CI->getArgOperand(0); + Value *Arg1 = CI->getArgOperand(1); + + // Convert the type of the pointer to a pointer to the stored type. + Value *BC = Builder.CreateBitCast(Arg0, + PointerType::getUnqual(Arg1->getType()), + "cast"); + StoreInst *SI = Builder.CreateStore(Arg1, BC); + SI->setMetadata(M->getMDKindID("nontemporal"), Node); + SI->setAlignment(16); + + // Remove intrinsic. + CI->eraseFromParent(); + return; + } else if (Name.startswith("llvm.x86.xop.vpcom")) { + Intrinsic::ID intID; + if (Name.endswith("ub")) + intID = Intrinsic::x86_xop_vpcomub; + else if (Name.endswith("uw")) + intID = Intrinsic::x86_xop_vpcomuw; + else if (Name.endswith("ud")) + intID = Intrinsic::x86_xop_vpcomud; + else if (Name.endswith("uq")) + intID = Intrinsic::x86_xop_vpcomuq; + else if (Name.endswith("b")) + intID = Intrinsic::x86_xop_vpcomb; + else if (Name.endswith("w")) + intID = Intrinsic::x86_xop_vpcomw; + else if (Name.endswith("d")) + intID = Intrinsic::x86_xop_vpcomd; + else if (Name.endswith("q")) + intID = Intrinsic::x86_xop_vpcomq; + else + llvm_unreachable("Unknown suffix"); + + Name = Name.substr(18); // strip off "llvm.x86.xop.vpcom" + unsigned Imm; + if (Name.startswith("lt")) + Imm = 0; + else if (Name.startswith("le")) + Imm = 1; + else if (Name.startswith("gt")) + Imm = 2; + else if (Name.startswith("ge")) + Imm = 3; + else if (Name.startswith("eq")) + Imm = 4; + else if (Name.startswith("ne")) + Imm = 5; + else if (Name.startswith("true")) + Imm = 6; + else if (Name.startswith("false")) + Imm = 7; + else + llvm_unreachable("Unknown condition"); + + Function *VPCOM = Intrinsic::getDeclaration(F->getParent(), intID); + Rep = Builder.CreateCall3(VPCOM, CI->getArgOperand(0), + CI->getArgOperand(1), Builder.getInt8(Imm)); } else { bool PD128 = false, PD256 = false, PS128 = false, PS256 = false; - if (Name.startswith("llvm.x86.avx.vpermil.pd.256")) + if (Name == "llvm.x86.avx.vpermil.pd.256") PD256 = true; - else if (Name.startswith("llvm.x86.avx.vpermil.pd")) + else if (Name == "llvm.x86.avx.vpermil.pd") PD128 = true; - else if (Name.startswith("llvm.x86.avx.vpermil.ps.256")) + else if (Name == "llvm.x86.avx.vpermil.ps.256") PS256 = true; - else if (Name.startswith("llvm.x86.avx.vpermil.ps")) + else if (Name == "llvm.x86.avx.vpermil.ps") PS128 = true; if (PD256 || PD128 || PS256 || PS128) { @@ -162,6 +300,9 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { return; } + std::string Name = CI->getName().str(); + CI->setName(Name + ".old"); + switch (NewFn->getIntrinsicID()) { default: llvm_unreachable("Unknown function for CallInst upgrade."); @@ -170,12 +311,60 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::cttz: assert(CI->getNumArgOperands() == 1 && "Mismatch between function args and call args"); - StringRef Name = CI->getName(); - CI->setName(Name + ".old"); CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), Builder.getFalse(), Name)); CI->eraseFromParent(); return; + + case Intrinsic::arm_neon_vclz: { + // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.* + CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), + Builder.getFalse(), + "llvm.ctlz." + Name.substr(14))); + CI->eraseFromParent(); + return; + } + case Intrinsic::ctpop: { + CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0))); + CI->eraseFromParent(); + return; + } + + case Intrinsic::x86_xop_vfrcz_ss: + case Intrinsic::x86_xop_vfrcz_sd: + CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(1), + Name)); + CI->eraseFromParent(); + return; + + case Intrinsic::x86_sse41_ptestc: + case Intrinsic::x86_sse41_ptestz: + case Intrinsic::x86_sse41_ptestnzc: { + // The arguments for these intrinsics used to be v4f32, and changed + // to v2i64. This is purely a nop, since those are bitwise intrinsics. + // So, the only thing required is a bitcast for both arguments. + // First, check the arguments have the old type. + Value *Arg0 = CI->getArgOperand(0); + if (Arg0->getType() != VectorType::get(Type::getFloatTy(C), 4)) + return; + + // Old intrinsic, add bitcasts + Value *Arg1 = CI->getArgOperand(1); + + Value *BC0 = + Builder.CreateBitCast(Arg0, + VectorType::get(Type::getInt64Ty(C), 2), + "cast"); + Value *BC1 = + Builder.CreateBitCast(Arg1, + VectorType::get(Type::getInt64Ty(C), 2), + "cast"); + + CallInst* NewCall = Builder.CreateCall2(NewFn, BC0, BC1, Name); + CI->replaceAllUsesWith(NewCall); + CI->eraseFromParent(); + return; + } } } diff --git a/lib/VMCore/CMakeLists.txt b/lib/VMCore/CMakeLists.txt index e1efcda..6a20be6 100644 --- a/lib/VMCore/CMakeLists.txt +++ b/lib/VMCore/CMakeLists.txt @@ -8,7 +8,9 @@ add_llvm_library(LLVMCore ConstantFold.cpp Constants.cpp Core.cpp + DebugInfo.cpp DebugLoc.cpp + DIBuilder.cpp Dominators.cpp Function.cpp GCOV.cpp @@ -29,6 +31,7 @@ add_llvm_library(LLVMCore PassRegistry.cpp PrintModulePass.cpp Type.cpp + TypeFinder.cpp Use.cpp User.cpp Value.cpp @@ -36,3 +39,14 @@ add_llvm_library(LLVMCore ValueTypes.cpp Verifier.cpp ) + +# Workaround: It takes over 20 minutes to compile with msvc10. +# FIXME: Suppressing optimizations to core libraries would not be good thing. +if( MSVC_VERSION EQUAL 1600 ) +set_property( + SOURCE Function.cpp + PROPERTY COMPILE_FLAGS "/Og-" + ) +endif() + +add_dependencies(LLVMCore intrinsics_gen) diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index b743287..8e82876 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -55,13 +55,12 @@ static Constant *BitCastConstantVector(Constant *CV, VectorType *DstTy) { Type *DstEltTy = DstTy->getElementType(); - // Check to verify that all elements of the input are simple. SmallVector<Constant*, 16> Result; + Type *Ty = IntegerType::get(CV->getContext(), 32); for (unsigned i = 0; i != NumElts; ++i) { - Constant *C = CV->getAggregateElement(i); - if (C == 0) return 0; + Constant *C = + ConstantExpr::getExtractElement(CV, ConstantInt::get(Ty, i)); C = ConstantExpr::getBitCast(C, DstEltTy); - if (isa<ConstantExpr>(C)) return 0; Result.push_back(C); } @@ -553,9 +552,12 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, SmallVector<Constant*, 16> res; VectorType *DestVecTy = cast<VectorType>(DestTy); Type *DstEltTy = DestVecTy->getElementType(); - for (unsigned i = 0, e = V->getType()->getVectorNumElements(); i != e; ++i) - res.push_back(ConstantExpr::getCast(opc, - V->getAggregateElement(i), DstEltTy)); + Type *Ty = IntegerType::get(V->getContext(), 32); + for (unsigned i = 0, e = V->getType()->getVectorNumElements(); i != e; ++i) { + Constant *C = + ConstantExpr::getExtractElement(V, ConstantInt::get(Ty, i)); + res.push_back(ConstantExpr::getCast(opc, C, DstEltTy)); + } return ConstantVector::get(res); } @@ -696,12 +698,13 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond, // If the condition is a vector constant, fold the result elementwise. if (ConstantVector *CondV = dyn_cast<ConstantVector>(Cond)) { SmallVector<Constant*, 16> Result; + Type *Ty = IntegerType::get(CondV->getContext(), 32); for (unsigned i = 0, e = V1->getType()->getVectorNumElements(); i != e;++i){ ConstantInt *Cond = dyn_cast<ConstantInt>(CondV->getOperand(i)); if (Cond == 0) break; - Constant *Res = (Cond->getZExtValue() ? V2 : V1)->getAggregateElement(i); - if (Res == 0) break; + Constant *V = Cond->isNullValue() ? V2 : V1; + Constant *Res = ConstantExpr::getExtractElement(V, ConstantInt::get(Ty, i)); Result.push_back(Res); } @@ -721,12 +724,12 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond, if (ConstantExpr *TrueVal = dyn_cast<ConstantExpr>(V1)) { if (TrueVal->getOpcode() == Instruction::Select) if (TrueVal->getOperand(0) == Cond) - return ConstantExpr::getSelect(Cond, TrueVal->getOperand(1), V2); + return ConstantExpr::getSelect(Cond, TrueVal->getOperand(1), V2); } if (ConstantExpr *FalseVal = dyn_cast<ConstantExpr>(V2)) { if (FalseVal->getOpcode() == Instruction::Select) if (FalseVal->getOperand(0) == Cond) - return ConstantExpr::getSelect(Cond, V1, FalseVal->getOperand(2)); + return ConstantExpr::getSelect(Cond, V1, FalseVal->getOperand(2)); } return 0; @@ -760,16 +763,16 @@ Constant *llvm::ConstantFoldInsertElementInstruction(Constant *Val, const APInt &IdxVal = CIdx->getValue(); SmallVector<Constant*, 16> Result; + Type *Ty = IntegerType::get(Val->getContext(), 32); for (unsigned i = 0, e = Val->getType()->getVectorNumElements(); i != e; ++i){ if (i == IdxVal) { Result.push_back(Elt); continue; } - if (Constant *C = Val->getAggregateElement(i)) - Result.push_back(C); - else - return 0; + Constant *C = + ConstantExpr::getExtractElement(Val, ConstantInt::get(Ty, i)); + Result.push_back(C); } return ConstantVector::get(Result); @@ -801,11 +804,15 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *InElt; if (unsigned(Elt) >= SrcNumElts*2) InElt = UndefValue::get(EltTy); - else if (unsigned(Elt) >= SrcNumElts) - InElt = V2->getAggregateElement(Elt - SrcNumElts); - else - InElt = V1->getAggregateElement(Elt); - if (InElt == 0) return 0; + else if (unsigned(Elt) >= SrcNumElts) { + Type *Ty = IntegerType::get(V2->getContext(), 32); + InElt = + ConstantExpr::getExtractElement(V2, + ConstantInt::get(Ty, Elt - SrcNumElts)); + } else { + Type *Ty = IntegerType::get(V1->getContext(), 32); + InElt = ConstantExpr::getExtractElement(V1, ConstantInt::get(Ty, Elt)); + } Result.push_back(InElt); } @@ -1130,16 +1137,17 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, } else if (VectorType *VTy = dyn_cast<VectorType>(C1->getType())) { // Perform elementwise folding. SmallVector<Constant*, 16> Result; + Type *Ty = IntegerType::get(VTy->getContext(), 32); for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { - Constant *LHS = C1->getAggregateElement(i); - Constant *RHS = C2->getAggregateElement(i); - if (LHS == 0 || RHS == 0) break; + Constant *LHS = + ConstantExpr::getExtractElement(C1, ConstantInt::get(Ty, i)); + Constant *RHS = + ConstantExpr::getExtractElement(C2, ConstantInt::get(Ty, i)); Result.push_back(ConstantExpr::get(Opcode, LHS, RHS)); } - if (Result.size() == VTy->getNumElements()) - return ConstantVector::get(Result); + return ConstantVector::get(Result); } if (ConstantExpr *CE1 = dyn_cast<ConstantExpr>(C1)) { @@ -1697,17 +1705,18 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, // If we can constant fold the comparison of each element, constant fold // the whole vector comparison. SmallVector<Constant*, 4> ResElts; + Type *Ty = IntegerType::get(C1->getContext(), 32); // Compare the elements, producing an i1 result or constant expr. for (unsigned i = 0, e = C1->getType()->getVectorNumElements(); i != e;++i){ - Constant *C1E = C1->getAggregateElement(i); - Constant *C2E = C2->getAggregateElement(i); - if (C1E == 0 || C2E == 0) break; + Constant *C1E = + ConstantExpr::getExtractElement(C1, ConstantInt::get(Ty, i)); + Constant *C2E = + ConstantExpr::getExtractElement(C2, ConstantInt::get(Ty, i)); ResElts.push_back(ConstantExpr::getCompare(pred, C1E, C2E)); } - if (ResElts.size() == C1->getType()->getVectorNumElements()) - return ConstantVector::get(ResElts); + return ConstantVector::get(ResElts); } if (C1->getType()->isFloatingPointTy()) { diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 6dbc144..a4e21e1 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -46,7 +46,7 @@ bool Constant::isNegativeZeroValue() const { // Floating point values have an explicit -0.0 value. if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) return CFP->isZero() && CFP->isNegative(); - + // Otherwise, just use +0.0. return isNullValue(); } @@ -55,7 +55,7 @@ bool Constant::isNullValue() const { // 0 is null. if (const ConstantInt *CI = dyn_cast<ConstantInt>(this)) return CI->isZero(); - + // +0.0 is null. if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) return CFP->isZero() && !CFP->isNegative(); @@ -161,19 +161,19 @@ Constant *Constant::getAllOnesValue(Type *Ty) { Constant *Constant::getAggregateElement(unsigned Elt) const { if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(this)) return Elt < CS->getNumOperands() ? CS->getOperand(Elt) : 0; - + if (const ConstantArray *CA = dyn_cast<ConstantArray>(this)) return Elt < CA->getNumOperands() ? CA->getOperand(Elt) : 0; - + if (const ConstantVector *CV = dyn_cast<ConstantVector>(this)) return Elt < CV->getNumOperands() ? CV->getOperand(Elt) : 0; - + if (const ConstantAggregateZero *CAZ =dyn_cast<ConstantAggregateZero>(this)) return CAZ->getElementValue(Elt); - + if (const UndefValue *UV = dyn_cast<UndefValue>(this)) return UV->getElementValue(Elt); - + if (const ConstantDataSequential *CDS =dyn_cast<ConstantDataSequential>(this)) return Elt < CDS->getNumElements() ? CDS->getElementAsConstant(Elt) : 0; return 0; @@ -222,10 +222,10 @@ bool Constant::canTrap() const { // The only thing that could possibly trap are constant exprs. const ConstantExpr *CE = dyn_cast<ConstantExpr>(this); if (!CE) return false; - - // ConstantExpr traps if any operands can trap. + + // ConstantExpr traps if any operands can trap. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (CE->getOperand(i)->canTrap()) + if (CE->getOperand(i)->canTrap()) return true; // Otherwise, only specific operations can trap. @@ -252,7 +252,7 @@ bool Constant::isConstantUsed() const { const Constant *UC = dyn_cast<Constant>(*UI); if (UC == 0 || isa<GlobalValue>(UC)) return true; - + if (UC->isConstantUsed()) return true; } @@ -302,12 +302,12 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { cast<BlockAddress>(RHS->getOperand(0))->getFunction()) return NoRelocation; } - + PossibleRelocationsTy Result = NoRelocation; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) Result = std::max(Result, cast<Constant>(getOperand(i))->getRelocationInfo()); - + return Result; } @@ -316,14 +316,14 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { /// constantexpr. static bool removeDeadUsersOfConstant(const Constant *C) { if (isa<GlobalValue>(C)) return false; // Cannot remove this - + while (!C->use_empty()) { const Constant *User = dyn_cast<Constant>(C->use_back()); if (!User) return false; // Non-constant usage; if (!removeDeadUsersOfConstant(User)) return false; // Constant wasn't dead } - + const_cast<Constant*>(C)->destroyConstant(); return true; } @@ -343,7 +343,7 @@ void Constant::removeDeadConstantUsers() const { ++I; continue; } - + if (!removeDeadUsersOfConstant(User)) { // If the constant wasn't dead, remember that this was the last live use // and move on to the next constant. @@ -351,7 +351,7 @@ void Constant::removeDeadConstantUsers() const { ++I; continue; } - + // If the constant was dead, then the iterator is invalidated. if (LastNonDeadUser == E) { I = use_begin(); @@ -485,7 +485,7 @@ static const fltSemantics *TypeToFloatSemantics(Type *Ty) { return &APFloat::x87DoubleExtended; else if (Ty->isFP128Ty()) return &APFloat::IEEEquad; - + assert(Ty->isPPC_FP128Ty() && "Unknown FP format"); return &APFloat::PPCDoubleDouble; } @@ -497,7 +497,7 @@ void ConstantFP::anchor() { } /// 2.0/1.0 etc, that are known-valid both as double and as the target format. Constant *ConstantFP::get(Type *Ty, double V) { LLVMContext &Context = Ty->getContext(); - + APFloat FV(V); bool ignored; FV.convert(*TypeToFloatSemantics(Ty->getScalarType()), @@ -550,11 +550,11 @@ Constant *ConstantFP::getZeroValueForNegation(Type *Ty) { // ConstantFP accessors. ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) { DenseMapAPFloatKeyInfo::KeyTy Key(V); - + LLVMContextImpl* pImpl = Context.pImpl; - + ConstantFP *&Slot = pImpl->FPConstants[Key]; - + if (!Slot) { Type *Ty; if (&V.getSemantics() == &APFloat::IEEEhalf) @@ -574,7 +574,7 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) { } Slot = new ConstantFP(Ty, V); } - + return Slot; } @@ -695,7 +695,7 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { "Wrong type in array element initializer"); } LLVMContextImpl *pImpl = Ty->getContext().pImpl; - + // If this is an all-zero array, return a ConstantAggregateZero object. If // all undef, return an UndefValue, if "all simple", then return a // ConstantDataArray. @@ -751,7 +751,7 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { return ConstantDataArray::get(C->getContext(), Elts); } } - + if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { if (CFP->getType()->isFloatTy()) { SmallVector<float, 16> Elts; @@ -788,7 +788,7 @@ StructType *ConstantStruct::getTypeForElements(LLVMContext &Context, SmallVector<Type*, 16> EltTypes(VecSize); for (unsigned i = 0; i != VecSize; ++i) EltTypes[i] = V[i]->getType(); - + return StructType::get(Context, EltTypes, Packed); } @@ -833,12 +833,12 @@ Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) { isUndef = false; } } - } + } if (isZero) return ConstantAggregateZero::get(ST); if (isUndef) return UndefValue::get(ST); - + return ST->getContext().pImpl->StructConstants.getOrCreate(ST, V); } @@ -881,12 +881,12 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { break; } } - + if (isZero) return ConstantAggregateZero::get(T); if (isUndef) return UndefValue::get(T); - + // Check to see if all of the elements are ConstantFP or ConstantInt and if // the element type is compatible with ConstantDataVector. If so, use it. if (ConstantDataSequential::isElementTypeCompatible(C->getType())) { @@ -932,7 +932,7 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { return ConstantDataVector::get(C->getContext(), Elts); } } - + if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { if (CFP->getType()->isFloatTy()) { SmallVector<float, 16> Elts; @@ -955,7 +955,7 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) { } } } - + // Otherwise, the element type isn't compatible with ConstantDataVector, or // the operand list constants a ConstantExpr or something else strange. return pImpl->VectorConstants.getOrCreate(T, V); @@ -967,7 +967,7 @@ Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) { if ((isa<ConstantFP>(V) || isa<ConstantInt>(V)) && ConstantDataSequential::isElementTypeCompatible(V->getType())) return ConstantDataVector::getSplat(NumElts, V); - + SmallVector<Constant*, 32> Elts(NumElts, V); return get(Elts); } @@ -1039,7 +1039,7 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { SmallVector<Constant*, 8> NewOps; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) NewOps.push_back(i == OpNo ? Op : getOperand(i)); - + return getWithOperands(NewOps); } @@ -1052,7 +1052,7 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const { bool AnyChange = Ty != getType(); for (unsigned i = 0; i != Ops.size(); ++i) AnyChange |= Ops[i] != getOperand(i); - + if (!AnyChange) // No operands changed, return self. return const_cast<ConstantExpr*>(this); @@ -1177,7 +1177,7 @@ ConstantAggregateZero *ConstantAggregateZero::get(Type *Ty) { ConstantAggregateZero *&Entry = Ty->getContext().pImpl->CAZConstants[Ty]; if (Entry == 0) Entry = new ConstantAggregateZero(Ty); - + return Entry; } @@ -1232,7 +1232,7 @@ ConstantPointerNull *ConstantPointerNull::get(PointerType *Ty) { ConstantPointerNull *&Entry = Ty->getContext().pImpl->CPNConstants[Ty]; if (Entry == 0) Entry = new ConstantPointerNull(Ty); - + return Entry; } @@ -1252,7 +1252,7 @@ UndefValue *UndefValue::get(Type *Ty) { UndefValue *&Entry = Ty->getContext().pImpl->UVConstants[Ty]; if (Entry == 0) Entry = new UndefValue(Ty); - + return Entry; } @@ -1277,7 +1277,7 @@ BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) { F->getContext().pImpl->BlockAddresses[std::make_pair(F, BB)]; if (BA == 0) BA = new BlockAddress(F, BB); - + assert(BA->getFunction() == F && "Basic block moved between functions"); return BA; } @@ -1305,19 +1305,19 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // case, we have to remove the map entry. Function *NewF = getFunction(); BasicBlock *NewBB = getBasicBlock(); - + if (U == &Op<0>()) NewF = cast<Function>(To); else NewBB = cast<BasicBlock>(To); - + // See if the 'new' entry already exists, if not, just update this in place // and return early. BlockAddress *&NewBA = getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)]; if (NewBA == 0) { getBasicBlock()->AdjustBlockAddressRefCount(-1); - + // Remove the old entry, this can't cause the map to rehash (just a // tombstone will get added). getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), @@ -1331,10 +1331,10 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // Otherwise, I do need to replace this with an existing value. assert(NewBA != this && "I didn't contain From!"); - + // Everyone using this now uses the replacement. replaceAllUsesWith(NewBA); - + destroyConstant(); } @@ -1355,10 +1355,10 @@ static inline Constant *getFoldedCast( // Look up the constant in the table first to ensure uniqueness std::vector<Constant*> argVec(1, C); ExprMapKeyType Key(opc, argVec); - + return pImpl->ExprConstants.getOrCreate(Ty, Key); } - + Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { Instruction::CastOps opc = Instruction::CastOps(oc); assert(Instruction::isCast(opc) && "opcode out of range"); @@ -1381,7 +1381,7 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { case Instruction::IntToPtr: return getIntToPtr(C, Ty); case Instruction::BitCast: return getBitCast(C, Ty); } -} +} Constant *ConstantExpr::getZExtOrBitCast(Constant *C, Type *Ty) { if (C->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits()) @@ -1572,11 +1572,11 @@ Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) { Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) { assert(CastInst::castIsValid(Instruction::BitCast, C, DstTy) && "Invalid constantexpr bitcast!"); - + // It is common to ask for a bitcast of a value to its own type, handle this // speedily. if (C->getType() == DstTy) return C; - + return getFoldedCast(Instruction::BitCast, C, DstTy); } @@ -1588,7 +1588,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, "Invalid opcode in binary constant expression"); assert(C1->getType() == C2->getType() && "Operand types in binary constant expression should match"); - + #ifndef NDEBUG switch (Opcode) { case Instruction::Add: @@ -1649,11 +1649,11 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2)) return FC; // Fold a few common cases. - + std::vector<Constant*> argVec(1, C1); argVec.push_back(C2); ExprMapKeyType Key(Opcode, argVec, 0, Flags); - + LLVMContextImpl *pImpl = C1->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(C1->getType(), Key); } @@ -1703,7 +1703,7 @@ Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) { Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1, Constant *C2) { assert(C1->getType() == C2->getType() && "Op types should be identical!"); - + switch (Predicate) { default: llvm_unreachable("Invalid CmpInst predicate"); case CmpInst::FCMP_FALSE: case CmpInst::FCMP_OEQ: case CmpInst::FCMP_OGT: @@ -1713,7 +1713,7 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE: case CmpInst::FCMP_TRUE: return getFCmp(Predicate, C1, C2); - + case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT: case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT: @@ -1732,7 +1732,7 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) { argVec[1] = V1; argVec[2] = V2; ExprMapKeyType Key(Instruction::Select, argVec); - + LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(V1->getType(), Key); } @@ -1747,7 +1747,7 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, assert(Ty && "GEP indices invalid!"); unsigned AS = C->getType()->getPointerAddressSpace(); Type *ReqTy = Ty->getPointerTo(AS); - + assert(C->getType()->isPointerTy() && "Non-pointer type for constant GetElementPtr expression"); // Look up the constant in the table first to ensure uniqueness @@ -1758,7 +1758,7 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, ArgVec.push_back(cast<Constant>(Idxs[i])); const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, InBounds ? GEPOperator::IsInBounds : 0); - + LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } @@ -1815,15 +1815,15 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { "Tried to create extractelement operation on non-vector type!"); assert(Idx->getType()->isIntegerTy(32) && "Extractelement index must be i32 type!"); - + if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx)) return FC; // Fold a few common cases. - + // Look up the constant in the table first to ensure uniqueness std::vector<Constant*> ArgVec(1, Val); ArgVec.push_back(Idx); const ExprMapKeyType Key(Instruction::ExtractElement,ArgVec); - + LLVMContextImpl *pImpl = Val->getContext().pImpl; Type *ReqTy = Val->getType()->getVectorElementType(); return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -1845,7 +1845,7 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, ArgVec.push_back(Elt); ArgVec.push_back(Idx); const ExprMapKeyType Key(Instruction::InsertElement,ArgVec); - + LLVMContextImpl *pImpl = Val->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(Val->getType(), Key); } @@ -1867,7 +1867,7 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, ArgVec.push_back(V2); ArgVec.push_back(Mask); const ExprMapKeyType Key(Instruction::ShuffleVector,ArgVec); - + LLVMContextImpl *pImpl = ShufTy->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ShufTy, Key); } @@ -1892,7 +1892,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, Type *ReqTy = ExtractValueInst::getIndexedType(Agg->getType(), Idxs); (void)ReqTy; assert(ReqTy && "extractvalue indices invalid!"); - + assert(Agg->getType()->isFirstClassType() && "Non-first-class type for constant extractvalue expression"); Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs); @@ -2007,6 +2007,47 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) { isExact ? PossiblyExactOperator::IsExact : 0); } +/// getBinOpIdentity - Return the identity for the given binary operation, +/// i.e. a constant C such that X op C = X and C op X = X for every X. It +/// returns null if the operator doesn't have an identity. +Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty) { + switch (Opcode) { + default: + // Doesn't have an identity. + return 0; + + case Instruction::Add: + case Instruction::Or: + case Instruction::Xor: + return Constant::getNullValue(Ty); + + case Instruction::Mul: + return ConstantInt::get(Ty, 1); + + case Instruction::And: + return Constant::getAllOnesValue(Ty); + } +} + +/// getBinOpAbsorber - Return the absorbing element for the given binary +/// operation, i.e. a constant C such that X op C = C and C op X = C for +/// every X. For example, this returns zero for integer multiplication. +/// It returns null if the operator doesn't have an absorbing element. +Constant *ConstantExpr::getBinOpAbsorber(unsigned Opcode, Type *Ty) { + switch (Opcode) { + default: + // Doesn't have an absorber. + return 0; + + case Instruction::Or: + return Constant::getAllOnesValue(Ty); + + case Instruction::And: + case Instruction::Mul: + return Constant::getNullValue(Ty); + } +} + // destroyConstant - Remove the constant from the constant table... // void ConstantExpr::destroyConstant() { @@ -2107,7 +2148,7 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { // Do a lookup to see if we have already formed one of these. StringMap<ConstantDataSequential*>::MapEntryTy &Slot = Ty->getContext().pImpl->CDSConstants.GetOrCreateValue(Elements); - + // The bucket can point to a linked list of different CDS's that have the same // body but different types. For example, 0,0,0,1 could be a 4 element array // of i8, or a 1-element array of i32. They'll both end up in the same @@ -2117,7 +2158,7 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { Entry = &Node->Next, Node = *Entry) if (Node->getType() == Ty) return Node; - + // Okay, we didn't get a hit. Create a node of the right class, link it in, // and return it. if (isa<ArrayType>(Ty)) @@ -2131,7 +2172,7 @@ void ConstantDataSequential::destroyConstant() { // Remove the constant from the StringMap. StringMap<ConstantDataSequential*> &CDSConstants = getType()->getContext().pImpl->CDSConstants; - + StringMap<ConstantDataSequential*>::iterator Slot = CDSConstants.find(getRawDataValues()); @@ -2158,11 +2199,11 @@ void ConstantDataSequential::destroyConstant() { } } } - + // If we were part of a list, make sure that we don't delete the list that is // still owned by the uniquing map. Next = 0; - + // Finally, actually delete it. destroyConstantImpl(); } @@ -2172,27 +2213,33 @@ void ConstantDataSequential::destroyConstant() { /// can return a ConstantAggregateZero object. Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint8_t> Elts) { Type *Ty = ArrayType::get(Type::getInt8Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*1), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*1), Ty); } Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint16_t> Elts){ Type *Ty = ArrayType::get(Type::getInt16Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*2), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*2), Ty); } Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint32_t> Elts){ Type *Ty = ArrayType::get(Type::getInt32Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*4), Ty); } Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint64_t> Elts){ Type *Ty = ArrayType::get(Type::getInt64Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); } Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<float> Elts) { Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*4), Ty); } Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<double> Elts) { Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); } /// getString - This method constructs a CDS and initializes it with a text @@ -2202,9 +2249,12 @@ Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<double> Elts) { /// to disable this behavior. Constant *ConstantDataArray::getString(LLVMContext &Context, StringRef Str, bool AddNull) { - if (!AddNull) - return get(Context, ArrayRef<uint8_t>((uint8_t*)Str.data(), Str.size())); - + if (!AddNull) { + const uint8_t *Data = reinterpret_cast<const uint8_t *>(Str.data()); + return get(Context, ArrayRef<uint8_t>(const_cast<uint8_t *>(Data), + Str.size())); + } + SmallVector<uint8_t, 64> ElementVals; ElementVals.append(Str.begin(), Str.end()); ElementVals.push_back(0); @@ -2216,27 +2266,33 @@ Constant *ConstantDataArray::getString(LLVMContext &Context, /// can return a ConstantAggregateZero object. Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<uint8_t> Elts){ Type *Ty = VectorType::get(Type::getInt8Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*1), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*1), Ty); } Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<uint16_t> Elts){ Type *Ty = VectorType::get(Type::getInt16Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*2), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*2), Ty); } Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<uint32_t> Elts){ Type *Ty = VectorType::get(Type::getInt32Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*4), Ty); } Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<uint64_t> Elts){ Type *Ty = VectorType::get(Type::getInt64Ty(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); } Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<float> Elts) { Type *Ty = VectorType::get(Type::getFloatTy(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*4), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*4), Ty); } Constant *ConstantDataVector::get(LLVMContext &Context, ArrayRef<double> Elts) { Type *Ty = VectorType::get(Type::getDoubleTy(Context), Elts.size()); - return getImpl(StringRef((char*)Elts.data(), Elts.size()*8), Ty); + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getImpl(StringRef(const_cast<char *>(Data), Elts.size()*8), Ty); } Constant *ConstantDataVector::getSplat(unsigned NumElts, Constant *V) { @@ -2281,15 +2337,19 @@ uint64_t ConstantDataSequential::getElementAsInteger(unsigned Elt) const { assert(isa<IntegerType>(getElementType()) && "Accessor can only be used when element is an integer"); const char *EltPtr = getElementPointer(Elt); - + // The data is stored in host byte order, make sure to cast back to the right // type to load with the right endianness. switch (getElementType()->getIntegerBitWidth()) { default: llvm_unreachable("Invalid bitwidth for CDS"); - case 8: return *(uint8_t*)EltPtr; - case 16: return *(uint16_t*)EltPtr; - case 32: return *(uint32_t*)EltPtr; - case 64: return *(uint64_t*)EltPtr; + case 8: + return *const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(EltPtr)); + case 16: + return *const_cast<uint16_t *>(reinterpret_cast<const uint16_t *>(EltPtr)); + case 32: + return *const_cast<uint32_t *>(reinterpret_cast<const uint32_t *>(EltPtr)); + case 64: + return *const_cast<uint64_t *>(reinterpret_cast<const uint64_t *>(EltPtr)); } } @@ -2301,8 +2361,14 @@ APFloat ConstantDataSequential::getElementAsAPFloat(unsigned Elt) const { switch (getElementType()->getTypeID()) { default: llvm_unreachable("Accessor can only be used when element is float/double!"); - case Type::FloatTyID: return APFloat(*(float*)EltPtr); - case Type::DoubleTyID: return APFloat(*(double*)EltPtr); + case Type::FloatTyID: { + const float *FloatPrt = reinterpret_cast<const float *>(EltPtr); + return APFloat(*const_cast<float *>(FloatPrt)); + } + case Type::DoubleTyID: { + const double *DoublePtr = reinterpret_cast<const double *>(EltPtr); + return APFloat(*const_cast<double *>(DoublePtr)); + } } } @@ -2311,7 +2377,8 @@ APFloat ConstantDataSequential::getElementAsAPFloat(unsigned Elt) const { float ConstantDataSequential::getElementAsFloat(unsigned Elt) const { assert(getElementType()->isFloatTy() && "Accessor can only be used when element is a 'float'"); - return *(float*)getElementPointer(Elt); + const float *EltPtr = reinterpret_cast<const float *>(getElementPointer(Elt)); + return *const_cast<float *>(EltPtr); } /// getElementAsDouble - If this is an sequential container of doubles, return @@ -2319,7 +2386,9 @@ float ConstantDataSequential::getElementAsFloat(unsigned Elt) const { double ConstantDataSequential::getElementAsDouble(unsigned Elt) const { assert(getElementType()->isDoubleTy() && "Accessor can only be used when element is a 'float'"); - return *(double*)getElementPointer(Elt); + const double *EltPtr = + reinterpret_cast<const double *>(getElementPointer(Elt)); + return *const_cast<double *>(EltPtr); } /// getElementAsConstant - Return a Constant for a specified index's element. @@ -2328,7 +2397,7 @@ double ConstantDataSequential::getElementAsDouble(unsigned Elt) const { Constant *ConstantDataSequential::getElementAsConstant(unsigned Elt) const { if (getElementType()->isFloatTy() || getElementType()->isDoubleTy()) return ConstantFP::get(getContext(), getElementAsAPFloat(Elt)); - + return ConstantInt::get(getElementType(), getElementAsInteger(Elt)); } @@ -2342,12 +2411,12 @@ bool ConstantDataSequential::isString() const { bool ConstantDataSequential::isCString() const { if (!isString()) return false; - + StringRef Str = getAsString(); - + // The last value must be nul. if (Str.back() != 0) return false; - + // Other elements must be non-nul. return Str.drop_back().find(0) == StringRef::npos; } @@ -2356,13 +2425,13 @@ bool ConstantDataSequential::isCString() const { /// elements have the same value, return that value. Otherwise return NULL. Constant *ConstantDataVector::getSplatValue() const { const char *Base = getRawDataValues().data(); - + // Compare elements 1+ to the 0'th element. unsigned EltSize = getElementByteSize(); for (unsigned i = 1, e = getNumElements(); i != e; ++i) if (memcmp(Base, Base+i*EltSize, EltSize)) return 0; - + // If they're all the same, return the 0th one as a representative. return getElementAsConstant(0); } @@ -2393,10 +2462,10 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Lookup.first = cast<ArrayType>(getType()); Values.reserve(getNumOperands()); // Build replacement array. - // Fill values with the modified operands of the constant array. Also, + // Fill values with the modified operands of the constant array. Also, // compute whether this turns into an all-zeros array. unsigned NumUpdated = 0; - + // Keep track of whether all the values in the array are "ToC". bool AllSame = true; for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { @@ -2408,7 +2477,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Values.push_back(Val); AllSame &= Val == ToC; } - + Constant *Replacement = 0; if (AllSame && ToC->isNullValue()) { Replacement = ConstantAggregateZero::get(getType()); @@ -2419,7 +2488,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Lookup.second = makeArrayRef(Values); LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I = pImpl->ArrayConstants.find(Lookup); - + if (I != pImpl->ArrayConstants.map_end()) { Replacement = I->first; } else { @@ -2428,7 +2497,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, // old with the new, then deleting the old... just update the current one // in place! pImpl->ArrayConstants.remove(this); - + // Update to the new value. Optimize for the case when we have a single // operand that we're changing, but handle bulk updates efficiently. if (NumUpdated == 1) { @@ -2445,13 +2514,13 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, return; } } - + // Otherwise, I do need to replace this with an existing value. assert(Replacement != this && "I didn't contain From!"); - + // Everyone using this now uses the replacement. replaceAllUsesWith(Replacement); - + // Delete the old constant! destroyConstant(); } @@ -2468,8 +2537,8 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, LLVMContextImpl::StructConstantsTy::LookupKey Lookup; Lookup.first = cast<StructType>(getType()); Values.reserve(getNumOperands()); // Build replacement struct. - - // Fill values with the modified operands of the constant struct. Also, + + // Fill values with the modified operands of the constant struct. Also, // compute whether this turns into an all-zeros struct. bool isAllZeros = false; bool isAllUndef = false; @@ -2492,9 +2561,9 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, Values.push_back(cast<Constant>(O->get())); } Values[OperandToUpdate] = ToC; - + LLVMContextImpl *pImpl = getContext().pImpl; - + Constant *Replacement = 0; if (isAllZeros) { Replacement = ConstantAggregateZero::get(getType()); @@ -2505,7 +2574,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, Lookup.second = makeArrayRef(Values); LLVMContextImpl::StructConstantsTy::MapTy::iterator I = pImpl->StructConstants.find(Lookup); - + if (I != pImpl->StructConstants.map_end()) { Replacement = I->first; } else { @@ -2514,19 +2583,19 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, // old with the new, then deleting the old... just update the current one // in place! pImpl->StructConstants.remove(this); - + // Update to the new value. setOperand(OperandToUpdate, ToC); pImpl->StructConstants.insert(this); return; } } - + assert(Replacement != this && "I didn't contain From!"); - + // Everyone using this now uses the replacement. replaceAllUsesWith(Replacement); - + // Delete the old constant! destroyConstant(); } @@ -2534,7 +2603,7 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); - + SmallVector<Constant*, 8> Values; Values.reserve(getNumOperands()); // Build replacement array... for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { @@ -2542,13 +2611,13 @@ void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, if (Val == From) Val = cast<Constant>(To); Values.push_back(Val); } - + Constant *Replacement = get(Values); assert(Replacement != this && "I didn't contain From!"); - + // Everyone using this now uses the replacement. replaceAllUsesWith(Replacement); - + // Delete the old constant! destroyConstant(); } @@ -2557,19 +2626,19 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Use *U) { assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!"); Constant *To = cast<Constant>(ToV); - + SmallVector<Constant*, 8> NewOps; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Op = getOperand(i); NewOps.push_back(Op == From ? To : Op); } - + Constant *Replacement = getWithOperands(NewOps); assert(Replacement != this && "I didn't contain From!"); - + // Everyone using this now uses the replacement. replaceAllUsesWith(Replacement); - + // Delete the old constant! destroyConstant(); } diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index a9cca22..972db3c 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -115,6 +115,25 @@ void LLVMDumpModule(LLVMModuleRef M) { unwrap(M)->dump(); } +LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, + char **ErrorMessage) { + std::string error; + raw_fd_ostream dest(Filename, error); + if (!error.empty()) { + *ErrorMessage = strdup(error.c_str()); + return true; + } + + unwrap(M)->print(dest, NULL); + + if (!error.empty()) { + *ErrorMessage = strdup(error.c_str()); + return true; + } + dest.flush(); + return false; +} + /*--.. Operations on inline assembler ......................................--*/ void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm) { unwrap(M)->setModuleInlineAsm(StringRef(Asm)); @@ -1191,7 +1210,7 @@ LLVMValueRef LLVMAddGlobalInAddressSpace(LLVMModuleRef M, LLVMTypeRef Ty, unsigned AddressSpace) { return wrap(new GlobalVariable(*unwrap(M), unwrap(Ty), false, GlobalValue::ExternalLinkage, 0, Name, 0, - false, AddressSpace)); + GlobalVariable::NotThreadLocal, AddressSpace)); } LLVMValueRef LLVMGetNamedGlobal(LLVMModuleRef M, const char *Name) { diff --git a/lib/VMCore/DIBuilder.cpp b/lib/VMCore/DIBuilder.cpp new file mode 100644 index 0000000..f5894e9 --- /dev/null +++ b/lib/VMCore/DIBuilder.cpp @@ -0,0 +1,1019 @@ +//===--- DIBuilder.cpp - Debug Information Builder ------------------------===// +// +// 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 DIBuilder. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DIBuilder.h" +#include "llvm/Constants.h" +#include "llvm/DebugInfo.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" + +using namespace llvm; +using namespace llvm::dwarf; + +static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { + assert((Tag & LLVMDebugVersionMask) == 0 && + "Tag too large for debug encoding!"); + return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion); +} + +DIBuilder::DIBuilder(Module &m) + : M(m), VMContext(M.getContext()), TheCU(0), TempEnumTypes(0), + TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0), + ValueFn(0) +{} + +/// finalize - Construct any deferred debug info descriptors. +void DIBuilder::finalize() { + DIArray Enums = getOrCreateArray(AllEnumTypes); + DIType(TempEnumTypes).replaceAllUsesWith(Enums); + + DIArray RetainTypes = getOrCreateArray(AllRetainTypes); + DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); + + DIArray SPs = getOrCreateArray(AllSubprograms); + DIType(TempSubprograms).replaceAllUsesWith(SPs); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { + DISubprogram SP(SPs.getElement(i)); + SmallVector<Value *, 4> Variables; + if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) { + for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii) + Variables.push_back(NMD->getOperand(ii)); + NMD->eraseFromParent(); + } + if (MDNode *Temp = SP.getVariablesNodes()) { + DIArray AV = getOrCreateArray(Variables); + DIType(Temp).replaceAllUsesWith(AV); + } + } + + DIArray GVs = getOrCreateArray(AllGVs); + DIType(TempGVs).replaceAllUsesWith(GVs); +} + +/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return +/// N. +static MDNode *getNonCompileUnitScope(MDNode *N) { + if (DIDescriptor(N).isCompileUnit()) + return NULL; + return N; +} + +/// createCompileUnit - A CompileUnit provides an anchor for all debugging +/// information generated during this instance of compilation. +void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, + StringRef Directory, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RunTimeVer) { + assert(((Lang <= dwarf::DW_LANG_Python && Lang >= dwarf::DW_LANG_C89) || + (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && + "Invalid Language tag"); + assert(!Filename.empty() && + "Unable to create compile unit without filename"); + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + TempEnumTypes = MDNode::getTemporary(VMContext, TElts); + Value *THElts[] = { TempEnumTypes }; + MDNode *EnumHolder = MDNode::get(VMContext, THElts); + + TempRetainTypes = MDNode::getTemporary(VMContext, TElts); + Value *TRElts[] = { TempRetainTypes }; + MDNode *RetainHolder = MDNode::get(VMContext, TRElts); + + TempSubprograms = MDNode::getTemporary(VMContext, TElts); + Value *TSElts[] = { TempSubprograms }; + MDNode *SPHolder = MDNode::get(VMContext, TSElts); + + TempGVs = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { TempGVs }; + MDNode *GVHolder = MDNode::get(VMContext, TVElts); + + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + ConstantInt::get(Type::getInt32Ty(VMContext), Lang), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + MDString::get(VMContext, Producer), + // Deprecate isMain field. + ConstantInt::get(Type::getInt1Ty(VMContext), true), // isMain + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + MDString::get(VMContext, Flags), + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer), + EnumHolder, + RetainHolder, + SPHolder, + GVHolder + }; + TheCU = DICompileUnit(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(TheCU); +} + +/// createFile - Create a file descriptor to hold debugging information +/// for a file. +DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { + assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit"); + assert(!Filename.empty() && "Unable to create file without name"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_file_type), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + NULL // TheCU + }; + return DIFile(MDNode::get(VMContext, Elts)); +} + +/// createEnumerator - Create a single enumerator value. +DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { + assert(!Name.empty() && "Unable to create enumerator without name"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), + MDString::get(VMContext, Name), + ConstantInt::get(Type::getInt64Ty(VMContext), Val) + }; + return DIEnumerator(MDNode::get(VMContext, Elts)); +} + +/// createNullPtrType - Create C++0x nullptr type. +DIType DIBuilder::createNullPtrType(StringRef Name) { + assert(!Name.empty() && "Unable to create type without name"); + // nullptr is encoded in DIBasicType format. Line number, filename, + // ,size, alignment, offset and flags are always empty here. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type), + NULL, //TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; + ConstantInt::get(Type::getInt32Ty(VMContext), 0) // Encoding + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createBasicType - Create debugging information entry for a basic +/// type, e.g 'char'. +DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { + assert(!Name.empty() && "Unable to create type without name"); + // Basic types are encoded in DIBasicType format. Line number, filename, + // offset and flags are always empty here. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_base_type), + NULL, //TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; + ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createQualifiedType - Create debugging information entry for a qualified +/// type, e.g. 'const int'. +DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { + // Qualified types are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + NULL, //TheCU, + MDString::get(VMContext, StringRef()), // Empty name. + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + FromTy + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createPointerType - Create debugging information entry for a pointer. +DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits, StringRef Name) { + // Pointer types are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), + NULL, //TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + PointeeTy + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createReferenceType - Create debugging information entry for a reference +/// type. +DIType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { + assert(RTy.Verify() && "Unable to create reference type"); + // References are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + NULL, // TheCU, + NULL, // Name + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + RTy + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createTypedef - Create debugging information entry for a typedef. +DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo, DIDescriptor Context) { + // typedefs are encoded in DIDerivedType format. + assert(Ty.Verify() && "Invalid typedef type!"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_typedef), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + Ty + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createFriend - Create debugging information entry for a 'friend'. +DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { + // typedefs are encoded in DIDerivedType format. + assert(Ty.Verify() && "Invalid type!"); + assert(FriendTy.Verify() && "Invalid friend type!"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_friend), + Ty, + NULL, // Name + Ty.getFile(), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + FriendTy + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createInheritance - Create debugging information entry to establish +/// inheritance relationship between two types. +DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, + uint64_t BaseOffset, unsigned Flags) { + assert(Ty.Verify() && "Unable to create inheritance"); + // TAG_inheritance is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), + Ty, + NULL, // Name + Ty.getFile(), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + BaseTy + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createMemberType - Create debugging information entry for a member. +DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType Ty) { + // TAG_member is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_member), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Ty + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createObjCIVar - Create debugging information entry for Objective-C +/// instance variable. +DIType DIBuilder::createObjCIVar(StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType Ty, StringRef PropertyName, + StringRef GetterName, StringRef SetterName, + unsigned PropertyAttributes) { + // TAG_member is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_member), + getNonCompileUnitScope(File), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Ty, + MDString::get(VMContext, PropertyName), + MDString::get(VMContext, GetterName), + MDString::get(VMContext, SetterName), + ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createObjCIVar - Create debugging information entry for Objective-C +/// instance variable. +DIType DIBuilder::createObjCIVar(StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType Ty, MDNode *PropertyNode) { + // TAG_member is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_member), + getNonCompileUnitScope(File), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Ty, + PropertyNode + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createObjCProperty - Create debugging information entry for Objective-C +/// property. +DIObjCProperty DIBuilder::createObjCProperty(StringRef Name, + DIFile File, unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, + DIType Ty) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_APPLE_property), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + MDString::get(VMContext, GetterName), + MDString::get(VMContext, SetterName), + ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes), + Ty + }; + return DIObjCProperty(MDNode::get(VMContext, Elts)); +} + +/// createTemplateTypeParameter - Create debugging information for template +/// type parameter. +DITemplateTypeParameter +DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, + DIType Ty, MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + Ty, + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) + }; + return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); +} + +/// createTemplateValueParameter - Create debugging information for template +/// value parameter. +DITemplateValueParameter +DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, + DIType Ty, uint64_t Val, + MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_template_value_parameter), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + Ty, + ConstantInt::get(Type::getInt64Ty(VMContext), Val), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) + }; + return DITemplateValueParameter(MDNode::get(VMContext, Elts)); +} + +/// createClassType - Create debugging information entry for a class. +DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType DerivedFrom, DIArray Elements, + MDNode *VTableHolder, + MDNode *TemplateParams) { + // TAG_class_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_class_type), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom, + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + VTableHolder, + TemplateParams + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createStructType - Create debugging information entry for a struct. +DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DIArray Elements, + unsigned RunTimeLang) { + // TAG_structure_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + NULL, + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createUnionType - Create debugging information entry for an union. +DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, + DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang) { + // TAG_union_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_union_type), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + NULL, + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createSubroutineType - Create subroutine type. +DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { + // TAG_subroutine_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + MDString::get(VMContext, ""), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + NULL, + ParameterTypes, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createEnumerationType - Create debugging information entry for an +/// enumeration. +DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + DIArray Elements, + DIType ClassType, unsigned Flags) { + // TAG_enumeration_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ClassType, + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + MDNode *Node = MDNode::get(VMContext, Elts); + AllEnumTypes.push_back(Node); + return DIType(Node); +} + +/// createArrayType - Create debugging information entry for an array. +DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts) { + // TAG_array_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_array_type), + NULL, //TheCU, + MDString::get(VMContext, ""), + NULL, //TheCU, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), Size), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Ty, + Subscripts, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createVectorType - Create debugging information entry for a vector. +DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts) { + // TAG_vector_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_vector_type), + NULL, //TheCU, + MDString::get(VMContext, ""), + NULL, //TheCU, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), Size), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Ty, + Subscripts, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + return DIType(MDNode::get(VMContext, Elts)); +} + +/// createArtificialType - Create a new DIType with "artificial" flag set. +DIType DIBuilder::createArtificialType(DIType Ty) { + if (Ty.isArtificial()) + return Ty; + + SmallVector<Value *, 9> Elts; + MDNode *N = Ty; + assert (N && "Unexpected input DIType!"); + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (Value *V = N->getOperand(i)) + Elts.push_back(V); + else + Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); + } + + unsigned CurFlags = Ty.getFlags(); + CurFlags = CurFlags | DIType::FlagArtificial; + + // Flags are stored at this slot. + Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); + + return DIType(MDNode::get(VMContext, Elts)); +} + +/// retainType - Retain DIType in a module even if it is not referenced +/// through debug info anchors. +void DIBuilder::retainType(DIType T) { + AllRetainTypes.push_back(T); +} + +/// createUnspecifiedParameter - Create unspeicified type descriptor +/// for the subroutine type. +DIDescriptor DIBuilder::createUnspecifiedParameter() { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) + }; + return DIDescriptor(MDNode::get(VMContext, Elts)); +} + +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType() { + // Give the temporary MDNode a tag. It doesn't matter what tag we + // use here as long as DIType accepts it. + Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts); + return DIType(Node); +} + +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType(DIFile F) { + // Give the temporary MDNode a tag. It doesn't matter what tag we + // use here as long as DIType accepts it. + Value *Elts[] = { + GetTagConstant(VMContext, DW_TAG_base_type), + TheCU, + NULL, + F + }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts); + return DIType(Node); +} + +/// createForwardDecl - Create a temporary forward-declared type that +/// can be RAUW'd if the full type is seen. +DIType DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, + DIDescriptor Scope, DIFile F, + unsigned Line, unsigned RuntimeLang) { + // Create a temporary MDNode. + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), Line), + // To ease transition include sizes etc of 0. + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), + DIDescriptor::FlagFwdDecl), + NULL, + DIArray(), + ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang) + }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts); + return DIType(Node); +} + +/// getOrCreateArray - Get a DIArray, create one if required. +DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) { + if (Elements.empty()) { + Value *Null = Constant::getNullValue(Type::getInt32Ty(VMContext)); + return DIArray(MDNode::get(VMContext, Null)); + } + return DIArray(MDNode::get(VMContext, Elements)); +} + +/// getOrCreateSubrange - Create a descriptor for a value range. This +/// implicitly uniques the values returned. +DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), + ConstantInt::get(Type::getInt64Ty(VMContext), Lo), + ConstantInt::get(Type::getInt64Ty(VMContext), Hi) + }; + + return DISubrange(MDNode::get(VMContext, Elts)); +} + +/// createGlobalVariable - Create a new descriptor for the specified global. +DIGlobalVariable DIBuilder:: +createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, + DIType Ty, bool isLocalToUnit, Value *Val) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_variable), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + NULL, // TheCU, + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ + Val + }; + MDNode *Node = MDNode::get(VMContext, Elts); + AllGVs.push_back(Node); + return DIGlobalVariable(Node); +} + +/// createStaticVariable - Create a new descriptor for the specified static +/// variable. +DIGlobalVariable DIBuilder:: +createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile F, unsigned LineNumber, + DIType Ty, bool isLocalToUnit, Value *Val) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_variable), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ + Val + }; + MDNode *Node = MDNode::get(VMContext, Elts); + AllGVs.push_back(Node); + return DIGlobalVariable(Node); +} + +/// createVariable - Create a new descriptor for the specified variable. +DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile File, + unsigned LineNo, DIType Ty, + bool AlwaysPreserve, unsigned Flags, + unsigned ArgNo) { + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Constant::getNullValue(Type::getInt32Ty(VMContext)) + }; + MDNode *Node = MDNode::get(VMContext, Elts); + if (AlwaysPreserve) { + // The optimizer may remove local variable. If there is an interest + // to preserve variable info in such situation then stash it in a + // named mdnode. + DISubprogram Fn(getDISubprogram(Scope)); + NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); + FnLocals->addOperand(Node); + } + return DIVariable(Node); +} + +/// createComplexVariable - Create a new descriptor for the specified variable +/// which has a complex address expression for its address. +DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile F, + unsigned LineNo, + DIType 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()); + + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// createFunction - Create a new descriptor for the specified function. +DISubprogram DIBuilder::createFunction(DIDescriptor Context, + StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, + bool isLocalToUnit, bool isDefinition, + unsigned ScopeLine, + unsigned Flags, bool isOptimized, + Function *Fn, + MDNode *TParams, + MDNode *Decl) { + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Temp = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { Temp }; + MDNode *THolder = MDNode::get(VMContext, TVElts); + + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Ty, + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + NULL, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + Fn, + TParams, + Decl, + THolder, + ConstantInt::get(Type::getInt32Ty(VMContext), ScopeLine) + }; + MDNode *Node = MDNode::get(VMContext, Elts); + + // Create a named metadata so that we do not lose this mdnode. + AllSubprograms.push_back(Node); + return DISubprogram(Node); +} + +/// createMethod - Create a new descriptor for the specified C++ method. +DISubprogram DIBuilder::createMethod(DIDescriptor Context, + StringRef Name, + StringRef LinkageName, + DIFile F, + unsigned LineNo, DIType Ty, + bool isLocalToUnit, + bool isDefinition, + unsigned VK, unsigned VIndex, + MDNode *VTableHolder, + unsigned Flags, + bool isOptimized, + Function *Fn, + MDNode *TParam) { + Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Temp = MDNode::getTemporary(VMContext, TElts); + Value *TVElts[] = { Temp }; + MDNode *THolder = MDNode::get(VMContext, TVElts); + + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), + Constant::getNullValue(Type::getInt32Ty(VMContext)), + getNonCompileUnitScope(Context), + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Ty, + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), + ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), + ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), + VTableHolder, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + Fn, + TParam, + Constant::getNullValue(Type::getInt32Ty(VMContext)), + THolder, + // FIXME: Do we want to use different scope/lines? + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) + }; + MDNode *Node = MDNode::get(VMContext, Elts); + return DISubprogram(Node); +} + +/// createNameSpace - This creates new descriptor for a namespace +/// with the specified parent scope. +DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_namespace), + getNonCompileUnitScope(Scope), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) + }; + return DINameSpace(MDNode::get(VMContext, Elts)); +} + +/// createLexicalBlockFile - This creates a new MDNode that encapsulates +/// an existing scope with a new filename. +DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, + DIFile File) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), + Scope, + File + }; + return DILexicalBlockFile(MDNode::get(VMContext, Elts)); +} + +DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, + unsigned Line, unsigned Col) { + // Defeat MDNode uniqing for lexical blocks by using unique id. + static unsigned int unique_id = 0; + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), + getNonCompileUnitScope(Scope), + ConstantInt::get(Type::getInt32Ty(VMContext), Line), + ConstantInt::get(Type::getInt32Ty(VMContext), Col), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) + }; + return DILexicalBlock(MDNode::get(VMContext, Elts)); +} + +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + Instruction *InsertBefore) { + assert(Storage && "no storage passed to dbg.declare"); + assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare"); + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + return CallInst::Create(DeclareFn, Args, "", InsertBefore); +} + +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + BasicBlock *InsertAtEnd) { + assert(Storage && "no storage passed to dbg.declare"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare"); + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + + // If this block already has a terminator then insert this intrinsic + // before the terminator. + if (TerminatorInst *T = InsertAtEnd->getTerminator()) + return CallInst::Create(DeclareFn, Args, "", T); + else + return CallInst::Create(DeclareFn, Args, "", InsertAtEnd); +} + +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, + DIVariable VarInfo, + Instruction *InsertBefore) { + assert(V && "no value passed to dbg.value"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + if (!ValueFn) + ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); + + Value *Args[] = { MDNode::get(V->getContext(), V), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo }; + return CallInst::Create(ValueFn, Args, "", InsertBefore); +} + +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, + DIVariable VarInfo, + BasicBlock *InsertAtEnd) { + assert(V && "no value passed to dbg.value"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + if (!ValueFn) + ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); + + Value *Args[] = { MDNode::get(V->getContext(), V), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo }; + return CallInst::Create(ValueFn, Args, "", InsertAtEnd); +} diff --git a/lib/VMCore/DebugInfo.cpp b/lib/VMCore/DebugInfo.cpp new file mode 100644 index 0000000..c8f8f7d --- /dev/null +++ b/lib/VMCore/DebugInfo.cpp @@ -0,0 +1,1168 @@ +//===--- DebugInfo.cpp - Debug Information Helper 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 helper classes used to build and interpret debug +// information in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::dwarf; + +//===----------------------------------------------------------------------===// +// DIDescriptor +//===----------------------------------------------------------------------===// + +DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DILexicalBlockFile F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { +} + +StringRef +DIDescriptor::getStringField(unsigned Elt) const { + if (DbgNode == 0) + return StringRef(); + + if (Elt < DbgNode->getNumOperands()) + if (MDString *MDS = dyn_cast_or_null<MDString>(DbgNode->getOperand(Elt))) + return MDS->getString(); + + return StringRef(); +} + +uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt))) + return CI->getZExtValue(); + + return 0; +} + +DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { + if (DbgNode == 0) + return DIDescriptor(); + + if (Elt < DbgNode->getNumOperands()) + return + DIDescriptor(dyn_cast_or_null<const MDNode>(DbgNode->getOperand(Elt))); + return DIDescriptor(); +} + +GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null<GlobalVariable>(DbgNode->getOperand(Elt)); + return 0; +} + +Constant *DIDescriptor::getConstantField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null<Constant>(DbgNode->getOperand(Elt)); + return 0; +} + +Function *DIDescriptor::getFunctionField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null<Function>(DbgNode->getOperand(Elt)); + return 0; +} + +unsigned DIVariable::getNumAddrElements() const { + if (getVersion() <= LLVMDebugVersion8) + return DbgNode->getNumOperands()-6; + if (getVersion() == LLVMDebugVersion9) + return DbgNode->getNumOperands()-7; + return DbgNode->getNumOperands()-8; +} + +/// getInlinedAt - If this variable is inlined then return inline location. +MDNode *DIVariable::getInlinedAt() const { + if (getVersion() <= LLVMDebugVersion9) + return NULL; + return dyn_cast_or_null<MDNode>(DbgNode->getOperand(7)); +} + +//===----------------------------------------------------------------------===// +// Predicates +//===----------------------------------------------------------------------===// + +/// isBasicType - Return true if the specified tag is legal for +/// DIBasicType. +bool DIDescriptor::isBasicType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_unspecified_type: + return true; + default: + return false; + } +} + +/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. +bool DIDescriptor::isDerivedType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_reference_type: + case dwarf::DW_TAG_rvalue_reference_type: + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_member: + case dwarf::DW_TAG_inheritance: + case dwarf::DW_TAG_friend: + return true; + default: + // CompositeTypes are currently modelled as DerivedTypes. + return isCompositeType(); + } +} + +/// isCompositeType - Return true if the specified tag is legal for +/// DICompositeType. +bool DIDescriptor::isCompositeType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_array_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_subroutine_type: + case dwarf::DW_TAG_class_type: + return true; + default: + return false; + } +} + +/// isVariable - Return true if the specified tag is legal for DIVariable. +bool DIDescriptor::isVariable() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_auto_variable: + case dwarf::DW_TAG_arg_variable: + case dwarf::DW_TAG_return_variable: + return true; + default: + return false; + } +} + +/// isType - Return true if the specified tag is legal for DIType. +bool DIDescriptor::isType() const { + return isBasicType() || isCompositeType() || isDerivedType(); +} + +/// isSubprogram - Return true if the specified tag is legal for +/// DISubprogram. +bool DIDescriptor::isSubprogram() const { + return DbgNode && getTag() == dwarf::DW_TAG_subprogram; +} + +/// isGlobalVariable - Return true if the specified tag is legal for +/// DIGlobalVariable. +bool DIDescriptor::isGlobalVariable() const { + return DbgNode && (getTag() == dwarf::DW_TAG_variable || + getTag() == dwarf::DW_TAG_constant); +} + +/// isGlobal - Return true if the specified tag is legal for DIGlobal. +bool DIDescriptor::isGlobal() const { + return isGlobalVariable(); +} + +/// isUnspecifiedParmeter - Return true if the specified tag is +/// DW_TAG_unspecified_parameters. +bool DIDescriptor::isUnspecifiedParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters; +} + +/// isScope - Return true if the specified tag is one of the scope +/// related tag. +bool DIDescriptor::isScope() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_compile_unit: + case dwarf::DW_TAG_lexical_block: + case dwarf::DW_TAG_subprogram: + case dwarf::DW_TAG_namespace: + return true; + default: + break; + } + return false; +} + +/// isTemplateTypeParameter - Return true if the specified tag is +/// DW_TAG_template_type_parameter. +bool DIDescriptor::isTemplateTypeParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter; +} + +/// isTemplateValueParameter - Return true if the specified tag is +/// DW_TAG_template_value_parameter. +bool DIDescriptor::isTemplateValueParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_value_parameter; +} + +/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. +bool DIDescriptor::isCompileUnit() const { + return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; +} + +/// isFile - Return true if the specified tag is DW_TAG_file_type. +bool DIDescriptor::isFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_file_type; +} + +/// isNameSpace - Return true if the specified tag is DW_TAG_namespace. +bool DIDescriptor::isNameSpace() const { + return DbgNode && getTag() == dwarf::DW_TAG_namespace; +} + +/// isLexicalBlockFile - Return true if the specified descriptor is a +/// lexical block with an extra file. +bool DIDescriptor::isLexicalBlockFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() == 3); +} + +/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. +bool DIDescriptor::isLexicalBlock() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && + (DbgNode->getNumOperands() > 3); +} + +/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. +bool DIDescriptor::isSubrange() const { + return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; +} + +/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. +bool DIDescriptor::isEnumerator() const { + return DbgNode && getTag() == dwarf::DW_TAG_enumerator; +} + +/// isObjCProperty - Return true if the specified tag is DW_TAG +bool DIDescriptor::isObjCProperty() const { + return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; +} +//===----------------------------------------------------------------------===// +// Simple Descriptor Constructors and other Methods +//===----------------------------------------------------------------------===// + +DIType::DIType(const MDNode *N) : DIScope(N) { + if (!N) return; + if (!isBasicType() && !isDerivedType() && !isCompositeType()) { + DbgNode = 0; + } +} + +unsigned DIArray::getNumElements() const { + if (!DbgNode) + return 0; + return DbgNode->getNumOperands(); +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(DIDescriptor &D) { + if (!DbgNode) + return; + + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (DbgNode != D) { + MDNode *Node = const_cast<MDNode*>(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null<Value>(DN); + Node->replaceAllUsesWith(const_cast<Value*>(V)); + MDNode::deleteTemporary(Node); + } +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(MDNode *D) { + if (!DbgNode) + return; + + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (DbgNode != D) { + MDNode *Node = const_cast<MDNode*>(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null<Value>(DN); + Node->replaceAllUsesWith(const_cast<Value*>(V)); + MDNode::deleteTemporary(Node); + } +} + +/// isUnsignedDIType - Return true if type encoding is unsigned. +bool DIType::isUnsignedDIType() { + DIDerivedType DTy(DbgNode); + if (DTy.Verify()) + return DTy.getTypeDerivedFrom().isUnsignedDIType(); + + DIBasicType BTy(DbgNode); + if (BTy.Verify()) { + unsigned Encoding = BTy.getEncoding(); + if (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char) + return true; + } + return false; +} + +/// Verify - Verify that a compile unit is well formed. +bool DICompileUnit::Verify() const { + if (!DbgNode) + return false; + StringRef N = getFilename(); + if (N.empty()) + return false; + // It is possible that directory and produce string is empty. + return true; +} + +/// Verify - Verify that an ObjC property is well formed. +bool DIObjCProperty::Verify() const { + if (!DbgNode) + return false; + unsigned Tag = getTag(); + if (Tag != dwarf::DW_TAG_APPLE_property) return false; + DIType Ty = getType(); + if (!Ty.Verify()) return false; + + // Don't worry about the rest of the strings for now. + return true; +} + +/// Verify - Verify that a type descriptor is well formed. +bool DIType::Verify() const { + if (!DbgNode) + return false; + if (getContext() && !getContext().Verify()) + return false; + unsigned Tag = getTag(); + if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type && + Tag != dwarf::DW_TAG_reference_type && + Tag != dwarf::DW_TAG_rvalue_reference_type && + Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_vector_type && + Tag != dwarf::DW_TAG_array_type && + Tag != dwarf::DW_TAG_enumeration_type && + Tag != dwarf::DW_TAG_subroutine_type && + getFilename().empty()) + return false; + return true; +} + +/// Verify - Verify that a basic type descriptor is well formed. +bool DIBasicType::Verify() const { + return isBasicType(); +} + +/// Verify - Verify that a derived type descriptor is well formed. +bool DIDerivedType::Verify() const { + return isDerivedType(); +} + +/// Verify - Verify that a composite type descriptor is well formed. +bool DICompositeType::Verify() const { + if (!DbgNode) + return false; + if (getContext() && !getContext().Verify()) + return false; + + return true; +} + +/// Verify - Verify that a subprogram descriptor is well formed. +bool DISubprogram::Verify() const { + if (!DbgNode) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DICompositeType Ty = getType(); + if (!Ty.Verify()) + return false; + return true; +} + +/// Verify - Verify that a global variable descriptor is well formed. +bool DIGlobalVariable::Verify() const { + if (!DbgNode) + return false; + + if (getDisplayName().empty()) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + if (!getGlobal() && !getConstant()) + return false; + + return true; +} + +/// Verify - Verify that a variable descriptor is well formed. +bool DIVariable::Verify() const { + if (!DbgNode) + return false; + + if (getContext() && !getContext().Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + return true; +} + +/// Verify - Verify that a location descriptor is well formed. +bool DILocation::Verify() const { + if (!DbgNode) + return false; + + return DbgNode->getNumOperands() == 4; +} + +/// Verify - Verify that a namespace descriptor is well formed. +bool DINameSpace::Verify() const { + if (!DbgNode) + return false; + if (getName().empty()) + return false; + return true; +} + +/// getOriginalTypeSize - If this type is derived from a base type then +/// return base type size. +uint64_t DIDerivedType::getOriginalTypeSize() const { + unsigned Tag = getTag(); + + if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && + Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + return getSizeInBits(); + + DIType BaseType = getTypeDerivedFrom(); + + // If this type is not derived from any type then take conservative approach. + if (!BaseType.isValid()) + return getSizeInBits(); + + // If this is a derived type, go ahead and get the base type, unless it's a + // reference then it's just the size of the field. Pointer types have no need + // of this since they're a different type of qualification on the type. + if (BaseType.getTag() == dwarf::DW_TAG_reference_type || + BaseType.getTag() == dwarf::DW_TAG_rvalue_reference_type) + return getSizeInBits(); + + if (BaseType.isDerivedType()) + return DIDerivedType(BaseType).getOriginalTypeSize(); + + return BaseType.getSizeInBits(); +} + +/// getObjCProperty - Return property node, if this ivar is associated with one. +MDNode *DIDerivedType::getObjCProperty() const { + if (getVersion() <= LLVMDebugVersion11 || DbgNode->getNumOperands() <= 10) + return NULL; + return dyn_cast_or_null<MDNode>(DbgNode->getOperand(10)); +} + +/// isInlinedFnArgument - Return true if this variable provides debugging +/// information for an inlined function arguments. +bool DIVariable::isInlinedFnArgument(const Function *CurFn) { + assert(CurFn && "Invalid function"); + if (!getContext().isSubprogram()) + return false; + // This variable is not inlined function argument if its scope + // does not describe current function. + return !DISubprogram(getContext()).describes(CurFn); +} + +/// describes - Return true if this subprogram provides debugging +/// information for the function F. +bool DISubprogram::describes(const Function *F) { + assert(F && "Invalid function"); + if (F == getFunction()) + return true; + StringRef Name = getLinkageName(); + if (Name.empty()) + Name = getName(); + if (F->getName() == Name) + return true; + return false; +} + +unsigned DISubprogram::isOptimized() const { + assert (DbgNode && "Invalid subprogram descriptor!"); + if (DbgNode->getNumOperands() == 16) + return getUnsignedField(15); + return 0; +} + +MDNode *DISubprogram::getVariablesNodes() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return NULL; + if (MDNode *Temp = dyn_cast_or_null<MDNode>(DbgNode->getOperand(19))) + return dyn_cast_or_null<MDNode>(Temp->getOperand(0)); + return NULL; +} + +DIArray DISubprogram::getVariables() const { + if (!DbgNode || DbgNode->getNumOperands() <= 19) + return DIArray(); + if (MDNode *T = dyn_cast_or_null<MDNode>(DbgNode->getOperand(19))) + if (MDNode *A = dyn_cast_or_null<MDNode>(T->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +StringRef DIScope::getFilename() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getFilename(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getFilename(); + if (isSubprogram()) + return DISubprogram(DbgNode).getFilename(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getFilename(); + if (isNameSpace()) + return DINameSpace(DbgNode).getFilename(); + if (isType()) + return DIType(DbgNode).getFilename(); + if (isFile()) + return DIFile(DbgNode).getFilename(); + llvm_unreachable("Invalid DIScope!"); +} + +StringRef DIScope::getDirectory() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlockFile()) + return DILexicalBlockFile(DbgNode).getDirectory(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getDirectory(); + if (isSubprogram()) + return DISubprogram(DbgNode).getDirectory(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getDirectory(); + if (isNameSpace()) + return DINameSpace(DbgNode).getDirectory(); + if (isType()) + return DIType(DbgNode).getDirectory(); + if (isFile()) + return DIFile(DbgNode).getDirectory(); + llvm_unreachable("Invalid DIScope!"); +} + +DIArray DICompileUnit::getEnumTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(10))) + if (MDNode *A = dyn_cast_or_null<MDNode>(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getRetainedTypes() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(11))) + if (MDNode *A = dyn_cast_or_null<MDNode>(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +DIArray DICompileUnit::getSubprograms() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(12))) + if (MDNode *A = dyn_cast_or_null<MDNode>(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + + +DIArray DICompileUnit::getGlobalVariables() const { + if (!DbgNode || DbgNode->getNumOperands() < 14) + return DIArray(); + + if (MDNode *N = dyn_cast_or_null<MDNode>(DbgNode->getOperand(13))) + if (MDNode *A = dyn_cast_or_null<MDNode>(N->getOperand(0))) + return DIArray(A); + return DIArray(); +} + +/// fixupObjcLikeName - Replace contains special characters used +/// in a typical Objective-C names with '.' in a given string. +static void fixupObjcLikeName(StringRef Str, SmallVectorImpl<char> &Out) { + bool isObjCLike = false; + for (size_t i = 0, e = Str.size(); i < e; ++i) { + char C = Str[i]; + if (C == '[') + isObjCLike = true; + + if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' || + C == '+' || C == '(' || C == ')')) + Out.push_back('.'); + else + Out.push_back(C); + } +} + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); + return M.getNamedMetadata(Name.str()); +} + +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { + SmallString<32> Name = StringRef("llvm.dbg.lv."); + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + else + FName = Fn.getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + fixupObjcLikeName(FName, Name); + + return M.getOrInsertNamedMetadata(Name.str()); +} + +/// createInlinedVariable - Create a new inlined variable based on current +/// variable. +/// @param DV Current Variable. +/// @param InlinedScope Location at current variable is inlined. +DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, + LLVMContext &VMContext) { + SmallVector<Value *, 16> Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? Elts.push_back(InlinedScope) : + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// cleanseInlinedVariable - Remove inlined scope from the variable. +DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { + SmallVector<Value *, 16> Elts; + // Insert inlined scope as 7th element. + for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) + i == 7 ? + Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))): + Elts.push_back(DV->getOperand(i)); + return DIVariable(MDNode::get(VMContext, Elts)); +} + +/// getDISubprogram - Find subprogram that is enclosing this scope. +DISubprogram llvm::getDISubprogram(const MDNode *Scope) { + DIDescriptor D(Scope); + if (D.isSubprogram()) + return DISubprogram(Scope); + + if (D.isLexicalBlockFile()) + return getDISubprogram(DILexicalBlockFile(Scope).getContext()); + + if (D.isLexicalBlock()) + return getDISubprogram(DILexicalBlock(Scope).getContext()); + + return DISubprogram(); +} + +/// getDICompositeType - Find underlying composite type. +DICompositeType llvm::getDICompositeType(DIType T) { + if (T.isCompositeType()) + return DICompositeType(T); + + if (T.isDerivedType()) + return getDICompositeType(DIDerivedType(T).getTypeDerivedFrom()); + + return DICompositeType(); +} + +/// isSubprogramContext - Return true if Context is either a subprogram +/// or another context nested inside a subprogram. +bool llvm::isSubprogramContext(const MDNode *Context) { + if (!Context) + return false; + DIDescriptor D(Context); + if (D.isSubprogram()) + return true; + if (D.isType()) + return isSubprogramContext(DIType(Context).getContext()); + return false; +} + +//===----------------------------------------------------------------------===// +// DebugInfoFinder implementations. +//===----------------------------------------------------------------------===// + +/// processModule - Process entire module and collect debug info. +void DebugInfoFinder::processModule(Module &M) { + if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { + for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { + DICompileUnit CU(CU_Nodes->getOperand(i)); + addCompileUnit(CU); + if (CU.getVersion() > LLVMDebugVersion10) { + DIArray GVs = CU.getGlobalVariables(); + for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { + DIGlobalVariable DIG(GVs.getElement(i)); + if (addGlobalVariable(DIG)) + processType(DIG.getType()); + } + DIArray SPs = CU.getSubprograms(); + for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) + processSubprogram(DISubprogram(SPs.getElement(i))); + DIArray EnumTypes = CU.getEnumTypes(); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) + processType(DIType(EnumTypes.getElement(i))); + DIArray RetainedTypes = CU.getRetainedTypes(); + for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) + processType(DIType(RetainedTypes.getElement(i))); + return; + } + } + } + + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; + ++BI) { + if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) + processDeclare(DDI); + + DebugLoc Loc = BI->getDebugLoc(); + if (Loc.isUnknown()) + continue; + + LLVMContext &Ctx = BI->getContext(); + DIDescriptor Scope(Loc.getScope(Ctx)); + + if (Scope.isCompileUnit()) + addCompileUnit(DICompileUnit(Scope)); + else if (Scope.isSubprogram()) + processSubprogram(DISubprogram(Scope)); + else if (Scope.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Scope); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + else if (Scope.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(Scope)); + + if (MDNode *IA = Loc.getInlinedAt(Ctx)) + processLocation(DILocation(IA)); + } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv")) { + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIGlobalVariable DIG(cast<MDNode>(NMD->getOperand(i))); + if (addGlobalVariable(DIG)) { + if (DIG.getVersion() <= LLVMDebugVersion10) + addCompileUnit(DIG.getCompileUnit()); + processType(DIG.getType()); + } + } + } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + processSubprogram(DISubprogram(NMD->getOperand(i))); +} + +/// processLocation - Process DILocation. +void DebugInfoFinder::processLocation(DILocation Loc) { + if (!Loc.Verify()) return; + DIDescriptor S(Loc.getScope()); + if (S.isCompileUnit()) + addCompileUnit(DICompileUnit(S)); + else if (S.isSubprogram()) + processSubprogram(DISubprogram(S)); + else if (S.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(S)); + else if (S.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(S); + processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + processLocation(Loc.getOrigLocation()); +} + +/// processType - Process DIType. +void DebugInfoFinder::processType(DIType DT) { + if (!addType(DT)) + return; + if (DT.getVersion() <= LLVMDebugVersion10) + addCompileUnit(DT.getCompileUnit()); + if (DT.isCompositeType()) { + DICompositeType DCT(DT); + processType(DCT.getTypeDerivedFrom()); + DIArray DA = DCT.getTypeArray(); + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + if (D.isType()) + processType(DIType(D)); + else if (D.isSubprogram()) + processSubprogram(DISubprogram(D)); + } + } else if (DT.isDerivedType()) { + DIDerivedType DDT(DT); + processType(DDT.getTypeDerivedFrom()); + } +} + +/// processLexicalBlock +void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { + DIScope Context = LB.getContext(); + if (Context.isLexicalBlock()) + return processLexicalBlock(DILexicalBlock(Context)); + else if (Context.isLexicalBlockFile()) { + DILexicalBlockFile DBF = DILexicalBlockFile(Context); + return processLexicalBlock(DILexicalBlock(DBF.getScope())); + } + else + return processSubprogram(DISubprogram(Context)); +} + +/// processSubprogram - Process DISubprogram. +void DebugInfoFinder::processSubprogram(DISubprogram SP) { + if (!addSubprogram(SP)) + return; + if (SP.getVersion() <= LLVMDebugVersion10) + addCompileUnit(SP.getCompileUnit()); + processType(SP.getType()); +} + +/// processDeclare - Process DbgDeclareInst. +void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { + MDNode *N = dyn_cast<MDNode>(DDI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) + return; + + if (!NodesSeen.insert(DV)) + return; + if (DIVariable(N).getVersion() <= LLVMDebugVersion10) + addCompileUnit(DIVariable(N).getCompileUnit()); + processType(DIVariable(N).getType()); +} + +/// addType - Add type into Tys. +bool DebugInfoFinder::addType(DIType DT) { + if (!DT.isValid()) + return false; + + if (!NodesSeen.insert(DT)) + return false; + + TYs.push_back(DT); + return true; +} + +/// addCompileUnit - Add compile unit into CUs. +bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { + if (!CU.Verify()) + return false; + + if (!NodesSeen.insert(CU)) + return false; + + CUs.push_back(CU); + return true; +} + +/// addGlobalVariable - Add global variable into GVs. +bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { + if (!DIDescriptor(DIG).isGlobalVariable()) + return false; + + if (!NodesSeen.insert(DIG)) + return false; + + GVs.push_back(DIG); + return true; +} + +// addSubprogram - Add subprgoram into SPs. +bool DebugInfoFinder::addSubprogram(DISubprogram SP) { + if (!DIDescriptor(SP).isSubprogram()) + return false; + + if (!NodesSeen.insert(SP)) + return false; + + SPs.push_back(SP); + return true; +} + +//===----------------------------------------------------------------------===// +// DIDescriptor: dump routines for all descriptors. +//===----------------------------------------------------------------------===// + +/// dump - Print descriptor to dbgs() with a newline. +void DIDescriptor::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// print - Print descriptor. +void DIDescriptor::print(raw_ostream &OS) const { + if (!DbgNode) return; + + if (const char *Tag = dwarf::TagString(getTag())) + OS << "[ " << Tag << " ]"; + + if (this->isSubrange()) { + DISubrange(DbgNode).printInternal(OS); + } else if (this->isCompileUnit()) { + DICompileUnit(DbgNode).printInternal(OS); + } else if (this->isFile()) { + DIFile(DbgNode).printInternal(OS); + } else if (this->isEnumerator()) { + DIEnumerator(DbgNode).printInternal(OS); + } else if (this->isBasicType()) { + DIType(DbgNode).printInternal(OS); + } else if (this->isDerivedType()) { + DIDerivedType(DbgNode).printInternal(OS); + } else if (this->isCompositeType()) { + DICompositeType(DbgNode).printInternal(OS); + } else if (this->isSubprogram()) { + DISubprogram(DbgNode).printInternal(OS); + } else if (this->isGlobalVariable()) { + DIGlobalVariable(DbgNode).printInternal(OS); + } else if (this->isVariable()) { + DIVariable(DbgNode).printInternal(OS); + } else if (this->isObjCProperty()) { + DIObjCProperty(DbgNode).printInternal(OS); + } else if (this->isScope()) { + DIScope(DbgNode).printInternal(OS); + } +} + +void DISubrange::printInternal(raw_ostream &OS) const { + OS << " [" << getLo() << ", " << getHi() << ']'; +} + +void DIScope::printInternal(raw_ostream &OS) const { + OS << " [" << getDirectory() << "/" << getFilename() << ']'; +} + +void DICompileUnit::printInternal(raw_ostream &OS) const { + DIScope::printInternal(OS); + if (unsigned Lang = getLanguage()) + OS << " [" << dwarf::LanguageString(Lang) << ']'; +} + +void DIEnumerator::printInternal(raw_ostream &OS) const { + OS << " [" << getName() << " :: " << getEnumValue() << ']'; +} + +void DIType::printInternal(raw_ostream &OS) const { + if (!DbgNode) return; + + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "]"; + + // TODO: Print context? + + OS << " [line " << getLineNumber() + << ", size " << getSizeInBits() + << ", align " << getAlignInBits() + << ", offset " << getOffsetInBits(); + if (isBasicType()) + if (const char *Enc = + dwarf::AttributeEncodingString(DIBasicType(DbgNode).getEncoding())) + OS << ", enc " << Enc; + OS << "]"; + + if (isPrivate()) + OS << " [private]"; + else if (isProtected()) + OS << " [protected]"; + + if (isForwardDecl()) + OS << " [fwd]"; +} + +void DIDerivedType::printInternal(raw_ostream &OS) const { + DIType::printInternal(OS); + OS << " [from " << getTypeDerivedFrom().getName() << ']'; +} + +void DICompositeType::printInternal(raw_ostream &OS) const { + DIType::printInternal(OS); + DIArray A = getTypeArray(); + OS << " [" << A.getNumElements() << " elements]"; +} + +void DISubprogram::printInternal(raw_ostream &OS) const { + // TODO : Print context + OS << " [line " << getLineNumber() << ']'; + + if (isLocalToUnit()) + OS << " [local]"; + + if (isDefinition()) + OS << " [def]"; + + if (getScopeLineNumber() != getLineNumber()) + OS << " [scope " << getScopeLineNumber() << "]"; + + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; +} + +void DIGlobalVariable::printInternal(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; + + OS << " [line " << getLineNumber() << ']'; + + // TODO : Print context + + if (isLocalToUnit()) + OS << " [local]"; + + if (isDefinition()) + OS << " [def]"; +} + +void DIVariable::printInternal(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << ']'; + + OS << " [line " << getLineNumber() << ']'; +} + +void DIObjCProperty::printInternal(raw_ostream &OS) const { + StringRef Name = getObjCPropertyName(); + if (!Name.empty()) + OS << " [" << Name << ']'; + + OS << " [line " << getLineNumber() + << ", properties " << getUnsignedField(6) << ']'; +} + +static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, + const LLVMContext &Ctx) { + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << "<unknown>"; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, CommentOS, Ctx); + CommentOS << " ]"; + } + } +} + +void DIVariable::printExtendedName(raw_ostream &OS) const { + const LLVMContext &Ctx = DbgNode->getContext(); + StringRef Res = getName(); + if (!Res.empty()) + OS << Res << "," << getLineNumber(); + if (MDNode *InlinedAt = getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} diff --git a/lib/VMCore/DebugLoc.cpp b/lib/VMCore/DebugLoc.cpp index 9013d28..c6a3053 100644 --- a/lib/VMCore/DebugLoc.cpp +++ b/lib/VMCore/DebugLoc.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/DebugLoc.h" +#include "llvm/DebugInfo.h" #include "llvm/ADT/DenseMapInfo.h" #include "LLVMContextImpl.h" using namespace llvm; @@ -114,34 +115,19 @@ MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const { /// getFromDILocation - Translate the DILocation quad into a DebugLoc. DebugLoc DebugLoc::getFromDILocation(MDNode *N) { - if (N == 0 || N->getNumOperands() != 4) return DebugLoc(); - - MDNode *Scope = dyn_cast_or_null<MDNode>(N->getOperand(2)); + DILocation Loc(N); + MDNode *Scope = Loc.getScope(); if (Scope == 0) return DebugLoc(); - - unsigned LineNo = 0, ColNo = 0; - if (ConstantInt *Line = dyn_cast_or_null<ConstantInt>(N->getOperand(0))) - LineNo = Line->getZExtValue(); - if (ConstantInt *Col = dyn_cast_or_null<ConstantInt>(N->getOperand(1))) - ColNo = Col->getZExtValue(); - - return get(LineNo, ColNo, Scope, dyn_cast_or_null<MDNode>(N->getOperand(3))); + return get(Loc.getLineNumber(), Loc.getColumnNumber(), Scope, + Loc.getOrigLocation()); } /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) { - if (N == 0 || N->getNumOperands() < 3) return DebugLoc(); - - MDNode *Scope = dyn_cast_or_null<MDNode>(N->getOperand(1)); + DILexicalBlock LexBlock(N); + MDNode *Scope = LexBlock.getContext(); if (Scope == 0) return DebugLoc(); - - unsigned LineNo = 0, ColNo = 0; - if (ConstantInt *Line = dyn_cast_or_null<ConstantInt>(N->getOperand(2))) - LineNo = Line->getZExtValue(); - if (ConstantInt *Col = dyn_cast_or_null<ConstantInt>(N->getOperand(3))) - ColNo = Col->getZExtValue(); - - return get(LineNo, ColNo, Scope, NULL); + return get(LexBlock.getLineNumber(), LexBlock.getColumnNumber(), Scope, NULL); } void DebugLoc::dump(const LLVMContext &Ctx) const { @@ -164,22 +150,10 @@ void DebugLoc::dump(const LLVMContext &Ctx) const { // DenseMap specialization //===----------------------------------------------------------------------===// -DebugLoc DenseMapInfo<DebugLoc>::getEmptyKey() { - return DebugLoc::getEmptyKey(); -} - -DebugLoc DenseMapInfo<DebugLoc>::getTombstoneKey() { - return DebugLoc::getTombstoneKey(); -} - unsigned DenseMapInfo<DebugLoc>::getHashValue(const DebugLoc &Key) { return static_cast<unsigned>(hash_combine(Key.LineCol, Key.ScopeIdx)); } -bool DenseMapInfo<DebugLoc>::isEqual(const DebugLoc &LHS, const DebugLoc &RHS) { - return LHS == RHS; -} - //===----------------------------------------------------------------------===// // LLVMContextImpl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Dominators.cpp b/lib/VMCore/Dominators.cpp index 219e631..682d928 100644 --- a/lib/VMCore/Dominators.cpp +++ b/lib/VMCore/Dominators.cpp @@ -39,6 +39,22 @@ static cl::opt<bool,true> VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), cl::desc("Verify dominator info (time consuming)")); +namespace llvm { + class BasicBlockEdge { + const BasicBlock *Start; + const BasicBlock *End; + public: + BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : + Start(Start_), End(End_) { } + const BasicBlock *getStart() const { + return Start; + } + const BasicBlock *getEnd() const { + return End; + } + }; +} + //===----------------------------------------------------------------------===// // DominatorTree Implementation //===----------------------------------------------------------------------===// @@ -142,12 +158,22 @@ bool DominatorTree::dominates(const Instruction *Def, // Invoke results are only usable in the normal destination, not in the // exceptional destination. BasicBlock *NormalDest = II->getNormalDest(); - if (!dominates(NormalDest, UseBB)) + BasicBlockEdge E(DefBB, NormalDest); + return dominates(E, UseBB); +} + +bool DominatorTree::dominates(const BasicBlockEdge &BBE, + const BasicBlock *UseBB) const { + // If the BB the edge ends in doesn't dominate the use BB, then the + // edge also doesn't. + const BasicBlock *Start = BBE.getStart(); + const BasicBlock *End = BBE.getEnd(); + if (!dominates(End, UseBB)) return false; - // Simple case: if the normal destination has a single predecessor, the - // fact that it dominates the use block implies that we also do. - if (NormalDest->getSinglePredecessor()) + // Simple case: if the end BB has a single predecessor, the fact that it + // dominates the use block implies that the edge also does. + if (End->getSinglePredecessor()) return true; // The normal edge from the invoke is critical. Conceptually, what we would @@ -170,29 +196,40 @@ bool DominatorTree::dominates(const Instruction *Def, // trivially dominates itself, so we only have to find if it dominates the // other predecessors. Since the only way out of X is via NormalDest, X can // only properly dominate a node if NormalDest dominates that node too. - for (pred_iterator PI = pred_begin(NormalDest), - E = pred_end(NormalDest); PI != E; ++PI) { + for (const_pred_iterator PI = pred_begin(End), E = pred_end(End); + PI != E; ++PI) { const BasicBlock *BB = *PI; - if (BB == DefBB) + if (BB == Start) continue; - if (!DT->isReachableFromEntry(BB)) - continue; - - if (!dominates(NormalDest, BB)) + if (!dominates(End, BB)) return false; } return true; } -bool DominatorTree::dominates(const Instruction *Def, +bool DominatorTree::dominates(const BasicBlockEdge &BBE, const Use &U) const { - Instruction *UserInst = dyn_cast<Instruction>(U.getUser()); + Instruction *UserInst = cast<Instruction>(U.getUser()); + // A PHI in the end of the edge is dominated by it. + PHINode *PN = dyn_cast<PHINode>(UserInst); + if (PN && PN->getParent() == BBE.getEnd() && + PN->getIncomingBlock(U) == BBE.getStart()) + return true; - // Instructions do not dominate non-instructions. - if (!UserInst) - return false; + // Otherwise use the edge-dominates-block query, which + // handles the crazy critical edge cases properly. + const BasicBlock *UseBB; + if (PN) + UseBB = PN->getIncomingBlock(U); + else + UseBB = UserInst->getParent(); + return dominates(BBE, UseBB); +} +bool DominatorTree::dominates(const Instruction *Def, + const Use &U) const { + Instruction *UserInst = cast<Instruction>(U.getUser()); const BasicBlock *DefBB = Def->getParent(); // Determine the block in which the use happens. PHI nodes use @@ -218,17 +255,9 @@ bool DominatorTree::dominates(const Instruction *Def, // their own block, except possibly a phi, so we don't need to // walk the block in any case. if (const InvokeInst *II = dyn_cast<InvokeInst>(Def)) { - // A PHI in the normal successor using the invoke's return value is - // dominated by the invoke's return value. - if (isa<PHINode>(UserInst) && - UserInst->getParent() == II->getNormalDest() && - cast<PHINode>(UserInst)->getIncomingBlock(U) == DefBB) - return true; - - // Otherwise use the instruction-dominates-block query, which - // handles the crazy case of an invoke with a critical edge - // properly. - return dominates(Def, UseBB); + BasicBlock *NormalDest = II->getNormalDest(); + BasicBlockEdge E(DefBB, NormalDest); + return dominates(E, U); } // If the def and use are in different blocks, do a simple CFG dominator diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index af6344e..2e0b316 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -29,7 +29,6 @@ #include "llvm/ADT/StringExtras.h" using namespace llvm; - // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... template class llvm::SymbolTableListTraits<Argument, Function>; @@ -358,17 +357,239 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) { return Result; } -FunctionType *Intrinsic::getType(LLVMContext &Context, - ID id, ArrayRef<Type*> Tys) { - Type *ResultTy = NULL; - SmallVector<Type*, 8> ArgTys; - bool IsVarArg = false; + +/// IIT_Info - These are enumerators that describe the entries returned by the +/// getIntrinsicInfoTableEntries function. +/// +/// NOTE: This must be kept in synch with the copy in TblGen/IntrinsicEmitter! +enum IIT_Info { + // Common values should be encoded with 0-15. + IIT_Done = 0, + IIT_I1 = 1, + IIT_I8 = 2, + IIT_I16 = 3, + IIT_I32 = 4, + IIT_I64 = 5, + IIT_F32 = 6, + IIT_F64 = 7, + IIT_V2 = 8, + IIT_V4 = 9, + IIT_V8 = 10, + IIT_V16 = 11, + IIT_V32 = 12, + IIT_MMX = 13, + IIT_PTR = 14, + IIT_ARG = 15, -#define GET_INTRINSIC_GENERATOR + // Values from 16+ are only encodable with the inefficient encoding. + IIT_METADATA = 16, + IIT_EMPTYSTRUCT = 17, + IIT_STRUCT2 = 18, + IIT_STRUCT3 = 19, + IIT_STRUCT4 = 20, + IIT_STRUCT5 = 21, + IIT_EXTEND_VEC_ARG = 22, + IIT_TRUNC_VEC_ARG = 23, + IIT_ANYPTR = 24 +}; + + +static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, + SmallVectorImpl<Intrinsic::IITDescriptor> &OutputTable) { + IIT_Info Info = IIT_Info(Infos[NextElt++]); + unsigned StructElts = 2; + using namespace Intrinsic; + + switch (Info) { + case IIT_Done: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0)); + return; + case IIT_MMX: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0)); + return; + case IIT_METADATA: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Metadata, 0)); + return; + case IIT_F32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Float, 0)); + return; + case IIT_F64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0)); + return; + case IIT_I1: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1)); + return; + case IIT_I8: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8)); + return; + case IIT_I16: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer,16)); + return; + case IIT_I32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 32)); + return; + case IIT_I64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64)); + return; + case IIT_V2: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 2)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_V4: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 4)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_V8: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 8)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_V16: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 16)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_V32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_PTR: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); + DecodeIITType(NextElt, Infos, OutputTable); + return; + case IIT_ANYPTR: { // [ANYPTR addrspace, subtype] + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, + Infos[NextElt++])); + DecodeIITType(NextElt, Infos, OutputTable); + return; + } + case IIT_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo)); + return; + } + case IIT_EXTEND_VEC_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendVecArgument, + ArgInfo)); + return; + } + case IIT_TRUNC_VEC_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncVecArgument, + ArgInfo)); + return; + } + case IIT_EMPTYSTRUCT: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); + return; + case IIT_STRUCT5: ++StructElts; // FALL THROUGH. + case IIT_STRUCT4: ++StructElts; // FALL THROUGH. + case IIT_STRUCT3: ++StructElts; // FALL THROUGH. + case IIT_STRUCT2: { + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct,StructElts)); + + for (unsigned i = 0; i != StructElts; ++i) + DecodeIITType(NextElt, Infos, OutputTable); + return; + } + } + llvm_unreachable("unhandled"); +} + + +#define GET_INTRINSIC_GENERATOR_GLOBAL #include "llvm/Intrinsics.gen" -#undef GET_INTRINSIC_GENERATOR +#undef GET_INTRINSIC_GENERATOR_GLOBAL + +void Intrinsic::getIntrinsicInfoTableEntries(ID id, + SmallVectorImpl<IITDescriptor> &T){ + // Check to see if the intrinsic's type was expressible by the table. + unsigned TableVal = IIT_Table[id-1]; + + // Decode the TableVal into an array of IITValues. + SmallVector<unsigned char, 8> IITValues; + ArrayRef<unsigned char> IITEntries; + unsigned NextElt = 0; + if ((TableVal >> 31) != 0) { + // This is an offset into the IIT_LongEncodingTable. + IITEntries = IIT_LongEncodingTable; + + // Strip sentinel bit. + NextElt = (TableVal << 1) >> 1; + } else { + // Decode the TableVal into an array of IITValues. If the entry was encoded + // into a single word in the table itself, decode it now. + do { + IITValues.push_back(TableVal & 0xF); + TableVal >>= 4; + } while (TableVal); + + IITEntries = IITValues; + NextElt = 0; + } - return FunctionType::get(ResultTy, ArgTys, IsVarArg); + // Okay, decode the table into the output vector of IITDescriptors. + DecodeIITType(NextElt, IITEntries, T); + while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0) + DecodeIITType(NextElt, IITEntries, T); +} + + +static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, + ArrayRef<Type*> Tys, LLVMContext &Context) { + using namespace Intrinsic; + IITDescriptor D = Infos.front(); + Infos = Infos.slice(1); + + switch (D.Kind) { + case IITDescriptor::Void: return Type::getVoidTy(Context); + case IITDescriptor::MMX: return Type::getX86_MMXTy(Context); + case IITDescriptor::Metadata: return Type::getMetadataTy(Context); + case IITDescriptor::Float: return Type::getFloatTy(Context); + case IITDescriptor::Double: return Type::getDoubleTy(Context); + + case IITDescriptor::Integer: + return IntegerType::get(Context, D.Integer_Width); + case IITDescriptor::Vector: + return VectorType::get(DecodeFixedType(Infos, Tys, Context),D.Vector_Width); + case IITDescriptor::Pointer: + return PointerType::get(DecodeFixedType(Infos, Tys, Context), + D.Pointer_AddressSpace); + case IITDescriptor::Struct: { + Type *Elts[5]; + assert(D.Struct_NumElements <= 5 && "Can't handle this yet"); + for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) + Elts[i] = DecodeFixedType(Infos, Tys, Context); + return StructType::get(Context, ArrayRef<Type*>(Elts,D.Struct_NumElements)); + } + + case IITDescriptor::Argument: + return Tys[D.getArgumentNumber()]; + case IITDescriptor::ExtendVecArgument: + return VectorType::getExtendedElementVectorType(cast<VectorType>( + Tys[D.getArgumentNumber()])); + + case IITDescriptor::TruncVecArgument: + return VectorType::getTruncatedElementVectorType(cast<VectorType>( + Tys[D.getArgumentNumber()])); + } + llvm_unreachable("unhandled"); +} + + + +FunctionType *Intrinsic::getType(LLVMContext &Context, + ID id, ArrayRef<Type*> Tys) { + SmallVector<IITDescriptor, 8> Table; + getIntrinsicInfoTableEntries(id, Table); + + ArrayRef<IITDescriptor> TableRef = Table; + Type *ResultTy = DecodeFixedType(TableRef, Tys, Context); + + SmallVector<Type*, 8> ArgTys; + while (!TableRef.empty()) + ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context)); + + return FunctionType::get(ResultTy, ArgTys, false); } bool Intrinsic::isOverloaded(ID id) { @@ -400,7 +621,8 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) { bool Function::hasAddressTaken(const User* *PutOffender) const { for (Value::const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) { const User *U = *I; - // FIXME: Check for blockaddress, which does not take the address. + if (isa<BlockAddress>(U)) + continue; if (!isa<CallInst>(U) && !isa<InvokeInst>(U)) return PutOffender ? (*PutOffender = U, true) : true; ImmutableCallSite CS(cast<Instruction>(U)); @@ -439,4 +661,3 @@ bool Function::callsFunctionThatReturnsTwice() const { return false; } -// vim: sw=2 ai diff --git a/lib/VMCore/GCOV.cpp b/lib/VMCore/GCOV.cpp index 595c452..003a5d4 100644 --- a/lib/VMCore/GCOV.cpp +++ b/lib/VMCore/GCOV.cpp @@ -64,7 +64,7 @@ bool GCOVFile::read(GCOVBuffer &Buffer) { /// dump - Dump GCOVFile content on standard out for debugging purposes. void GCOVFile::dump() { for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), - E = Functions.end(); I != E; ++I) + E = Functions.end(); I != E; ++I) (*I)->dump(); } @@ -72,7 +72,7 @@ void GCOVFile::dump() { /// reading .gcno and .gcda files. void GCOVFile::collectLineCounts(FileInfo &FI) { for (SmallVector<GCOVFunction *, 16>::iterator I = Functions.begin(), - E = Functions.end(); I != E; ++I) + E = Functions.end(); I != E; ++I) (*I)->collectLineCounts(FI); FI.print(); } @@ -143,7 +143,7 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) { StringRef Filename = Buff.readString(); if (Buff.getCursor() == (Size - 4)) break; while (uint32_t L = Buff.readInt()) - Block->addLine(Filename, L); + Block->addLine(Filename, L); } Buff.readInt(); // flag } @@ -154,7 +154,7 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOVFormat Format) { void GCOVFunction::dump() { outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), - E = Blocks.end(); I != E; ++I) + E = Blocks.end(); I != E; ++I) (*I)->dump(); } @@ -162,7 +162,7 @@ void GCOVFunction::dump() { /// reading .gcno and .gcda files. void GCOVFunction::collectLineCounts(FileInfo &FI) { for (SmallVector<GCOVBlock *, 16>::iterator I = Blocks.begin(), - E = Blocks.end(); I != E; ++I) + E = Blocks.end(); I != E; ++I) (*I)->collectLineCounts(FI); } @@ -186,7 +186,7 @@ void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) { /// reading .gcno and .gcda files. void GCOVBlock::collectLineCounts(FileInfo &FI) { for (StringMap<GCOVLines *>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) + E = Lines.end(); I != E; ++I) I->second->collectLineCounts(FI, I->first(), Counter); } @@ -196,14 +196,14 @@ void GCOVBlock::dump() { if (!Edges.empty()) { outs() << "\tEdges : "; for (SmallVector<uint32_t, 16>::iterator I = Edges.begin(), E = Edges.end(); - I != E; ++I) + I != E; ++I) outs() << (*I) << ","; outs() << "\n"; } if (!Lines.empty()) { outs() << "\tLines : "; for (StringMap<GCOVLines *>::iterator LI = Lines.begin(), - LE = Lines.end(); LI != LE; ++LI) { + LE = Lines.end(); LI != LE; ++LI) { outs() << LI->first() << " -> "; LI->second->dump(); outs() << "\n"; @@ -217,16 +217,16 @@ void GCOVBlock::dump() { /// collectLineCounts - Collect line counts. This must be used after /// reading .gcno and .gcda files. void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename, - uint32_t Count) { + uint32_t Count) { for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) + E = Lines.end(); I != E; ++I) FI.addLineCount(Filename, *I, Count); } /// dump - Dump GCOVLines content on standard out for debugging purposes. void GCOVLines::dump() { for (SmallVector<uint32_t, 16>::iterator I = Lines.begin(), - E = Lines.end(); I != E; ++I) + E = Lines.end(); I != E; ++I) outs() << (*I) << ","; } @@ -266,12 +266,12 @@ void FileInfo::print() { StringRef AllLines = Buff.take()->getBuffer(); for (unsigned i = 0, e = L.size(); i != e; ++i) { if (L[i]) - outs() << L[i] << ":\t"; + outs() << L[i] << ":\t"; else - outs() << " :\t"; + outs() << " :\t"; std::pair<StringRef, StringRef> P = AllLines.split('\n'); if (AllLines != P.first) - outs() << P.first; + outs() << P.first; outs() << "\n"; AllLines = P.second; } diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp index 4254fb2..c428b88 100644 --- a/lib/VMCore/Globals.cpp +++ b/lib/VMCore/Globals.cpp @@ -82,12 +82,12 @@ bool GlobalValue::isDeclaration() const { GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, Constant *InitVal, const Twine &Name, - bool ThreadLocal, unsigned AddressSpace) - : GlobalValue(PointerType::get(Ty, AddressSpace), + ThreadLocalMode TLMode, unsigned AddressSpace) + : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != 0, Link, Name), - isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) { + isConstantGlobal(constant), threadLocalMode(TLMode) { if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); @@ -100,13 +100,13 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, LinkageTypes Link, Constant *InitVal, const Twine &Name, - GlobalVariable *Before, bool ThreadLocal, + GlobalVariable *Before, ThreadLocalMode TLMode, unsigned AddressSpace) - : GlobalValue(PointerType::get(Ty, AddressSpace), + : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal, OperandTraits<GlobalVariable>::op_begin(this), InitVal != 0, Link, Name), - isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) { + isConstantGlobal(constant), threadLocalMode(TLMode) { if (InitVal) { assert(InitVal->getType() == Ty && "Initializer should be the same type as the GlobalVariable!"); diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp index b459234..5c4e6d9 100644 --- a/lib/VMCore/IRBuilder.cpp +++ b/lib/VMCore/IRBuilder.cpp @@ -12,9 +12,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/IRBuilder.h" -#include "llvm/GlobalVariable.h" #include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/IRBuilder.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" using namespace llvm; @@ -28,7 +28,7 @@ Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), true, GlobalValue::PrivateLinkage, - StrConstant, "", 0, false); + StrConstant); GV->setName(Name); GV->setUnnamedAddr(true); return GV; @@ -120,13 +120,13 @@ CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) { assert(isa<PointerType>(Ptr->getType()) && - "lifetime.start only applies to pointers."); + "lifetime.start only applies to pointers."); Ptr = getCastedInt8PtrValue(Ptr); if (!Size) Size = getInt64(-1); else assert(Size->getType() == getInt64Ty() && - "lifetime.start requires the size to be an i64"); + "lifetime.start requires the size to be an i64"); Value *Ops[] = { Size, Ptr }; Module *M = BB->getParent()->getParent(); Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_start); @@ -135,13 +135,13 @@ CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) { CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { assert(isa<PointerType>(Ptr->getType()) && - "lifetime.end only applies to pointers."); + "lifetime.end only applies to pointers."); Ptr = getCastedInt8PtrValue(Ptr); if (!Size) Size = getInt64(-1); else assert(Size->getType() == getInt64Ty() && - "lifetime.end requires the size to be an i64"); + "lifetime.end requires the size to be an i64"); Value *Ops[] = { Size, Ptr }; Module *M = BB->getParent()->getParent(); Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end); diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 5449714..66379a0 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -226,34 +226,52 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const { RMWI->isVolatile() == cast<AtomicRMWInst>(I)->isVolatile() && RMWI->getOrdering() == cast<AtomicRMWInst>(I)->getOrdering() && RMWI->getSynchScope() == cast<AtomicRMWInst>(I)->getSynchScope(); - + if (const PHINode *thisPHI = dyn_cast<PHINode>(this)) { + const PHINode *otherPHI = cast<PHINode>(I); + for (unsigned i = 0, e = thisPHI->getNumOperands(); i != e; ++i) { + if (thisPHI->getIncomingBlock(i) != otherPHI->getIncomingBlock(i)) + return false; + } + return true; + } return true; } // isSameOperationAs // This should be kept in sync with isEquivalentOperation in // lib/Transforms/IPO/MergeFunctions.cpp. -bool Instruction::isSameOperationAs(const Instruction *I) const { +bool Instruction::isSameOperationAs(const Instruction *I, + unsigned flags) const { + bool IgnoreAlignment = flags & CompareIgnoringAlignment; + bool UseScalarTypes = flags & CompareUsingScalarTypes; + if (getOpcode() != I->getOpcode() || getNumOperands() != I->getNumOperands() || - getType() != I->getType()) + (UseScalarTypes ? + getType()->getScalarType() != I->getType()->getScalarType() : + getType() != I->getType())) return false; // We have two instructions of identical opcode and #operands. Check to see // if all operands are the same type for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (getOperand(i)->getType() != I->getOperand(i)->getType()) + if (UseScalarTypes ? + getOperand(i)->getType()->getScalarType() != + I->getOperand(i)->getType()->getScalarType() : + getOperand(i)->getType() != I->getOperand(i)->getType()) return false; // Check special state that is a part of some instructions. if (const LoadInst *LI = dyn_cast<LoadInst>(this)) return LI->isVolatile() == cast<LoadInst>(I)->isVolatile() && - LI->getAlignment() == cast<LoadInst>(I)->getAlignment() && + (LI->getAlignment() == cast<LoadInst>(I)->getAlignment() || + IgnoreAlignment) && LI->getOrdering() == cast<LoadInst>(I)->getOrdering() && LI->getSynchScope() == cast<LoadInst>(I)->getSynchScope(); if (const StoreInst *SI = dyn_cast<StoreInst>(this)) return SI->isVolatile() == cast<StoreInst>(I)->isVolatile() && - SI->getAlignment() == cast<StoreInst>(I)->getAlignment() && + (SI->getAlignment() == cast<StoreInst>(I)->getAlignment() || + IgnoreAlignment) && SI->getOrdering() == cast<StoreInst>(I)->getOrdering() && SI->getSynchScope() == cast<StoreInst>(I)->getSynchScope(); if (const CmpInst *CI = dyn_cast<CmpInst>(this)) @@ -388,6 +406,29 @@ bool Instruction::isCommutative(unsigned op) { } } +/// isIdempotent - Return true if the instruction is idempotent: +/// +/// Idempotent operators satisfy: x op x === x +/// +/// In LLVM, the And and Or operators are idempotent. +/// +bool Instruction::isIdempotent(unsigned Opcode) { + return Opcode == And || Opcode == Or; +} + +/// isNilpotent - Return true if the instruction is nilpotent: +/// +/// Nilpotent operators satisfy: x op x === Id, +/// +/// where Id is the identity for the operator, i.e. a constant such that +/// x op Id === x and Id op x === x for all x. +/// +/// In LLVM, the Xor operator is nilpotent. +/// +bool Instruction::isNilpotent(unsigned Opcode) { + return Opcode == Xor; +} + Instruction *Instruction::clone() const { Instruction *New = clone_impl(); New->SubclassOptionalData = SubclassOptionalData; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 6c5db32..9af98e8 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -161,8 +161,14 @@ Value *PHINode::hasConstantValue() const { // Exploit the fact that phi nodes always have at least one entry. Value *ConstantValue = getIncomingValue(0); for (unsigned i = 1, e = getNumIncomingValues(); i != e; ++i) - if (getIncomingValue(i) != ConstantValue) - return 0; // Incoming values not all the same. + if (getIncomingValue(i) != ConstantValue && getIncomingValue(i) != this) { + if (ConstantValue != this) + return 0; // Incoming values not all the same. + // The case where the first value is this PHI. + ConstantValue = getIncomingValue(i); + } + if (ConstantValue == this) + return UndefValue::get(getType()); return ConstantValue; } @@ -3158,6 +3164,7 @@ SwitchInst::SwitchInst(const SwitchInst &SI) OL[i] = InOL[i]; OL[i+1] = InOL[i+1]; } + TheSubsets = SI.TheSubsets; SubclassOptionalData = SI.SubclassOptionalData; } @@ -3169,6 +3176,16 @@ SwitchInst::~SwitchInst() { /// addCase - Add an entry to the switch instruction... /// void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { + IntegersSubsetToBB Mapping; + + // FIXME: Currently we work with ConstantInt based cases. + // So inititalize IntItem container directly from ConstantInt. + Mapping.add(IntItem::fromConstantInt(OnVal)); + IntegersSubset CaseRanges = Mapping.getCase(); + addCase(CaseRanges, Dest); +} + +void SwitchInst::addCase(IntegersSubset& OnVal, BasicBlock *Dest) { unsigned NewCaseIdx = getNumCases(); unsigned OpNo = NumOperands; if (OpNo+2 > ReservedSpace) @@ -3176,14 +3193,17 @@ void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { // Initialize some new operands. assert(OpNo+1 < ReservedSpace && "Growing didn't work!"); NumOperands = OpNo+2; - CaseIt Case(this, NewCaseIdx); - Case.setValue(OnVal); + + SubsetsIt TheSubsetsIt = TheSubsets.insert(TheSubsets.end(), OnVal); + + CaseIt Case(this, NewCaseIdx, TheSubsetsIt); + Case.updateCaseValueOperand(OnVal); Case.setSuccessor(Dest); } /// removeCase - This method removes the specified case and its successor /// from the switch instruction. -void SwitchInst::removeCase(CaseIt i) { +void SwitchInst::removeCase(CaseIt& i) { unsigned idx = i.getCaseIndex(); assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!"); @@ -3200,6 +3220,16 @@ void SwitchInst::removeCase(CaseIt i) { // Nuke the last value. OL[NumOps-2].set(0); OL[NumOps-2+1].set(0); + + // Do the same with TheCases collection: + if (i.SubsetIt != --TheSubsets.end()) { + *i.SubsetIt = TheSubsets.back(); + TheSubsets.pop_back(); + } else { + TheSubsets.pop_back(); + i.SubsetIt = TheSubsets.end(); + } + NumOperands = NumOps-2; } diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index 090b09a..95e5a8b 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/Support/ConstantRange.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/ValueHandle.h" using namespace llvm; @@ -66,7 +67,11 @@ public: MDNodeOperand(Value *V) : CallbackVH(V) {} ~MDNodeOperand() {} - void set(Value *V) { this->setValPtr(V); } + void set(Value *V) { + unsigned IsFirst = this->getValPtrInt(); + this->setValPtr(V); + this->setAsFirstOperand(IsFirst); + } /// setAsFirstOperand - Accessor method to mark the operand as the first in /// the list. @@ -95,7 +100,7 @@ void MDNodeOperand::allUsesReplacedWith(Value *NV) { static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) { // Use <= instead of < to permit a one-past-the-end address. assert(Op <= N->getNumOperands() && "Invalid operand number"); - return reinterpret_cast<MDNodeOperand*>(N+1)+Op; + return reinterpret_cast<MDNodeOperand*>(N + 1) + Op; } void MDNode::replaceOperandWith(unsigned i, Value *Val) { @@ -122,7 +127,6 @@ MDNode::MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal) } } - /// ~MDNode - Destroy MDNode. MDNode::~MDNode() { assert((getSubclassDataFromValue() & DestroyFlag) != 0 && @@ -196,7 +200,7 @@ const Function *MDNode::getFunction() const { // destroy - Delete this node. Only when there are no uses. void MDNode::destroy() { setValueSubclassData(getSubclassDataFromValue() | DestroyFlag); - // Placement delete, the free the memory. + // Placement delete, then free the memory. this->~MDNode(); free(this); } @@ -247,7 +251,7 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals, } // Coallocate space for the node and Operands together, then placement new. - void *Ptr = malloc(sizeof(MDNode)+Vals.size()*sizeof(MDNodeOperand)); + void *Ptr = malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); N = new (Ptr) MDNode(Context, Vals, isFunctionLocal); // Cache the operand hash. @@ -275,7 +279,7 @@ MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals) { MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals) { MDNode *N = - (MDNode *)malloc(sizeof(MDNode)+Vals.size()*sizeof(MDNodeOperand)); + (MDNode *)malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); N = new (N) MDNode(Context, Vals, FL_No); N->setValueSubclassData(N->getSubclassDataFromValue() | NotUniquedBit); @@ -398,6 +402,155 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { } } +MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) { + if (!A || !B) + return NULL; + + if (A == B) + return A; + + SmallVector<MDNode *, 4> PathA; + MDNode *T = A; + while (T) { + PathA.push_back(T); + T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0; + } + + SmallVector<MDNode *, 4> PathB; + T = B; + while (T) { + PathB.push_back(T); + T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0; + } + + int IA = PathA.size() - 1; + int IB = PathB.size() - 1; + + MDNode *Ret = 0; + while (IA >= 0 && IB >=0) { + if (PathA[IA] == PathB[IB]) + Ret = PathA[IA]; + else + break; + --IA; + --IB; + } + return Ret; +} + +MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { + if (!A || !B) + return NULL; + + APFloat AVal = cast<ConstantFP>(A->getOperand(0))->getValueAPF(); + APFloat BVal = cast<ConstantFP>(B->getOperand(0))->getValueAPF(); + if (AVal.compare(BVal) == APFloat::cmpLessThan) + return A; + return B; +} + +static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { + return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); +} + +static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) { + return !A.intersectWith(B).isEmptySet() || isContiguous(A, B); +} + +static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low, + ConstantInt *High) { + ConstantRange NewRange(Low->getValue(), High->getValue()); + unsigned Size = EndPoints.size(); + APInt LB = cast<ConstantInt>(EndPoints[Size - 2])->getValue(); + APInt LE = cast<ConstantInt>(EndPoints[Size - 1])->getValue(); + ConstantRange LastRange(LB, LE); + if (canBeMerged(NewRange, LastRange)) { + ConstantRange Union = LastRange.unionWith(NewRange); + Type *Ty = High->getType(); + EndPoints[Size - 2] = ConstantInt::get(Ty, Union.getLower()); + EndPoints[Size - 1] = ConstantInt::get(Ty, Union.getUpper()); + return true; + } + return false; +} + +static void addRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low, + ConstantInt *High) { + if (!EndPoints.empty()) + if (tryMergeRange(EndPoints, Low, High)) + return; + + EndPoints.push_back(Low); + EndPoints.push_back(High); +} + +MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) { + // Given two ranges, we want to compute the union of the ranges. This + // is slightly complitade by having to combine the intervals and merge + // the ones that overlap. + + if (!A || !B) + return NULL; + + if (A == B) + return A; + + // First, walk both lists in older of the lower boundary of each interval. + // At each step, try to merge the new interval to the last one we adedd. + SmallVector<Value*, 4> EndPoints; + int AI = 0; + int BI = 0; + int AN = A->getNumOperands() / 2; + int BN = B->getNumOperands() / 2; + while (AI < AN && BI < BN) { + ConstantInt *ALow = cast<ConstantInt>(A->getOperand(2 * AI)); + ConstantInt *BLow = cast<ConstantInt>(B->getOperand(2 * BI)); + + if (ALow->getValue().slt(BLow->getValue())) { + addRange(EndPoints, ALow, cast<ConstantInt>(A->getOperand(2 * AI + 1))); + ++AI; + } else { + addRange(EndPoints, BLow, cast<ConstantInt>(B->getOperand(2 * BI + 1))); + ++BI; + } + } + while (AI < AN) { + addRange(EndPoints, cast<ConstantInt>(A->getOperand(2 * AI)), + cast<ConstantInt>(A->getOperand(2 * AI + 1))); + ++AI; + } + while (BI < BN) { + addRange(EndPoints, cast<ConstantInt>(B->getOperand(2 * BI)), + cast<ConstantInt>(B->getOperand(2 * BI + 1))); + ++BI; + } + + // If we have more than 2 ranges (4 endpoints) we have to try to merge + // the last and first ones. + unsigned Size = EndPoints.size(); + if (Size > 4) { + ConstantInt *FB = cast<ConstantInt>(EndPoints[0]); + ConstantInt *FE = cast<ConstantInt>(EndPoints[1]); + if (tryMergeRange(EndPoints, FB, FE)) { + for (unsigned i = 0; i < Size - 2; ++i) { + EndPoints[i] = EndPoints[i + 2]; + } + EndPoints.resize(Size - 2); + } + } + + // If in the end we have a single range, it is possible that it is now the + // full range. Just drop the metadata in that case. + if (EndPoints.size() == 2) { + ConstantRange Range(cast<ConstantInt>(EndPoints[0])->getValue(), + cast<ConstantInt>(EndPoints[1])->getValue()); + if (Range.isFullSet()) + return NULL; + } + + return MDNode::get(A->getContext(), EndPoints); +} + //===----------------------------------------------------------------------===// // NamedMDNode implementation. // diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp index 3c67191..5b5176b 100644 --- a/lib/VMCore/Module.cpp +++ b/lib/VMCore/Module.cpp @@ -65,20 +65,20 @@ Module::~Module() { Module::Endianness Module::getEndianness() const { StringRef temp = DataLayout; Module::Endianness ret = AnyEndianness; - + while (!temp.empty()) { std::pair<StringRef, StringRef> P = getToken(temp, "-"); - + StringRef token = P.first; temp = P.second; - + if (token[0] == 'e') { ret = LittleEndian; } else if (token[0] == 'E') { ret = BigEndian; } } - + return ret; } @@ -86,13 +86,13 @@ Module::Endianness Module::getEndianness() const { Module::PointerSize Module::getPointerSize() const { StringRef temp = DataLayout; Module::PointerSize ret = AnyPointerSize; - + while (!temp.empty()) { std::pair<StringRef, StringRef> TmpP = getToken(temp, "-"); temp = TmpP.second; TmpP = getToken(TmpP.first, ":"); StringRef token = TmpP.second, signalToken = TmpP.first; - + if (signalToken[0] == 'p') { int size = 0; getToken(token, ":").first.getAsInteger(10, size); @@ -102,7 +102,7 @@ Module::PointerSize Module::getPointerSize() const { ret = Pointer64; } } - + return ret; } @@ -164,9 +164,9 @@ Constant *Module::getOrInsertFunction(StringRef Name, // right type. if (F->getType() != PointerType::getUnqual(Ty)) return ConstantExpr::getBitCast(F, PointerType::getUnqual(Ty)); - + // Otherwise, we just found the existing function or a prototype. - return F; + return F; } Constant *Module::getOrInsertTargetIntrinsic(StringRef Name, @@ -183,13 +183,12 @@ Constant *Module::getOrInsertTargetIntrinsic(StringRef Name, } // Otherwise, we just found the existing function or a prototype. - return F; + return F; } Constant *Module::getOrInsertFunction(StringRef Name, FunctionType *Ty) { - AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0); - return getOrInsertFunction(Name, Ty, AttributeList); + return getOrInsertFunction(Name, Ty, AttrListPtr()); } // getOrInsertFunction - Look up the specified function in the module symbol @@ -229,9 +228,9 @@ Constant *Module::getOrInsertFunction(StringRef Name, va_end(Args); // Build the function type and chain to the other getOrInsertFunction... - return getOrInsertFunction(Name, + return getOrInsertFunction(Name, FunctionType::get(RetTy, ArgTys, false), - AttrListPtr::get((AttributeWithIndex *)0, 0)); + AttrListPtr()); } // getFunction - Look up the specified function in the module symbol table. @@ -254,7 +253,7 @@ Function *Module::getFunction(StringRef Name) const { /// GlobalVariable *Module::getGlobalVariable(StringRef Name, bool AllowLocal) const { - if (GlobalVariable *Result = + if (GlobalVariable *Result = dyn_cast_or_null<GlobalVariable>(getNamedValue(Name))) if (AllowLocal || !Result->hasLocalLinkage()) return Result; @@ -282,7 +281,7 @@ Constant *Module::getOrInsertGlobal(StringRef Name, Type *Ty) { // right type. if (GV->getType() != PointerType::getUnqual(Ty)) return ConstantExpr::getBitCast(GV, PointerType::getUnqual(Ty)); - + // Otherwise, we just found the existing function or a prototype. return GV; } @@ -299,7 +298,7 @@ GlobalAlias *Module::getNamedAlias(StringRef Name) const { } /// getNamedMetadata - Return the first NamedMDNode in the module with the -/// specified name. This method returns null if a NamedMDNode with the +/// specified name. This method returns null if a NamedMDNode with the /// specified name is not found. NamedMDNode *Module::getNamedMetadata(const Twine &Name) const { SmallString<256> NameData; @@ -307,8 +306,8 @@ NamedMDNode *Module::getNamedMetadata(const Twine &Name) const { return static_cast<StringMap<NamedMDNode*> *>(NamedMDSymTab)->lookup(NameRef); } -/// getOrInsertNamedMetadata - Return the first named MDNode in the module -/// with the specified name. This method returns a new NamedMDNode if a +/// getOrInsertNamedMetadata - Return the first named MDNode in the module +/// with the specified name. This method returns a new NamedMDNode if a /// NamedMDNode with the specified name is not found. NamedMDNode *Module::getOrInsertNamedMetadata(StringRef Name) { NamedMDNode *&NMD = @@ -468,128 +467,3 @@ void Module::removeLibrary(StringRef Lib) { return; } } - -//===----------------------------------------------------------------------===// -// Type finding functionality. -//===----------------------------------------------------------------------===// - -namespace { - /// TypeFinder - Walk over a module, identifying all of the types that are - /// used by the module. - class TypeFinder { - // To avoid walking constant expressions multiple times and other IR - // objects, we keep several helper maps. - DenseSet<const Value*> VisitedConstants; - DenseSet<Type*> VisitedTypes; - - std::vector<StructType*> &StructTypes; - public: - TypeFinder(std::vector<StructType*> &structTypes) - : StructTypes(structTypes) {} - - void run(const Module &M) { - // Get types from global variables. - for (Module::const_global_iterator I = M.global_begin(), - E = M.global_end(); I != E; ++I) { - incorporateType(I->getType()); - if (I->hasInitializer()) - incorporateValue(I->getInitializer()); - } - - // Get types from aliases. - for (Module::const_alias_iterator I = M.alias_begin(), - E = M.alias_end(); I != E; ++I) { - incorporateType(I->getType()); - if (const Value *Aliasee = I->getAliasee()) - incorporateValue(Aliasee); - } - - SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; - - // Get types from functions. - for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) { - incorporateType(FI->getType()); - - for (Function::const_iterator BB = FI->begin(), E = FI->end(); - BB != E;++BB) - for (BasicBlock::const_iterator II = BB->begin(), - E = BB->end(); II != E; ++II) { - const Instruction &I = *II; - // Incorporate the type of the instruction and all its operands. - incorporateType(I.getType()); - for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); - OI != OE; ++OI) - incorporateValue(*OI); - - // Incorporate types hiding in metadata. - I.getAllMetadataOtherThanDebugLoc(MDForInst); - for (unsigned i = 0, e = MDForInst.size(); i != e; ++i) - incorporateMDNode(MDForInst[i].second); - MDForInst.clear(); - } - } - - for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), - E = M.named_metadata_end(); I != E; ++I) { - const NamedMDNode *NMD = I; - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - incorporateMDNode(NMD->getOperand(i)); - } - } - - private: - void incorporateType(Type *Ty) { - // Check to see if we're already visited this type. - if (!VisitedTypes.insert(Ty).second) - return; - - // If this is a structure or opaque type, add a name for the type. - if (StructType *STy = dyn_cast<StructType>(Ty)) - StructTypes.push_back(STy); - - // Recursively walk all contained types. - for (Type::subtype_iterator I = Ty->subtype_begin(), - E = Ty->subtype_end(); I != E; ++I) - incorporateType(*I); - } - - /// incorporateValue - This method is used to walk operand lists finding - /// types hiding in constant expressions and other operands that won't be - /// walked in other ways. GlobalValues, basic blocks, instructions, and - /// inst operands are all explicitly enumerated. - void incorporateValue(const Value *V) { - if (const MDNode *M = dyn_cast<MDNode>(V)) - return incorporateMDNode(M); - if (!isa<Constant>(V) || isa<GlobalValue>(V)) return; - - // Already visited? - if (!VisitedConstants.insert(V).second) - return; - - // Check this type. - incorporateType(V->getType()); - - // Look in operands for types. - const User *U = cast<User>(V); - for (Constant::const_op_iterator I = U->op_begin(), - E = U->op_end(); I != E;++I) - incorporateValue(*I); - } - - void incorporateMDNode(const MDNode *V) { - - // Already visited? - if (!VisitedConstants.insert(V).second) - return; - - // Look in operands for types. - for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) - if (Value *Op = V->getOperand(i)) - incorporateValue(Op); - } - }; -} // end anonymous namespace - -void Module::findUsedStructTypes(std::vector<StructType*> &StructTypes) const { - TypeFinder(StructTypes).run(*this); -} diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index 28fbaa6..4530c04 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -478,8 +478,7 @@ PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) { /// Set pass P as the last user of the given analysis passes. void -PMTopLevelManager::setLastUser(const SmallVectorImpl<Pass *> &AnalysisPasses, - Pass *P) { +PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) { unsigned PDepth = 0; if (P->getResolver()) PDepth = P->getResolver()->getPMDataManager().getDepth(); @@ -594,6 +593,26 @@ void PMTopLevelManager::schedulePass(Pass *P) { Pass *AnalysisPass = findAnalysisPass(*I); if (!AnalysisPass) { const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I); + + if (PI == NULL) { + // Pass P is not in the global PassRegistry + dbgs() << "Pass '" << P->getPassName() << "' is not initialized." << "\n"; + dbgs() << "Verify if there is a pass dependency cycle." << "\n"; + dbgs() << "Required Passes:" << "\n"; + for (AnalysisUsage::VectorType::const_iterator I2 = RequiredSet.begin(), + E = RequiredSet.end(); I2 != E && I2 != I; ++I2) { + Pass *AnalysisPass2 = findAnalysisPass(*I2); + if (AnalysisPass2) { + dbgs() << "\t" << AnalysisPass2->getPassName() << "\n"; + } + else { + dbgs() << "\t" << "Error: Required pass not found! Possible causes:" << "\n"; + dbgs() << "\t\t" << "- Pass misconfiguration (e.g.: missing macros)" << "\n"; + dbgs() << "\t\t" << "- Corruption of the global PassRegistry" << "\n"; + } + } + } + assert(PI && "Expected required passes to be initialized"); AnalysisPass = PI->createPass(); if (P->getPotentialPassManagerType () == diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index c6f3558..5e9a00f 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -464,19 +464,26 @@ void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) { void StructType::setName(StringRef Name) { if (Name == getName()) return; - // If this struct already had a name, remove its symbol table entry. - if (SymbolTableEntry) { - getContext().pImpl->NamedStructTypes.erase(getName()); - SymbolTableEntry = 0; - } - + StringMap<StructType *> &SymbolTable = getContext().pImpl->NamedStructTypes; + typedef StringMap<StructType *>::MapEntryTy EntryTy; + + // If this struct already had a name, remove its symbol table entry. Don't + // delete the data yet because it may be part of the new name. + if (SymbolTableEntry) + SymbolTable.remove((EntryTy *)SymbolTableEntry); + // If this is just removing the name, we're done. - if (Name.empty()) + if (Name.empty()) { + if (SymbolTableEntry) { + // Delete the old string data. + ((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator()); + SymbolTableEntry = 0; + } return; + } // Look up the entry for the name. - StringMapEntry<StructType*> *Entry = - &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name); + EntryTy *Entry = &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name); // While we have a name collision, try a random rename. if (Entry->getValue()) { @@ -497,7 +504,10 @@ void StructType::setName(StringRef Name) { // Okay, we found an entry that isn't used. It's us! Entry->setValue(this); - + + // Delete the old string data. + if (SymbolTableEntry) + ((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator()); SymbolTableEntry = Entry; } diff --git a/lib/VMCore/TypeFinder.cpp b/lib/VMCore/TypeFinder.cpp new file mode 100644 index 0000000..4de649f --- /dev/null +++ b/lib/VMCore/TypeFinder.cpp @@ -0,0 +1,148 @@ +//===-- TypeFinder.cpp - Implement the TypeFinder class -------------------===// +// +// 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 TypeFinder class for the VMCore library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TypeFinder.h" +#include "llvm/BasicBlock.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +void TypeFinder::run(const Module &M, bool onlyNamed) { + OnlyNamed = onlyNamed; + + // Get types from global variables. + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + incorporateType(I->getType()); + if (I->hasInitializer()) + incorporateValue(I->getInitializer()); + } + + // Get types from aliases. + for (Module::const_alias_iterator I = M.alias_begin(), + E = M.alias_end(); I != E; ++I) { + incorporateType(I->getType()); + if (const Value *Aliasee = I->getAliasee()) + incorporateValue(Aliasee); + } + + // Get types from functions. + SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; + for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) { + incorporateType(FI->getType()); + + // First incorporate the arguments. + for (Function::const_arg_iterator AI = FI->arg_begin(), + AE = FI->arg_end(); AI != AE; ++AI) + incorporateValue(AI); + + for (Function::const_iterator BB = FI->begin(), E = FI->end(); + BB != E;++BB) + for (BasicBlock::const_iterator II = BB->begin(), + E = BB->end(); II != E; ++II) { + const Instruction &I = *II; + + // Incorporate the type of the instruction. + incorporateType(I.getType()); + + // Incorporate non-instruction operand types. (We are incorporating all + // instructions with this loop.) + for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); + OI != OE; ++OI) + if (!isa<Instruction>(OI)) + incorporateValue(*OI); + + // Incorporate types hiding in metadata. + I.getAllMetadataOtherThanDebugLoc(MDForInst); + for (unsigned i = 0, e = MDForInst.size(); i != e; ++i) + incorporateMDNode(MDForInst[i].second); + + MDForInst.clear(); + } + } + + for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), + E = M.named_metadata_end(); I != E; ++I) { + const NamedMDNode *NMD = I; + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + incorporateMDNode(NMD->getOperand(i)); + } +} + +void TypeFinder::clear() { + VisitedConstants.clear(); + VisitedTypes.clear(); + StructTypes.clear(); +} + +/// incorporateType - This method adds the type to the list of used structures +/// if it's not in there already. +void TypeFinder::incorporateType(Type *Ty) { + // Check to see if we're already visited this type. + if (!VisitedTypes.insert(Ty).second) + return; + + // If this is a structure or opaque type, add a name for the type. + if (StructType *STy = dyn_cast<StructType>(Ty)) + if (!OnlyNamed || STy->hasName()) + StructTypes.push_back(STy); + + // Recursively walk all contained types. + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) + incorporateType(*I); +} + +/// incorporateValue - This method is used to walk operand lists finding types +/// hiding in constant expressions and other operands that won't be walked in +/// other ways. GlobalValues, basic blocks, instructions, and inst operands are +/// all explicitly enumerated. +void TypeFinder::incorporateValue(const Value *V) { + if (const MDNode *M = dyn_cast<MDNode>(V)) + return incorporateMDNode(M); + + if (!isa<Constant>(V) || isa<GlobalValue>(V)) return; + + // Already visited? + if (!VisitedConstants.insert(V).second) + return; + + // Check this type. + incorporateType(V->getType()); + + // If this is an instruction, we incorporate it separately. + if (isa<Instruction>(V)) + return; + + // Look in operands for types. + const User *U = cast<User>(V); + for (Constant::const_op_iterator I = U->op_begin(), + E = U->op_end(); I != E;++I) + incorporateValue(*I); +} + +/// incorporateMDNode - This method is used to walk the operands of an MDNode to +/// find types hiding within. +void TypeFinder::incorporateMDNode(const MDNode *V) { + // Already visited? + if (!VisitedConstants.insert(V).second) + return; + + // Look in operands for types. + for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) + if (Value *Op = V->getOperand(i)) + incorporateValue(Op); +} diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp index 4006b2c..d871108 100644 --- a/lib/VMCore/Value.cpp +++ b/lib/VMCore/Value.cpp @@ -686,6 +686,9 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { #endif } -/// ~CallbackVH. Empty, but defined here to avoid emitting the vtable -/// more than once. -CallbackVH::~CallbackVH() {} +// Default implementation for CallbackVH. +void CallbackVH::allUsesReplacedWith(Value *) {} + +void CallbackVH::deleted() { + setValPtr(NULL); +} diff --git a/lib/VMCore/ValueTypes.cpp b/lib/VMCore/ValueTypes.cpp index 9a8e185..d1ca953 100644 --- a/lib/VMCore/ValueTypes.cpp +++ b/lib/VMCore/ValueTypes.cpp @@ -71,6 +71,10 @@ bool EVT::isExtended512BitVector() const { return isExtendedVector() && getSizeInBits() == 512; } +bool EVT::isExtended1024BitVector() const { + return isExtendedVector() && getSizeInBits() == 1024; +} + EVT EVT::getExtendedVectorElementType() const { assert(isExtended() && "Type is not extended!"); return EVT::getEVT(cast<VectorType>(LLVMTy)->getElementType()); @@ -128,10 +132,12 @@ std::string EVT::getEVTString() const { case MVT::v2i32: return "v2i32"; case MVT::v4i32: return "v4i32"; case MVT::v8i32: return "v8i32"; + case MVT::v16i32: return "v16i32"; case MVT::v1i64: return "v1i64"; case MVT::v2i64: return "v2i64"; case MVT::v4i64: return "v4i64"; case MVT::v8i64: return "v8i64"; + case MVT::v16i64: return "v16i64"; case MVT::v2f32: return "v2f32"; case MVT::v2f16: return "v2f16"; case MVT::v4f32: return "v4f32"; @@ -177,10 +183,12 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const { case MVT::v2i32: return VectorType::get(Type::getInt32Ty(Context), 2); case MVT::v4i32: return VectorType::get(Type::getInt32Ty(Context), 4); case MVT::v8i32: return VectorType::get(Type::getInt32Ty(Context), 8); + case MVT::v16i32: return VectorType::get(Type::getInt32Ty(Context), 16); case MVT::v1i64: return VectorType::get(Type::getInt64Ty(Context), 1); case MVT::v2i64: return VectorType::get(Type::getInt64Ty(Context), 2); case MVT::v4i64: return VectorType::get(Type::getInt64Ty(Context), 4); case MVT::v8i64: return VectorType::get(Type::getInt64Ty(Context), 8); + case MVT::v16i64: return VectorType::get(Type::getInt64Ty(Context), 16); case MVT::v2f16: return VectorType::get(Type::getHalfTy(Context), 2); case MVT::v2f32: return VectorType::get(Type::getFloatTy(Context), 2); case MVT::v4f32: return VectorType::get(Type::getFloatTy(Context), 4); diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 47baef3..6851246 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -68,6 +68,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ConstantRange.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -293,8 +294,9 @@ namespace { void VerifyCallSite(CallSite CS); bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT, unsigned ArgNo, std::string &Suffix); - void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, - unsigned RetNum, unsigned ParamNum, ...); + bool VerifyIntrinsicType(Type *Ty, + ArrayRef<Intrinsic::IITDescriptor> &Infos, + SmallVectorImpl<Type*> &ArgTys); void VerifyParameterAttrs(Attributes Attrs, Type *Ty, bool isReturnValue, const Value *V); void VerifyFunctionAttrs(FunctionType *FT, const AttrListPtr &Attrs, @@ -804,14 +806,29 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { // Check to make sure that all of the constants in the switch instruction // have the same type as the switched-on value. Type *SwitchTy = SI.getCondition()->getType(); - SmallPtrSet<ConstantInt*, 32> Constants; + IntegerType *IntTy = cast<IntegerType>(SwitchTy); + IntegersSubsetToBB Mapping; + std::map<IntegersSubset::Range, unsigned> RangeSetMap; for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { - Assert1(i.getCaseValue()->getType() == SwitchTy, - "Switch constants must all be same type as switch value!", &SI); - Assert2(Constants.insert(i.getCaseValue()), - "Duplicate integer as switch case", &SI, i.getCaseValue()); + IntegersSubset CaseRanges = i.getCaseValueEx(); + for (unsigned ri = 0, rie = CaseRanges.getNumItems(); ri < rie; ++ri) { + IntegersSubset::Range r = CaseRanges.getItem(ri); + Assert1(((const APInt&)r.getLow()).getBitWidth() == IntTy->getBitWidth(), + "Switch constants must all be same type as switch value!", &SI); + Assert1(((const APInt&)r.getHigh()).getBitWidth() == IntTy->getBitWidth(), + "Switch constants must all be same type as switch value!", &SI); + Mapping.add(r); + RangeSetMap[r] = i.getCaseIndex(); + } } - + + IntegersSubsetToBB::RangeIterator errItem; + if (!Mapping.verify(errItem)) { + unsigned CaseIndex = RangeSetMap[errItem->first]; + SwitchInst::CaseIt i(&SI, CaseIndex); + Assert2(false, "Duplicate integer as switch case", &SI, i.getCaseValueEx()); + } + visitTerminatorInst(SI); } @@ -1346,6 +1363,10 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { visitInstruction(GEP); } +static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { + return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); +} + void Verifier::visitLoadInst(LoadInst &LI) { PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); Assert1(PTy, "Load operand must be a pointer.", &LI); @@ -1367,6 +1388,8 @@ void Verifier::visitLoadInst(LoadInst &LI) { Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); unsigned NumRanges = NumOperands / 2; Assert1(NumRanges >= 1, "It should have at least one range!", Range); + + ConstantRange LastRange(1); // Dummy initial value for (unsigned i = 0; i < NumRanges; ++i) { ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i)); Assert1(Low, "The lower limit must be an integer!", Low); @@ -1375,9 +1398,35 @@ void Verifier::visitLoadInst(LoadInst &LI) { Assert1(High->getType() == Low->getType() && High->getType() == ElTy, "Range types must match load type!", &LI); - Assert1(High->getValue() != Low->getValue(), "Range must not be empty!", + + APInt HighV = High->getValue(); + APInt LowV = Low->getValue(); + ConstantRange CurRange(LowV, HighV); + Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(), + "Range must not be empty!", Range); + if (i != 0) { + Assert1(CurRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order", + Range); + Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous", + Range); + } + LastRange = ConstantRange(LowV, HighV); + } + if (NumRanges > 2) { + APInt FirstLow = + dyn_cast<ConstantInt>(Range->getOperand(0))->getValue(); + APInt FirstHigh = + dyn_cast<ConstantInt>(Range->getOperand(1))->getValue(); + ConstantRange FirstRange(FirstLow, FirstHigh); + Assert1(FirstRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous", Range); } + + } visitInstruction(LI); @@ -1487,7 +1536,7 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { // landing pad block may be branched to only by the unwind edge of an invoke. for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) { const InvokeInst *II = dyn_cast<InvokeInst>((*I)->getTerminator()); - Assert1(II && II->getUnwindDest() == BB, + Assert1(II && II->getUnwindDest() == BB && II->getNormalDest() != BB, "Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", &LPI); } @@ -1526,53 +1575,9 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) { void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { Instruction *Op = cast<Instruction>(I.getOperand(i)); - BasicBlock *BB = I.getParent(); - BasicBlock *OpBlock = Op->getParent(); - PHINode *PN = dyn_cast<PHINode>(&I); - - // DT can handle non phi instructions for us. - if (!PN) { - // Definition must dominate use unless use is unreachable! - Assert2(InstsInThisBlock.count(Op) || !DT->isReachableFromEntry(BB) || - DT->dominates(Op, &I), - "Instruction does not dominate all uses!", Op, &I); - return; - } - // Check that a definition dominates all of its uses. - if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { - // Invoke results are only usable in the normal destination, not in the - // exceptional destination. - BasicBlock *NormalDest = II->getNormalDest(); - - - // PHI nodes differ from other nodes because they actually "use" the - // value in the predecessor basic blocks they correspond to. - BasicBlock *UseBlock = BB; - unsigned j = PHINode::getIncomingValueNumForOperand(i); - UseBlock = PN->getIncomingBlock(j); - Assert2(UseBlock, "Invoke operand is PHI node with bad incoming-BB", - Op, &I); - - if (UseBlock == OpBlock) { - // Special case of a phi node in the normal destination or the unwind - // destination. - Assert2(BB == NormalDest || !DT->isReachableFromEntry(UseBlock), - "Invoke result not available in the unwind destination!", - Op, &I); - } else { - Assert2(DT->dominates(II, UseBlock) || - !DT->isReachableFromEntry(UseBlock), - "Invoke result does not dominate all uses!", Op, &I); - } - } - - // PHI nodes are more difficult than other nodes because they actually - // "use" the value in the predecessor basic blocks they correspond to. - unsigned j = PHINode::getIncomingValueNumForOperand(i); - BasicBlock *PredBB = PN->getIncomingBlock(j); - Assert2(PredBB && (DT->dominates(OpBlock, PredBB) || - !DT->isReachableFromEntry(PredBB)), + const Use &U = I.getOperandUse(i); + Assert2(InstsInThisBlock.count(Op) || DT->dominates(Op, U), "Instruction does not dominate all uses!", Op, &I); } @@ -1631,8 +1636,11 @@ void Verifier::visitInstruction(Instruction &I) { if (Function *F = dyn_cast<Function>(I.getOperand(i))) { // Check to make sure that the "address of" an intrinsic function is never // taken. - Assert1(!F->isIntrinsic() || (i + 1 == e && isa<CallInst>(I)), + Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 : 0), "Cannot take the address of an intrinsic!", &I); + Assert1(!F->isIntrinsic() || isa<CallInst>(I) || + F->getIntrinsicID() == Intrinsic::donothing, + "Cannot invoke an intrinsinc other than donothing", &I); Assert1(F->getParent() == Mod, "Referencing function in another module!", &I); } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { @@ -1673,10 +1681,85 @@ void Verifier::visitInstruction(Instruction &I) { InstsInThisBlock.insert(&I); } -// Flags used by TableGen to mark intrinsic parameters with the -// LLVMExtendedElementVectorType and LLVMTruncatedElementVectorType classes. -static const unsigned ExtendedElementVectorType = 0x40000000; -static const unsigned TruncatedElementVectorType = 0x20000000; +/// VerifyIntrinsicType - Verify that the specified type (which comes from an +/// intrinsic argument or return value) matches the type constraints specified +/// by the .td file (e.g. an "any integer" argument really is an integer). +/// +/// This return true on error but does not print a message. +bool Verifier::VerifyIntrinsicType(Type *Ty, + ArrayRef<Intrinsic::IITDescriptor> &Infos, + SmallVectorImpl<Type*> &ArgTys) { + using namespace Intrinsic; + + // If we ran out of descriptors, there are too many arguments. + if (Infos.empty()) return true; + IITDescriptor D = Infos.front(); + Infos = Infos.slice(1); + + switch (D.Kind) { + case IITDescriptor::Void: return !Ty->isVoidTy(); + case IITDescriptor::MMX: return !Ty->isX86_MMXTy(); + case IITDescriptor::Metadata: return !Ty->isMetadataTy(); + case IITDescriptor::Float: return !Ty->isFloatTy(); + case IITDescriptor::Double: return !Ty->isDoubleTy(); + case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); + case IITDescriptor::Vector: { + VectorType *VT = dyn_cast<VectorType>(Ty); + return VT == 0 || VT->getNumElements() != D.Vector_Width || + VerifyIntrinsicType(VT->getElementType(), Infos, ArgTys); + } + case IITDescriptor::Pointer: { + PointerType *PT = dyn_cast<PointerType>(Ty); + return PT == 0 || PT->getAddressSpace() != D.Pointer_AddressSpace || + VerifyIntrinsicType(PT->getElementType(), Infos, ArgTys); + } + + case IITDescriptor::Struct: { + StructType *ST = dyn_cast<StructType>(Ty); + if (ST == 0 || ST->getNumElements() != D.Struct_NumElements) + return true; + + for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) + if (VerifyIntrinsicType(ST->getElementType(i), Infos, ArgTys)) + return true; + return false; + } + + case IITDescriptor::Argument: + // Two cases here - If this is the second occurrence of an argument, verify + // that the later instance matches the previous instance. + if (D.getArgumentNumber() < ArgTys.size()) + return Ty != ArgTys[D.getArgumentNumber()]; + + // Otherwise, if this is the first instance of an argument, record it and + // verify the "Any" kind. + assert(D.getArgumentNumber() == ArgTys.size() && "Table consistency error"); + ArgTys.push_back(Ty); + + switch (D.getArgumentKind()) { + case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy(); + case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); + case IITDescriptor::AK_AnyVector: return !isa<VectorType>(Ty); + case IITDescriptor::AK_AnyPointer: return !isa<PointerType>(Ty); + } + llvm_unreachable("all argument kinds not covered"); + + case IITDescriptor::ExtendVecArgument: + // This may only be used when referring to a previous vector argument. + return D.getArgumentNumber() >= ArgTys.size() || + !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || + VectorType::getExtendedElementVectorType( + cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; + + case IITDescriptor::TruncVecArgument: + // This may only be used when referring to a previous vector argument. + return D.getArgumentNumber() >= ArgTys.size() || + !isa<VectorType>(ArgTys[D.getArgumentNumber()]) || + VectorType::getTruncatedElementVectorType( + cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty; + } + llvm_unreachable("unhandled"); +} /// visitIntrinsicFunction - Allow intrinsics to be verified in different ways. /// @@ -1685,10 +1768,30 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Assert1(IF->isDeclaration(), "Intrinsic functions should never be defined!", IF); -#define GET_INTRINSIC_VERIFIER -#include "llvm/Intrinsics.gen" -#undef GET_INTRINSIC_VERIFIER - + // Verify that the intrinsic prototype lines up with what the .td files + // describe. + FunctionType *IFTy = IF->getFunctionType(); + Assert1(!IFTy->isVarArg(), "Intrinsic prototypes are not varargs", IF); + + SmallVector<Intrinsic::IITDescriptor, 8> Table; + getIntrinsicInfoTableEntries(ID, Table); + ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; + + SmallVector<Type *, 4> ArgTys; + Assert1(!VerifyIntrinsicType(IFTy->getReturnType(), TableRef, ArgTys), + "Intrinsic has incorrect return type!", IF); + for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i) + Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys), + "Intrinsic has incorrect argument type!", IF); + Assert1(TableRef.empty(), "Intrinsic has too few arguments!", IF); + + // Now that we have the intrinsic ID and the actual argument types (and we + // know they are legal for the intrinsic!) get the intrinsic name through the + // usual means. This allows us to verify the mangling of argument types into + // the name. + Assert1(Intrinsic::getName(ID, ArgTys) == IF->getName(), + "Intrinsic name not mangled correctly for type arguments!", IF); + // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. for (unsigned i = 0, e = CI.getNumArgOperands(); i != e; ++i) @@ -1772,261 +1875,6 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { } } -/// Produce a string to identify an intrinsic parameter or return value. -/// The ArgNo value numbers the return values from 0 to NumRets-1 and the -/// parameters beginning with NumRets. -/// -static std::string IntrinsicParam(unsigned ArgNo, unsigned NumRets) { - if (ArgNo >= NumRets) - return "Intrinsic parameter #" + utostr(ArgNo - NumRets); - if (NumRets == 1) - return "Intrinsic result type"; - return "Intrinsic result type #" + utostr(ArgNo); -} - -bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, - int VT, unsigned ArgNo, std::string &Suffix) { - FunctionType *FTy = F->getFunctionType(); - - unsigned NumElts = 0; - Type *EltTy = Ty; - VectorType *VTy = dyn_cast<VectorType>(Ty); - if (VTy) { - EltTy = VTy->getElementType(); - NumElts = VTy->getNumElements(); - } - - Type *RetTy = FTy->getReturnType(); - StructType *ST = dyn_cast<StructType>(RetTy); - unsigned NumRetVals; - if (RetTy->isVoidTy()) - NumRetVals = 0; - else if (ST) - NumRetVals = ST->getNumElements(); - else - NumRetVals = 1; - - if (VT < 0) { - int Match = ~VT; - - // Check flags that indicate a type that is an integral vector type with - // elements that are larger or smaller than the elements of the matched - // type. - if ((Match & (ExtendedElementVectorType | - TruncatedElementVectorType)) != 0) { - IntegerType *IEltTy = dyn_cast<IntegerType>(EltTy); - if (!VTy || !IEltTy) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not " - "an integral vector type.", F); - return false; - } - // Adjust the current Ty (in the opposite direction) rather than - // the type being matched against. - if ((Match & ExtendedElementVectorType) != 0) { - if ((IEltTy->getBitWidth() & 1) != 0) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " vector " - "element bit-width is odd.", F); - return false; - } - Ty = VectorType::getTruncatedElementVectorType(VTy); - } else - Ty = VectorType::getExtendedElementVectorType(VTy); - Match &= ~(ExtendedElementVectorType | TruncatedElementVectorType); - } - - if (Match <= static_cast<int>(NumRetVals - 1)) { - if (ST) - RetTy = ST->getElementType(Match); - - if (Ty != RetTy) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " does not " - "match return type.", F); - return false; - } - } else { - if (Ty != FTy->getParamType(Match - NumRetVals)) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " does not " - "match parameter %" + utostr(Match - NumRetVals) + ".", F); - return false; - } - } - } else if (VT == MVT::iAny) { - if (!EltTy->isIntegerTy()) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not " - "an integer type.", F); - return false; - } - - unsigned GotBits = cast<IntegerType>(EltTy)->getBitWidth(); - Suffix += "."; - - if (EltTy != Ty) - Suffix += "v" + utostr(NumElts); - - Suffix += "i" + utostr(GotBits); - - // Check some constraints on various intrinsics. - switch (ID) { - default: break; // Not everything needs to be checked. - case Intrinsic::bswap: - if (GotBits < 16 || GotBits % 16 != 0) { - CheckFailed("Intrinsic requires even byte width argument", F); - return false; - } - break; - } - } else if (VT == MVT::fAny) { - if (!EltTy->isFloatingPointTy()) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not " - "a floating-point type.", F); - return false; - } - - Suffix += "."; - - if (EltTy != Ty) - Suffix += "v" + utostr(NumElts); - - Suffix += EVT::getEVT(EltTy).getEVTString(); - } else if (VT == MVT::vAny) { - if (!VTy) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not a vector type.", - F); - return false; - } - Suffix += ".v" + utostr(NumElts) + EVT::getEVT(EltTy).getEVTString(); - } else if (VT == MVT::iPTR) { - if (!Ty->isPointerTy()) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not a " - "pointer and a pointer is required.", F); - return false; - } - } else if (VT == MVT::iPTRAny) { - // Outside of TableGen, we don't distinguish iPTRAny (to any address space) - // and iPTR. In the verifier, we can not distinguish which case we have so - // allow either case to be legal. - if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) { - EVT PointeeVT = EVT::getEVT(PTyp->getElementType(), true); - if (PointeeVT == MVT::Other) { - CheckFailed("Intrinsic has pointer to complex type."); - return false; - } - Suffix += ".p" + utostr(PTyp->getAddressSpace()) + - PointeeVT.getEVTString(); - } else { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is not a " - "pointer and a pointer is required.", F); - return false; - } - } else if (EVT((MVT::SimpleValueType)VT).isVector()) { - EVT VVT = EVT((MVT::SimpleValueType)VT); - - // If this is a vector argument, verify the number and type of elements. - if (VVT.getVectorElementType() != EVT::getEVT(EltTy)) { - CheckFailed("Intrinsic prototype has incorrect vector element type!", F); - return false; - } - - if (VVT.getVectorNumElements() != NumElts) { - CheckFailed("Intrinsic prototype has incorrect number of " - "vector elements!", F); - return false; - } - } else if (EVT((MVT::SimpleValueType)VT).getTypeForEVT(Ty->getContext()) != - EltTy) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is wrong!", F); - return false; - } else if (EltTy != Ty) { - CheckFailed(IntrinsicParam(ArgNo, NumRetVals) + " is a vector " - "and a scalar is required.", F); - return false; - } - - return true; -} - -/// VerifyIntrinsicPrototype - TableGen emits calls to this function into -/// Intrinsics.gen. This implements a little state machine that verifies the -/// prototype of intrinsics. -void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, - unsigned NumRetVals, - unsigned NumParams, ...) { - va_list VA; - va_start(VA, NumParams); - FunctionType *FTy = F->getFunctionType(); - - // For overloaded intrinsics, the Suffix of the function name must match the - // types of the arguments. This variable keeps track of the expected - // suffix, to be checked at the end. - std::string Suffix; - - if (FTy->getNumParams() + FTy->isVarArg() != NumParams) { - CheckFailed("Intrinsic prototype has incorrect number of arguments!", F); - return; - } - - Type *Ty = FTy->getReturnType(); - StructType *ST = dyn_cast<StructType>(Ty); - - if (NumRetVals == 0 && !Ty->isVoidTy()) { - CheckFailed("Intrinsic should return void", F); - return; - } - - // Verify the return types. - if (ST && ST->getNumElements() != NumRetVals) { - CheckFailed("Intrinsic prototype has incorrect number of return types!", F); - return; - } - - for (unsigned ArgNo = 0; ArgNo != NumRetVals; ++ArgNo) { - int VT = va_arg(VA, int); // An MVT::SimpleValueType when non-negative. - - if (ST) Ty = ST->getElementType(ArgNo); - if (!PerformTypeCheck(ID, F, Ty, VT, ArgNo, Suffix)) - break; - } - - // Verify the parameter types. - for (unsigned ArgNo = 0; ArgNo != NumParams; ++ArgNo) { - int VT = va_arg(VA, int); // An MVT::SimpleValueType when non-negative. - - if (VT == MVT::isVoid && ArgNo > 0) { - if (!FTy->isVarArg()) - CheckFailed("Intrinsic prototype has no '...'!", F); - break; - } - - if (!PerformTypeCheck(ID, F, FTy->getParamType(ArgNo), VT, - ArgNo + NumRetVals, Suffix)) - break; - } - - va_end(VA); - - // For intrinsics without pointer arguments, if we computed a Suffix then the - // intrinsic is overloaded and we need to make sure that the name of the - // function is correct. We add the suffix to the name of the intrinsic and - // compare against the given function name. If they are not the same, the - // function name is invalid. This ensures that overloading of intrinsics - // uses a sane and consistent naming convention. Note that intrinsics with - // pointer argument may or may not be overloaded so we will check assuming it - // has a suffix and not. - if (!Suffix.empty()) { - std::string Name(Intrinsic::getName(ID)); - if (Name + Suffix != F->getName()) { - CheckFailed("Overloaded intrinsic has incorrect suffix: '" + - F->getName().substr(Name.length()) + "'. It should be '" + - Suffix + "'", F); - } - } - - // Check parameter attributes. - Assert1(F->getAttributes() == Intrinsic::getAttributes(ID), - "Intrinsic has wrong parameter attributes!", F); -} - - //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... //===----------------------------------------------------------------------===// |