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 @@ -451,6 +451,7 @@ std::vector GCTable; std::vector TypeList; + DenseMap FunctionTypes; BitcodeReaderValueList ValueList; Optional MDLoader; std::vector ComdatList; @@ -549,12 +550,42 @@ StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name); StructType *createIdentifiedStructType(LLVMContext &Context); - Type *getTypeByID(unsigned ID); + /// Map all pointer types within \param Ty to the opaque pointer + /// type in the same address space if opaque pointers are being + /// used, otherwise nop. This converts a bitcode-reader internal + /// type into one suitable for use in a Value. + Type *flattenPointerTypes(Type *Ty) { + return Ty; + } + + /// Given a fully structured pointer type (i.e. not opaque), return + /// the flattened form of its element, suitable for use in a Value. + Type *getPointerElementFlatType(Type *Ty) { + return flattenPointerTypes(cast(Ty)->getElementType()); + } + + /// Given a fully structured pointer type, get its element type in + /// both fully structured form, and flattened form suitable for use + /// in a Value. + std::pair getPointerElementTypes(Type *FullTy) { + Type *ElTy = cast(FullTy)->getElementType(); + return std::make_pair(ElTy, flattenPointerTypes(ElTy)); + } + + /// Return the flattened type (suitable for use in a Value) + /// specified by the given \param ID. + Type *getTypeByID(unsigned ID) { + return flattenPointerTypes(getFullyStructuredTypeByID(ID)); + } - Value *getFnValueByID(unsigned ID, Type *Ty) { + /// Return the fully structured (bitcode-reader internal) type + /// corresponding to the given \param ID. + Type *getFullyStructuredTypeByID(unsigned ID); + + Value *getFnValueByID(unsigned ID, Type *Ty, Type **FullTy = nullptr) { if (Ty && Ty->isMetadataTy()) return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID)); - return ValueList.getValueFwdRef(ID, Ty); + return ValueList.getValueFwdRef(ID, Ty, FullTy); } Metadata *getFnMetadataByID(unsigned ID) { @@ -576,7 +607,8 @@ /// Increment Slot past the number of slots used in the record. Return true on /// failure. bool getValueTypePair(SmallVectorImpl &Record, unsigned &Slot, - unsigned InstNum, Value *&ResVal) { + unsigned InstNum, Value *&ResVal, + Type **FullTy = nullptr) { if (Slot == Record.size()) return true; unsigned ValNo = (unsigned)Record[Slot++]; // Adjust the ValNo, if it was encoded relative to the InstNum. @@ -585,7 +617,7 @@ if (ValNo < InstNum) { // If this is not a forward reference, just return the value we already // have. - ResVal = getFnValueByID(ValNo, nullptr); + ResVal = getFnValueByID(ValNo, nullptr, FullTy); return ResVal == nullptr; } if (Slot == Record.size()) @@ -593,6 +625,8 @@ unsigned TypeNo = (unsigned)Record[Slot++]; ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo)); + if (FullTy) + *FullTy = getFullyStructuredTypeByID(TypeNo); return ResVal == nullptr; } @@ -640,7 +674,7 @@ /// Upgrades old-style typeless byval attributes by adding the corresponding /// argument's pointee type. - void propagateByValTypes(CallBase *CB); + void propagateByValTypes(CallBase *CB, ArrayRef ArgsFullTys); /// Converts alignment exponent (i.e. power of two (or zero)) to the /// corresponding alignment to use. If alignment is too large, returns @@ -1101,7 +1135,7 @@ } } -Type *BitcodeReader::getTypeByID(unsigned ID) { +Type *BitcodeReader::getFullyStructuredTypeByID(unsigned ID) { // The type table size is always specified correctly. if (ID >= TypeList.size()) return nullptr; @@ -2183,6 +2217,7 @@ // Read all the records for this value table. Type *CurTy = Type::getInt32Ty(Context); + Type *CurFullTy = Type::getInt32Ty(Context); unsigned NextCstNo = ValueList.size(); while (true) { @@ -2222,7 +2257,8 @@ return error("Invalid record"); if (TypeList[Record[0]] == VoidType) return error("Invalid constant type"); - CurTy = TypeList[Record[0]]; + CurFullTy = TypeList[Record[0]]; + CurTy = flattenPointerTypes(CurFullTy); continue; // Skip the ValueList manipulation. case bitc::CST_CODE_NULL: // NULL V = Constant::getNullValue(CurTy); @@ -2441,7 +2477,10 @@ InBounds = true; SmallVector Elts; + Type *Elt0FullTy = nullptr; while (OpNum != Record.size()) { + if (!Elt0FullTy) + Elt0FullTy = getFullyStructuredTypeByID(Record[OpNum]); Type *ElTy = getTypeByID(Record[OpNum++]); if (!ElTy) return error("Invalid record"); @@ -2452,8 +2491,7 @@ return error("Invalid gep with no operands"); Type *ImplicitPointeeType = - cast(Elts[0]->getType()->getScalarType()) - ->getElementType(); + getPointerElementFlatType(Elt0FullTy->getScalarType()); if (!PointeeType) PointeeType = ImplicitPointeeType; else if (PointeeType != ImplicitPointeeType) @@ -2587,10 +2625,10 @@ AsmStr += (char)Record[2+i]; for (unsigned i = 0; i != ConstStrSize; ++i) ConstrStr += (char)Record[3+AsmStrSize+i]; - PointerType *PTy = cast(CurTy); UpgradeInlineAsmString(&AsmStr); - V = InlineAsm::get(cast(PTy->getElementType()), - AsmStr, ConstrStr, HasSideEffects, IsAlignStack); + V = InlineAsm::get( + cast(getPointerElementFlatType(CurFullTy)), AsmStr, + ConstrStr, HasSideEffects, IsAlignStack); break; } // This version adds support for the asm dialect keywords (e.g., @@ -2613,11 +2651,11 @@ AsmStr += (char)Record[2+i]; for (unsigned i = 0; i != ConstStrSize; ++i) ConstrStr += (char)Record[3+AsmStrSize+i]; - PointerType *PTy = cast(CurTy); UpgradeInlineAsmString(&AsmStr); - V = InlineAsm::get(cast(PTy->getElementType()), - AsmStr, ConstrStr, HasSideEffects, IsAlignStack, - InlineAsm::AsmDialect(AsmDialect)); + V = InlineAsm::get( + cast(getPointerElementFlatType(CurFullTy)), AsmStr, + ConstrStr, HasSideEffects, IsAlignStack, + InlineAsm::AsmDialect(AsmDialect)); break; } case bitc::CST_CODE_BLOCKADDRESS:{ @@ -2663,7 +2701,9 @@ } } - ValueList.assignValue(V, NextCstNo); + assert(V->getType() == flattenPointerTypes(CurFullTy) && + "Incorrect fully structured type provided for Constant"); + ValueList.assignValue(V, NextCstNo, CurFullTy); ++NextCstNo; } } @@ -2919,7 +2959,8 @@ if (Record.size() < 6) return error("Invalid record"); - Type *Ty = getTypeByID(Record[0]); + Type *FullTy = getFullyStructuredTypeByID(Record[0]); + Type *Ty = flattenPointerTypes(FullTy); if (!Ty) return error("Invalid record"); bool isConstant = Record[1] & 1; @@ -2931,7 +2972,7 @@ if (!Ty->isPointerTy()) return error("Invalid type for value"); AddressSpace = cast(Ty)->getAddressSpace(); - Ty = cast(Ty)->getElementType(); + std::tie(FullTy, Ty) = getPointerElementTypes(FullTy); } uint64_t RawLinkage = Record[3]; @@ -2977,7 +3018,10 @@ else upgradeDLLImportExportLinkage(NewGV, RawLinkage); - ValueList.push_back(NewGV); + FullTy = PointerType::get(FullTy, AddressSpace); + assert(NewGV->getType() == flattenPointerTypes(FullTy) && + "Incorrect fully specified type for GlobalVariable"); + ValueList.push_back(NewGV, FullTy); // Remember which value to use for the global initializer. if (unsigned InitID = Record[2]) @@ -3020,13 +3064,14 @@ if (Record.size() < 8) return error("Invalid record"); - Type *Ty = getTypeByID(Record[0]); - if (!Ty) - return error("Invalid record"); - if (auto *PTy = dyn_cast(Ty)) - Ty = PTy->getElementType(); - auto *FTy = dyn_cast(Ty); + Type *FullFTy = getFullyStructuredTypeByID(Record[0]); + Type *FTy = flattenPointerTypes(FullFTy); if (!FTy) + return error("Invalid record"); + if (isa(FTy)) + std::tie(FullFTy, FTy) = getPointerElementTypes(FullFTy); + + if (!isa(FTy)) return error("Invalid type for value"); auto CC = static_cast(Record[1]); if (CC & ~CallingConv::MaxID) @@ -3036,8 +3081,13 @@ if (Record.size() > 16) AddrSpace = Record[16]; - Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage, - AddrSpace, Name, TheModule); + Function *Func = + Function::Create(cast(FTy), GlobalValue::ExternalLinkage, + AddrSpace, Name, TheModule); + + assert(Func->getFunctionType() == flattenPointerTypes(FullFTy) && + "Incorrect fully specified type provided for function"); + FunctionTypes[Func] = cast(FullFTy); Func->setCallingConv(CC); bool isProto = Record[2]; @@ -3048,12 +3098,14 @@ // Upgrade any old-style byval without a type by propagating the argument's // pointee type. There should be no opaque pointers where the byval type is // implicit. - for (auto &Arg : Func->args()) { - if (Arg.hasByValAttr() && !Arg.getParamByValType()) { - Arg.removeAttr(Attribute::ByVal); - Arg.addAttr(Attribute::getWithByValType( - Context, Arg.getType()->getPointerElementType())); - } + for (unsigned i = 0; i != Func->arg_size(); ++i) { + if (!Func->hasParamAttribute(i, Attribute::ByVal)) + continue; + + Type *PTy = cast(FullFTy)->getParamType(i); + Func->removeParamAttr(i, Attribute::ByVal); + Func->addParamAttr(i, Attribute::getWithByValType( + Context, getPointerElementFlatType(PTy))); } unsigned Alignment; @@ -3113,7 +3165,10 @@ if (Record.size() > 18) Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18])); - ValueList.push_back(Func); + Type *FullTy = PointerType::get(FullFTy, AddrSpace); + assert(Func->getType() == flattenPointerTypes(FullTy) && + "Incorrect fully specified type provided for Function"); + ValueList.push_back(Func, FullTy); // If this is a function with a body, remember the prototype we are // creating now, so that we can match up the body with them later. @@ -3142,7 +3197,8 @@ if (Record.size() < (3 + (unsigned)NewRecord)) return error("Invalid record"); unsigned OpNum = 0; - Type *Ty = getTypeByID(Record[OpNum++]); + Type *FullTy = getFullyStructuredTypeByID(Record[OpNum++]); + Type *Ty = flattenPointerTypes(FullTy); if (!Ty) return error("Invalid record"); @@ -3151,7 +3207,7 @@ auto *PTy = dyn_cast(Ty); if (!PTy) return error("Invalid type for value"); - Ty = PTy->getElementType(); + std::tie(FullTy, Ty) = getPointerElementTypes(FullTy); AddrSpace = PTy->getAddressSpace(); } else { AddrSpace = Record[OpNum++]; @@ -3167,6 +3223,9 @@ else NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name, nullptr, TheModule); + + assert(NewGA->getValueType() == flattenPointerTypes(FullTy) && + "Incorrect fully structured type provided for GlobalIndirectSymbol"); // Old bitcode files didn't have visibility field. // Local linkage must have default visibility. if (OpNum != Record.size()) { @@ -3197,7 +3256,10 @@ OpNum += 2; } - ValueList.push_back(NewGA); + FullTy = PointerType::get(FullTy, AddrSpace); + assert(NewGA->getType() == flattenPointerTypes(FullTy) && + "Incorrect fully structured type provided for GlobalIndirectSymbol"); + ValueList.push_back(NewGA, FullTy); IndirectSymbolInits.push_back(std::make_pair(NewGA, Val)); return Error::success(); } @@ -3469,16 +3531,16 @@ return Error::success(); } -void BitcodeReader::propagateByValTypes(CallBase *CB) { - for (unsigned i = 0; i < CB->getNumArgOperands(); ++i) { - if (CB->paramHasAttr(i, Attribute::ByVal) && - !CB->getAttribute(i, Attribute::ByVal).getValueAsType()) { - CB->removeParamAttr(i, Attribute::ByVal); - CB->addParamAttr( - i, Attribute::getWithByValType( - Context, - CB->getArgOperand(i)->getType()->getPointerElementType())); - } +void BitcodeReader::propagateByValTypes(CallBase *CB, + ArrayRef ArgsFullTys) { + for (unsigned i = 0; i != CB->arg_size(); ++i) { + if (!CB->paramHasAttr(i, Attribute::ByVal)) + continue; + + CB->removeParamAttr(i, Attribute::ByVal); + CB->addParamAttr( + i, Attribute::getWithByValType( + Context, getPointerElementFlatType(ArgsFullTys[i]))); } } @@ -3496,9 +3558,13 @@ unsigned ModuleMDLoaderSize = MDLoader->size(); // Add all the function arguments to the value table. - for (Argument &I : F->args()) - ValueList.push_back(&I); - + unsigned ArgNo = 0; + FunctionType *FullFTy = FunctionTypes[F]; + for (Argument &I : F->args()) { + assert(I.getType() == flattenPointerTypes(FullFTy->getParamType(ArgNo)) && + "Incorrect fully specified type for Function Argument"); + ValueList.push_back(&I, FullFTy->getParamType(ArgNo++)); + } unsigned NextValueNo = ValueList.size(); BasicBlock *CurBB = nullptr; unsigned CurBBNo = 0; @@ -3567,6 +3633,7 @@ // Read a record. Record.clear(); Instruction *I = nullptr; + Type *FullTy = nullptr; unsigned BitCode = Stream.readRecord(Entry.ID, Record); switch (BitCode) { default: // Default behavior: reject @@ -3709,7 +3776,8 @@ OpNum+2 != Record.size()) return error("Invalid record"); - Type *ResTy = getTypeByID(Record[OpNum]); + FullTy = getFullyStructuredTypeByID(Record[OpNum]); + Type *ResTy = flattenPointerTypes(FullTy); int Opc = getDecodedCastOpcode(Record[OpNum + 1]); if (Opc == -1 || !ResTy) return error("Invalid record"); @@ -3738,22 +3806,22 @@ if (BitCode == bitc::FUNC_CODE_INST_GEP) { InBounds = Record[OpNum++]; - Ty = getTypeByID(Record[OpNum++]); + FullTy = getFullyStructuredTypeByID(Record[OpNum++]); + Ty = flattenPointerTypes(FullTy); } else { InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD; Ty = nullptr; } Value *BasePtr; - if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr)) + Type *FullBaseTy = nullptr; + if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr, &FullBaseTy)) return error("Invalid record"); - if (!Ty) - Ty = cast(BasePtr->getType()->getScalarType()) - ->getElementType(); - else if (Ty != - cast(BasePtr->getType()->getScalarType()) - ->getElementType()) + if (!Ty) { + std::tie(FullTy, Ty) = + getPointerElementTypes(FullBaseTy->getScalarType()); + } else if (Ty != getPointerElementFlatType(FullBaseTy->getScalarType())) return error( "Explicit gep type does not match pointee type of pointer operand"); @@ -3766,6 +3834,7 @@ } I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx); + FullTy = GetElementPtrInst::getGEPReturnType(FullTy, I, GEPIdx); InstructionList.push_back(I); if (InBounds) @@ -3777,7 +3846,7 @@ // EXTRACTVAL: [opty, opval, n x indices] unsigned OpNum = 0; Value *Agg; - if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + if (getValueTypePair(Record, OpNum, NextValueNo, Agg, &FullTy)) return error("Invalid record"); unsigned RecSize = Record.size(); @@ -3785,26 +3854,25 @@ return error("EXTRACTVAL: Invalid instruction with 0 indices"); SmallVector EXTRACTVALIdx; - Type *CurTy = Agg->getType(); for (; OpNum != RecSize; ++OpNum) { - bool IsArray = CurTy->isArrayTy(); - bool IsStruct = CurTy->isStructTy(); + bool IsArray = FullTy->isArrayTy(); + bool IsStruct = FullTy->isStructTy(); uint64_t Index = Record[OpNum]; if (!IsStruct && !IsArray) return error("EXTRACTVAL: Invalid type"); if ((unsigned)Index != Index) return error("Invalid value"); - if (IsStruct && Index >= CurTy->getStructNumElements()) + if (IsStruct && Index >= FullTy->getStructNumElements()) return error("EXTRACTVAL: Invalid struct index"); - if (IsArray && Index >= CurTy->getArrayNumElements()) + if (IsArray && Index >= FullTy->getArrayNumElements()) return error("EXTRACTVAL: Invalid array index"); EXTRACTVALIdx.push_back((unsigned)Index); if (IsStruct) - CurTy = CurTy->getStructElementType(Index); + FullTy = FullTy->getStructElementType(Index); else - CurTy = CurTy->getArrayElementType(); + FullTy = FullTy->getArrayElementType(); } I = ExtractValueInst::Create(Agg, EXTRACTVALIdx); @@ -3816,7 +3884,7 @@ // INSERTVAL: [opty, opval, opty, opval, n x indices] unsigned OpNum = 0; Value *Agg; - if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + if (getValueTypePair(Record, OpNum, NextValueNo, Agg, &FullTy)) return error("Invalid record"); Value *Val; if (getValueTypePair(Record, OpNum, NextValueNo, Val)) @@ -3862,7 +3930,7 @@ // handles select i1 ... in old bitcode unsigned OpNum = 0; Value *TrueVal, *FalseVal, *Cond; - if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal, &FullTy) || popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) || popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), Cond)) return error("Invalid record"); @@ -3877,7 +3945,7 @@ // handles select i1 or select [N x i1] unsigned OpNum = 0; Value *TrueVal, *FalseVal, *Cond; - if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal, &FullTy) || popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) || getValueTypePair(Record, OpNum, NextValueNo, Cond)) return error("Invalid record"); @@ -3907,12 +3975,13 @@ case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval] unsigned OpNum = 0; Value *Vec, *Idx; - if (getValueTypePair(Record, OpNum, NextValueNo, Vec) || + if (getValueTypePair(Record, OpNum, NextValueNo, Vec, &FullTy) || getValueTypePair(Record, OpNum, NextValueNo, Idx)) return error("Invalid record"); if (!Vec->getType()->isVectorTy()) return error("Invalid type for value"); I = ExtractElementInst::Create(Vec, Idx); + FullTy = FullTy->getVectorElementType(); InstructionList.push_back(I); break; } @@ -3920,7 +3989,7 @@ case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval] unsigned OpNum = 0; Value *Vec, *Elt, *Idx; - if (getValueTypePair(Record, OpNum, NextValueNo, Vec)) + if (getValueTypePair(Record, OpNum, NextValueNo, Vec, &FullTy)) return error("Invalid record"); if (!Vec->getType()->isVectorTy()) return error("Invalid type for value"); @@ -3936,7 +4005,7 @@ case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval] unsigned OpNum = 0; Value *Vec1, *Vec2, *Mask; - if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) || + if (getValueTypePair(Record, OpNum, NextValueNo, Vec1, &FullTy) || popValue(Record, OpNum, NextValueNo, Vec1->getType(), Vec2)) return error("Invalid record"); @@ -3945,6 +4014,8 @@ if (!Vec1->getType()->isVectorTy() || !Vec2->getType()->isVectorTy()) return error("Invalid type for value"); I = new ShuffleVectorInst(Vec1, Vec2, Mask); + FullTy = VectorType::get(FullTy->getVectorElementType(), + Mask->getType()->getVectorNumElements()); InstructionList.push_back(I); break; } @@ -4248,31 +4319,40 @@ BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]); FunctionType *FTy = nullptr; - if (CCInfo >> 13 & 1 && - !(FTy = dyn_cast(getTypeByID(Record[OpNum++])))) - return error("Explicit invoke type is not a function type"); + FunctionType *FullFTy = nullptr; + if ((CCInfo >> 13) & 1) { + FullFTy = + dyn_cast(getFullyStructuredTypeByID(Record[OpNum++])); + if (!FullFTy) + return error("Explicit invoke type is not a function type"); + FTy = cast(flattenPointerTypes(FullFTy)); + } Value *Callee; - if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy)) return error("Invalid record"); PointerType *CalleeTy = dyn_cast(Callee->getType()); if (!CalleeTy) return error("Callee is not a pointer"); if (!FTy) { - FTy = dyn_cast(CalleeTy->getElementType()); - if (!FTy) + FullFTy = + dyn_cast(cast(FullTy)->getElementType()); + if (!FullFTy) return error("Callee is not of pointer to function type"); - } else if (CalleeTy->getElementType() != FTy) + FTy = cast(flattenPointerTypes(FullFTy)); + } else if (getPointerElementFlatType(FullTy) != FTy) return error("Explicit invoke type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) return error("Insufficient operands to call"); SmallVector Ops; + SmallVector ArgsFullTys; for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { Ops.push_back(getValue(Record, OpNum, NextValueNo, FTy->getParamType(i))); + ArgsFullTys.push_back(FullFTy->getParamType(i)); if (!Ops.back()) return error("Invalid record"); } @@ -4284,20 +4364,23 @@ // Read type/value pairs for varargs params. while (OpNum != Record.size()) { Value *Op; - if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + Type *FullTy; + if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy)) return error("Invalid record"); Ops.push_back(Op); + ArgsFullTys.push_back(FullTy); } } I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops, OperandBundles); + FullTy = FullFTy->getReturnType(); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( static_cast(CallingConv::MaxID & CCInfo)); cast(I)->setAttributes(PAL); - propagateByValTypes(cast(I)); + propagateByValTypes(cast(I), ArgsFullTys); break; } @@ -4323,22 +4406,29 @@ IndirectDests.push_back(getBasicBlock(Record[OpNum++])); FunctionType *FTy = nullptr; - if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 && - !(FTy = dyn_cast(getTypeByID(Record[OpNum++])))) - return error("Explicit call type is not a function type"); + FunctionType *FullFTy = nullptr; + if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) { + FullFTy = + dyn_cast(getFullyStructuredTypeByID(Record[OpNum++])); + if (!FullFTy) + return error("Explicit call type is not a function type"); + FTy = cast(flattenPointerTypes(FullFTy)); + } Value *Callee; - if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy)) return error("Invalid record"); PointerType *OpTy = dyn_cast(Callee->getType()); if (!OpTy) return error("Callee is not a pointer type"); if (!FTy) { - FTy = dyn_cast(OpTy->getElementType()); - if (!FTy) + FullFTy = + dyn_cast(cast(FullTy)->getElementType()); + if (!FullFTy) return error("Callee is not of pointer to function type"); - } else if (OpTy->getElementType() != FTy) + FTy = cast(flattenPointerTypes(FullFTy)); + } else if (getPointerElementFlatType(FullTy) != FTy) return error("Explicit call type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) @@ -4371,6 +4461,7 @@ I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, OperandBundles); + FullTy = FullFTy->getReturnType(); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( @@ -4385,7 +4476,8 @@ case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...] if (Record.size() < 1 || ((Record.size()-1)&1)) return error("Invalid record"); - Type *Ty = getTypeByID(Record[0]); + FullTy = getFullyStructuredTypeByID(Record[0]); + Type *Ty = flattenPointerTypes(FullTy); if (!Ty) return error("Invalid record"); @@ -4422,7 +4514,8 @@ if (Record.size() < 4) return error("Invalid record"); } - Type *Ty = getTypeByID(Record[Idx++]); + FullTy = getFullyStructuredTypeByID(Record[Idx++]); + Type *Ty = flattenPointerTypes(FullTy); if (!Ty) return error("Invalid record"); if (BitCode == bitc::FUNC_CODE_INST_LANDINGPAD_OLD) { @@ -4475,12 +4568,13 @@ SwiftErrorMask; bool InAlloca = AlignRecord & InAllocaMask; bool SwiftError = AlignRecord & SwiftErrorMask; - Type *Ty = getTypeByID(Record[0]); + FullTy = getFullyStructuredTypeByID(Record[0]); + Type *Ty = flattenPointerTypes(FullTy); if ((AlignRecord & ExplicitTypeMask) == 0) { auto *PTy = dyn_cast_or_null(Ty); if (!PTy) return error("Old-style alloca with a non-pointer type"); - Ty = PTy->getElementType(); + std::tie(FullTy, Ty) = getPointerElementTypes(FullTy); } Type *OpTy = getTypeByID(Record[1]); Value *Size = getFnValueByID(Record[2], OpTy); @@ -4499,29 +4593,34 @@ AI->setUsedWithInAlloca(InAlloca); AI->setSwiftError(SwiftError); I = AI; + FullTy = PointerType::get(FullTy, AS); InstructionList.push_back(I); break; } case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol] unsigned OpNum = 0; Value *Op; - if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy) || (OpNum + 2 != Record.size() && OpNum + 3 != Record.size())) return error("Invalid record"); + if (!isa(Op->getType())) + return error("Load operand is not a pointer type"); + Type *Ty = nullptr; - if (OpNum + 3 == Record.size()) - Ty = getTypeByID(Record[OpNum++]); + if (OpNum + 3 == Record.size()) { + FullTy = getFullyStructuredTypeByID(Record[OpNum++]); + Ty = flattenPointerTypes(FullTy); + } else + std::tie(FullTy, Ty) = getPointerElementTypes(FullTy); + if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType())) return Err; - if (!Ty) - Ty = cast(Op->getType())->getElementType(); unsigned Align; if (Error Err = parseAlignmentValue(Record[OpNum], Align)) return Err; I = new LoadInst(Ty, Op, "", Record[OpNum + 1], Align); - InstructionList.push_back(I); break; } @@ -4529,17 +4628,22 @@ // LOADATOMIC: [opty, op, align, vol, ordering, ssid] unsigned OpNum = 0; Value *Op; - if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy) || (OpNum + 4 != Record.size() && OpNum + 5 != Record.size())) return error("Invalid record"); + if (!isa(Op->getType())) + return error("Load operand is not a pointer type"); + Type *Ty = nullptr; - if (OpNum + 5 == Record.size()) - Ty = getTypeByID(Record[OpNum++]); + if (OpNum + 5 == Record.size()) { + FullTy = getFullyStructuredTypeByID(Record[OpNum++]); + Ty = flattenPointerTypes(FullTy); + } else + std::tie(FullTy, Ty) = getPointerElementTypes(FullTy); + if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType())) return Err; - if (!Ty) - Ty = cast(Op->getType())->getElementType(); AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]); if (Ordering == AtomicOrdering::NotAtomic || @@ -4554,7 +4658,6 @@ if (Error Err = parseAlignmentValue(Record[OpNum], Align)) return Err; I = new LoadInst(Ty, Op, "", Record[OpNum + 1], Align, Ordering, SSID); - InstructionList.push_back(I); break; } @@ -4562,12 +4665,12 @@ case bitc::FUNC_CODE_INST_STORE_OLD: { // STORE2:[ptrty, ptr, val, align, vol] unsigned OpNum = 0; Value *Val, *Ptr; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + Type *FullTy; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) || (BitCode == bitc::FUNC_CODE_INST_STORE ? getValueTypePair(Record, OpNum, NextValueNo, Val) : popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getElementType(), - Val)) || + getPointerElementFlatType(FullTy), Val)) || OpNum + 2 != Record.size()) return error("Invalid record"); @@ -4585,13 +4688,13 @@ // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, ssid] unsigned OpNum = 0; Value *Val, *Ptr; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + Type *FullTy; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) || !isa(Ptr->getType()) || (BitCode == bitc::FUNC_CODE_INST_STOREATOMIC ? getValueTypePair(Record, OpNum, NextValueNo, Val) : popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getElementType(), - Val)) || + getPointerElementFlatType(FullTy), Val)) || OpNum + 4 != Record.size()) return error("Invalid record"); @@ -4619,15 +4722,25 @@ // failureordering?, isweak?] unsigned OpNum = 0; Value *Ptr, *Cmp, *New; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || - (BitCode == bitc::FUNC_CODE_INST_CMPXCHG - ? getValueTypePair(Record, OpNum, NextValueNo, Cmp) - : popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getElementType(), - Cmp)) || - popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) || + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy)) + return error("Invalid record"); + + if (!isa(Ptr->getType())) + return error("Cmpxchg operand is not a pointer type"); + + if (BitCode == bitc::FUNC_CODE_INST_CMPXCHG) { + if (getValueTypePair(Record, OpNum, NextValueNo, Cmp, &FullTy)) + return error("Invalid record"); + } else if (popValue(Record, OpNum, NextValueNo, + getPointerElementFlatType(FullTy), Cmp)) + return error("Invalid record"); + else + FullTy = cast(FullTy)->getElementType(); + + if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) || Record.size() < OpNum + 3 || Record.size() > OpNum + 5) return error("Invalid record"); + AtomicOrdering SuccessOrdering = getDecodedOrdering(Record[OpNum + 1]); if (SuccessOrdering == AtomicOrdering::NotAtomic || SuccessOrdering == AtomicOrdering::Unordered) @@ -4645,6 +4758,7 @@ I = new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, FailureOrdering, SSID); + FullTy = StructType::get(Context, {FullTy, Type::getInt1Ty(Context)}); cast(I)->setVolatile(Record[OpNum]); if (Record.size() < 8) { @@ -4653,6 +4767,7 @@ // expecting the first component of a modern cmpxchg. CurBB->getInstList().push_back(I); I = ExtractValueInst::Create(I, 0); + FullTy = cast(FullTy)->getElementType(0); } else { cast(I)->setWeak(Record[OpNum+4]); } @@ -4664,11 +4779,11 @@ // ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, ssid] unsigned OpNum = 0; Value *Ptr, *Val; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) || !isa(Ptr->getType()) || popValue(Record, OpNum, NextValueNo, - cast(Ptr->getType())->getElementType(), Val) || - OpNum+4 != Record.size()) + getPointerElementFlatType(FullTy), Val) || + OpNum + 4 != Record.size()) return error("Invalid record"); AtomicRMWInst::BinOp Operation = getDecodedRMWOperation(Record[OpNum]); if (Operation < AtomicRMWInst::FIRST_BINOP || @@ -4680,6 +4795,7 @@ return error("Invalid record"); SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 3]); I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SSID); + FullTy = getPointerElementFlatType(FullTy); cast(I)->setVolatile(Record[OpNum+1]); InstructionList.push_back(I); break; @@ -4714,28 +4830,36 @@ } FunctionType *FTy = nullptr; - if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 && - !(FTy = dyn_cast(getTypeByID(Record[OpNum++])))) - return error("Explicit call type is not a function type"); + FunctionType *FullFTy = nullptr; + if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) { + FullFTy = + dyn_cast(getFullyStructuredTypeByID(Record[OpNum++])); + if (!FullFTy) + return error("Explicit call type is not a function type"); + FTy = cast(flattenPointerTypes(FullFTy)); + } Value *Callee; - if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy)) return error("Invalid record"); PointerType *OpTy = dyn_cast(Callee->getType()); if (!OpTy) return error("Callee is not a pointer type"); if (!FTy) { - FTy = dyn_cast(OpTy->getElementType()); - if (!FTy) + FullFTy = + dyn_cast(cast(FullTy)->getElementType()); + if (!FullFTy) return error("Callee is not of pointer to function type"); - } else if (OpTy->getElementType() != FTy) + FTy = cast(flattenPointerTypes(FullFTy)); + } else if (getPointerElementFlatType(FullTy) != FTy) return error("Explicit call type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) return error("Insufficient operands to call"); SmallVector Args; + SmallVector ArgsFullTys; // Read the fixed params. for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { if (FTy->getParamType(i)->isLabelTy()) @@ -4743,6 +4867,7 @@ else Args.push_back(getValue(Record, OpNum, NextValueNo, FTy->getParamType(i))); + ArgsFullTys.push_back(FullFTy->getParamType(i)); if (!Args.back()) return error("Invalid record"); } @@ -4754,13 +4879,16 @@ } else { while (OpNum != Record.size()) { Value *Op; - if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + Type *FullTy; + if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy)) return error("Invalid record"); Args.push_back(Op); + ArgsFullTys.push_back(FullTy); } } I = CallInst::Create(FTy, Callee, Args, OperandBundles); + FullTy = FullFTy->getReturnType(); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( @@ -4774,7 +4902,7 @@ TCK = CallInst::TCK_NoTail; cast(I)->setTailCallKind(TCK); cast(I)->setAttributes(PAL); - propagateByValTypes(cast(I)); + propagateByValTypes(cast(I), ArgsFullTys); if (FMF.any()) { if (!isa(I)) return error("Fast-math-flags specified for call without " @@ -4788,7 +4916,8 @@ return error("Invalid record"); Type *OpTy = getTypeByID(Record[0]); Value *Op = getValue(Record, 1, NextValueNo, OpTy); - Type *ResTy = getTypeByID(Record[2]); + FullTy = getFullyStructuredTypeByID(Record[2]); + Type *ResTy = flattenPointerTypes(FullTy); if (!OpTy || !Op || !ResTy) return error("Invalid record"); I = new VAArgInst(Op, ResTy); @@ -4838,8 +4967,23 @@ } // Non-void values get registered in the value table for future use. - if (I && !I->getType()->isVoidTy()) - ValueList.assignValue(I, NextValueNo++); + if (I && !I->getType()->isVoidTy()) { + if (!FullTy) { + FullTy = I->getType(); + assert( + !FullTy->isPointerTy() && !isa(FullTy) && + !isa(FullTy) && + (!isa(FullTy) || + FullTy->getVectorElementType()->isFloatingPointTy() || + FullTy->getVectorElementType()->isIntegerTy()) && + "Structured types must be assigned with corresponding non-opaque " + "pointer type"); + } + + assert(I->getType() == flattenPointerTypes(FullTy) && + "Incorrect fully structured type provided for Instruction"); + ValueList.assignValue(I, NextValueNo++, FullTy); + } } OutOfRecordLoop: diff --git a/llvm/lib/Bitcode/Reader/ValueList.h b/llvm/lib/Bitcode/Reader/ValueList.h --- a/llvm/lib/Bitcode/Reader/ValueList.h +++ b/llvm/lib/Bitcode/Reader/ValueList.h @@ -28,6 +28,13 @@ class BitcodeReaderValueList { std::vector ValuePtrs; + /// Struct containing fully-specified copies of the type of each + /// value. When pointers are opaque, this will be contain non-opaque + /// variants so that restructuring instructions can determine their + /// type correctly even if being loaded from old bitcode where some + /// types are implicit. + std::vector FullTypes; + /// As we resolve forward-referenced constants, we add information about them /// to this vector. This allows us to resolve them in bulk instead of /// resolving each reference at a time. See the code in @@ -48,12 +55,19 @@ // vector compatibility methods unsigned size() const { return ValuePtrs.size(); } - void resize(unsigned N) { ValuePtrs.resize(N); } - void push_back(Value *V) { ValuePtrs.emplace_back(V); } + void resize(unsigned N) { + ValuePtrs.resize(N); + FullTypes.resize(N); + } + void push_back(Value *V, Type *Ty) { + ValuePtrs.emplace_back(V); + FullTypes.emplace_back(Ty); + } void clear() { assert(ResolveConstants.empty() && "Constants not resolved?"); ValuePtrs.clear(); + FullTypes.clear(); } Value *operator[](unsigned i) const { @@ -62,18 +76,22 @@ } Value *back() const { return ValuePtrs.back(); } - void pop_back() { ValuePtrs.pop_back(); } + void pop_back() { + ValuePtrs.pop_back(); + FullTypes.pop_back(); + } bool empty() const { return ValuePtrs.empty(); } void shrinkTo(unsigned N) { assert(N <= size() && "Invalid shrinkTo request!"); ValuePtrs.resize(N); + FullTypes.resize(N); } Constant *getConstantFwdRef(unsigned Idx, Type *Ty); - Value *getValueFwdRef(unsigned Idx, Type *Ty); + Value *getValueFwdRef(unsigned Idx, Type *Ty, Type **FullTy = nullptr); - void assignValue(Value *V, unsigned Idx); + void assignValue(Value *V, unsigned Idx, Type *FullTy); /// Once all constants are read, this method bulk resolves any forward /// references. diff --git a/llvm/lib/Bitcode/Reader/ValueList.cpp b/llvm/lib/Bitcode/Reader/ValueList.cpp --- a/llvm/lib/Bitcode/Reader/ValueList.cpp +++ b/llvm/lib/Bitcode/Reader/ValueList.cpp @@ -65,15 +65,18 @@ } // end namespace llvm -void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) { +void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx, Type *FullTy) { if (Idx == size()) { - push_back(V); + push_back(V, FullTy); return; } if (Idx >= size()) resize(Idx + 1); + assert(FullTypes[Idx] == nullptr || FullTypes[Idx] == FullTy); + FullTypes[Idx] = FullTy; + WeakTrackingVH &OldV = ValuePtrs[Idx]; if (!OldV) { OldV = V; @@ -109,7 +112,8 @@ return C; } -Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) { +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty, + Type **FullTy) { // Bail out for a clearly invalid value. This would make us call resize(0) if (Idx == std::numeric_limits::max()) return nullptr; @@ -121,6 +125,8 @@ // If the types don't match, it's invalid. if (Ty && Ty != V->getType()) return nullptr; + if (FullTy) + *FullTy = FullTypes[Idx]; return V; } diff --git a/llvm/test/Bitcode/invalid.test b/llvm/test/Bitcode/invalid.test --- a/llvm/test/Bitcode/invalid.test +++ b/llvm/test/Bitcode/invalid.test @@ -134,7 +134,7 @@ RUN: not llvm-dis -disable-output %p/Inputs/invalid-load-pointer-type.bc 2>&1 | \ RUN: FileCheck --check-prefix=LOAD-BAD-TYPE %s -LOAD-BAD-TYPE: Load/Store operand is not a pointer type +LOAD-BAD-TYPE: Load operand is not a pointer type RUN: not llvm-dis -disable-output %p/Inputs/invalid-GCTable-overflow.bc 2>&1 | \ RUN: FileCheck --check-prefix=GCTABLE-OFLOW %s