From 1ade9071319309ef1cdde0ab9364f245ceb0b05a Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Thu, 27 Jun 2019 14:46:51 +0000 Subject: [PATCH] Bitcode: derive all types used from records instead of Values. There is existing bitcode that we need to support where the structured nature of pointer types is used to derive the result type of some operation. For example a GEP's operation and result will be based on its input Type. When pointers become opaque, the BitcodeReader will still have access to this information because it's explicitly told how to construct the more complex types used, but this information will not be attached to any Value that gets looked up. This changes BitcodeReader so that in all places which use type information in this manner, it's derived from a side-table rather than from the Value in question. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364550 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Bitcode/Reader/BitcodeReader.cpp | 415 +++++++++++++++++++++++------------ lib/Bitcode/Reader/ValueList.cpp | 12 +- lib/Bitcode/Reader/ValueList.h | 28 ++- test/Bitcode/invalid.test | 2 +- 4 files changed, 312 insertions(+), 145 deletions(-) diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 3772d08115c..4c346176bec 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -494,6 +494,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { std::vector GCTable; std::vector TypeList; + DenseMap FunctionTypes; BitcodeReaderValueList ValueList; Optional MDLoader; std::vector ComdatList; @@ -592,12 +593,42 @@ private: 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) { @@ -619,7 +650,8 @@ private: /// 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. @@ -628,7 +660,7 @@ private: 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()) @@ -636,6 +668,8 @@ private: unsigned TypeNo = (unsigned)Record[Slot++]; ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo)); + if (FullTy) + *FullTy = getFullyStructuredTypeByID(TypeNo); return ResVal == nullptr; } @@ -683,7 +717,7 @@ private: /// 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 @@ -1144,7 +1178,7 @@ static void upgradeDLLImportExportLinkage(GlobalValue *GV, unsigned Val) { } } -Type *BitcodeReader::getTypeByID(unsigned ID) { +Type *BitcodeReader::getFullyStructuredTypeByID(unsigned ID) { // The type table size is always specified correctly. if (ID >= TypeList.size()) return nullptr; @@ -2268,6 +2302,7 @@ Error BitcodeReader::parseConstants() { // Read all the records for this value table. Type *CurTy = Type::getInt32Ty(Context); + Type *CurFullTy = Type::getInt32Ty(Context); unsigned NextCstNo = ValueList.size(); while (true) { @@ -2312,7 +2347,8 @@ Error BitcodeReader::parseConstants() { 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); @@ -2531,7 +2567,10 @@ Error BitcodeReader::parseConstants() { 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"); @@ -2542,8 +2581,7 @@ Error BitcodeReader::parseConstants() { 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) @@ -2677,10 +2715,10 @@ Error BitcodeReader::parseConstants() { 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., @@ -2703,11 +2741,11 @@ Error BitcodeReader::parseConstants() { 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:{ @@ -2753,7 +2791,9 @@ Error BitcodeReader::parseConstants() { } } - ValueList.assignValue(V, NextCstNo); + assert(V->getType() == flattenPointerTypes(CurFullTy) && + "Incorrect fully structured type provided for Constant"); + ValueList.assignValue(V, NextCstNo, CurFullTy); ++NextCstNo; } } @@ -3026,7 +3066,8 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { 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; @@ -3038,7 +3079,7 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { 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]; @@ -3084,7 +3125,10 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { 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]) @@ -3127,13 +3171,14 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { 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) @@ -3143,8 +3188,13 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { 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]; @@ -3155,13 +3205,14 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { // 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.getAttribute(Attribute::ByVal).getValueAsType()) { - 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; @@ -3221,7 +3272,10 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { 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. @@ -3250,7 +3304,8 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( 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"); @@ -3259,7 +3314,7 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( 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++]; @@ -3275,6 +3330,9 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( 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()) { @@ -3305,7 +3363,10 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( 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(); } @@ -3583,16 +3644,16 @@ Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) { 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]))); } } @@ -3610,9 +3671,13 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; @@ -3684,6 +3749,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // Read a record. Record.clear(); Instruction *I = nullptr; + Type *FullTy = nullptr; Expected MaybeBitCode = Stream.readRecord(Entry.ID, Record); if (!MaybeBitCode) return MaybeBitCode.takeError(); @@ -3828,7 +3894,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -3857,22 +3924,22 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -3885,6 +3952,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { } I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx); + FullTy = GetElementPtrInst::getGEPReturnType(FullTy, I, GEPIdx); InstructionList.push_back(I); if (InBounds) @@ -3896,7 +3964,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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(); @@ -3904,26 +3972,25 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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); @@ -3935,7 +4002,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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)) @@ -3981,7 +4048,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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"); @@ -3996,7 +4063,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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"); @@ -4026,12 +4093,13 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; } @@ -4039,7 +4107,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -4055,7 +4123,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -4064,6 +4132,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; } @@ -4367,31 +4437,40 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); } @@ -4403,20 +4482,23 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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; } @@ -4442,22 +4524,29 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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) @@ -4490,6 +4579,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args, OperandBundles); + FullTy = FullFTy->getReturnType(); OperandBundles.clear(); InstructionList.push_back(I); cast(I)->setCallingConv( @@ -4504,7 +4594,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -4541,7 +4632,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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) { @@ -4594,12 +4686,13 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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); @@ -4618,29 +4711,34 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; } @@ -4648,17 +4746,22 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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 || @@ -4673,7 +4776,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; } @@ -4681,12 +4783,12 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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"); @@ -4704,13 +4806,13 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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"); @@ -4738,15 +4840,25 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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) @@ -4764,6 +4876,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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) { @@ -4772,6 +4885,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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]); } @@ -4783,11 +4897,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // 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 || @@ -4799,6 +4913,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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; @@ -4833,28 +4948,36 @@ Error BitcodeReader::parseFunctionBody(Function *F) { } 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()) @@ -4862,6 +4985,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { else Args.push_back(getValue(Record, OpNum, NextValueNo, FTy->getParamType(i))); + ArgsFullTys.push_back(FullFTy->getParamType(i)); if (!Args.back()) return error("Invalid record"); } @@ -4873,13 +4997,16 @@ Error BitcodeReader::parseFunctionBody(Function *F) { } 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( @@ -4893,7 +5020,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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 " @@ -4907,7 +5034,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) { 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); @@ -4957,8 +5085,23 @@ Error BitcodeReader::parseFunctionBody(Function *F) { } // 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/lib/Bitcode/Reader/ValueList.cpp b/lib/Bitcode/Reader/ValueList.cpp index 6cf1f4c1dd9..da2d24d103b 100644 --- a/lib/Bitcode/Reader/ValueList.cpp +++ b/lib/Bitcode/Reader/ValueList.cpp @@ -65,15 +65,18 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value) } // 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 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) { 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 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) { // 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/lib/Bitcode/Reader/ValueList.h b/lib/Bitcode/Reader/ValueList.h index c636a74d2f6..1c54911650f 100644 --- a/lib/Bitcode/Reader/ValueList.h +++ b/lib/Bitcode/Reader/ValueList.h @@ -28,6 +28,13 @@ class Value; 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 @@ public: // 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 @@ public: } 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/test/Bitcode/invalid.test b/test/Bitcode/invalid.test index b7f976eaec9..2a9af0626c6 100644 --- a/test/Bitcode/invalid.test +++ b/test/Bitcode/invalid.test @@ -134,7 +134,7 @@ HUGE-FWDREF: Invalid record 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 -- 2.11.0