This is an archive of the discontinued LLVM Phabricator instance.

[clang][Interp] Implement __builtin_nan family of functions
ClosedPublic

Authored by tbaeder on Jul 14 2023, 11:03 PM.

Details

Summary

One existing problem is that we can't do much with the values since comparing with nans is broken ATM and I don't want to make this patch depend on the __builtin_bit_cast patch.

Diff Detail

Event Timeline

tbaeder created this revision.Jul 14 2023, 11:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 14 2023, 11:03 PM
tbaeder requested review of this revision.Jul 14 2023, 11:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 14 2023, 11:03 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
tbaeder updated this revision to Diff 541314.Jul 17 2023, 9:42 PM
tbaeder updated this revision to Diff 541318.Jul 17 2023, 10:07 PM
aaron.ballman added inline comments.Jul 18 2023, 12:24 PM
clang/lib/AST/Interp/InterpBuiltin.cpp
88

Please add test coverage for a case like __builtin_nan("derp") to show it's not a valid constant expression.

106

LOL, thank you for this comment and wow. :-D

135–137

We should have test coverage for these odd sizes just to ensure we're properly pushing/popping what we expect off the stack.

clang/test/AST/Interp/builtin-functions.cpp
44

Probably worth a comment here mentioning that the ref-error is a rejects-valid issue that the experimental compiler accepts correctly.

tbaeder added inline comments.Jul 18 2023, 12:33 PM
clang/test/AST/Interp/builtin-functions.cpp
44

I thought you said on Discord that the current interpreter is correct? I made the new one reject anything but string literals in https://reviews.llvm.org/D155545.

aaron.ballman added inline comments.Jul 18 2023, 12:42 PM
clang/test/AST/Interp/builtin-functions.cpp
44

Oops, crossing streams as I just mentioned this in another review of yours in the same area.

I think I misunderstood the question on Discord when we were chatting. I was thinking the situation was more that Sema was allowing through something like __builtin_nan(12); and diagnosing it later during CodeGen. I think constexpr builtins should generally behave the same as regular constexpr functions the user could write.

I'm really sorry if I made extra work for you with this confusion!

tbaeder updated this revision to Diff 541832.Jul 18 2023, 9:00 PM
tbaeder marked 3 inline comments as done.
tbaeder marked 2 inline comments as done.Jul 18 2023, 9:02 PM
tbaeder added inline comments.
clang/lib/AST/Interp/InterpBuiltin.cpp
106

That's just copy/paste from ExprConst.cpp :)

clang/test/AST/Interp/builtin-functions.cpp
44

No problem, passing the CallExpr along still makes sense.

tbaeder updated this revision to Diff 541833.Jul 18 2023, 9:02 PM
tbaeder marked an inline comment as done.

One thing I'm wondering though is:

constexpr char A[] = {'1', '2', '3'};
constexpr double d = __builtin_nans(A);

what's expected here? The given char array is not null-terminated.
Should the interpreter ignore the null byte at the end if it's there? StringRef::getAsInteger() always returns an error if it encounters one, so the currentcode in InterpBuiltin.cpp ignores the last byte and will pass 12 along for the example above.

One thing I'm wondering though is:

constexpr char A[] = {'1', '2', '3'};
constexpr double d = __builtin_nans(A);

what's expected here? The given char array is not null-terminated.

The builtin expects a null terminated string, so that should be an invalid constant expression due to reading off the end of the array.

Should the interpreter ignore the null byte at the end if it's there? StringRef::getAsInteger() always returns an error if it encounters one, so the currentcode in InterpBuiltin.cpp ignores the last byte and will pass 12 along for the example above.

Yeah, we should not do that. :-D In GCC, this builtin exists to support the nans() function from https://www.open-std.org/jtc1/sc22/wg14/www/docs/n965.htm (which was proposed but never adopted); Clang's support is for parity with GCC.

tbaeder updated this revision to Diff 544258.Jul 26 2023, 1:44 AM
aaron.ballman added inline comments.Jul 26 2023, 10:20 AM
clang/test/AST/Interp/builtin-functions.cpp
45

This should be accepted by both the current and the new interpreter, right?

53

This should be accepted, shouldn't it? The payload is a valid integer constant (as a string).

tbaeder added inline comments.Jul 26 2023, 10:37 AM
clang/test/AST/Interp/builtin-functions.cpp
53

So answer both your questions: Yes, but the current interpreter has a isa<StringLiteral>() check and rejects everything that isn't a string literal.

aaron.ballman accepted this revision.Jul 26 2023, 10:38 AM

LG!

clang/test/AST/Interp/builtin-functions.cpp
53

Ah! Slap some FIXME comments around the two cases to explain what's going on and that can be solved separately. Seem reasonable?

This revision is now accepted and ready to land.Jul 26 2023, 10:38 AM
tbaeder added inline comments.Jul 26 2023, 10:40 AM
clang/test/AST/Interp/builtin-functions.cpp
53

Sure, I can do that.

tbaeder updated this revision to Diff 544435.Jul 26 2023, 10:44 AM
This revision was landed with ongoing or failed builds.Jul 28 2023, 1:29 AM
This revision was automatically updated to reflect the committed changes.