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.
This commit is contained in:
commit
5d01f649b4
22 changed files with 521 additions and 71 deletions
|
@ -88,6 +88,7 @@ pub enum Repr {
|
||||||
struct Struct {
|
struct Struct {
|
||||||
size: u64,
|
size: u64,
|
||||||
align: u64,
|
align: u64,
|
||||||
|
packed: bool,
|
||||||
fields: ~[ty::t]
|
fields: ~[ty::t]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,17 +110,18 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
|
||||||
}
|
}
|
||||||
let repr = @match ty::get(t).sty {
|
let repr = @match ty::get(t).sty {
|
||||||
ty::ty_tup(ref elems) => {
|
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) => {
|
||||||
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
|
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
|
||||||
let ftys = do fields.map |field| {
|
let ftys = do fields.map |field| {
|
||||||
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
|
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 dtor = ty::ty_dtor(cx.tcx, def_id).is_present();
|
||||||
let ftys =
|
let ftys =
|
||||||
if dtor { ftys + [ty::mk_bool(cx.tcx)] } else { 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) => {
|
ty::ty_enum(def_id, ref substs) => {
|
||||||
struct Case { discr: int, tys: ~[ty::t] };
|
struct Case { discr: int, tys: ~[ty::t] };
|
||||||
|
@ -132,7 +134,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
|
||||||
};
|
};
|
||||||
if cases.len() == 0 {
|
if cases.len() == 0 {
|
||||||
// Uninhabitable; represent as unit
|
// Uninhabitable; represent as unit
|
||||||
Univariant(mk_struct(cx, ~[]), false)
|
Univariant(mk_struct(cx, ~[], false), false)
|
||||||
} else if cases.all(|c| c.tys.len() == 0) {
|
} else if cases.all(|c| c.tys.len() == 0) {
|
||||||
// All bodies empty -> intlike
|
// All bodies empty -> intlike
|
||||||
let discrs = cases.map(|c| c.discr);
|
let discrs = cases.map(|c| c.discr);
|
||||||
|
@ -140,7 +142,7 @@ pub fn represent_type(cx: @CrateContext, t: ty::t) -> @Repr {
|
||||||
} else if cases.len() == 1 {
|
} else if cases.len() == 1 {
|
||||||
// Equivalent to a struct/tuple/newtype.
|
// Equivalent to a struct/tuple/newtype.
|
||||||
assert!(cases[0].discr == 0);
|
assert!(cases[0].discr == 0);
|
||||||
Univariant(mk_struct(cx, cases[0].tys), false)
|
Univariant(mk_struct(cx, cases[0].tys, false), false)
|
||||||
} else {
|
} else {
|
||||||
// The general case. Since there's at least one
|
// The general case. Since there's at least one
|
||||||
// non-empty body, explicit discriminants should have
|
// 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)))
|
ty::item_path_str(cx.tcx, def_id)))
|
||||||
}
|
}
|
||||||
let discr = ~[ty::mk_int(cx.tcx)];
|
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")
|
_ => 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;
|
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 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 {
|
Struct {
|
||||||
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
|
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
|
||||||
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
|
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
|
||||||
|
packed: packed,
|
||||||
fields: vec::from_slice(tys)
|
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 val = if needs_cast {
|
||||||
let real_llty = T_struct(st.fields.map(
|
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))
|
PointerCast(bcx, val, T_ptr(real_llty))
|
||||||
} else {
|
} else {
|
||||||
val
|
val
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// 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 {
|
} else if numOutputs == 1 {
|
||||||
val_ty(outputs[0])
|
val_ty(outputs[0])
|
||||||
} else {
|
} else {
|
||||||
T_struct(outputs.map(|o| val_ty(*o)))
|
T_struct(outputs.map(|o| val_ty(*o)), false)
|
||||||
};
|
};
|
||||||
|
|
||||||
let dialect = match ia.dialect {
|
let dialect = match ia.dialect {
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// 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
|
// The landing pad return type (the type being propagated). Not sure what
|
||||||
// this represents but it's determined by the personality function and
|
// this represents but it's determined by the personality function and
|
||||||
// this is what the EH proposal example uses.
|
// 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++
|
// The exception handling personality function. This is the C++
|
||||||
// personality function __gxx_personality_v0, wrapped in our naming
|
// personality function __gxx_personality_v0, wrapped in our naming
|
||||||
// convention.
|
// convention.
|
||||||
|
@ -2837,7 +2837,7 @@ pub fn decl_gc_metadata(ccx: @CrateContext, llmod_id: &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_module_map(ccx: @CrateContext) -> ValueRef {
|
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 maptype = T_array(elttype, ccx.module_data.len() + 1);
|
||||||
let map = str::as_c_str(~"_rust_mod_map", |buf| {
|
let map = str::as_c_str(~"_rust_mod_map", |buf| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -2877,7 +2877,7 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
||||||
};
|
};
|
||||||
let sym_name = ~"_rust_crate_map_" + mapname;
|
let sym_name = ~"_rust_crate_map_" + mapname;
|
||||||
let arrtype = T_array(int_type, n_subcrates as uint);
|
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| {
|
let map = str::as_c_str(sym_name, |buf| {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMAddGlobal(llmod, maptype, buf)
|
llvm::LLVMAddGlobal(llmod, maptype, buf)
|
||||||
|
|
|
@ -12,6 +12,7 @@ use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
|
||||||
use lib::llvm::struct_tys;
|
use lib::llvm::struct_tys;
|
||||||
use lib::llvm::TypeRef;
|
use lib::llvm::TypeRef;
|
||||||
use lib::llvm::{Attribute, StructRetAttribute};
|
use lib::llvm::{Attribute, StructRetAttribute};
|
||||||
|
use lib::llvm::True;
|
||||||
use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
|
use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
|
||||||
use middle::trans::common::{T_i8, T_i16, T_i32, T_i64};
|
use middle::trans::common::{T_i8, T_i16, T_i32, T_i64};
|
||||||
use middle::trans::common::{T_array, T_ptr, T_void};
|
use middle::trans::common::{T_array, T_ptr, T_void};
|
||||||
|
@ -39,8 +40,12 @@ fn ty_align(ty: TypeRef) -> uint {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
Struct => {
|
||||||
do vec::foldl(1, struct_tys(ty)) |a, t| {
|
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||||
uint::max(a, ty_align(*t))
|
1
|
||||||
|
} else {
|
||||||
|
do vec::foldl(1, struct_tys(ty)) |a, t| {
|
||||||
|
uint::max(a, ty_align(*t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
|
@ -62,10 +67,16 @@ fn ty_size(ty: TypeRef) -> uint {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
Struct => {
|
||||||
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
|
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||||
align(s, *t) + ty_size(*t)
|
do vec::foldl(0, struct_tys(ty)) |s, t| {
|
||||||
};
|
s + ty_size(*t)
|
||||||
align(size, ty)
|
}
|
||||||
|
} else {
|
||||||
|
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
|
||||||
|
align(s, *t) + ty_size(*t)
|
||||||
|
};
|
||||||
|
align(size, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -14,6 +14,7 @@ use core::libc::c_uint;
|
||||||
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
||||||
use lib::llvm::{Struct, Array, Attribute};
|
use lib::llvm::{Struct, Array, Attribute};
|
||||||
use lib::llvm::{StructRetAttribute};
|
use lib::llvm::{StructRetAttribute};
|
||||||
|
use lib::llvm::True;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::cabi::*;
|
use middle::trans::cabi::*;
|
||||||
|
|
||||||
|
@ -49,8 +50,12 @@ fn ty_align(ty: TypeRef) -> uint {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
Struct => {
|
||||||
do vec::foldl(1, struct_tys(ty)) |a, t| {
|
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||||
uint::max(a, ty_align(*t))
|
1
|
||||||
|
} else {
|
||||||
|
do vec::foldl(1, struct_tys(ty)) |a, t| {
|
||||||
|
uint::max(a, ty_align(*t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
|
@ -72,10 +77,16 @@ fn ty_size(ty: TypeRef) -> uint {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
Struct => {
|
||||||
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
|
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||||
align(s, *t) + ty_size(*t)
|
do vec::foldl(0, struct_tys(ty)) |s, t| {
|
||||||
};
|
s + ty_size(*t)
|
||||||
align(size, ty)
|
}
|
||||||
|
} else {
|
||||||
|
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
|
||||||
|
align(s, *t) + ty_size(*t)
|
||||||
|
};
|
||||||
|
align(size, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||||
|
@ -174,7 +185,7 @@ fn struct_ty(ty: TypeRef,
|
||||||
fields.push(ty);
|
fields.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return T_struct(fields);
|
return T_struct(fields, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MIPS_ABIInfo { MIPS_ABIInfo }
|
enum MIPS_ABIInfo { MIPS_ABIInfo }
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -15,6 +15,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
||||||
use lib::llvm::{Struct, Array, Attribute};
|
use lib::llvm::{Struct, Array, Attribute};
|
||||||
use lib::llvm::{StructRetAttribute, ByValAttribute};
|
use lib::llvm::{StructRetAttribute, ByValAttribute};
|
||||||
use lib::llvm::struct_tys;
|
use lib::llvm::struct_tys;
|
||||||
|
use lib::llvm::True;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::cabi::*;
|
use middle::trans::cabi::*;
|
||||||
|
|
||||||
|
@ -76,8 +77,12 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
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))
|
uint::max(a, ty_align(*t))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
|
@ -99,10 +104,16 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||||
Float => 4,
|
Float => 4,
|
||||||
Double => 8,
|
Double => 8,
|
||||||
Struct => {
|
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(s, *t) + ty_size(*t)
|
||||||
};
|
};
|
||||||
align(size, ty)
|
align(size, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Array => {
|
Array => {
|
||||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||||
|
@ -308,7 +319,7 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
|
||||||
}
|
}
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
return T_struct(tys);
|
return T_struct(tys, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -765,7 +765,7 @@ pub fn T_void() -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_nil() -> TypeRef {
|
pub fn T_nil() -> TypeRef {
|
||||||
return T_struct(~[])
|
return T_struct(~[], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
|
pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
|
||||||
|
@ -848,7 +848,7 @@ pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef {
|
pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef {
|
||||||
return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)]);
|
return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_ptr(t: TypeRef) -> TypeRef {
|
pub fn T_ptr(t: TypeRef) -> TypeRef {
|
||||||
|
@ -863,11 +863,11 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_struct(elts: &[TypeRef]) -> TypeRef {
|
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
|
||||||
unsafe {
|
unsafe {
|
||||||
return llvm::LLVMStructType(to_ptr(elts),
|
return llvm::LLVMStructType(to_ptr(elts),
|
||||||
elts.len() as c_uint,
|
elts.len() as c_uint,
|
||||||
False);
|
packed as Bool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,16 +878,16 @@ pub fn T_named_struct(name: &str) -> TypeRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef]) {
|
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMStructSetBody(t,
|
llvm::LLVMStructSetBody(t,
|
||||||
to_ptr(elts),
|
to_ptr(elts),
|
||||||
elts.len() as c_uint,
|
elts.len() as c_uint,
|
||||||
False);
|
packed as Bool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_empty_struct() -> TypeRef { return T_struct(~[]); }
|
pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); }
|
||||||
|
|
||||||
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
|
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
|
||||||
// to tydescs and other vtables that it closes over. But the types and number
|
// 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 {
|
||||||
let elems =
|
let elems =
|
||||||
~[t_int, t_int, t_int, t_int,
|
~[t_int, t_int, t_int, t_int,
|
||||||
t_int, t_int, t_int, t_int];
|
t_int, t_int, t_int, t_int];
|
||||||
set_struct_body(t, elems);
|
set_struct_body(t, elems, false);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
|
||||||
~[int_type, int_type,
|
~[int_type, int_type,
|
||||||
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
|
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
|
||||||
T_ptr(T_i8()), T_ptr(T_i8())];
|
T_ptr(T_i8()), T_ptr(T_i8())];
|
||||||
set_struct_body(tydesc, elems);
|
set_struct_body(tydesc, elems, false);
|
||||||
return tydesc;
|
return tydesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,8 +969,9 @@ pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
|
||||||
// Interior vector.
|
// Interior vector.
|
||||||
pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
|
pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
|
||||||
return T_struct(~[T_int(targ_cfg), // fill
|
return T_struct(~[T_int(targ_cfg), // fill
|
||||||
T_int(targ_cfg), // alloc
|
T_int(targ_cfg), // alloc
|
||||||
T_array(t, 0u)]); // elements
|
T_array(t, 0u)], // elements
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef {
|
pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef {
|
||||||
|
@ -1001,11 +1002,11 @@ pub fn T_box_header_fields(cx: @CrateContext) -> ~[TypeRef] {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_box_header(cx: @CrateContext) -> TypeRef {
|
pub fn T_box_header(cx: @CrateContext) -> TypeRef {
|
||||||
return T_struct(T_box_header_fields(cx));
|
return T_struct(T_box_header_fields(cx), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
||||||
return T_struct(vec::append(T_box_header_fields(cx), ~[t]));
|
return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_box_ptr(t: TypeRef) -> TypeRef {
|
pub fn T_box_ptr(t: TypeRef) -> TypeRef {
|
||||||
|
@ -1023,7 +1024,7 @@ pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
||||||
return T_struct(vec::append(T_box_header_fields(cx), ~[t]));
|
return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
|
pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
|
||||||
|
@ -1033,12 +1034,12 @@ pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
||||||
return T_struct(~[cx.int_type]); // Refcount
|
return T_struct(~[cx.int_type], false); // Refcount
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
||||||
return T_struct(~[cx.int_type]); // Refcount
|
return T_struct(~[cx.int_type], false); // Refcount
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,21 +1057,22 @@ pub fn T_enum_discrim(cx: @CrateContext) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef {
|
pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef {
|
||||||
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)));
|
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
|
pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
|
||||||
match store {
|
match store {
|
||||||
ty::BoxTraitStore => {
|
ty::BoxTraitStore => {
|
||||||
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)])
|
T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
|
||||||
}
|
}
|
||||||
ty::UniqTraitStore => {
|
ty::UniqTraitStore => {
|
||||||
T_struct(~[T_ptr(cx.tydesc_type),
|
T_struct(~[T_ptr(cx.tydesc_type),
|
||||||
T_unique_ptr(T_unique(cx, T_i8())),
|
T_unique_ptr(T_unique(cx, T_i8())),
|
||||||
T_ptr(cx.tydesc_type)])
|
T_ptr(cx.tydesc_type)],
|
||||||
|
false)
|
||||||
}
|
}
|
||||||
ty::RegionTraitStore(_) => {
|
ty::RegionTraitStore(_) => {
|
||||||
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
|
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -106,7 +106,8 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes {
|
||||||
};
|
};
|
||||||
let llsig = foreign_signature(ccx, &fn_sig);
|
let llsig = foreign_signature(ccx, &fn_sig);
|
||||||
let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys,
|
let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys,
|
||||||
T_ptr(llsig.llret_ty)));
|
T_ptr(llsig.llret_ty)),
|
||||||
|
false);
|
||||||
let ret_def =
|
let ret_def =
|
||||||
!ty::type_is_bot(fn_sig.output) &&
|
!ty::type_is_bot(fn_sig.output) &&
|
||||||
!ty::type_is_nil(fn_sig.output);
|
!ty::type_is_nil(fn_sig.output);
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -142,9 +142,9 @@ pub fn static_size_of_enum(cx: @CrateContext, t: ty::t) -> uint {
|
||||||
|
|
||||||
debug!("static_size_of_enum: variant %s type %s",
|
debug!("static_size_of_enum: variant %s type %s",
|
||||||
*cx.tcx.sess.str_of(variant.name),
|
*cx.tcx.sess.str_of(variant.name),
|
||||||
ty_str(cx.tn, T_struct(lltypes)));
|
ty_str(cx.tn, T_struct(lltypes, false)));
|
||||||
|
|
||||||
let this_size = llsize_of_real(cx, T_struct(lltypes));
|
let this_size = llsize_of_real(cx, T_struct(lltypes, false));
|
||||||
if max_size < this_size {
|
if max_size < this_size {
|
||||||
max_size = this_size;
|
max_size = this_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -128,11 +128,11 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||||
|
|
||||||
ty::ty_estr(ty::vstore_slice(*)) |
|
ty::ty_estr(ty::vstore_slice(*)) |
|
||||||
ty::ty_evec(_, ty::vstore_slice(*)) => {
|
ty::ty_evec(_, ty::vstore_slice(*)) => {
|
||||||
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())])
|
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_bare_fn(*) => T_ptr(T_i8()),
|
ty::ty_bare_fn(*) => T_ptr(T_i8()),
|
||||||
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
|
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false),
|
||||||
ty::ty_trait(_, _, store) => T_opaque_trait(cx, store),
|
ty::ty_trait(_, _, store) => T_opaque_trait(cx, store),
|
||||||
|
|
||||||
ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size),
|
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 {
|
||||||
|
|
||||||
ty::ty_unboxed_vec(mt) => T_vec(cx, sizing_type_of(cx, mt.ty)),
|
ty::ty_unboxed_vec(mt) => T_vec(cx, sizing_type_of(cx, mt.ty)),
|
||||||
|
|
||||||
ty::ty_tup(*) | ty::ty_struct(*) | ty::ty_enum(*) => {
|
ty::ty_tup(*) | ty::ty_enum(*) => {
|
||||||
let repr = adt::represent_type(cx, t);
|
let repr = adt::represent_type(cx, t);
|
||||||
T_struct(adt::sizing_fields_of(cx, repr))
|
T_struct(adt::sizing_fields_of(cx, repr), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_struct(did, _) => {
|
||||||
|
let repr = adt::represent_type(cx, t);
|
||||||
|
let packed = ty::lookup_packed(cx.tcx, did);
|
||||||
|
T_struct(adt::sizing_fields_of(cx, repr), packed)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
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 {
|
||||||
|
|
||||||
ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
|
ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
|
||||||
T_struct(~[T_ptr(type_of(cx, mt.ty)),
|
T_struct(~[T_ptr(type_of(cx, mt.ty)),
|
||||||
T_uint_ty(cx, ast::ty_u)])
|
T_uint_ty(cx, ast::ty_u)],
|
||||||
|
false)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_estr(ty::vstore_slice(_)) => {
|
ty::ty_estr(ty::vstore_slice(_)) => {
|
||||||
T_struct(~[T_ptr(T_i8()),
|
T_struct(~[T_ptr(T_i8()),
|
||||||
T_uint_ty(cx, ast::ty_u)])
|
T_uint_ty(cx, ast::ty_u)],
|
||||||
|
false)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_estr(ty::vstore_fixed(n)) => {
|
ty::ty_estr(ty::vstore_fixed(n)) => {
|
||||||
|
@ -245,7 +253,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||||
ty::ty_tup(*) => {
|
ty::ty_tup(*) => {
|
||||||
let repr = adt::represent_type(cx, t);
|
let repr = adt::represent_type(cx, t);
|
||||||
T_struct(adt::fields_of(cx, repr))
|
T_struct(adt::fields_of(cx, repr), false)
|
||||||
}
|
}
|
||||||
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
|
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
|
||||||
ty::ty_struct(did, ref substs) => {
|
ty::ty_struct(did, ref substs) => {
|
||||||
|
@ -268,9 +276,17 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||||
|
|
||||||
// If this was an enum or struct, fill in the type now.
|
// If this was an enum or struct, fill in the type now.
|
||||||
match ty::get(t).sty {
|
match ty::get(t).sty {
|
||||||
ty::ty_enum(*) | ty::ty_struct(*) => {
|
ty::ty_enum(*) => {
|
||||||
let repr = adt::represent_type(cx, t);
|
let repr = adt::represent_type(cx, t);
|
||||||
common::set_struct_body(llty, adt::fields_of(cx, repr));
|
common::set_struct_body(llty, adt::fields_of(cx, repr),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::ty_struct(did, _) => {
|
||||||
|
let repr = adt::represent_type(cx, t);
|
||||||
|
let packed = ty::lookup_packed(cx.tcx, did);
|
||||||
|
common::set_struct_body(llty, adt::fields_of(cx, repr),
|
||||||
|
packed);
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
|
@ -44,6 +44,7 @@ use std::smallintmap::SmallIntMap;
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::ast_util::{is_local, local_def};
|
use syntax::ast_util::{is_local, local_def};
|
||||||
use syntax::ast_util;
|
use syntax::ast_util;
|
||||||
|
use syntax::attr;
|
||||||
use syntax::codemap::span;
|
use syntax::codemap::span;
|
||||||
use syntax::codemap;
|
use syntax::codemap;
|
||||||
use syntax::print::pprust;
|
use syntax::print::pprust;
|
||||||
|
@ -3933,6 +3934,28 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether an item is annotated with #[packed] or not
|
||||||
|
pub fn lookup_packed(tcx: ctxt,
|
||||||
|
did: def_id) -> bool {
|
||||||
|
if is_local(did) {
|
||||||
|
match tcx.items.find(&did.node) {
|
||||||
|
Some(
|
||||||
|
&ast_map::node_item(@ast::item {
|
||||||
|
attrs: ref attrs,
|
||||||
|
_
|
||||||
|
}, _)) => attr::attrs_contains_name(*attrs, "packed"),
|
||||||
|
_ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item",
|
||||||
|
did))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut ret = false;
|
||||||
|
do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
|
||||||
|
ret = attr::contains_name(meta_items, "packed");
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Look up a field ID, whether or not it's local
|
// Look up a field ID, whether or not it's local
|
||||||
// Takes a list of type substs in case the struct is generic
|
// Takes a list of type substs in case the struct is generic
|
||||||
pub fn lookup_field_type(tcx: ctxt,
|
pub fn lookup_field_type(tcx: ctxt,
|
||||||
|
|
35
src/test/compile-fail/packed-struct-generic-transmute.rs
Normal file
35
src/test/compile-fail/packed-struct-generic-transmute.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// This assumes the packed and non-packed structs are different sizes.
|
||||||
|
|
||||||
|
// the error points to the start of the file, not the line with the
|
||||||
|
// transmute
|
||||||
|
|
||||||
|
// error-pattern: reinterpret_cast called on types with different size
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct Foo<T,S> {
|
||||||
|
bar: T,
|
||||||
|
baz: S
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Oof<T, S> {
|
||||||
|
rab: T,
|
||||||
|
zab: S
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 };
|
||||||
|
unsafe {
|
||||||
|
let oof: Oof<[u8, .. 5], i32> = cast::transmute(foo);
|
||||||
|
debug!(oof);
|
||||||
|
}
|
||||||
|
}
|
35
src/test/compile-fail/packed-struct-transmute.rs
Normal file
35
src/test/compile-fail/packed-struct-transmute.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// This assumes the packed and non-packed structs are different sizes.
|
||||||
|
|
||||||
|
// the error points to the start of the file, not the line with the
|
||||||
|
// transmute
|
||||||
|
|
||||||
|
// error-pattern: reinterpret_cast called on types with different size
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct Foo {
|
||||||
|
bar: u8,
|
||||||
|
baz: uint
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Oof {
|
||||||
|
rab: u8,
|
||||||
|
zab: uint
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = Foo { bar: 1, baz: 10 };
|
||||||
|
unsafe {
|
||||||
|
let oof: Oof = cast::transmute(foo);
|
||||||
|
debug!(oof);
|
||||||
|
}
|
||||||
|
}
|
22
src/test/run-pass/packed-struct-borrow-element.rs
Normal file
22
src/test/run-pass/packed-struct-borrow-element.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct Foo {
|
||||||
|
bar: u8,
|
||||||
|
baz: uint
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = Foo { bar: 1, baz: 2 };
|
||||||
|
let brw = &foo.baz;
|
||||||
|
|
||||||
|
assert_eq!(*brw, 2);
|
||||||
|
}
|
35
src/test/run-pass/packed-struct-generic-layout.rs
Normal file
35
src/test/run-pass/packed-struct-generic-layout.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S<T, S> {
|
||||||
|
a: T,
|
||||||
|
b: u8,
|
||||||
|
c: S
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
let s = S { a: 0xff_ff_ff_ffu32, b: 1, c: 0xaa_aa_aa_aa as i32 };
|
||||||
|
let transd : [u8, .. 9] = cast::transmute(s);
|
||||||
|
// Don't worry about endianness, the numbers are palindromic.
|
||||||
|
assert_eq!(transd,
|
||||||
|
[0xff, 0xff, 0xff, 0xff,
|
||||||
|
1,
|
||||||
|
0xaa, 0xaa, 0xaa, 0xaa]);
|
||||||
|
|
||||||
|
|
||||||
|
let s = S { a: 1u8, b: 2u8, c: 0b10000001_10000001 as i16};
|
||||||
|
let transd : [u8, .. 4] = cast::transmute(s);
|
||||||
|
// Again, no endianness problems.
|
||||||
|
assert_eq!(transd,
|
||||||
|
[1, 2, 0b10000001, 0b10000001]);
|
||||||
|
}
|
||||||
|
}
|
25
src/test/run-pass/packed-struct-generic-size.rs
Normal file
25
src/test/run-pass/packed-struct-generic-size.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S<T, S> {
|
||||||
|
a: T,
|
||||||
|
b: u8,
|
||||||
|
c: S
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(sys::size_of::<S<u8, u8>>(), 3);
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S<u64, u16>>(), 11);
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S<~str, @mut [int]>>(),
|
||||||
|
1 + sys::size_of::<~str>() + sys::size_of::<@mut [int]>());
|
||||||
|
}
|
34
src/test/run-pass/packed-struct-layout.rs
Normal file
34
src/test/run-pass/packed-struct-layout.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S4 {
|
||||||
|
a: u8,
|
||||||
|
b: [u8, .. 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S5 {
|
||||||
|
a: u8,
|
||||||
|
b: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
let s4 = S4 { a: 1, b: [2,3,4] };
|
||||||
|
let transd : [u8, .. 4] = cast::transmute(s4);
|
||||||
|
assert_eq!(transd, [1, 2, 3, 4]);
|
||||||
|
|
||||||
|
let s5 = S5 { a: 1, b: 0xff_00_00_ff };
|
||||||
|
let transd : [u8, .. 5] = cast::transmute(s5);
|
||||||
|
// Don't worry about endianness, the u32 is palindromic.
|
||||||
|
assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
|
||||||
|
}
|
||||||
|
}
|
25
src/test/run-pass/packed-struct-match.rs
Normal file
25
src/test/run-pass/packed-struct-match.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct Foo {
|
||||||
|
bar: u8,
|
||||||
|
baz: uint
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = Foo { bar: 1, baz: 2 };
|
||||||
|
match foo {
|
||||||
|
Foo {bar, baz} => {
|
||||||
|
assert_eq!(bar, 1);
|
||||||
|
assert_eq!(baz, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
src/test/run-pass/packed-struct-size.rs
Normal file
58
src/test/run-pass/packed-struct-size.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S4 {
|
||||||
|
a: u8,
|
||||||
|
b: [u8, .. 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S5 {
|
||||||
|
a: u8,
|
||||||
|
b: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S13_str {
|
||||||
|
a: i64,
|
||||||
|
b: f32,
|
||||||
|
c: u8,
|
||||||
|
d: ~str
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Foo {
|
||||||
|
Bar = 1,
|
||||||
|
Baz = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S3_Foo {
|
||||||
|
a: u8,
|
||||||
|
b: u16,
|
||||||
|
c: Foo
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S7_Option {
|
||||||
|
a: f32,
|
||||||
|
b: u8,
|
||||||
|
c: u16,
|
||||||
|
d: Option<@mut f64>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(sys::size_of::<S4>(), 4);
|
||||||
|
assert_eq!(sys::size_of::<S5>(), 5);
|
||||||
|
assert_eq!(sys::size_of::<S13_str>(), 13 + sys::size_of::<~str>());
|
||||||
|
assert_eq!(sys::size_of::<S3_Foo>(), 3 + sys::size_of::<Foo>());
|
||||||
|
assert_eq!(sys::size_of::<S7_Option>(), 7 + sys::size_of::<Option<@mut f64>>());
|
||||||
|
}
|
30
src/test/run-pass/packed-struct-vec.rs
Normal file
30
src/test/run-pass/packed-struct-vec.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
#[deriving(Eq)]
|
||||||
|
struct Foo {
|
||||||
|
bar: u8,
|
||||||
|
baz: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foos = [Foo { bar: 1, baz: 2 }, .. 10];
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<[Foo, .. 10]>(), 90);
|
||||||
|
|
||||||
|
for uint::range(0, 10) |i| {
|
||||||
|
assert_eq!(foos[i], Foo { bar: 1, baz: 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
for foos.each |&foo| {
|
||||||
|
assert_eq!(foo, Foo { bar: 1, baz: 2 });
|
||||||
|
}
|
||||||
|
}
|
28
src/test/run-pass/packed-tuple-struct-layout.rs
Normal file
28
src/test/run-pass/packed-tuple-struct-layout.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S4(u8,[u8, .. 3]);
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S5(u8,u32);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
let s4 = S4(1, [2,3,4]);
|
||||||
|
let transd : [u8, .. 4] = cast::transmute(s4);
|
||||||
|
assert_eq!(transd, [1, 2, 3, 4]);
|
||||||
|
|
||||||
|
let s5 = S5(1, 0xff_00_00_ff);
|
||||||
|
let transd : [u8, .. 5] = cast::transmute(s5);
|
||||||
|
// Don't worry about endianness, the u32 is palindromic.
|
||||||
|
assert_eq!(transd, [1, 0xff, 0, 0, 0xff]);
|
||||||
|
}
|
||||||
|
}
|
44
src/test/run-pass/packed-tuple-struct-size.rs
Normal file
44
src/test/run-pass/packed-tuple-struct-size.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S4(u8,[u8, .. 3]);
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S5(u8, u32);
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S13_str(i64, f32, u8, ~str);
|
||||||
|
|
||||||
|
enum Foo {
|
||||||
|
Bar = 1,
|
||||||
|
Baz = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S3_Foo(u8, u16, Foo);
|
||||||
|
|
||||||
|
#[packed]
|
||||||
|
struct S7_Option(f32, u8, u16, Option<@mut f64>);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(sys::size_of::<S4>(), 4);
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S5>(), 5);
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S13_str>(),
|
||||||
|
13 + sys::size_of::<~str>());
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S3_Foo>(),
|
||||||
|
3 + sys::size_of::<Foo>());
|
||||||
|
|
||||||
|
assert_eq!(sys::size_of::<S7_Option>(),
|
||||||
|
7 + sys::size_of::<Option<@mut f64>>());
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue