Repository: carbon-language/carbon-lang
File: toolchain/sem_ir/inst.h (C/C++)

Code before:
 public:
  using BaseType = BlockValueStore<InstBlockId>;

  explicit InstBlockStore(llvm::BumpPtrAllocator& allocator)
      : BaseType(allocator) {
    auto exports_id = AddPlaceholder();
    CARBON_CHECK(exports_id == InstBlockId::Exports);
    auto import_refs_id = AddPlaceholder();
    CARBON_CHECK(import_refs_id == InstBlockId::ImportRefs);
    auto global_init_id = AddPlaceholder();
    CARBON_CHECK(global_init_id == InstBlockId::GlobalInit);
  }

  // Adds an uninitialized block of the given size. The caller is expected to
  // modify values.
  auto AddUninitialized(size_t size) -> InstBlockId {
    return values().Add(AllocateUninitialized(size));
  }

  // Reserves and returns a block ID. The contents of the block should be
  // specified by calling ReplacePlaceholder.
  auto AddPlaceholder() -> InstBlockId {
    return values().Add(llvm::MutableArrayRef<ElementType>());
  }

  // Sets the contents of an empty block to the given content.
  auto ReplacePlaceholder(InstBlockId block_id, llvm::ArrayRef<InstId> content)
      -> void {
    CARBON_CHECK(Get(block_id).empty(),
                 "inst block content set more than once");
    values().Get(block_id) = AllocateCopy(content);
  }

  // Returns the contents of the specified block, or an empty array if the block
  // is invalid.
  auto GetOrEmpty(InstBlockId block_id) const -> llvm::ArrayRef<InstId> {
    return block_id.has_value() ? Get(block_id) : llvm::ArrayRef<InstId>();
  }
};

// See common/hashing.h.
inline auto CarbonHashValue(const Inst& value, uint64_t seed) -> HashCode {
  Hasher hasher(seed);
  hasher.HashRaw(value);
  return static_cast<HashCode>(hasher);
}

}  // namespace Carbon::SemIR

#endif  // CARBON_TOOLCHAIN_SEM_IR_INST_H_


Review comment (bug):
```suggestion
  // Sets the contents of a placeholder block to the given content.
```
Just to avoid the suggestion that you can `Add({})` and then `ReplacePlaceholder`. Might also be nice to CHECK-fail if `block_id` is `InstBlockId::Empty`.

Code after:
 public:
  using BaseType = BlockValueStore<InstBlockId>;

  explicit InstBlockStore(llvm::BumpPtrAllocator& allocator)
      : BaseType(allocator) {
    auto exports_id = AddPlaceholder();
    CARBON_CHECK(exports_id == InstBlockId::Exports);
    auto import_refs_id = AddPlaceholder();
    CARBON_CHECK(import_refs_id == InstBlockId::ImportRefs);
    auto global_init_id = AddPlaceholder();
    CARBON_CHECK(global_init_id == InstBlockId::GlobalInit);
  }

  // Adds an uninitialized block of the given size. The caller is expected to
  // modify values.
  auto AddUninitialized(size_t size) -> InstBlockId {
    return values().Add(AllocateUninitialized(size));
  }

  // Reserves and returns a block ID. The contents of the block should be
  // specified by calling ReplacePlaceholder.
  auto AddPlaceholder() -> InstBlockId {
    return values().Add(llvm::MutableArrayRef<ElementType>());
  }

  // Sets the contents of a placeholder block to the given content.
  auto ReplacePlaceholder(InstBlockId block_id, llvm::ArrayRef<InstId> content)
      -> void {
    CARBON_CHECK(block_id != SemIR::InstBlockId::Empty);
    CARBON_CHECK(Get(block_id).empty(),
                 "inst block content set more than once");
    values().Get(block_id) = AllocateCopy(content);
  }

  // Returns the contents of the specified block, or an empty array if the block
  // is invalid.
  auto GetOrEmpty(InstBlockId block_id) const -> llvm::ArrayRef<InstId> {
    return block_id.has_value() ? Get(block_id) : llvm::ArrayRef<InstId>();
  }
};

// See common/hashing.h.
inline auto CarbonHashValue(const Inst& value, uint64_t seed) -> HashCode {
  Hasher hasher(seed);
  hasher.HashRaw(value);
  return static_cast<HashCode>(hasher);
}

}  // namespace Carbon::SemIR

#endif  // CARBON_TOOLCHAIN_SEM_IR_INST_H_