jax-ml/jax · error · ValueError

tmem_addr_ref must be an i32 memref, got: {addr_ref_ty}

Error message

tmem_addr_ref must be an i32 memref, got: {addr_ref_ty}

What it means

TMEMRef.from_alloc loads the TMEM base address via memref.load from the provided smem memref, which requires the element type to be exactly signless i32 — the tcgen05.alloc instruction returns a 32-bit address. Any other element type (i64, f32, i16, signed variants) is rejected.

Source

Thrown at jax/experimental/mosaic/gpu/tcgen05.py:1225

    self.layout.check_type(self.shape, utils.bitwidth(self.dtype))

  @classmethod
  def from_alloc(
      cls,
      tmem_addr_ref: ir.Value,
      shape: tuple[int, int],
      dtype,
      collective: bool | None = None,
      layout: TMEMLayout | None = None,
  ) -> TMEMRef:
    i32 = ir.IntegerType.get_signless(32)
    if not isinstance(tmem_addr_ref.type, ir.MemRefType):
      raise ValueError(f"tmem_addr_ref must be a memref or a pointer, got: {tmem_addr_ref.type}")
    addr_ref_ty = ir.MemRefType(tmem_addr_ref.type)
    if not utils.is_smem_ref(addr_ref_ty):
      raise ValueError(f"tmem_addr_ref must be in shared memory, got: {addr_ref_ty}")
    if addr_ref_ty.element_type != i32:
      raise ValueError(f"tmem_addr_ref must be an i32 memref, got: {addr_ref_ty}")
    if math.prod(addr_ref_ty.shape) != 1:
      raise ValueError(f"tmem_addr_ref must contain a single element, got: {addr_ref_ty}")
    i0 = arith.ConstantOp.create_index(0)
    tmem_addr = memref.load(tmem_addr_ref, [i0] * addr_ref_ty.rank)
    if shape[0] < 32:
      raise ValueError(f"TMEM refs must have at least 32 rows, got: {shape[0]}")
    if layout is None:
      if collective is None:
        raise ValueError(
            "collective argument must be provided when TMEM layout is inferred"
        )
      layout = _infer_tmem_layout(shape, collective, packing=1)
    # TODO: Do we have to do this??
    # warp_idx = utils.warp_idx(sync=False)
    # tmem_addr = arith.ori(tmem_addr, arith.shli(warp_idx, utils.c(21, i32)))
    return cls(tmem_addr, shape, dtype, layout)

  def slice(self, *idxs) -> TMEMRef:

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Make the address memref signless i32: ir.MemRefType.get([], i32) with smem address space
  2. Cast: store an i32 truncation of your address value into the i32 smem memref
  3. Use the library's tmem allocation helpers which produce the correct type

Example fix

# before
addr_ref = smem_alloca(i64, [])
# after
i32 = ir.IntegerType.get_signless(32)
addr_ref = smem_alloca(i32, [])
Defensive patterns

Strategy: type-guard

Validate before calling

i32 = ir.IntegerType.get_signless(32)
assert ir.MemRefType(tmem_addr_ref.type).element_type == i32

Type guard

def is_signless_i32_memref(ref) -> bool:
    t = getattr(ref, 'type', None)
    return isinstance(t, ir.MemRefType) and t.element_type == ir.IntegerType.get_signless(32)

Prevention

When it happens

Trigger: Passing an smem memref of i64/f32/i16 to from_alloc; using a signful integer type (e.g. si32) instead of signless i32.

Common situations: Building the address buffer with a helper defaulting to a different integer width; older snippets that used 64-bit address arithmetic.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/906e13d6ca009617. Report an issue: GitHub.