The P4 spec makes it clear that int<N> literals are expressed in the form <N>s<value>. In the examples given in the spec, negative literals use the two's complement representation for the <value> (eg. to represent -1 as an int<2>, we use 2s3) and an overflow warning is emitted.
I was curious how the compiler handles/represents this internally, so I tried constructing some IR nodes and outputting them (both manually using toString and via top4). In both cases, the emitted string had form -<N>s<abs-value> for negative values, which is valid P4 syntax but parses as the unary negation of a positive int<N> value rather than a single IR::Constant node.
This representation is warning-free for all values except the minimum value of the type (-2^(N-1)), which emits an overflow warning because its absolute value 2^(N-1) is out-of-range of int<N>. It seems to be semantically equivalent in all cases (though the minimum value case is a bit confusing because it relies on the fact that -(-2^(N-1)) = -2^(N-1) in N-bit two's complement).
This has me wondering how closely the top4 output is intended to match the input IR. Is it intended to be:
(a) recompileable (semantically equivalent, warnings acceptable) - current behavior
(b) recompileable without warnings
(c) recompileable with the same IR shape
In some sense, the answer above determines what the canonical representation for negative int<N> literals should be:
- if (a), the current
-<N>s<abs-value> behavior makes sense as the top4 output
- if (b), the current behavior doesn't quite satisfy this due to the warning on the minimum value. Some workaround (such as a cast expression
(int<N>)(value)) might be required.
- If (c),
top4 should likely use the two's complement form seen in the spec's examples to match the IR shape more closely
I'm happy to open a separate bug/PR if the current behavior is considered unintentional. Mainly wanted to raise the question to understand the intended semantics first. Thanks!
The P4 spec makes it clear that
int<N>literals are expressed in the form<N>s<value>. In the examples given in the spec, negative literals use the two's complement representation for the<value>(eg. to represent -1 as anint<2>, we use2s3) and an overflow warning is emitted.I was curious how the compiler handles/represents this internally, so I tried constructing some IR nodes and outputting them (both manually using
toStringand viatop4). In both cases, the emitted string had form-<N>s<abs-value>for negative values, which is valid P4 syntax but parses as the unary negation of a positiveint<N>value rather than a singleIR::Constantnode.This representation is warning-free for all values except the minimum value of the type (
-2^(N-1)), which emits an overflow warning because its absolute value2^(N-1)is out-of-range ofint<N>. It seems to be semantically equivalent in all cases (though the minimum value case is a bit confusing because it relies on the fact that-(-2^(N-1)) = -2^(N-1)inN-bit two's complement).This has me wondering how closely the
top4output is intended to match the input IR. Is it intended to be:(a) recompileable (semantically equivalent, warnings acceptable) - current behavior
(b) recompileable without warnings
(c) recompileable with the same IR shape
In some sense, the answer above determines what the canonical representation for negative
int<N>literals should be:-<N>s<abs-value>behavior makes sense as thetop4output(int<N>)(value)) might be required.top4should likely use the two's complement form seen in the spec's examples to match the IR shape more closelyI'm happy to open a separate bug/PR if the current behavior is considered unintentional. Mainly wanted to raise the question to understand the intended semantics first. Thanks!