From 1c456a82205cd3a06c87ad498f0bbddf963d8645 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Feb 2022 14:44:20 +0100 Subject: [Bitcode] Improve support for opaque-pointer bitcode upgrade This is step two of supporting autoupgrade of old bitcode to opaque pointers. Rather than tracking the element type ID of pointers in particular, track all type IDs that a type contains. This allows us to recover the element type in more complex situations, e.g. when we need to determine the pointer element type of a vector element or function type parameter. Differential Revision: https://reviews.llvm.org/D119339 --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 73 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp') diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index fa57edbc..f460bfe 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -484,9 +484,10 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { std::vector GCTable; std::vector TypeList; - /// Stores pointer element type for a given type ID. This is used during - /// upgrades of typed pointer IR in opaque pointer mode. - std::vector ElementTypeList; + /// Track type IDs of contained types. Order is the same as the contained + /// types of a Type*. This is used during upgrades of typed pointer IR in + /// opaque pointer mode. + DenseMap> ContainedTypeIDs; DenseMap FunctionTypes; BitcodeReaderValueList ValueList; Optional MDLoader; @@ -593,8 +594,11 @@ private: StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name); StructType *createIdentifiedStructType(LLVMContext &Context); + static constexpr unsigned InvalidTypeID = ~0u; + Type *getTypeByID(unsigned ID); Type *getPtrElementTypeByID(unsigned ID); + unsigned getContainedTypeID(unsigned ID, unsigned Idx); Value *getFnValueByID(unsigned ID, Type *Ty) { if (Ty && Ty->isMetadataTy()) @@ -1180,6 +1184,17 @@ Type *BitcodeReader::getTypeByID(unsigned ID) { return TypeList[ID] = createIdentifiedStructType(Context); } +unsigned BitcodeReader::getContainedTypeID(unsigned ID, unsigned Idx) { + auto It = ContainedTypeIDs.find(ID); + if (It == ContainedTypeIDs.end()) + return InvalidTypeID; + + if (Idx >= It->second.size()) + return InvalidTypeID; + + return It->second[Idx]; +} + Type *BitcodeReader::getPtrElementTypeByID(unsigned ID) { if (ID >= TypeList.size()) return nullptr; @@ -1188,7 +1203,7 @@ Type *BitcodeReader::getPtrElementTypeByID(unsigned ID) { if (!Ty->isPointerTy()) return nullptr; - Type *ElemTy = ElementTypeList[ID]; + Type *ElemTy = getTypeByID(getContainedTypeID(ID, 0)); if (!ElemTy) return nullptr; @@ -1733,7 +1748,7 @@ Error BitcodeReader::parseTypeTableBody() { // Read a record. Record.clear(); Type *ResultTy = nullptr; - Type *ElemTy = nullptr; + SmallVector ContainedIDs; Expected MaybeRecord = Stream.readRecord(Entry.ID, Record); if (!MaybeRecord) return MaybeRecord.takeError(); @@ -1746,7 +1761,6 @@ Error BitcodeReader::parseTypeTableBody() { if (Record.empty()) return error("Invalid record"); TypeList.resize(Record[0]); - ElementTypeList.resize(Record[0]); continue; case bitc::TYPE_CODE_VOID: // VOID ResultTy = Type::getVoidTy(Context); @@ -1809,7 +1823,7 @@ Error BitcodeReader::parseTypeTableBody() { if (!ResultTy || !PointerType::isValidElementType(ResultTy)) return error("Invalid type"); - ElemTy = ResultTy; + ContainedIDs.push_back(Record[0]); ResultTy = PointerType::get(ResultTy, AddressSpace); break; } @@ -1840,6 +1854,7 @@ Error BitcodeReader::parseTypeTableBody() { if (!ResultTy || ArgTys.size() < Record.size()-3) return error("Invalid type"); + ContainedIDs.append(Record.begin() + 2, Record.end()); ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]); break; } @@ -1862,6 +1877,7 @@ Error BitcodeReader::parseTypeTableBody() { if (!ResultTy || ArgTys.size() < Record.size()-2) return error("Invalid type"); + ContainedIDs.append(Record.begin() + 1, Record.end()); ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]); break; } @@ -1877,6 +1893,7 @@ Error BitcodeReader::parseTypeTableBody() { } if (EltTys.size() != Record.size()-1) return error("Invalid type"); + ContainedIDs.append(Record.begin() + 1, Record.end()); ResultTy = StructType::get(Context, EltTys, Record[0]); break; } @@ -1911,6 +1928,7 @@ Error BitcodeReader::parseTypeTableBody() { if (EltTys.size() != Record.size()-1) return error("Invalid record"); Res->setBody(EltTys, Record[0]); + ContainedIDs.append(Record.begin() + 1, Record.end()); ResultTy = Res; break; } @@ -1938,6 +1956,7 @@ Error BitcodeReader::parseTypeTableBody() { ResultTy = getTypeByID(Record[1]); if (!ResultTy || !ArrayType::isValidElementType(ResultTy)) return error("Invalid type"); + ContainedIDs.push_back(Record[1]); ResultTy = ArrayType::get(ResultTy, Record[0]); break; case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty] or @@ -1950,6 +1969,7 @@ Error BitcodeReader::parseTypeTableBody() { if (!ResultTy || !VectorType::isValidElementType(ResultTy)) return error("Invalid type"); bool Scalable = Record.size() > 2 ? Record[2] : false; + ContainedIDs.push_back(Record[1]); ResultTy = VectorType::get(ResultTy, Record[0], Scalable); break; } @@ -1961,7 +1981,8 @@ Error BitcodeReader::parseTypeTableBody() { "Invalid TYPE table: Only named structs can be forward referenced"); assert(ResultTy && "Didn't read a type?"); TypeList[NumRecords] = ResultTy; - ElementTypeList[NumRecords] = ElemTy; + if (!ContainedIDs.empty()) + ContainedTypeIDs[NumRecords] = std::move(ContainedIDs); ++NumRecords; } } @@ -2726,10 +2747,8 @@ Error BitcodeReader::parseConstants() { InBounds = true; SmallVector Elts; - Type *Elt0FullTy = nullptr; + unsigned BaseTypeID = Record[OpNum]; while (OpNum != Record.size()) { - if (!Elt0FullTy) - Elt0FullTy = getTypeByID(Record[OpNum]); Type *ElTy = getTypeByID(Record[OpNum++]); if (!ElTy) return error("Invalid record"); @@ -2739,10 +2758,21 @@ Error BitcodeReader::parseConstants() { if (Elts.size() < 1) return error("Invalid gep with no operands"); - PointerType *OrigPtrTy = cast(Elt0FullTy->getScalarType()); - if (!PointeeType) - PointeeType = OrigPtrTy->getPointerElementType(); - else if (!OrigPtrTy->isOpaqueOrPointeeTypeMatches(PointeeType)) + Type *BaseType = getTypeByID(BaseTypeID); + if (isa(BaseType)) { + BaseTypeID = getContainedTypeID(BaseTypeID, 0); + BaseType = getTypeByID(BaseTypeID); + } + + PointerType *OrigPtrTy = dyn_cast_or_null(BaseType); + if (!OrigPtrTy) + return error("GEP base operand must be pointer or vector of pointer"); + + if (!PointeeType) { + PointeeType = getPtrElementTypeByID(BaseTypeID); + if (!PointeeType) + return error("Missing element type for old-style constant GEP"); + } else if (!OrigPtrTy->isOpaqueOrPointeeTypeMatches(PointeeType)) return error("Explicit gep operator type does not match pointee type " "of pointer operand"); @@ -3414,11 +3444,13 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { if (Record.size() < 8) return error("Invalid record"); - Type *FTy = getTypeByID(Record[0]); + unsigned FTyID = Record[0]; + Type *FTy = getTypeByID(FTyID); if (!FTy) return error("Invalid record"); if (isa(FTy)) { - FTy = getPtrElementTypeByID(Record[0]); + FTyID = getContainedTypeID(FTyID, 0); + FTy = getTypeByID(FTyID); if (!FTy) return error("Missing element type for old-style function"); } @@ -3461,8 +3493,11 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { Func->removeParamAttr(i, Kind); - Type *PTy = cast(FTy)->getParamType(i); - Type *PtrEltTy = PTy->getPointerElementType(); + unsigned ParamTypeID = getContainedTypeID(FTyID, i + 1); + Type *PtrEltTy = getPtrElementTypeByID(ParamTypeID); + if (!PtrEltTy) + return error("Missing param element type for attribute upgrade"); + Attribute NewAttr; switch (Kind) { case Attribute::ByVal: -- cgit v1.1