Closed jopperm closed 1 year ago
While I do like the idea of a ranged index operator, I don't believe this is the best approach. The way your current syntax is structured, it looks like the "start" and "end" operands are independent expressions with no known relationship, so it is impossible to determine the range size and hence the width of the concatenated type at compile time.
It could be mitigated by requiring the second operand to be an identifier name and the first to be an addition node where the first operand is the same identifier, but those are very arbitrary restrictions that will be hard to communicate clearly.
I would instead suggest something like X[rd] = MEM[base : 4]
, where 4
is the number of elements to concatenate (a compile-time constant).
I realize my alternate syntax would only work for one endianness, so it still needs some refinement if we want to support both (i.e. allow to specifiy the order in which the elements are concatenated). Maybe switch the order if the number is negative or something like that.
[...] it looks like the "start" and "end" operands are independent expressions with no known relationship, so it is impossible to determine the range size and hence the width of the concatenated type at compile time.
Good point, the same problem also ails the bit-range operator, which also would be more useful if it allowed variable offsets (but still fixed range sizes).
Why does it have to be a compile-time constant? And how is -in your view- compile-time defined? Just the parsing? Many other design languages have an elaboratation step to exactly determine these things and even C++ evaluates code during compilation to determine concrete values and ranges. Don't we limit ourselfs by only allowing constants? One constraint I could imagine ranges is that the size of the range has to be fixed. And this should be possible to evaluate...
To clarify, the bit-range operator is specified to accept literals and parameters, so compile-time in that context already means "after elaboration". I would apply the same terminology to a hypothetical ranged address space access. Still, you currently cannot write a loop that sweeps over the bits of value:
for (i = 0; i < sizeof(x); i += 3)
x[i+2:i] = ... // prohibited
In order to not mix up the existing and proposed operator here, I filed a new issue for the extension for bit-range operator here: #57
A ranged access operator for address spaces that only allows compile-constant bounds seems impractical. In any case, the same syntax and rules should be used for both operators.
@eyck I believe you misunderstood me, I am not proposing to restrict the offset to a compile time constant. The width of the resulting type is what needs to be known at compile time. The issue with two independent expressions is that they don't necessarily have a fixed difference.
Take this example:
function void foo(int a, int b) {
??? x = MEM[a:b];
}
The type of x
is impossible to determine because it depends on how many elements are selected, i.e. the difference between a
and b
, whose values are not known at compile time.
That's why I'm saying instead of the array[start:end]
syntax we should use array[start:length]
instead, where start
is still any arbitrary (non-constant) expression, but length
must be an expression that can be evaluated at compile time.
Exactly the same goes for the bit-range operator, which should in my opinion also use a length
operand instead of end
. Not only does that solve the beforementioned problem, but it also avoids repetition as you don't need to type the start offset twice.
And how is -in your view- compile-time defined?
A compile-time constant is any expression that can be constructed from integer literals, ISA parameter references and a limited set of arithmetic and logic operators. An expression is a compile-time constant if and only if the CoreDslConstantExpressionEvaluator
(formerly CoreDslInterpreter
) can determine its value.
We settled unanimously on the [start:end]
syntax in yesterday's working group meeting. This operator will be specified with a limited set of "patterns" a frontend must understand (like ID_1 + expr_1 : ID_1
) to make it feasible to context-check this operator without the need for advanced partial evaluation capabilities.
This was added some time ago. The contextual analysis result works great for the MLIR code generator.
Idea: Introduce a ranged index operator
as syntactic sugar for
See also https://github.com/Minres/RISCV_ISA_CoreDSL/issues/4 for context.