Skip to content

Commit 5d01f64

Browse files
committedApr 10, 2013
auto merge of #5816 : dbaupp/rust/rustc-packed-v2, r=nikomatsakis
#5758 take 2. This adds a `#[packed]` attribute for structs, like GCC's `__attribute__((packed))`, e.g. ```rust #[packed] struct Size5 { a: u8, b: u32 } ``` It works on normal and tuple structs, but is (silently) ignored on enums. Closes #1704.
2 parents a425b75 + 7d7e149 commit 5d01f64

22 files changed

+521
-71
lines changed
 

‎src/librustc/middle/trans/adt.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub enum Repr {
8888
struct Struct {
8989
size: u64,
9090
align: u64,
91+
packed: bool,
9192
fields: ~[ty::t]
9293
}
9394

@@ -109,17 +110,18 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
109110
}
110111
let repr = @match ty::get(t).sty {
111112
ty::ty_tup(ref elems) => {
112-
Univariant(mk_struct(cx, *elems), false)
113+
Univariant(mk_struct(cx, *elems, false), false)
113114
}
114115
ty::ty_struct(def_id, ref substs) => {
115116
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
116117
let ftys = do fields.map |field| {
117118
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
118119
};
120+
let packed = ty::lookup_packed(cx.tcx, def_id);
119121
let dtor = ty::ty_dtor(cx.tcx, def_id).is_present();
120122
let ftys =
121123
if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { ftys };
122-
Univariant(mk_struct(cx, ftys), dtor)
124+
Univariant(mk_struct(cx, ftys, packed), dtor)
123125
}
124126
ty::ty_enum(def_id, ref substs) => {
125127
struct Case { discr: int, tys: ~[ty::t] };
@@ -132,15 +134,15 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
132134
};
133135
if cases.len() == 0 {
134136
// Uninhabitable; represent as unit
135-
Univariant(mk_struct(cx, ~[]), false)
137+
Univariant(mk_struct(cx, ~[], false), false)
136138
} else if cases.all(|c| c.tys.len() == 0) {
137139
// All bodies empty -> intlike
138140
let discrs = cases.map(|c| c.discr);
139141
CEnum(discrs.min(), discrs.max())
140142
} else if cases.len() == 1 {
141143
// Equivalent to a struct/tuple/newtype.
142144
assert!(cases[0].discr == 0);
143-
Univariant(mk_struct(cx, cases[0].tys), false)
145+
Univariant(mk_struct(cx, cases[0].tys, false), false)
144146
} else {
145147
// The general case. Since there's at least one
146148
// non-empty body, explicit discriminants should have
@@ -151,7 +153,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
151153
ty::item_path_str(cx.tcx, def_id)))
152154
}
153155
let discr = ~[ty::mk_int(cx.tcx)];
154-
General(cases.map(|c| mk_struct(cx, discr + c.tys)))
156+
General(cases.map(|c| mk_struct(cx, discr + c.tys, false)))
155157
}
156158
}
157159
_ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
@@ -160,12 +162,13 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
160162
return repr;
161163
}
162164

163-
fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
165+
fn mk_struct(cx: @CrateContext, tys: &[ty::t], packed: bool) -> Struct {
164166
let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
165-
let llty_rec = T_struct(lltys);
167+
let llty_rec = T_struct(lltys, packed);
166168
Struct {
167169
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
168170
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
171+
packed: packed,
169172
fields: vec::from_slice(tys)
170173
}
171174
}
@@ -358,7 +361,8 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
358361

