Skip to content
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

emit "align 1" metadata on loads/stores of packed structs #39586

Merged
merged 5 commits into from
Feb 9, 2017

Conversation

arielb1
Copy link
Contributor

@arielb1 arielb1 commented Feb 6, 2017

According to the LLVM reference:

A value of 0 or an omitted align argument means that the operation has
the ABI alignment for the target.

So loads/stores of fields of packed structs need to have their align set
to 1. Implement that by tracking the alignment of LvalueRefs.

Fixes #39376.

r? @eddyb

@@ -243,7 +245,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
bcx.volatile_store(llargs[2], get_meta(bcx, llargs[0]));
} else {
let val = if fn_ty.args[1].is_indirect() {
bcx.load(llargs[1])
bcx.load(llargs[1], None) // FIXME: this is incorrect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to do something about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hard to fix without a refactor.

@eddyb
Copy link
Member

eddyb commented Feb 6, 2017

LGTM, except for that one FIXME. f? @Aatch, r=me if no concerns remain.

@arielb1
Copy link
Contributor Author

arielb1 commented Feb 6, 2017

And the FIXME turned out to be unneeded - ABI indirect arguments are always aligned.

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Feb 6, 2017

📌 Commit 56591f6 has been approved by eddyb

@Aatch
Copy link
Contributor

Aatch commented Feb 6, 2017

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Feb 6, 2017

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Contributor

bors commented Feb 6, 2017

📌 Commit 56591f6 has been approved by eddyb

@arielb1
Copy link
Contributor Author

arielb1 commented Feb 6, 2017

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Feb 6, 2017

📌 Commit 67789c4 has been approved by eddyb

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Feb 7, 2017
emit "align 1" metadata on loads/stores of packed structs

According to the LLVM reference:
> A value of 0 or an omitted align argument means that the operation has
the ABI alignment for the target.

So loads/stores of fields of packed structs need to have their align set
to 1. Implement that by tracking the alignment of `LvalueRef`s.

Fixes rust-lang#39376.

r? @eddyb
According to the LLVM reference:
> A value of 0 or an omitted align argument means that the operation has
the ABI alignment for the target.

So loads/stores of fields of packed structs need to have their align set
to 1. Implement that by tracking the alignment of `LvalueRef`s.

Fixes rust-lang#39376.
The function was a footgun because it created `undef` references to
ZSTs, which could cause trouble were they to leak to user code.
@arielb1
Copy link
Contributor Author

arielb1 commented Feb 8, 2017

rebased

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Feb 8, 2017

📌 Commit d71988a has been approved by eddyb

bors added a commit that referenced this pull request Feb 8, 2017
Rollup of 6 pull requests

- Successful merges: #38165, #39456, #39587, #39589, #39598, #39641
- Failed merges: #39586, #39595
@binarycrusader
Copy link
Contributor

binarycrusader commented Feb 9, 2017

Unfortunately, this patch doesn't seem to resolve the issue fully. See #39376 for an example test case that appears to still fail.

Note that brute force hack patch also mentioned in the bug there that does resolve the issue for the test case shown.

@binarycrusader
Copy link
Contributor

binarycrusader commented Feb 9, 2017

This is seen in the RUST_LOG=4 output when building the referenced example:

DEBUG:rustc_trans::mir::operand: trans_operand(operand=_15)
DEBUG:rustc_trans::mir::operand: trans_consume(lvalue=_15)
DEBUG:rustc_trans::mir::lvalue: trans_lvalue(lvalue=(*(*_4))[_15]) => LvalueRef { llval: 0x154f0e0, llextra: 0x0, ty: Ty { ty: Unaligned<u32> }, alignment: AbiAligned }
DEBUG:rustc_trans::mir::operand: trans_load: (%"Unaligned<u32>"*:  %26 = getelementptr inbounds %"Unaligned<u32>", %"Unaligned<u32>"* %23, i64 %13, !dbg !85) @ Unaligned<u32>
DEBUG:rustc_trans::mir::operand: store_operand: operand=OperandRef(Immediate((%"Unaligned<u32>" = type <{ i32 }>:  %27 = load %"Unaligned<u32>", %"Unaligned<u32>"* %26, !dbg !85)) @ Unaligned<u32>), align=None
DEBUG:rustc_trans::builder: Store (%"Unaligned<u32>" = type <{ i32 }>:  %27 = load %"Unaligned<u32>", %"Unaligned<u32>"* %26, !dbg !85) -> (%"Unaligned<u32>"*:  %_14 = alloca %"Unaligned<u32>")

@arielb1
Copy link
Contributor Author

arielb1 commented Feb 9, 2017

@binarycrusader

I compile your example using your patch - that's it,

use std::slice;
use std::u32;

#[repr(packed)]
#[derive(Copy, Clone)]
struct Unaligned<T>(T);

impl<T> Unaligned<T> {
    fn get(self) -> T { self.0 }
}

fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
}

fn main() {
        let values = String::from("fedcba98765432100123456789abcdef");
        let bytes = values.as_bytes();
        let mut words = &bytes_to_words(&bytes[1..]);
        let index = 1;
        let position = u32::from_le(words[index].get());
}

and it works (emits align metadata on the necessary loads).

Is there some other example you are talking about?

Immediate((%"Unaligned" = type <{ i32 }>: %27 = load %"Unaligned", %"Unaligned"* %26, !dbg !85)) @ Unaligned

We should not be having this (immediate Unaligned<u32>) in code. Are you using some old version of rustc with my patch applied?

@bors
Copy link
Contributor

bors commented Feb 9, 2017

⌛ Testing commit d71988a with merge b0e46f0...

bors added a commit that referenced this pull request Feb 9, 2017
emit "align 1" metadata on loads/stores of packed structs

According to the LLVM reference:
> A value of 0 or an omitted align argument means that the operation has
the ABI alignment for the target.

So loads/stores of fields of packed structs need to have their align set
to 1. Implement that by tracking the alignment of `LvalueRef`s.

Fixes #39376.

r? @eddyb
@bors
Copy link
Contributor

bors commented Feb 9, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: eddyb
Pushing b0e46f0 to master...

@binarycrusader
Copy link
Contributor

Would someone be willing to beta-nominate this? This patch has been used successfully against 1.16 beta for almost two weeks and resolved the last code generation issue we encountered on sparc (and I suspect would help other architectures too). I believe it applies cleanly without any changes to current beta tip.

@eddyb eddyb added the beta-nominated Nominated for backporting to the compiler in the beta channel. label Feb 21, 2017
@alexcrichton alexcrichton added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Feb 21, 2017
@brson brson added the beta-accepted Accepted for backporting to the compiler in the beta channel. label Feb 23, 2017
@brson brson mentioned this pull request Feb 23, 2017
@alexcrichton alexcrichton removed the beta-nominated Nominated for backporting to the compiler in the beta channel. label Feb 23, 2017
bors added a commit that referenced this pull request Mar 2, 2017
[beta] next

- #39913
- #39730
- #39674
- #39602
- #39586
- #39471
- #39980
- #40020
- #40135

@nikomatsakis [this commit](3787d33) did not pick cleanly. You might peek at it.

I took the liberty of accepting all the nominations myself, but the [packed struct alignment](#39586) PR is quite large. It did pick fine though and there's a comment there suggesting it works on beta cc @rust-lang/compiler.

cc @alexcrichton
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beta-accepted Accepted for backporting to the compiler in the beta channel. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants