Skip to content

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

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

Merged
merged 2 commits into from
Apr 10, 2013
Merged
Show file tree
Hide file tree
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
20 changes: 12 additions & 8 deletions src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub enum Repr {
struct Struct {
size: u64,
align: u64,
packed: bool,
fields: ~[ty::t]
}

Expand All @@ -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) => {
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 packed = ty::lookup_packed(cx.tcx, def_id);
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] };
Expand All @@ -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
Expand All @@ -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")
Expand All @@ -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)
}
}
Expand Down Expand Up @@ -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
Expand Down
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.
//
Expand Down Expand Up @@ -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 {
Expand Down
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.
//
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -2837,7 +2837,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 {
Expand Down Expand Up @@ -2877,7 +2877,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)
Expand Down
23 changes: 17 additions & 6 deletions src/librustc/middle/trans/cabi_arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 => {
Expand All @@ -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;
Expand Down
27 changes: 19 additions & 8 deletions src/librustc/middle/trans/cabi_mips.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.
//
Expand All @@ -14,6 +14,7 @@ use core::libc::c_uint;
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
use lib::llvm::{Struct, Array, Attribute};
use lib::llvm::{StructRetAttribute};
use lib::llvm::True;
use middle::trans::common::*;
use middle::trans::cabi::*;

Expand Down Expand Up @@ -49,8 +50,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 => {
Expand All @@ -72,10 +77,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;
Expand Down Expand Up @@ -174,7 +185,7 @@ fn struct_ty(ty: TypeRef,
fields.push(ty);
}

return T_struct(fields);
return T_struct(fields, false);
}

enum MIPS_ABIInfo { MIPS_ABIInfo }
Expand Down
23 changes: 17 additions & 6 deletions src/librustc/middle/trans/cabi_x86_64.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.
//
Expand All @@ -15,6 +15,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
use lib::llvm::{Struct, Array, Attribute};
use lib::llvm::{StructRetAttribute, ByValAttribute};
use lib::llvm::struct_tys;
use lib::llvm::True;
use middle::trans::common::*;
use middle::trans::cabi::*;

Expand Down Expand Up @@ -76,8 +77,12 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
Float => 4,
Double => 8,
Struct => {
do vec::foldl(1, struct_tys(ty)) |a, t| {
if llvm::LLVMIsPackedStruct(ty) == True {
1
} else {
do vec::foldl(1, struct_tys(ty)) |a, t| {
uint::max(a, ty_align(*t))
}
}
}
Array => {
Expand All @@ -99,10 +104,16 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
Float => 4,
Double => 8,
Struct => {
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
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)
};
align(size, ty)
}
}
Array => {
let len = llvm::LLVMGetArrayLength(ty) as uint;
Expand Down Expand Up @@ -308,7 +319,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
}
i += 1u;
}
return T_struct(tys);
return T_struct(tys, false);
}
}

Expand Down
Loading