================ @@ -52,171 +91,132 @@ static Error parseRecord(BitstreamMetaParserHelper &Parser, unsigned Code) { switch (*RecordID) { case RECORD_META_CONTAINER_INFO: { if (Record.size() != 2) - return malformedRecord("BLOCK_META", "RECORD_META_CONTAINER_INFO"); - Parser.ContainerVersion = Record[0]; - Parser.ContainerType = Record[1]; + return malformedRecord(MetaContainerInfoName); + Container = {Record[0], Record[1]}; + // Error immediately if container version is outdated, so the user sees an + // explanation instead of a parser error. + if (Container->Version != CurrentContainerVersion) { + return ::error( + "Unsupported remark container version (expected: {}, read: {}). " + "Please upgrade/downgrade your toolchain to read this container.", + CurrentContainerVersion, Container->Version); + } break; } case RECORD_META_REMARK_VERSION: { if (Record.size() != 1) - return malformedRecord("BLOCK_META", "RECORD_META_REMARK_VERSION"); - Parser.RemarkVersion = Record[0]; + return malformedRecord(MetaRemarkVersionName); + RemarkVersion = Record[0]; + // Error immediately if remark version is outdated, so the user sees an + // explanation instead of a parser error. + if (*RemarkVersion != CurrentRemarkVersion) { + return ::error( + "Unsupported remark version in container (expected: {}, read: {}). " + "Please upgrade/downgrade your toolchain to read this container.", + CurrentRemarkVersion, *RemarkVersion); + } break; } case RECORD_META_STRTAB: { if (Record.size() != 0) - return malformedRecord("BLOCK_META", "RECORD_META_STRTAB"); - Parser.StrTabBuf = Blob; + return malformedRecord(MetaStrTabName); + StrTabBuf = Blob; break; } case RECORD_META_EXTERNAL_FILE: { if (Record.size() != 0) - return malformedRecord("BLOCK_META", "RECORD_META_EXTERNAL_FILE"); - Parser.ExternalFilePath = Blob; + return malformedRecord(MetaExternalFileName); + ExternalFilePath = Blob; break; } default: - return unknownRecord("BLOCK_META", *RecordID); + return unknownRecord(*RecordID); } return Error::success(); } -BitstreamRemarkParserHelper::BitstreamRemarkParserHelper( - BitstreamCursor &Stream) - : Stream(Stream) {} - -/// Parse a record and fill in the fields in the parser. -static Error parseRecord(BitstreamRemarkParserHelper &Parser, unsigned Code) { - BitstreamCursor &Stream = Parser.Stream; - // Note: 5 is used here because it's the max number of fields we have per - // record. - SmallVector<uint64_t, 5> Record; - StringRef Blob; - Expected<unsigned> RecordID = Stream.readRecord(Code, Record, &Blob); - if (!RecordID) - return RecordID.takeError(); +Error BitstreamRemarkParserHelper::parseRecord(unsigned Code) { + Record.clear(); + Expected<unsigned> MaybeRecordID = + Stream.readRecord(Code, Record, &RecordBlob); + if (!MaybeRecordID) + return MaybeRecordID.takeError(); + RecordID = *MaybeRecordID; + return handleRecord(); +} - switch (*RecordID) { +Error BitstreamRemarkParserHelper::handleRecord() { + switch (RecordID) { case RECORD_REMARK_HEADER: { if (Record.size() != 4) - return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HEADER"); - Parser.Type = Record[0]; - Parser.RemarkNameIdx = Record[1]; - Parser.PassNameIdx = Record[2]; - Parser.FunctionNameIdx = Record[3]; + return malformedRecord(RemarkHeaderName); + Type = Record[0]; + RemarkNameIdx = Record[1]; + PassNameIdx = Record[2]; + FunctionNameIdx = Record[3]; break; } case RECORD_REMARK_DEBUG_LOC: { if (Record.size() != 3) - return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_DEBUG_LOC"); - Parser.SourceFileNameIdx = Record[0]; - Parser.SourceLine = Record[1]; - Parser.SourceColumn = Record[2]; + return malformedRecord(RemarkDebugLocName); + Loc = {Record[0], Record[1], Record[2]}; break; } case RECORD_REMARK_HOTNESS: { if (Record.size() != 1) - return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_HOTNESS"); - Parser.Hotness = Record[0]; + return malformedRecord(RemarkHotnessName); + Hotness = Record[0]; break; } case RECORD_REMARK_ARG_WITH_DEBUGLOC: { if (Record.size() != 5) - return malformedRecord("BLOCK_REMARK", "RECORD_REMARK_ARG_WITH_DEBUGLOC"); - // Create a temporary argument. Use that as a valid memory location for this - // argument entry. - Parser.TmpArgs.emplace_back(); - Parser.TmpArgs.back().KeyIdx = Record[0]; - Parser.TmpArgs.back().ValueIdx = Record[1]; - Parser.TmpArgs.back().SourceFileNameIdx = Record[2]; - Parser.TmpArgs.back().SourceLine = Record[3]; - Parser.TmpArgs.back().SourceColumn = Record[4]; - Parser.Args = - ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); + return malformedRecord(RemarkArgWithDebugLocName); + auto &Arg = Args.emplace_back(Record[0], Record[1]); + Arg.Loc = {Record[2], Record[3], Record[4]}; break; } case RECORD_REMARK_ARG_WITHOUT_DEBUGLOC: { if (Record.size() != 2) - return malformedRecord("BLOCK_REMARK", - "RECORD_REMARK_ARG_WITHOUT_DEBUGLOC"); - // Create a temporary argument. Use that as a valid memory location for this - // argument entry. - Parser.TmpArgs.emplace_back(); - Parser.TmpArgs.back().KeyIdx = Record[0]; - Parser.TmpArgs.back().ValueIdx = Record[1]; - Parser.Args = - ArrayRef<BitstreamRemarkParserHelper::Argument>(Parser.TmpArgs); + return malformedRecord(RemarkArgWithoutDebugLocName); + Args.emplace_back(Record[0], Record[1]); break; } default: - return unknownRecord("BLOCK_REMARK", *RecordID); + return unknownRecord(RecordID); } return Error::success(); } -template <typename T> -static Error parseBlock(T &ParserHelper, unsigned BlockID, - const char *BlockName) { - BitstreamCursor &Stream = ParserHelper.Stream; - Expected<BitstreamEntry> Next = Stream.advance(); - if (!Next) - return Next.takeError(); - if (Next->Kind != BitstreamEntry::SubBlock || Next->ID != BlockID) - return createStringError( - std::make_error_code(std::errc::illegal_byte_sequence), - "Error while parsing %s: expecting [ENTER_SUBBLOCK, %s, ...].", - BlockName, BlockName); - if (Stream.EnterSubBlock(BlockID)) - return createStringError( - std::make_error_code(std::errc::illegal_byte_sequence), - "Error while entering %s.", BlockName); - - // Stop when there is nothing to read anymore or when we encounter an - // END_BLOCK. - while (!Stream.AtEndOfStream()) { - Next = Stream.advance(); - if (!Next) - return Next.takeError(); - switch (Next->Kind) { - case BitstreamEntry::EndBlock: - return Error::success(); - case BitstreamEntry::Error: - case BitstreamEntry::SubBlock: - return createStringError( - std::make_error_code(std::errc::illegal_byte_sequence), - "Error while parsing %s: expecting records.", BlockName); - case BitstreamEntry::Record: - if (Error E = parseRecord(ParserHelper, Next->ID)) - return E; - continue; - } - } - // If we're here, it means we didn't get an END_BLOCK yet, but we're at the - // end of the stream. In this case, error. - return createStringError( - std::make_error_code(std::errc::illegal_byte_sequence), - "Error while parsing %s: unterminated block.", BlockName); -} +Error BitstreamRemarkParserHelper::parseNext() { + Type.reset(); + RemarkNameIdx.reset(); + PassNameIdx.reset(); + FunctionNameIdx.reset(); + Hotness.reset(); + Loc.reset(); + Args.clear(); -Error BitstreamMetaParserHelper::parse() { - return parseBlock(*this, META_BLOCK_ID, "META_BLOCK"); -} - -Error BitstreamRemarkParserHelper::parse() { - return parseBlock(*this, REMARK_BLOCK_ID, "REMARK_BLOCK"); + if (Error E = expectBlock()) + return E; + return parseBlock(); } BitstreamParserHelper::BitstreamParserHelper(StringRef Buffer) : Stream(Buffer) {} -Expected<std::array<char, 4>> BitstreamParserHelper::parseMagic() { +Error BitstreamParserHelper::expectMagic() { std::array<char, 4> Result; - for (unsigned i = 0; i < 4; ++i) + for (unsigned I = 0; I < 4; ++I) if (Expected<unsigned> R = Stream.Read(8)) - Result[i] = *R; + Result[I] = *R; else return R.takeError(); - return Result; + + StringRef MagicNumber{Result.data(), Result.size()}; + if (MagicNumber != remarks::ContainerMagic) + return error("Unknown magic number: expecting {}, got {}.", + remarks::ContainerMagic, MagicNumber); ---------------- jroelofs wrote:
ok, fair. https://github.com/llvm/llvm-project/pull/156511 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits