Skip to content

Commit f92015f

Browse files
committed
auto merge of #16499 : cmr/rust/struct-undef-repr, r=pcwalton
r? @pcwalton
2 parents 4444aec + 01d2efa commit f92015f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+505
-219
lines changed

src/doc/guide-ffi.md

+10-9
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,13 @@ Rust code:
263263
264264
~~~~no_run
265265
266+
#[repr(C)]
266267
struct RustObject {
267268
a: i32,
268269
// other members
269270
}
270271
271-
extern fn callback(target: *mut RustObject, a:i32) {
272+
extern "C" fn callback(target: *mut RustObject, a:i32) {
272273
println!("I'm called from C with value {0}", a);
273274
unsafe {
274275
// Update the value in RustObject with the value received from the callback
@@ -506,16 +507,16 @@ to define a block for all windows systems, not just x86 ones.
506507
507508
# Interoperability with foreign code
508509
509-
Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C.
510-
A `#[packed]` attribute is available, which will lay out the struct members without padding.
511-
However, there are currently no guarantees about the layout of an `enum`.
510+
Rust guarantees that the layout of a `struct` is compatible with the platform's representation in C
511+
only if the `#[repr(C)]` attribute is applied to it. `#[repr(C, packed)]` can be used to lay out
512+
struct members without padding. `#[repr(C)]` can also be applied to an enum.
512513
513-
Rust's owned and managed boxes use non-nullable pointers as handles which point to the contained
514+
Rust's owned boxes (`Box<T>`) use non-nullable pointers as handles which point to the contained
514515
object. However, they should not be manually created because they are managed by internal
515-
allocators. References can safely be assumed to be non-nullable pointers directly to the
516-
type. However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so
517-
prefer using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions
518-
about them.
516+
allocators. References can safely be assumed to be non-nullable pointers directly to the type.
517+
However, breaking the borrow checking or mutability rules is not guaranteed to be safe, so prefer
518+
using raw pointers (`*`) if that's needed because the compiler can't make as many assumptions about
519+
them.
519520
520521
Vectors and strings share the same basic memory layout, and utilities are available in the `vec` and
521522
`str` modules for working with C APIs. However, strings are not terminated with `\0`. If you need a

src/doc/rust.md

+20-6
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,9 @@ struct Cookie;
13081308
let c = [Cookie, Cookie, Cookie, Cookie];
13091309
~~~~
13101310

1311+
The precise memory layout of a structure is not specified. One can specify a
1312+
particular layout using the [`repr` attribute](#ffi-attributes).
1313+
13111314
By using the `struct_inherit` feature gate, structures may use single inheritance. A Structure may only
13121315
inherit from a single other structure, called the _super-struct_. The inheriting structure (sub-struct)
13131316
acts as if all fields in the super-struct were present in the sub-struct. Fields declared in a sub-struct
@@ -1941,6 +1944,23 @@ interpreted:
19411944
- `linkage` - on a static, this specifies the [linkage
19421945
type](http://llvm.org/docs/LangRef.html#linkage-types).
19431946

1947+
On `enum`s:
1948+
1949+
- `repr` - on C-like enums, this sets the underlying type used for
1950+
representation. Takes one argument, which is the primitive
1951+
type this enum should be represented for, or `C`, which specifies that it
1952+
should be the default `enum` size of the C ABI for that platform. Note that
1953+
enum representation in C is undefined, and this may be incorrect when the C
1954+
code is compiled with certain flags.
1955+
1956+
On `struct`s:
1957+
1958+
- `repr` - specifies the representation to use for this struct. Takes a list
1959+
of options. The currently accepted ones are `C` and `packed`, which may be
1960+
combined. `C` will use a C ABI comptible struct layout, and `packed` will
1961+
remove any padding between fields (note that this is very fragile and may
1962+
break platforms which require aligned access).
1963+
19441964
### Miscellaneous attributes
19451965

19461966
- `export_name` - on statics and functions, this determines the name of the
@@ -1958,12 +1978,6 @@ interpreted:
19581978
crate at compile-time and use any syntax extensions or lints that the crate
19591979
defines. They can both be specified, `#[phase(link, plugin)]` to use a crate
19601980
both at runtime and compiletime.
1961-
- `repr` - on C-like enums, this sets the underlying type used for
1962-
representation. Useful for FFI. Takes one argument, which is the primitive
1963-
type this enum should be represented for, or `C`, which specifies that it
1964-
should be the default `enum` size of the C ABI for that platform. Note that
1965-
enum representation in C is undefined, and this may be incorrect when the C
1966-
code is compiled with certain flags.
19671981
- `simd` - on certain tuple structs, derive the arithmetic operators, which
19681982
lower to the target's SIMD instructions, if any; the `simd` feature gate
19691983
is necessary to use this attribute.

src/libcore/simd.rs

+10
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#[experimental]
4141
#[simd]
4242
#[deriving(Show)]
43+
#[repr(C)]
4344
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
4445
pub i8, pub i8, pub i8, pub i8,
4546
pub i8, pub i8, pub i8, pub i8,
@@ -48,22 +49,26 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
4849
#[experimental]
4950
#[simd]
5051
#[deriving(Show)]
52+
#[repr(C)]
5153
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
5254
pub i16, pub i16, pub i16, pub i16);
5355

5456
#[experimental]
5557
#[simd]
5658
#[deriving(Show)]
59+
#[repr(C)]
5760
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
5861

5962
#[experimental]
6063
#[simd]
6164
#[deriving(Show)]
65+
#[repr(C)]
6266
pub struct i64x2(pub i64, pub i64);
6367

6468
#[experimental]
6569
#[simd]
6670
#[deriving(Show)]
71+
#[repr(C)]
6772
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
6873
pub u8, pub u8, pub u8, pub u8,
6974
pub u8, pub u8, pub u8, pub u8,
@@ -72,25 +77,30 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
7277
#[experimental]
7378
#[simd]
7479
#[deriving(Show)]
80+
#[repr(C)]
7581
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
7682
pub u16, pub u16, pub u16, pub u16);
7783

7884
#[experimental]
7985
#[simd]
8086
#[deriving(Show)]
87+
#[repr(C)]
8188
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
8289

8390
#[experimental]
8491
#[simd]
8592
#[deriving(Show)]
93+
#[repr(C)]
8694
pub struct u64x2(pub u64, pub u64);
8795

8896
#[experimental]
8997
#[simd]
9098
#[deriving(Show)]
99+
#[repr(C)]
91100
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
92101

93102
#[experimental]
94103
#[simd]
95104
#[deriving(Show)]
105+
#[repr(C)]
96106
pub struct f64x2(pub f64, pub f64);

src/libgreen/context.rs

+28-25
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::rt::stack;
1515
use std::raw;
1616
#[cfg(target_arch = "x86_64")]
1717
use std::simd;
18+
use libc;
1819

1920
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
2021
// SSE regs. It would be marginally better not to do this. In C++ we
@@ -69,7 +70,7 @@ impl Context {
6970
// overflow). Additionally, their coroutine stacks are listed as being
7071
// zero-length, so that's how we detect what's what here.
7172
let stack_base: *const uint = stack.start();
72-
let bounds = if sp as uint == stack_base as uint {
73+
let bounds = if sp as libc::uintptr_t == stack_base as libc::uintptr_t {
7374
None
7475
} else {
7576
Some((stack_base as uint, sp as uint))
@@ -166,7 +167,7 @@ fn new_regs() -> Box<Registers> {
166167
#[cfg(target_arch = "x86")]
167168
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
168169
procedure: raw::Procedure, sp: *mut uint) {
169-
170+
let sp = sp as *mut uint;
170171
// x86 has interesting stack alignment requirements, so do some alignment
171172
// plus some offsetting to figure out what the actual stack should be.
172173
let sp = align_down(sp);
@@ -188,13 +189,15 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
188189
// windows requires saving more registers (both general and XMM), so the windows
189190
// register context must be larger.
190191
#[cfg(windows, target_arch = "x86_64")]
192+
#[repr(C)]
191193
struct Registers {
192-
gpr:[uint, ..14],
194+
gpr:[libc::uintptr_t, ..14],
193195
_xmm:[simd::u32x4, ..10]
194196
}
195197
#[cfg(not(windows), target_arch = "x86_64")]
198+
#[repr(C)]
196199
struct Registers {
197-
gpr:[uint, ..10],
200+
gpr:[libc::uintptr_t, ..10],
198201
_xmm:[simd::u32x4, ..6]
199202
}
200203

@@ -234,30 +237,30 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
234237
unsafe { *sp = 0; }
235238

236239
rtdebug!("creating call frame");
237-
rtdebug!("fptr {:#x}", fptr as uint);
240+
rtdebug!("fptr {:#x}", fptr as libc::uintptr_t);
238241
rtdebug!("arg {:#x}", arg);
239242
rtdebug!("sp {}", sp);
240243

241244
// These registers are frobbed by rust_bootstrap_green_task into the right
242245
// location so we can invoke the "real init function", `fptr`.
243-
regs.gpr[RUSTRT_R12] = arg as uint;
244-
regs.gpr[RUSTRT_R13] = procedure.code as uint;
245-
regs.gpr[RUSTRT_R14] = procedure.env as uint;
246-
regs.gpr[RUSTRT_R15] = fptr as uint;
246+
regs.gpr[RUSTRT_R12] = arg as libc::uintptr_t;
247+
regs.gpr[RUSTRT_R13] = procedure.code as libc::uintptr_t;
248+
regs.gpr[RUSTRT_R14] = procedure.env as libc::uintptr_t;
249+
regs.gpr[RUSTRT_R15] = fptr as libc::uintptr_t;
247250

248251
// These registers are picked up by the regular context switch paths. These
249252
// will put us in "mostly the right context" except for frobbing all the
250253
// arguments to the right place. We have the small trampoline code inside of
251254
// rust_bootstrap_green_task to do that.
252-
regs.gpr[RUSTRT_RSP] = sp as uint;
253-
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as uint;
255+
regs.gpr[RUSTRT_RSP] = sp as libc::uintptr_t;
256+
regs.gpr[RUSTRT_IP] = rust_bootstrap_green_task as libc::uintptr_t;
254257

255258
// Last base pointer on the stack should be 0
256259
regs.gpr[RUSTRT_RBP] = 0;
257260
}
258261

259262
#[cfg(target_arch = "arm")]
260-
type Registers = [uint, ..32];
263+
type Registers = [libc::uintptr_t, ..32];
261264

262265
#[cfg(target_arch = "arm")]
263266
fn new_regs() -> Box<Registers> { box {[0, .. 32]} }
@@ -277,17 +280,17 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
277280
// ARM uses the same technique as x86_64 to have a landing pad for the start
278281
// of all new green tasks. Neither r1/r2 are saved on a context switch, so
279282
// the shim will copy r3/r4 into r1/r2 and then execute the function in r5
280-
regs[0] = arg as uint; // r0
281-
regs[3] = procedure.code as uint; // r3
282-
regs[4] = procedure.env as uint; // r4
283-
regs[5] = fptr as uint; // r5
284-
regs[13] = sp as uint; // #52 sp, r13
285-
regs[14] = rust_bootstrap_green_task as uint; // #56 pc, r14 --> lr
283+
regs[0] = arg as libc::uintptr_t; // r0
284+
regs[3] = procedure.code as libc::uintptr_t; // r3
285+
regs[4] = procedure.env as libc::uintptr_t; // r4
286+
regs[5] = fptr as libc::uintptr_t; // r5
287+
regs[13] = sp as libc::uintptr_t; // #52 sp, r13
288+
regs[14] = rust_bootstrap_green_task as libc::uintptr_t; // #56 pc, r14 --> lr
286289
}
287290

288291
#[cfg(target_arch = "mips")]
289292
#[cfg(target_arch = "mipsel")]
290-
type Registers = [uint, ..32];
293+
type Registers = [libc::uintptr_t, ..32];
291294

292295
#[cfg(target_arch = "mips")]
293296
#[cfg(target_arch = "mipsel")]
@@ -304,12 +307,12 @@ fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
304307
// The final return address. 0 indicates the bottom of the stack
305308
unsafe { *sp = 0; }
306309

307-
regs[4] = arg as uint;
308-
regs[5] = procedure.code as uint;
309-
regs[6] = procedure.env as uint;
310-
regs[29] = sp as uint;
311-
regs[25] = fptr as uint;
312-
regs[31] = fptr as uint;
310+
regs[4] = arg as libc::uintptr_t;
311+
regs[5] = procedure.code as libc::uintptr_t;
312+
regs[6] = procedure.env as libc::uintptr_t;
313+
regs[29] = sp as libc::uintptr_t;
314+
regs[25] = fptr as libc::uintptr_t;
315+
regs[31] = fptr as libc::uintptr_t;
313316
}
314317

315318
fn align_down(sp: *mut uint) -> *mut uint {

src/libgreen/stack.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ impl Stack {
6868

6969
// FIXME: Using the FFI to call a C macro. Slow
7070
stk.valgrind_id = unsafe {
71-
rust_valgrind_stack_register(stk.start(), stk.end())
71+
rust_valgrind_stack_register(stk.start() as *const libc::uintptr_t,
72+
stk.end() as *const libc::uintptr_t)
7273
};
7374
return stk;
7475
}

0 commit comments

Comments
 (0)