359362
let val = if needs_cast {
360363
let real_llty = T_struct(st.fields.map(
361-
|&ty| type_of::type_of(ccx, ty)));
364+
|&ty| type_of::type_of(ccx, ty)),
365+
st.packed);
362366
PointerCast(bcx, val, T_ptr(real_llty))
363367
} else {
364368
val

‎src/librustc/middle/trans/asm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -108,7 +108,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
108108
} else if numOutputs == 1 {
109109
val_ty(outputs[0])
110110
} else {
111-
T_struct(outputs.map(|o| val_ty(*o)))
111+
T_struct(outputs.map(|o| val_ty(*o)), false)
112112
};
113113
114114
let dialect = match ia.dialect {

‎src/librustc/middle/trans/base.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -938,7 +938,7 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
938938
// The landing pad return type (the type being propagated). Not sure what
939939
// this represents but it's determined by the personality function and
940940
// this is what the EH proposal example uses.
941-
let llretty = T_struct(~[T_ptr(T_i8()), T_i32()]);
941+
let llretty = T_struct(~[T_ptr(T_i8()), T_i32()], false);
942942
// The exception handling personality function. This is the C++
943943
// personality function __gxx_personality_v0, wrapped in our naming
944944
// convention.
@@ -2837,7 +2837,7 @@ pub fn decl_gc_metadata(ccx: @CrateContext, llmod_id: &str) {
28372837
}
28382838
28392839
pub fn create_module_map(ccx: @CrateContext) -> ValueRef {
2840-
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
2840+
let elttype = T_struct(~[ccx.int_type, ccx.int_type], false);
28412841
let maptype = T_array(elttype, ccx.module_data.len() + 1);
28422842
let map = str::as_c_str(~"_rust_mod_map", |buf| {
28432843
unsafe {
@@ -2877,7 +2877,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
28772877
};
28782878
let sym_name = ~"_rust_crate_map_" + mapname;
28792879
let arrtype = T_array(int_type, n_subcrates as uint);
2880-
let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype]);
2880+
let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype], false);
28812881
let map = str::as_c_str(sym_name, |buf| {
28822882
unsafe {
28832883
llvm::LLVMAddGlobal(llmod, maptype, buf)

‎src/librustc/middle/trans/cabi_arm.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
1212
use lib::llvm::struct_tys;
1313
use lib::llvm::TypeRef;
1414
use lib::llvm::{Attribute, StructRetAttribute};
15+
use lib::llvm::True;
1516
use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
1617
use middle::trans::common::{T_i8, T_i16, T_i32, T_i64};
1718
use middle::trans::common::{T_array, T_ptr, T_void};
@@ -39,8 +40,12 @@ fn ty_align(ty: TypeRef) -> uint {
3940
Float => 4,
4041
Double => 8,
4142
Struct => {
42-
do vec::foldl(1, struct_tys(ty)) |a, t| {
43-
uint::max(a, ty_align(*t))
43+
if llvm::LLVMIsPackedStruct(ty) == True {
44+
1
45+
} else {
46+
do vec::foldl(1, struct_tys(ty)) |a, t| {
47+
uint::max(a, ty_align(*t))
48+
}
4449
}
4550
}
4651
Array => {
@@ -62,10 +67,16 @@ fn ty_size(ty: TypeRef) -> uint {
6267
Float => 4,
6368
Double => 8,
6469
Struct => {
65-
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
66-
align(s, *t) + ty_size(*t)
67-
};
68-
align(size, ty)
70+
if llvm::LLVMIsPackedStruct(ty) == True {
71+
do vec::foldl(0, struct_tys(ty)) |s, t| {
72+
s + ty_size(*t)
73+
}
74+
} else {
75+
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
76+
align(s, *t) + ty_size(*t)
77+
};
78+
align(size, ty)
79+
}
6980
}
7081
Array => {
7182
let len = llvm::LLVMGetArrayLength(ty) as uint;

‎src/librustc/middle/trans/cabi_mips.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -14,6 +14,7 @@ use core::libc::c_uint;
1414
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
1515
use lib::llvm::{Struct, Array, Attribute};
1616
use lib::llvm::{StructRetAttribute};
17+
use lib::llvm::True;
1718
use middle::trans::common::*;
1819
use middle::trans::cabi::*;
1920

@@ -49,8 +50,12 @@ fn ty_align(ty: TypeRef) -> uint {
4950
Float => 4,
5051
Double => 8,
5152
Struct => {
52-
do vec::foldl(1, struct_tys(ty)) |a, t| {
53-
uint::max(a, ty_align(*t))
53+
if llvm::LLVMIsPackedStruct(ty) == True {
54+
1
55+
} else {
56+
do vec::foldl(1, struct_tys(ty)) |a, t| {
57+
uint::max(a, ty_align(*t))
58+
}
5459
}
5560
}
5661
Array => {
@@ -72,10 +77,16 @@ fn ty_size(ty: TypeRef) -> uint {
7277
Float => 4,
7378
Double => 8,
7479
Struct => {
75-
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
76-
align(s, *t) + ty_size(*t)
77-
};
78-
align(size, ty)
80+
if llvm::LLVMIsPackedStruct(ty) == True {
81+
do vec::foldl(0, struct_tys(ty)) |s, t| {
82+
s + ty_size(*t)
83+
}
84+
} else {
85+
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
86+
align(s, *t) + ty_size(*t)
87+
};
88+
align(size, ty)
89+
}
7990
}
8091
Array => {
8192
let len = llvm::LLVMGetArrayLength(ty) as uint;
@@ -174,7 +185,7 @@ fn struct_ty(ty: TypeRef,
174185
fields.push(ty);
175186
}
176187

177-
return T_struct(fields);
188+
return T_struct(fields, false);
178189
}
179190

180191
enum MIPS_ABIInfo { MIPS_ABIInfo }

‎src/librustc/middle/trans/cabi_x86_64.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -15,6 +15,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
1515
use lib::llvm::{Struct, Array, Attribute};
1616
use lib::llvm::{StructRetAttribute, ByValAttribute};
1717
use lib::llvm::struct_tys;
18+
use lib::llvm::True;
1819
use middle::trans::common::*;
1920
use middle::trans::cabi::*;
2021

@@ -76,8 +77,12 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
7677
Float => 4,
7778
Double => 8,
7879
Struct => {
79-
do vec::foldl(1, struct_tys(ty)) |a, t| {
80+
if llvm::LLVMIsPackedStruct(ty) == True {
81+
1
82+
} else {
83+
do vec::foldl(1, struct_tys(ty)) |a, t| {
8084
uint::max(a, ty_align(*t))
85+
}
8186
}
8287
}
8388
Array => {
@@ -99,10 +104,16 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
99104
Float => 4,
100105
Double => 8,
101106
Struct => {
102-
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
107+
if llvm::LLVMIsPackedStruct(ty) == True {
108+
do vec::foldl(0, struct_tys(ty)) |s, t| {
109+
s + ty_size(*t)
110+
}
111+
} else {
112+
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
103113
align(s, *t) + ty_size(*t)
104-
};
105-
align(size, ty)
114+
};
115+
align(size, ty)
116+
}
106117
}
107118
Array => {
108119
let len = llvm::LLVMGetArrayLength(ty) as uint;
@@ -308,7 +319,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
308319
}
309320
i += 1u;
310321
}
311-
return T_struct(tys);
322+
return T_struct(tys, false);
312323
}
313324
}
314325

‎src/librustc/middle/trans/common.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -765,7 +765,7 @@ pub fn T_void() -> TypeRef {
765765
}
766766

767767
pub fn T_nil() -> TypeRef {
768-
return T_struct(~[])
768+
return T_struct(~[], false)
769769
}
770770

771771
pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
@@ -848,7 +848,7 @@ pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
848848
}
849849

850850
pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef {
851-
return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)]);
851+
return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
852852
}
853853

854854
pub fn T_ptr(t: TypeRef) -> TypeRef {
@@ -863,11 +863,11 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
863863
}
864864
}
865865

866-
pub fn T_struct(elts: &[TypeRef]) -> TypeRef {
866+
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
867867
unsafe {
868868
return llvm::LLVMStructType(to_ptr(elts),
869869
elts.len() as c_uint,
870-
False);
870+
packed as Bool);
871871
}
872872
}
873873

@@ -878,16 +878,16 @@ pub fn T_named_struct(name: &str) -> TypeRef {
878878
}
879879
}
880880

881-
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef]) {
881+
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
882882
unsafe {
883883
llvm::LLVMStructSetBody(t,
884884
to_ptr(elts),
885885
elts.len() as c_uint,
886-
False);
886+
packed as Bool);
887887
}
888888
}
889889

890-
pub fn T_empty_struct() -> TypeRef { return T_struct(~[]); }
890+
pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); }
891891

892892
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
893893
// to tydescs and other vtables that it closes over. But the types and number
@@ -913,7 +913,7 @@ pub fn T_task(targ_cfg: @session::config) -> TypeRef {
913913
let elems =
914914
~[t_int, t_int, t_int, t_int,
915915
t_int, t_int, t_int, t_int];
916-
set_struct_body(t, elems);
916+
set_struct_body(t, elems, false);
917917
return t;
918918
}
919919

@@ -956,7 +956,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
956956
~[int_type, int_type,
957957
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
958958
T_ptr(T_i8()), T_ptr(T_i8())];
959-
set_struct_body(tydesc, elems);
959+
set_struct_body(tydesc, elems, false);
960960
return tydesc;
961961
}
962962

@@ -969,8 +969,9 @@ pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
969969
// Interior vector.
970970
pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
971971
return T_struct(~[T_int(targ_cfg), // fill
972-
T_int(targ_cfg), // alloc
973-
T_array(t, 0u)]); // elements
972+
T_int(targ_cfg), // alloc
973+
T_array(t, 0u)], // elements
974+
false);
974975
}
975976

976977
pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef {
@@ -1001,11 +1002,11 @@ pub fn T_box_header_fields(cx: @CrateContext) -> ~[TypeRef] {
10011002
}
10021003

10031004
pub fn T_box_header(cx: @CrateContext) -> TypeRef {
1004-
return T_struct(T_box_header_fields(cx));
1005+
return T_struct(T_box_header_fields(cx), false);
10051006
}
10061007

10071008
pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef {
1008-
return T_struct(vec::append(T_box_header_fields(cx), ~[t]));
1009+
return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
10091010
}
10101011

10111012
pub fn T_box_ptr(t: TypeRef) -> TypeRef {
@@ -1023,7 +1024,7 @@ pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef {
10231024
}
10241025

10251026
pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef {
1026-
return T_struct(vec::append(T_box_header_fields(cx), ~[t]));
1027+
return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
10271028
}
10281029

10291030
pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
@@ -1033,12 +1034,12 @@ pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
10331034
}
10341035

10351036
pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef {
1036-
return T_struct(~[cx.int_type]); // Refcount
1037+
return T_struct(~[cx.int_type], false); // Refcount
10371038

10381039
}
10391040

10401041
pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef {
1041-
return T_struct(~[cx.int_type]); // Refcount
1042+
return T_struct(~[cx.int_type], false); // Refcount
10421043

10431044
}
10441045

@@ -1056,21 +1057,22 @@ pub fn T_enum_discrim(cx: @CrateContext) -> TypeRef {
10561057
}
10571058

10581059
pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef {
1059-
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
1060+
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
10601061
}
10611062

10621063
pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
10631064
match store {
10641065
ty::BoxTraitStore => {
1065-
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
1066+
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
10661067
}
10671068
ty::UniqTraitStore => {
10681069
T_struct(~[T_ptr(cx.tydesc_type),
10691070
T_unique_ptr(T_unique(cx, T_i8())),
1070-
T_ptr(cx.tydesc_type)])
1071+
T_ptr(cx.tydesc_type)],
1072+
false)
10711073
}
10721074
ty::RegionTraitStore(_) => {
1073-
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
1075+
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
10741076
}
10751077
}
10761078
}

‎src/librustc/middle/trans/foreign.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -106,7 +106,8 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes {
106106
};
107107
let llsig = foreign_signature(ccx, &fn_sig);
108108
let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys,
109-
T_ptr(llsig.llret_ty)));
109+
T_ptr(llsig.llret_ty)),
110+
false);
110111
let ret_def =
111112
!ty::type_is_bot(fn_sig.output) &&
112113
!ty::type_is_nil(fn_sig.output);

‎src/librustc/middle/trans/machine.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -142,9 +142,9 @@ pub fn static_size_of_enum(cx: @CrateContext, t: ty::t) -> uint {
142142

143143
debug!("static_size_of_enum: variant %s type %s",
144144
*cx.tcx.sess.str_of(variant.name),
145-
ty_str(cx.tn, T_struct(lltypes)));
145+
ty_str(cx.tn, T_struct(lltypes, false)));
146146

