[llvm] [Object] Extract format-agnostic BBAddrMap decoder (PR #188435)

Haohai Wen via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 19:15:28 PDT 2026


================
@@ -0,0 +1,220 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements shared utilities for basic-block address maps.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/BBAddrMap.h"
+#include "llvm/Object/Error.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+
+// Helper to extract and decode the next ULEB128 value as unsigned int.
+// Returns zero and sets ULEBSizeErr if the ULEB128 value exceeds the unsigned
+// int limit.
+// Also returns zero if ULEBSizeErr is already in an error state.
+// ULEBSizeErr is an out variable if an error occurs.
+template <typename IntTy, std::enable_if_t<std::is_unsigned_v<IntTy>, int> = 0>
+static IntTy readULEB128As(DataExtractor &Data, DataExtractor::Cursor &Cur,
+                           Error &ULEBSizeErr) {
+  // Bail out and do not extract data if ULEBSizeErr is already set.
+  if (ULEBSizeErr)
+    return 0;
+  uint64_t Offset = Cur.tell();
+  uint64_t Value = Data.getULEB128(Cur);
+  if (Value > std::numeric_limits<IntTy>::max()) {
+    ULEBSizeErr = createError("ULEB128 value at offset 0x" +
+                              Twine::utohexstr(Offset) + " exceeds UINT" +
+                              Twine(std::numeric_limits<IntTy>::digits) +
+                              "_MAX (0x" + Twine::utohexstr(Value) + ")");
+    return 0;
+  }
+  return static_cast<IntTy>(Value);
+}
+} // end anonymous namespace
+
+Expected<std::vector<BBAddrMap>>
+llvm::object::decodeBBAddrMapPayload(AddressExtractor &Extractor,
+                                     std::vector<PGOAnalysisMap> *PGOAnalyses) {
+  DataExtractor &Data = Extractor.getDataExtractor();
+  std::vector<BBAddrMap> FunctionEntries;
+
+  DataExtractor::Cursor Cur(0);
+  Error ULEBSizeErr = Error::success();
+  Error MetadataDecodeErr = Error::success();
+
+  uint8_t Version = 0;
+  uint16_t Feature = 0;
+  BBAddrMap::Features FeatEnable{};
+  while (!ULEBSizeErr && !MetadataDecodeErr && Cur &&
+         Cur.tell() < Data.getData().size()) {
+    Version = Data.getU8(Cur);
+    if (!Cur)
+      break;
+    if (Version < 2 || Version > 5)
+      return createError("unsupported BB address map version: " +
+                         Twine(static_cast<int>(Version)));
+    Feature = Version < 5 ? Data.getU8(Cur) : Data.getU16(Cur);
+    if (!Cur)
+      break;
+    auto FeatEnableOrErr = BBAddrMap::Features::decode(Feature);
+    if (!FeatEnableOrErr)
+      return FeatEnableOrErr.takeError();
+    FeatEnable = *FeatEnableOrErr;
+    if (FeatEnable.CallsiteEndOffsets && Version < 3)
+      return createError("version should be >= 3 for BB address map when "
+                         "callsite offsets feature is enabled: version = " +
+                         Twine(static_cast<int>(Version)) +
+                         " feature = " + Twine(static_cast<int>(Feature)));
+    if (FeatEnable.BBHash && Version < 4)
+      return createError("version should be >= 4 for BB address map when "
+                         "basic block hash feature is enabled: version = " +
+                         Twine(static_cast<int>(Version)) +
+                         " feature = " + Twine(static_cast<int>(Feature)));
+    if (FeatEnable.PostLinkCfg && Version < 5)
+      return createError("version should be >= 5 for BB address map when "
+                         "post link cfg feature is enabled: version = " +
+                         Twine(static_cast<int>(Version)) +
+                         " feature = " + Twine(static_cast<int>(Feature)));
+    uint32_t NumBlocksInBBRange = 0;
+    uint32_t NumBBRanges = 1;
+    uint64_t RangeBaseAddress = 0;
+    if (FeatEnable.MultiBBRange) {
+      NumBBRanges = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+      if (!Cur || ULEBSizeErr)
+        break;
+      if (!NumBBRanges) {
+        std::string SecDesc = Extractor.getSectionDescription();
+        return createError("invalid zero number of BB ranges at offset " +
+                           Twine::utohexstr(Cur.tell()) +
+                           (SecDesc.empty() ? "" : " in " + SecDesc));
----------------
HaohaiWen wrote:

Done.

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


More information about the llvm-commits mailing list