-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Domain Restriction Semantics #1344
Comments
I'd personally argue for #1: Do nothing, UB is UB. Using 32-bit ints in a logic program is like using assembly. One should know what to expect and the language is a thin veneer of convenience over the raw machine. This answer is orthogonal to the possible addition of more disciplined (but clearly designated) numeric types. If a different, more disciplined, type were offered, I'd expect the conversions to work differently. But with "number" being "int", I'd find any "clever" semantics (e.g., saturating) surprising and the current semantics unsurprising. |
Ram{32,64} Portability: UB Sanitizers: UB in C++ code-gen:
Synthesis (simplified snippet, bit-casts omitted when not needed): SignalHandler::instance()->setMsg(R"_(a(((2bshl31)-1)).
in file /home/olivier/projects/souffle/TOY/ub-tester-2.dl [3:1-3:20])_");
/* BEGIN visitQuery @Synthesiser.cpp:273 */
[&]() {
CREATE_OP_CONTEXT(rel_1_a_op_ctxt, rel_1_a->createContext());
Tuple<RamDomain, 1> tuple{{
// VISIBLE UB!
ramBitCast<RamSigned>(RamUnsigned(2) << (RamSigned(31) & RAM_BIT_SHIFT_MASK)) - 1
}};
rel_1_a->insert(tuple, READ_OP_CONTEXT(rel_1_a_op_ctxt));
}(); /* END visitQuery @Synthesiser.cpp:359 */ At which point the compiler is allowed to get rather creative. |
Note that the overflow behaviour already varies. On some ARM64 platforms. One reason there hasn't been much interest about this before is that it's not usually of concern - either the range used is well within the non-UB range, such as counting from 0/1 up, or arithmetic just isn't used as you're dealing with constants. A version of (3) would be that only RamDomains have UB, RamSpecificTypes do not. If you need clearly defined behaviour, then use a clearly defined type. |
I would argue for 1 or maybe some version of 3 like @mmcgr suggests. For integers and RamDomains having UB is the least surprising behavior. |
Yet another proposal: compile using
|
There's also A comparison of the effect of the flags is shown here: https://godbolt.org/z/_dzEQJ |
This issue should be considered an RFC, so please do propose alternatives if you have any.
We should have an official policy regarding the behaviour of souffle as to what happens when a computation produces a value that cannot be stored in its declared type. The initial motivating example is
2^31
in the test suite, however the same idea extends to other examples, see below and the issue list. I begin with a description and examples of the issue, and then propose some possible policies.All examples assume
RAM_DOMAIN_SIZE == 32
.Current Behaviour:
Any type of overflow is UB. This will likely result in surprising behavior if this computation is not a literal expression. e.g. arguments in a recursive expression. e.g.
This behaviour also extends conversions between numeric types. e.g.
Complicating this is the fact that there are users currently (ab)using the fact that
2^31
is INT_MIN. Prior to the addition of Java-style bit-shift operators this was somewhat excusable as a way to avoid having to tattoo that awful constant somwhere on your body to keep it handy.Possible General Policies:
^
) aren't.Deprecating
2^31
This can now be replaced by the well defined expression
2 bshl 31
. Any changes to2^31
's behaviour will likely have to wait for Souffle 2's release. Until then, the expression2^31
could be special-cased for back-compat.In the future we may also wish to provide pre-proc defs for
{UN}SIGNED_{MAX, MIN}
.The text was updated successfully, but these errors were encountered: