authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-02 20:26:33+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-03 01:04:46+03:00
logb83c037f9ffd7a4285de41c95827615fcbdbbf2f
tree25b6f3ce249c9b77603a47647fc9d658980da08a
parent6aee07c1446f3ce98d326998c887fbca3b7fd945

Sema: only ABI sized packed structs are extern compatible


9 files changed, 116 insertions(+), 125 deletions(-)

src/Sema.zig+31-16
...@@ -5056,7 +5056,7 @@ pub fn analyzeExport(...@@ -5056,7 +5056,7 @@ pub fn analyzeExport(
5056 try mod.ensureDeclAnalyzed(exported_decl_index);5056 try mod.ensureDeclAnalyzed(exported_decl_index);
5057 const exported_decl = mod.declPtr(exported_decl_index);5057 const exported_decl = mod.declPtr(exported_decl_index);
50585058
5059 if (!sema.validateExternType(exported_decl.ty, .other)) {5059 if (!try sema.validateExternType(block, src, exported_decl.ty, .other)) {
5060 const msg = msg: {5060 const msg = msg: {
5061 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});5061 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5062 errdefer msg.destroy(sema.gpa);5062 errdefer msg.destroy(sema.gpa);
...@@ -7896,7 +7896,7 @@ fn funcCommon(...@@ -7896,7 +7896,7 @@ fn funcCommon(
7896 };7896 };
7897 return sema.failWithOwnedErrorMsg(msg);7897 return sema.failWithOwnedErrorMsg(msg);
7898 }7898 }
7899 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {7899 if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !try sema.validateExternType(block, ret_ty_src, return_type, .ret_ty)) {
7900 const msg = msg: {7900 const msg = msg: {
7901 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{7901 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
7902 return_type.fmt(sema.mod), @tagName(cc_workaround),7902 return_type.fmt(sema.mod), @tagName(cc_workaround),
...@@ -8115,7 +8115,7 @@ fn analyzeParameter(...@@ -8115,7 +8115,7 @@ fn analyzeParameter(
8115 };8115 };
8116 return sema.failWithOwnedErrorMsg(msg);8116 return sema.failWithOwnedErrorMsg(msg);
8117 }8117 }
8118 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {8118 if (!Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(block, param_src, param.ty, .param_ty)) {
8119 const msg = msg: {8119 const msg = msg: {
8120 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{8120 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
8121 param.ty.fmt(sema.mod), @tagName(cc),8121 param.ty.fmt(sema.mod), @tagName(cc),
...@@ -15583,7 +15583,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -15583,7 +15583,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
15583 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {15583 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
15584 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});15584 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
15585 } else if (inst_data.size == .C) {15585 } else if (inst_data.size == .C) {
15586 if (!sema.validateExternType(elem_ty, .other)) {15586 if (!try sema.validateExternType(block, elem_ty_src, elem_ty, .other)) {
15587 const msg = msg: {15587 const msg = msg: {
15588 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});15588 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
15589 errdefer msg.destroy(sema.gpa);15589 errdefer msg.destroy(sema.gpa);
...@@ -16681,7 +16681,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in...@@ -16681,7 +16681,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
16681 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {16681 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
16682 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});16682 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
16683 } else if (ptr_size == .C) {16683 } else if (ptr_size == .C) {
16684 if (!sema.validateExternType(elem_ty, .other)) {16684 if (!try sema.validateExternType(block, src, elem_ty, .other)) {
16685 const msg = msg: {16685 const msg = msg: {
16686 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});16686 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
16687 errdefer msg.destroy(sema.gpa);16687 errdefer msg.destroy(sema.gpa);
...@@ -20549,7 +20549,14 @@ const ExternPosition = enum {...@@ -20549,7 +20549,14 @@ const ExternPosition = enum {
2054920549
20550/// Returns true if `ty` is allowed in extern types.20550/// Returns true if `ty` is allowed in extern types.
20551/// Does *NOT* require `ty` to be resolved in any way.20551/// Does *NOT* require `ty` to be resolved in any way.
20552fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {20552/// Calls `resolveTypeLayout` for packed containers.
20553fn validateExternType(
20554 sema: *Sema,
20555 block: *Block,
20556 src: LazySrcLoc,
20557 ty: Type,
20558 position: ExternPosition,
20559) !bool {
20553 switch (ty.zigTypeTag()) {20560 switch (ty.zigTypeTag()) {
20554 .Type,20561 .Type,
20555 .ComptimeFloat,20562 .ComptimeFloat,
...@@ -20577,17 +20584,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {...@@ -20577,17 +20584,25 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
20577 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),20584 .Fn => return !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()),
20578 .Enum => {20585 .Enum => {
20579 var buf: Type.Payload.Bits = undefined;20586 var buf: Type.Payload.Bits = undefined;
20580 return sema.validateExternType(ty.intTagType(&buf), position);20587 return sema.validateExternType(block, src, ty.intTagType(&buf), position);
20581 },20588 },
20582 .Struct, .Union => switch (ty.containerLayout()) {20589 .Struct, .Union => switch (ty.containerLayout()) {
20583 .Extern, .Packed => return true,20590 .Extern => return true,
20584 else => return false,20591 .Packed => {
20592 const target = sema.mod.getTarget();
20593 const bit_size = try ty.bitSizeAdvanced(target, sema.kit(block, src));
20594 switch (bit_size) {
20595 8, 16, 32, 64, 128 => return true,
20596 else => return false,
20597 }
20598 },
20599 .Auto => return false,
20585 },20600 },
20586 .Array => {20601 .Array => {
20587 if (position == .ret_ty or position == .param_ty) return false;20602 if (position == .ret_ty or position == .param_ty) return false;
20588 return sema.validateExternType(ty.elemType2(), .other);20603 return sema.validateExternType(block, src, ty.elemType2(), .other);
20589 },20604 },
20590 .Vector => return sema.validateExternType(ty.elemType2(), .other),20605 .Vector => return sema.validateExternType(block, src, ty.elemType2(), .other),
20591 .Optional => return ty.isPtrLikeOptional(),20606 .Optional => return ty.isPtrLikeOptional(),
20592 }20607 }
20593}20608}
...@@ -20639,8 +20654,8 @@ fn explainWhyTypeIsNotExtern(...@@ -20639,8 +20654,8 @@ fn explainWhyTypeIsNotExtern(
20639 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});20654 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
20640 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);20655 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
20641 },20656 },
20642 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),20657 .Struct => try mod.errNoteNonLazy(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
20643 .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),20658 .Union => try mod.errNoteNonLazy(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}),
20644 .Array => {20659 .Array => {
20645 if (position == .ret_ty) {20660 if (position == .ret_ty) {
20646 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});20661 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a return type", .{});
...@@ -24119,7 +24134,7 @@ fn coerceVarArgParam(...@@ -24119,7 +24134,7 @@ fn coerceVarArgParam(
24119 };24134 };
2412024135
24121 const coerced_ty = sema.typeOf(coerced);24136 const coerced_ty = sema.typeOf(coerced);
24122 if (!sema.validateExternType(coerced_ty, .other)) {24137 if (!try sema.validateExternType(block, inst_src, coerced_ty, .other)) {
24123 const msg = msg: {24138 const msg = msg: {
24124 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});24139 const msg = try sema.errMsg(block, inst_src, "cannot pass '{}' to variadic function", .{coerced_ty.fmt(sema.mod)});
24125 errdefer msg.destroy(sema.gpa);24140 errdefer msg.destroy(sema.gpa);
...@@ -28321,7 +28336,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -28321,7 +28336,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
28321 };28336 };
28322 return sema.failWithOwnedErrorMsg(msg);28337 return sema.failWithOwnedErrorMsg(msg);
28323 }28338 }
28324 if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {28339 if (struct_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field.ty, .other)) {
28325 const msg = msg: {28340 const msg = msg: {
28326 const tree = try sema.getAstTree(&block_scope);28341 const tree = try sema.getAstTree(&block_scope);
28327 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);28342 const fields_src = enumFieldSrcLoc(decl, tree.*, 0, i);
...@@ -28658,7 +28673,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -28658,7 +28673,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
28658 };28673 };
28659 return sema.failWithOwnedErrorMsg(msg);28674 return sema.failWithOwnedErrorMsg(msg);
28660 }28675 }
28661 if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) {28676 if (union_obj.layout == .Extern and !try sema.validateExternType(&block_scope, src, field_ty, .union_field)) {
28662 const msg = msg: {28677 const msg = msg: {
28663 const tree = try sema.getAstTree(&block_scope);28678 const tree = try sema.getAstTree(&block_scope);
28664 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);28679 const field_src = enumFieldSrcLoc(decl, tree.*, 0, field_i);
src/arch/wasm/abi.zig+8
...@@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -23,6 +23,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;
24 switch (ty.zigTypeTag()) {24 switch (ty.zigTypeTag()) {
25 .Struct => {25 .Struct => {
26 if (ty.containerLayout() == .Packed) {
27 if (ty.bitSize(target) <= 64) return direct;
28 return .{ .direct, .direct };
29 }
26 // When the struct type is non-scalar30 // When the struct type is non-scalar
27 if (ty.structFieldCount() > 1) return memory;31 if (ty.structFieldCount() > 1) return memory;
28 // When the struct's alignment is non-natural32 // When the struct's alignment is non-natural
...@@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {...@@ -57,6 +61,10 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
57 return direct;61 return direct;
58 },62 },
59 .Union => {63 .Union => {
64 if (ty.containerLayout() == .Packed) {
65 if (ty.bitSize(target) <= 64) return direct;
66 return .{ .direct, .direct };
67 }
60 const layout = ty.unionGetLayout(target);68 const layout = ty.unionGetLayout(target);
61 std.debug.assert(layout.tag_size == 0);69 std.debug.assert(layout.tag_size == 0);
62 if (ty.unionFields().count() > 1) return memory;70 if (ty.unionFields().count() > 1) return memory;
src/arch/x86_64/abi.zig+12
...@@ -174,6 +174,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -174,6 +174,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
174 // "If the size of the aggregate exceeds a single eightbyte, each is classified174 // "If the size of the aggregate exceeds a single eightbyte, each is classified
175 // separately.".175 // separately.".
176 const ty_size = ty.abiSize(target);176 const ty_size = ty.abiSize(target);
177 if (ty.containerLayout() == .Packed) {
178 assert(ty_size <= 128);
179 result[0] = .integer;
180 if (ty_size > 64) result[1] = .integer;
181 return result;
182 }
177 if (ty_size > 64)183 if (ty_size > 64)
178 return memory_class;184 return memory_class;
179185
...@@ -284,6 +290,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -284,6 +290,12 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
284 // "If the size of the aggregate exceeds a single eightbyte, each is classified290 // "If the size of the aggregate exceeds a single eightbyte, each is classified
285 // separately.".291 // separately.".
286 const ty_size = ty.abiSize(target);292 const ty_size = ty.abiSize(target);
293 if (ty.containerLayout() == .Packed) {
294 assert(ty_size <= 128);
295 result[0] = .integer;
296 if (ty_size > 64) result[1] = .integer;
297 return result;
298 }
287 if (ty_size > 64)299 if (ty_size > 64)
288 return memory_class;300 return memory_class;
289301
src/codegen/llvm.zig+23-34
...@@ -9674,22 +9674,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm....@@ -9674,22 +9674,7 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*const llvm.
9674 }9674 }
9675 },9675 },
9676 .C => {9676 .C => {
9677 const is_scalar = switch (fn_info.return_type.zigTypeTag()) {9677 const is_scalar = isScalar(fn_info.return_type);
9678 .Void,
9679 .Bool,
9680 .NoReturn,
9681 .Int,
9682 .Float,
9683 .Pointer,
9684 .Optional,
9685 .ErrorSet,
9686 .Enum,
9687 .AnyFrame,
9688 .Vector,
9689 => true,
9690
9691 else => false,
9692 };
9693 switch (target.cpu.arch) {9678 switch (target.cpu.arch) {
9694 .mips, .mipsel => return dg.lowerType(fn_info.return_type),9679 .mips, .mipsel => return dg.lowerType(fn_info.return_type),
9695 .x86_64 => switch (target.os.tag) {9680 .x86_64 => switch (target.os.tag) {
...@@ -9837,24 +9822,7 @@ const ParamTypeIterator = struct {...@@ -9837,24 +9822,7 @@ const ParamTypeIterator = struct {
9837 @panic("TODO implement async function lowering in the LLVM backend");9822 @panic("TODO implement async function lowering in the LLVM backend");
9838 },9823 },
9839 .C => {9824 .C => {
9840 const is_scalar = switch (ty.zigTypeTag()) {9825 const is_scalar = isScalar(ty);
9841 .Void,
9842 .Bool,
9843 .NoReturn,
9844 .Int,
9845 .Float,
9846 .Pointer,
9847 .Optional,
9848 .ErrorSet,
9849 .Enum,
9850 .AnyFrame,
9851 .Vector,
9852 => true,
9853 .Struct => ty.containerLayout() == .Packed,
9854 .Union => ty.containerLayout() == .Packed,
9855
9856 else => false,
9857 };
9858 switch (it.target.cpu.arch) {9826 switch (it.target.cpu.arch) {
9859 .riscv32, .riscv64 => {9827 .riscv32, .riscv64 => {
9860 it.zig_index += 1;9828 it.zig_index += 1;
...@@ -10108,6 +10076,27 @@ fn isByRef(ty: Type) bool {...@@ -10108,6 +10076,27 @@ fn isByRef(ty: Type) bool {
10108 }10076 }
10109}10077}
1011010078
10079fn isScalar(ty: Type) bool {
10080 return switch (ty.zigTypeTag()) {
10081 .Void,
10082 .Bool,
10083 .NoReturn,
10084 .Int,
10085 .Float,
10086 .Pointer,
10087 .Optional,
10088 .ErrorSet,
10089 .Enum,
10090 .AnyFrame,
10091 .Vector,
10092 => true,
10093
10094 .Struct => ty.containerLayout() == .Packed,
10095 .Union => ty.containerLayout() == .Packed,
10096 else => false,
10097 };
10098}
10099
10111/// This function returns true if we expect LLVM to lower x86_fp80 correctly10100/// This function returns true if we expect LLVM to lower x86_fp80 correctly
10112/// and false if we expect LLVM to crash if it counters an x86_fp80 type.10101/// and false if we expect LLVM to crash if it counters an x86_fp80 type.
10113fn backendSupportsF80(target: std.Target) bool {10102fn backendSupportsF80(target: std.Target) bool {
test/c_abi/cfuncs.c+29-49
...@@ -86,24 +86,8 @@ struct MedStructMixed {...@@ -86,24 +86,8 @@ struct MedStructMixed {
86void zig_med_struct_mixed(struct MedStructMixed);86void zig_med_struct_mixed(struct MedStructMixed);
87struct MedStructMixed zig_ret_med_struct_mixed();87struct MedStructMixed zig_ret_med_struct_mixed();
8888
89struct SmallPackedStruct {89void zig_small_packed_struct(uint8_t);
90 uint8_t a: 2;90void zig_big_packed_struct(__int128);
91 uint8_t b: 2;
92 uint8_t c: 2;
93 uint8_t d: 2;
94 uint8_t e: 1;
95};
96
97struct BigPackedStruct {
98 uint64_t a: 64;
99 uint64_t b: 64;
100 uint64_t c: 64;
101 uint64_t d: 64;
102 uint8_t e: 8;
103};
104
105//void zig_small_packed_struct(struct SmallPackedStruct); // #1481
106void zig_big_packed_struct(struct BigPackedStruct);
10791
108struct SplitStructInts {92struct SplitStructInts {
109 uint64_t a;93 uint64_t a;
...@@ -176,13 +160,19 @@ void run_c_tests(void) {...@@ -176,13 +160,19 @@ void run_c_tests(void) {
176 }160 }
177161
178 {162 {
179 struct BigPackedStruct s = {1, 2, 3, 4, 5};163 __int128 s = 0;
164 s |= 1 << 0;
165 s |= (__int128)2 << 64;
180 zig_big_packed_struct(s);166 zig_big_packed_struct(s);
181 }167 }
182168
183 {169 {
184 struct SmallPackedStruct s = {0, 1, 2, 3, 1};170 uint8_t s = 0;
185 //zig_small_packed_struct(s);171 s |= 0 << 0;
172 s |= 1 << 2;
173 s |= 2 << 4;
174 s |= 3 << 6;
175 zig_small_packed_struct(s);
186 }176 }
187177
188 {178 {
...@@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) {...@@ -378,42 +368,32 @@ void c_split_struct_mixed(struct SplitStructMixed x) {
378 assert_or_panic(y.c == 1337.0f);368 assert_or_panic(y.c == 1337.0f);
379}369}
380370
381struct SmallPackedStruct c_ret_small_packed_struct() {371uint8_t c_ret_small_packed_struct() {
382 struct SmallPackedStruct s = {372 uint8_t s = 0;
383 .a = 0,373 s |= 0 << 0;
384 .b = 1,374 s |= 1 << 2;
385 .c = 2,375 s |= 2 << 4;
386 .d = 3,376 s |= 3 << 6;
387 .e = 1,
388 };
389 return s;377 return s;
390}378}
391379
392void c_small_packed_struct(struct SmallPackedStruct x) {380void c_small_packed_struct(uint8_t x) {
393 assert_or_panic(x.a == 0);381 assert_or_panic(((x >> 0) & 0x3) == 0);
394 assert_or_panic(x.a == 1);382 assert_or_panic(((x >> 2) & 0x3) == 1);
395 assert_or_panic(x.a == 2);383 assert_or_panic(((x >> 4) & 0x3) == 2);
396 assert_or_panic(x.a == 3);384 assert_or_panic(((x >> 6) & 0x3) == 3);
397 assert_or_panic(x.e == 1);
398}385}
399386
400struct BigPackedStruct c_ret_big_packed_struct() {387__int128 c_ret_big_packed_struct() {
401 struct BigPackedStruct s = {388 __int128 s = 0;
402 .a = 1,389 s |= 1 << 0;
403 .b = 2,390 s |= (__int128)2 << 64;
404 .c = 3,
405 .d = 4,
406 .e = 5,
407 };
408 return s;391 return s;
409}392}
410393
411void c_big_packed_struct(struct BigPackedStruct x) {394void c_big_packed_struct(__int128 x) {
412 assert_or_panic(x.a == 1);395 assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1);
413 assert_or_panic(x.b == 2);396 assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2);
414 assert_or_panic(x.c == 3);
415 assert_or_panic(x.d == 4);
416 assert_or_panic(x.e == 5);
417}397}
418398
419struct SplitStructMixed c_ret_split_struct_mixed() {399struct SplitStructMixed c_ret_split_struct_mixed() {
test/c_abi/main.zig+10-23
...@@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct {...@@ -263,37 +263,30 @@ const SmallPackedStruct = packed struct {
263 b: u2,263 b: u2,
264 c: u2,264 c: u2,
265 d: u2,265 d: u2,
266 e: bool,
267};266};
268const c_small_packed_struct: fn (SmallPackedStruct) callconv(.C) void = @compileError("TODO: #1481");267extern fn c_small_packed_struct(SmallPackedStruct) void;
269extern fn c_ret_small_packed_struct() SmallPackedStruct;268extern fn c_ret_small_packed_struct() SmallPackedStruct;
270269
271// waiting on #1481270export fn zig_small_packed_struct(x: SmallPackedStruct) void {
272//export fn zig_small_packed_struct(x: SmallPackedStruct) void {271 expect(x.a == 0) catch @panic("test failure");
273// expect(x.a == 0) catch @panic("test failure");272 expect(x.b == 1) catch @panic("test failure");
274// expect(x.b == 1) catch @panic("test failure");273 expect(x.c == 2) catch @panic("test failure");
275// expect(x.c == 2) catch @panic("test failure");274 expect(x.d == 3) catch @panic("test failure");
276// expect(x.d == 3) catch @panic("test failure");275}
277// expect(x.e) catch @panic("test failure");
278//}
279276
280test "C ABI small packed struct" {277test "C ABI small packed struct" {
281 var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, .e = true };278 var s = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3 };
282 _ = s; //c_small_packed_struct(s); // waiting on #1481279 c_small_packed_struct(s);
283 var s2 = c_ret_small_packed_struct();280 var s2 = c_ret_small_packed_struct();
284 try expect(s2.a == 0);281 try expect(s2.a == 0);
285 try expect(s2.b == 1);282 try expect(s2.b == 1);
286 try expect(s2.c == 2);283 try expect(s2.c == 2);
287 try expect(s2.d == 3);284 try expect(s2.d == 3);
288 try expect(s2.e);
289}285}
290286
291const BigPackedStruct = packed struct {287const BigPackedStruct = packed struct {
292 a: u64,288 a: u64,
293 b: u64,289 b: u64,
294 c: u64,
295 d: u64,
296 e: u8,
297};290};
298extern fn c_big_packed_struct(BigPackedStruct) void;291extern fn c_big_packed_struct(BigPackedStruct) void;
299extern fn c_ret_big_packed_struct() BigPackedStruct;292extern fn c_ret_big_packed_struct() BigPackedStruct;
...@@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct;...@@ -301,20 +294,14 @@ extern fn c_ret_big_packed_struct() BigPackedStruct;
301export fn zig_big_packed_struct(x: BigPackedStruct) void {294export fn zig_big_packed_struct(x: BigPackedStruct) void {
302 expect(x.a == 1) catch @panic("test failure");295 expect(x.a == 1) catch @panic("test failure");
303 expect(x.b == 2) catch @panic("test failure");296 expect(x.b == 2) catch @panic("test failure");
304 expect(x.c == 3) catch @panic("test failure");
305 expect(x.d == 4) catch @panic("test failure");
306 expect(x.e == 5) catch @panic("test failure");
307}297}
308298
309test "C ABI big packed struct" {299test "C ABI big packed struct" {
310 var s = BigPackedStruct{ .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };300 var s = BigPackedStruct{ .a = 1, .b = 2 };
311 c_big_packed_struct(s);301 c_big_packed_struct(s);
312 var s2 = c_ret_big_packed_struct();302 var s2 = c_ret_big_packed_struct();
313 try expect(s2.a == 1);303 try expect(s2.a == 1);
314 try expect(s2.b == 2);304 try expect(s2.b == 2);
315 try expect(s2.c == 3);
316 try expect(s2.d == 4);
317 try expect(s2.e == 5);
318}305}
319306
320const SplitStructInt = extern struct {307const SplitStructInt = extern struct {
test/cases/compile_errors/C_pointer_pointing_to_non_C_ABI_compatible_type_or_has_align_attr.zig+1-1
...@@ -10,5 +10,5 @@ export fn a() void {...@@ -10,5 +10,5 @@ export fn a() void {
10// target=native10// target=native
11//11//
12// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'12// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'
13// :3:19: note: only structs with packed or extern layout are extern compatible13// :3:19: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :1:13: note: struct declared here
test/cases/compile_errors/function_with_non-extern_non-packed_struct_parameter.zig+1-1
...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }
10// target=native10// target=native
11//11//
12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: note: only structs with packed or extern layout are extern compatible13// :6:17: note: only extern structs and ABI sized packed structs are extern compatible
14// :1:13: note: struct declared here14// :1:13: note: struct declared here
test/cases/compile_errors/function_with_non-extern_non-packed_union_parameter.zig+1-1
...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }...@@ -10,5 +10,5 @@ export fn entry(foo: Foo) void { _ = foo; }
10// target=native10// target=native
11//11//
12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'12// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
13// :6:17: note: only unions with packed or extern layout are extern compatible13// :6:17: note: only extern unions and ABI sized packed unions are extern compatible
14// :1:13: note: union declared here14// :1:13: note: union declared here