[clang] [APINotes] Upstream APINotesReader (PR #66769)

Egor Zhdan via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 10 11:07:20 PDT 2023


================
@@ -0,0 +1,2001 @@
+//===--- APINotesReader.cpp - API Notes Reader ------------------*- C++ -*-===//
+//
+// 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 "clang/APINotes/APINotesReader.h"
+#include "APINotesFormat.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Bitstream/BitstreamReader.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/OnDiskHashTable.h"
+
+namespace clang {
+namespace api_notes {
+using namespace llvm::support;
+
+namespace {
+/// Deserialize a version tuple.
+llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
+  uint8_t NumVersions = (*Data++) & 0x03;
+
+  unsigned Major = endian::readNext<uint32_t, little, unaligned>(Data);
+  if (NumVersions == 0)
+    return llvm::VersionTuple(Major);
+
+  unsigned Minor = endian::readNext<uint32_t, little, unaligned>(Data);
+  if (NumVersions == 1)
+    return llvm::VersionTuple(Major, Minor);
+
+  unsigned Subminor = endian::readNext<uint32_t, little, unaligned>(Data);
+  if (NumVersions == 2)
+    return llvm::VersionTuple(Major, Minor, Subminor);
+
+  unsigned Build = endian::readNext<uint32_t, little, unaligned>(Data);
+  return llvm::VersionTuple(Major, Minor, Subminor, Build);
+}
+
+/// An on-disk hash table whose data is versioned based on the Swift version.
+template <typename Derived, typename KeyType, typename UnversionedDataType>
+class VersionedTableInfo {
+public:
+  using internal_key_type = KeyType;
+  using external_key_type = KeyType;
+  using data_type =
+      llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
+  using hash_value_type = size_t;
+  using offset_type = unsigned;
+
+  internal_key_type GetInternalKey(external_key_type Key) { return Key; }
+
+  external_key_type GetExternalKey(internal_key_type Key) { return Key; }
+
+  static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
+    return LHS == RHS;
+  }
+
+  static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
+    unsigned KeyLength = endian::readNext<uint16_t, little, unaligned>(Data);
+    unsigned DataLength = endian::readNext<uint16_t, little, unaligned>(Data);
+    return {KeyLength, DataLength};
+  }
+
+  static data_type ReadData(internal_key_type Key, const uint8_t *Data,
+                            unsigned Length) {
+    unsigned NumElements = endian::readNext<uint16_t, little, unaligned>(Data);
+    data_type Result;
+    Result.reserve(NumElements);
+    for (unsigned i = 0; i != NumElements; ++i) {
+      auto version = ReadVersionTuple(Data);
+      const auto *DataBefore = Data;
+      (void)DataBefore;
+      auto UnversionedData = Derived::readUnversioned(Key, Data);
+      assert(Data != DataBefore &&
+             "Unversioned data reader didn't move pointer");
+      Result.push_back({version, UnversionedData});
+    }
+    return Result;
+  }
+};
+
+/// Read serialized CommonEntityInfo.
+void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
+  uint8_t UnavailableBits = *Data++;
+  Info.Unavailable = (UnavailableBits >> 1) & 0x01;
+  Info.UnavailableInSwift = UnavailableBits & 0x01;
+  if ((UnavailableBits >> 2) & 0x01)
+    Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01));
+
+  unsigned MsgLength = endian::readNext<uint16_t, little, unaligned>(Data);
+  Info.UnavailableMsg =
+      std::string(reinterpret_cast<const char *>(Data),
+                  reinterpret_cast<const char *>(Data) + MsgLength);
+  Data += MsgLength;
+
+  unsigned SwiftNameLength =
+      endian::readNext<uint16_t, little, unaligned>(Data);
+  Info.SwiftName =
+      std::string(reinterpret_cast<const char *>(Data),
+                  reinterpret_cast<const char *>(Data) + SwiftNameLength);
+  Data += SwiftNameLength;
+}
+
+/// Read serialized CommonTypeInfo.
+void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
+  ReadCommonEntityInfo(Data, Info);
+
+  unsigned SwiftBridgeLength =
+      endian::readNext<uint16_t, little, unaligned>(Data);
+  if (SwiftBridgeLength > 0) {
+    Info.setSwiftBridge(std::optional<std::string>(std::string(
----------------
egorzhdan wrote:

It was required because of resolution ambiguity, but one of the `setSwiftBridge` overloads wasn't used anywhere. I removed it.

https://github.com/llvm/llvm-project/pull/66769


More information about the cfe-commits mailing list