E3022

E3022 — An extern function whose signature mentions a tensor. A tensor is a memref, and lowering expands a memref parameter into the seven scalars of its descriptor — allocated pointer, aligned pointer, offset, and a size and stride per rank. So fn c_take(t : Tensor<f32, [?, ?]>) -> i32 declares a C symbol taking seven arguments, which is not a signature anyone writes on the C side; the call links by name and passes something the callee never agreed to. Take a raw pointer and build the tensor in Vx (Tensor<f32, [?, ?]>::from_ptr_2d), which is what the corpus already does.

What the compiler reports

E3022 … parameter `t` of extern fn `c_take` … cannot mention a tensor

The fragments the test suite holds the compiler to. An ellipsis marks text the test does not constrain; the emitted message also carries a source location.

A program that triggers it

//
// Part of the Vx Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Lowering expands a memref parameter into the seven scalars of its descriptor,
// so a tensor in an `extern` signature declares a C symbol taking seven
// arguments -- a signature no C source writes. The call links by name and
// passes something the callee never agreed to.
//
// This was accepted: `fn c_take(t : Tensor<f32, [?, ?]>) -> i32` emitted
// `llvm.func @c_take(!llvm.ptr, !llvm.ptr, i64, i64, i64, i64, i64)`.
//
// A raw pointer stays legal, and is how the corpus does it: `vx_load_weights`
// in std::llama returns `*mut f32`, and `Tensor<f32, [?, ?]>::from_ptr_2d` builds the
// tensor on the Vx side.
//

extern {
  fn c_ok(p : *mut f32, n : i32) -> i32;
  fn c_take(t : Tensor<f32, [?, ?]>) -> i32;
  fn c_give(n : i32) -> Tensor<f32, [?, ?]>;
}

fn main() -> i32 {
  return 0;
}

From tests/frontend/fail/extern_signature_cannot_mention_a_tensor.vx, which asserts this diagnostic on every commit.

Related