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

+12-8
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

+2-2
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

+4-4
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

+17-6
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

+19-8
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

+17-6
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

0 commit comments

Comments
 (0)
Please sign in to comment.