2017-08-29 05:35:51 -07:00
|
|
|
const assert = @import("std").debug.assert;
|
2017-10-02 19:00:42 -07:00
|
|
|
const builtin = @import("builtin");
|
2017-08-29 05:35:51 -07:00
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
var foo: u8 align(4) = 100;
|
2017-08-29 05:35:51 -07:00
|
|
|
|
|
|
|
test "global variable alignment" {
|
2017-08-29 23:41:27 -07:00
|
|
|
assert(@typeOf(&foo).alignment == 4);
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(&foo) == &align(4) u8);
|
2017-08-29 05:35:51 -07:00
|
|
|
const slice = (&foo)[0..1];
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(slice) == []align(4) u8);
|
2017-08-29 05:35:51 -07:00
|
|
|
}
|
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
fn derp() align(@sizeOf(usize) * 2) -> i32 { 1234 }
|
|
|
|
fn noop1() align(1) {}
|
|
|
|
fn noop4() align(4) {}
|
2017-08-29 05:35:51 -07:00
|
|
|
|
|
|
|
test "function alignment" {
|
|
|
|
assert(derp() == 1234);
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(noop1) == fn() align(1));
|
|
|
|
assert(@typeOf(noop4) == fn() align(4));
|
2017-08-29 21:06:14 -07:00
|
|
|
noop1();
|
|
|
|
noop4();
|
2017-08-29 05:35:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var baz: packed struct {
|
|
|
|
a: u32,
|
|
|
|
b: u32,
|
|
|
|
} = undefined;
|
|
|
|
|
|
|
|
test "packed struct alignment" {
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(&baz.b) == &align(1) u32);
|
2017-08-29 05:35:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const blah: packed struct {
|
|
|
|
a: u3,
|
|
|
|
b: u3,
|
|
|
|
c: u2,
|
|
|
|
} = undefined;
|
|
|
|
|
|
|
|
test "bit field alignment" {
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(&blah.b) == &align(1:3:6) const u3);
|
2017-08-29 05:35:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
test "default alignment allows unspecified in type syntax" {
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(&u32 == &align(@alignOf(u32)) u32);
|
2017-08-29 05:35:51 -07:00
|
|
|
}
|
2017-08-29 12:19:15 -07:00
|
|
|
|
|
|
|
test "implicitly decreasing pointer alignment" {
|
2017-08-30 01:54:33 -07:00
|
|
|
const a: u32 align(4) = 3;
|
|
|
|
const b: u32 align(8) = 4;
|
2017-08-29 12:19:15 -07:00
|
|
|
assert(addUnaligned(&a, &b) == 7);
|
|
|
|
}
|
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) -> u32 { *a + *b }
|
2017-08-29 12:19:15 -07:00
|
|
|
|
|
|
|
test "implicitly decreasing slice alignment" {
|
2017-08-30 01:54:33 -07:00
|
|
|
const a: u32 align(4) = 3;
|
|
|
|
const b: u32 align(8) = 4;
|
2017-08-29 12:19:15 -07:00
|
|
|
assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) -> u32 { a[0] + b[0] }
|
2017-08-29 13:52:31 -07:00
|
|
|
|
|
|
|
test "specifying alignment allows pointer cast" {
|
|
|
|
testBytesAlign(0x33);
|
|
|
|
}
|
|
|
|
fn testBytesAlign(b: u8) {
|
2017-08-30 01:54:33 -07:00
|
|
|
var bytes align(4) = []u8{b, b, b, b};
|
2017-08-29 13:52:31 -07:00
|
|
|
const ptr = @ptrCast(&u32, &bytes[0]);
|
|
|
|
assert(*ptr == 0x33333333);
|
|
|
|
}
|
2017-08-29 20:33:25 -07:00
|
|
|
|
|
|
|
test "specifying alignment allows slice cast" {
|
|
|
|
testBytesAlignSlice(0x33);
|
|
|
|
}
|
|
|
|
fn testBytesAlignSlice(b: u8) {
|
2017-08-30 01:54:33 -07:00
|
|
|
var bytes align(4) = []u8{b, b, b, b};
|
2017-08-29 20:33:25 -07:00
|
|
|
const slice = ([]u32)(bytes[0..]);
|
|
|
|
assert(slice[0] == 0x33333333);
|
|
|
|
}
|
|
|
|
|
2017-08-29 20:39:54 -07:00
|
|
|
test "@alignCast pointers" {
|
2017-08-30 01:54:33 -07:00
|
|
|
var x: u32 align(4) = 1;
|
2017-08-29 20:33:25 -07:00
|
|
|
expectsOnly1(&x);
|
|
|
|
assert(x == 2);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn expectsOnly1(x: &align(1) u32) {
|
2017-08-29 20:33:25 -07:00
|
|
|
expects4(@alignCast(4, x));
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn expects4(x: &align(4) u32) {
|
2017-08-29 20:33:25 -07:00
|
|
|
*x += 1;
|
|
|
|
}
|
2017-08-29 20:39:54 -07:00
|
|
|
|
|
|
|
test "@alignCast slices" {
|
2017-08-30 01:54:33 -07:00
|
|
|
var array align(4) = []u32{1, 1};
|
2017-08-29 20:39:54 -07:00
|
|
|
const slice = array[0..];
|
|
|
|
sliceExpectsOnly1(slice);
|
|
|
|
assert(slice[0] == 2);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn sliceExpectsOnly1(slice: []align(1) u32) {
|
2017-08-29 20:39:54 -07:00
|
|
|
sliceExpects4(@alignCast(4, slice));
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn sliceExpects4(slice: []align(4) u32) {
|
2017-08-29 20:39:54 -07:00
|
|
|
slice[0] += 1;
|
|
|
|
}
|
2017-08-29 21:06:14 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "implicitly decreasing fn alignment" {
|
|
|
|
testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
|
|
|
|
testImplicitlyDecreaseFnAlign(alignedBig, 5678);
|
|
|
|
}
|
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) -> i32, answer: i32) {
|
2017-08-29 21:06:14 -07:00
|
|
|
assert(ptr() == answer);
|
|
|
|
}
|
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
fn alignedSmall() align(8) -> i32 { 1234 }
|
|
|
|
fn alignedBig() align(16) -> i32 { 5678 }
|
2017-08-29 21:06:14 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "@alignCast functions" {
|
|
|
|
assert(fnExpectsOnly1(simple4) == 0x19);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn fnExpectsOnly1(ptr: fn()align(1) -> i32) -> i32 {
|
2017-08-29 21:06:14 -07:00
|
|
|
fnExpects4(@alignCast(4, ptr))
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn fnExpects4(ptr: fn()align(4) -> i32) -> i32 {
|
2017-08-29 21:06:14 -07:00
|
|
|
ptr()
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn simple4() align(4) -> i32 { 0x19 }
|
2017-08-29 21:46:38 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "generic function with align param" {
|
|
|
|
assert(whyWouldYouEverDoThis(1) == 0x1);
|
|
|
|
assert(whyWouldYouEverDoThis(4) == 0x1);
|
|
|
|
assert(whyWouldYouEverDoThis(8) == 0x1);
|
|
|
|
}
|
|
|
|
|
2017-08-30 01:54:33 -07:00
|
|
|
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) -> u8 { 0x1 }
|
2017-08-29 22:12:47 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "@ptrCast preserves alignment of bigger source" {
|
2017-08-30 01:54:33 -07:00
|
|
|
var x: u32 align(16) = 1234;
|
2017-08-29 22:12:47 -07:00
|
|
|
const ptr = @ptrCast(&u8, &x);
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(ptr) == &align(16) u8);
|
2017-08-29 22:12:47 -07:00
|
|
|
}
|
2017-08-29 23:25:41 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "compile-time known array index has best alignment possible" {
|
|
|
|
// take full advantage of over-alignment
|
2017-08-30 01:54:33 -07:00
|
|
|
var array align(4) = []u8 {1, 2, 3, 4};
|
|
|
|
assert(@typeOf(&array[0]) == &align(4) u8);
|
2017-08-29 23:25:41 -07:00
|
|
|
assert(@typeOf(&array[1]) == &u8);
|
2017-08-30 01:54:33 -07:00
|
|
|
assert(@typeOf(&array[2]) == &align(2) u8);
|
2017-08-29 23:25:41 -07:00
|
|
|
assert(@typeOf(&array[3]) == &u8);
|
|
|
|
|
|
|
|
// because align is too small but we still figure out to use 2
|
2017-08-30 01:54:33 -07:00
|
|
|
var bigger align(2) = []u64{1, 2, 3, 4};
|
|
|
|
assert(@typeOf(&bigger[0]) == &align(2) u64);
|
|
|
|
assert(@typeOf(&bigger[1]) == &align(2) u64);
|
|
|
|
assert(@typeOf(&bigger[2]) == &align(2) u64);
|
|
|
|
assert(@typeOf(&bigger[3]) == &align(2) u64);
|
2017-08-29 23:25:41 -07:00
|
|
|
|
|
|
|
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
|
2017-08-30 01:54:33 -07:00
|
|
|
var smaller align(2) = []u32{1, 2, 3, 4};
|
|
|
|
testIndex(&smaller[0], 0, &align(2) u32);
|
|
|
|
testIndex(&smaller[0], 1, &align(2) u32);
|
|
|
|
testIndex(&smaller[0], 2, &align(2) u32);
|
|
|
|
testIndex(&smaller[0], 3, &align(2) u32);
|
2017-08-29 23:25:41 -07:00
|
|
|
|
|
|
|
// has to use ABI alignment because index known at runtime only
|
|
|
|
testIndex2(&array[0], 0, &u8);
|
|
|
|
testIndex2(&array[0], 1, &u8);
|
|
|
|
testIndex2(&array[0], 2, &u8);
|
|
|
|
testIndex2(&array[0], 3, &u8);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn testIndex(smaller: &align(2) u32, index: usize, comptime T: type) {
|
2017-08-29 23:25:41 -07:00
|
|
|
assert(@typeOf(&smaller[index]) == T);
|
|
|
|
}
|
2017-08-30 01:54:33 -07:00
|
|
|
fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) {
|
2017-08-29 23:25:41 -07:00
|
|
|
assert(@typeOf(&ptr[index]) == T);
|
|
|
|
}
|
2017-10-02 19:00:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
test "alignstack" {
|
2017-10-02 22:14:29 -07:00
|
|
|
assert(fnWithAlignedStack() == 1234);
|
2017-10-02 19:00:42 -07:00
|
|
|
}
|
|
|
|
|
2017-10-02 22:14:29 -07:00
|
|
|
fn fnWithAlignedStack() -> i32 {
|
2017-10-23 19:33:00 -07:00
|
|
|
@setAlignStack(256);
|
2017-10-02 22:14:29 -07:00
|
|
|
return 1234;
|
2017-10-02 19:00:42 -07:00
|
|
|
}
|