-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Incorrectly generated code for struct alignments #23431
Labels
A-codegen
Area: Code generation
Comments
To quote myself:
|
dotdash
added a commit
to dotdash/rust
that referenced
this issue
Apr 15, 2015
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
Manishearth
added a commit
to Manishearth/rust
that referenced
this issue
Apr 17, 2015
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
Manishearth
added a commit
to Manishearth/rust
that referenced
this issue
Apr 17, 2015
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
dotdash
added a commit
to dotdash/rust
that referenced
this issue
Apr 18, 2015
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
Manishearth
added a commit
to Manishearth/rust
that referenced
this issue
Apr 18, 2015
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The attached source produces code that misbehaves on some platforms that are picky about memory access alignment. The code should exit with code 2, but on both Emscripten-generated JavaScript and ARMv5, it finishes with exit code 1 to indicate that the
en
field is incorrectly tested as equal toEnum::A
. Changing theval
field to au32
type results in proper execution on these platforms. All optimization levels seem to cause it.Libraries that make use of structs with
u8
fields followed by enums seem particularly prone to this problem. It all works fine on platforms that allow unaligned memory access like x86, ARMv6, etc.Expected output: (x86, ARMv6)
Actual output: (ARMv5, Emscripten)
Note that the same ARM binary runs on both ARMv5 and ARMv6 platforms, producing the different results.
See also: emscripten-core/emscripten#3261
Generated LLVM IR (
println!()
andderive(Debug)
removed)The text was updated successfully, but these errors were encountered: