authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-21 12:11:49+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-21 12:11:49+02:00
log972c39e2c00c487a483bad002ef33ca1a5c21d02
tree8a5ef4ae22f2a36b020062a913c79278bfb79a30
parent41575b1f55b0f18d65bfeb23dc04a5489ed47b65
parent2609e33ab08850405682a79f60cca66c13f9a40d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13219 from Vexu/stage2-fixes

Stage2 bug fixes

46 files changed, 647 insertions(+), 201 deletions(-)

src/AstGen.zig+33-17
...@@ -232,7 +232,7 @@ pub const ResultLoc = union(enum) {...@@ -232,7 +232,7 @@ pub const ResultLoc = union(enum) {
232 coerced_ty: Zir.Inst.Ref,232 coerced_ty: Zir.Inst.Ref,
233 /// The expression must store its result into this typed pointer. The result instruction233 /// The expression must store its result into this typed pointer. The result instruction
234 /// from the expression must be ignored.234 /// from the expression must be ignored.
235 ptr: Zir.Inst.Ref,235 ptr: PtrResultLoc,
236 /// The expression must store its result into this allocation, which has an inferred type.236 /// The expression must store its result into this allocation, which has an inferred type.
237 /// The result instruction from the expression must be ignored.237 /// The result instruction from the expression must be ignored.
238 /// Always an instruction with tag `alloc_inferred`.238 /// Always an instruction with tag `alloc_inferred`.
...@@ -242,6 +242,11 @@ pub const ResultLoc = union(enum) {...@@ -242,6 +242,11 @@ pub const ResultLoc = union(enum) {
242 /// The result instruction from the expression must be ignored.242 /// The result instruction from the expression must be ignored.
243 block_ptr: *GenZir,243 block_ptr: *GenZir,
244244
245 const PtrResultLoc = struct {
246 inst: Zir.Inst.Ref,
247 src_node: ?Ast.Node.Index = null,
248 };
249
245 pub const Strategy = struct {250 pub const Strategy = struct {
246 elide_store_to_block_ptr_instructions: bool,251 elide_store_to_block_ptr_instructions: bool,
247 tag: Tag,252 tag: Tag,
...@@ -1380,8 +1385,8 @@ fn arrayInitExpr(...@@ -1380,8 +1385,8 @@ fn arrayInitExpr(
1380 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);1385 const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag);
1381 return rvalue(gz, rl, result, node);1386 return rvalue(gz, rl, result, node);
1382 },1387 },
1383 .ptr => |ptr_inst| {1388 .ptr => |ptr_res| {
1384 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array);1389 return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array);
1385 },1390 },
1386 .inferred_ptr => |ptr_inst| {1391 .inferred_ptr => |ptr_inst| {
1387 if (types.array == .none) {1392 if (types.array == .none) {
...@@ -1513,7 +1518,7 @@ fn arrayInitExprRlPtrInner(...@@ -1513,7 +1518,7 @@ fn arrayInitExprRlPtrInner(
1513 });1518 });
1514 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;1519 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1515 extra_index += 1;1520 extra_index += 1;
1516 _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init);1521 _ = try expr(gz, scope, .{ .ptr = .{ .inst = elem_ptr } }, elem_init);
1517 }1522 }
15181523
1519 const tag: Zir.Inst.Tag = if (gz.force_comptime)1524 const tag: Zir.Inst.Tag = if (gz.force_comptime)
...@@ -1631,7 +1636,7 @@ fn structInitExpr(...@@ -1631,7 +1636,7 @@ fn structInitExpr(
1631 const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);1636 const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init);
1632 return rvalue(gz, rl, result, node);1637 return rvalue(gz, rl, result, node);
1633 },1638 },
1634 .ptr => |ptr_inst| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_inst),1639 .ptr => |ptr_res| return structInitExprRlPtr(gz, scope, rl, node, struct_init, ptr_res.inst),
1635 .inferred_ptr => |ptr_inst| {1640 .inferred_ptr => |ptr_inst| {
1636 if (struct_init.ast.type_expr == 0) {1641 if (struct_init.ast.type_expr == 0) {
1637 // We treat this case differently so that we don't get a crash when1642 // We treat this case differently so that we don't get a crash when
...@@ -1739,7 +1744,7 @@ fn structInitExprRlPtrInner(...@@ -1739,7 +1744,7 @@ fn structInitExprRlPtrInner(
1739 });1744 });
1740 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;1745 astgen.extra.items[extra_index] = refToIndex(field_ptr).?;
1741 extra_index += 1;1746 extra_index += 1;
1742 _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init);1747 _ = try expr(gz, scope, .{ .ptr = .{ .inst = field_ptr } }, field_init);
1743 }1748 }
17441749
1745 const tag: Zir.Inst.Tag = if (gz.force_comptime)1750 const tag: Zir.Inst.Tag = if (gz.force_comptime)
...@@ -2998,7 +3003,7 @@ fn varDecl(...@@ -2998,7 +3003,7 @@ fn varDecl(
2998 }3003 }
2999 };3004 };
3000 gz.rl_ty_inst = type_inst;3005 gz.rl_ty_inst = type_inst;
3001 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };3006 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = .{ .inst = alloc } } };
3002 } else a: {3007 } else a: {
3003 const alloc = alloc: {3008 const alloc = alloc: {
3004 if (align_inst == .none) {3009 if (align_inst == .none) {
...@@ -3098,7 +3103,10 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi...@@ -3098,7 +3103,10 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi
3098 }3103 }
3099 }3104 }
3100 const lvalue = try lvalExpr(gz, scope, lhs);3105 const lvalue = try lvalExpr(gz, scope, lhs);
3101 _ = try expr(gz, scope, .{ .ptr = lvalue }, rhs);3106 _ = try expr(gz, scope, .{ .ptr = .{
3107 .inst = lvalue,
3108 .src_node = infix_node,
3109 } }, rhs);
3102}3110}
31033111
3104fn assignOp(3112fn assignOp(
...@@ -6729,7 +6737,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6729,7 +6737,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6729 }6737 }
67306738
6731 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{6739 const rl: ResultLoc = if (nodeMayNeedMemoryLocation(tree, operand_node, true)) .{
6732 .ptr = try gz.addNode(.ret_ptr, node),6740 .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) },
6733 } else .{6741 } else .{
6734 .ty = try gz.addNode(.ret_type, node),6742 .ty = try gz.addNode(.ret_type, node),
6735 };6743 };
...@@ -6748,7 +6756,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6748,7 +6756,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6748 },6756 },
6749 .always => {6757 .always => {
6750 // Value is always an error. Emit both error defers and regular defers.6758 // Value is always an error. Emit both error defers and regular defers.
6751 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;6759 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand;
6752 try genDefers(gz, defer_outer, scope, .{ .both = err_code });6760 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6753 try emitDbgStmt(gz, ret_line, ret_column);6761 try emitDbgStmt(gz, ret_line, ret_column);
6754 try gz.addRet(rl, operand, node);6762 try gz.addRet(rl, operand, node);
...@@ -6765,7 +6773,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6765,7 +6773,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6765 }6773 }
67666774
6767 // Emit conditional branch for generating errdefers.6775 // Emit conditional branch for generating errdefers.
6768 const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;6776 const result = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr.inst, node) else operand;
6769 const is_non_err = try gz.addUnNode(.is_non_err, result, node);6777 const is_non_err = try gz.addUnNode(.is_non_err, result, node);
6770 const condbr = try gz.addCondBr(.condbr, node);6778 const condbr = try gz.addCondBr(.condbr, node);
67716779
...@@ -7336,7 +7344,10 @@ fn as(...@@ -7336,7 +7344,10 @@ fn as(
7336 const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node);7344 const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node);
7337 return rvalue(gz, rl, result, node);7345 return rvalue(gz, rl, result, node);
7338 },7346 },
7339 .ptr, .inferred_ptr => |result_ptr| {7347 .ptr => |result_ptr| {
7348 return asRlPtr(gz, scope, rl, node, result_ptr.inst, rhs, dest_type);
7349 },
7350 .inferred_ptr => |result_ptr| {
7340 return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type);7351 return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type);
7341 },7352 },
7342 .block_ptr => |block_scope| {7353 .block_ptr => |block_scope| {
...@@ -9569,9 +9580,9 @@ fn rvalue(...@@ -9569,9 +9580,9 @@ fn rvalue(
9569 }),9580 }),
9570 }9581 }
9571 },9582 },
9572 .ptr => |ptr_inst| {9583 .ptr => |ptr_res| {
9573 _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{9584 _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{
9574 .lhs = ptr_inst,9585 .lhs = ptr_res.inst,
9575 .rhs = result,9586 .rhs = result,
9576 });9587 });
9577 return result;9588 return result;
...@@ -10444,11 +10455,16 @@ const GenZir = struct {...@@ -10444,11 +10455,16 @@ const GenZir = struct {
10444 gz.break_result_loc = parent_rl;10455 gz.break_result_loc = parent_rl;
10445 },10456 },
1044610457
10447 .discard, .none, .ptr, .ref => {10458 .discard, .none, .ref => {
10448 gz.rl_ty_inst = .none;10459 gz.rl_ty_inst = .none;
10449 gz.break_result_loc = parent_rl;10460 gz.break_result_loc = parent_rl;
10450 },10461 },
1045110462
10463 .ptr => |ptr_res| {
10464 gz.rl_ty_inst = .none;
10465 gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } };
10466 },
10467
10452 .inferred_ptr => |ptr| {10468 .inferred_ptr => |ptr| {
10453 gz.rl_ty_inst = .none;10469 gz.rl_ty_inst = .none;
10454 gz.rl_ptr = ptr;10470 gz.rl_ptr = ptr;
...@@ -11610,7 +11626,7 @@ const GenZir = struct {...@@ -11610,7 +11626,7 @@ const GenZir = struct {
1161011626
11611 fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {11627 fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void {
11612 switch (rl) {11628 switch (rl) {
11613 .ptr => |ret_ptr| _ = try gz.addUnNode(.ret_load, ret_ptr, node),11629 .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node),
11614 .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node),11630 .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node),
11615 else => unreachable,11631 else => unreachable,
11616 }11632 }
src/Module.zig+46
...@@ -2878,6 +2878,32 @@ pub const SrcLoc = struct {...@@ -2878,6 +2878,32 @@ pub const SrcLoc = struct {
2878 };2878 };
2879 return nodeToSpan(tree, full.ast.type_expr);2879 return nodeToSpan(tree, full.ast.type_expr);
2880 },2880 },
2881 .node_offset_store_ptr => |node_off| {
2882 const tree = try src_loc.file_scope.getTree(gpa);
2883 const node_tags = tree.nodes.items(.tag);
2884 const node_datas = tree.nodes.items(.data);
2885 const node = src_loc.declRelativeToNodeIndex(node_off);
2886
2887 switch (node_tags[node]) {
2888 .assign => {
2889 return nodeToSpan(tree, node_datas[node].lhs);
2890 },
2891 else => return nodeToSpan(tree, node),
2892 }
2893 },
2894 .node_offset_store_operand => |node_off| {
2895 const tree = try src_loc.file_scope.getTree(gpa);
2896 const node_tags = tree.nodes.items(.tag);
2897 const node_datas = tree.nodes.items(.data);
2898 const node = src_loc.declRelativeToNodeIndex(node_off);
2899
2900 switch (node_tags[node]) {
2901 .assign => {
2902 return nodeToSpan(tree, node_datas[node].rhs);
2903 },
2904 else => return nodeToSpan(tree, node),
2905 }
2906 },
2881 }2907 }
2882 }2908 }
28832909
...@@ -3213,6 +3239,12 @@ pub const LazySrcLoc = union(enum) {...@@ -3213,6 +3239,12 @@ pub const LazySrcLoc = union(enum) {
3213 /// The source location points to the type of an array or struct initializer.3239 /// The source location points to the type of an array or struct initializer.
3214 /// The Decl is determined contextually.3240 /// The Decl is determined contextually.
3215 node_offset_init_ty: i32,3241 node_offset_init_ty: i32,
3242 /// The source location points to the LHS of an assignment.
3243 /// The Decl is determined contextually.
3244 node_offset_store_ptr: i32,
3245 /// The source location points to the RHS of an assignment.
3246 /// The Decl is determined contextually.
3247 node_offset_store_operand: i32,
32163248
3217 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;3249 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
32183250
...@@ -3296,6 +3328,8 @@ pub const LazySrcLoc = union(enum) {...@@ -3296,6 +3328,8 @@ pub const LazySrcLoc = union(enum) {
3296 .node_offset_container_tag,3328 .node_offset_container_tag,
3297 .node_offset_field_default,3329 .node_offset_field_default,
3298 .node_offset_init_ty,3330 .node_offset_init_ty,
3331 .node_offset_store_ptr,
3332 .node_offset_store_operand,
3299 => .{3333 => .{
3300 .file_scope = decl.getFileScope(),3334 .file_scope = decl.getFileScope(),
3301 .parent_decl_node = decl.src_node,3335 .parent_decl_node = decl.src_node,
...@@ -5607,6 +5641,18 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {...@@ -5607,6 +5641,18 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5607 else => |e| return e,5641 else => |e| return e,
5608 };5642 };
56095643
5644 {
5645 var it = sema.unresolved_inferred_allocs.keyIterator();
5646 while (it.next()) |ptr_inst| {
5647 // The lack of a resolve_inferred_alloc means that this instruction
5648 // is unused so it just has to be a no-op.
5649 sema.air_instructions.set(ptr_inst.*, .{
5650 .tag = .alloc,
5651 .data = .{ .ty = Type.initTag(.single_const_pointer_to_comptime_int) },
5652 });
5653 }
5654 }
5655
5610 // If we don't get an error return trace from a caller, create our own.5656 // If we don't get an error return trace from a caller, create our own.
5611 if (func.calls_or_awaits_errorable_fn and5657 if (func.calls_or_awaits_errorable_fn and
5612 mod.comp.bin_file.options.error_return_tracing and5658 mod.comp.bin_file.options.error_return_tracing and
src/Sema.zig+82-44
...@@ -82,6 +82,8 @@ is_generic_instantiation: bool = false,...@@ -82,6 +82,8 @@ is_generic_instantiation: bool = false,
82/// function types will emit generic poison instead of a partial type.82/// function types will emit generic poison instead of a partial type.
83no_partial_func_ty: bool = false,83no_partial_func_ty: bool = false,
8484
85unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{},
86
85const std = @import("std");87const std = @import("std");
86const math = std.math;88const math = std.math;
87const mem = std.mem;89const mem = std.mem;
...@@ -579,6 +581,7 @@ pub fn deinit(sema: *Sema) void {...@@ -579,6 +581,7 @@ pub fn deinit(sema: *Sema) void {
579 }581 }
580 sema.post_hoc_blocks.deinit(gpa);582 sema.post_hoc_blocks.deinit(gpa);
581 }583 }
584 sema.unresolved_inferred_allocs.deinit(gpa);
582 sema.* = undefined;585 sema.* = undefined;
583}586}
584587
...@@ -1235,9 +1238,6 @@ fn analyzeBodyInner(...@@ -1235,9 +1238,6 @@ fn analyzeBodyInner(
1235 i = 0;1238 i = 0;
1236 continue;1239 continue;
1237 } else {1240 } else {
1238 const src_node = sema.code.instructions.items(.data)[inst].node;
1239 const src = LazySrcLoc.nodeOffset(src_node);
1240 try sema.requireFunctionBlock(block, src);
1241 break always_noreturn;1241 break always_noreturn;
1242 }1242 }
1243 },1243 },
...@@ -2186,7 +2186,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -2186,7 +2186,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
2186 defer trash_block.instructions.deinit(sema.gpa);2186 defer trash_block.instructions.deinit(sema.gpa);
2187 const operand = try trash_block.addBitCast(pointee_ty, .void_value);2187 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
21882188
2189 try sema.requireFunctionBlock(block, src);
2190 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{2189 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
2191 .pointee_type = pointee_ty,2190 .pointee_type = pointee_ty,
2192 .@"align" = inferred_alloc.alignment,2191 .@"align" = inferred_alloc.alignment,
...@@ -3219,7 +3218,6 @@ fn zirAllocExtended(...@@ -3219,7 +3218,6 @@ fn zirAllocExtended(
3219 try sema.validateVarType(block, ty_src, var_ty, false);3218 try sema.validateVarType(block, ty_src, var_ty, false);
3220 }3219 }
3221 const target = sema.mod.getTarget();3220 const target = sema.mod.getTarget();
3222 try sema.requireFunctionBlock(block, src);
3223 try sema.resolveTypeLayout(block, src, var_ty);3221 try sema.resolveTypeLayout(block, src, var_ty);
3224 const ptr_type = try Type.ptr(sema.arena, sema.mod, .{3222 const ptr_type = try Type.ptr(sema.arena, sema.mod, .{
3225 .pointee_type = var_ty,3223 .pointee_type = var_ty,
...@@ -3237,8 +3235,8 @@ fn zirAllocExtended(...@@ -3237,8 +3235,8 @@ fn zirAllocExtended(
3237 inferred_alloc_ty,3235 inferred_alloc_ty,
3238 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }),3236 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }),
3239 );3237 );
3240 try sema.requireFunctionBlock(block, src);
3241 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);3238 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
3239 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3242 return result;3240 return result;
3243}3241}
32443242
...@@ -3318,7 +3316,6 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -3318,7 +3316,6 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
3318 return sema.addConstant(const_ptr_ty, val);3316 return sema.addConstant(const_ptr_ty, val);
3319 }3317 }
33203318
3321 try sema.requireFunctionBlock(block, src);
3322 return block.addBitCast(const_ptr_ty, alloc);3319 return block.addBitCast(const_ptr_ty, alloc);
3323}3320}
33243321
...@@ -3345,7 +3342,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -3345,7 +3342,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
33453342
3346 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3343 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3347 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };3344 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
3348 const var_decl_src = inst_data.src();
3349 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);3345 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
3350 if (block.is_comptime) {3346 if (block.is_comptime) {
3351 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);3347 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);
...@@ -3355,7 +3351,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -3355,7 +3351,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
3355 .pointee_type = var_ty,3351 .pointee_type = var_ty,
3356 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3352 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3357 });3353 });
3358 try sema.requireFunctionBlock(block, var_decl_src);
3359 try sema.queueFullTypeResolution(var_ty);3354 try sema.queueFullTypeResolution(var_ty);
3360 return block.addTy(.alloc, ptr_type);3355 return block.addTy(.alloc, ptr_type);
3361}3356}
...@@ -3365,7 +3360,6 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -3365,7 +3360,6 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
3365 defer tracy.end();3360 defer tracy.end();
33663361
3367 const inst_data = sema.code.instructions.items(.data)[inst].un_node;3362 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
3368 const var_decl_src = inst_data.src();
3369 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };3363 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
3370 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);3364 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
3371 if (block.is_comptime) {3365 if (block.is_comptime) {
...@@ -3377,7 +3371,6 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -3377,7 +3371,6 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
3377 .pointee_type = var_ty,3371 .pointee_type = var_ty,
3378 .@"addrspace" = target_util.defaultAddressSpace(target, .local),3372 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3379 });3373 });
3380 try sema.requireFunctionBlock(block, var_decl_src);
3381 try sema.queueFullTypeResolution(var_ty);3374 try sema.queueFullTypeResolution(var_ty);
3382 return block.addTy(.alloc, ptr_type);3375 return block.addTy(.alloc, ptr_type);
3383}3376}
...@@ -3413,8 +3406,8 @@ fn zirAllocInferred(...@@ -3413,8 +3406,8 @@ fn zirAllocInferred(
3413 inferred_alloc_ty,3406 inferred_alloc_ty,
3414 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }),3407 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }),
3415 );3408 );
3416 try sema.requireFunctionBlock(block, src);
3417 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);3409 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
3410 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3418 return result;3411 return result;
3419}3412}
34203413
...@@ -3464,6 +3457,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3464,6 +3457,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3464 }3457 }
3465 },3458 },
3466 .inferred_alloc => {3459 .inferred_alloc => {
3460 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
3467 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;3461 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
3468 const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);3462 const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);
3469 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);3463 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
...@@ -3566,7 +3560,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -3566,7 +3560,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
3566 return;3560 return;
3567 }3561 }
35683562
3569 try sema.requireFunctionBlock(block, src);
3570 try sema.queueFullTypeResolution(final_elem_ty);3563 try sema.queueFullTypeResolution(final_elem_ty);
35713564
3572 // Change it to a normal alloc.3565 // Change it to a normal alloc.
...@@ -3912,7 +3905,6 @@ fn validateUnionInit(...@@ -3912,7 +3905,6 @@ fn validateUnionInit(
3912 return;3905 return;
3913 }3906 }
39143907
3915 try sema.requireFunctionBlock(block, init_src);
3916 const new_tag = try sema.addConstant(tag_ty, tag_val);3908 const new_tag = try sema.addConstant(tag_ty, tag_val);
3917 _ = try block.addBinOp(.set_union_tag, union_ptr, new_tag);3909 _ = try block.addBinOp(.set_union_tag, union_ptr, new_tag);
3918}3910}
...@@ -4648,7 +4640,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -4648,7 +4640,10 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
4648 try sema.addToInferredErrorSet(operand);4640 try sema.addToInferredErrorSet(operand);
4649 }4641 }
46504642
4651 return sema.storePtr2(block, src, ptr, src, operand, src, if (is_ret) .ret_ptr else .store);4643 const ptr_src: LazySrcLoc = .{ .node_offset_store_ptr = inst_data.src_node };
4644 const operand_src: LazySrcLoc = .{ .node_offset_store_operand = inst_data.src_node };
4645 const air_tag: Air.Inst.Tag = if (is_ret) .ret_ptr else .store;
4646 return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
4652}4647}
46534648
4654fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4649fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -4808,7 +4803,6 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bo...@@ -4808,7 +4803,6 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index, force_comptime: bo
4808 if (block.is_comptime or force_comptime) {4803 if (block.is_comptime or force_comptime) {
4809 return sema.fail(block, src, "encountered @panic at comptime", .{});4804 return sema.fail(block, src, "encountered @panic at comptime", .{});
4810 }4805 }
4811 try sema.requireFunctionBlock(block, src);
4812 return sema.panicWithMsg(block, src, msg_inst);4806 return sema.panicWithMsg(block, src, msg_inst);
4813}4807}
48144808
...@@ -6288,7 +6282,6 @@ fn analyzeCall(...@@ -6288,7 +6282,6 @@ fn analyzeCall(
6288 break :res res2;6282 break :res res2;
6289 } else res: {6283 } else res: {
6290 assert(!func_ty_info.is_generic);6284 assert(!func_ty_info.is_generic);
6291 try sema.requireFunctionBlock(block, call_src);
62926285
6293 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);6286 const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);
6294 for (uncasted_args) |uncasted_arg, i| {6287 for (uncasted_args) |uncasted_arg, i| {
...@@ -6414,9 +6407,9 @@ fn analyzeInlineCallArg(...@@ -6414,9 +6407,9 @@ fn analyzeInlineCallArg(
6414 };6407 };
6415 }6408 }
6416 const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src);6409 const casted_arg = try sema.coerce(arg_block, param_ty, uncasted_arg, arg_src);
6417 try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
64186410
6419 if (is_comptime_call) {6411 if (is_comptime_call) {
6412 try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
6420 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {6413 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, casted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
6421 if (err == error.AnalysisFail and sema.err != null) {6414 if (err == error.AnalysisFail and sema.err != null) {
6422 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);6415 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
...@@ -6441,6 +6434,20 @@ fn analyzeInlineCallArg(...@@ -6441,6 +6434,20 @@ fn analyzeInlineCallArg(
6441 .ty = param_ty,6434 .ty = param_ty,
6442 .val = arg_val,6435 .val = arg_val,
6443 };6436 };
6437 } else if (((try sema.resolveMaybeUndefVal(arg_block, arg_src, casted_arg)) == null) or
6438 try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_comptime)
6439 {
6440 try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg);
6441 } else {
6442 // We have a comptime value but we need a runtime value to preserve inlining semantics,
6443 const ptr_type = try Type.ptr(sema.arena, sema.mod, .{
6444 .pointee_type = param_ty,
6445 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
6446 });
6447 const alloc = try arg_block.addTy(.alloc, ptr_type);
6448 _ = try arg_block.addBinOp(.store, alloc, casted_arg);
6449 const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
6450 try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
6444 }6451 }
64456452
6446 arg_i.* += 1;6453 arg_i.* += 1;
...@@ -6449,9 +6456,10 @@ fn analyzeInlineCallArg(...@@ -6449,9 +6456,10 @@ fn analyzeInlineCallArg(
6449 // No coercion needed.6456 // No coercion needed.
6450 const uncasted_arg = uncasted_args[arg_i.*];6457 const uncasted_arg = uncasted_args[arg_i.*];
6451 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);6458 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);
6452 try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);6459 const param_ty = sema.typeOf(uncasted_arg);
64536460
6454 if (is_comptime_call) {6461 if (is_comptime_call) {
6462 try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
6455 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {6463 const arg_val = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to function being called at comptime must be comptime-known") catch |err| {
6456 if (err == error.AnalysisFail and sema.err != null) {6464 if (err == error.AnalysisFail and sema.err != null) {
6457 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);6465 try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty);
...@@ -6476,6 +6484,20 @@ fn analyzeInlineCallArg(...@@ -6476,6 +6484,20 @@ fn analyzeInlineCallArg(
6476 .ty = sema.typeOf(uncasted_arg),6484 .ty = sema.typeOf(uncasted_arg),
6477 .val = arg_val,6485 .val = arg_val,
6478 };6486 };
6487 } else if ((try sema.resolveMaybeUndefVal(arg_block, arg_src, uncasted_arg)) == null or
6488 try sema.typeRequiresComptime(param_ty) or zir_tags[inst] == .param_anytype_comptime)
6489 {
6490 try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg);
6491 } else {
6492 // We have a comptime value but we need a runtime value to preserve inlining semantics,
6493 const ptr_type = try Type.ptr(sema.arena, sema.mod, .{
6494 .pointee_type = param_ty,
6495 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
6496 });
6497 const alloc = try arg_block.addTy(.alloc, ptr_type);
6498 _ = try arg_block.addBinOp(.store, alloc, uncasted_arg);
6499 const loaded = try arg_block.addTyOp(.load, param_ty, alloc);
6500 try sema.inst_map.putNoClobber(sema.gpa, inst, loaded);
6479 }6501 }
64806502
6481 arg_i.* += 1;6503 arg_i.* += 1;
...@@ -6588,6 +6610,11 @@ fn instantiateGenericCall(...@@ -6588,6 +6610,11 @@ fn instantiateGenericCall(
6588 }6610 }
65896611
6590 const arg_ty = sema.typeOf(uncasted_args[i]);6612 const arg_ty = sema.typeOf(uncasted_args[i]);
6613 if (is_comptime or is_anytype) {
6614 // Tuple default values are a part of the type and need to be
6615 // resolved to hash the type.
6616 try sema.resolveTupleLazyValues(block, call_src, arg_ty);
6617 }
65916618
6592 if (is_comptime) {6619 if (is_comptime) {
6593 const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {6620 const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {
...@@ -6892,8 +6919,6 @@ fn instantiateGenericCall(...@@ -6892,8 +6919,6 @@ fn instantiateGenericCall(
6892 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);6919 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
68936920
6894 // Make a runtime call to the new function, making sure to omit the comptime args.6921 // Make a runtime call to the new function, making sure to omit the comptime args.
6895 try sema.requireFunctionBlock(block, call_src);
6896
6897 const comptime_args = callee.comptime_args.?;6922 const comptime_args = callee.comptime_args.?;
6898 const func_ty = mod.declPtr(callee.owner_decl).ty;6923 const func_ty = mod.declPtr(callee.owner_decl).ty;
6899 const new_fn_info = func_ty.fnInfo();6924 const new_fn_info = func_ty.fnInfo();
...@@ -6963,6 +6988,16 @@ fn instantiateGenericCall(...@@ -6963,6 +6988,16 @@ fn instantiateGenericCall(
6963 return result;6988 return result;
6964}6989}
69656990
6991fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
6992 if (!ty.isTuple()) return;
6993 const tuple = ty.tupleFields();
6994 for (tuple.values) |field_val, i| {
6995 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);
6996 if (field_val.tag() == .unreachable_value) continue;
6997 try sema.resolveLazyValue(block, src, field_val);
6998 }
6999}
7000
6966fn emitDbgInline(7001fn emitDbgInline(
6967 sema: *Sema,7002 sema: *Sema,
6968 block: *Block,7003 block: *Block,
...@@ -7441,7 +7476,6 @@ fn analyzeOptionalPayloadPtr(...@@ -7441,7 +7476,6 @@ fn analyzeOptionalPayloadPtr(
7441 // If the pointer resulting from this function was stored at comptime,7476 // If the pointer resulting from this function was stored at comptime,
7442 // the optional non-null bit would be set that way. But in this case,7477 // the optional non-null bit would be set that way. But in this case,
7443 // we need to emit a runtime instruction to do it.7478 // we need to emit a runtime instruction to do it.
7444 try sema.requireFunctionBlock(block, src);
7445 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);7479 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
7446 }7480 }
7447 return sema.addConstant(7481 return sema.addConstant(
...@@ -14499,6 +14533,12 @@ fn zirClosureGet(...@@ -14499,6 +14533,12 @@ fn zirClosureGet(
14499 return sema.failWithOwnedErrorMsg(msg);14533 return sema.failWithOwnedErrorMsg(msg);
14500 }14534 }
1450114535
14536 if (tv.val.tag() == .unreachable_value) {
14537 assert(block.is_typeof);
14538 // We need a dummy runtime instruction with the correct type.
14539 return block.addTy(.alloc, tv.ty);
14540 }
14541
14502 return sema.addConstant(tv.ty, tv.val);14542 return sema.addConstant(tv.ty, tv.val);
14503}14543}
1450414544
...@@ -15664,7 +15704,9 @@ fn zirBoolBr(...@@ -15664,7 +15704,9 @@ fn zirBoolBr(
15664 _ = try lhs_block.addBr(block_inst, lhs_result);15704 _ = try lhs_block.addBr(block_inst, lhs_result);
1566515705
15666 const rhs_result = try sema.resolveBody(rhs_block, body, inst);15706 const rhs_result = try sema.resolveBody(rhs_block, body, inst);
15667 _ = try rhs_block.addBr(block_inst, rhs_result);15707 if (!sema.typeOf(rhs_result).isNoReturn()) {
15708 _ = try rhs_block.addBr(block_inst, rhs_result);
15709 }
1566815710
15669 return finishCondBr(sema, parent_block, &child_block, &then_block, &else_block, lhs, block_inst);15711 return finishCondBr(sema, parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
15670}15712}
...@@ -15996,7 +16038,6 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -15996,7 +16038,6 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
15996 if (block.is_comptime or inst_data.force_comptime) {16038 if (block.is_comptime or inst_data.force_comptime) {
15997 return sema.fail(block, src, "reached unreachable code", .{});16039 return sema.fail(block, src, "reached unreachable code", .{});
15998 }16040 }
15999 try sema.requireFunctionBlock(block, src);
16000 // TODO Add compile error for @optimizeFor occurring too late in a scope.16041 // TODO Add compile error for @optimizeFor occurring too late in a scope.
16001 try block.addUnreachable(src, true);16042 try block.addUnreachable(src, true);
16002 return always_noreturn;16043 return always_noreturn;
...@@ -16171,6 +16212,7 @@ fn analyzeRet(...@@ -16171,6 +16212,7 @@ fn analyzeRet(
1617116212
16172 if (block.inlining) |inlining| {16213 if (block.inlining) |inlining| {
16173 if (block.is_comptime) {16214 if (block.is_comptime) {
16215 _ = try sema.resolveConstMaybeUndefVal(block, src, operand, "value being returned at comptime must be comptime-known");
16174 inlining.comptime_result = operand;16216 inlining.comptime_result = operand;
16175 return error.ComptimeReturn;16217 return error.ComptimeReturn;
16176 }16218 }
...@@ -21117,14 +21159,6 @@ fn zirBuiltinExtern(...@@ -21117,14 +21159,6 @@ fn zirBuiltinExtern(
21117 return block.addBitCast(ty, ref);21159 return block.addBitCast(ty, ref);
21118}21160}
2111921161
21120/// Asserts that the block is not comptime.
21121fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
21122 assert(!block.is_comptime);
21123 if (sema.func == null and !block.is_typeof and !block.is_coerce_result_ptr) {
21124 return sema.fail(block, src, "instruction illegal outside function body", .{});
21125 }
21126}
21127
21128fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void {21162fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void {
21129 if (block.is_comptime) {21163 if (block.is_comptime) {
21130 const msg = msg: {21164 const msg = msg: {
...@@ -21138,7 +21172,6 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:...@@ -21138,7 +21172,6 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
21138 };21172 };
21139 return sema.failWithOwnedErrorMsg(msg);21173 return sema.failWithOwnedErrorMsg(msg);
21140 }21174 }
21141 try sema.requireFunctionBlock(block, src);
21142}21175}
2114321176
21144/// Emit a compile error if type cannot be used for a runtime variable.21177/// Emit a compile error if type cannot be used for a runtime variable.
...@@ -25111,11 +25144,6 @@ fn storePtr2(...@@ -25111,11 +25144,6 @@ fn storePtr2(
25111 return;25144 return;
25112 }25145 }
2511325146
25114 if (block.is_comptime) {
25115 // TODO ideally this would tell why the block is comptime
25116 return sema.fail(block, ptr_src, "cannot store to runtime value in comptime block", .{});
25117 }
25118
25119 try sema.requireRuntimeBlock(block, src, runtime_src);25147 try sema.requireRuntimeBlock(block, src, runtime_src);
25120 try sema.queueFullTypeResolution(elem_ty);25148 try sema.queueFullTypeResolution(elem_ty);
25121 if (is_ret) {25149 if (is_ret) {
...@@ -27023,12 +27051,6 @@ fn analyzeLoad(...@@ -27023,12 +27051,6 @@ fn analyzeLoad(
27023 }27051 }
27024 }27052 }
2702527053
27026 if (block.is_comptime) {
27027 // TODO ideally this would tell why the block is comptime
27028 return sema.fail(block, ptr_src, "cannot load runtime value in comptime block", .{});
27029 }
27030
27031 try sema.requireFunctionBlock(block, src);
27032 return block.addTyOp(.load, elem_ty, ptr);27054 return block.addTyOp(.load, elem_ty, ptr);
27033}27055}
2703427056
...@@ -28581,6 +28603,20 @@ fn resolveLazyValue(...@@ -28581,6 +28603,20 @@ fn resolveLazyValue(
28581 const ty = val.castTag(.lazy_size).?.data;28603 const ty = val.castTag(.lazy_size).?.data;
28582 return sema.resolveTypeLayout(block, src, ty);28604 return sema.resolveTypeLayout(block, src, ty);
28583 },28605 },
28606 .comptime_field_ptr => {
28607 const field_ptr = val.castTag(.comptime_field_ptr).?.data;
28608 return sema.resolveLazyValue(block, src, field_ptr.field_val);
28609 },
28610 .@"union" => {
28611 const union_val = val.castTag(.@"union").?.data;
28612 return sema.resolveLazyValue(block, src, union_val.val);
28613 },
28614 .aggregate => {
28615 const aggregate = val.castTag(.aggregate).?.data;
28616 for (aggregate) |elem_val| {
28617 try sema.resolveLazyValue(block, src, elem_val);
28618 }
28619 },
28584 else => return,28620 else => return,
28585 }28621 }
28586}28622}
...@@ -28751,6 +28787,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -28751,6 +28787,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
2875128787
28752 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);28788 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
28753 struct_obj.backing_int_ty = try backing_int_ty.copy(decl_arena_allocator);28789 struct_obj.backing_int_ty = try backing_int_ty.copy(decl_arena_allocator);
28790 try wip_captures.finalize();
28754 } else {28791 } else {
28755 var buf: Type.Payload.Bits = .{28792 var buf: Type.Payload.Bits = .{
28756 .base = .{ .tag = .int_unsigned },28793 .base = .{ .tag = .int_unsigned },
...@@ -29362,6 +29399,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -29362,6 +29399,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
29362 }29399 }
29363 }29400 }
29364 }29401 }
29402 try wip_captures.finalize();
2936529403
29366 struct_obj.have_field_inits = true;29404 struct_obj.have_field_inits = true;
29367}29405}
src/arch/aarch64/abi.zig+73-17
...@@ -5,29 +5,21 @@ const Register = bits.Register;...@@ -5,29 +5,21 @@ const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;6const Type = @import("../../type.zig").Type;
77
8pub const Class = enum { memory, integer, none, float_array };8pub const Class = enum(u8) { memory, integer, none, float_array, _ };
99
10/// For `float_array` the second element will be the amount of floats.
10pub fn classifyType(ty: Type, target: std.Target) [2]Class {11pub fn classifyType(ty: Type, target: std.Target) [2]Class {
12 var maybe_float_bits: ?u16 = null;
13 const float_count = countFloats(ty, target, &maybe_float_bits);
14 if (float_count <= sret_float_count) return .{ .float_array, @intToEnum(Class, float_count) };
15 return classifyTypeInner(ty, target);
16}
17
18fn classifyTypeInner(ty: Type, target: std.Target) [2]Class {
11 if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none };19 if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none };
12 switch (ty.zigTypeTag()) {20 switch (ty.zigTypeTag()) {
13 .Struct => {21 .Struct => {
14 if (ty.containerLayout() == .Packed) return .{ .integer, .none };22 if (ty.containerLayout() == .Packed) return .{ .integer, .none };
15
16 if (ty.structFieldCount() <= 4) {
17 const fields = ty.structFields();
18 var float_size: ?u64 = null;
19 for (fields.values()) |field| {
20 if (field.ty.zigTypeTag() != .Float) break;
21 const field_size = field.ty.bitSize(target);
22 const prev_size = float_size orelse {
23 float_size = field_size;
24 continue;
25 };
26 if (field_size != prev_size) break;
27 } else {
28 return .{ .float_array, .none };
29 }
30 }
31 const bit_size = ty.bitSize(target);23 const bit_size = ty.bitSize(target);
32 if (bit_size > 128) return .{ .memory, .none };24 if (bit_size > 128) return .{ .memory, .none };
33 if (bit_size > 64) return .{ .integer, .integer };25 if (bit_size > 64) return .{ .integer, .integer };
...@@ -67,6 +59,70 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class {...@@ -67,6 +59,70 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class {
67 }59 }
68}60}
6961
62const sret_float_count = 4;
63fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
64 const invalid = std.math.maxInt(u32);
65 switch (ty.zigTypeTag()) {
66 .Union => {
67 const fields = ty.unionFields();
68 var max_count: u32 = 0;
69 for (fields.values()) |field| {
70 const field_count = countFloats(field.ty, target, maybe_float_bits);
71 if (field_count == invalid) return invalid;
72 if (field_count > max_count) max_count = field_count;
73 if (max_count > sret_float_count) return invalid;
74 }
75 return max_count;
76 },
77 .Struct => {
78 const fields_len = ty.structFieldCount();
79 var count: u32 = 0;
80 var i: u32 = 0;
81 while (i < fields_len) : (i += 1) {
82 const field_ty = ty.structFieldType(i);
83 const field_count = countFloats(field_ty, target, maybe_float_bits);
84 if (field_count == invalid) return invalid;
85 count += field_count;
86 if (count > sret_float_count) return invalid;
87 }
88 return count;
89 },
90 .Float => {
91 const float_bits = maybe_float_bits.* orelse {
92 maybe_float_bits.* = ty.floatBits(target);
93 return 1;
94 };
95 if (ty.floatBits(target) == float_bits) return 1;
96 return invalid;
97 },
98 .Void => return 0,
99 else => return invalid,
100 }
101}
102
103pub fn getFloatArrayType(ty: Type) ?Type {
104 switch (ty.zigTypeTag()) {
105 .Union => {
106 const fields = ty.unionFields();
107 for (fields.values()) |field| {
108 if (getFloatArrayType(field.ty)) |some| return some;
109 }
110 return null;
111 },
112 .Struct => {
113 const fields_len = ty.structFieldCount();
114 var i: u32 = 0;
115 while (i < fields_len) : (i += 1) {
116 const field_ty = ty.structFieldType(i);
117 if (getFloatArrayType(field_ty)) |some| return some;
118 }
119 return null;
120 },
121 .Float => return ty,
122 else => return null,
123 }
124}
125
70const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct {126const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct {
71 pub const callee_preserved_regs = [_]Register{127 pub const callee_preserved_regs = [_]Register{
72 .x20, .x21, .x22, .x23,128 .x20, .x21, .x22, .x23,
src/arch/x86_64/abi.zig+13
...@@ -388,6 +388,19 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -388,6 +388,19 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
388 }388 }
389 return result;389 return result;
390 },390 },
391 .Array => {
392 const ty_size = ty.abiSize(target);
393 if (ty_size <= 64) {
394 result[0] = .integer;
395 return result;
396 }
397 if (ty_size <= 128) {
398 result[0] = .integer;
399 result[1] = .integer;
400 return result;
401 }
402 return memory_class;
403 },
391 else => unreachable,404 else => unreachable,
392 }405 }
393}406}
src/codegen/llvm.zig+9-10
...@@ -3125,10 +3125,10 @@ pub const DeclGen = struct {...@@ -3125,10 +3125,10 @@ pub const DeclGen = struct {
3125 .as_u16 => {3125 .as_u16 => {
3126 try llvm_params.append(dg.context.intType(16));3126 try llvm_params.append(dg.context.intType(16));
3127 },3127 },
3128 .float_array => {3128 .float_array => |count| {
3129 const param_ty = fn_info.param_types[it.zig_index - 1];3129 const param_ty = fn_info.param_types[it.zig_index - 1];
3130 const float_ty = try dg.lowerType(param_ty.structFieldType(0));3130 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty).?);
3131 const field_count = @intCast(c_uint, param_ty.structFieldCount());3131 const field_count = @intCast(c_uint, count);
3132 const arr_ty = float_ty.arrayType(field_count);3132 const arr_ty = float_ty.arrayType(field_count);
3133 try llvm_params.append(arr_ty);3133 try llvm_params.append(arr_ty);
3134 },3134 },
...@@ -4801,7 +4801,7 @@ pub const FuncGen = struct {...@@ -4801,7 +4801,7 @@ pub const FuncGen = struct {
4801 const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), "");4801 const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), "");
4802 try llvm_args.append(casted);4802 try llvm_args.append(casted);
4803 },4803 },
4804 .float_array => {4804 .float_array => |count| {
4805 const arg = args[it.zig_index - 1];4805 const arg = args[it.zig_index - 1];
4806 const arg_ty = self.air.typeOf(arg);4806 const arg_ty = self.air.typeOf(arg);
4807 var llvm_arg = try self.resolveInst(arg);4807 var llvm_arg = try self.resolveInst(arg);
...@@ -4812,9 +4812,8 @@ pub const FuncGen = struct {...@@ -4812,9 +4812,8 @@ pub const FuncGen = struct {
4812 llvm_arg = store_inst;4812 llvm_arg = store_inst;
4813 }4813 }
48144814
4815 const float_ty = try self.dg.lowerType(arg_ty.structFieldType(0));4815 const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty).?);
4816 const field_count = @intCast(u32, arg_ty.structFieldCount());4816 const array_llvm_ty = float_ty.arrayType(count);
4817 const array_llvm_ty = float_ty.arrayType(field_count);
48184817
4819 const casted = self.builder.buildBitCast(llvm_arg, array_llvm_ty.pointerType(0), "");4818 const casted = self.builder.buildBitCast(llvm_arg, array_llvm_ty.pointerType(0), "");
4820 const alignment = arg_ty.abiAlignment(target);4819 const alignment = arg_ty.abiAlignment(target);
...@@ -10214,7 +10213,7 @@ const ParamTypeIterator = struct {...@@ -10214,7 +10213,7 @@ const ParamTypeIterator = struct {
10214 llvm_types_buffer: [8]u16,10213 llvm_types_buffer: [8]u16,
10215 byval_attr: bool,10214 byval_attr: bool,
1021610215
10217 const Lowering = enum {10216 const Lowering = union(enum) {
10218 no_bits,10217 no_bits,
10219 byval,10218 byval,
10220 byref,10219 byref,
...@@ -10223,7 +10222,7 @@ const ParamTypeIterator = struct {...@@ -10223,7 +10222,7 @@ const ParamTypeIterator = struct {
10223 multiple_llvm_float,10222 multiple_llvm_float,
10224 slice,10223 slice,
10225 as_u16,10224 as_u16,
10226 float_array,10225 float_array: u8,
10227 };10226 };
1022810227
10229 pub fn next(it: *ParamTypeIterator) ?Lowering {10228 pub fn next(it: *ParamTypeIterator) ?Lowering {
...@@ -10400,7 +10399,7 @@ const ParamTypeIterator = struct {...@@ -10400,7 +10399,7 @@ const ParamTypeIterator = struct {
10400 return .byref;10399 return .byref;
10401 }10400 }
10402 if (classes[0] == .float_array) {10401 if (classes[0] == .float_array) {
10403 return .float_array;10402 return Lowering{ .float_array = @enumToInt(classes[1]) };
10404 }10403 }
10405 if (classes[1] == .none) {10404 if (classes[1] == .none) {
10406 it.llvm_types_len = 1;10405 it.llvm_types_len = 1;
src/type.zig+9
...@@ -3619,6 +3619,9 @@ pub const Type = extern union {...@@ -3619,6 +3619,9 @@ pub const Type = extern union {
36193619
3620 .@"struct" => {3620 .@"struct" => {
3621 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);3621 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3622 if (ty.containerLayout() != .Packed) {
3623 return (try ty.abiSizeAdvanced(target, if (sema_kit) |sk| .{ .sema_kit = sk } else .eager)).scalar * 8;
3624 }
3622 var total: u64 = 0;3625 var total: u64 = 0;
3623 for (ty.structFields().values()) |field| {3626 for (ty.structFields().values()) |field| {
3624 total += try bitSizeAdvanced(field.ty, target, sema_kit);3627 total += try bitSizeAdvanced(field.ty, target, sema_kit);
...@@ -3628,6 +3631,9 @@ pub const Type = extern union {...@@ -3628,6 +3631,9 @@ pub const Type = extern union {
36283631
3629 .tuple, .anon_struct => {3632 .tuple, .anon_struct => {
3630 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);3633 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3634 if (ty.containerLayout() != .Packed) {
3635 return (try ty.abiSizeAdvanced(target, if (sema_kit) |sk| .{ .sema_kit = sk } else .eager)).scalar * 8;
3636 }
3631 var total: u64 = 0;3637 var total: u64 = 0;
3632 for (ty.tupleFields().types) |field_ty| {3638 for (ty.tupleFields().types) |field_ty| {
3633 total += try bitSizeAdvanced(field_ty, target, sema_kit);3639 total += try bitSizeAdvanced(field_ty, target, sema_kit);
...@@ -3643,6 +3649,9 @@ pub const Type = extern union {...@@ -3643,6 +3649,9 @@ pub const Type = extern union {
36433649
3644 .@"union", .union_safety_tagged, .union_tagged => {3650 .@"union", .union_safety_tagged, .union_tagged => {
3645 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);3651 if (sema_kit) |sk| _ = try sk.sema.resolveTypeFields(sk.block, sk.src, ty);
3652 if (ty.containerLayout() != .Packed) {
3653 return (try ty.abiSizeAdvanced(target, if (sema_kit) |sk| .{ .sema_kit = sk } else .eager)).scalar * 8;
3654 }
3646 const union_obj = ty.cast(Payload.Union).?.data;3655 const union_obj = ty.cast(Payload.Union).?.data;
3647 assert(union_obj.haveFieldTypes());3656 assert(union_obj.haveFieldTypes());
36483657
src/value.zig+3
...@@ -2632,6 +2632,9 @@ pub const Value = extern union {...@@ -2632,6 +2632,9 @@ pub const Value = extern union {
2632 .lazy_size,2632 .lazy_size,
2633 => return hashInt(ptr_val, hasher, target),2633 => return hashInt(ptr_val, hasher, target),
26342634
2635 // The value is runtime-known and shouldn't affect the hash.
2636 .runtime_int => {},
2637
2635 else => unreachable,2638 else => unreachable,
2636 }2639 }
2637 }2640 }
test/behavior.zig+5
...@@ -41,6 +41,7 @@ test {...@@ -41,6 +41,7 @@ test {
41 _ = @import("behavior/bugs/2006.zig");41 _ = @import("behavior/bugs/2006.zig");
42 _ = @import("behavior/bugs/2114.zig");42 _ = @import("behavior/bugs/2114.zig");
43 _ = @import("behavior/bugs/2346.zig");43 _ = @import("behavior/bugs/2346.zig");
44 _ = @import("behavior/bugs/2557.zig");
44 _ = @import("behavior/bugs/2578.zig");45 _ = @import("behavior/bugs/2578.zig");
45 _ = @import("behavior/bugs/2692.zig");46 _ = @import("behavior/bugs/2692.zig");
46 _ = @import("behavior/bugs/2889.zig");47 _ = @import("behavior/bugs/2889.zig");
...@@ -87,6 +88,7 @@ test {...@@ -87,6 +88,7 @@ test {
87 _ = @import("behavior/bugs/12033.zig");88 _ = @import("behavior/bugs/12033.zig");
88 _ = @import("behavior/bugs/12430.zig");89 _ = @import("behavior/bugs/12430.zig");
89 _ = @import("behavior/bugs/12486.zig");90 _ = @import("behavior/bugs/12486.zig");
91 _ = @import("behavior/bugs/12488.zig");
90 _ = @import("behavior/bugs/12551.zig");92 _ = @import("behavior/bugs/12551.zig");
91 _ = @import("behavior/bugs/12644.zig");93 _ = @import("behavior/bugs/12644.zig");
92 _ = @import("behavior/bugs/12680.zig");94 _ = @import("behavior/bugs/12680.zig");
...@@ -103,7 +105,10 @@ test {...@@ -103,7 +105,10 @@ test {
103 _ = @import("behavior/bugs/12972.zig");105 _ = @import("behavior/bugs/12972.zig");
104 _ = @import("behavior/bugs/12984.zig");106 _ = @import("behavior/bugs/12984.zig");
105 _ = @import("behavior/bugs/13068.zig");107 _ = @import("behavior/bugs/13068.zig");
108 _ = @import("behavior/bugs/13112.zig");
106 _ = @import("behavior/bugs/13128.zig");109 _ = @import("behavior/bugs/13128.zig");
110 _ = @import("behavior/bugs/13164.zig");
111 _ = @import("behavior/bugs/13171.zig");
107 _ = @import("behavior/byteswap.zig");112 _ = @import("behavior/byteswap.zig");
108 _ = @import("behavior/byval_arg_var.zig");113 _ = @import("behavior/byval_arg_var.zig");
109 _ = @import("behavior/call.zig");114 _ = @import("behavior/call.zig");
test/behavior/bugs/12488.zig created+13
...@@ -0,0 +1,13 @@
1const expect = @import("std").testing.expect;
2
3const A = struct {
4 a: u32,
5};
6
7fn foo(comptime a: anytype) !void {
8 try expect(a[0][0] == @sizeOf(A));
9}
10
11test {
12 try foo(.{[_]usize{@sizeOf(A)}});
13}
test/behavior/bugs/13112.zig created+7
...@@ -0,0 +1,7 @@
1fn nice(a: u32, b: u32) bool {
2 return a == 5 or b == 2 or @panic("oh no");
3}
4
5test {
6 _ = nice(2, 2);
7}
test/behavior/bugs/13164.zig created+16
...@@ -0,0 +1,16 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4inline fn setLimits(min: ?u32, max: ?u32) !void {
5 if (min != null and max != null) {
6 try std.testing.expect(min.? <= max.?);
7 }
8}
9
10test {
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13
14 var x: u32 = 42;
15 try setLimits(x, null);
16}
test/behavior/bugs/13171.zig created+16
...@@ -0,0 +1,16 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4fn BuildType(comptime T: type) type {
5 return struct {
6 val: union {
7 b: T,
8 },
9 };
10}
11
12test {
13 const TestStruct = BuildType(u32);
14 const c = TestStruct{ .val = .{ .b = 10 } };
15 try expect(c.val.b == 10);
16}
test/behavior/bugs/2557.zig created+6
...@@ -0,0 +1,6 @@
1test {
2 var a = if (true) {
3 return;
4 } else true;
5 _ = a;
6}
test/behavior/eval.zig+11
...@@ -1414,3 +1414,14 @@ test "continue nested inline for loop" {...@@ -1414,3 +1414,14 @@ test "continue nested inline for loop" {
1414 }1414 }
1415 try expect(a == 2);1415 try expect(a == 2);
1416}1416}
1417
1418test "length of global array is determinable at comptime" {
1419 const S = struct {
1420 var bytes: [1024]u8 = undefined;
1421
1422 fn foo() !void {
1423 try std.testing.expect(bytes.len == 1024);
1424 }
1425 };
1426 comptime try S.foo();
1427}
test/behavior/sizeof_and_typeof.zig+25-1
...@@ -218,7 +218,7 @@ test "@bitSizeOf" {...@@ -218,7 +218,7 @@ test "@bitSizeOf" {
218 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);218 try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8);
219 try expect(@bitSizeOf(struct {219 try expect(@bitSizeOf(struct {
220 a: u2,220 a: u2,
221 }) == 2);221 }) == 8);
222 try expect(@bitSizeOf(packed struct {222 try expect(@bitSizeOf(packed struct {
223 a: u2,223 a: u2,
224 }) == 2);224 }) == 2);
...@@ -314,3 +314,27 @@ test "lazy size cast to float" {...@@ -314,3 +314,27 @@ test "lazy size cast to float" {
314test "bitSizeOf comptime_int" {314test "bitSizeOf comptime_int" {
315 try expect(@bitSizeOf(comptime_int) == 0);315 try expect(@bitSizeOf(comptime_int) == 0);
316}316}
317
318test "runtime instructions inside typeof in comptime only scope" {
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
321
322 {
323 var y: i8 = 2;
324 const i: [2]i8 = [_]i8{ 1, y };
325 const T = struct {
326 a: @TypeOf(i) = undefined, // causes crash
327 b: @TypeOf(i[0]) = undefined, // causes crash
328 };
329 try expect(@TypeOf((T{}).a) == [2]i8);
330 try expect(@TypeOf((T{}).b) == i8);
331 }
332 {
333 var y: i8 = 2;
334 const i = .{ 1, y };
335 const T = struct {
336 b: @TypeOf(i[1]) = undefined,
337 };
338 try expect(@TypeOf((T{}).b) == i8);
339 }
340}
test/behavior/src.zig+11
...@@ -20,3 +20,14 @@ test "@src" {...@@ -20,3 +20,14 @@ test "@src" {
2020
21 try doTheTest();21 try doTheTest();
22}22}
23
24test "@src used as a comptime parameter" {
25 const S = struct {
26 fn Foo(comptime _: std.builtin.SourceLocation) type {
27 return struct {};
28 }
29 };
30 const T1 = S.Foo(@src());
31 const T2 = S.Foo(@src());
32 try expect(T1 != T2);
33}
test/c_abi/cfuncs.c+105
...@@ -12,6 +12,27 @@ static void assert_or_panic(bool ok) {...@@ -12,6 +12,27 @@ static void assert_or_panic(bool ok) {
12 }12 }
13}13}
1414
15#ifdef __i386__
16# define ZIG_NO_I128
17#endif
18
19#ifdef __arm__
20# define ZIG_NO_I128
21#endif
22
23#ifdef __mips__
24# define ZIG_NO_I128
25#endif
26
27#ifdef __i386__
28# define ZIG_NO_COMPLEX
29#endif
30
31#ifdef __mips__
32# define ZIG_NO_COMPLEX
33#endif
34
35#ifndef ZIG_NO_I128
15struct i128 {36struct i128 {
16 __int128 value;37 __int128 value;
17};38};
...@@ -19,17 +40,22 @@ struct i128 {...@@ -19,17 +40,22 @@ struct i128 {
19struct u128 {40struct u128 {
20 unsigned __int128 value;41 unsigned __int128 value;
21};42};
43#endif
2244
23void zig_u8(uint8_t);45void zig_u8(uint8_t);
24void zig_u16(uint16_t);46void zig_u16(uint16_t);
25void zig_u32(uint32_t);47void zig_u32(uint32_t);
26void zig_u64(uint64_t);48void zig_u64(uint64_t);
49#ifndef ZIG_NO_I128
27void zig_struct_u128(struct u128);50void zig_struct_u128(struct u128);
51#endif
28void zig_i8(int8_t);52void zig_i8(int8_t);
29void zig_i16(int16_t);53void zig_i16(int16_t);
30void zig_i32(int32_t);54void zig_i32(int32_t);
31void zig_i64(int64_t);55void zig_i64(int64_t);
56#ifndef ZIG_NO_I128
32void zig_struct_i128(struct i128);57void zig_struct_i128(struct i128);
58#endif
33void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);59void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t);
3460
35void zig_f32(float);61void zig_f32(float);
...@@ -95,7 +121,9 @@ void zig_med_struct_mixed(struct MedStructMixed);...@@ -95,7 +121,9 @@ void zig_med_struct_mixed(struct MedStructMixed);
95struct MedStructMixed zig_ret_med_struct_mixed();121struct MedStructMixed zig_ret_med_struct_mixed();
96122
97void zig_small_packed_struct(uint8_t);123void zig_small_packed_struct(uint8_t);
124#ifndef ZIG_NO_I128
98void zig_big_packed_struct(__int128);125void zig_big_packed_struct(__int128);
126#endif
99127
100struct SplitStructInts {128struct SplitStructInts {
101 uint64_t a;129 uint64_t a;
...@@ -151,19 +179,26 @@ void run_c_tests(void) {...@@ -151,19 +179,26 @@ void run_c_tests(void) {
151 zig_u16(0xfffe);179 zig_u16(0xfffe);
152 zig_u32(0xfffffffd);180 zig_u32(0xfffffffd);
153 zig_u64(0xfffffffffffffffc);181 zig_u64(0xfffffffffffffffc);
182
183#ifndef ZIG_NO_I128
154 {184 {
155 struct u128 s = {0xfffffffffffffffc};185 struct u128 s = {0xfffffffffffffffc};
156 zig_struct_u128(s);186 zig_struct_u128(s);
157 }187 }
188#endif
158189
159 zig_i8(-1);190 zig_i8(-1);
160 zig_i16(-2);191 zig_i16(-2);
161 zig_i32(-3);192 zig_i32(-3);
162 zig_i64(-4);193 zig_i64(-4);
194
195#ifndef ZIG_NO_I128
163 {196 {
164 struct i128 s = {-6};197 struct i128 s = {-6};
165 zig_struct_i128(s);198 zig_struct_i128(s);
166 }199 }
200#endif
201
167 zig_five_integers(12, 34, 56, 78, 90);202 zig_five_integers(12, 34, 56, 78, 90);
168203
169 zig_f32(12.34f);204 zig_f32(12.34f);
...@@ -175,6 +210,7 @@ void run_c_tests(void) {...@@ -175,6 +210,7 @@ void run_c_tests(void) {
175210
176 zig_bool(true);211 zig_bool(true);
177212
213#ifndef ZIG_NO_COMPLEX
178 // TODO: Resolve https://github.com/ziglang/zig/issues/8465214 // TODO: Resolve https://github.com/ziglang/zig/issues/8465
179 //{215 //{
180 // float complex a = 1.25f + I * 2.6f;216 // float complex a = 1.25f + I * 2.6f;
...@@ -211,23 +247,30 @@ void run_c_tests(void) {...@@ -211,23 +247,30 @@ void run_c_tests(void) {
211 assert_or_panic(creal(z) == 1.5);247 assert_or_panic(creal(z) == 1.5);
212 assert_or_panic(cimag(z) == 13.5);248 assert_or_panic(cimag(z) == 13.5);
213 }249 }
250#endif
214251
252#if !defined __mips__ && !defined __riscv
215 {253 {
216 struct BigStruct s = {1, 2, 3, 4, 5};254 struct BigStruct s = {1, 2, 3, 4, 5};
217 zig_big_struct(s);255 zig_big_struct(s);
218 }256 }
257#endif
219258
259#if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv
220 {260 {
221 struct SmallStructInts s = {1, 2, 3, 4};261 struct SmallStructInts s = {1, 2, 3, 4};
222 zig_small_struct_ints(s);262 zig_small_struct_ints(s);
223 }263 }
264#endif
224265
266#ifndef ZIG_NO_I128
225 {267 {
226 __int128 s = 0;268 __int128 s = 0;
227 s |= 1 << 0;269 s |= 1 << 0;
228 s |= (__int128)2 << 64;270 s |= (__int128)2 << 64;
229 zig_big_packed_struct(s);271 zig_big_packed_struct(s);
230 }272 }
273#endif
231274
232 {275 {
233 uint8_t s = 0;276 uint8_t s = 0;
...@@ -238,21 +281,28 @@ void run_c_tests(void) {...@@ -238,21 +281,28 @@ void run_c_tests(void) {
238 zig_small_packed_struct(s);281 zig_small_packed_struct(s);
239 }282 }
240283
284#if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv
241 {285 {
242 struct SplitStructInts s = {1234, 100, 1337};286 struct SplitStructInts s = {1234, 100, 1337};
243 zig_split_struct_ints(s);287 zig_split_struct_ints(s);
244 }288 }
289#endif
245290
291#if !defined __arm__ && !defined __riscv
246 {292 {
247 struct MedStructMixed s = {1234, 100.0f, 1337.0f};293 struct MedStructMixed s = {1234, 100.0f, 1337.0f};
248 zig_med_struct_mixed(s);294 zig_med_struct_mixed(s);
249 }295 }
296#endif
250297
298#if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv
251 {299 {
252 struct SplitStructMixed s = {1234, 100, 1337.0f};300 struct SplitStructMixed s = {1234, 100, 1337.0f};
253 zig_split_struct_mixed(s);301 zig_split_struct_mixed(s);
254 }302 }
303#endif
255304
305#if !defined __mips__ && !defined __riscv
256 {306 {
257 struct BigStruct s = {30, 31, 32, 33, 34};307 struct BigStruct s = {30, 31, 32, 33, 34};
258 struct BigStruct res = zig_big_struct_both(s);308 struct BigStruct res = zig_big_struct_both(s);
...@@ -262,25 +312,32 @@ void run_c_tests(void) {...@@ -262,25 +312,32 @@ void run_c_tests(void) {
262 assert_or_panic(res.d == 23);312 assert_or_panic(res.d == 23);
263 assert_or_panic(res.e == 24);313 assert_or_panic(res.e == 24);
264 }314 }
315#endif
265316
317#ifndef __riscv
266 {318 {
267 struct Rect r1 = {1, 21, 16, 4};319 struct Rect r1 = {1, 21, 16, 4};
268 struct Rect r2 = {178, 189, 21, 15};320 struct Rect r2 = {178, 189, 21, 15};
269 zig_multiple_struct_ints(r1, r2);321 zig_multiple_struct_ints(r1, r2);
270 }322 }
323#endif
271324
325#if !defined __mips__ && !defined __riscv
272 {326 {
273 struct FloatRect r1 = {1, 21, 16, 4};327 struct FloatRect r1 = {1, 21, 16, 4};
274 struct FloatRect r2 = {178, 189, 21, 15};328 struct FloatRect r2 = {178, 189, 21, 15};
275 zig_multiple_struct_floats(r1, r2);329 zig_multiple_struct_floats(r1, r2);
276 }330 }
331#endif
277332
278 {333 {
279 assert_or_panic(zig_ret_bool() == 1);334 assert_or_panic(zig_ret_bool() == 1);
280335
281 assert_or_panic(zig_ret_u8() == 0xff);336 assert_or_panic(zig_ret_u8() == 0xff);
282 assert_or_panic(zig_ret_u16() == 0xffff);337 assert_or_panic(zig_ret_u16() == 0xffff);
338#ifndef __riscv
283 assert_or_panic(zig_ret_u32() == 0xffffffff);339 assert_or_panic(zig_ret_u32() == 0xffffffff);
340#endif
284 assert_or_panic(zig_ret_u64() == 0xffffffffffffffff);341 assert_or_panic(zig_ret_u64() == 0xffffffffffffffff);
285342
286 assert_or_panic(zig_ret_i8() == -1);343 assert_or_panic(zig_ret_i8() == -1);
...@@ -306,9 +363,11 @@ void c_u64(uint64_t x) {...@@ -306,9 +363,11 @@ void c_u64(uint64_t x) {
306 assert_or_panic(x == 0xfffffffffffffffcULL);363 assert_or_panic(x == 0xfffffffffffffffcULL);
307}364}
308365
366#ifndef ZIG_NO_I128
309void c_struct_u128(struct u128 x) {367void c_struct_u128(struct u128 x) {
310 assert_or_panic(x.value == 0xfffffffffffffffcULL);368 assert_or_panic(x.value == 0xfffffffffffffffcULL);
311}369}
370#endif
312371
313void c_i8(int8_t x) {372void c_i8(int8_t x) {
314 assert_or_panic(x == -1);373 assert_or_panic(x == -1);
...@@ -326,9 +385,11 @@ void c_i64(int64_t x) {...@@ -326,9 +385,11 @@ void c_i64(int64_t x) {
326 assert_or_panic(x == -4);385 assert_or_panic(x == -4);
327}386}
328387
388#ifndef ZIG_NO_I128
329void c_struct_i128(struct i128 x) {389void c_struct_i128(struct i128 x) {
330 assert_or_panic(x.value == -6);390 assert_or_panic(x.value == -6);
331}391}
392#endif
332393
333void c_f32(float x) {394void c_f32(float x) {
334 assert_or_panic(x == 12.34f);395 assert_or_panic(x == 12.34f);
...@@ -495,6 +556,7 @@ void c_small_packed_struct(uint8_t x) {...@@ -495,6 +556,7 @@ void c_small_packed_struct(uint8_t x) {
495 assert_or_panic(((x >> 6) & 0x3) == 3);556 assert_or_panic(((x >> 6) & 0x3) == 3);
496}557}
497558
559#ifndef ZIG_NO_I128
498__int128 c_ret_big_packed_struct() {560__int128 c_ret_big_packed_struct() {
499 __int128 s = 0;561 __int128 s = 0;
500 s |= 1 << 0;562 s |= 1 << 0;
...@@ -506,6 +568,7 @@ void c_big_packed_struct(__int128 x) {...@@ -506,6 +568,7 @@ void c_big_packed_struct(__int128 x) {
506 assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1);568 assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1);
507 assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2);569 assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2);
508}570}
571#endif
509572
510struct SplitStructMixed c_ret_split_struct_mixed() {573struct SplitStructMixed c_ret_split_struct_mixed() {
511 struct SplitStructMixed s = {574 struct SplitStructMixed s = {
...@@ -596,3 +659,45 @@ int32_t c_ret_i32() {...@@ -596,3 +659,45 @@ int32_t c_ret_i32() {
596int64_t c_ret_i64() {659int64_t c_ret_i64() {
597 return -1;660 return -1;
598}661}
662
663typedef struct {
664 uint32_t a;
665 uint8_t padding[4];
666 uint64_t b;
667} StructWithArray;
668
669void c_struct_with_array(StructWithArray x) {
670 assert_or_panic(x.a == 1);
671 assert_or_panic(x.b == 2);
672}
673
674StructWithArray c_ret_struct_with_array() {
675 return (StructWithArray) { 4, {}, 155 };
676}
677
678typedef struct {
679 struct Point {
680 double x;
681 double y;
682 } origin;
683 struct Size {
684 double width;
685 double height;
686 } size;
687} FloatArrayStruct;
688
689void c_float_array_struct(FloatArrayStruct x) {
690 assert_or_panic(x.origin.x == 5);
691 assert_or_panic(x.origin.y == 6);
692 assert_or_panic(x.size.width == 7);
693 assert_or_panic(x.size.height == 8);
694}
695
696FloatArrayStruct c_ret_float_array_struct() {
697 FloatArrayStruct x;
698 x.origin.x = 1;
699 x.origin.y = 2;
700 x.size.width = 3;
701 x.size.height = 4;
702 return x;
703}
test/c_abi/main.zig+110-4
...@@ -2,6 +2,8 @@ const std = @import("std");...@@ -2,6 +2,8 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const print = std.debug.print;3const print = std.debug.print;
4const expect = std.testing.expect;4const expect = std.testing.expect;
5const has_i128 = builtin.cpu.arch != .i386 and !builtin.cpu.arch.isARM() and
6 !builtin.cpu.arch.isMIPS();
57
6extern fn run_c_tests() void;8extern fn run_c_tests() void;
79
...@@ -40,13 +42,13 @@ test "C ABI integers" {...@@ -40,13 +42,13 @@ test "C ABI integers" {
40 c_u16(0xfffe);42 c_u16(0xfffe);
41 c_u32(0xfffffffd);43 c_u32(0xfffffffd);
42 c_u64(0xfffffffffffffffc);44 c_u64(0xfffffffffffffffc);
43 c_struct_u128(.{ .value = 0xfffffffffffffffc });45 if (has_i128) c_struct_u128(.{ .value = 0xfffffffffffffffc });
4446
45 c_i8(-1);47 c_i8(-1);
46 c_i16(-2);48 c_i16(-2);
47 c_i32(-3);49 c_i32(-3);
48 c_i64(-4);50 c_i64(-4);
49 c_struct_i128(.{ .value = -6 });51 if (has_i128) c_struct_i128(.{ .value = -6 });
50 c_five_integers(12, 34, 56, 78, 90);52 c_five_integers(12, 34, 56, 78, 90);
51}53}
5254
...@@ -110,7 +112,6 @@ test "C ABI floats" {...@@ -110,7 +112,6 @@ test "C ABI floats" {
110}112}
111113
112test "C ABI long double" {114test "C ABI long double" {
113 if (!builtin.cpu.arch.isWasm() and !builtin.cpu.arch.isAARCH64()) return error.SkipZigTest;
114 c_long_double(12.34);115 c_long_double(12.34);
115}116}
116117
...@@ -166,8 +167,11 @@ extern fn c_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble;...@@ -166,8 +167,11 @@ extern fn c_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble;
166extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;167extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat;
167extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;168extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble;
168169
170const complex_abi_compatible = builtin.cpu.arch != .i386 and !builtin.cpu.arch.isMIPS();
171
169test "C ABI complex float" {172test "C ABI complex float" {
170 if (true) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465173 if (!complex_abi_compatible) return error.SkipZigTest;
174 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
171175
172 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };176 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
173 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };177 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
...@@ -178,6 +182,8 @@ test "C ABI complex float" {...@@ -178,6 +182,8 @@ test "C ABI complex float" {
178}182}
179183
180test "C ABI complex float by component" {184test "C ABI complex float by component" {
185 if (!complex_abi_compatible) return error.SkipZigTest;
186
181 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };187 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
182 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };188 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
183189
...@@ -187,6 +193,8 @@ test "C ABI complex float by component" {...@@ -187,6 +193,8 @@ test "C ABI complex float by component" {
187}193}
188194
189test "C ABI complex double" {195test "C ABI complex double" {
196 if (!complex_abi_compatible) return error.SkipZigTest;
197
190 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };198 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
191 const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };199 const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };
192200
...@@ -196,6 +204,8 @@ test "C ABI complex double" {...@@ -196,6 +204,8 @@ test "C ABI complex double" {
196}204}
197205
198test "C ABI complex double by component" {206test "C ABI complex double by component" {
207 if (!complex_abi_compatible) return error.SkipZigTest;
208
199 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };209 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
200 const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };210 const b = ComplexDouble{ .real = 11.3, .imag = -1.5 };
201211
...@@ -250,6 +260,9 @@ const BigStruct = extern struct {...@@ -250,6 +260,9 @@ const BigStruct = extern struct {
250extern fn c_big_struct(BigStruct) void;260extern fn c_big_struct(BigStruct) void;
251261
252test "C ABI big struct" {262test "C ABI big struct" {
263 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
264 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
265
253 var s = BigStruct{266 var s = BigStruct{
254 .a = 1,267 .a = 1,
255 .b = 2,268 .b = 2,
...@@ -274,6 +287,8 @@ const BigUnion = extern union {...@@ -274,6 +287,8 @@ const BigUnion = extern union {
274extern fn c_big_union(BigUnion) void;287extern fn c_big_union(BigUnion) void;
275288
276test "C ABI big union" {289test "C ABI big union" {
290 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
291
277 var x = BigUnion{292 var x = BigUnion{
278 .a = BigStruct{293 .a = BigStruct{
279 .a = 1,294 .a = 1,
...@@ -304,6 +319,11 @@ extern fn c_med_struct_mixed(MedStructMixed) void;...@@ -304,6 +319,11 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
304extern fn c_ret_med_struct_mixed() MedStructMixed;319extern fn c_ret_med_struct_mixed() MedStructMixed;
305320
306test "C ABI medium struct of ints and floats" {321test "C ABI medium struct of ints and floats" {
322 if (builtin.cpu.arch == .i386) return error.SkipZigTest;
323 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
324 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
325 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
326
307 var s = MedStructMixed{327 var s = MedStructMixed{
308 .a = 1234,328 .a = 1234,
309 .b = 100.0,329 .b = 100.0,
...@@ -332,6 +352,11 @@ extern fn c_small_struct_ints(SmallStructInts) void;...@@ -332,6 +352,11 @@ extern fn c_small_struct_ints(SmallStructInts) void;
332extern fn c_ret_small_struct_ints() SmallStructInts;352extern fn c_ret_small_struct_ints() SmallStructInts;
333353
334test "C ABI small struct of ints" {354test "C ABI small struct of ints" {
355 if (builtin.cpu.arch == .i386) return error.SkipZigTest;
356 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
357 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
358 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
359
335 var s = SmallStructInts{360 var s = SmallStructInts{
336 .a = 1,361 .a = 1,
337 .b = 2,362 .b = 2,
...@@ -392,6 +417,8 @@ export fn zig_big_packed_struct(x: BigPackedStruct) void {...@@ -392,6 +417,8 @@ export fn zig_big_packed_struct(x: BigPackedStruct) void {
392}417}
393418
394test "C ABI big packed struct" {419test "C ABI big packed struct" {
420 if (!has_i128) return error.SkipZigTest;
421
395 var s = BigPackedStruct{ .a = 1, .b = 2 };422 var s = BigPackedStruct{ .a = 1, .b = 2 };
396 c_big_packed_struct(s);423 c_big_packed_struct(s);
397 var s2 = c_ret_big_packed_struct();424 var s2 = c_ret_big_packed_struct();
...@@ -407,6 +434,11 @@ const SplitStructInt = extern struct {...@@ -407,6 +434,11 @@ const SplitStructInt = extern struct {
407extern fn c_split_struct_ints(SplitStructInt) void;434extern fn c_split_struct_ints(SplitStructInt) void;
408435
409test "C ABI split struct of ints" {436test "C ABI split struct of ints" {
437 if (builtin.cpu.arch == .i386) return error.SkipZigTest;
438 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
439 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
440 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
441
410 var s = SplitStructInt{442 var s = SplitStructInt{
411 .a = 1234,443 .a = 1234,
412 .b = 100,444 .b = 100,
...@@ -430,6 +462,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;...@@ -430,6 +462,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
430extern fn c_ret_split_struct_mixed() SplitStructMixed;462extern fn c_ret_split_struct_mixed() SplitStructMixed;
431463
432test "C ABI split struct of ints and floats" {464test "C ABI split struct of ints and floats" {
465 if (builtin.cpu.arch == .i386) return error.SkipZigTest;
466 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
467 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
468 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
469
433 var s = SplitStructMixed{470 var s = SplitStructMixed{
434 .a = 1234,471 .a = 1234,
435 .b = 100,472 .b = 100,
...@@ -454,6 +491,9 @@ extern fn c_multiple_struct_ints(Rect, Rect) void;...@@ -454,6 +491,9 @@ extern fn c_multiple_struct_ints(Rect, Rect) void;
454extern fn c_multiple_struct_floats(FloatRect, FloatRect) void;491extern fn c_multiple_struct_floats(FloatRect, FloatRect) void;
455492
456test "C ABI sret and byval together" {493test "C ABI sret and byval together" {
494 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
495 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
496
457 var s = BigStruct{497 var s = BigStruct{
458 .a = 1,498 .a = 1,
459 .b = 2,499 .b = 2,
...@@ -503,6 +543,10 @@ const Vector5 = extern struct {...@@ -503,6 +543,10 @@ const Vector5 = extern struct {
503extern fn c_big_struct_floats(Vector5) void;543extern fn c_big_struct_floats(Vector5) void;
504544
505test "C ABI structs of floats as parameter" {545test "C ABI structs of floats as parameter" {
546 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
547 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
548 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
549
506 var v3 = Vector3{550 var v3 = Vector3{
507 .x = 3.0,551 .x = 3.0,
508 .y = 6.0,552 .y = 6.0,
...@@ -540,6 +584,8 @@ export fn zig_multiple_struct_ints(x: Rect, y: Rect) void {...@@ -540,6 +584,8 @@ export fn zig_multiple_struct_ints(x: Rect, y: Rect) void {
540}584}
541585
542test "C ABI structs of ints as multiple parameters" {586test "C ABI structs of ints as multiple parameters" {
587 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
588
543 var r1 = Rect{589 var r1 = Rect{
544 .left = 1,590 .left = 1,
545 .right = 21,591 .right = 21,
...@@ -574,6 +620,9 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {...@@ -574,6 +620,9 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
574}620}
575621
576test "C ABI structs of floats as multiple parameters" {622test "C ABI structs of floats as multiple parameters" {
623 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
624 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
625
577 var r1 = FloatRect{626 var r1 = FloatRect{
578 .left = 1,627 .left = 1,
579 .right = 21,628 .right = 21,
...@@ -665,3 +714,60 @@ test "C ABI integer return types" {...@@ -665,3 +714,60 @@ test "C ABI integer return types" {
665 try expect(c_ret_i32() == -1);714 try expect(c_ret_i32() == -1);
666 try expect(c_ret_i64() == -1);715 try expect(c_ret_i64() == -1);
667}716}
717
718const StructWithArray = extern struct {
719 a: i32,
720 padding: [4]u8,
721 b: i64,
722};
723extern fn c_struct_with_array(StructWithArray) void;
724extern fn c_ret_struct_with_array() StructWithArray;
725
726test "Struct with array as padding." {
727 if (builtin.cpu.arch == .i386) return error.SkipZigTest;
728 if (comptime builtin.cpu.arch.isARM()) return error.SkipZigTest;
729 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
730 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
731
732 c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 });
733
734 var x = c_ret_struct_with_array();
735 try std.testing.expect(x.a == 4);
736 try std.testing.expect(x.b == 155);
737}
738
739const FloatArrayStruct = extern struct {
740 origin: extern struct {
741 x: f64,
742 y: f64,
743 },
744 size: extern struct {
745 width: f64,
746 height: f64,
747 },
748};
749
750extern fn c_float_array_struct(FloatArrayStruct) void;
751extern fn c_ret_float_array_struct() FloatArrayStruct;
752
753test "Float array like struct" {
754 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
755 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
756
757 c_float_array_struct(.{
758 .origin = .{
759 .x = 5,
760 .y = 6,
761 },
762 .size = .{
763 .width = 7,
764 .height = 8,
765 },
766 });
767
768 var x = c_ret_float_array_struct();
769 try std.testing.expect(x.origin.x == 1);
770 try std.testing.expect(x.origin.y == 2);
771 try std.testing.expect(x.size.width == 3);
772 try std.testing.expect(x.size.height == 4);
773}
test/cases/compile_error_in_inline_fn_call_fixed.0.zig deleted-16
...@@ -1,16 +0,0 @@
1pub fn main() void {
2 var x: usize = 3;
3 const y = add(10, 2, x);
4 if (y - 6 != 0) unreachable;
5}
6
7inline fn add(a: usize, b: usize, c: usize) usize {
8 if (a == 10) @compileError("bad");
9 return a + b + c;
10}
11
12// error
13// output_mode=Exe
14//
15// :8:18: error: bad
16// :3:18: note: called from here
test/cases/compile_error_in_inline_fn_call_fixed.1.zig deleted-13
...@@ -1,13 +0,0 @@
1pub fn main() void {
2 var x: usize = 3;
3 const y = add(1, 2, x);
4 if (y - 6 != 0) unreachable;
5}
6
7inline fn add(a: usize, b: usize, c: usize) usize {
8 if (a == 10) @compileError("bad");
9 return a + b + c;
10}
11
12// run
13//
test/cases/compile_errors/any_typed_null_to_any_typed_optional.zig+2-2
...@@ -7,5 +7,5 @@ pub export fn entry() void {...@@ -7,5 +7,5 @@ pub export fn entry() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:21: error: expected type '?*anyopaque', found '?usize'10// :3:9: error: expected type '?*anyopaque', found '?usize'
11// :3:21: note: optional type child 'usize' cannot cast into optional type child '*anyopaque'11// :3:9: note: optional type child 'usize' cannot cast into optional type child '*anyopaque'
test/cases/compile_errors/assign_through_constant_pointer.zig+1-1
...@@ -7,4 +7,4 @@ export fn f() void {...@@ -7,4 +7,4 @@ export fn f() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:13: error: cannot assign to constant10// :3:7: error: cannot assign to constant
test/cases/compile_errors/assign_through_constant_slice.zig+1-1
...@@ -7,4 +7,4 @@ export fn f() void {...@@ -7,4 +7,4 @@ export fn f() void {
7// backend=stage27// backend=stage2
8// target=native8// target=native
9//9//
10// :3:13: error: cannot assign to constant10// :3:7: error: cannot assign to constant
test/cases/compile_errors/assign_to_constant_field.zig+1-1
...@@ -10,4 +10,4 @@ export fn derp() void {...@@ -10,4 +10,4 @@ export fn derp() void {
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :6:15: error: cannot assign to constant13// :6:6: error: cannot assign to constant
test/cases/compile_errors/assign_to_constant_variable.zig+1-1
...@@ -75,7 +75,7 @@ export fn entry18() void {...@@ -75,7 +75,7 @@ export fn entry18() void {
75// backend=stage275// backend=stage2
76// target=native76// target=native
77//77//
78// :3:9: error: cannot assign to constant78// :3:5: error: cannot assign to constant
79// :7:7: error: cannot assign to constant79// :7:7: error: cannot assign to constant
80// :11:7: error: cannot assign to constant80// :11:7: error: cannot assign to constant
81// :15:7: error: cannot assign to constant81// :15:7: error: cannot assign to constant
test/cases/compile_errors/call method on bound fn referring to var instance.zig deleted-20
...@@ -1,20 +0,0 @@
1export fn entry() void {
2 bad(bound_fn() == 1237);
3}
4const SimpleStruct = struct {
5 field: i32,
6
7 fn method(self: *const SimpleStruct) i32 {
8 return self.field + 3;
9 }
10};
11var simple_struct = SimpleStruct{ .field = 1234 };
12const bound_fn = simple_struct.method;
13fn bad(ok: bool) void {
14 _ = ok;
15}
16// error
17// target=native
18// backend=stage2
19//
20// :12:18: error: cannot load runtime value in comptime block
test/cases/compile_errors/call_assigned_to_constant.zig+2-2
...@@ -20,5 +20,5 @@ export fn entry1() void {...@@ -20,5 +20,5 @@ export fn entry1() void {
20// backend=stage220// backend=stage2
21// target=native21// target=native
22//22//
23// :12:14: error: cannot assign to constant23// :12:5: error: cannot assign to constant
24// :16:14: error: cannot assign to constant24// :16:5: error: cannot assign to constant
test/cases/compile_errors/callconv_from_global_variable.zig created+9
...@@ -0,0 +1,9 @@
1var cc: @import("std").builtin.CallingConvention = .C;
2export fn foo() callconv(cc) void {}
3
4// error
5// backend=stage2
6// target=native
7//
8// :2:26: error: unable to resolve comptime value
9// :2:26: note: calling convention must be comptime-known
test/cases/compile_errors/comptime_store_in_comptime_switch_in_runtime_if.zig+1-1
...@@ -21,5 +21,5 @@ pub export fn entry() void {...@@ -21,5 +21,5 @@ pub export fn entry() void {
21// backend=stage221// backend=stage2
22// target=native22// target=native
23//23//
24// :13:27: error: store to comptime variable depends on runtime condition24// :13:25: error: store to comptime variable depends on runtime condition
25// :11:16: note: runtime condition here25// :11:16: note: runtime condition here
test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig created+14
...@@ -0,0 +1,14 @@
1const Foo = struct {
2 x: i32,
3};
4var x: Foo = .{ .x = 2 };
5comptime {
6 x = .{ .x = 3 };
7}
8
9// error
10// backend=stage2
11// target=native
12//
13// :6:17: error: unable to evaluate comptime expression
14// :6:17: note: operation is runtime due to this operand
test/cases/compile_errors/implicit_cast_from_f64_to_f32.zig+1-1
...@@ -14,5 +14,5 @@ export fn entry2() void {...@@ -14,5 +14,5 @@ export fn entry2() void {
14// backend=llvm14// backend=llvm
15// target=native15// target=native
16//16//
17// :2:14: error: cannot load runtime value in comptime block17// :2:14: error: expected type 'f32', found 'f64'
18// :9:19: error: expected type 'f32', found 'f64'18// :9:19: error: expected type 'f32', found 'f64'
test/cases/compile_errors/non-const_expression_function_call_with_struct_return_value_outside_function.zig+2-1
...@@ -14,5 +14,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }...@@ -14,5 +14,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
14// backend=stage214// backend=stage2
15// target=native15// target=native
16//16//
17// :6:26: error: cannot store to runtime value in comptime block17// :6:24: error: unable to evaluate comptime expression
18// :6:5: note: operation is runtime due to this operand
18// :4:17: note: called from here19// :4:17: note: called from here
test/cases/compile_errors/non-pure_function_returns_type.zig+2-1
...@@ -21,5 +21,6 @@ export fn function_with_return_type_type() void {...@@ -21,5 +21,6 @@ export fn function_with_return_type_type() void {
21// backend=stage221// backend=stage2
22// target=native22// target=native
23//23//
24// :3:7: error: cannot load runtime value in comptime block24// :3:7: error: unable to evaluate comptime expression
25// :3:5: note: operation is runtime due to this operand
25// :16:19: note: called from here26// :16:19: note: called from here
test/cases/compile_errors/non_constant_expression_in_array_size.zig+2-1
...@@ -10,5 +10,6 @@ export fn entry() usize { return @offsetOf(Foo, "y"); }...@@ -10,5 +10,6 @@ export fn entry() usize { return @offsetOf(Foo, "y"); }
10// backend=stage210// backend=stage2
11// target=native11// target=native
12//12//
13// :5:25: error: cannot load runtime value in comptime block13// :5:18: error: unable to resolve comptime value
14// :5:18: note: value being returned at comptime must be comptime-known
14// :2:12: note: called from here15// :2:12: note: called from here
test/cases/compile_errors/reassign_to_slice_parameter.zig+1-1
...@@ -9,4 +9,4 @@ export fn entry() void {...@@ -9,4 +9,4 @@ export fn entry() void {
9// backend=llvm9// backend=llvm
10// target=native10// target=native
11//11//
12// :2:10: error: cannot assign to constant12// :2:5: error: cannot assign to constant
test/cases/compile_errors/reference_to_const_data.zig+4-4
...@@ -23,7 +23,7 @@ export fn qux() void {...@@ -23,7 +23,7 @@ export fn qux() void {
23// backend=stage223// backend=stage2
24// target=native24// target=native
25//25//
26// :3:14: error: cannot assign to constant26// :3:8: error: cannot assign to constant
27// :7:13: error: cannot assign to constant27// :7:8: error: cannot assign to constant
28// :11:13: error: cannot assign to constant28// :11:8: error: cannot assign to constant
29// :19:13: error: cannot assign to constant29// :19:8: error: cannot assign to constant
test/cases/compile_errors/write_to_const_global_variable.zig+1-1
...@@ -8,4 +8,4 @@ export fn entry() void { f(); }...@@ -8,4 +8,4 @@ export fn entry() void { f(); }
8// backend=stage28// backend=stage2
9// target=native9// target=native
10//10//
11// :3:9: error: cannot assign to constant11// :3:5: error: cannot assign to constant
test/cases/extern_variable_has_no_type.0.zig+2-1
...@@ -6,4 +6,5 @@ extern var foo: i32;...@@ -6,4 +6,5 @@ extern var foo: i32;
66
7// error7// error
8//8//
9// :2:15: error: cannot load runtime value in comptime block9// :2:19: error: unable to evaluate comptime expression
10// :2:15: note: operation is runtime due to this operand
test/cases/recursive_inline_function.0.zig deleted-13
...@@ -1,13 +0,0 @@
1pub fn main() void {
2 const y = fibonacci(7);
3 if (y - 21 != 0) unreachable;
4}
5
6inline fn fibonacci(n: usize) usize {
7 if (n <= 2) return n;
8 return fibonacci(n - 2) + fibonacci(n - 1);
9}
10
11// run
12// target=x86_64-linux,arm-linux,wasm32-wasi
13//
test/cases/recursive_inline_function.1.zig deleted-20
...@@ -1,20 +0,0 @@
1// This additionally tests that the compile error reports the correct source location.
2// Without storing source locations relative to the owner decl, the compile error
3// here would be off by 2 bytes (from the "7" -> "999").
4pub fn main() void {
5 const y = fibonacci(999);
6 if (y - 21 != 0) unreachable;
7}
8
9inline fn fibonacci(n: usize) usize {
10 if (n <= 2) return n;
11 return fibonacci(n - 2) + fibonacci(n - 1);
12}
13
14// error
15//
16// :11:21: error: evaluation exceeded 1000 backwards branches
17// :11:21: note: use @setEvalBranchQuota() to raise the branch limit from 1000
18// :11:40: note: called from here (6 times)
19// :11:21: note: called from here (495 times)
20// :5:24: note: called from here
test/cases/x86_64-linux/comptime_var.0.zig+1-1
...@@ -8,5 +8,5 @@ pub fn main() void {...@@ -8,5 +8,5 @@ pub fn main() void {
8// output_mode=Exe8// output_mode=Exe
9// target=x86_64-linux9// target=x86_64-linux
10//10//
11// :4:21: error: store to comptime variable depends on runtime condition11// :4:19: error: store to comptime variable depends on runtime condition
12// :4:11: note: runtime condition here12// :4:11: note: runtime condition here
test/cases/x86_64-linux/comptime_var.1.zig+1-1
...@@ -9,5 +9,5 @@ pub fn main() void {...@@ -9,5 +9,5 @@ pub fn main() void {
99
10// error10// error
11//11//
12// :6:21: error: store to comptime variable depends on runtime condition12// :6:19: error: store to comptime variable depends on runtime condition
13// :4:13: note: runtime condition here13// :4:13: note: runtime condition here
test/cases/x86_64-macos/comptime_var.0.zig+1-1
...@@ -8,5 +8,5 @@ pub fn main() void {...@@ -8,5 +8,5 @@ pub fn main() void {
8// output_mode=Exe8// output_mode=Exe
9// target=x86_64-macos9// target=x86_64-macos
10//10//
11// :4:21: error: store to comptime variable depends on runtime condition11// :4:19: error: store to comptime variable depends on runtime condition
12// :4:11: note: runtime condition here12// :4:11: note: runtime condition here
test/cases/x86_64-macos/comptime_var.1.zig+1-1
...@@ -9,5 +9,5 @@ pub fn main() void {...@@ -9,5 +9,5 @@ pub fn main() void {
99
10// error10// error
11//11//
12// :6:21: error: store to comptime variable depends on runtime condition12// :6:19: error: store to comptime variable depends on runtime condition
13// :4:13: note: runtime condition here13// :4:13: note: runtime condition here
test/stage2/cbe.zig+3-2
...@@ -51,8 +51,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -51,8 +51,9 @@ pub fn addCases(ctx: *TestContext) !void {
51 \\}51 \\}
52 \\var y: @import("std").builtin.CallingConvention = .C;52 \\var y: @import("std").builtin.CallingConvention = .C;
53 , &.{53 , &.{
54 ":2:22: error: cannot load runtime value in comptime block",54 ":2:22: error: expected type 'type', found 'i32'",
55 ":5:26: error: cannot load runtime value in comptime block",55 ":5:26: error: unable to resolve comptime value",
56 ":5:26: note: calling convention must be comptime-known",
56 });57 });
57 }58 }
5859