This is an archive of the discontinued LLVM Phabricator instance.

[clang][Interp] Start supporting complex types
ClosedPublic

Authored by tbaeder on Mar 20 2023, 1:37 AM.

Details

Summary

Trying a different approach here where I split the implementation into smaller patches so they are easier to review.

Diff Detail

Event Timeline

tbaeder created this revision.Mar 20 2023, 1:37 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 20 2023, 1:37 AM
tbaeder requested review of this revision.Mar 20 2023, 1:37 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 20 2023, 1:37 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
tbaeder updated this revision to Diff 507646.Mar 23 2023, 1:42 AM

Completely forgot to add the tests to the patch, oops.

aaron.ballman added inline comments.Mar 23 2023, 10:28 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
2103

Member calls as well?

clang/lib/AST/Interp/Context.cpp
95–96

Hmmm, this seems surprising to me, I would have assumed that _Complex needed to be a primitive type so that we could perform typical math on it rather than treat it as a pair of values.

clang/test/AST/Interp/complex.cpp
8

Can you add tests for _Complex int as well? (That's also covered by isAnyComplexType())

tbaeder added inline comments.Mar 24 2023, 1:08 AM
clang/lib/AST/Interp/Context.cpp
95–96

I was going to add special opcodes for this case (or add one opcode for complex/vector/bitint/... things to do everything?).

If we don't do it this way we'd have to add isAnyComplexType() checks everywhere so we can figure out if we need to look at one or two values, don't we?

clang/test/AST/Interp/complex.cpp
8

There's a FIXME comment above in EvalEmitter.cpp so returning those doesn't work yet (but is otherwise not problematic I think.)

aaron.ballman added inline comments.Mar 24 2023, 7:56 AM
clang/lib/AST/Interp/Context.cpp
95–96

Hmm I think it depends on whether we consider the type to be primitive or not, maybe? I can see why it's not primitive -- it's comprised of two other primitive types. So that could be reasonable. But it's also primitive in that you need both of those values in order for the type to be meaningful for any operation (e.g., we don't want to accidentally split the values; we're always going to want to pass a complex value as "one thing", right). Buttttttt then again, if we treat it as not being primitive, then perhaps that gives us more optimization opportunities around things like "is an array of complex values an array of structs or a struct of arrays" kind of situations where we can decide to handle it differently depending on the situation.

So I guess I'm not certain of whether this is wrong or right.

clang/test/AST/Interp/complex.cpp
8

Hmmm, why the FIXME instead of just making the complex int type? (Alternatively, should we not use isAnyComplexType() and wait to add complex int support later?)

tbaeder updated this revision to Diff 509021.Mar 28 2023, 8:03 AM
tbaeder set the repository for this revision to rG LLVM Github Monorepo.

Add support for integer complex types as well.

tbaeder added inline comments.Mar 28 2023, 8:05 AM
clang/lib/AST/Interp/ByteCodeExprGen.cpp
2103

Yes, and some others, but I've only added the minimum for now to keep the patch small.

clang/test/AST/Interp/complex.cpp
8

Added int support, I just wasn't sure about the INT_TYPE_SWITCH.

I don't think the _BitInt test case should block this patch if that turns out to cause problems.

clang/lib/AST/Interp/EvalEmitter.cpp
224–226

The switch is fully covered with an unreachable, and the outer level returns false anyway.

clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

Oh boy, this is going to be interesting, isn't it?

consteval _Complex _BitInt(12) UhOh() { return (_Complex _BitInt(12))1; }
consteval _Complex _BitInt(18) Why() { return (_Complex _BitInt(18))1; }

static_assert(UhOh() + Why() == 2);
tbaeder added inline comments.Mar 28 2023, 10:57 PM
clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

_BitInt isn't supported in the new interpreter at all right now, so this just gets rejected.

Apart from that... is a complex bitint really something that should be supported? Not just in the new interpreter but generally?

tbaeder updated this revision to Diff 509223.Mar 28 2023, 11:46 PM
tbaeder marked an inline comment as done.Mar 28 2023, 11:47 PM
aaron.ballman accepted this revision.Mar 29 2023, 7:02 AM

LGTM but perhaps we should add an expected-failing test case for the _BitInt situation just so we don't forget about it.

clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

_BitInt isn't supported in the new interpreter at all right now, so this just gets rejected.

Well, that's sort of good then! :-D We'll have to deal with _BitInt at some point, so maybe we can add this as a test case with expected failures and a fixit comment so we don't forget about it?

Apart from that... is a complex bitint really something that should be supported? Not just in the new interpreter but generally?

I don't see why not; we support complex integer types and _BitInt is an integer type. We support _Complex from C in C++ and we support _BitInt from C in C++, so it seems reasonable to expect _Complex _BitInt to work.

This revision is now accepted and ready to land.Mar 29 2023, 7:02 AM
tbaeder updated this revision to Diff 509359.Mar 29 2023, 7:22 AM
tbaeder set the repository for this revision to rG LLVM Github Monorepo.
tbaeder added inline comments.
clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

I don't see why not; we support complex integer types and _BitInt is an integer type. We support _Complex from C in C++ and we support _BitInt from C in C++, so it seems reasonable to expect _Complex _BitInt to work.

My immediate reaction to something like _Complex is "this is stupid, this belongs in user code". For floating-point values it at least makes sense from a mathematical POV I guess. But complex ints is already weird and complex arbitrary-width integers? What's the use case? _Complex bool is rejected as well after all.

108 ↗(On Diff #509021)

We'll have to deal with _BitInt at some point, so maybe we can add this as a test case with expected failures and a fixit comment so we don't forget about it?

It's running into an assertion for the test case, so I added it commented-out.

aaron.ballman added inline comments.Mar 29 2023, 7:42 AM
clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

My immediate reaction to something like _Complex is "this is stupid, this belongs in user code". For floating-point values it at least makes sense from a mathematical POV I guess. But complex ints is already weird and complex arbitrary-width integers? What's the use case? _Complex bool is rejected as well after all.

How would you explain this?

_Complex int32_t Val; // OK
_Complex _BitInt(32) OtherVal; // Not OK

The use case is the same as for _Complex int, just with getting to pick the width you want to use, which users can already do for some specific widths. Neither is a particularly strong motivation (to me anyway!), but I can't see why we'd allow a 32-bit integer but not a 32-bit (et al) precise integer.

tbaeder added inline comments.Mar 29 2023, 7:52 AM
clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

Sure, the bitint one is just a bit crazier, I was hoping we could draw the line a little earlier and save ourselves some headaches, but this doesn't seem to be a problem in the current interpreter.

With constexpr being in c++ now and c++20 having enough to implement complex numbers in user code anyway, are there any plans to deprecate _Complex in c++20 onward (not sure about C2x)? That doesn't help me of course but it would maybe give me more hope for the future :)

aaron.ballman added inline comments.Mar 29 2023, 7:58 AM
clang/lib/AST/Interp/PrimType.h
108 ↗(On Diff #509021)

C++ has std::complex as the official API for complex numbers (http://eel.is/c++draft/complex.numbers), but we expose _Complex in C++ as an extension because it makes it easier to ensure you're getting the same ABI between C and C++ with that datatype. (That said, I've always had the impression that std::complex and _Complex are intended to be ABI compatible in practice, but there's nothing in the C++ standard that requires it.) I'm not certain that we'd want to deprecate support for _Complex in C++ without plenty of investigation into whether it's used in practice or not.

As for deprecating _Complex in C, I'd be surprised but stranger things have happened.

This revision was landed with ongoing or failed builds.Thu, Dec 14, 2:58 AM
This revision was automatically updated to reflect the committed changes.