Skip to content

Add #[packed] attribute to create packed structs #5758

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
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -387,9 +387,11 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
'a' => {
assert!((next(st) == '['));
let did = parse_def(st, NominalType, conv);
let packed = next(st) == '1';
assert!((next(st) == '|'));
let substs = parse_substs(st, conv);
assert!((next(st) == ']'));
return ty::mk_struct(st.tcx, did, substs);
return ty::mk_struct(st.tcx, did, substs, packed);
}
c => { error!("unexpected char in type string: %c", c); fail!();}
}
10 changes: 8 additions & 2 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -328,14 +328,20 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, +st: ty::sty) {
enc_sigil(w, p);
}
ty::ty_opaque_box => w.write_char('B'),
ty::ty_struct(def, ref substs) => {
ty::ty_struct(def, ref substs, packed) => {
debug!("~~~~ %s", ~"a[");
w.write_str(&"a[");
let s = (cx.ds)(def);
debug!("~~~~ %s", s);
w.write_str(s);
debug!("~~~~ %s", ~"|");
w.write_char('|');
let p = if packed { '1' }
else { '0' };
debug!("~~~~ %c", p);
w.write_char(p);
debug!("~~~~ %s", ~"|");
w.write_char('|');
enc_substs(w, cx, (*substs));
debug!("~~~~ %s", ~"]");
w.write_char(']');
6 changes: 3 additions & 3 deletions src/librustc/middle/check_match.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -459,7 +459,7 @@ pub fn ctor_arity(cx: @MatchCheckCtxt, ctor: ctor, ty: ty::t) -> uint {
None => fail!(~"impossible case")
}
}
ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
ty::ty_struct(cid, _, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
match ctor {
vec(n) => n,
@@ -589,7 +589,7 @@ pub fn specialize(cx: @MatchCheckCtxt,
// Grab the class data that we care about.
let class_fields, class_id;
match ty::get(left_ty).sty {
ty::ty_struct(cid, _) => {
ty::ty_struct(cid, _, _) => {
class_id = cid;
class_fields =
ty::lookup_struct_fields(cx.tcx,
4 changes: 2 additions & 2 deletions src/librustc/middle/kind.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -96,7 +96,7 @@ fn check_struct_safe_for_destructor(cx: Context,
self_r: None,
self_ty: None,
tps: ~[]
});
}, false); // packed-ness doesn't matter for destructor safety
if !ty::type_is_owned(cx.tcx, struct_ty) {
cx.tcx.sess.span_err(span,
~"cannot implement a destructor on a struct \
7 changes: 3 additions & 4 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -188,7 +188,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
Some(deref_comp(comp_variant(did)))
}

ty::ty_struct(_, _) => {
ty::ty_struct(*) => {
Some(deref_comp(comp_anon_field))
}

@@ -1112,7 +1112,7 @@ pub fn field_mutbl(tcx: ty::ctxt,
-> Option<ast::mutability> {
// Need to refactor so that struct/enum fields can be treated uniformly.
match ty::get(base_ty).sty {
ty::ty_struct(did, _) => {
ty::ty_struct(did, _, _) => {
for ty::lookup_struct_fields(tcx, did).each |fld| {
if fld.ident == f_name {
let m = match fld.mutability {
@@ -1175,4 +1175,3 @@ pub impl categorization {
}
}
}

4 changes: 2 additions & 2 deletions src/librustc/middle/moves.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -477,7 +477,7 @@ pub impl VisitContext {
// then `with` is consumed, otherwise it is only read
let with_ty = ty::expr_ty(self.tcx, *with_expr);
let with_fields = match ty::get(with_ty).sty {
ty::ty_struct(did, ref substs) => {
ty::ty_struct(did, ref substs, _) => {
ty::struct_fields(self.tcx, did, substs)
}
ref r => {
11 changes: 5 additions & 6 deletions src/librustc/middle/privacy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -437,7 +437,7 @@ pub fn check_crate(tcx: ty::ctxt,
// allow pointers to violate privacy
match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
base))).sty {
ty_struct(id, _)
ty_struct(id, _, _)
if id.crate != local_crate ||
!privileged_items.contains(&(id.node)) => {
match method_map.find(&expr.id) {
@@ -462,7 +462,7 @@ pub fn check_crate(tcx: ty::ctxt,
// Ditto
match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
base))).sty {
ty_struct(id, _)
ty_struct(id, _, _)
if id.crate != local_crate ||
!privileged_items.contains(&(id.node)) => {
match method_map.find(&expr.id) {
@@ -488,7 +488,7 @@ pub fn check_crate(tcx: ty::ctxt,
}
expr_struct(_, ref fields, _) => {
match ty::get(ty::expr_ty(tcx, expr)).sty {
ty_struct(id, _) => {
ty_struct(id, _, _) => {
if id.crate != local_crate ||
!privileged_items.contains(&(id.node)) {
for (*fields).each |field| {
@@ -554,7 +554,7 @@ pub fn check_crate(tcx: ty::ctxt,
match pattern.node {
pat_struct(_, ref fields, _) => {
match ty::get(ty::pat_ty(tcx, pattern)).sty {
ty_struct(id, _) => {
ty_struct(id, _, _) => {
if id.crate != local_crate ||
!privileged_items.contains(&(id.node)) {
for fields.each |field| {
@@ -606,4 +606,3 @@ pub fn check_crate(tcx: ty::ctxt,
});
visit::visit_crate(*crate, method_map, visitor);
}

4 changes: 2 additions & 2 deletions src/librustc/middle/trans/_match.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -1339,7 +1339,7 @@ pub fn compile_submatch(bcx: block,
let struct_ty = node_id_type(bcx, pat_id);
let struct_element_count;
match ty::get(struct_ty).sty {
ty::ty_struct(struct_id, _) => {
ty::ty_struct(struct_id, _, _) => {
struct_element_count =
ty::lookup_struct_fields(tcx, struct_id).len();
}
22 changes: 13 additions & 9 deletions src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ pub enum Repr {
struct Struct {
size: u64,
align: u64,
packed: bool,
fields: ~[ty::t]
}

@@ -109,17 +110,18 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
}
let repr = @match ty::get(t).sty {
ty::ty_tup(ref elems) => {
Univariant(mk_struct(cx, *elems), false)
Univariant(mk_struct(cx, *elems, false), false)
}
ty::ty_struct(def_id, ref substs) => {
ty::ty_struct(def_id, ref substs, packed) => {
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
let ftys = do fields.map |field| {
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
};
let dtor = ty::ty_dtor(cx.tcx, def_id).is_present();
let ftys =
if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { ftys };
Univariant(mk_struct(cx, ftys), dtor)

Univariant(mk_struct(cx, ftys, packed), dtor)
}
ty::ty_enum(def_id, ref substs) => {
struct Case { discr: int, tys: ~[ty::t] };
@@ -132,15 +134,15 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
};
if cases.len() == 0 {
// Uninhabitable; represent as unit
Univariant(mk_struct(cx, ~[]), false)
Univariant(mk_struct(cx, ~[], false), false)
} else if cases.all(|c| c.tys.len() == 0) {
// All bodies empty -> intlike
let discrs = cases.map(|c| c.discr);
CEnum(discrs.min(), discrs.max())
} else if cases.len() == 1 {
// Equivalent to a struct/tuple/newtype.
assert!(cases[0].discr == 0);
Univariant(mk_struct(cx, cases[0].tys), false)
Univariant(mk_struct(cx, cases[0].tys, false), false)
} else {
// The general case. Since there's at least one
// non-empty body, explicit discriminants should have
@@ -151,7 +153,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
ty::item_path_str(cx.tcx, def_id)))
}
let discr = ~[ty::mk_int(cx.tcx)];
General(cases.map(|c| mk_struct(cx, discr + c.tys)))
General(cases.map(|c| mk_struct(cx, discr + c.tys, false)))
}
}
_ => 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 {
return repr;
}

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

let val = if needs_cast {
let real_llty = T_struct(st.fields.map(
|&ty| type_of::type_of(ccx, ty)));
|&ty| type_of::type_of(ccx, ty)),
st.packed);
PointerCast(bcx, val, T_ptr(real_llty))
} else {
val
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/asm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -108,7 +108,7 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
} else if numOutputs == 1 {
val_ty(outputs[0])
} else {
T_struct(outputs.map(|o| val_ty(*o)))
T_struct(outputs.map(|o| val_ty(*o)), false)
};

let dialect = match ia.dialect {
8 changes: 4 additions & 4 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -938,7 +938,7 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef {
// The landing pad return type (the type being propagated). Not sure what
// this represents but it's determined by the personality function and
// this is what the EH proposal example uses.
let llretty = T_struct(~[T_ptr(T_i8()), T_i32()]);
let llretty = T_struct(~[T_ptr(T_i8()), T_i32()], false);
// The exception handling personality function. This is the C++
// personality function __gxx_personality_v0, wrapped in our naming
// convention.
@@ -2832,7 +2832,7 @@ pub fn decl_gc_metadata(ccx: @CrateContext, llmod_id: &str) {
}

pub fn create_module_map(ccx: @CrateContext) -> ValueRef {
let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
let elttype = T_struct(~[ccx.int_type, ccx.int_type], false);
let maptype = T_array(elttype, ccx.module_data.len() + 1);
let map = str::as_c_str(~"_rust_mod_map", |buf| {
unsafe {
@@ -2872,7 +2872,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
};
let sym_name = ~"_rust_crate_map_" + mapname;
let arrtype = T_array(int_type, n_subcrates as uint);
let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype]);
let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype], false);
let map = str::as_c_str(sym_name, |buf| {
unsafe {
llvm::LLVMAddGlobal(llmod, maptype, buf)
23 changes: 17 additions & 6 deletions src/librustc/middle/trans/cabi_arm.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
use lib::llvm::struct_tys;
use lib::llvm::TypeRef;
use lib::llvm::{Attribute, StructRetAttribute};
use lib::llvm::True;
use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
use middle::trans::common::{T_i8, T_i16, T_i32, T_i64};
use middle::trans::common::{T_array, T_ptr, T_void};
@@ -39,8 +40,12 @@ fn ty_align(ty: TypeRef) -> uint {
Float => 4,
Double => 8,
Struct => {
do vec::foldl(1, struct_tys(ty)) |a, t| {
uint::max(a, ty_align(*t))
if llvm::LLVMIsPackedStruct(ty) == True {
1
} else {
do vec::foldl(1, struct_tys(ty)) |a, t| {
uint::max(a, ty_align(*t))
}
}
}
Array => {
@@ -62,10 +67,16 @@ fn ty_size(ty: TypeRef) -> uint {
Float => 4,
Double => 8,
Struct => {
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
align(s, *t) + ty_size(*t)
};
align(size, ty)
if llvm::LLVMIsPackedStruct(ty) == True {
do vec::foldl(0, struct_tys(ty)) |s, t| {
s + ty_size(*t)
}
} else {
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
align(s, *t) + ty_size(*t)
};
align(size, ty)
}
}
Array => {
let len = llvm::LLVMGetArrayLength(ty) as uint;
Loading