Commit f1b91bb41b
Changed files (6)
test
src/codegen/c.zig
@@ -121,7 +121,13 @@ pub const Function = struct {
const decl_c_value = f.allocLocalValue();
gop.value_ptr.* = decl_c_value;
try writer.writeAll("static ");
- try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const);
+ try f.object.dg.renderTypeAndName(
+ writer,
+ ty,
+ decl_c_value,
+ .Const,
+ Value.initTag(.abi_align_default),
+ );
try writer.writeAll(" = ");
try f.object.dg.renderValue(writer, ty, val);
try writer.writeAll(";\n ");
@@ -142,8 +148,18 @@ pub const Function = struct {
}
fn allocLocal(f: *Function, ty: Type, mutability: Mutability) !CValue {
+ return f.allocAlignedLocal(ty, mutability, Value.initTag(.abi_align_default));
+ }
+
+ fn allocAlignedLocal(f: *Function, ty: Type, mutability: Mutability, alignment: Value) !CValue {
const local_value = f.allocLocalValue();
- try f.object.dg.renderTypeAndName(f.object.writer(), ty, local_value, mutability);
+ try f.object.dg.renderTypeAndName(
+ f.object.writer(),
+ ty,
+ local_value,
+ mutability,
+ alignment,
+ );
return local_value;
}
@@ -711,9 +727,11 @@ pub const DeclGen = struct {
while (it.next()) |entry| {
const field_ty = entry.value_ptr.ty;
if (!field_ty.hasCodeGenBits()) continue;
+
+ const alignment = entry.value_ptr.abi_align;
const name: CValue = .{ .bytes = entry.key_ptr.* };
try buffer.append(' ');
- try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut);
+ try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
try buffer.appendSlice(";\n");
}
}
@@ -950,6 +968,7 @@ pub const DeclGen = struct {
ty: Type,
name: CValue,
mutability: Mutability,
+ alignment: Value,
) error{ OutOfMemory, AnalysisFail }!void {
var suffix = std.ArrayList(u8).init(dg.gpa);
defer suffix.deinit();
@@ -962,6 +981,8 @@ pub const DeclGen = struct {
render_ty = render_ty.elemType();
}
+ if (alignment.tag() != .abi_align_default and alignment.tag() != .null_value)
+ try w.print("ZIG_ALIGN({}) ", .{alignment.toUnsignedInt()});
try dg.renderType(w, render_ty);
const const_prefix = switch (mutability) {
@@ -1118,7 +1139,7 @@ pub fn genDecl(o: *Object) !void {
// https://github.com/ziglang/zig/issues/7582
const decl_c_value: CValue = .{ .decl = o.dg.decl };
- try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut);
+ try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.align_val);
try writer.writeAll(" = ");
try o.dg.renderValue(writer, tv.ty, tv.val);
@@ -1460,8 +1481,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
return CValue{ .bytes = literal };
}
+ const target = f.object.dg.module.getTarget();
+ const alignment = inst_ty.ptrAlignment(target);
+ var payload = Value.Payload.U64{
+ .base = .{ .tag = .int_u64 },
+ .data = alignment,
+ };
+ const alignment_value = Value.initPayload(&payload.base);
+
// First line: the variable used as data storage.
- const local = try f.allocLocal(elem_type, mutability);
+ const local = try f.allocAlignedLocal(elem_type, mutability, alignment_value);
try writer.writeAll(";\n");
// Arrays are already pointers so they don't need to be referenced.
src/link/C/zig.h
@@ -26,6 +26,15 @@
#define ZIG_RESTRICT
#endif
+#if __STDC_VERSION__ >= 201112L
+#include <stdalign.h>
+#define ZIG_ALIGN(alignment) alignas(alignment)
+#elif defined(__GNUC__)
+#define ZIG_ALIGN(alignment) __attribute__((aligned(alignment)))
+#else
+#define ZIG_ALIGN(alignment) zig_compile_error("the C compiler being used does not support aligning variables")
+#endif
+
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
test/behavior/align.zig
@@ -163,3 +163,21 @@ test "return error union with 128-bit integer" {
fn give() anyerror!u128 {
return 3;
}
+
+test "page aligned array on stack" {
+ if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm or
+ builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
+
+ // Large alignment value to make it hard to accidentally pass.
+ var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
+ var number1: u8 align(16) = 42;
+ var number2: u8 align(16) = 43;
+
+ try expect(@ptrToInt(&array[0]) & 0xFFF == 0);
+ try expect(array[3] == 4);
+
+ try expect(@truncate(u4, @ptrToInt(&number1)) == 0);
+ try expect(@truncate(u4, @ptrToInt(&number2)) == 0);
+ try expect(number1 == 42);
+ try expect(number2 == 43);
+}
test/behavior/align_llvm.zig
@@ -1,19 +0,0 @@
-const std = @import("std");
-const expect = std.testing.expect;
-const builtin = @import("builtin");
-const native_arch = builtin.target.cpu.arch;
-
-test "page aligned array on stack" {
- // Large alignment value to make it hard to accidentally pass.
- var array align(0x1000) = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
- var number1: u8 align(16) = 42;
- var number2: u8 align(16) = 43;
-
- try expect(@ptrToInt(&array[0]) & 0xFFF == 0);
- try expect(array[3] == 4);
-
- try expect(@truncate(u4, @ptrToInt(&number1)) == 0);
- try expect(@truncate(u4, @ptrToInt(&number2)) == 0);
- try expect(number1 == 42);
- try expect(number2 == 43);
-}
test/behavior/struct.zig
@@ -201,6 +201,8 @@ test "struct field init with catch" {
}
test "packed struct field alignment" {
+ if (builtin.object_format == .c) return error.SkipZigTest;
+
const Stage1 = struct {
var baz: packed struct {
a: u32,
test/behavior.zig
@@ -71,7 +71,6 @@ test {
if (builtin.zig_backend != .stage2_c) {
// Tests that pass for stage1 and the llvm backend.
- _ = @import("behavior/align_llvm.zig");
_ = @import("behavior/alignof.zig");
_ = @import("behavior/array_llvm.zig");
_ = @import("behavior/atomics.zig");