Skip to content

Commit 559c135

Browse files
committed
Tests of -Z print-type-sizes functionality.
Note that the tests have been updated to initialize the local variables; originally it was enough just to declare them. Back when I started this, the `layout_cache` contained entries even just for types that had been declared but not initialized. Apparently things have changed in the interim so that if I want one of those layouts to be computed, I need to actually initialize the value. (Incidentally, this shows a weakness in the strategy of just walking the `layout_cache`; the original strategy of using a MIR visitor would probably have exhibited more robustness in terms of consistent output, but it had other weaknesses so I chose not to reimplement it. At least, not yet.)
1 parent cf2d375 commit 559c135

15 files changed

+425
-0
lines changed
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// All of the types that occur in this function are uninteresting, in
12+
// that one cannot control the sizes of these types with the same sort
13+
// of enum-variant manipulation tricks.
14+
15+
pub fn main() {
16+
let _byte: u8 = Default::default();
17+
let _word: usize = Default::default();
18+
let _tuple: (u8, usize)= Default::default();
19+
let _array: [u8; 128] = [0; 128];
20+
let _fn: fn (u8) -> u8 = id;
21+
let _diverging: fn (u8) -> ! = bye;
22+
23+
fn id(x: u8) -> u8 { x };
24+
fn bye(_: u8) -> ! { loop { } }
25+
}
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates how generics are handled: types have to be
14+
// monomorphized, in the MIR of the original function in which they
15+
// occur, to have their size reported.
16+
17+
// In an ad-hoc attempt to avoid the injection of unwinding code
18+
// (which clutters the output of `-Z print-type-sizes` with types from
19+
// `unwind::libunwind`):
20+
//
21+
// * I am not using Default to build values because that seems to
22+
// cause the injection of unwinding code. (Instead I just make `fn new`
23+
// methods.)
24+
//
25+
// * Pair derive Copy to ensure that we don't inject
26+
// unwinding code into generic uses of Pair when T itself is also
27+
// Copy.
28+
//
29+
// (I suspect this reflect some naivety within the rust compiler
30+
// itself; it should be checking for drop glue, i.e. a destructor
31+
// somewhere in the monomorphized types. It should not matter whether
32+
// the type is Copy.)
33+
#[derive(Copy, Clone)]
34+
pub struct Pair<T> {
35+
_car: T,
36+
_cdr: T,
37+
}
38+
39+
impl<T> Pair<T> {
40+
fn new(a: T, d: T) -> Self {
41+
Pair {
42+
_car: a,
43+
_cdr: d,
44+
}
45+
}
46+
}
47+
48+
#[derive(Copy, Clone)]
49+
pub struct SevenBytes([u8; 7]);
50+
pub struct FiftyBytes([u8; 50]);
51+
52+
pub struct ZeroSized;
53+
54+
impl SevenBytes {
55+
fn new() -> Self { SevenBytes([0; 7]) }
56+
}
57+
58+
impl FiftyBytes {
59+
fn new() -> Self { FiftyBytes([0; 50]) }
60+
}
61+
62+
pub fn f1<T:Copy>(x: T) {
63+
let _v: Pair<T> = Pair::new(x, x);
64+
let _v2: Pair<FiftyBytes> =
65+
Pair::new(FiftyBytes::new(), FiftyBytes::new());
66+
}
67+
68+
pub fn main() {
69+
let _b: Pair<u8> = Pair::new(0, 0);
70+
let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
71+
let _z: ZeroSized = ZeroSized;
72+
f1::<SevenBytes>(SevenBytes::new());
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
print-type-size type: `Pair<FiftyBytes>`: 100 bytes, alignment: 1 bytes
2+
print-type-size field `._car`: 50 bytes
3+
print-type-size field `._cdr`: 50 bytes
4+
print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
5+
print-type-size field `.0`: 50 bytes
6+
print-type-size type: `Pair<SevenBytes>`: 14 bytes, alignment: 1 bytes
7+
print-type-size field `._car`: 7 bytes
8+
print-type-size field `._cdr`: 7 bytes
9+
print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
10+
print-type-size field `.0`: 7 bytes
11+
print-type-size type: `Pair<u8>`: 2 bytes, alignment: 1 bytes
12+
print-type-size field `._car`: 1 bytes
13+
print-type-size field `._cdr`: 1 bytes
14+
print-type-size type: `ZeroSized`: 0 bytes, alignment: 1 bytes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates that when multiple structural types occur in
14+
// a function, every one of them is included in the output.
15+
16+
pub struct SevenBytes([u8; 7]);
17+
pub struct FiftyBytes([u8; 50]);
18+
19+
pub enum Enum {
20+
Small(SevenBytes),
21+
Large(FiftyBytes),
22+
}
23+
24+
pub fn main() {
25+
let _e: Enum;
26+
let _f: FiftyBytes;
27+
let _s: SevenBytes;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
2+
print-type-size discriminant: 1 bytes
3+
print-type-size variant `Small`: 7 bytes
4+
print-type-size field `.0`: 7 bytes
5+
print-type-size variant `Large`: 50 bytes
6+
print-type-size field `.0`: 50 bytes
7+
print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
8+
print-type-size field `.0`: 50 bytes
9+
print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
10+
print-type-size field `.0`: 7 bytes
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates that when the same type occurs repeatedly
14+
// (even if multiple functions), it is only printed once in the
15+
// print-type-sizes output.
16+
17+
pub struct SevenBytes([u8; 7]);
18+
19+
pub fn f1() {
20+
let _s: SevenBytes = SevenBytes([0; 7]);
21+
}
22+
23+
pub fn main() {
24+
let _s: SevenBytes = SevenBytes([0; 7]);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
2+
print-type-size field `.0`: 7 bytes
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates how enums with a non-null field are handled,
14+
// modelled after cases like `Option<&u32>` and such.
15+
//
16+
// It uses NonZero directly, rather than `&_` or `Unique<_>`, because
17+
// the test is not set up to deal with target-dependent pointer width.
18+
19+
#![feature(nonzero)]
20+
#![allow(dead_code)]
21+
22+
extern crate core;
23+
use core::nonzero::{NonZero, Zeroable};
24+
25+
pub enum MyOption<T> { None, Some(T) }
26+
27+
impl<T> Default for MyOption<T> {
28+
fn default() -> Self { MyOption::None }
29+
}
30+
31+
pub enum EmbeddedDiscr {
32+
None,
33+
Record { pre: u64, val: NonZero<u64>, post: u64 },
34+
}
35+
36+
impl Default for EmbeddedDiscr {
37+
fn default() -> Self { EmbeddedDiscr::None }
38+
}
39+
40+
#[derive(Default)]
41+
pub struct IndirectNonZero<T: Zeroable> {
42+
pre: u64,
43+
nested: NestedNonZero<T>,
44+
post: u64,
45+
}
46+
47+
pub struct NestedNonZero<T: Zeroable> {
48+
pre: u64,
49+
val: NonZero<T>,
50+
post: u64,
51+
}
52+
53+
impl<T: Zeroable+Default> Default for NestedNonZero<T> {
54+
fn default() -> Self {
55+
unsafe {
56+
NestedNonZero { pre: 0, val: NonZero::new(Default::default()), post: 0 }
57+
}
58+
}
59+
}
60+
61+
pub fn main() {
62+
let _x: MyOption<NonZero<u64>> = Default::default();
63+
let _y: EmbeddedDiscr = Default::default();
64+
let _z: MyOption<IndirectNonZero<u32>> = Default::default();
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
print-type-size type: `IndirectNonZero<u32>`: 40 bytes, alignment: 8 bytes
2+
print-type-size field `.pre`: 8 bytes
3+
print-type-size field `.nested`: 24 bytes
4+
print-type-size field `.post`: 8 bytes
5+
print-type-size type: `MyOption<IndirectNonZero<u32>>`: 40 bytes, alignment: 8 bytes
6+
print-type-size variant `Some`: 40 bytes
7+
print-type-size field `.0`: 40 bytes
8+
print-type-size type: `EmbeddedDiscr`: 24 bytes, alignment: 8 bytes
9+
print-type-size variant `Record`: 24 bytes
10+
print-type-size field `.pre`: 8 bytes
11+
print-type-size field `.val`: 8 bytes
12+
print-type-size field `.post`: 8 bytes
13+
print-type-size type: `NestedNonZero<u32>`: 24 bytes, alignment: 8 bytes
14+
print-type-size field `.pre`: 8 bytes
15+
print-type-size field `.val`: 4 bytes
16+
print-type-size padding bytes: 4
17+
print-type-size field `.post`: 8 bytes, alignment: 8 bytes
18+
print-type-size type: `MyOption<core::nonzero::NonZero<u64>>`: 8 bytes, alignment: 8 bytes
19+
print-type-size variant `Some`: 8 bytes
20+
print-type-size field `.0`: 8 bytes
21+
print-type-size type: `core::nonzero::NonZero<u64>`: 8 bytes, alignment: 8 bytes
22+
print-type-size field `.0`: 8 bytes
23+
print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes
24+
print-type-size field `.0`: 4 bytes
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates how packing is handled; it should cause
14+
// the elimination of padding that would normally be introduced
15+
// to satisfy alignment desirata.
16+
17+
#![feature(untagged_unions)]
18+
19+
#![allow(dead_code)]
20+
21+
#[derive(Default)]
22+
#[repr(packed)]
23+
struct Packed {
24+
a: bool,
25+
b: bool,
26+
g: i32,
27+
c: bool,
28+
w: i64,
29+
d: bool,
30+
}
31+
32+
#[derive(Default)]
33+
struct Padded {
34+
a: bool,
35+
b: bool,
36+
g: i32,
37+
c: bool,
38+
w: i64,
39+
d: bool,
40+
}
41+
42+
pub fn main() {
43+
let _c: Packed = Default::default();
44+
let _d: Padded = Default::default();
45+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
print-type-size type: `Padded`: 32 bytes, alignment: 8 bytes
2+
print-type-size field `.a`: 1 bytes
3+
print-type-size field `.b`: 1 bytes
4+
print-type-size padding bytes: 2
5+
print-type-size field `.g`: 4 bytes, alignment: 4 bytes
6+
print-type-size field `.c`: 1 bytes
7+
print-type-size padding bytes: 7
8+
print-type-size field `.w`: 8 bytes, alignment: 8 bytes
9+
print-type-size field `.d`: 1 bytes
10+
print-type-size end padding bytes: 7
11+
print-type-size type: `Packed`: 16 bytes, alignment: 1 bytes
12+
print-type-size field `.a`: 1 bytes
13+
print-type-size field `.b`: 1 bytes
14+
print-type-size field `.g`: 4 bytes
15+
print-type-size field `.c`: 1 bytes
16+
print-type-size field `.w`: 8 bytes
17+
print-type-size field `.d`: 1 bytes
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z print-type-sizes
12+
13+
// This file illustrates how padding is handled: alignment
14+
// requirements can lead to the introduction of padding, either before
15+
// fields or at the end of the structure as a whole.
16+
17+
#![allow(dead_code)]
18+
19+
struct S {
20+
a: bool,
21+
b: bool,
22+
g: i32,
23+
}
24+
25+
enum E1 {
26+
A(i64, i32),
27+
B(S),
28+
}
29+
30+
enum E2 {
31+
A(i32, i64),
32+
B(S),
33+
}
34+
35+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
print-type-size type: `E1`: 24 bytes, alignment: 8 bytes
2+
print-type-size discriminant: 4 bytes
3+
print-type-size variant `A`: 16 bytes
4+
print-type-size padding bytes: 4
5+
print-type-size field `.0`: 8 bytes, alignment: 8 bytes
6+
print-type-size field `.1`: 4 bytes
7+
print-type-size variant `B`: 8 bytes
8+
print-type-size field `.0`: 8 bytes
9+
print-type-size end padding bytes: 4
10+
print-type-size type: `E2`: 16 bytes, alignment: 8 bytes
11+
print-type-size discriminant: 4 bytes
12+
print-type-size variant `A`: 12 bytes
13+
print-type-size field `.0`: 4 bytes
14+
print-type-size field `.1`: 8 bytes
15+
print-type-size variant `B`: 8 bytes
16+
print-type-size field `.0`: 8 bytes
17+
print-type-size type: `S`: 8 bytes, alignment: 4 bytes
18+
print-type-size field `.a`: 1 bytes
19+
print-type-size field `.b`: 1 bytes
20+
print-type-size padding bytes: 2
21+
print-type-size field `.g`: 4 bytes, alignment: 4 bytes

0 commit comments

Comments
 (0)