diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -39,6 +39,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GVMaterializer.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" #include "llvm/IR/GlobalObject.h" @@ -488,6 +489,13 @@ /// types of a Type*. This is used during upgrades of typed pointer IR in /// opaque pointer mode. DenseMap> ContainedTypeIDs; + /// In some cases, we need to create a type ID for a type that was not + /// explicitly encoded in the bitcode, or we don't know about at the current + /// point. For example, a global may explicitly encode the value type ID, but + /// not have a type ID for the pointer to value type, for which we create a + /// virtual type ID instead. This map stores the new type ID that was created + /// for the given pair of Type and contained type ID. + DenseMap, unsigned> VirtualTypeIDs; DenseMap FunctionTypeIDs; BitcodeReaderValueList ValueList; Optional MDLoader; @@ -595,12 +603,11 @@ StructType *createIdentifiedStructType(LLVMContext &Context); static constexpr unsigned InvalidTypeID = ~0u; - /// Placeholder for value type IDs we don't yet determine. - static constexpr unsigned TODOTypeID = InvalidTypeID - 1; Type *getTypeByID(unsigned ID); Type *getPtrElementTypeByID(unsigned ID); unsigned getContainedTypeID(unsigned ID, unsigned Idx = 0); + unsigned getVirtualTypeID(Type *Ty, ArrayRef ContainedTypeIDs = {}); Value *getFnValueByID(unsigned ID, Type *Ty, unsigned TyID) { if (Ty && Ty->isMetadataTy()) @@ -638,6 +645,8 @@ // have. TypeID = ValueList.getTypeID(ValNo); ResVal = getFnValueByID(ValNo, nullptr, TypeID); + assert((!ResVal || ResVal->getType() == getTypeByID(TypeID)) && + "Incorrect type ID stored for value"); return ResVal == nullptr; } if (Slot == Record.size()) @@ -693,7 +702,7 @@ /// Upgrades old-style typeless byval/sret/inalloca attributes by adding the /// corresponding argument's pointee type. Also upgrades intrinsics that now /// require an elementtype attribute. - void propagateAttributeTypes(CallBase *CB, ArrayRef ArgsTys); + void propagateAttributeTypes(CallBase *CB, ArrayRef ArgsTys); /// Converts alignment exponent (i.e. power of two (or zero)) to the /// corresponding alignment to use. If alignment is too large, returns @@ -1188,9 +1197,6 @@ } unsigned BitcodeReader::getContainedTypeID(unsigned ID, unsigned Idx) { - if (ID == TODOTypeID) - return TODOTypeID; - auto It = ContainedTypeIDs.find(ID); if (It == ContainedTypeIDs.end()) return InvalidTypeID; @@ -1218,6 +1224,41 @@ return ElemTy; } +unsigned BitcodeReader::getVirtualTypeID(Type *Ty, + ArrayRef ChildTypeIDs) { + unsigned ChildTypeID = ChildTypeIDs.empty() ? InvalidTypeID : ChildTypeIDs[0]; + auto CacheKey = std::make_pair(Ty, ChildTypeID); + auto It = VirtualTypeIDs.find(CacheKey); + if (It != VirtualTypeIDs.end()) { + // The cmpxchg return value is the only place we need more than one + // contained type ID, however the second one will always be the same (i1), + // so we don't need to include it in the cache key. This asserts that the + // contained types are indeed as expected and there are no collisions. + assert((ChildTypeIDs.empty() || + ContainedTypeIDs[It->second] == ChildTypeIDs) && + "Incorrect cached contained type IDs"); + return It->second; + } + +#ifndef NDEBUG + if (!Ty->isOpaquePointerTy()) { + assert(Ty->getNumContainedTypes() == ChildTypeIDs.size() && + "Wrong number of contained types"); + for (auto Pair : zip(Ty->subtypes(), ChildTypeIDs)) { + assert(std::get<0>(Pair) == getTypeByID(std::get<1>(Pair)) && + "Incorrect contained type ID"); + } + } +#endif + + unsigned TypeID = TypeList.size(); + TypeList.push_back(Ty); + if (!ChildTypeIDs.empty()) + append_range(ContainedTypeIDs[TypeID], ChildTypeIDs); + VirtualTypeIDs.insert({CacheKey, TypeID}); + return TypeID; +} + StructType *BitcodeReader::createIdentifiedStructType(LLVMContext &Context, StringRef Name) { auto *Ret = StructType::create(Context, Name); @@ -2406,8 +2447,9 @@ SmallVector Record; // Read all the records for this value table. - unsigned CurTyID = TODOTypeID; Type *CurTy = Type::getInt32Ty(Context); + unsigned Int32TyID = getVirtualTypeID(CurTy); + unsigned CurTyID = Int32TyID; Type *CurElemTy = nullptr; unsigned NextCstNo = ValueList.size(); @@ -2460,18 +2502,22 @@ Constant *Op1 = ValueList.getConstantFwdRef(Op1Idx, OpTy, OpTyID); Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), RTy->getElementCount()); - Constant *Op2 = ValueList.getConstantFwdRef(Op2Idx, ShufTy, TODOTypeID); + Constant *Op2 = ValueList.getConstantFwdRef( + Op2Idx, ShufTy, getVirtualTypeID(ShufTy, Int32TyID)); if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2)) return error("Invalid shufflevector operands"); SmallVector Mask; ShuffleVectorInst::getShuffleMask(Op2, Mask); Value *V = ConstantExpr::getShuffleVector(Op0, Op1, Mask); - ValueList.assignValue(CstNo, V, TODOTypeID); + ValueList.assignValue( + CstNo, V, + getVirtualTypeID(V->getType(), getContainedTypeID(OpTyID))); } for (auto &DelayedSelector : DelayedSelectors) { Type *OpTy = DelayedSelector.OpTy; unsigned OpTyID = DelayedSelector.OpTyID; Type *SelectorTy = Type::getInt1Ty(Context); + unsigned SelectorTyID = getVirtualTypeID(SelectorTy); uint64_t Op0Idx = DelayedSelector.Op0Idx; uint64_t Op1Idx = DelayedSelector.Op1Idx; uint64_t Op2Idx = DelayedSelector.Op2Idx; @@ -2483,13 +2529,15 @@ if (VectorType *VTy = dyn_cast(OpTy)) { Value *V = ValueList[Op0Idx]; assert(V); - if (SelectorTy != V->getType()) + if (SelectorTy != V->getType()) { SelectorTy = VectorType::get(SelectorTy, VTy->getElementCount()); + SelectorTyID = getVirtualTypeID(SelectorTy, SelectorTyID); + } } Constant *Op0 = - ValueList.getConstantFwdRef(Op0Idx, SelectorTy, TODOTypeID); + ValueList.getConstantFwdRef(Op0Idx, SelectorTy, SelectorTyID); Value *V = ConstantExpr::getSelect(Op0, Op1, Op2); - ValueList.assignValue(CstNo, V, TODOTypeID); + ValueList.assignValue(CstNo, V, OpTyID); } if (NextCstNo != ValueList.size()) @@ -2834,7 +2882,7 @@ } else { // Deprecated, but still needed to read old bitcode files. Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context), - TODOTypeID); + Int32TyID); } if (!Op1) return error("Invalid record"); @@ -2860,7 +2908,7 @@ } else { // Deprecated, but still needed to read old bitcode files. Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context), - TODOTypeID); + Int32TyID); } if (!Op2) return error("Invalid record"); @@ -3095,6 +3143,7 @@ } } + assert(V->getType() == getTypeByID(CurTyID) && "Incorrect result type ID"); ValueList.assignValue(NextCstNo, V, CurTyID); ++NextCstNo; } @@ -3387,7 +3436,8 @@ if (!Ty->isPointerTy()) return error("Invalid type for value"); AddressSpace = cast(Ty)->getAddressSpace(); - Ty = getPtrElementTypeByID(Record[0]); + TyID = getContainedTypeID(TyID); + Ty = getTypeByID(TyID); if (!Ty) return error("Missing element type for old-style global"); } @@ -3435,7 +3485,7 @@ else upgradeDLLImportExportLinkage(NewGV, RawLinkage); - ValueList.push_back(NewGV, TyID); + ValueList.push_back(NewGV, getVirtualTypeID(NewGV->getType(), TyID)); // Remember which value to use for the global initializer. if (unsigned InitID = Record[2]) @@ -3613,7 +3663,7 @@ Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18])); } - ValueList.push_back(Func, TODOTypeID); + ValueList.push_back(Func, getVirtualTypeID(Func->getType(), FTyID)); if (OperandInfo.PersonalityFn || OperandInfo.Prefix || OperandInfo.Prologue) FunctionOperands.push_back(OperandInfo); @@ -3656,7 +3706,8 @@ if (!PTy) return error("Invalid type for value"); AddrSpace = PTy->getAddressSpace(); - Ty = getPtrElementTypeByID(TypeID); + TypeID = getContainedTypeID(TypeID); + Ty = getTypeByID(TypeID); if (!Ty) return error("Missing element type for old-style indirect symbol"); } else { @@ -3703,7 +3754,7 @@ OpNum += 2; } - ValueList.push_back(NewGA, TypeID); + ValueList.push_back(NewGA, getVirtualTypeID(NewGA->getType(), TypeID)); IndirectSymbolInits.push_back(std::make_pair(NewGA, Val)); return Error::success(); } @@ -4019,7 +4070,7 @@ } void BitcodeReader::propagateAttributeTypes(CallBase *CB, - ArrayRef ArgsTys) { + ArrayRef ArgTyIDs) { for (unsigned i = 0; i != CB->arg_size(); ++i) { for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet, Attribute::InAlloca}) { @@ -4029,7 +4080,7 @@ CB->removeParamAttr(i, Kind); - Type *PtrEltTy = ArgsTys[i]->getPointerElementType(); + Type *PtrEltTy = getPtrElementTypeByID(ArgTyIDs[i]); Attribute NewAttr; switch (Kind) { case Attribute::ByVal: @@ -4057,7 +4108,7 @@ continue; if (CI.isIndirect && !CB->getParamElementType(ArgNo)) { - Type *ElemTy = ArgsTys[ArgNo]->getPointerElementType(); + Type *ElemTy = getPtrElementTypeByID(ArgTyIDs[ArgNo]); CB->addParamAttr( ArgNo, Attribute::get(Context, Attribute::ElementType, ElemTy)); } @@ -4070,7 +4121,7 @@ case Intrinsic::preserve_array_access_index: case Intrinsic::preserve_struct_access_index: if (!CB->getParamElementType(0)) { - Type *ElTy = ArgsTys[0]->getPointerElementType(); + Type *ElTy = getPtrElementTypeByID(ArgTyIDs[0]); Attribute NewAttr = Attribute::get(Context, Attribute::ElementType, ElTy); CB->addParamAttr(0, NewAttr); } @@ -4351,14 +4402,17 @@ case bitc::FUNC_CODE_INST_GEP: { // GEP: type, [n x operands] unsigned OpNum = 0; + unsigned TyID; Type *Ty; bool InBounds; if (BitCode == bitc::FUNC_CODE_INST_GEP) { InBounds = Record[OpNum++]; - Ty = getTypeByID(Record[OpNum++]); + TyID = Record[OpNum++]; + Ty = getTypeByID(TyID); } else { InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD; + TyID = InvalidTypeID; Ty = nullptr; } @@ -4368,7 +4422,10 @@ return error("Invalid record"); if (!Ty) { - Ty = BasePtr->getType()->getScalarType()->getPointerElementType(); + TyID = getContainedTypeID(BasePtrTypeID); + if (BasePtr->getType()->isVectorTy()) + TyID = getContainedTypeID(TyID); + Ty = getTypeByID(TyID); } else if (!cast(BasePtr->getType()->getScalarType()) ->isOpaqueOrPointeeTypeMatches(Ty)) { return error( @@ -4385,7 +4442,27 @@ } I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx); - ResTypeID = TODOTypeID; + + ResTypeID = TyID; + auto GTI = std::next(gep_type_begin(I)); + for (Value *Idx : drop_begin(cast(I)->indices())) { + unsigned SubType = 0; + if (GTI.isStruct()) { + ConstantInt *IdxC = + Idx->getType()->isVectorTy() + ? cast(cast(Idx)->getSplatValue()) + : cast(Idx); + SubType = IdxC->getZExtValue(); + } + ResTypeID = getContainedTypeID(ResTypeID, SubType); + ++GTI; + } + + // At this point ResTypeID is the result element type. We need a pointer + // or vector of pointer to it. + ResTypeID = getVirtualTypeID(I->getType()->getScalarType(), ResTypeID); + if (I->getType()->isVectorTy()) + ResTypeID = getVirtualTypeID(I->getType(), ResTypeID); InstructionList.push_back(I); if (InBounds) @@ -4491,11 +4568,12 @@ unsigned OpNum = 0; Value *TrueVal, *FalseVal, *Cond; unsigned TypeID; + Type *CondType = Type::getInt1Ty(Context); if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal, TypeID) || popValue(Record, OpNum, NextValueNo, TrueVal->getType(), TypeID, FalseVal) || - popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), - TODOTypeID, Cond)) + popValue(Record, OpNum, NextValueNo, CondType, + getVirtualTypeID(CondType), Cond)) return error("Invalid record"); I = SelectInst::Create(Cond, TrueVal, FalseVal); @@ -4589,7 +4667,8 @@ return error("Invalid type for value"); I = new ShuffleVectorInst(Vec1, Vec2, Mask); - ResTypeID = TODOTypeID; + ResTypeID = + getVirtualTypeID(I->getType(), getContainedTypeID(Vec1TypeID)); InstructionList.push_back(I); break; } @@ -4625,7 +4704,10 @@ I = new FCmpInst((FCmpInst::Predicate)PredVal, LHS, RHS); else I = new ICmpInst((ICmpInst::Predicate)PredVal, LHS, RHS); - ResTypeID = TODOTypeID; + + ResTypeID = getVirtualTypeID(I->getType()->getScalarType()); + if (LHS->getType()->isVectorTy()) + ResTypeID = getVirtualTypeID(I->getType(), ResTypeID); if (FMF.any()) I->setFastMathFlags(FMF); @@ -4667,8 +4749,9 @@ } else { BasicBlock *FalseDest = getBasicBlock(Record[1]); - Value *Cond = getValue(Record, 2, NextValueNo, - Type::getInt1Ty(Context), TODOTypeID); + Type *CondType = Type::getInt1Ty(Context); + Value *Cond = getValue(Record, 2, NextValueNo, CondType, + getVirtualTypeID(CondType)); if (!FalseDest || !Cond) return error("Invalid record"); I = BranchInst::Create(TrueDest, FalseDest, Cond); @@ -4680,8 +4763,9 @@ if (Record.size() != 1 && Record.size() != 2) return error("Invalid record"); unsigned Idx = 0; - Value *CleanupPad = getValue( - Record, Idx++, NextValueNo, Type::getTokenTy(Context), TODOTypeID); + Type *TokenTy = Type::getTokenTy(Context); + Value *CleanupPad = getValue(Record, Idx++, NextValueNo, TokenTy, + getVirtualTypeID(TokenTy)); if (!CleanupPad) return error("Invalid record"); BasicBlock *UnwindDest = nullptr; @@ -4699,8 +4783,9 @@ if (Record.size() != 2) return error("Invalid record"); unsigned Idx = 0; - Value *CatchPad = getValue( - Record, Idx++, NextValueNo, Type::getTokenTy(Context), TODOTypeID); + Type *TokenTy = Type::getTokenTy(Context); + Value *CatchPad = getValue(Record, Idx++, NextValueNo, TokenTy, + getVirtualTypeID(TokenTy)); if (!CatchPad) return error("Invalid record"); BasicBlock *BB = getBasicBlock(Record[Idx++]); @@ -4718,8 +4803,9 @@ unsigned Idx = 0; - Value *ParentPad = getValue( - Record, Idx++, NextValueNo, Type::getTokenTy(Context), TODOTypeID); + Type *TokenTy = Type::getTokenTy(Context); + Value *ParentPad = getValue(Record, Idx++, NextValueNo, TokenTy, + getVirtualTypeID(TokenTy)); unsigned NumHandlers = Record[Idx++]; @@ -4746,7 +4832,7 @@ for (BasicBlock *Handler : Handlers) CatchSwitch->addHandler(Handler); I = CatchSwitch; - ResTypeID = TODOTypeID; + ResTypeID = getVirtualTypeID(I->getType()); InstructionList.push_back(I); break; } @@ -4758,8 +4844,9 @@ unsigned Idx = 0; - Value *ParentPad = getValue( - Record, Idx++, NextValueNo, Type::getTokenTy(Context), TODOTypeID); + Type *TokenTy = Type::getTokenTy(Context); + Value *ParentPad = getValue(Record, Idx++, NextValueNo, TokenTy, + getVirtualTypeID(TokenTy)); unsigned NumArgOperands = Record[Idx++]; @@ -4779,7 +4866,7 @@ I = CleanupPadInst::Create(ParentPad, Args); else I = CatchPadInst::Create(ParentPad, Args); - ResTypeID = TODOTypeID; + ResTypeID = getVirtualTypeID(I->getType()); InstructionList.push_back(I); break; } @@ -4904,9 +4991,11 @@ BasicBlock *NormalBB = getBasicBlock(Record[OpNum++]); BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]); + unsigned FTyID = InvalidTypeID; FunctionType *FTy = nullptr; if ((CCInfo >> 13) & 1) { - FTy = dyn_cast(getTypeByID(Record[OpNum++])); + FTyID = Record[OpNum++]; + FTy = dyn_cast(getTypeByID(FTyID)); if (!FTy) return error("Explicit invoke type is not a function type"); } @@ -4920,8 +5009,8 @@ if (!CalleeTy) return error("Callee is not a pointer"); if (!FTy) { - FTy = - dyn_cast(Callee->getType()->getPointerElementType()); + FTyID = getContainedTypeID(CalleeTypeID); + FTy = dyn_cast_or_null(getTypeByID(FTyID)); if (!FTy) return error("Callee is not of pointer to function type"); } else if (!CalleeTy->isOpaqueOrPointeeTypeMatches(FTy)) @@ -4931,11 +5020,12 @@ return error("Insufficient operands to call"); SmallVector Ops; - SmallVector ArgsTys; + SmallVector ArgTyIDs; for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { - Ops.push_back(getValue(Record, OpNum, NextValueNo, - FTy->getParamType(i), TODOTypeID)); - ArgsTys.push_back(FTy->getParamType(i)); + unsigned ArgTyID = getContainedTypeID(FTyID, i + 1); + Ops.push_back(getValue(Record, OpNum, NextValueNo, FTy->getParamType(i), + ArgTyID)); + ArgTyIDs.push_back(ArgTyID); if (!Ops.back()) return error("Invalid record"); } @@ -4951,19 +5041,19 @@ if (getValueTypePair(Record, OpNum, NextValueNo, Op, OpTypeID)) return error("Invalid record"); Ops.push_back(Op); - ArgsTys.push_back(Op->getType()); + ArgTyIDs.push_back(OpTypeID); } } I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops, OperandBundles); - ResTypeID = TODOTypeID; + ResTypeID = getContainedTypeID(FTyID); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( static_cast(CallingConv::MaxID & CCInfo)); cast(I)->setAttributes(PAL); - propagateAttributeTypes(cast(I), ArgsTys); + propagateAttributeTypes(cast(I), ArgTyIDs); break; } @@ -4989,9 +5079,11 @@ for (unsigned i = 0, e = NumIndirectDests; i != e; ++i) IndirectDests.push_back(getBasicBlock(Record[OpNum++])); + unsigned FTyID = InvalidTypeID; FunctionType *FTy = nullptr; if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) { - FTy = dyn_cast(getTypeByID(Record[OpNum++])); + FTyID = Record[OpNum++]; + FTy = dyn_cast_or_null(getTypeByID(FTyID)); if (!FTy) return error("Explicit call type is not a function type"); } @@ -5005,8 +5097,8 @@ if (!OpTy) return error("Callee is not a pointer type"); if (!FTy) { - FTy = - dyn_cast(Callee->getType()->getPointerElementType()); + FTyID = getContainedTypeID(CalleeTypeID); + FTy = dyn_cast_or_null(getTypeByID(FTyID)); if (!FTy) return error("Callee is not of pointer to function type"); } else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy)) @@ -5016,19 +5108,20 @@ return error("Insufficient operands to call"); SmallVector Args; - SmallVector ArgsTys; + SmallVector ArgTyIDs; // Read the fixed params. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { Value *Arg; + unsigned ArgTyID = getContainedTypeID(FTyID, i + 1); if (FTy->getParamType(i)->isLabelTy()) Arg = getBasicBlock(Record[OpNum]); else Arg = getValue(Record, OpNum, NextValueNo, FTy->getParamType(i), - TODOTypeID); + ArgTyID); if (!Arg) return error("Invalid record"); Args.push_back(Arg); - ArgsTys.push_back(Arg->getType()); + ArgTyIDs.push_back(ArgTyID); } // Read type/value pairs for varargs params. @@ -5042,19 +5135,19 @@ if (getValueTypePair(Record, OpNum, NextValueNo, Op, OpTypeID)) return error("Invalid record"); Args.push_back(Op); - ArgsTys.push_back(Op->getType()); + ArgTyIDs.push_back(OpTypeID); } } I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, OperandBundles); - ResTypeID = TODOTypeID; + ResTypeID = getContainedTypeID(FTyID); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( static_cast((0x7ff & CCInfo) >> bitc::CALL_CCONV)); cast(I)->setAttributes(PAL); - propagateAttributeTypes(cast(I), ArgsTys); + propagateAttributeTypes(cast(I), ArgTyIDs); break; } case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE @@ -5171,9 +5264,11 @@ const uint64_t Rec = Record[3]; const bool InAlloca = Bitfield::get(Rec); const bool SwiftError = Bitfield::get(Rec); - Type *Ty = getTypeByID(Record[0]); + unsigned TyID = Record[0]; + Type *Ty = getTypeByID(TyID); if (!Bitfield::get(Rec)) { - Ty = getPtrElementTypeByID(Record[0]); + TyID = getContainedTypeID(TyID); + Ty = getTypeByID(TyID); if (!Ty) return error("Missing element type for old-style alloca"); } @@ -5204,7 +5299,7 @@ AI->setUsedWithInAlloca(InAlloca); AI->setSwiftError(SwiftError); I = AI; - ResTypeID = TODOTypeID; + ResTypeID = getVirtualTypeID(AI->getType(), TyID); InstructionList.push_back(I); break; } @@ -5225,7 +5320,9 @@ Ty = getTypeByID(ResTypeID); } else { ResTypeID = getContainedTypeID(OpTypeID); - Ty = Op->getType()->getPointerElementType(); + Ty = getTypeByID(ResTypeID); + if (!Ty) + return error("Missing element type for old-style load"); } if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType())) @@ -5261,7 +5358,9 @@ Ty = getTypeByID(ResTypeID); } else { ResTypeID = getContainedTypeID(OpTypeID); - Ty = Op->getType()->getPointerElementType(); + Ty = getTypeByID(ResTypeID); + if (!Ty) + return error("Missing element type for old style atomic load"); } if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType())) @@ -5290,13 +5389,20 @@ unsigned OpNum = 0; Value *Val, *Ptr; unsigned PtrTypeID, ValTypeID; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, PtrTypeID) || - (BitCode == bitc::FUNC_CODE_INST_STORE - ? getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID) - : popValue(Record, OpNum, NextValueNo, - Ptr->getType()->getPointerElementType(), - getContainedTypeID(PtrTypeID), Val)) || - OpNum + 2 != Record.size()) + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, PtrTypeID)) + return error("Invalid record"); + + if (BitCode == bitc::FUNC_CODE_INST_STORE) { + if (getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID)) + return error("Invalid record"); + } else { + ValTypeID = getContainedTypeID(PtrTypeID); + if (popValue(Record, OpNum, NextValueNo, getTypeByID(ValTypeID), + ValTypeID, Val)) + return error("Invalid record"); + } + + if (OpNum + 2 != Record.size()) return error("Invalid record"); if (Error Err = typeCheckLoadStoreInst(Val->getType(), Ptr->getType())) @@ -5320,13 +5426,19 @@ Value *Val, *Ptr; unsigned PtrTypeID, ValTypeID; if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, PtrTypeID) || - !isa(Ptr->getType()) || - (BitCode == bitc::FUNC_CODE_INST_STOREATOMIC - ? getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID) - : popValue(Record, OpNum, NextValueNo, - Ptr->getType()->getPointerElementType(), - getContainedTypeID(PtrTypeID), Val)) || - OpNum + 4 != Record.size()) + !isa(Ptr->getType())) + return error("Invalid record"); + if (BitCode == bitc::FUNC_CODE_INST_STOREATOMIC) { + if (getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID)) + return error("Invalid record"); + } else { + ValTypeID = getContainedTypeID(PtrTypeID); + if (popValue(Record, OpNum, NextValueNo, getTypeByID(ValTypeID), + ValTypeID, Val)) + return error("Invalid record"); + } + + if (OpNum + 4 != Record.size()) return error("Invalid record"); if (Error Err = typeCheckLoadStoreInst(Val->getType(), Ptr->getType())) @@ -5364,8 +5476,7 @@ Value *Cmp = nullptr; unsigned CmpTypeID = getContainedTypeID(PtrTypeID); - if (popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getPointerElementType(), + if (popValue(Record, OpNum, NextValueNo, getTypeByID(CmpTypeID), CmpTypeID, Cmp)) return error("Invalid record"); @@ -5400,7 +5511,6 @@ I = new AtomicCmpXchgInst(Ptr, Cmp, New, Alignment, SuccessOrdering, FailureOrdering, SSID); - ResTypeID = TODOTypeID; cast(I)->setVolatile(Record[OpNum]); if (NumRecords < 8) { @@ -5409,9 +5519,11 @@ // expecting the first component of a modern cmpxchg. CurBB->getInstList().push_back(I); I = ExtractValueInst::Create(I, 0); - ResTypeID = TODOTypeID; + ResTypeID = CmpTypeID; } else { cast(I)->setWeak(Record[OpNum + 4]); + unsigned I1TypeID = getVirtualTypeID(Type::getInt1Ty(Context)); + ResTypeID = getVirtualTypeID(I->getType(), {CmpTypeID, I1TypeID}); } InstructionList.push_back(I); @@ -5475,7 +5587,9 @@ FailureOrdering, SSID); cast(I)->setVolatile(IsVol); cast(I)->setWeak(IsWeak); - ResTypeID = TODOTypeID; + + unsigned I1TypeID = getVirtualTypeID(Type::getInt1Ty(Context)); + ResTypeID = getVirtualTypeID(I->getType(), {CmpTypeID, I1TypeID}); InstructionList.push_back(I); break; @@ -5496,13 +5610,13 @@ return error("Invalid record"); Value *Val = nullptr; + unsigned ValTypeID = InvalidTypeID; if (BitCode == bitc::FUNC_CODE_INST_ATOMICRMW_OLD) { + ValTypeID = getContainedTypeID(PtrTypeID); if (popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getPointerElementType(), - getContainedTypeID(PtrTypeID), Val)) + getTypeByID(ValTypeID), ValTypeID, Val)) return error("Invalid record"); } else { - unsigned ValTypeID; if (getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID)) return error("Invalid record"); } @@ -5537,7 +5651,7 @@ Align(TheModule->getDataLayout().getTypeStoreSize(Val->getType())); I = new AtomicRMWInst(Operation, Ptr, Val, *Alignment, Ordering, SSID); - ResTypeID = TODOTypeID; + ResTypeID = ValTypeID; cast(I)->setVolatile(IsVol); InstructionList.push_back(I); @@ -5572,9 +5686,11 @@ return error("Fast math flags indicator set for call with no FMF"); } + unsigned FTyID = InvalidTypeID; FunctionType *FTy = nullptr; if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) { - FTy = dyn_cast(getTypeByID(Record[OpNum++])); + FTyID = Record[OpNum++]; + FTy = dyn_cast_or_null(getTypeByID(FTyID)); if (!FTy) return error("Explicit call type is not a function type"); } @@ -5588,8 +5704,8 @@ if (!OpTy) return error("Callee is not a pointer type"); if (!FTy) { - FTy = - dyn_cast(Callee->getType()->getPointerElementType()); + FTyID = getContainedTypeID(CalleeTypeID); + FTy = dyn_cast_or_null(getTypeByID(FTyID)); if (!FTy) return error("Callee is not of pointer to function type"); } else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy)) @@ -5599,15 +5715,16 @@ return error("Insufficient operands to call"); SmallVector Args; - SmallVector ArgsTys; + SmallVector ArgTyIDs; // Read the fixed params. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + unsigned ArgTyID = getContainedTypeID(FTyID, i + 1); if (FTy->getParamType(i)->isLabelTy()) Args.push_back(getBasicBlock(Record[OpNum])); else Args.push_back(getValue(Record, OpNum, NextValueNo, - FTy->getParamType(i), TODOTypeID)); - ArgsTys.push_back(FTy->getParamType(i)); + FTy->getParamType(i), ArgTyID)); + ArgTyIDs.push_back(ArgTyID); if (!Args.back()) return error("Invalid record"); } @@ -5623,12 +5740,12 @@ if (getValueTypePair(Record, OpNum, NextValueNo, Op, OpTypeID)) return error("Invalid record"); Args.push_back(Op); - ArgsTys.push_back(Op->getType()); + ArgTyIDs.push_back(OpTypeID); } } I = CallInst::Create(FTy, Callee, Args, OperandBundles); - ResTypeID = TODOTypeID; + ResTypeID = getContainedTypeID(FTyID); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( @@ -5642,7 +5759,7 @@ TCK = CallInst::TCK_NoTail; cast(I)->setTailCallKind(TCK); cast(I)->setAttributes(PAL); - propagateAttributeTypes(cast(I), ArgsTys); + propagateAttributeTypes(cast(I), ArgTyIDs); if (FMF.any()) { if (!isa(I)) return error("Fast-math-flags specified for call without " @@ -5725,7 +5842,8 @@ // Non-void values get registered in the value table for future use. if (!I->getType()->isVoidTy()) { - assert(ResTypeID != InvalidTypeID && "Should have ID for non-void type"); + assert(I->getType() == getTypeByID(ResTypeID) && + "Incorrect result type ID"); ValueList.assignValue(NextValueNo++, I, ResTypeID); } } diff --git a/llvm/test/Bitcode/case-ranges-3.3.ll b/llvm/test/Bitcode/case-ranges-3.3.ll --- a/llvm/test/Bitcode/case-ranges-3.3.ll +++ b/llvm/test/Bitcode/case-ranges-3.3.ll @@ -1,4 +1,5 @@ -; RUN: llvm-dis < %s.bc| FileCheck %s +; RUN: llvm-dis -opaque-pointers=0 < %s.bc| FileCheck %s +; RUN: llvm-dis -opaque-pointers=1 < %s.bc| FileCheck %s ; RUN: verify-uselistorder < %s.bc ; case-ranges.ll.bc was generated by passing this file to llvm-as from the 3.3 diff --git a/llvm/test/Bitcode/function-local-metadata.3.5.ll b/llvm/test/Bitcode/function-local-metadata.3.5.ll --- a/llvm/test/Bitcode/function-local-metadata.3.5.ll +++ b/llvm/test/Bitcode/function-local-metadata.3.5.ll @@ -1,4 +1,5 @@ -; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: llvm-dis -opaque-pointers=0 < %s.bc | FileCheck %s +; RUN: llvm-dis -opaque-pointers=1 < %s.bc | FileCheck %s ; Check that function-local metadata is dropped correctly when it's not a ; direct argument to a call instruction.