Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -484,7 +484,9 @@ std::vector GCTable; std::vector TypeList; - std::vector ElementTypeList; + // Track type IDs of contained types. Order is the same as the contained + // types of a Type*. + DenseMap> ContainedTypeIDs; DenseMap FunctionTypes; BitcodeReaderValueList ValueList; Optional MDLoader; @@ -591,7 +593,10 @@ StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name); StructType *createIdentifiedStructType(LLVMContext &Context); + static constexpr unsigned InvalidTypeID = ~0u; + Type *getTypeByID(unsigned ID); + unsigned getContainedTypeID(unsigned ID, unsigned Idx); Type *getElementTypeByID(unsigned ID); Value *getFnValueByID(unsigned ID, Type *Ty) { @@ -1178,6 +1183,18 @@ 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; + + assert(It->second[Idx] < TypeList.size() && "Invalid type ID"); + return It->second[Idx]; +} + Type *BitcodeReader::getElementTypeByID(unsigned ID) { if (ID >= TypeList.size()) return nullptr; @@ -1186,7 +1203,7 @@ if (!Ty->isPointerTy()) return nullptr; - Type *ElemTy = ElementTypeList[ID]; + Type *ElemTy = getTypeByID(getContainedTypeID(ID, 0)); if (!ElemTy) return nullptr; @@ -1727,7 +1744,7 @@ // 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(); @@ -1740,7 +1757,6 @@ 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); @@ -1803,7 +1819,7 @@ if (!ResultTy || !PointerType::isValidElementType(ResultTy)) return error("Invalid type"); - ElemTy = ResultTy; + ContainedIDs.push_back(Record[0]); ResultTy = PointerType::get(ResultTy, AddressSpace); break; } @@ -1834,6 +1850,7 @@ 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; } @@ -1856,6 +1873,7 @@ 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; } @@ -1871,6 +1889,7 @@ } 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; } @@ -1905,6 +1924,7 @@ 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; } @@ -1932,6 +1952,7 @@ 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 @@ -1944,6 +1965,7 @@ 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; } @@ -1955,7 +1977,8 @@ "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; } } @@ -2720,10 +2743,8 @@ 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"); @@ -2733,10 +2754,21 @@ 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 = getElementTypeByID(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"); @@ -3408,11 +3440,13 @@ 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 = getElementTypeByID(Record[0]); + FTyID = getContainedTypeID(FTyID, 0); + FTy = getTypeByID(FTyID); if (!FTy) return error("Missing element type for old-style function"); } @@ -3455,8 +3489,11 @@ Func->removeParamAttr(i, Kind); - Type *PTy = cast(FTy)->getParamType(i); - Type *PtrEltTy = PTy->getPointerElementType(); + unsigned ParamTypeID = getContainedTypeID(FTyID, i + 1); + Type *PtrEltTy = getElementTypeByID(ParamTypeID); + if (!PtrEltTy) + return error("Missing param element type for attribute upgrade"); + Attribute NewAttr; switch (Kind) { case Attribute::ByVal: Index: llvm/test/Bitcode/DIExpression-aggresult.ll =================================================================== --- llvm/test/Bitcode/DIExpression-aggresult.ll +++ llvm/test/Bitcode/DIExpression-aggresult.ll @@ -1,4 +1,5 @@ -; RUN: llvm-dis -o - %s.bc | FileCheck %s +; RUN: llvm-dis -opaque-pointers=0 -o - %s.bc | FileCheck %s +; RUN: llvm-dis -opaque-pointers=1 -o - %s.bc | FileCheck %s %class.A = type { i32, i32, i32, i32 } define void @_Z3fooi(%class.A* sret(%class.A) %agg.result) #0 !dbg !3 {