147-
let this_size = llsize_of_real(cx, T_struct(lltypes));
147+
let this_size = llsize_of_real(cx, T_struct(lltypes, false));
148148
if max_size < this_size {
149149
max_size = this_size;
150150
}

‎src/librustc/middle/trans/type_of.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -128,11 +128,11 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
128128

129129
ty::ty_estr(ty::vstore_slice(*)) |
130130
ty::ty_evec(_, ty::vstore_slice(*)) => {
131-
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())])
131+
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false)
132132
}
133133

134134
ty::ty_bare_fn(*) => T_ptr(T_i8()),
135-
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
135+
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false),
136136
ty::ty_trait(_, _, store) => T_opaque_trait(cx, store),
137137

138138
ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size),
@@ -142,9 +142,15 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
142142

143143
ty::ty_unboxed_vec(mt) => T_vec(cx, sizing_type_of(cx, mt.ty)),
144144

145-
ty::ty_tup(*) | ty::ty_struct(*) | ty::ty_enum(*) => {
145+
ty::ty_tup(*) | ty::ty_enum(*) => {
146146
let repr = adt::represent_type(cx, t);
147-
T_struct(adt::sizing_fields_of(cx, repr))
147+
T_struct(adt::sizing_fields_of(cx, repr), false)
148+
}
149+
150+
ty::ty_struct(did, _) => {
151+
let repr = adt::represent_type(cx, t);
152+
let packed = ty::lookup_packed(cx.tcx, did);
153+
T_struct(adt::sizing_fields_of(cx, repr), packed)
148154
}
149155

150156
ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
@@ -223,12 +229,14 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
223229

224230
ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
225231
T_struct(~[T_ptr(type_of(cx, mt.ty)),
226-
T_uint_ty(cx, ast::ty_u)])
232+
T_uint_ty(cx, ast::ty_u)],
233+
false)
227234
}
228235

229236
ty::ty_estr(ty::vstore_slice(_)) => {
230237
T_struct(~[T_ptr(T_i8()),
231-
T_uint_ty(cx, ast::ty_u)])
238+
T_uint_ty(cx, ast::ty_u)],
239+
false)
232240
}
233241

234242
ty::ty_estr(ty::vstore_fixed(n)) => {
@@ -245,7 +253,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
245253
ty::ty_type => T_ptr(cx.tydesc_type),
246254
ty::ty_tup(*) => {
247255
let repr = adt::represent_type(cx, t);
248-
T_struct(adt::fields_of(cx, repr))
256+
T_struct(adt::fields_of(cx, repr), false)
249257
}
250258
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
251259
ty::ty_struct(did, ref substs) => {
@@ -268,9 +276,17 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
268276

269277
// If this was an enum or struct, fill in the type now.
270278
match ty::get(t).sty {
271-
ty::ty_enum(*) | ty::ty_struct(*) => {
279+
ty::ty_enum(*) => {
272280
let repr = adt::represent_type(cx, t);
273-
common::set_struct_body(llty, adt::fields_of(cx, repr));
281+
common::set_struct_body(llty, adt::fields_of(cx, repr),
282+
false);
283+
}
284+
285+
ty::ty_struct(did, _) => {
286+
let repr = adt::represent_type(cx, t);
287+
let packed = ty::lookup_packed(cx.tcx, did);
288+
common::set_struct_body(llty, adt::fields_of(cx, repr),
289+
packed);
274290
}
275291
_ => ()
276292
}

‎src/librustc/middle/ty.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -44,6 +44,7 @@ use std::smallintmap::SmallIntMap;
4444
use syntax::ast::*;
4545
use syntax::ast_util::{is_local, local_def};
4646
use syntax::ast_util;
47+
use syntax::attr;
4748
use syntax::codemap::span;
4849
use syntax::codemap;
4950
use syntax::print::pprust;
@@ -3933,6 +3934,28 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
39333934
}
39343935
}
39353936
3937+
// Determine whether an item is annotated with #[packed] or not
3938+
pub fn lookup_packed(tcx: ctxt,
3939+
did: def_id) -> bool {
3940+
if is_local(did) {
3941+
match tcx.items.find(&did.node) {
3942+
Some(
3943+
&ast_map::node_item(@ast::item {
3944+
attrs: ref attrs,
3945+
_
3946+
}, _)) => attr::attrs_contains_name(*attrs, "packed"),
3947+
_ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item",
3948+
did))
3949+
}
3950+
} else {
3951+
let mut ret = false;
3952+
do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
3953+
ret = attr::contains_name(meta_items, "packed");
3954+
}
3955+
ret
3956+
}
3957+
}
3958+
39363959
// Look up a field ID, whether or not it's local
39373960
// Takes a list of type substs in case the struct is generic
39383961
pub fn lookup_field_type(tcx: ctxt,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2013 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+
// This assumes the packed and non-packed structs are different sizes.
12+
13+
// the error points to the start of the file, not the line with the
14+
// transmute
15+
16+
// error-pattern: reinterpret_cast called on types with different size
17+
18+
#[packed]
19+
struct Foo<T,S> {
20+
bar: T,
21+
baz: S
22+
}
23+
24+
struct Oof<T, S> {
25+
rab: T,
26+
zab: S
27+
}
28+
29+
fn main() {
30+
let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 };
31+
unsafe {
32+
let oof: Oof<[u8, .. 5], i32> = cast::transmute(foo);
33+
debug!(oof);
34+
}
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2013 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+
// This assumes the packed and non-packed structs are different sizes.
12+
13+
// the error points to the start of the file, not the line with the
14+
// transmute
15+
16+
// error-pattern: reinterpret_cast called on types with different size
17+
18+
#[packed]
19+
struct Foo {
20+
bar: u8,
21+
baz: uint
22+
}
23+
24+
struct Oof {
25+
rab: u8,
26+
zab: uint
27+
}
28+
29+
fn main() {
30+
let foo = Foo { bar: 1, baz: 10 };
31+
unsafe {
32+
let oof: Oof = cast::transmute(foo);
33+
debug!(oof);
34+
}
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct Foo {
13+
bar: u8,
14+
baz: uint
15+
}
16+
17+
fn main() {
18+
let foo = Foo { bar: 1, baz: 2 };
19+
let brw = &foo.baz;
20+
21+
assert_eq!(*brw, 2);
22+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S<T, S> {
13+
a: T,
14+
b: u8,
15+
c: S
16+
}
17+
18+
fn main() {
19+
unsafe {
20+
let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 };
21+
let transd : [u8, .. 9] = cast::transmute(s);
22+
// Don't worry about endianness, the numbers are palindromic.
23+
assert_eq!(transd,
24+
[0xff, 0xff, 0xff, 0xff,
25+
1,
26+
0xaa, 0xaa, 0xaa, 0xaa]);
27+
28+
29+
let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16};
30+
let transd : [u8, .. 4] = cast::transmute(s);
31+
// Again, no endianness problems.
32+
assert_eq!(transd,
33+
[1, 2, 0b10000001, 0b10000001]);
34+
}
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S<T, S> {
13+
a: T,
14+
b: u8,
15+
c: S
16+
}
17+
18+
fn main() {
19+
assert_eq!(sys::size_of::<S<u8, u8>>(), 3);
20+
21+
assert_eq!(sys::size_of::<S<u64, u16>>(), 11);
22+
23+
assert_eq!(sys::size_of::<S<~str, @mut [int]>>(),
24+
1 + sys::size_of::<~str>() + sys::size_of::<@mut [int]>());
25+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S4 {
13+
a: u8,
14+
b: [u8, .. 3],
15+
}
16+
17+
#[packed]
18+
struct S5 {
19+
a: u8,
20+
b: u32
21+
}
22+
23+
fn main() {
24+
unsafe {
25+
let s4 = S4 { a: 1, b: [2,3,4] };
26+
let transd : [u8, .. 4] = cast::transmute(s4);
27+
assert_eq!(transd, [1, 2, 3, 4]);
28+
29+
let s5 = S5 { a: 1, b: 0xff_00_00_ff };
30+
let transd : [u8, .. 5] = cast::transmute(s5);
31+
// Don't worry about endianness, the u32 is palindromic.
32+
assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
33+
}
34+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct Foo {
13+
bar: u8,
14+
baz: uint
15+
}
16+
17+
fn main() {
18+
let foo = Foo { bar: 1, baz: 2 };
19+
match foo {
20+
Foo {bar, baz} => {
21+
assert_eq!(bar, 1);
22+
assert_eq!(baz, 2);
23+
}
24+
}
25+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S4 {
13+
a: u8,
14+
b: [u8, .. 3],
15+
}
16+
17+
#[packed]
18+
struct S5 {
19+
a: u8,
20+
b: u32
21+
}
22+
23+
#[packed]
24+
struct S13_str {
25+
a: i64,
26+
b: f32,
27+
c: u8,
28+
d: ~str
29+
}
30+
31+
enum Foo {
32+
Bar = 1,
33+
Baz = 2
34+
}
35+
36+
#[packed]
37+
struct S3_Foo {
38+
a: u8,
39+
b: u16,
40+
c: Foo
41+
}
42+
43+
#[packed]
44+
struct S7_Option {
45+
a: f32,
46+
b: u8,
47+
c: u16,
48+
d: Option<@mut f64>
49+
}
50+
51+
52+
fn main() {
53+
assert_eq!(sys::size_of::<S4>(), 4);
54+
assert_eq!(sys::size_of::<S5>(), 5);
55+
assert_eq!(sys::size_of::<S13_str>(), 13 + sys::size_of::<~str>());
56+
assert_eq!(sys::size_of::<S3_Foo>(), 3 + sys::size_of::<Foo>());
57+
assert_eq!(sys::size_of::<S7_Option>(), 7 + sys::size_of::<Option<@mut f64>>());
58+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2013 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+
#[packed]
12+
#[deriving(Eq)]
13+
struct Foo {
14+
bar: u8,
15+
baz: u64
16+
}
17+
18+
fn main() {
19+
let foos = [Foo { bar: 1, baz: 2 }, .. 10];
20+
21+
assert_eq!(sys::size_of::<[Foo, .. 10]>(), 90);
22+
23+
for uint::range(0, 10) |i| {
24+
assert_eq!(foos[i], Foo { bar: 1, baz: 2});
25+
}
26+
27+
for foos.each |&foo| {
28+
assert_eq!(foo, Foo { bar: 1, baz: 2 });
29+
}
30+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S4(u8,[u8, .. 3]);
13+
14+
#[packed]
15+
struct S5(u8,u32);
16+
17+
fn main() {
18+
unsafe {
19+
let s4 = S4(1, [2,3,4]);
20+
let transd : [u8, .. 4] = cast::transmute(s4);
21+
assert_eq!(transd, [1, 2, 3, 4]);
22+
23+
let s5 = S5(1, 0xff_00_00_ff);
24+
let transd : [u8, .. 5] = cast::transmute(s5);
25+
// Don't worry about endianness, the u32 is palindromic.
26+
assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
27+
}
28+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2013 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+
#[packed]
12+
struct S4(u8,[u8, .. 3]);
13+
14+
#[packed]
15+
struct S5(u8, u32);
16+
17+
#[packed]
18+
struct S13_str(i64, f32, u8, ~str);
19+
20+
enum Foo {
21+
Bar = 1,
22+
Baz = 2
23+
}
24+
25+
#[packed]
26+
struct S3_Foo(u8, u16, Foo);
27+
28+
#[packed]
29+
struct S7_Option(f32, u8, u16, Option<@mut f64>);
30+
31+
fn main() {
32+
assert_eq!(sys::size_of::<S4>(), 4);
33+
34+
assert_eq!(sys::size_of::<S5>(), 5);
35+
36+
assert_eq!(sys::size_of::<S13_str>(),
37+
13 + sys::size_of::<~str>());
38+
39+
assert_eq!(sys::size_of::<S3_Foo>(),
40+
3 + sys::size_of::<Foo>());
41+
42+
assert_eq!(sys::size_of::<S7_Option>(),
43+
7 + sys::size_of::<Option<@mut f64>>());
44+
}

0 commit comments

Comments
 (0)
Please sign in to comment.