E3023
E3023 — A shaped tensor initialized from a scalar.let a : Tensor<f32, [128, 64]> = 1.0allocated and filled a whole buffer from something that reads as an assignment, and the two codegen paths disagreed about it: the AST path emitted the allocation and alinalg.fill, the flat path kept the bare constant and handed anf32to a call expecting a memref.Tensor<T, [..]>::fill(v)is the spelling. The rank-0 wrap (Tensor<f32, []> = 1.0) is a different thing and stays legal.
What the compiler reports
E3023 … 'a' is a shaped tensor initialized from a scalar … ::fill(v)
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
//
// `let a : Tensor<f32, [2, 2]> = 1.0` read as an assignment and meant an
// allocation and a fill of every element. The two codegen paths did not agree
// about it: the AST path emitted the allocation and a `linalg.fill`, the flat
// path kept the bare constant, so a call expecting `memref<2x2xf32>` was handed
// an `f32` and the module did not parse.
//
// `Tensor<T, [..]>::fill(v)` says it instead, and says it once for both paths.
//
// The rank-0 wrap is a different thing and stays legal: `b` below binds a
// scalar into a rank-0 tensor, which is what that spelling has always meant,
// and it is not refused.
//
fn main() -> i32 {
let a : Tensor<f32, [2, 2]> = 1.0;
let b : Tensor<f32, []> = 2.0;
return 0;
}
From tests/frontend/fail/shaped_tensor_from_a_scalar.vx, which asserts this diagnostic on every commit.
Related
A tour of VxThe chapter covering the rule this code enforces.
All diagnosticsEvery code the compiler can emit, grouped by stage.
E3022An
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.
E3024.shape[i] on a tensor. It answered on any value, not only a tensor, and typed its answer as a rank-0 tensor. extent(i) is the read of a run-time extent.