Commit Graph

16 Commits

Author SHA1 Message Date
Nikita Popov
c2fd26a115 Separate immediate and in-memory ScalarPair representation
Currently, we assume that ScalarPair is always represented using
a two-element struct, both as an immediate value and when stored
in memory.

This currently works fairly well, but runs into problems with
https://github.com/rust-lang/rust/pull/116672, where a ScalarPair
involving an i128 type can no longer be represented as a two-element
struct in memory. For example, the tuple `(i32, i128)` needs to be
represented in-memory as `{ i32, [3 x i32], i128 }` to satisfy
alignment requirement. Using `{ i32, i128 }` instead will result in
the second element being stored at the wrong offset (prior to
LLVM 18).

Resolve this issue by no longer requiring that the immediate and
in-memory type for ScalarPair are the same. The in-memory type
will now look the same as for normal struct types (and will include
padding filler and similar), while the immediate type stays a
simple two-element struct type. This also means that booleans in
immediate ScalarPair are now represented as i1 rather than i8,
just like we do everywhere else.

The core change here is to llvm_type (which now treats ScalarPair
as a normal struct) and immediate_llvm_type (which returns the
two-element struct that llvm_type used to produce). The rest is
fixing things up to no longer assume these are the same. In
particular, this switches places that try to get pointers to the
ScalarPair elements to use byte-geps instead of struct-geps.
2023-12-15 17:42:05 +01:00
Scott McMurray
502af03445 Add a new compare_bytes intrinsic instead of calling memcmp directly 2023-08-06 15:47:40 -07:00
Josh Stone
da47736f42 CHECK only for opaque ptr 2023-07-27 14:44:13 -07:00
Josh Stone
190ded8443 Update the minimum external LLVM to 15 2023-07-27 14:07:08 -07:00
Camille GILLOT
d7983a2f23 Always name the return place. 2023-07-08 15:38:40 +02:00
Scott McMurray
bf36193ef6 Add a distinct OperandValue::ZeroSized variant for ZSTs
These tend to have special handling in a bunch of places anyway, so the variant helps remember that.  And I think it's easier to grok than non-Scalar Aggregates sometimes being `Immediates` (like I got wrong and caused 109992).  As a minor bonus, it means we don't need to generate poison LLVM values for them to pass around in `OperandValue::Immediate`s.
2023-05-31 19:10:28 -07:00
Scott McMurray
e1da77c76d Also use mir::Offset for pointer add 2023-04-27 22:44:42 -07:00
Scott McMurray
1de2257c3f Add intrinsics::transmute_unchecked
This takes a whole 3 lines in `compiler/` since it lowers to `CastKind::Transmute` in MIR *exactly* the same as the existing `intrinsics::transmute` does, it just doesn't have the fancy checking in `hir_typeck`.

Added to enable experimenting with the request in <https://github.com/rust-lang/rust/pull/106281#issuecomment-1496648190> and because the portable-simd folks might be interested for dependently-sized array-vector conversions.

It also simplifies a couple places in `core`.
2023-04-22 17:22:03 -07:00
Scott McMurray
1bcb0ec28c assume value ranges in transmute
Fixes #109958
2023-04-13 00:12:39 -07:00
Scott McMurray
d757c4b904 Handle not all immediates having abi::Scalars 2023-04-09 11:16:50 -07:00
Scott McMurray
454bca514a Check CastKind::Transmute sizes in a better way
Fixes #110005
2023-04-06 13:53:10 -07:00
Scott McMurray
9aa9a846b6 Allow transmutes to produce OperandValues instead of always using allocas
LLVM can usually optimize these away, but especially for things like transmutes of newtypes it's silly to generate the `alloc`+`store`+`load` at all when it's actually a nop at LLVM level.
2023-04-04 18:44:29 -07:00
Scott McMurray
64cce5fc7d Add CastKind::Transmute to MIR
Updates `interpret`, `codegen_ssa`, and `codegen_cranelift` to consume the new cast instead of the intrinsic.

Includes `CastTransmute` for custom MIR building, to be able to test the extra UB.
2023-03-22 15:15:41 -07:00
Nilstrieb
f1255380ac Add more codegen tests 2023-01-17 16:23:22 +01:00
Nilstrieb
645c0fddd2 Put noundef on all scalars that don't allow uninit
Previously, it was only put on scalars with range validity invariants
like bool, was uninit was obviously invalid for those.

Since then, we have normatively declared all uninit primitives to be
undefined behavior and can therefore put `noundef` on them.

The remaining concern was the `mem::uninitialized` function, which cause
quite a lot of UB in the older parts of the ecosystem. This function now
doesn't return uninit values anymore, making users of it safe from this
change.

The only real sources of UB where people could encounter uninit
primitives are `MaybeUninit::uninit().assume_init()`, which has always
be clear in the docs about being UB and from heap allocations (like
reading from the spare capacity of a vec. This is hopefully rare enough
to not break anything.
2023-01-17 08:14:35 +01:00
Albert Larsan
cf2dff2b1e
Move /src/test to /tests 2023-01-11 09:32:08 +00:00