Skip to content

LLVM lint: Memory reference address is misaligned #28912

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

Closed
sanxiyn opened this issue Oct 8, 2015 · 4 comments
Closed

LLVM lint: Memory reference address is misaligned #28912

sanxiyn opened this issue Oct 8, 2015 · 4 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.

Comments

@sanxiyn
Copy link
Member

sanxiyn commented Oct 8, 2015

This is a subissue of #7463.

pub enum H<A, B> {
    L(A),
    R(B),
}
pub fn test() -> H<i32, i64> {
    H::L(0)
}

Compile with rustc -C passes=lint and you get:

Undefined behavior: Memory reference address is misaligned
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* getelementptr inbounds ({ i8, i32, [8 x i8] }, { i8, i32, [8 x i8] }* @const3020, i32 0, i32 0), i64 16, i32 8, i1 false)

Manually setting alignment of const3020 to 8 in LLVM IR fixes the lint.

@sanxiyn sanxiyn added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Oct 8, 2015
@dotdash
Copy link
Contributor

dotdash commented Oct 8, 2015

Seems to be caused by using the sizing_type for alignment.

@dotdash
Copy link
Contributor

dotdash commented Oct 8, 2015

Oh, nevermind, I completely misread the problem here and confused it with a different issue. The alignment of the sizing type is fine and the right thing would indeed be to add the alignment info to the constant.

@sanxiyn
Copy link
Member Author

sanxiyn commented Oct 8, 2015

Eh, I am confused. Isn't the alignment of { i8, i32, [8 x i8] } 4, i32 being the most aligned? Then why are we passing 8 as alignment to memcpy intrinsic? Is this related to sizing type?

@dotdash
Copy link
Contributor

dotdash commented Oct 8, 2015

{ i8, i32, [8 x i8] } is just the specific representation for the L variant. The type H<i32, i64> is represented as %"H<i32, i64>" = type { i8, [7 x i8], [1 x i64] }, so its alignment is 8. And I think all our code deals with types rather than concrete variants when checking for alignment.

We could probably extend that to allow for better packing of constants in some cases, but I'm not sure whether that's worth the trouble.

dotdash added a commit to dotdash/rust that referenced this issue Oct 9, 2015
For enum variants, the default alignment for a specific variant might be
lower than the alignment of the enum type itself. In such cases we, for
example, generate memcpy calls with an alignment that's higher than the
alignment of the constant we copy from.

To avoid that, we need to explicitly set the required alignment on
constants.

Fixes rust-lang#28912.
bors added a commit that referenced this issue Oct 10, 2015
For enum variants, the default alignment for a specific variant might be
lower than the alignment of the enum type itself. In such cases we, for
example, generate memcpy calls with an alignment that's higher than the
alignment of the constant we copy from.

To avoid that, we need to explicitly set the required alignment on
constants.

Fixes #28912.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
Projects
None yet
Development

No branches or pull requests

2 participants