aboutsummaryrefslogtreecommitdiff
path: root/lib/Bitcode/Reader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bitcode/Reader')
-rw-r--r--lib/Bitcode/Reader/BitReader.cpp7
-rw-r--r--lib/Bitcode/Reader/BitcodeAnalyzer.cpp980
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp1261
-rw-r--r--lib/Bitcode/Reader/BitstreamReader.cpp390
-rw-r--r--lib/Bitcode/Reader/MetadataLoader.cpp269
-rw-r--r--lib/Bitcode/Reader/MetadataLoader.h7
-rw-r--r--lib/Bitcode/Reader/ValueList.cpp31
-rw-r--r--lib/Bitcode/Reader/ValueList.h44
8 files changed, 2157 insertions, 832 deletions
diff --git a/lib/Bitcode/Reader/BitReader.cpp b/lib/Bitcode/Reader/BitReader.cpp
index 3ec45956b3e5..5ac893aef14e 100644
--- a/lib/Bitcode/Reader/BitReader.cpp
+++ b/lib/Bitcode/Reader/BitReader.cpp
@@ -1,9 +1,8 @@
//===-- BitReader.cpp -----------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
new file mode 100644
index 000000000000..9c30d563a314
--- /dev/null
+++ b/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
@@ -0,0 +1,980 @@
+//===- BitcodeAnalyzer.cpp - Internal BitcodeAnalyzer implementation ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/BitcodeAnalyzer.h"
+#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Bitstream/BitCodes.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/SHA1.h"
+
+using namespace llvm;
+
+static Error reportError(StringRef Message) {
+ return createStringError(std::errc::illegal_byte_sequence, Message.data());
+}
+
+/// Return a symbolic block name if known, otherwise return null.
+static Optional<const char *> GetBlockName(unsigned BlockID,
+ const BitstreamBlockInfo &BlockInfo,
+ CurStreamTypeType CurStreamType) {
+ // Standard blocks for all bitcode files.
+ if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID)
+ return "BLOCKINFO_BLOCK";
+ return None;
+ }
+
+ // Check to see if we have a blockinfo record for this block, with a name.
+ if (const BitstreamBlockInfo::BlockInfo *Info =
+ BlockInfo.getBlockInfo(BlockID)) {
+ if (!Info->Name.empty())
+ return Info->Name.c_str();
+ }
+
+ if (CurStreamType != LLVMIRBitstream)
+ return None;
+
+ switch (BlockID) {
+ default:
+ return None;
+ case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
+ return "OPERAND_BUNDLE_TAGS_BLOCK";
+ case bitc::MODULE_BLOCK_ID:
+ return "MODULE_BLOCK";
+ case bitc::PARAMATTR_BLOCK_ID:
+ return "PARAMATTR_BLOCK";
+ case bitc::PARAMATTR_GROUP_BLOCK_ID:
+ return "PARAMATTR_GROUP_BLOCK_ID";
+ case bitc::TYPE_BLOCK_ID_NEW:
+ return "TYPE_BLOCK_ID";
+ case bitc::CONSTANTS_BLOCK_ID:
+ return "CONSTANTS_BLOCK";
+ case bitc::FUNCTION_BLOCK_ID:
+ return "FUNCTION_BLOCK";
+ case bitc::IDENTIFICATION_BLOCK_ID:
+ return "IDENTIFICATION_BLOCK_ID";
+ case bitc::VALUE_SYMTAB_BLOCK_ID:
+ return "VALUE_SYMTAB";
+ case bitc::METADATA_BLOCK_ID:
+ return "METADATA_BLOCK";
+ case bitc::METADATA_KIND_BLOCK_ID:
+ return "METADATA_KIND_BLOCK";
+ case bitc::METADATA_ATTACHMENT_ID:
+ return "METADATA_ATTACHMENT_BLOCK";
+ case bitc::USELIST_BLOCK_ID:
+ return "USELIST_BLOCK_ID";
+ case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
+ return "GLOBALVAL_SUMMARY_BLOCK";
+ case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
+ return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";
+ case bitc::MODULE_STRTAB_BLOCK_ID:
+ return "MODULE_STRTAB_BLOCK";
+ case bitc::STRTAB_BLOCK_ID:
+ return "STRTAB_BLOCK";
+ case bitc::SYMTAB_BLOCK_ID:
+ return "SYMTAB_BLOCK";
+ }
+}
+
+/// Return a symbolic code name if known, otherwise return null.
+static Optional<const char *> GetCodeName(unsigned CodeID, unsigned BlockID,
+ const BitstreamBlockInfo &BlockInfo,
+ CurStreamTypeType CurStreamType) {
+ // Standard blocks for all bitcode files.
+ if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::BLOCKINFO_CODE_SETBID:
+ return "SETBID";
+ case bitc::BLOCKINFO_CODE_BLOCKNAME:
+ return "BLOCKNAME";
+ case bitc::BLOCKINFO_CODE_SETRECORDNAME:
+ return "SETRECORDNAME";
+ }
+ }
+ return None;
+ }
+
+ // Check to see if we have a blockinfo record for this record, with a name.
+ if (const BitstreamBlockInfo::BlockInfo *Info =
+ BlockInfo.getBlockInfo(BlockID)) {
+ for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
+ if (Info->RecordNames[i].first == CodeID)
+ return Info->RecordNames[i].second.c_str();
+ }
+
+ if (CurStreamType != LLVMIRBitstream)
+ return None;
+
+#define STRINGIFY_CODE(PREFIX, CODE) \
+ case bitc::PREFIX##_##CODE: \
+ return #CODE;
+ switch (BlockID) {
+ default:
+ return None;
+ case bitc::MODULE_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(MODULE_CODE, VERSION)
+ STRINGIFY_CODE(MODULE_CODE, TRIPLE)
+ STRINGIFY_CODE(MODULE_CODE, DATALAYOUT)
+ STRINGIFY_CODE(MODULE_CODE, ASM)
+ STRINGIFY_CODE(MODULE_CODE, SECTIONNAME)
+ STRINGIFY_CODE(MODULE_CODE, DEPLIB) // FIXME: Remove in 4.0
+ STRINGIFY_CODE(MODULE_CODE, GLOBALVAR)
+ STRINGIFY_CODE(MODULE_CODE, FUNCTION)
+ STRINGIFY_CODE(MODULE_CODE, ALIAS)
+ STRINGIFY_CODE(MODULE_CODE, GCNAME)
+ STRINGIFY_CODE(MODULE_CODE, VSTOFFSET)
+ STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)
+ STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)
+ STRINGIFY_CODE(MODULE_CODE, HASH)
+ }
+ case bitc::IDENTIFICATION_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(IDENTIFICATION_CODE, STRING)
+ STRINGIFY_CODE(IDENTIFICATION_CODE, EPOCH)
+ }
+ case bitc::PARAMATTR_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ // FIXME: Should these be different?
+ case bitc::PARAMATTR_CODE_ENTRY_OLD:
+ return "ENTRY";
+ case bitc::PARAMATTR_CODE_ENTRY:
+ return "ENTRY";
+ }
+ case bitc::PARAMATTR_GROUP_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::PARAMATTR_GRP_CODE_ENTRY:
+ return "ENTRY";
+ }
+ case bitc::TYPE_BLOCK_ID_NEW:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(TYPE_CODE, NUMENTRY)
+ STRINGIFY_CODE(TYPE_CODE, VOID)
+ STRINGIFY_CODE(TYPE_CODE, FLOAT)
+ STRINGIFY_CODE(TYPE_CODE, DOUBLE)
+ STRINGIFY_CODE(TYPE_CODE, LABEL)
+ STRINGIFY_CODE(TYPE_CODE, OPAQUE)
+ STRINGIFY_CODE(TYPE_CODE, INTEGER)
+ STRINGIFY_CODE(TYPE_CODE, POINTER)
+ STRINGIFY_CODE(TYPE_CODE, ARRAY)
+ STRINGIFY_CODE(TYPE_CODE, VECTOR)
+ STRINGIFY_CODE(TYPE_CODE, X86_FP80)
+ STRINGIFY_CODE(TYPE_CODE, FP128)
+ STRINGIFY_CODE(TYPE_CODE, PPC_FP128)
+ STRINGIFY_CODE(TYPE_CODE, METADATA)
+ STRINGIFY_CODE(TYPE_CODE, STRUCT_ANON)
+ STRINGIFY_CODE(TYPE_CODE, STRUCT_NAME)
+ STRINGIFY_CODE(TYPE_CODE, STRUCT_NAMED)
+ STRINGIFY_CODE(TYPE_CODE, FUNCTION)
+ }
+
+ case bitc::CONSTANTS_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(CST_CODE, SETTYPE)
+ STRINGIFY_CODE(CST_CODE, NULL)
+ STRINGIFY_CODE(CST_CODE, UNDEF)
+ STRINGIFY_CODE(CST_CODE, INTEGER)
+ STRINGIFY_CODE(CST_CODE, WIDE_INTEGER)
+ STRINGIFY_CODE(CST_CODE, FLOAT)
+ STRINGIFY_CODE(CST_CODE, AGGREGATE)
+ STRINGIFY_CODE(CST_CODE, STRING)
+ STRINGIFY_CODE(CST_CODE, CSTRING)
+ STRINGIFY_CODE(CST_CODE, CE_BINOP)
+ STRINGIFY_CODE(CST_CODE, CE_CAST)
+ STRINGIFY_CODE(CST_CODE, CE_GEP)
+ STRINGIFY_CODE(CST_CODE, CE_INBOUNDS_GEP)
+ STRINGIFY_CODE(CST_CODE, CE_SELECT)
+ STRINGIFY_CODE(CST_CODE, CE_EXTRACTELT)
+ STRINGIFY_CODE(CST_CODE, CE_INSERTELT)
+ STRINGIFY_CODE(CST_CODE, CE_SHUFFLEVEC)
+ STRINGIFY_CODE(CST_CODE, CE_CMP)
+ STRINGIFY_CODE(CST_CODE, INLINEASM)
+ STRINGIFY_CODE(CST_CODE, CE_SHUFVEC_EX)
+ STRINGIFY_CODE(CST_CODE, CE_UNOP)
+ case bitc::CST_CODE_BLOCKADDRESS:
+ return "CST_CODE_BLOCKADDRESS";
+ STRINGIFY_CODE(CST_CODE, DATA)
+ }
+ case bitc::FUNCTION_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(FUNC_CODE, DECLAREBLOCKS)
+ STRINGIFY_CODE(FUNC_CODE, INST_BINOP)
+ STRINGIFY_CODE(FUNC_CODE, INST_CAST)
+ STRINGIFY_CODE(FUNC_CODE, INST_GEP_OLD)
+ STRINGIFY_CODE(FUNC_CODE, INST_INBOUNDS_GEP_OLD)
+ STRINGIFY_CODE(FUNC_CODE, INST_SELECT)
+ STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTELT)
+ STRINGIFY_CODE(FUNC_CODE, INST_INSERTELT)
+ STRINGIFY_CODE(FUNC_CODE, INST_SHUFFLEVEC)
+ STRINGIFY_CODE(FUNC_CODE, INST_CMP)
+ STRINGIFY_CODE(FUNC_CODE, INST_RET)
+ STRINGIFY_CODE(FUNC_CODE, INST_BR)
+ STRINGIFY_CODE(FUNC_CODE, INST_SWITCH)
+ STRINGIFY_CODE(FUNC_CODE, INST_INVOKE)
+ STRINGIFY_CODE(FUNC_CODE, INST_UNOP)
+ STRINGIFY_CODE(FUNC_CODE, INST_UNREACHABLE)
+ STRINGIFY_CODE(FUNC_CODE, INST_CLEANUPRET)
+ STRINGIFY_CODE(FUNC_CODE, INST_CATCHRET)
+ STRINGIFY_CODE(FUNC_CODE, INST_CATCHPAD)
+ STRINGIFY_CODE(FUNC_CODE, INST_PHI)
+ STRINGIFY_CODE(FUNC_CODE, INST_ALLOCA)
+ STRINGIFY_CODE(FUNC_CODE, INST_LOAD)
+ STRINGIFY_CODE(FUNC_CODE, INST_VAARG)
+ STRINGIFY_CODE(FUNC_CODE, INST_STORE)
+ STRINGIFY_CODE(FUNC_CODE, INST_EXTRACTVAL)
+ STRINGIFY_CODE(FUNC_CODE, INST_INSERTVAL)
+ STRINGIFY_CODE(FUNC_CODE, INST_CMP2)
+ STRINGIFY_CODE(FUNC_CODE, INST_VSELECT)
+ STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC_AGAIN)
+ STRINGIFY_CODE(FUNC_CODE, INST_CALL)
+ STRINGIFY_CODE(FUNC_CODE, DEBUG_LOC)
+ STRINGIFY_CODE(FUNC_CODE, INST_GEP)
+ STRINGIFY_CODE(FUNC_CODE, OPERAND_BUNDLE)
+ STRINGIFY_CODE(FUNC_CODE, INST_FENCE)
+ STRINGIFY_CODE(FUNC_CODE, INST_ATOMICRMW)
+ STRINGIFY_CODE(FUNC_CODE, INST_LOADATOMIC)
+ STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC)
+ STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG)
+ STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
+ }
+ case bitc::VALUE_SYMTAB_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(VST_CODE, ENTRY)
+ STRINGIFY_CODE(VST_CODE, BBENTRY)
+ STRINGIFY_CODE(VST_CODE, FNENTRY)
+ STRINGIFY_CODE(VST_CODE, COMBINED_ENTRY)
+ }
+ case bitc::MODULE_STRTAB_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(MST_CODE, ENTRY)
+ STRINGIFY_CODE(MST_CODE, HASH)
+ }
+ case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
+ case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(FS, PERMODULE)
+ STRINGIFY_CODE(FS, PERMODULE_PROFILE)
+ STRINGIFY_CODE(FS, PERMODULE_RELBF)
+ STRINGIFY_CODE(FS, PERMODULE_GLOBALVAR_INIT_REFS)
+ STRINGIFY_CODE(FS, PERMODULE_VTABLE_GLOBALVAR_INIT_REFS)
+ STRINGIFY_CODE(FS, COMBINED)
+ STRINGIFY_CODE(FS, COMBINED_PROFILE)
+ STRINGIFY_CODE(FS, COMBINED_GLOBALVAR_INIT_REFS)
+ STRINGIFY_CODE(FS, ALIAS)
+ STRINGIFY_CODE(FS, COMBINED_ALIAS)
+ STRINGIFY_CODE(FS, COMBINED_ORIGINAL_NAME)
+ STRINGIFY_CODE(FS, VERSION)
+ STRINGIFY_CODE(FS, FLAGS)
+ STRINGIFY_CODE(FS, TYPE_TESTS)
+ STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_VCALLS)
+ STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_VCALLS)
+ STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL)
+ STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL)
+ STRINGIFY_CODE(FS, VALUE_GUID)
+ STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
+ STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
+ STRINGIFY_CODE(FS, TYPE_ID)
+ STRINGIFY_CODE(FS, TYPE_ID_METADATA)
+ }
+ case bitc::METADATA_ATTACHMENT_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(METADATA, ATTACHMENT)
+ }
+ case bitc::METADATA_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(METADATA, STRING_OLD)
+ STRINGIFY_CODE(METADATA, VALUE)
+ STRINGIFY_CODE(METADATA, NODE)
+ STRINGIFY_CODE(METADATA, NAME)
+ STRINGIFY_CODE(METADATA, DISTINCT_NODE)
+ STRINGIFY_CODE(METADATA, KIND) // Older bitcode has it in a MODULE_BLOCK
+ STRINGIFY_CODE(METADATA, LOCATION)
+ STRINGIFY_CODE(METADATA, OLD_NODE)
+ STRINGIFY_CODE(METADATA, OLD_FN_NODE)
+ STRINGIFY_CODE(METADATA, NAMED_NODE)
+ STRINGIFY_CODE(METADATA, GENERIC_DEBUG)
+ STRINGIFY_CODE(METADATA, SUBRANGE)
+ STRINGIFY_CODE(METADATA, ENUMERATOR)
+ STRINGIFY_CODE(METADATA, BASIC_TYPE)
+ STRINGIFY_CODE(METADATA, FILE)
+ STRINGIFY_CODE(METADATA, DERIVED_TYPE)
+ STRINGIFY_CODE(METADATA, COMPOSITE_TYPE)
+ STRINGIFY_CODE(METADATA, SUBROUTINE_TYPE)
+ STRINGIFY_CODE(METADATA, COMPILE_UNIT)
+ STRINGIFY_CODE(METADATA, SUBPROGRAM)
+ STRINGIFY_CODE(METADATA, LEXICAL_BLOCK)
+ STRINGIFY_CODE(METADATA, LEXICAL_BLOCK_FILE)
+ STRINGIFY_CODE(METADATA, NAMESPACE)
+ STRINGIFY_CODE(METADATA, TEMPLATE_TYPE)
+ STRINGIFY_CODE(METADATA, TEMPLATE_VALUE)
+ STRINGIFY_CODE(METADATA, GLOBAL_VAR)
+ STRINGIFY_CODE(METADATA, LOCAL_VAR)
+ STRINGIFY_CODE(METADATA, EXPRESSION)
+ STRINGIFY_CODE(METADATA, OBJC_PROPERTY)
+ STRINGIFY_CODE(METADATA, IMPORTED_ENTITY)
+ STRINGIFY_CODE(METADATA, MODULE)
+ STRINGIFY_CODE(METADATA, MACRO)
+ STRINGIFY_CODE(METADATA, MACRO_FILE)
+ STRINGIFY_CODE(METADATA, STRINGS)
+ STRINGIFY_CODE(METADATA, GLOBAL_DECL_ATTACHMENT)
+ STRINGIFY_CODE(METADATA, GLOBAL_VAR_EXPR)
+ STRINGIFY_CODE(METADATA, INDEX_OFFSET)
+ STRINGIFY_CODE(METADATA, INDEX)
+ }
+ case bitc::METADATA_KIND_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ STRINGIFY_CODE(METADATA, KIND)
+ }
+ case bitc::USELIST_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::USELIST_CODE_DEFAULT:
+ return "USELIST_CODE_DEFAULT";
+ case bitc::USELIST_CODE_BB:
+ return "USELIST_CODE_BB";
+ }
+
+ case bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::OPERAND_BUNDLE_TAG:
+ return "OPERAND_BUNDLE_TAG";
+ }
+ case bitc::STRTAB_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::STRTAB_BLOB:
+ return "BLOB";
+ }
+ case bitc::SYMTAB_BLOCK_ID:
+ switch (CodeID) {
+ default:
+ return None;
+ case bitc::SYMTAB_BLOB:
+ return "BLOB";
+ }
+ }
+#undef STRINGIFY_CODE
+}
+
+static void printSize(raw_ostream &OS, double Bits) {
+ OS << format("%.2f/%.2fB/%luW", Bits, Bits / 8, (unsigned long)(Bits / 32));
+}
+static void printSize(raw_ostream &OS, uint64_t Bits) {
+ OS << format("%lub/%.2fB/%luW", (unsigned long)Bits, (double)Bits / 8,
+ (unsigned long)(Bits / 32));
+}
+
+static Expected<CurStreamTypeType> ReadSignature(BitstreamCursor &Stream) {
+ auto tryRead = [&Stream](char &Dest, size_t size) -> Error {
+ if (Expected<SimpleBitstreamCursor::word_t> MaybeWord = Stream.Read(size))
+ Dest = MaybeWord.get();
+ else
+ return MaybeWord.takeError();
+ return Error::success();
+ };
+
+ char Signature[6];
+ if (Error Err = tryRead(Signature[0], 8))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[1], 8))
+ return std::move(Err);
+
+ // Autodetect the file contents, if it is one we know.
+ if (Signature[0] == 'C' && Signature[1] == 'P') {
+ if (Error Err = tryRead(Signature[2], 8))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[3], 8))
+ return std::move(Err);
+ if (Signature[2] == 'C' && Signature[3] == 'H')
+ return ClangSerializedASTBitstream;
+ } else if (Signature[0] == 'D' && Signature[1] == 'I') {
+ if (Error Err = tryRead(Signature[2], 8))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[3], 8))
+ return std::move(Err);
+ if (Signature[2] == 'A' && Signature[3] == 'G')
+ return ClangSerializedDiagnosticsBitstream;
+ } else {
+ if (Error Err = tryRead(Signature[2], 4))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[3], 4))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[4], 4))
+ return std::move(Err);
+ if (Error Err = tryRead(Signature[5], 4))
+ return std::move(Err);
+ if (Signature[0] == 'B' && Signature[1] == 'C' && Signature[2] == 0x0 &&
+ Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD)
+ return LLVMIRBitstream;
+ }
+ return UnknownBitstream;
+}
+
+static Expected<CurStreamTypeType> analyzeHeader(Optional<BCDumpOptions> O,
+ BitstreamCursor &Stream) {
+ ArrayRef<uint8_t> Bytes = Stream.getBitcodeBytes();
+ const unsigned char *BufPtr = (const unsigned char *)Bytes.data();
+ const unsigned char *EndBufPtr = BufPtr + Bytes.size();
+
+ // If we have a wrapper header, parse it and ignore the non-bc file
+ // contents. The magic number is 0x0B17C0DE stored in little endian.
+ if (isBitcodeWrapper(BufPtr, EndBufPtr)) {
+ if (Bytes.size() < BWH_HeaderSize)
+ return reportError("Invalid bitcode wrapper header");
+
+ if (O) {
+ unsigned Magic = support::endian::read32le(&BufPtr[BWH_MagicField]);
+ unsigned Version = support::endian::read32le(&BufPtr[BWH_VersionField]);
+ unsigned Offset = support::endian::read32le(&BufPtr[BWH_OffsetField]);
+ unsigned Size = support::endian::read32le(&BufPtr[BWH_SizeField]);
+ unsigned CPUType = support::endian::read32le(&BufPtr[BWH_CPUTypeField]);
+
+ O->OS << "<BITCODE_WRAPPER_HEADER"
+ << " Magic=" << format_hex(Magic, 10)
+ << " Version=" << format_hex(Version, 10)
+ << " Offset=" << format_hex(Offset, 10)
+ << " Size=" << format_hex(Size, 10)
+ << " CPUType=" << format_hex(CPUType, 10) << "/>\n";
+ }
+
+ if (SkipBitcodeWrapperHeader(BufPtr, EndBufPtr, true))
+ return reportError("Invalid bitcode wrapper header");
+ }
+
+ // Use the cursor modified by skipping the wrapper header.
+ Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
+
+ return ReadSignature(Stream);
+}
+
+static bool canDecodeBlob(unsigned Code, unsigned BlockID) {
+ return BlockID == bitc::METADATA_BLOCK_ID && Code == bitc::METADATA_STRINGS;
+}
+
+Error BitcodeAnalyzer::decodeMetadataStringsBlob(StringRef Indent,
+ ArrayRef<uint64_t> Record,
+ StringRef Blob,
+ raw_ostream &OS) {
+ if (Blob.empty())
+ return reportError("Cannot decode empty blob.");
+
+ if (Record.size() != 2)
+ return reportError(
+ "Decoding metadata strings blob needs two record entries.");
+
+ unsigned NumStrings = Record[0];
+ unsigned StringsOffset = Record[1];
+ OS << " num-strings = " << NumStrings << " {\n";
+
+ StringRef Lengths = Blob.slice(0, StringsOffset);
+ SimpleBitstreamCursor R(Lengths);
+ StringRef Strings = Blob.drop_front(StringsOffset);
+ do {
+ if (R.AtEndOfStream())
+ return reportError("bad length");
+
+ Expected<uint32_t> MaybeSize = R.ReadVBR(6);
+ if (!MaybeSize)
+ return MaybeSize.takeError();
+ uint32_t Size = MaybeSize.get();
+ if (Strings.size() < Size)
+ return reportError("truncated chars");
+
+ OS << Indent << " '";
+ OS.write_escaped(Strings.slice(0, Size), /*hex=*/true);
+ OS << "'\n";
+ Strings = Strings.drop_front(Size);
+ } while (--NumStrings);
+
+ OS << Indent << " }";
+ return Error::success();
+}
+
+BitcodeAnalyzer::BitcodeAnalyzer(StringRef Buffer,
+ Optional<StringRef> BlockInfoBuffer)
+ : Stream(Buffer) {
+ if (BlockInfoBuffer)
+ BlockInfoStream.emplace(*BlockInfoBuffer);
+}
+
+Error BitcodeAnalyzer::analyze(Optional<BCDumpOptions> O,
+ Optional<StringRef> CheckHash) {
+ Expected<CurStreamTypeType> MaybeType = analyzeHeader(O, Stream);
+ if (!MaybeType)
+ return MaybeType.takeError();
+ else
+ CurStreamType = *MaybeType;
+
+ Stream.setBlockInfo(&BlockInfo);
+
+ // Read block info from BlockInfoStream, if specified.
+ // The block info must be a top-level block.
+ if (BlockInfoStream) {
+ BitstreamCursor BlockInfoCursor(*BlockInfoStream);
+ Expected<CurStreamTypeType> H = analyzeHeader(O, BlockInfoCursor);
+ if (!H)
+ return H.takeError();
+
+ while (!BlockInfoCursor.AtEndOfStream()) {
+ Expected<unsigned> MaybeCode = BlockInfoCursor.ReadCode();
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
+ return reportError("Invalid record at top-level in block info file");
+
+ Expected<unsigned> MaybeBlockID = BlockInfoCursor.ReadSubBlockID();
+ if (!MaybeBlockID)
+ return MaybeBlockID.takeError();
+ if (MaybeBlockID.get() == bitc::BLOCKINFO_BLOCK_ID) {
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
+ BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
+ if (!MaybeNewBlockInfo)
+ return MaybeNewBlockInfo.takeError();
+ Optional<BitstreamBlockInfo> NewBlockInfo =
+ std::move(MaybeNewBlockInfo.get());
+ if (!NewBlockInfo)
+ return reportError("Malformed BlockInfoBlock in block info file");
+ BlockInfo = std::move(*NewBlockInfo);
+ break;
+ }
+
+ if (Error Err = BlockInfoCursor.SkipBlock())
+ return Err;
+ }
+ }
+
+ // Parse the top-level structure. We only allow blocks at the top-level.
+ while (!Stream.AtEndOfStream()) {
+ Expected<unsigned> MaybeCode = Stream.ReadCode();
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ if (MaybeCode.get() != bitc::ENTER_SUBBLOCK)
+ return reportError("Invalid record at top-level");
+
+ Expected<unsigned> MaybeBlockID = Stream.ReadSubBlockID();
+ if (!MaybeBlockID)
+ return MaybeBlockID.takeError();
+
+ if (Error E = parseBlock(MaybeBlockID.get(), 0, O, CheckHash))
+ return E;
+ ++NumTopBlocks;
+ }
+
+ return Error::success();
+}
+
+void BitcodeAnalyzer::printStats(BCDumpOptions O,
+ Optional<StringRef> Filename) {
+ uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
+ // Print a summary of the read file.
+ O.OS << "Summary ";
+ if (Filename)
+ O.OS << "of " << Filename->data() << ":\n";
+ O.OS << " Total size: ";
+ printSize(O.OS, BufferSizeBits);
+ O.OS << "\n";
+ O.OS << " Stream type: ";
+ switch (CurStreamType) {
+ case UnknownBitstream:
+ O.OS << "unknown\n";
+ break;
+ case LLVMIRBitstream:
+ O.OS << "LLVM IR\n";
+ break;
+ case ClangSerializedASTBitstream:
+ O.OS << "Clang Serialized AST\n";
+ break;
+ case ClangSerializedDiagnosticsBitstream:
+ O.OS << "Clang Serialized Diagnostics\n";
+ break;
+ }
+ O.OS << " # Toplevel Blocks: " << NumTopBlocks << "\n";
+ O.OS << "\n";
+
+ // Emit per-block stats.
+ O.OS << "Per-block Summary:\n";
+ for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
+ E = BlockIDStats.end();
+ I != E; ++I) {
+ O.OS << " Block ID #" << I->first;
+ if (Optional<const char *> BlockName =
+ GetBlockName(I->first, BlockInfo, CurStreamType))
+ O.OS << " (" << *BlockName << ")";
+ O.OS << ":\n";
+
+ const PerBlockIDStats &Stats = I->second;
+ O.OS << " Num Instances: " << Stats.NumInstances << "\n";
+ O.OS << " Total Size: ";
+ printSize(O.OS, Stats.NumBits);
+ O.OS << "\n";
+ double pct = (Stats.NumBits * 100.0) / BufferSizeBits;
+ O.OS << " Percent of file: " << format("%2.4f%%", pct) << "\n";
+ if (Stats.NumInstances > 1) {
+ O.OS << " Average Size: ";
+ printSize(O.OS, Stats.NumBits / (double)Stats.NumInstances);
+ O.OS << "\n";
+ O.OS << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
+ << Stats.NumSubBlocks / (double)Stats.NumInstances << "\n";
+ O.OS << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
+ << Stats.NumAbbrevs / (double)Stats.NumInstances << "\n";
+ O.OS << " Tot/Avg Records: " << Stats.NumRecords << "/"
+ << Stats.NumRecords / (double)Stats.NumInstances << "\n";
+ } else {
+ O.OS << " Num SubBlocks: " << Stats.NumSubBlocks << "\n";
+ O.OS << " Num Abbrevs: " << Stats.NumAbbrevs << "\n";
+ O.OS << " Num Records: " << Stats.NumRecords << "\n";
+ }
+ if (Stats.NumRecords) {
+ double pct = (Stats.NumAbbreviatedRecords * 100.0) / Stats.NumRecords;
+ O.OS << " Percent Abbrevs: " << format("%2.4f%%", pct) << "\n";
+ }
+ O.OS << "\n";
+
+ // Print a histogram of the codes we see.
+ if (O.Histogram && !Stats.CodeFreq.empty()) {
+ std::vector<std::pair<unsigned, unsigned>> FreqPairs; // <freq,code>
+ for (unsigned i = 0, e = Stats.CodeFreq.size(); i != e; ++i)
+ if (unsigned Freq = Stats.CodeFreq[i].NumInstances)
+ FreqPairs.push_back(std::make_pair(Freq, i));
+ llvm::stable_sort(FreqPairs);
+ std::reverse(FreqPairs.begin(), FreqPairs.end());
+
+ O.OS << "\tRecord Histogram:\n";
+ O.OS << "\t\t Count # Bits b/Rec % Abv Record Kind\n";
+ for (unsigned i = 0, e = FreqPairs.size(); i != e; ++i) {
+ const PerRecordStats &RecStats = Stats.CodeFreq[FreqPairs[i].second];
+
+ O.OS << format("\t\t%7d %9lu", RecStats.NumInstances,
+ (unsigned long)RecStats.TotalBits);
+
+ if (RecStats.NumInstances > 1)
+ O.OS << format(" %9.1f",
+ (double)RecStats.TotalBits / RecStats.NumInstances);
+ else
+ O.OS << " ";
+
+ if (RecStats.NumAbbrev)
+ O.OS << format(" %7.2f", (double)RecStats.NumAbbrev /
+ RecStats.NumInstances * 100);
+ else
+ O.OS << " ";
+
+ O.OS << " ";
+ if (Optional<const char *> CodeName = GetCodeName(
+ FreqPairs[i].second, I->first, BlockInfo, CurStreamType))
+ O.OS << *CodeName << "\n";
+ else
+ O.OS << "UnknownCode" << FreqPairs[i].second << "\n";
+ }
+ O.OS << "\n";
+ }
+ }
+}
+
+Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel,
+ Optional<BCDumpOptions> O,
+ Optional<StringRef> CheckHash) {
+ std::string Indent(IndentLevel * 2, ' ');
+ uint64_t BlockBitStart = Stream.GetCurrentBitNo();
+
+ // Get the statistics for this BlockID.
+ PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
+
+ BlockStats.NumInstances++;
+
+ // BLOCKINFO is a special part of the stream.
+ bool DumpRecords = O.hasValue();
+ if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
+ if (O)
+ O->OS << Indent << "<BLOCKINFO_BLOCK/>\n";
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
+ Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
+ if (!MaybeNewBlockInfo)
+ return MaybeNewBlockInfo.takeError();
+ Optional<BitstreamBlockInfo> NewBlockInfo =
+ std::move(MaybeNewBlockInfo.get());
+ if (!NewBlockInfo)
+ return reportError("Malformed BlockInfoBlock");
+ BlockInfo = std::move(*NewBlockInfo);
+ if (Error Err = Stream.JumpToBit(BlockBitStart))
+ return Err;
+ // It's not really interesting to dump the contents of the blockinfo
+ // block.
+ DumpRecords = false;
+ }
+
+ unsigned NumWords = 0;
+ if (Error Err = Stream.EnterSubBlock(BlockID, &NumWords))
+ return Err;
+
+ // Keep it for later, when we see a MODULE_HASH record
+ uint64_t BlockEntryPos = Stream.getCurrentByteNo();
+
+ Optional<const char *> BlockName = None;
+ if (DumpRecords) {
+ O->OS << Indent << "<";
+ if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))
+ O->OS << *BlockName;
+ else
+ O->OS << "UnknownBlock" << BlockID;
+
+ if (!O->Symbolic && BlockName)
+ O->OS << " BlockID=" << BlockID;
+
+ O->OS << " NumWords=" << NumWords
+ << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";
+ }
+
+ SmallVector<uint64_t, 64> Record;
+
+ // Keep the offset to the metadata index if seen.
+ uint64_t MetadataIndexOffset = 0;
+
+ // Read all the records for this block.
+ while (1) {
+ if (Stream.AtEndOfStream())
+ return reportError("Premature end of bitstream");
+
+ uint64_t RecordStartBit = Stream.GetCurrentBitNo();
+
+ Expected<BitstreamEntry> MaybeEntry =
+ Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::Error:
+ return reportError("malformed bitcode file");
+ case BitstreamEntry::EndBlock: {
+ uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
+ BlockStats.NumBits += BlockBitEnd - BlockBitStart;
+ if (DumpRecords) {
+ O->OS << Indent << "</";
+ if (BlockName)
+ O->OS << *BlockName << ">\n";
+ else
+ O->OS << "UnknownBlock" << BlockID << ">\n";
+ }
+ return Error::success();
+ }
+
+ case BitstreamEntry::SubBlock: {
+ uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
+ if (Error E = parseBlock(Entry.ID, IndentLevel + 1, O, CheckHash))
+ return E;
+ ++BlockStats.NumSubBlocks;
+ uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
+
+ // Don't include subblock sizes in the size of this block.
+ BlockBitStart += SubBlockBitEnd - SubBlockBitStart;
+ continue;
+ }
+ case BitstreamEntry::Record:
+ // The interesting case.
+ break;
+ }
+
+ if (Entry.ID == bitc::DEFINE_ABBREV) {
+ if (Error Err = Stream.ReadAbbrevRecord())
+ return Err;
+ ++BlockStats.NumAbbrevs;
+ continue;
+ }
+
+ Record.clear();
+
+ ++BlockStats.NumRecords;
+
+ StringRef Blob;
+ uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
+ Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
+
+ // Increment the # occurrences of this code.
+ if (BlockStats.CodeFreq.size() <= Code)
+ BlockStats.CodeFreq.resize(Code + 1);
+ BlockStats.CodeFreq[Code].NumInstances++;
+ BlockStats.CodeFreq[Code].TotalBits +=
+ Stream.GetCurrentBitNo() - RecordStartBit;
+ if (Entry.ID != bitc::UNABBREV_RECORD) {
+ BlockStats.CodeFreq[Code].NumAbbrev++;
+ ++BlockStats.NumAbbreviatedRecords;
+ }
+
+ if (DumpRecords) {
+ O->OS << Indent << " <";
+ Optional<const char *> CodeName =
+ GetCodeName(Code, BlockID, BlockInfo, CurStreamType);
+ if (CodeName)
+ O->OS << *CodeName;
+ else
+ O->OS << "UnknownCode" << Code;
+ if (!O->Symbolic && CodeName)
+ O->OS << " codeid=" << Code;
+ const BitCodeAbbrev *Abbv = nullptr;
+ if (Entry.ID != bitc::UNABBREV_RECORD) {
+ Abbv = Stream.getAbbrev(Entry.ID);
+ O->OS << " abbrevid=" << Entry.ID;
+ }
+
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ O->OS << " op" << i << "=" << (int64_t)Record[i];
+
+ // If we found a metadata index, let's verify that we had an offset
+ // before and validate its forward reference offset was correct!
+ if (BlockID == bitc::METADATA_BLOCK_ID) {
+ if (Code == bitc::METADATA_INDEX_OFFSET) {
+ if (Record.size() != 2)
+ O->OS << "(Invalid record)";
+ else {
+ auto Offset = Record[0] + (Record[1] << 32);
+ MetadataIndexOffset = Stream.GetCurrentBitNo() + Offset;
+ }
+ }
+ if (Code == bitc::METADATA_INDEX) {
+ O->OS << " (offset ";
+ if (MetadataIndexOffset == RecordStartBit)
+ O->OS << "match)";
+ else
+ O->OS << "mismatch: " << MetadataIndexOffset << " vs "
+ << RecordStartBit << ")";
+ }
+ }
+
+ // If we found a module hash, let's verify that it matches!
+ if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH &&
+ CheckHash.hasValue()) {
+ if (Record.size() != 5)
+ O->OS << " (invalid)";
+ else {
+ // Recompute the hash and compare it to the one in the bitcode
+ SHA1 Hasher;
+ StringRef Hash;
+ Hasher.update(*CheckHash);
+ {
+ int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
+ auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize);
+ Hasher.update(ArrayRef<uint8_t>(Ptr, BlockSize));
+ Hash = Hasher.result();
+ }
+ SmallString<20> RecordedHash;
+ RecordedHash.resize(20);
+ int Pos = 0;
+ for (auto &Val : Record) {
+ assert(!(Val >> 32) && "Unexpected high bits set");
+ RecordedHash[Pos++] = (Val >> 24) & 0xFF;
+ RecordedHash[Pos++] = (Val >> 16) & 0xFF;
+ RecordedHash[Pos++] = (Val >> 8) & 0xFF;
+ RecordedHash[Pos++] = (Val >> 0) & 0xFF;
+ }
+ if (Hash == RecordedHash)
+ O->OS << " (match)";
+ else
+ O->OS << " (!mismatch!)";
+ }
+ }
+
+ O->OS << "/>";
+
+ if (Abbv) {
+ for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
+ const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
+ if (!Op.isEncoding() || Op.getEncoding() != BitCodeAbbrevOp::Array)
+ continue;
+ assert(i + 2 == e && "Array op not second to last");
+ std::string Str;
+ bool ArrayIsPrintable = true;
+ for (unsigned j = i - 1, je = Record.size(); j != je; ++j) {
+ if (!isPrint(static_cast<unsigned char>(Record[j]))) {
+ ArrayIsPrintable = false;
+ break;
+ }
+ Str += (char)Record[j];
+ }
+ if (ArrayIsPrintable)
+ O->OS << " record string = '" << Str << "'";
+ break;
+ }
+ }
+
+ if (Blob.data()) {
+ if (canDecodeBlob(Code, BlockID)) {
+ if (Error E = decodeMetadataStringsBlob(Indent, Record, Blob, O->OS))
+ return E;
+ } else {
+ O->OS << " blob data = ";
+ if (O->ShowBinaryBlobs) {
+ O->OS << "'";
+ O->OS.write_escaped(Blob, /*hex=*/true) << "'";
+ } else {
+ bool BlobIsPrintable = true;
+ for (unsigned i = 0, e = Blob.size(); i != e; ++i)
+ if (!isPrint(static_cast<unsigned char>(Blob[i]))) {
+ BlobIsPrintable = false;
+ break;
+ }
+
+ if (BlobIsPrintable)
+ O->OS << "'" << Blob << "'";
+ else
+ O->OS << "unprintable, " << Blob.size() << " bytes.";
+ }
+ }
+ }
+
+ O->OS << "\n";
+ }
+
+ // Make sure that we can skip the current record.
+ if (Error Err = Stream.JumpToBit(CurrentRecordPos))
+ return Err;
+ if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ ; // Do nothing.
+ else
+ return Skipped.takeError();
+ }
+}
+
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index fe051e7a9125..29dc7f616392 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1,9 +1,8 @@
//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -21,7 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Argument.h"
@@ -106,18 +105,25 @@ static Error error(const Twine &Message) {
Message, make_error_code(BitcodeError::CorruptedBitcode));
}
-/// Helper to read the header common to all bitcode files.
-static bool hasValidBitcodeHeader(BitstreamCursor &Stream) {
- // Sniff for the signature.
- if (!Stream.canSkipToPos(4) ||
- Stream.Read(8) != 'B' ||
- Stream.Read(8) != 'C' ||
- Stream.Read(4) != 0x0 ||
- Stream.Read(4) != 0xC ||
- Stream.Read(4) != 0xE ||
- Stream.Read(4) != 0xD)
- return false;
- return true;
+static Error hasInvalidBitcodeHeader(BitstreamCursor &Stream) {
+ if (!Stream.canSkipToPos(4))
+ return createStringError(std::errc::illegal_byte_sequence,
+ "file too small to contain bitcode header");
+ for (unsigned C : {'B', 'C'})
+ if (Expected<SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) {
+ if (Res.get() != C)
+ return createStringError(std::errc::illegal_byte_sequence,
+ "file doesn't start with bitcode header");
+ } else
+ return Res.takeError();
+ for (unsigned C : {0x0, 0xC, 0xE, 0xD})
+ if (Expected<SimpleBitstreamCursor::word_t> Res = Stream.Read(4)) {
+ if (Res.get() != C)
+ return createStringError(std::errc::illegal_byte_sequence,
+ "file doesn't start with bitcode header");
+ } else
+ return Res.takeError();
+ return Error::success();
}
static Expected<BitstreamCursor> initStream(MemoryBufferRef Buffer) {
@@ -134,8 +140,8 @@ static Expected<BitstreamCursor> initStream(MemoryBufferRef Buffer) {
return error("Invalid bitcode wrapper header");
BitstreamCursor Stream(ArrayRef<uint8_t>(BufPtr, BufEnd));
- if (!hasValidBitcodeHeader(Stream))
- return error("Invalid bitcode signature");
+ if (Error Err = hasInvalidBitcodeHeader(Stream))
+ return std::move(Err);
return std::move(Stream);
}
@@ -165,8 +171,8 @@ static void stripTBAA(Module *M) {
/// Read the "IDENTIFICATION_BLOCK_ID" block, do some basic enforcement on the
/// "epoch" encoded in the bitcode, and return the producer name if any.
static Expected<std::string> readIdentificationBlock(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID))
+ return std::move(Err);
// Read all the records.
SmallVector<uint64_t, 64> Record;
@@ -174,7 +180,11 @@ static Expected<std::string> readIdentificationBlock(BitstreamCursor &Stream) {
std::string ProducerIdentification;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ BitstreamEntry Entry;
+ if (Expected<BitstreamEntry> Res = Stream.advance())
+ Entry = Res.get();
+ else
+ return Res.takeError();
switch (Entry.Kind) {
default:
@@ -189,8 +199,10 @@ static Expected<std::string> readIdentificationBlock(BitstreamCursor &Stream) {
// Read a record.
Record.clear();
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (MaybeBitCode.get()) {
default: // Default behavior: reject
return error("Invalid value");
case bitc::IDENTIFICATION_CODE_STRING: // IDENTIFICATION: [strchr x N]
@@ -215,7 +227,12 @@ static Expected<std::string> readIdentificationCode(BitstreamCursor &Stream) {
if (Stream.AtEndOfStream())
return "";
- BitstreamEntry Entry = Stream.advance();
+ BitstreamEntry Entry;
+ if (Expected<BitstreamEntry> Res = Stream.advance())
+ Entry = std::move(Res.get());
+ else
+ return Res.takeError();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
case BitstreamEntry::Error:
@@ -226,25 +243,30 @@ static Expected<std::string> readIdentificationCode(BitstreamCursor &Stream) {
return readIdentificationBlock(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
static Expected<bool> hasObjCCategoryInModule(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -258,7 +280,10 @@ static Expected<bool> hasObjCCategoryInModule(BitstreamCursor &Stream) {
}
// Read a record.
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default:
break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N]
@@ -281,7 +306,11 @@ static Expected<bool> hasObjCCategory(BitstreamCursor &Stream) {
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ BitstreamEntry Entry;
+ if (Expected<BitstreamEntry> Res = Stream.advance())
+ Entry = std::move(Res.get());
+ else
+ return Res.takeError();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -294,20 +323,22 @@ static Expected<bool> hasObjCCategory(BitstreamCursor &Stream) {
return hasObjCCategoryInModule(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
static Expected<std::string> readModuleTriple(BitstreamCursor &Stream) {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
@@ -315,7 +346,10 @@ static Expected<std::string> readModuleTriple(BitstreamCursor &Stream) {
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -329,7 +363,10 @@ static Expected<std::string> readModuleTriple(BitstreamCursor &Stream) {
}
// Read a record.
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
std::string S;
@@ -348,7 +385,10 @@ static Expected<std::string> readTriple(BitstreamCursor &Stream) {
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -361,13 +401,15 @@ static Expected<std::string> readTriple(BitstreamCursor &Stream) {
return readModuleTriple(Stream);
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (llvm::Expected<unsigned> Skipped = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return Skipped.takeError();
}
}
}
@@ -452,6 +494,7 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
std::vector<std::string> GCTable;
std::vector<Type*> TypeList;
+ DenseMap<Function *, FunctionType *> FunctionTypes;
BitcodeReaderValueList ValueList;
Optional<MetadataLoader> MDLoader;
std::vector<Comdat *> ComdatList;
@@ -550,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<PointerType>(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<Type *, Type *> getPointerElementTypes(Type *FullTy) {
+ Type *ElTy = cast<PointerType>(FullTy)->getElementType();
+ return std::make_pair(ElTy, flattenPointerTypes(ElTy));
+ }
- Value *getFnValueByID(unsigned ID, Type *Ty) {
+ /// Return the flattened type (suitable for use in a Value)
+ /// specified by the given \param ID .
+ Type *getTypeByID(unsigned ID) {
+ return flattenPointerTypes(getFullyStructuredTypeByID(ID));
+ }
+
+ /// 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) {
@@ -577,7 +650,8 @@ private:
/// Increment Slot past the number of slots used in the record. Return true on
/// failure.
bool getValueTypePair(SmallVectorImpl<uint64_t> &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.
@@ -586,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())
@@ -594,6 +668,8 @@ private:
unsigned TypeNo = (unsigned)Record[Slot++];
ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+ if (FullTy)
+ *FullTy = getFullyStructuredTypeByID(TypeNo);
return ResVal == nullptr;
}
@@ -639,6 +715,10 @@ private:
return getFnValueByID(ValNo, Ty);
}
+ /// Upgrades old-style typeless byval attributes by adding the corresponding
+ /// argument's pointee type.
+ void propagateByValTypes(CallBase *CB, ArrayRef<Type *> ArgsFullTys);
+
/// Converts alignment exponent (i.e. power of two (or zero)) to the
/// corresponding alignment to use. If alignment is too large, returns
/// a corresponding error code.
@@ -748,6 +828,9 @@ private:
bool HasRelBF);
Error parseEntireSummary(unsigned ID);
Error parseModuleStringTable();
+ void parseTypeIdCompatibleVtableSummaryRecord(ArrayRef<uint64_t> Record);
+ void parseTypeIdCompatibleVtableInfo(ArrayRef<uint64_t> Record, size_t &Slot,
+ TypeIdCompatibleVtableInfo &TypeId);
std::pair<ValueInfo, GlobalValue::GUID>
getValueInfoFromValueId(unsigned ValueId);
@@ -775,7 +858,7 @@ BitcodeReader::BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
StringRef ProducerIdentification,
LLVMContext &Context)
: BitcodeReaderBase(std::move(Stream), Strtab), Context(Context),
- ValueList(Context) {
+ ValueList(Context, Stream.SizeInBytes()) {
this->ProducerIdentification = ProducerIdentification;
}
@@ -894,13 +977,15 @@ static GlobalValueSummary::GVFlags getDecodedGVSummaryFlags(uint64_t RawFlags,
// values as live.
bool Live = (RawFlags & 0x2) || Version < 3;
bool Local = (RawFlags & 0x4);
+ bool AutoHide = (RawFlags & 0x8);
- return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live, Local);
+ return GlobalValueSummary::GVFlags(Linkage, NotEligibleToImport, Live, Local, AutoHide);
}
// Decode the flags for GlobalVariable in the summary
static GlobalVarSummary::GVarFlags getDecodedGVarFlags(uint64_t RawFlags) {
- return GlobalVarSummary::GVarFlags((RawFlags & 0x1) ? true : false);
+ return GlobalVarSummary::GVarFlags((RawFlags & 0x1) ? true : false,
+ (RawFlags & 0x2) ? true : false);
}
static GlobalValue::VisibilityTypes getDecodedVisibility(unsigned Val) {
@@ -1035,6 +1120,8 @@ static AtomicRMWInst::BinOp getDecodedRMWOperation(unsigned Val) {
case bitc::RMW_MIN: return AtomicRMWInst::Min;
case bitc::RMW_UMAX: return AtomicRMWInst::UMax;
case bitc::RMW_UMIN: return AtomicRMWInst::UMin;
+ case bitc::RMW_FADD: return AtomicRMWInst::FAdd;
+ case bitc::RMW_FSUB: return AtomicRMWInst::FSub;
}
}
@@ -1095,7 +1182,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;
@@ -1187,6 +1274,15 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
case Attribute::ShadowCallStack: return 1ULL << 59;
case Attribute::SpeculativeLoadHardening:
return 1ULL << 60;
+ case Attribute::ImmArg:
+ return 1ULL << 61;
+ case Attribute::WillReturn:
+ return 1ULL << 62;
+ case Attribute::NoFree:
+ return 1ULL << 63;
+ case Attribute::NoSync:
+ llvm_unreachable("nosync attribute not supported in raw format");
+ break;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
@@ -1200,6 +1296,9 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
case Attribute::AllocSize:
llvm_unreachable("allocsize not supported in raw format");
break;
+ case Attribute::SanitizeMemTag:
+ llvm_unreachable("sanitize_memtag attribute not supported in raw format");
+ break;
}
llvm_unreachable("Unsupported attribute type");
}
@@ -1209,10 +1308,12 @@ static void addRawAttributeValue(AttrBuilder &B, uint64_t Val) {
for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
I = Attribute::AttrKind(I + 1)) {
- if (I == Attribute::Dereferenceable ||
+ if (I == Attribute::SanitizeMemTag ||
+ I == Attribute::Dereferenceable ||
I == Attribute::DereferenceableOrNull ||
I == Attribute::ArgMemOnly ||
- I == Attribute::AllocSize)
+ I == Attribute::AllocSize ||
+ I == Attribute::NoSync)
continue;
if (uint64_t A = (Val & getRawAttributeMask(I))) {
if (I == Attribute::Alignment)
@@ -1245,8 +1346,8 @@ static void decodeLLVMAttributesForBitcode(AttrBuilder &B,
}
Error BitcodeReader::parseAttributeBlock() {
- if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID))
+ return Err;
if (!MAttributes.empty())
return error("Invalid multiple blocks");
@@ -1257,7 +1358,10 @@ Error BitcodeReader::parseAttributeBlock() {
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1272,7 +1376,10 @@ Error BitcodeReader::parseAttributeBlock() {
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::PARAMATTR_CODE_ENTRY_OLD: // ENTRY: [paramidx0, attr0, ...]
@@ -1345,6 +1452,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::NoCapture;
case bitc::ATTR_KIND_NO_DUPLICATE:
return Attribute::NoDuplicate;
+ case bitc::ATTR_KIND_NOFREE:
+ return Attribute::NoFree;
case bitc::ATTR_KIND_NO_IMPLICIT_FLOAT:
return Attribute::NoImplicitFloat;
case bitc::ATTR_KIND_NO_INLINE:
@@ -1365,6 +1474,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::NoRedZone;
case bitc::ATTR_KIND_NO_RETURN:
return Attribute::NoReturn;
+ case bitc::ATTR_KIND_NOSYNC:
+ return Attribute::NoSync;
case bitc::ATTR_KIND_NOCF_CHECK:
return Attribute::NoCfCheck;
case bitc::ATTR_KIND_NO_UNWIND:
@@ -1419,10 +1530,16 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::SwiftSelf;
case bitc::ATTR_KIND_UW_TABLE:
return Attribute::UWTable;
+ case bitc::ATTR_KIND_WILLRETURN:
+ return Attribute::WillReturn;
case bitc::ATTR_KIND_WRITEONLY:
return Attribute::WriteOnly;
case bitc::ATTR_KIND_Z_EXT:
return Attribute::ZExt;
+ case bitc::ATTR_KIND_IMMARG:
+ return Attribute::ImmArg;
+ case bitc::ATTR_KIND_SANITIZE_MEMTAG:
+ return Attribute::SanitizeMemTag;
}
}
@@ -1444,8 +1561,8 @@ Error BitcodeReader::parseAttrKind(uint64_t Code, Attribute::AttrKind *Kind) {
}
Error BitcodeReader::parseAttributeGroupBlock() {
- if (Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::PARAMATTR_GROUP_BLOCK_ID))
+ return Err;
if (!MAttributeGroups.empty())
return error("Invalid multiple blocks");
@@ -1454,7 +1571,10 @@ Error BitcodeReader::parseAttributeGroupBlock() {
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1469,7 +1589,10 @@ Error BitcodeReader::parseAttributeGroupBlock() {
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::PARAMATTR_GRP_CODE_ENTRY: { // ENTRY: [grpid, idx, a0, a1, ...]
@@ -1486,6 +1609,12 @@ Error BitcodeReader::parseAttributeGroupBlock() {
if (Error Err = parseAttrKind(Record[++i], &Kind))
return Err;
+ // Upgrade old-style byval attribute to one with a type, even if it's
+ // nullptr. We will have to insert the real type when we associate
+ // this AttributeList with a function.
+ if (Kind == Attribute::ByVal)
+ B.addByValAttr(nullptr);
+
B.addAttribute(Kind);
} else if (Record[i] == 1) { // Integer attribute
Attribute::AttrKind Kind;
@@ -1501,9 +1630,7 @@ Error BitcodeReader::parseAttributeGroupBlock() {
B.addDereferenceableOrNullAttr(Record[++i]);
else if (Kind == Attribute::AllocSize)
B.addAllocSizeAttrFromRawRepr(Record[++i]);
- } else { // String attribute
- assert((Record[i] == 3 || Record[i] == 4) &&
- "Invalid attribute group entry");
+ } else if (Record[i] == 3 || Record[i] == 4) { // String attribute
bool HasValue = (Record[i++] == 4);
SmallString<64> KindStr;
SmallString<64> ValStr;
@@ -1521,6 +1648,15 @@ Error BitcodeReader::parseAttributeGroupBlock() {
}
B.addAttribute(KindStr.str(), ValStr.str());
+ } else {
+ assert((Record[i] == 5 || Record[i] == 6) &&
+ "Invalid attribute group entry");
+ bool HasType = Record[i] == 6;
+ Attribute::AttrKind Kind;
+ if (Error Err = parseAttrKind(Record[++i], &Kind))
+ return Err;
+ if (Kind == Attribute::ByVal)
+ B.addByValAttr(HasType ? getTypeByID(Record[++i]) : nullptr);
}
}
@@ -1532,8 +1668,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
}
Error BitcodeReader::parseTypeTable() {
- if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID_NEW))
+ return Err;
return parseTypeTableBody();
}
@@ -1549,7 +1685,10 @@ Error BitcodeReader::parseTypeTableBody() {
// Read all the records for this type table.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1567,7 +1706,10 @@ Error BitcodeReader::parseTypeTableBody() {
// Read a record.
Record.clear();
Type *ResultTy = nullptr;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default:
return error("Invalid value");
case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
@@ -1752,7 +1894,8 @@ Error BitcodeReader::parseTypeTableBody() {
return error("Invalid type");
ResultTy = ArrayType::get(ResultTy, Record[0]);
break;
- case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty]
+ case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty] or
+ // [numelts, eltty, scalable]
if (Record.size() < 2)
return error("Invalid record");
if (Record[0] == 0)
@@ -1760,7 +1903,8 @@ Error BitcodeReader::parseTypeTableBody() {
ResultTy = getTypeByID(Record[1]);
if (!ResultTy || !StructType::isValidElementType(ResultTy))
return error("Invalid type");
- ResultTy = VectorType::get(ResultTy, Record[0]);
+ bool Scalable = Record.size() > 2 ? Record[2] : false;
+ ResultTy = VectorType::get(ResultTy, Record[0], Scalable);
break;
}
@@ -1775,8 +1919,8 @@ Error BitcodeReader::parseTypeTableBody() {
}
Error BitcodeReader::parseOperandBundleTags() {
- if (Stream.EnterSubBlock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::OPERAND_BUNDLE_TAGS_BLOCK_ID))
+ return Err;
if (!BundleTags.empty())
return error("Invalid multiple blocks");
@@ -1784,7 +1928,10 @@ Error BitcodeReader::parseOperandBundleTags() {
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1799,7 +1946,10 @@ Error BitcodeReader::parseOperandBundleTags() {
// Tags are implicitly mapped to integers by their order.
- if (Stream.readRecord(Entry.ID, Record) != bitc::OPERAND_BUNDLE_TAG)
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ if (MaybeRecord.get() != bitc::OPERAND_BUNDLE_TAG)
return error("Invalid record");
// OPERAND_BUNDLE_TAG: [strchr x N]
@@ -1811,15 +1961,19 @@ Error BitcodeReader::parseOperandBundleTags() {
}
Error BitcodeReader::parseSyncScopeNames() {
- if (Stream.EnterSubBlock(bitc::SYNC_SCOPE_NAMES_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::SYNC_SCOPE_NAMES_BLOCK_ID))
+ return Err;
if (!SSIDs.empty())
return error("Invalid multiple synchronization scope names blocks");
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
case BitstreamEntry::Error:
@@ -1836,7 +1990,10 @@ Error BitcodeReader::parseSyncScopeNames() {
// Synchronization scope names are implicitly mapped to synchronization
// scope IDs by their order.
- if (Stream.readRecord(Entry.ID, Record) != bitc::SYNC_SCOPE_NAME)
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ if (MaybeRecord.get() != bitc::SYNC_SCOPE_NAME)
return error("Invalid record");
SmallString<16> SSN;
@@ -1877,22 +2034,18 @@ Expected<Value *> BitcodeReader::recordValue(SmallVectorImpl<uint64_t> &Record,
/// Helper to note and return the current location, and jump to the given
/// offset.
-static uint64_t jumpToValueSymbolTable(uint64_t Offset,
- BitstreamCursor &Stream) {
+static Expected<uint64_t> jumpToValueSymbolTable(uint64_t Offset,
+ BitstreamCursor &Stream) {
// Save the current parsing location so we can jump back at the end
// of the VST read.
uint64_t CurrentBit = Stream.GetCurrentBitNo();
- Stream.JumpToBit(Offset * 32);
-#ifndef NDEBUG
- // Do some checking if we are in debug mode.
- BitstreamEntry Entry = Stream.advance();
- assert(Entry.Kind == BitstreamEntry::SubBlock);
- assert(Entry.ID == bitc::VALUE_SYMTAB_BLOCK_ID);
-#else
- // In NDEBUG mode ignore the output so we don't get an unused variable
- // warning.
- Stream.advance();
-#endif
+ if (Error JumpFailed = Stream.JumpToBit(Offset * 32))
+ return std::move(JumpFailed);
+ Expected<BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ assert(MaybeEntry.get().Kind == BitstreamEntry::SubBlock);
+ assert(MaybeEntry.get().ID == bitc::VALUE_SYMTAB_BLOCK_ID);
return CurrentBit;
}
@@ -1917,12 +2070,15 @@ Error BitcodeReader::parseGlobalValueSymbolTable() {
unsigned FuncBitcodeOffsetDelta =
Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
- if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock:
@@ -1935,7 +2091,10 @@ Error BitcodeReader::parseGlobalValueSymbolTable() {
}
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
case bitc::VST_CODE_FNENTRY: // [valueid, offset]
setDeferredFunctionInfo(FuncBitcodeOffsetDelta,
cast<Function>(ValueList[Record[0]]), Record);
@@ -1952,12 +2111,16 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
// VST (where we want to jump to the VST offset) and the function-level
// VST (where we don't).
if (Offset > 0) {
- CurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ Expected<uint64_t> MaybeCurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ if (!MaybeCurrentBit)
+ return MaybeCurrentBit.takeError();
+ CurrentBit = MaybeCurrentBit.get();
// If this module uses a string table, read this as a module-level VST.
if (UseStrtab) {
if (Error Err = parseGlobalValueSymbolTable())
return Err;
- Stream.JumpToBit(CurrentBit);
+ if (Error JumpFailed = Stream.JumpToBit(CurrentBit))
+ return JumpFailed;
return Error::success();
}
// Otherwise, the VST will be in a similar format to a function-level VST,
@@ -1978,8 +2141,8 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
unsigned FuncBitcodeOffsetDelta =
Stream.getAbbrevIDWidth() + bitc::BlockIDWidth;
- if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
@@ -1989,7 +2152,10 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
SmallString<128> ValueName;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1997,7 +2163,8 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
return error("Malformed block");
case BitstreamEntry::EndBlock:
if (Offset > 0)
- Stream.JumpToBit(CurrentBit);
+ if (Error JumpFailed = Stream.JumpToBit(CurrentBit))
+ return JumpFailed;
return Error::success();
case BitstreamEntry::Record:
// The interesting case.
@@ -2006,7 +2173,10 @@ Error BitcodeReader::parseValueSymbolTable(uint64_t Offset) {
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: unknown type.
break;
case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N]
@@ -2151,17 +2321,21 @@ static APInt readWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
}
Error BitcodeReader::parseConstants() {
- if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records for this value table.
Type *CurTy = Type::getInt32Ty(Context);
+ Type *CurFullTy = Type::getInt32Ty(Context);
unsigned NextCstNo = ValueList.size();
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -2184,8 +2358,10 @@ Error BitcodeReader::parseConstants() {
Record.clear();
Type *VoidType = Type::getVoidTy(Context);
Value *V = nullptr;
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (unsigned BitCode = MaybeBitCode.get()) {
default: // Default behavior: unknown constant
case bitc::CST_CODE_UNDEF: // UNDEF
V = UndefValue::get(CurTy);
@@ -2197,7 +2373,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);
@@ -2416,23 +2593,27 @@ Error BitcodeReader::parseConstants() {
InBounds = true;
SmallVector<Constant*, 16> 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");
Elts.push_back(ValueList.getConstantFwdRef(Record[OpNum++], ElTy));
}
- if (PointeeType &&
- PointeeType !=
- cast<PointerType>(Elts[0]->getType()->getScalarType())
- ->getElementType())
- return error("Explicit gep operator type does not match pointee type "
- "of pointer operand");
-
if (Elts.size() < 1)
return error("Invalid gep with no operands");
+ Type *ImplicitPointeeType =
+ getPointerElementFlatType(Elt0FullTy->getScalarType());
+ if (!PointeeType)
+ PointeeType = ImplicitPointeeType;
+ else if (PointeeType != ImplicitPointeeType)
+ return error("Explicit gep operator type does not match pointee type "
+ "of pointer operand");
+
ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
InBounds, InRangeIndex);
@@ -2560,10 +2741,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<PointerType>(CurTy);
UpgradeInlineAsmString(&AsmStr);
- V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
- AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+ V = InlineAsm::get(
+ cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr,
+ ConstrStr, HasSideEffects, IsAlignStack);
break;
}
// This version adds support for the asm dialect keywords (e.g.,
@@ -2586,11 +2767,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<PointerType>(CurTy);
UpgradeInlineAsmString(&AsmStr);
- V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
- AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
- InlineAsm::AsmDialect(AsmDialect));
+ V = InlineAsm::get(
+ cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr,
+ ConstrStr, HasSideEffects, IsAlignStack,
+ InlineAsm::AsmDialect(AsmDialect));
break;
}
case bitc::CST_CODE_BLOCKADDRESS:{
@@ -2636,20 +2817,25 @@ 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;
}
}
Error BitcodeReader::parseUseLists() {
- if (Stream.EnterSubBlock(bitc::USELIST_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::USELIST_BLOCK_ID))
+ return Err;
// Read all the records.
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -2665,7 +2851,10 @@ Error BitcodeReader::parseUseLists() {
// Read a use list record.
Record.clear();
bool IsBB = false;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: unknown type.
break;
case bitc::USELIST_CODE_BB:
@@ -2714,15 +2903,16 @@ Error BitcodeReader::rememberAndSkipMetadata() {
DeferredMetadataInfo.push_back(CurBit);
// Skip over the block for now.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
return Error::success();
}
Error BitcodeReader::materializeMetadata() {
for (uint64_t BitPos : DeferredMetadataInfo) {
// Move the bit stream to the saved position.
- Stream.JumpToBit(BitPos);
+ if (Error JumpFailed = Stream.JumpToBit(BitPos))
+ return JumpFailed;
if (Error Err = MDLoader->parseModuleMetadata())
return Err;
}
@@ -2760,8 +2950,8 @@ Error BitcodeReader::rememberAndSkipFunctionBody() {
DeferredFunctionInfo[Fn] = CurBit;
// Skip over the function block for now.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
return Error::success();
}
@@ -2786,8 +2976,14 @@ Error BitcodeReader::globalCleanup() {
}
// Look for global variables which need to be renamed.
+ std::vector<std::pair<GlobalVariable *, GlobalVariable *>> UpgradedVariables;
for (GlobalVariable &GV : TheModule->globals())
- UpgradeGlobalVariable(&GV);
+ if (GlobalVariable *Upgraded = UpgradeGlobalVariable(&GV))
+ UpgradedVariables.emplace_back(&GV, Upgraded);
+ for (auto &Pair : UpgradedVariables) {
+ Pair.first->eraseFromParent();
+ TheModule->getGlobalList().push_back(Pair.second);
+ }
// Force deallocation of memory for these vectors to favor the client that
// want lazy deserialization.
@@ -2802,7 +2998,8 @@ Error BitcodeReader::globalCleanup() {
/// or if we have an anonymous function being materialized, since anonymous
/// functions do not have a name and are therefore not in the VST.
Error BitcodeReader::rememberAndSkipFunctionBodies() {
- Stream.JumpToBit(NextUnreadBit);
+ if (Error JumpFailed = Stream.JumpToBit(NextUnreadBit))
+ return JumpFailed;
if (Stream.AtEndOfStream())
return error("Could not find function in stream");
@@ -2817,7 +3014,11 @@ Error BitcodeReader::rememberAndSkipFunctionBodies() {
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
default:
return error("Expect SubBlock");
@@ -2836,7 +3037,12 @@ Error BitcodeReader::rememberAndSkipFunctionBodies() {
}
bool BitcodeReaderBase::readBlockInfo() {
- Optional<BitstreamBlockInfo> NewBlockInfo = Stream.ReadBlockInfoBlock();
+ Expected<Optional<BitstreamBlockInfo>> MaybeNewBlockInfo =
+ Stream.ReadBlockInfoBlock();
+ if (!MaybeNewBlockInfo)
+ return true; // FIXME Handle the error.
+ Optional<BitstreamBlockInfo> NewBlockInfo =
+ std::move(MaybeNewBlockInfo.get());
if (!NewBlockInfo)
return true;
BlockInfo = std::move(*NewBlockInfo);
@@ -2878,14 +3084,16 @@ static void inferDSOLocal(GlobalValue *GV) {
Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
// v1: [pointer type, isconst, initid, linkage, alignment, section,
// visibility, threadlocal, unnamed_addr, externally_initialized,
- // dllstorageclass, comdat, attributes, preemption specifier] (name in VST)
+ // dllstorageclass, comdat, attributes, preemption specifier,
+ // partition strtab offset, partition strtab size] (name in VST)
// v2: [strtab_offset, strtab_size, v1]
StringRef Name;
std::tie(Name, Record) = readNameFromStrtab(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;
@@ -2897,7 +3105,7 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
if (!Ty->isPointerTy())
return error("Invalid type for value");
AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
- Ty = cast<PointerType>(Ty)->getElementType();
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
}
uint64_t RawLinkage = Record[3];
@@ -2943,7 +3151,10 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> 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])
@@ -2969,6 +3180,10 @@ Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
}
inferDSOLocal(NewGV);
+ // Check whether we have enough values to read a partition name.
+ if (Record.size() > 15)
+ NewGV->setPartition(StringRef(Strtab.data() + Record[14], Record[15]));
+
return Error::success();
}
@@ -2982,13 +3197,14 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> 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<PointerType>(Ty))
- Ty = PTy->getElementType();
- auto *FTy = dyn_cast<FunctionType>(Ty);
+ Type *FullFTy = getFullyStructuredTypeByID(Record[0]);
+ Type *FTy = flattenPointerTypes(FullFTy);
if (!FTy)
+ return error("Invalid record");
+ if (isa<PointerType>(FTy))
+ std::tie(FullFTy, FTy) = getPointerElementTypes(FullFTy);
+
+ if (!isa<FunctionType>(FTy))
return error("Invalid type for value");
auto CC = static_cast<CallingConv::ID>(Record[1]);
if (CC & ~CallingConv::MaxID)
@@ -2998,8 +3214,13 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
if (Record.size() > 16)
AddrSpace = Record[16];
- Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
- AddrSpace, Name, TheModule);
+ Function *Func =
+ Function::Create(cast<FunctionType>(FTy), GlobalValue::ExternalLinkage,
+ AddrSpace, Name, TheModule);
+
+ assert(Func->getFunctionType() == flattenPointerTypes(FullFTy) &&
+ "Incorrect fully specified type provided for function");
+ FunctionTypes[Func] = cast<FunctionType>(FullFTy);
Func->setCallingConv(CC);
bool isProto = Record[2];
@@ -3007,6 +3228,19 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
Func->setLinkage(getDecodedLinkage(RawLinkage));
Func->setAttributes(getAttributes(Record[4]));
+ // 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 (unsigned i = 0; i != Func->arg_size(); ++i) {
+ if (!Func->hasParamAttribute(i, Attribute::ByVal))
+ continue;
+
+ Type *PTy = cast<FunctionType>(FullFTy)->getParamType(i);
+ Func->removeParamAttr(i, Attribute::ByVal);
+ Func->addParamAttr(i, Attribute::getWithByValType(
+ Context, getPointerElementFlatType(PTy)));
+ }
+
unsigned Alignment;
if (Error Err = parseAlignmentValue(Record[5], Alignment))
return Err;
@@ -3058,7 +3292,16 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
}
inferDSOLocal(Func);
- ValueList.push_back(Func);
+ // Record[16] is the address space number.
+
+ // Check whether we have enough values to read a partition name.
+ if (Record.size() > 18)
+ Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18]));
+
+ 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.
@@ -3087,7 +3330,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");
@@ -3096,7 +3340,7 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord(
auto *PTy = dyn_cast<PointerType>(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++];
@@ -3112,6 +3356,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()) {
@@ -3135,23 +3382,37 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord(
NewGA->setDSOLocal(getDecodedDSOLocal(Record[OpNum++]));
inferDSOLocal(NewGA);
- ValueList.push_back(NewGA);
+ // Check whether we have enough values to read a partition name.
+ if (OpNum + 1 < Record.size()) {
+ NewGA->setPartition(
+ StringRef(Strtab.data() + Record[OpNum], Record[OpNum + 1]));
+ OpNum += 2;
+ }
+
+ 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();
}
Error BitcodeReader::parseModule(uint64_t ResumeBit,
bool ShouldLazyLoadMetadata) {
- if (ResumeBit)
- Stream.JumpToBit(ResumeBit);
- else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (ResumeBit) {
+ if (Error JumpFailed = Stream.JumpToBit(ResumeBit))
+ return JumpFailed;
+ } else if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -3162,8 +3423,8 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::BLOCKINFO_BLOCK_ID:
if (readBlockInfo())
@@ -3196,8 +3457,8 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
// We must have had a VST forward declaration record, which caused
// the parser to jump to and parse the VST earlier.
assert(VSTOffset > 0);
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
}
break;
case bitc::CONSTANTS_BLOCK_ID:
@@ -3249,8 +3510,8 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
// materializing functions. The ResumeBit points to the
// start of the last function block recorded in the
// DeferredFunctionInfo map. Skip it.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
continue;
}
}
@@ -3294,8 +3555,10 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
}
// Read a record.
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (unsigned BitCode = MaybeBitCode.get()) {
default: break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_VERSION: {
Expected<unsigned> VersionOrErr = parseVersionRecord(Record);
@@ -3407,10 +3670,23 @@ Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) {
return Error::success();
}
+void BitcodeReader::propagateByValTypes(CallBase *CB,
+ ArrayRef<Type *> 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])));
+ }
+}
+
/// Lazily parse the specified function body block.
Error BitcodeReader::parseFunctionBody(Function *F) {
- if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
+ return Err;
// Unexpected unresolved metadata when parsing function.
if (MDLoader->hasFwdRefs())
@@ -3421,9 +3697,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;
@@ -3444,7 +3724,10 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -3455,8 +3738,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::CONSTANTS_BLOCK_ID:
if (Error Err = parseConstants())
@@ -3492,8 +3775,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
// Read a record.
Record.clear();
Instruction *I = nullptr;
- unsigned BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Type *FullTy = nullptr;
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (unsigned BitCode = MaybeBitCode.get()) {
default: // Default behavior: reject
return error("Invalid value");
case bitc::FUNC_CODE_DECLAREBLOCKS: { // DECLAREBLOCKS: [nblocks]
@@ -3634,7 +3920,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");
@@ -3663,22 +3950,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<PointerType>(BasePtr->getType()->getScalarType())
- ->getElementType();
- else if (Ty !=
- cast<PointerType>(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");
@@ -3691,6 +3978,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
}
I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx);
+ FullTy = GetElementPtrInst::getGEPReturnType(FullTy, I, GEPIdx);
InstructionList.push_back(I);
if (InBounds)
@@ -3702,7 +3990,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();
@@ -3710,26 +3998,25 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
return error("EXTRACTVAL: Invalid instruction with 0 indices");
SmallVector<unsigned, 4> 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);
@@ -3741,7 +4028,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))
@@ -3787,7 +4074,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");
@@ -3802,7 +4089,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");
@@ -3821,18 +4108,24 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
I = SelectInst::Create(Cond, TrueVal, FalseVal);
InstructionList.push_back(I);
+ if (OpNum < Record.size() && isa<FPMathOperator>(I)) {
+ FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]);
+ if (FMF.any())
+ I->setFastMathFlags(FMF);
+ }
break;
}
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;
}
@@ -3840,7 +4133,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");
@@ -3856,7 +4149,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");
@@ -3865,6 +4158,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;
}
@@ -3882,6 +4177,10 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS))
return error("Invalid record");
+ if (OpNum >= Record.size())
+ return error(
+ "Invalid record: operand number exceeded available operands");
+
unsigned PredVal = Record[OpNum];
bool IsFP = LHS->getType()->isFPOrFPVectorTy();
FastMathFlags FMF;
@@ -4168,31 +4467,40 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]);
FunctionType *FTy = nullptr;
- if (CCInfo >> 13 & 1 &&
- !(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
- return error("Explicit invoke type is not a function type");
+ FunctionType *FullFTy = nullptr;
+ if ((CCInfo >> 13) & 1) {
+ FullFTy =
+ dyn_cast<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit invoke type is not a function type");
+ FTy = cast<FunctionType>(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<PointerType>(Callee->getType());
if (!CalleeTy)
return error("Callee is not a pointer");
if (!FTy) {
- FTy = dyn_cast<FunctionType>(CalleeTy->getElementType());
- if (!FTy)
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
return error("Callee is not of pointer to function type");
- } else if (CalleeTy->getElementType() != FTy)
+ FTy = cast<FunctionType>(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<Value*, 16> Ops;
+ SmallVector<Type *, 16> 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");
}
@@ -4204,18 +4512,24 @@ 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(Callee, NormalBB, UnwindBB, Ops, OperandBundles);
+ I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops,
+ OperandBundles);
+ FullTy = FullFTy->getReturnType();
OperandBundles.clear();
InstructionList.push_back(I);
cast<InvokeInst>(I)->setCallingConv(
static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
cast<InvokeInst>(I)->setAttributes(PAL);
+ propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
+
break;
}
case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
@@ -4227,6 +4541,82 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
InstructionList.push_back(I);
break;
}
+ case bitc::FUNC_CODE_INST_CALLBR: {
+ // CALLBR: [attr, cc, norm, transfs, fty, fnid, args]
+ unsigned OpNum = 0;
+ AttributeList PAL = getAttributes(Record[OpNum++]);
+ unsigned CCInfo = Record[OpNum++];
+
+ BasicBlock *DefaultDest = getBasicBlock(Record[OpNum++]);
+ unsigned NumIndirectDests = Record[OpNum++];
+ SmallVector<BasicBlock *, 16> IndirectDests;
+ for (unsigned i = 0, e = NumIndirectDests; i != e; ++i)
+ IndirectDests.push_back(getBasicBlock(Record[OpNum++]));
+
+ FunctionType *FTy = nullptr;
+ FunctionType *FullFTy = nullptr;
+ if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) {
+ FullFTy =
+ dyn_cast<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit call type is not a function type");
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ }
+
+ Value *Callee;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy))
+ return error("Invalid record");
+
+ PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
+ if (!OpTy)
+ return error("Callee is not a pointer type");
+ if (!FTy) {
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
+ return error("Callee is not of pointer to function type");
+ FTy = cast<FunctionType>(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<Value*, 16> Args;
+ // Read the fixed params.
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
+ if (FTy->getParamType(i)->isLabelTy())
+ Args.push_back(getBasicBlock(Record[OpNum]));
+ else
+ Args.push_back(getValue(Record, OpNum, NextValueNo,
+ FTy->getParamType(i)));
+ if (!Args.back())
+ return error("Invalid record");
+ }
+
+ // Read type/value pairs for varargs params.
+ if (!FTy->isVarArg()) {
+ if (OpNum != Record.size())
+ return error("Invalid record");
+ } else {
+ while (OpNum != Record.size()) {
+ Value *Op;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ return error("Invalid record");
+ Args.push_back(Op);
+ }
+ }
+
+ I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args,
+ OperandBundles);
+ FullTy = FullFTy->getReturnType();
+ OperandBundles.clear();
+ InstructionList.push_back(I);
+ cast<CallBrInst>(I)->setCallingConv(
+ static_cast<CallingConv::ID>((0x7ff & CCInfo) >> bitc::CALL_CCONV));
+ cast<CallBrInst>(I)->setAttributes(PAL);
+ break;
+ }
case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
I = new UnreachableInst(Context);
InstructionList.push_back(I);
@@ -4234,7 +4624,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");
@@ -4271,7 +4662,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) {
@@ -4324,12 +4716,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<PointerType>(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);
@@ -4348,29 +4741,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<PointerType>(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<PointerType>(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;
}
@@ -4378,17 +4776,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<PointerType>(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<PointerType>(Op->getType())->getElementType();
AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]);
if (Ordering == AtomicOrdering::NotAtomic ||
@@ -4402,8 +4805,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
unsigned Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
- I = new LoadInst(Op, "", Record[OpNum+1], Align, Ordering, SSID);
-
+ I = new LoadInst(Ty, Op, "", Record[OpNum + 1], Align, Ordering, SSID);
InstructionList.push_back(I);
break;
}
@@ -4411,12 +4813,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<PointerType>(Ptr->getType())->getElementType(),
- Val)) ||
+ getPointerElementFlatType(FullTy), Val)) ||
OpNum + 2 != Record.size())
return error("Invalid record");
@@ -4434,13 +4836,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<PointerType>(Ptr->getType()) ||
(BitCode == bitc::FUNC_CODE_INST_STOREATOMIC
? getValueTypePair(Record, OpNum, NextValueNo, Val)
: popValue(Record, OpNum, NextValueNo,
- cast<PointerType>(Ptr->getType())->getElementType(),
- Val)) ||
+ getPointerElementFlatType(FullTy), Val)) ||
OpNum + 4 != Record.size())
return error("Invalid record");
@@ -4468,15 +4870,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<PointerType>(Ptr->getType())->getElementType(),
- Cmp)) ||
- popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy))
+ return error("Invalid record");
+
+ if (!isa<PointerType>(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<PointerType>(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)
@@ -4494,6 +4906,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
I = new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, FailureOrdering,
SSID);
+ FullTy = StructType::get(Context, {FullTy, Type::getInt1Ty(Context)});
cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
if (Record.size() < 8) {
@@ -4502,6 +4915,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<StructType>(FullTy)->getElementType(0);
} else {
cast<AtomicCmpXchgInst>(I)->setWeak(Record[OpNum+4]);
}
@@ -4513,11 +4927,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<PointerType>(Ptr->getType()) ||
popValue(Record, OpNum, NextValueNo,
- cast<PointerType>(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 ||
@@ -4529,6 +4943,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<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
InstructionList.push_back(I);
break;
@@ -4563,28 +4978,36 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
}
FunctionType *FTy = nullptr;
- if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 &&
- !(FTy = dyn_cast<FunctionType>(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<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit call type is not a function type");
+ FTy = cast<FunctionType>(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<PointerType>(Callee->getType());
if (!OpTy)
return error("Callee is not a pointer type");
if (!FTy) {
- FTy = dyn_cast<FunctionType>(OpTy->getElementType());
- if (!FTy)
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
return error("Callee is not of pointer to function type");
- } else if (OpTy->getElementType() != FTy)
+ FTy = cast<FunctionType>(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<Value*, 16> Args;
+ SmallVector<Type*, 16> ArgsFullTys;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
if (FTy->getParamType(i)->isLabelTy())
@@ -4592,6 +5015,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");
}
@@ -4603,13 +5027,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<CallInst>(I)->setCallingConv(
@@ -4623,6 +5050,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
+ propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
if (FMF.any()) {
if (!isa<FPMathOperator>(I))
return error("Fast-math-flags specified for call without "
@@ -4636,7 +5064,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);
@@ -4686,8 +5115,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<StructType>(FullTy) &&
+ !isa<ArrayType>(FullTy) &&
+ (!isa<VectorType>(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:
@@ -4769,8 +5213,8 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
return Err;
// Move the bit stream to the saved position of the deferred function body.
- Stream.JumpToBit(DFII->second);
-
+ if (Error JumpFailed = Stream.JumpToBit(DFII->second))
+ return JumpFailed;
if (Error Err = parseFunctionBody(F))
return Err;
F->setIsMaterializable(false);
@@ -4933,10 +5377,13 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
return Error::success();
assert(Offset > 0 && "Expected non-zero VST offset");
- uint64_t CurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ Expected<uint64_t> MaybeCurrentBit = jumpToValueSymbolTable(Offset, Stream);
+ if (!MaybeCurrentBit)
+ return MaybeCurrentBit.takeError();
+ uint64_t CurrentBit = MaybeCurrentBit.get();
- if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
@@ -4944,7 +5391,10 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
SmallString<128> ValueName;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -4952,7 +5402,8 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
return error("Malformed block");
case BitstreamEntry::EndBlock:
// Done parsing VST, jump back to wherever we came from.
- Stream.JumpToBit(CurrentBit);
+ if (Error JumpFailed = Stream.JumpToBit(CurrentBit))
+ return JumpFailed;
return Error::success();
case BitstreamEntry::Record:
// The interesting case.
@@ -4961,7 +5412,10 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
// Read a record.
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore (e.g. VST_CODE_BBENTRY records).
break;
case bitc::VST_CODE_ENTRY: { // VST_CODE_ENTRY: [valueid, namechar x N]
@@ -5009,8 +5463,8 @@ Error ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
// At the end of this routine the module Index is populated with a map
// from global value id to GlobalValueSummary objects.
Error ModuleSummaryIndexBitcodeReader::parseModule() {
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
DenseMap<unsigned, GlobalValue::LinkageTypes> ValueIdToLinkageMap;
@@ -5018,7 +5472,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
// Read the index for this module.
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -5029,8 +5486,8 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::BLOCKINFO_BLOCK_ID:
// Need to parse these to get abbrev ids (e.g. for VST)
@@ -5043,8 +5500,8 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
assert(((SeenValueSymbolTable && VSTOffset > 0) ||
!SeenGlobalValSummary) &&
"Expected early VST parse via VSTOffset record");
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = Stream.SkipBlock())
+ return Err;
break;
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
@@ -5075,8 +5532,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
case BitstreamEntry::Record: {
Record.clear();
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (MaybeBitCode.get()) {
default:
break; // Default behavior, ignore unknown content.
case bitc::MODULE_CODE_VERSION: {
@@ -5224,32 +5683,66 @@ static void parseTypeIdSummaryRecord(ArrayRef<uint64_t> Record,
parseWholeProgramDevirtResolution(Record, Strtab, Slot, TypeId);
}
-static void setImmutableRefs(std::vector<ValueInfo> &Refs, unsigned Count) {
- // Read-only refs are in the end of the refs list.
- for (unsigned RefNo = Refs.size() - Count; RefNo < Refs.size(); ++RefNo)
+void ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableInfo(
+ ArrayRef<uint64_t> Record, size_t &Slot,
+ TypeIdCompatibleVtableInfo &TypeId) {
+ uint64_t Offset = Record[Slot++];
+ ValueInfo Callee = getValueInfoFromValueId(Record[Slot++]).first;
+ TypeId.push_back({Offset, Callee});
+}
+
+void ModuleSummaryIndexBitcodeReader::parseTypeIdCompatibleVtableSummaryRecord(
+ ArrayRef<uint64_t> Record) {
+ size_t Slot = 0;
+ TypeIdCompatibleVtableInfo &TypeId =
+ TheIndex.getOrInsertTypeIdCompatibleVtableSummary(
+ {Strtab.data() + Record[Slot],
+ static_cast<size_t>(Record[Slot + 1])});
+ Slot += 2;
+
+ while (Slot < Record.size())
+ parseTypeIdCompatibleVtableInfo(Record, Slot, TypeId);
+}
+
+static void setSpecialRefs(std::vector<ValueInfo> &Refs, unsigned ROCnt,
+ unsigned WOCnt) {
+ // Readonly and writeonly refs are in the end of the refs list.
+ assert(ROCnt + WOCnt <= Refs.size());
+ unsigned FirstWORef = Refs.size() - WOCnt;
+ unsigned RefNo = FirstWORef - ROCnt;
+ for (; RefNo < FirstWORef; ++RefNo)
Refs[RefNo].setReadOnly();
+ for (; RefNo < Refs.size(); ++RefNo)
+ Refs[RefNo].setWriteOnly();
}
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
- if (Stream.EnterSubBlock(ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Parse version
{
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
+
if (Entry.Kind != BitstreamEntry::Record)
return error("Invalid Summary Block: record for version expected");
- if (Stream.readRecord(Entry.ID, Record) != bitc::FS_VERSION)
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ if (MaybeRecord.get() != bitc::FS_VERSION)
return error("Invalid Summary Block: version expected");
}
const uint64_t Version = Record[0];
const bool IsOldProfileFormat = Version == 1;
- if (Version < 1 || Version > 6)
+ if (Version < 1 || Version > 7)
return error("Invalid summary version " + Twine(Version) +
- ". Version should be in the range [1-6].");
+ ". Version should be in the range [1-7].");
Record.clear();
// Keep around the last seen summary to be used when we see an optional
@@ -5267,7 +5760,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
PendingTypeCheckedLoadConstVCalls;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -5288,8 +5784,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
// in the combined index VST entries). The records also contain
// information used for ThinLTO renaming and importing.
Record.clear();
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (unsigned BitCode = MaybeBitCode.get()) {
default: // Default behavior: ignore.
break;
case bitc::FS_FLAGS: { // [flags]
@@ -5343,15 +5841,19 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
unsigned InstCount = Record[2];
uint64_t RawFunFlags = 0;
unsigned NumRefs = Record[3];
- unsigned NumImmutableRefs = 0;
+ unsigned NumRORefs = 0, NumWORefs = 0;
int RefListStartIndex = 4;
if (Version >= 4) {
RawFunFlags = Record[3];
NumRefs = Record[4];
RefListStartIndex = 5;
if (Version >= 5) {
- NumImmutableRefs = Record[5];
+ NumRORefs = Record[5];
RefListStartIndex = 6;
+ if (Version >= 7) {
+ NumWORefs = Record[6];
+ RefListStartIndex = 7;
+ }
}
}
@@ -5371,7 +5873,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
std::vector<FunctionSummary::EdgeTy> Calls = makeCallList(
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile, HasRelBF);
- setImmutableRefs(Refs, NumImmutableRefs);
+ setSpecialRefs(Refs, NumRORefs, NumWORefs);
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, getDecodedFFlags(RawFunFlags), /*EntryCount=*/0,
std::move(Refs), std::move(Calls), std::move(PendingTypeTests),
@@ -5406,14 +5908,11 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
// ownership.
AS->setModulePath(getThisModule()->first());
- GlobalValue::GUID AliaseeGUID =
- getValueInfoFromValueId(AliaseeID).first.getGUID();
- auto AliaseeInModule =
- TheIndex.findSummaryInModule(AliaseeGUID, ModulePath);
+ auto AliaseeVI = getValueInfoFromValueId(AliaseeID).first;
+ auto AliaseeInModule = TheIndex.findSummaryInModule(AliaseeVI, ModulePath);
if (!AliaseeInModule)
return error("Alias expects aliasee summary to be parsed");
- AS->setAliasee(AliaseeInModule);
- AS->setAliaseeGUID(AliaseeGUID);
+ AS->setAliasee(AliaseeVI, AliaseeInModule);
auto GUID = getValueInfoFromValueId(ValueID);
AS->setOriginalName(GUID.second);
@@ -5425,7 +5924,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
unsigned ValueID = Record[0];
uint64_t RawFlags = Record[1];
unsigned RefArrayStart = 2;
- GlobalVarSummary::GVarFlags GVF;
+ GlobalVarSummary::GVarFlags GVF(/* ReadOnly */ false,
+ /* WriteOnly */ false);
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
if (Version >= 5) {
GVF = getDecodedGVarFlags(Record[2]);
@@ -5441,6 +5941,34 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
break;
}
+ // FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags,
+ // numrefs, numrefs x valueid,
+ // n x (valueid, offset)]
+ case bitc::FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: {
+ unsigned ValueID = Record[0];
+ uint64_t RawFlags = Record[1];
+ GlobalVarSummary::GVarFlags GVF = getDecodedGVarFlags(Record[2]);
+ unsigned NumRefs = Record[3];
+ unsigned RefListStartIndex = 4;
+ unsigned VTableListStartIndex = RefListStartIndex + NumRefs;
+ auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
+ std::vector<ValueInfo> Refs = makeRefList(
+ ArrayRef<uint64_t>(Record).slice(RefListStartIndex, NumRefs));
+ VTableFuncList VTableFuncs;
+ for (unsigned I = VTableListStartIndex, E = Record.size(); I != E; ++I) {
+ ValueInfo Callee = getValueInfoFromValueId(Record[I]).first;
+ uint64_t Offset = Record[++I];
+ VTableFuncs.push_back({Callee, Offset});
+ }
+ auto VS =
+ llvm::make_unique<GlobalVarSummary>(Flags, GVF, std::move(Refs));
+ VS->setModulePath(getThisModule()->first());
+ VS->setVTableFuncs(VTableFuncs);
+ auto GUID = getValueInfoFromValueId(ValueID);
+ VS->setOriginalName(GUID.second);
+ TheIndex.addGlobalValueSummary(GUID.first, std::move(VS));
+ break;
+ }
// FS_COMBINED: [valueid, modid, flags, instcount, fflags, numrefs,
// numrefs x valueid, n x (valueid)]
// FS_COMBINED_PROFILE: [valueid, modid, flags, instcount, fflags, numrefs,
@@ -5454,7 +5982,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
uint64_t RawFunFlags = 0;
uint64_t EntryCount = 0;
unsigned NumRefs = Record[4];
- unsigned NumImmutableRefs = 0;
+ unsigned NumRORefs = 0, NumWORefs = 0;
int RefListStartIndex = 5;
if (Version >= 4) {
@@ -5462,13 +5990,19 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
RefListStartIndex = 6;
size_t NumRefsIndex = 5;
if (Version >= 5) {
+ unsigned NumRORefsOffset = 1;
RefListStartIndex = 7;
if (Version >= 6) {
NumRefsIndex = 6;
EntryCount = Record[5];
RefListStartIndex = 8;
+ if (Version >= 7) {
+ RefListStartIndex = 9;
+ NumWORefs = Record[8];
+ NumRORefsOffset = 2;
+ }
}
- NumImmutableRefs = Record[RefListStartIndex - 1];
+ NumRORefs = Record[RefListStartIndex - NumRORefsOffset];
}
NumRefs = Record[NumRefsIndex];
}
@@ -5484,7 +6018,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
ArrayRef<uint64_t>(Record).slice(CallGraphEdgeStartIndex),
IsOldProfileFormat, HasProfile, false);
ValueInfo VI = getValueInfoFromValueId(ValueID).first;
- setImmutableRefs(Refs, NumImmutableRefs);
+ setSpecialRefs(Refs, NumRORefs, NumWORefs);
auto FS = llvm::make_unique<FunctionSummary>(
Flags, InstCount, getDecodedFFlags(RawFunFlags), EntryCount,
std::move(Refs), std::move(Edges), std::move(PendingTypeTests),
@@ -5516,12 +6050,9 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
LastSeenSummary = AS.get();
AS->setModulePath(ModuleIdMap[ModuleId]);
- auto AliaseeGUID =
- getValueInfoFromValueId(AliaseeValueId).first.getGUID();
- auto AliaseeInModule =
- TheIndex.findSummaryInModule(AliaseeGUID, AS->modulePath());
- AS->setAliasee(AliaseeInModule);
- AS->setAliaseeGUID(AliaseeGUID);
+ auto AliaseeVI = getValueInfoFromValueId(AliaseeValueId).first;
+ auto AliaseeInModule = TheIndex.findSummaryInModule(AliaseeVI, AS->modulePath());
+ AS->setAliasee(AliaseeVI, AliaseeInModule);
ValueInfo VI = getValueInfoFromValueId(ValueID).first;
LastSeenGUID = VI.getGUID();
@@ -5534,7 +6065,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
uint64_t ModuleId = Record[1];
uint64_t RawFlags = Record[2];
unsigned RefArrayStart = 3;
- GlobalVarSummary::GVarFlags GVF;
+ GlobalVarSummary::GVarFlags GVF(/* ReadOnly */ false,
+ /* WriteOnly */ false);
auto Flags = getDecodedGVSummaryFlags(RawFlags, Version);
if (Version >= 5) {
GVF = getDecodedGVarFlags(Record[3]);
@@ -5610,6 +6142,10 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
case bitc::FS_TYPE_ID:
parseTypeIdSummaryRecord(Record, Strtab, TheIndex);
break;
+
+ case bitc::FS_TYPE_ID_METADATA:
+ parseTypeIdCompatibleVtableSummaryRecord(Record);
+ break;
}
}
llvm_unreachable("Exit infinite loop");
@@ -5618,8 +6154,8 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
// Parse the module string table block into the Index.
// This populates the ModulePathStringTable map in the index.
Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
- if (Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
@@ -5627,7 +6163,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
ModuleSummaryIndex::ModuleInfo *LastSeenModule = nullptr;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -5641,7 +6180,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
}
Record.clear();
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::MST_CODE_ENTRY: {
@@ -5707,12 +6249,16 @@ const std::error_category &llvm::BitcodeErrorCategory() {
static Expected<StringRef> readBlobInRecord(BitstreamCursor &Stream,
unsigned Block, unsigned RecordID) {
- if (Stream.EnterSubBlock(Block))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(Block))
+ return std::move(Err);
StringRef Strtab;
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
return Strtab;
@@ -5721,14 +6267,18 @@ static Expected<StringRef> readBlobInRecord(BitstreamCursor &Stream,
return error("Malformed block");
case BitstreamEntry::SubBlock:
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
break;
case BitstreamEntry::Record:
StringRef Blob;
SmallVector<uint64_t, 1> Record;
- if (Stream.readRecord(Entry.ID, Record, &Blob) == RecordID)
+ Expected<unsigned> MaybeRecord =
+ Stream.readRecord(Entry.ID, Record, &Blob);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ if (MaybeRecord.get() == RecordID)
Strtab = Blob;
break;
}
@@ -5764,7 +6314,11 @@ llvm::getBitcodeFileContents(MemoryBufferRef Buffer) {
if (BCBegin + 8 >= Stream.getBitcodeBytes().size())
return F;
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::EndBlock:
case BitstreamEntry::Error:
@@ -5774,10 +6328,16 @@ llvm::getBitcodeFileContents(MemoryBufferRef Buffer) {
uint64_t IdentificationBit = -1ull;
if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) {
IdentificationBit = Stream.GetCurrentBitNo() - BCBegin * 8;
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
+
+ {
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ Entry = MaybeEntry.get();
+ }
- Entry = Stream.advance();
if (Entry.Kind != BitstreamEntry::SubBlock ||
Entry.ID != bitc::MODULE_BLOCK_ID)
return error("Malformed block");
@@ -5785,8 +6345,8 @@ llvm::getBitcodeFileContents(MemoryBufferRef Buffer) {
if (Entry.ID == bitc::MODULE_BLOCK_ID) {
uint64_t ModuleBit = Stream.GetCurrentBitNo() - BCBegin * 8;
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
F.Mods.push_back({Stream.getBitcodeBytes().slice(
BCBegin, Stream.getCurrentByteNo() - BCBegin),
@@ -5834,13 +6394,15 @@ llvm::getBitcodeFileContents(MemoryBufferRef Buffer) {
continue;
}
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
}
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> StreamFailed = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return StreamFailed.takeError();
}
}
}
@@ -5860,7 +6422,8 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll,
std::string ProducerIdentification;
if (IdentificationBit != -1ull) {
- Stream.JumpToBit(IdentificationBit);
+ if (Error JumpFailed = Stream.JumpToBit(IdentificationBit))
+ return std::move(JumpFailed);
Expected<std::string> ProducerIdentificationOrErr =
readIdentificationBlock(Stream);
if (!ProducerIdentificationOrErr)
@@ -5869,7 +6432,8 @@ BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll,
ProducerIdentification = *ProducerIdentificationOrErr;
}
- Stream.JumpToBit(ModuleBit);
+ if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
+ return std::move(JumpFailed);
auto *R = new BitcodeReader(std::move(Stream), Strtab, ProducerIdentification,
Context);
@@ -5907,7 +6471,8 @@ BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata,
Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
StringRef ModulePath, uint64_t ModuleId) {
BitstreamCursor Stream(Buffer);
- Stream.JumpToBit(ModuleBit);
+ if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
+ return JumpFailed;
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex,
ModulePath, ModuleId);
@@ -5917,7 +6482,8 @@ Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
// Parse the specified bitcode buffer, returning the function info index.
Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
BitstreamCursor Stream(Buffer);
- Stream.JumpToBit(ModuleBit);
+ if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
+ return std::move(JumpFailed);
auto Index = llvm::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, *Index,
@@ -5931,12 +6497,15 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
unsigned ID) {
- if (Stream.EnterSubBlock(ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(ID))
+ return std::move(Err);
SmallVector<uint64_t, 64> Record;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -5953,8 +6522,10 @@ static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
// Look for the FS_FLAGS record.
Record.clear();
- auto BitCode = Stream.readRecord(Entry.ID, Record);
- switch (BitCode) {
+ Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeBitCode)
+ return MaybeBitCode.takeError();
+ switch (MaybeBitCode.get()) {
default: // Default behavior: ignore.
break;
case bitc::FS_FLAGS: { // [flags]
@@ -5972,13 +6543,17 @@ static Expected<bool> getEnableSplitLTOUnitFlag(BitstreamCursor &Stream,
// Check if the given bitcode buffer contains a global value summary block.
Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
BitstreamCursor Stream(Buffer);
- Stream.JumpToBit(ModuleBit);
+ if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
+ return std::move(JumpFailed);
- if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
+ return std::move(Err);
while (true) {
- BitstreamEntry Entry = Stream.advance();
+ Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
@@ -6007,13 +6582,15 @@ Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
}
// Ignore other sub-blocks.
- if (Stream.SkipBlock())
- return error("Malformed block");
+ if (Error Err = Stream.SkipBlock())
+ return std::move(Err);
continue;
case BitstreamEntry::Record:
- Stream.skipRecord(Entry.ID);
- continue;
+ if (Expected<unsigned> StreamFailed = Stream.skipRecord(Entry.ID))
+ continue;
+ else
+ return StreamFailed.takeError();
}
}
}
diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp
deleted file mode 100644
index 771cf3d927bc..000000000000
--- a/lib/Bitcode/Reader/BitstreamReader.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-//===- BitstreamReader.cpp - BitstreamReader implementation ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Bitcode/BitstreamReader.h"
-#include "llvm/ADT/StringRef.h"
-#include <cassert>
-#include <string>
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// BitstreamCursor implementation
-//===----------------------------------------------------------------------===//
-
-/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
-/// the block, and return true if the block has an error.
-bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
- // Save the current block's state on BlockScope.
- BlockScope.push_back(Block(CurCodeSize));
- BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
-
- // Add the abbrevs specific to this block to the CurAbbrevs list.
- if (BlockInfo) {
- if (const BitstreamBlockInfo::BlockInfo *Info =
- BlockInfo->getBlockInfo(BlockID)) {
- CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
- Info->Abbrevs.end());
- }
- }
-
- // Get the codesize of this block.
- CurCodeSize = ReadVBR(bitc::CodeLenWidth);
- // We can't read more than MaxChunkSize at a time
- if (CurCodeSize > MaxChunkSize)
- return true;
-
- SkipToFourByteBoundary();
- unsigned NumWords = Read(bitc::BlockSizeWidth);
- if (NumWordsP) *NumWordsP = NumWords;
-
- // Validate that this block is sane.
- return CurCodeSize == 0 || AtEndOfStream();
-}
-
-static uint64_t readAbbreviatedField(BitstreamCursor &Cursor,
- const BitCodeAbbrevOp &Op) {
- assert(!Op.isLiteral() && "Not to be used with literals!");
-
- // Decode the value as we are commanded.
- switch (Op.getEncoding()) {
- case BitCodeAbbrevOp::Array:
- case BitCodeAbbrevOp::Blob:
- llvm_unreachable("Should not reach here");
- case BitCodeAbbrevOp::Fixed:
- assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- return Cursor.Read((unsigned)Op.getEncodingData());
- case BitCodeAbbrevOp::VBR:
- assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- return Cursor.ReadVBR64((unsigned)Op.getEncodingData());
- case BitCodeAbbrevOp::Char6:
- return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6));
- }
- llvm_unreachable("invalid abbreviation encoding");
-}
-
-static void skipAbbreviatedField(BitstreamCursor &Cursor,
- const BitCodeAbbrevOp &Op) {
- assert(!Op.isLiteral() && "Not to be used with literals!");
-
- // Decode the value as we are commanded.
- switch (Op.getEncoding()) {
- case BitCodeAbbrevOp::Array:
- case BitCodeAbbrevOp::Blob:
- llvm_unreachable("Should not reach here");
- case BitCodeAbbrevOp::Fixed:
- assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- Cursor.Read((unsigned)Op.getEncodingData());
- break;
- case BitCodeAbbrevOp::VBR:
- assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize);
- Cursor.ReadVBR64((unsigned)Op.getEncodingData());
- break;
- case BitCodeAbbrevOp::Char6:
- Cursor.Read(6);
- break;
- }
-}
-
-/// skipRecord - Read the current record and discard it.
-unsigned BitstreamCursor::skipRecord(unsigned AbbrevID) {
- // Skip unabbreviated records by reading past their entries.
- if (AbbrevID == bitc::UNABBREV_RECORD) {
- unsigned Code = ReadVBR(6);
- unsigned NumElts = ReadVBR(6);
- for (unsigned i = 0; i != NumElts; ++i)
- (void)ReadVBR64(6);
- return Code;
- }
-
- const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
- const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);
- unsigned Code;
- if (CodeOp.isLiteral())
- Code = CodeOp.getLiteralValue();
- else {
- if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
- CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
- report_fatal_error("Abbreviation starts with an Array or a Blob");
- Code = readAbbreviatedField(*this, CodeOp);
- }
-
- for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i < e; ++i) {
- const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
- if (Op.isLiteral())
- continue;
-
- if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
- Op.getEncoding() != BitCodeAbbrevOp::Blob) {
- skipAbbreviatedField(*this, Op);
- continue;
- }
-
- if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
- // Array case. Read the number of elements as a vbr6.
- unsigned NumElts = ReadVBR(6);
-
- // Get the element encoding.
- assert(i+2 == e && "array op not second to last?");
- const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
-
- // Read all the elements.
- // Decode the value as we are commanded.
- switch (EltEnc.getEncoding()) {
- default:
- report_fatal_error("Array element type can't be an Array or a Blob");
- case BitCodeAbbrevOp::Fixed:
- assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
- JumpToBit(GetCurrentBitNo() + NumElts * EltEnc.getEncodingData());
- break;
- case BitCodeAbbrevOp::VBR:
- assert((unsigned)EltEnc.getEncodingData() <= MaxChunkSize);
- for (; NumElts; --NumElts)
- ReadVBR64((unsigned)EltEnc.getEncodingData());
- break;
- case BitCodeAbbrevOp::Char6:
- JumpToBit(GetCurrentBitNo() + NumElts * 6);
- break;
- }
- continue;
- }
-
- assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
- // Blob case. Read the number of bytes as a vbr6.
- unsigned NumElts = ReadVBR(6);
- SkipToFourByteBoundary(); // 32-bit alignment
-
- // Figure out where the end of this blob will be including tail padding.
- size_t NewEnd = GetCurrentBitNo()+((NumElts+3)&~3)*8;
-
- // If this would read off the end of the bitcode file, just set the
- // record to empty and return.
- if (!canSkipToPos(NewEnd/8)) {
- skipToEnd();
- break;
- }
-
- // Skip over the blob.
- JumpToBit(NewEnd);
- }
- return Code;
-}
-
-unsigned BitstreamCursor::readRecord(unsigned AbbrevID,
- SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob) {
- if (AbbrevID == bitc::UNABBREV_RECORD) {
- unsigned Code = ReadVBR(6);
- unsigned NumElts = ReadVBR(6);
- for (unsigned i = 0; i != NumElts; ++i)
- Vals.push_back(ReadVBR64(6));
- return Code;
- }
-
- const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
-
- // Read the record code first.
- assert(Abbv->getNumOperandInfos() != 0 && "no record code in abbreviation?");
- const BitCodeAbbrevOp &CodeOp = Abbv->getOperandInfo(0);
- unsigned Code;
- if (CodeOp.isLiteral())
- Code = CodeOp.getLiteralValue();
- else {
- if (CodeOp.getEncoding() == BitCodeAbbrevOp::Array ||
- CodeOp.getEncoding() == BitCodeAbbrevOp::Blob)
- report_fatal_error("Abbreviation starts with an Array or a Blob");
- Code = readAbbreviatedField(*this, CodeOp);
- }
-
- for (unsigned i = 1, e = Abbv->getNumOperandInfos(); i != e; ++i) {
- const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
- if (Op.isLiteral()) {
- Vals.push_back(Op.getLiteralValue());
- continue;
- }
-
- if (Op.getEncoding() != BitCodeAbbrevOp::Array &&
- Op.getEncoding() != BitCodeAbbrevOp::Blob) {
- Vals.push_back(readAbbreviatedField(*this, Op));
- continue;
- }
-
- if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
- // Array case. Read the number of elements as a vbr6.
- unsigned NumElts = ReadVBR(6);
-
- // Get the element encoding.
- if (i + 2 != e)
- report_fatal_error("Array op not second to last");
- const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
- if (!EltEnc.isEncoding())
- report_fatal_error(
- "Array element type has to be an encoding of a type");
-
- // Read all the elements.
- switch (EltEnc.getEncoding()) {
- default:
- report_fatal_error("Array element type can't be an Array or a Blob");
- case BitCodeAbbrevOp::Fixed:
- for (; NumElts; --NumElts)
- Vals.push_back(Read((unsigned)EltEnc.getEncodingData()));
- break;
- case BitCodeAbbrevOp::VBR:
- for (; NumElts; --NumElts)
- Vals.push_back(ReadVBR64((unsigned)EltEnc.getEncodingData()));
- break;
- case BitCodeAbbrevOp::Char6:
- for (; NumElts; --NumElts)
- Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6)));
- }
- continue;
- }
-
- assert(Op.getEncoding() == BitCodeAbbrevOp::Blob);
- // Blob case. Read the number of bytes as a vbr6.
- unsigned NumElts = ReadVBR(6);
- SkipToFourByteBoundary(); // 32-bit alignment
-
- // Figure out where the end of this blob will be including tail padding.
- size_t CurBitPos = GetCurrentBitNo();
- size_t NewEnd = CurBitPos+((NumElts+3)&~3)*8;
-
- // If this would read off the end of the bitcode file, just set the
- // record to empty and return.
- if (!canSkipToPos(NewEnd/8)) {
- Vals.append(NumElts, 0);
- skipToEnd();
- break;
- }
-
- // Otherwise, inform the streamer that we need these bytes in memory. Skip
- // over tail padding first, in case jumping to NewEnd invalidates the Blob
- // pointer.
- JumpToBit(NewEnd);
- const char *Ptr = (const char *)getPointerToBit(CurBitPos, NumElts);
-
- // If we can return a reference to the data, do so to avoid copying it.
- if (Blob) {
- *Blob = StringRef(Ptr, NumElts);
- } else {
- // Otherwise, unpack into Vals with zero extension.
- for (; NumElts; --NumElts)
- Vals.push_back((unsigned char)*Ptr++);
- }
- }
-
- return Code;
-}
-
-void BitstreamCursor::ReadAbbrevRecord() {
- auto Abbv = std::make_shared<BitCodeAbbrev>();
- unsigned NumOpInfo = ReadVBR(5);
- for (unsigned i = 0; i != NumOpInfo; ++i) {
- bool IsLiteral = Read(1);
- if (IsLiteral) {
- Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8)));
- continue;
- }
-
- BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3);
- if (BitCodeAbbrevOp::hasEncodingData(E)) {
- uint64_t Data = ReadVBR64(5);
-
- // As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
- // and vbr(0) as a literal zero. This is decoded the same way, and avoids
- // a slow path in Read() to have to handle reading zero bits.
- if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&
- Data == 0) {
- Abbv->Add(BitCodeAbbrevOp(0));
- continue;
- }
-
- if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) &&
- Data > MaxChunkSize)
- report_fatal_error(
- "Fixed or VBR abbrev record with size > MaxChunkData");
-
- Abbv->Add(BitCodeAbbrevOp(E, Data));
- } else
- Abbv->Add(BitCodeAbbrevOp(E));
- }
-
- if (Abbv->getNumOperandInfos() == 0)
- report_fatal_error("Abbrev record with no operands");
- CurAbbrevs.push_back(std::move(Abbv));
-}
-
-Optional<BitstreamBlockInfo>
-BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
- if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None;
-
- BitstreamBlockInfo NewBlockInfo;
-
- SmallVector<uint64_t, 64> Record;
- BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;
-
- // Read all the records for this module.
- while (true) {
- BitstreamEntry Entry = advanceSkippingSubblocks(AF_DontAutoprocessAbbrevs);
-
- switch (Entry.Kind) {
- case llvm::BitstreamEntry::SubBlock: // Handled for us already.
- case llvm::BitstreamEntry::Error:
- return None;
- case llvm::BitstreamEntry::EndBlock:
- return std::move(NewBlockInfo);
- case llvm::BitstreamEntry::Record:
- // The interesting case.
- break;
- }
-
- // Read abbrev records, associate them with CurBID.
- if (Entry.ID == bitc::DEFINE_ABBREV) {
- if (!CurBlockInfo) return None;
- ReadAbbrevRecord();
-
- // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the
- // appropriate BlockInfo.
- CurBlockInfo->Abbrevs.push_back(std::move(CurAbbrevs.back()));
- CurAbbrevs.pop_back();
- continue;
- }
-
- // Read a record.
- Record.clear();
- switch (readRecord(Entry.ID, Record)) {
- default: break; // Default behavior, ignore unknown content.
- case bitc::BLOCKINFO_CODE_SETBID:
- if (Record.size() < 1) return None;
- CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
- break;
- case bitc::BLOCKINFO_CODE_BLOCKNAME: {
- if (!CurBlockInfo) return None;
- if (!ReadBlockInfoNames)
- break; // Ignore name.
- std::string Name;
- for (unsigned i = 0, e = Record.size(); i != e; ++i)
- Name += (char)Record[i];
- CurBlockInfo->Name = Name;
- break;
- }
- case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
- if (!CurBlockInfo) return None;
- if (!ReadBlockInfoNames)
- break; // Ignore name.
- std::string Name;
- for (unsigned i = 1, e = Record.size(); i != e; ++i)
- Name += (char)Record[i];
- CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0],
- Name));
- break;
- }
- }
- }
-}
diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp
index 3289aa0acddd..108f71189585 100644
--- a/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1,9 +1,8 @@
//===- MetadataLoader.cpp - Internal BitcodeReader implementation ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -23,7 +22,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
@@ -104,7 +103,7 @@ static cl::opt<bool> DisableLazyLoading(
namespace {
-static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; }
+static int64_t unrotateSign(uint64_t U) { return (U & 1) ? ~(U >> 1) : U >> 1; }
class BitcodeReaderMetadataList {
/// Array of metadata references.
@@ -131,8 +130,15 @@ class BitcodeReaderMetadataList {
LLVMContext &Context;
+ /// Maximum number of valid references. Forward references exceeding the
+ /// maximum must be invalid.
+ unsigned RefsUpperBound;
+
public:
- BitcodeReaderMetadataList(LLVMContext &C) : Context(C) {}
+ BitcodeReaderMetadataList(LLVMContext &C, size_t RefsUpperBound)
+ : Context(C),
+ RefsUpperBound(std::min((size_t)std::numeric_limits<unsigned>::max(),
+ RefsUpperBound)) {}
// vector compatibility methods
unsigned size() const { return MetadataPtrs.size(); }
@@ -219,6 +225,10 @@ void BitcodeReaderMetadataList::assignValue(Metadata *MD, unsigned Idx) {
}
Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) {
+ // Bail out for a clearly invalid value.
+ if (Idx >= RefsUpperBound)
+ return nullptr;
+
if (Idx >= size())
resize(Idx + 1);
@@ -338,7 +348,7 @@ Metadata *BitcodeReaderMetadataList::resolveTypeRefArray(Metadata *MaybeTuple) {
if (!Tuple || Tuple->isDistinct())
return MaybeTuple;
- // Look through the DITypeRefArray, upgrading each DITypeRef.
+ // Look through the DITypeRefArray, upgrading each DIType *.
SmallVector<Metadata *, 32> Ops;
Ops.reserve(Tuple->getNumOperands());
for (Metadata *MD : Tuple->operands())
@@ -626,9 +636,10 @@ public:
BitcodeReaderValueList &ValueList,
std::function<Type *(unsigned)> getTypeByID,
bool IsImporting)
- : MetadataList(TheModule.getContext()), ValueList(ValueList),
- Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule),
- getTypeByID(std::move(getTypeByID)), IsImporting(IsImporting) {}
+ : MetadataList(TheModule.getContext(), Stream.SizeInBytes()),
+ ValueList(ValueList), Stream(Stream), Context(TheModule.getContext()),
+ TheModule(TheModule), getTypeByID(std::move(getTypeByID)),
+ IsImporting(IsImporting) {}
Error parseMetadata(bool ModuleLevel);
@@ -675,8 +686,12 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
SmallVector<uint64_t, 64> Record;
// Get the abbrevs, and preload record positions to make them lazy-loadable.
while (true) {
- BitstreamEntry Entry = IndexCursor.advanceSkippingSubblocks(
+ Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks(
BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
+
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
case BitstreamEntry::Error:
@@ -688,14 +703,22 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
// The interesting case.
++NumMDRecordLoaded;
uint64_t CurrentPos = IndexCursor.GetCurrentBitNo();
- auto Code = IndexCursor.skipRecord(Entry.ID);
+ Expected<unsigned> MaybeCode = IndexCursor.skipRecord(Entry.ID);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ unsigned Code = MaybeCode.get();
switch (Code) {
case bitc::METADATA_STRINGS: {
// Rewind and parse the strings.
- IndexCursor.JumpToBit(CurrentPos);
+ if (Error Err = IndexCursor.JumpToBit(CurrentPos))
+ return std::move(Err);
StringRef Blob;
Record.clear();
- IndexCursor.readRecord(Entry.ID, Record, &Blob);
+ if (Expected<unsigned> MaybeRecord =
+ IndexCursor.readRecord(Entry.ID, Record, &Blob))
+ ;
+ else
+ return MaybeRecord.takeError();
unsigned NumStrings = Record[0];
MDStringRef.reserve(NumStrings);
auto IndexNextMDString = [&](StringRef Str) {
@@ -708,26 +731,37 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
case bitc::METADATA_INDEX_OFFSET: {
// This is the offset to the index, when we see this we skip all the
// records and load only an index to these.
- IndexCursor.JumpToBit(CurrentPos);
+ if (Error Err = IndexCursor.JumpToBit(CurrentPos))
+ return std::move(Err);
Record.clear();
- IndexCursor.readRecord(Entry.ID, Record);
+ if (Expected<unsigned> MaybeRecord =
+ IndexCursor.readRecord(Entry.ID, Record))
+ ;
+ else
+ return MaybeRecord.takeError();
if (Record.size() != 2)
return error("Invalid record");
auto Offset = Record[0] + (Record[1] << 32);
auto BeginPos = IndexCursor.GetCurrentBitNo();
- IndexCursor.JumpToBit(BeginPos + Offset);
- Entry = IndexCursor.advanceSkippingSubblocks(
- BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (Error Err = IndexCursor.JumpToBit(BeginPos + Offset))
+ return std::move(Err);
+ Expected<BitstreamEntry> MaybeEntry =
+ IndexCursor.advanceSkippingSubblocks(
+ BitstreamCursor::AF_DontPopBlockAtEnd);
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ Entry = MaybeEntry.get();
assert(Entry.Kind == BitstreamEntry::Record &&
"Corrupted bitcode: Expected `Record` when trying to find the "
"Metadata index");
Record.clear();
- auto Code = IndexCursor.readRecord(Entry.ID, Record);
- (void)Code;
- assert(Code == bitc::METADATA_INDEX && "Corrupted bitcode: Expected "
- "`METADATA_INDEX` when trying "
- "to find the Metadata index");
-
+ if (Expected<unsigned> MaybeCode =
+ IndexCursor.readRecord(Entry.ID, Record))
+ assert(MaybeCode.get() == bitc::METADATA_INDEX &&
+ "Corrupted bitcode: Expected `METADATA_INDEX` when trying to "
+ "find the Metadata index");
+ else
+ return MaybeCode.takeError();
// Delta unpack
auto CurrentValue = BeginPos;
GlobalMetadataBitPosIndex.reserve(Record.size());
@@ -743,21 +777,33 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
return error("Corrupted Metadata block");
case bitc::METADATA_NAME: {
// Named metadata need to be materialized now and aren't deferred.
- IndexCursor.JumpToBit(CurrentPos);
+ if (Error Err = IndexCursor.JumpToBit(CurrentPos))
+ return std::move(Err);
Record.clear();
- unsigned Code = IndexCursor.readRecord(Entry.ID, Record);
- assert(Code == bitc::METADATA_NAME);
+
+ unsigned Code;
+ if (Expected<unsigned> MaybeCode =
+ IndexCursor.readRecord(Entry.ID, Record)) {
+ Code = MaybeCode.get();
+ assert(Code == bitc::METADATA_NAME);
+ } else
+ return MaybeCode.takeError();
// Read name of the named metadata.
SmallString<8> Name(Record.begin(), Record.end());
- Code = IndexCursor.ReadCode();
+ if (Expected<unsigned> MaybeCode = IndexCursor.ReadCode())
+ Code = MaybeCode.get();
+ else
+ return MaybeCode.takeError();
// Named Metadata comes in two parts, we expect the name to be followed
// by the node
Record.clear();
- unsigned NextBitCode = IndexCursor.readRecord(Code, Record);
- assert(NextBitCode == bitc::METADATA_NAMED_NODE);
- (void)NextBitCode;
+ if (Expected<unsigned> MaybeNextBitCode =
+ IndexCursor.readRecord(Code, Record))
+ assert(MaybeNextBitCode.get() == bitc::METADATA_NAMED_NODE);
+ else
+ return MaybeNextBitCode.takeError();
// Read named metadata elements.
unsigned Size = Record.size();
@@ -776,9 +822,14 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
// FIXME: we need to do this early because we don't materialize global
// value explicitly.
- IndexCursor.JumpToBit(CurrentPos);
+ if (Error Err = IndexCursor.JumpToBit(CurrentPos))
+ return std::move(Err);
Record.clear();
- IndexCursor.readRecord(Entry.ID, Record);
+ if (Expected<unsigned> MaybeRecord =
+ IndexCursor.readRecord(Entry.ID, Record))
+ ;
+ else
+ return MaybeRecord.takeError();
if (Record.size() % 2 == 0)
return error("Invalid record");
unsigned ValueID = Record[0];
@@ -812,6 +863,7 @@ MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
case bitc::METADATA_LEXICAL_BLOCK:
case bitc::METADATA_LEXICAL_BLOCK_FILE:
case bitc::METADATA_NAMESPACE:
+ case bitc::METADATA_COMMON_BLOCK:
case bitc::METADATA_MACRO:
case bitc::METADATA_MACRO_FILE:
case bitc::METADATA_TEMPLATE_TYPE:
@@ -845,8 +897,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
// skip the whole block in case we lazy-load.
auto EntryPos = Stream.GetCurrentBitNo();
- if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
PlaceholderQueue Placeholders;
@@ -871,9 +923,14 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
// Return at the beginning of the block, since it is easy to skip it
// entirely from there.
Stream.ReadBlockEnd(); // Pop the abbrev block context.
- Stream.JumpToBit(EntryPos);
- if (Stream.SkipBlock())
- return error("Invalid record");
+ if (Error Err = IndexCursor.JumpToBit(EntryPos))
+ return Err;
+ if (Error Err = Stream.SkipBlock()) {
+ // FIXME this drops the error on the floor, which
+ // ThinLTO/X86/debuginfo-cu-import.ll relies on.
+ consumeError(std::move(Err));
+ return Error::success();
+ }
return Error::success();
}
// Couldn't load an index, fallback to loading all the block "old-style".
@@ -883,7 +940,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -902,10 +962,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
Record.clear();
StringRef Blob;
++NumMDRecordLoaded;
- unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
- if (Error Err =
- parseOneMetadata(Record, Code, Placeholders, Blob, NextMetadataNo))
- return Err;
+ if (Expected<unsigned> MaybeCode =
+ Stream.readRecord(Entry.ID, Record, &Blob)) {
+ if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders,
+ Blob, NextMetadataNo))
+ return Err;
+ } else
+ return MaybeCode.takeError();
}
}
@@ -930,12 +993,25 @@ void MetadataLoader::MetadataLoaderImpl::lazyLoadOneMetadata(
}
SmallVector<uint64_t, 64> Record;
StringRef Blob;
- IndexCursor.JumpToBit(GlobalMetadataBitPosIndex[ID - MDStringRef.size()]);
- auto Entry = IndexCursor.advanceSkippingSubblocks();
+ if (Error Err = IndexCursor.JumpToBit(
+ GlobalMetadataBitPosIndex[ID - MDStringRef.size()]))
+ report_fatal_error("lazyLoadOneMetadata failed jumping: " +
+ toString(std::move(Err)));
+ Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ // FIXME this drops the error on the floor.
+ report_fatal_error("lazyLoadOneMetadata failed advanceSkippingSubblocks: " +
+ toString(MaybeEntry.takeError()));
+ BitstreamEntry Entry = MaybeEntry.get();
++NumMDRecordLoaded;
- unsigned Code = IndexCursor.readRecord(Entry.ID, Record, &Blob);
- if (Error Err = parseOneMetadata(Record, Code, Placeholders, Blob, ID))
- report_fatal_error("Can't lazyload MD");
+ if (Expected<unsigned> MaybeCode =
+ IndexCursor.readRecord(Entry.ID, Record, &Blob)) {
+ if (Error Err =
+ parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, ID))
+ report_fatal_error("Can't lazyload MD, parseOneMetadata: " +
+ toString(std::move(Err)));
+ } else
+ report_fatal_error("Can't lazyload MD: " + toString(MaybeCode.takeError()));
}
/// Ensure that all forward-references and placeholders are resolved.
@@ -1032,12 +1108,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
// Read name of the named metadata.
SmallString<8> Name(Record.begin(), Record.end());
Record.clear();
- Code = Stream.ReadCode();
+ Expected<unsigned> MaybeCode = Stream.ReadCode();
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ Code = MaybeCode.get();
++NumMDRecordLoaded;
- unsigned NextBitCode = Stream.readRecord(Code, Record);
- if (NextBitCode != bitc::METADATA_NAMED_NODE)
- return error("METADATA_NAME not followed by METADATA_NAMED_NODE");
+ if (Expected<unsigned> MaybeNextBitCode = Stream.readRecord(Code, Record)) {
+ if (MaybeNextBitCode.get() != bitc::METADATA_NAMED_NODE)
+ return error("METADATA_NAME not followed by METADATA_NAMED_NODE");
+ } else
+ return MaybeNextBitCode.takeError();
// Read named metadata elements.
unsigned Size = Record.size();
@@ -1407,12 +1488,33 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
return error("Invalid record");
bool HasSPFlags = Record[0] & 4;
- DISubprogram::DISPFlags SPFlags =
- HasSPFlags
- ? static_cast<DISubprogram::DISPFlags>(Record[9])
- : DISubprogram::toSPFlags(
- /*IsLocalToUnit=*/Record[7], /*IsDefinition=*/Record[8],
- /*IsOptimized=*/Record[14], /*Virtuality=*/Record[11]);
+
+ DINode::DIFlags Flags;
+ DISubprogram::DISPFlags SPFlags;
+ if (!HasSPFlags)
+ Flags = static_cast<DINode::DIFlags>(Record[11 + 2]);
+ else {
+ Flags = static_cast<DINode::DIFlags>(Record[11]);
+ SPFlags = static_cast<DISubprogram::DISPFlags>(Record[9]);
+ }
+
+ // Support for old metadata when
+ // subprogram specific flags are placed in DIFlags.
+ const unsigned DIFlagMainSubprogram = 1 << 21;
+ bool HasOldMainSubprogramFlag = Flags & DIFlagMainSubprogram;
+ if (HasOldMainSubprogramFlag)
+ // Remove old DIFlagMainSubprogram from DIFlags.
+ // Note: This assumes that any future use of bit 21 defaults to it
+ // being 0.
+ Flags &= ~static_cast<DINode::DIFlags>(DIFlagMainSubprogram);
+
+ if (HasOldMainSubprogramFlag && HasSPFlags)
+ SPFlags |= DISubprogram::SPFlagMainSubprogram;
+ else if (!HasSPFlags)
+ SPFlags = DISubprogram::toSPFlags(
+ /*IsLocalToUnit=*/Record[7], /*IsDefinition=*/Record[8],
+ /*IsOptimized=*/Record[14], /*Virtuality=*/Record[11],
+ /*DIFlagMainSubprogram*/HasOldMainSubprogramFlag);
// All definitions should be distinct.
IsDistinct = (Record[0] & 1) || (SPFlags & DISubprogram::SPFlagDefinition);
@@ -1456,7 +1558,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
getDITypeRefOrNull(Record[8 + OffsetA]), // containingType
Record[10 + OffsetA], // virtualIndex
HasThisAdj ? Record[16 + OffsetB] : 0, // thisAdjustment
- static_cast<DINode::DIFlags>(Record[11 + OffsetA]),// flags
+ Flags, // flags
SPFlags, // SPFlags
HasUnit ? CUorFn : nullptr, // unit
getMDOrNull(Record[13 + OffsetB]), // templateParams
@@ -1508,6 +1610,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
NextMetadataNo++;
break;
}
+ case bitc::METADATA_COMMON_BLOCK: {
+ IsDistinct = Record[0] & 1;
+ MetadataList.assignValue(
+ GET_OR_DISTINCT(DICommonBlock,
+ (Context, getMDOrNull(Record[1]),
+ getMDOrNull(Record[2]), getMDString(Record[3]),
+ getMDOrNull(Record[4]), Record[5])),
+ NextMetadataNo);
+ NextMetadataNo++;
+ break;
+ }
case bitc::METADATA_NAMESPACE: {
// Newer versions of DINamespace dropped file and line.
MDString *Name;
@@ -1831,7 +1944,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataStrings(
if (R.AtEndOfStream())
return error("Invalid record: metadata strings bad length");
- unsigned Size = R.ReadVBR(6);
+ Expected<uint32_t> MaybeSize = R.ReadVBR(6);
+ if (!MaybeSize)
+ return MaybeSize.takeError();
+ uint32_t Size = MaybeSize.get();
if (Strings.size() < Size)
return error("Invalid record: metadata strings truncated chars");
@@ -1860,14 +1976,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseGlobalObjectAttachment(
/// Parse metadata attachments.
Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
- if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
PlaceholderQueue Placeholders;
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1884,7 +2003,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
// Read a metadata attachment record.
Record.clear();
++NumMDRecordLoaded;
- switch (Stream.readRecord(Entry.ID, Record)) {
+ Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeRecord)
+ return MaybeRecord.takeError();
+ switch (MaybeRecord.get()) {
default: // Default behavior: ignore.
break;
case bitc::METADATA_ATTACHMENT: {
@@ -1958,14 +2080,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataKindRecord(
/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
- if (Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
- return error("Invalid record");
+ if (Error Err = Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
+ return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records.
while (true) {
- BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
+ Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
+ if (!MaybeEntry)
+ return MaybeEntry.takeError();
+ BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
@@ -1981,8 +2106,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
// Read a record.
Record.clear();
++NumMDRecordLoaded;
- unsigned Code = Stream.readRecord(Entry.ID, Record);
- switch (Code) {
+ Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record);
+ if (!MaybeCode)
+ return MaybeCode.takeError();
+ switch (MaybeCode.get()) {
default: // Default behavior: ignore.
break;
case bitc::METADATA_KIND: {
diff --git a/lib/Bitcode/Reader/MetadataLoader.h b/lib/Bitcode/Reader/MetadataLoader.h
index 07a77a086f32..fe2b20273249 100644
--- a/lib/Bitcode/Reader/MetadataLoader.h
+++ b/lib/Bitcode/Reader/MetadataLoader.h
@@ -1,9 +1,8 @@
//===-- Bitcode/Reader/MetadataLoader.h - Load Metadatas -------*- C++ -*-====//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/Bitcode/Reader/ValueList.cpp b/lib/Bitcode/Reader/ValueList.cpp
index b3945a37408f..431995fd40ac 100644
--- a/lib/Bitcode/Reader/ValueList.cpp
+++ b/lib/Bitcode/Reader/ValueList.cpp
@@ -1,9 +1,8 @@
//===- ValueList.cpp - Internal BitcodeReader implementation --------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -66,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;
@@ -95,6 +97,10 @@ void BitcodeReaderValueList::assignValue(Value *V, unsigned Idx) {
}
Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) {
+ // Bail out for a clearly invalid value.
+ if (Idx >= RefsUpperBound)
+ return nullptr;
+
if (Idx >= size())
resize(Idx + 1);
@@ -110,9 +116,10 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, Type *Ty) {
return C;
}
-Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty) {
- // Bail out for a clearly invalid value. This would make us call resize(0)
- if (Idx == std::numeric_limits<unsigned>::max())
+Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty,
+ Type **FullTy) {
+ // Bail out for a clearly invalid value.
+ if (Idx >= RefsUpperBound)
return nullptr;
if (Idx >= size())
@@ -122,6 +129,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;
}
@@ -181,8 +190,8 @@ void BitcodeReaderValueList::resolveConstantForwardRefs() {
NewOp = RealVal;
} else {
// Otherwise, look up the placeholder in ResolveConstants.
- ResolveConstantsTy::iterator It = std::lower_bound(
- ResolveConstants.begin(), ResolveConstants.end(),
+ ResolveConstantsTy::iterator It = llvm::lower_bound(
+ ResolveConstants,
std::pair<Constant *, unsigned>(cast<Constant>(*I), 0));
assert(It != ResolveConstants.end() && It->first == *I);
NewOp = operator[](It->second);
diff --git a/lib/Bitcode/Reader/ValueList.h b/lib/Bitcode/Reader/ValueList.h
index 5ad7899347ad..49900498c294 100644
--- a/lib/Bitcode/Reader/ValueList.h
+++ b/lib/Bitcode/Reader/ValueList.h
@@ -1,9 +1,8 @@
//===-- Bitcode/Reader/ValueList.h - Number values --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -29,6 +28,13 @@ class Value;
class BitcodeReaderValueList {
std::vector<WeakTrackingVH> 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<Type *> 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
@@ -40,8 +46,15 @@ class BitcodeReaderValueList {
ResolveConstantsTy ResolveConstants;
LLVMContext &Context;
+ /// Maximum number of valid references. Forward references exceeding the
+ /// maximum must be invalid.
+ unsigned RefsUpperBound;
+
public:
- BitcodeReaderValueList(LLVMContext &C) : Context(C) {}
+ BitcodeReaderValueList(LLVMContext &C, size_t RefsUpperBound)
+ : Context(C),
+ RefsUpperBound(std::min((size_t)std::numeric_limits<unsigned>::max(),
+ RefsUpperBound)) {}
~BitcodeReaderValueList() {
assert(ResolveConstants.empty() && "Constants not resolved?");
@@ -49,12 +62,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 {
@@ -63,18 +83,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.