Repository: rust
Issue: .rodata bloat with aligned zero sized objects
Labels: A-linkage,C-bug,C-optimization

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

I tried this code:

```rust
#![allow(unused_variables, unused_mut)]

#[repr(align(0x200000))]
pub struct Page2MiB;

pub fn main() {
    // Version a: .rodata size <<<<< 0x200000
    let mut slice = [0u8];

    // Version b: .rodata size > 0x200000
    let mut slice = vec![0u8]; let slice = slice.as_mut_slice();

    let (pre, middle, post) = unsafe { slice.align_to_mut::<Page2MiB>() };
    dbg!(pre.len(), middle.len(), post.len());
}
```

Edit: which can be further reduced to:
```rust
pub fn main() {
    #[repr(align(0x200000))]
    pub struct Aligned;
    dbg!();
    let slice: &mut [Aligned; 0] = &mut [];
    dbg!(slice.as_ptr());
}
```

I expected to see this happen:
```console
$ rustc main.rs && size -A main | fgrep .rodata
.rodata                   17449   2097152
```
A reasonable section size of `.rodata`, like if `Version b` is commented out.

Instead, this happened:
```console
$ rustc main.rs && size -A main | fgrep .rodata
.rodata                 2114473   2097152
```

A `.rodata` section with over 2MB.

With this minimal example, `opt-level` makes it go away, but with more complex code it does not.

The culprit is:
```console
$ rustc --emit=asm main.rs && egrep -5 'p2align[[:space:]]+21' main.s
	.asciz	"k\000\000\000\000\000\000\000[\004\000\000\035\000\000"
	.size	.L__unnamed_3, 24

	.type	.L__unnamed_19,@object
	.section	.rodata..L__unnamed_19,"a",@progbits
	.p2align	21
.L__unnamed_19:
	.size	.L__unnamed_19, 0

	.type	.L__unnamed_4,@object
	.section	.data.rel.ro..L__unnamed_4,"aw",@progbits
```

So, we have a zero-sized object, but an alignment was forced.
I don't know, if this is an LLVM bug.

```console
$ rustc --emit=llvm-ir main.rs && grep 'align 2097152' main.ll
@alloc162 = private unnamed_addr constant <{ [0 x i8] }> zeroinitializer, align 2097152
define internal i64 @"_ZN4core5slice29_$LT$impl$u20$$u5b$T$u5d$$GT$3len17h52545189b0701658E"([0 x %Page2MiB]* noalias nonnull readonly align 2097152 %self.0, i64 %self.1) unnamed_addr #1 {
  %_45 = call i64 @"_ZN4core5slice29_$LT$impl$u20$$u5b$T$u5d$$GT$3len17h52545189b0701658E"([0 x %Page2MiB]* noalias nonnull readonly align 2097152 %middle.0, i64 %middle.1)
```

Again, zero-sized, but with `align 2097152`.

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc --version --verbose
rustc 1.45.2 (d3fb005a3 2020-07-31)
binary: rustc
commit-hash: d3fb005a39e62501b8b0b356166e515ae24e2e54
commit-date: 2020-07-31
host: x86_64-unknown-linux-gnu
release: 1.45.2
LLVM version: 10.0
```

and nightly:
```
$ rustc +nightly -Vv
rustc 1.47.0-nightly (18f3be770 2020-08-09)
binary: rustc
commit-hash: 18f3be7704a4ec7976fcd1272c728974243d29bd
commit-date: 2020-08-09
host: x86_64-unknown-linux-gnu
release: 1.47.0-nightly
LLVM version: 10.0
```

</p>
</details>