| author | |
| committer | |
| log | 972c39e2c00c487a483bad002ef33ca1a5c21d02 |
| tree | 8a5ef4ae22f2a36b020062a913c79278bfb79a30 |
| parent | 41575b1f55b0f18d65bfeb23dc04a5489ed47b65 |
| parent | 2609e33ab08850405682a79f60cca66c13f9a40d |
| signature |
Stage2 bug fixes46 files changed, 647 insertions(+), 201 deletions(-)
src/AstGen.zig+33-17| ... | ... | @@ -232,7 +232,7 @@ pub const ResultLoc = union(enum) { |
| 232 | 232 | coerced_ty: Zir.Inst.Ref, |
| 233 | 233 | /// The expression must store its result into this typed pointer. The result instruction |
| 234 | 234 | /// from the expression must be ignored. |
| 235 | ptr: Zir.Inst.Ref, | |
| 235 | ptr: PtrResultLoc, | |
| 236 | 236 | /// The expression must store its result into this allocation, which has an inferred type. |
| 237 | 237 | /// The result instruction from the expression must be ignored. |
| 238 | 238 | /// Always an instruction with tag `alloc_inferred`. |
| ... | ... | @@ -242,6 +242,11 @@ pub const ResultLoc = union(enum) { |
| 242 | 242 | /// The result instruction from the expression must be ignored. |
| 243 | 243 | block_ptr: *GenZir, |
| 244 | 244 | |
| 245 | const PtrResultLoc = struct { | |
| 246 | inst: Zir.Inst.Ref, | |
| 247 | src_node: ?Ast.Node.Index = null, | |
| 248 | }; | |
| 249 | ||
| 245 | 250 | pub const Strategy = struct { |
| 246 | 251 | elide_store_to_block_ptr_instructions: bool, |
| 247 | 252 | tag: Tag, |
| ... | ... | @@ -1380,8 +1385,8 @@ fn arrayInitExpr( |
| 1380 | 1385 | const result = try arrayInitExprInner(gz, scope, node, array_init.ast.elements, types.array, types.elem, tag); |
| 1381 | 1386 | return rvalue(gz, rl, result, node); |
| 1382 | 1387 | }, |
| 1383 | .ptr => |ptr_inst| { | |
| 1384 | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_inst, array_init.ast.elements, types.array); | |
| 1388 | .ptr => |ptr_res| { | |
| 1389 | return arrayInitExprRlPtr(gz, scope, rl, node, ptr_res.inst, array_init.ast.elements, types.array); | |
| 1385 | 1390 | }, |
| 1386 | 1391 | .inferred_ptr => |ptr_inst| { |
| 1387 | 1392 | if (types.array == .none) { |
| ... | ... | @@ -1513,7 +1518,7 @@ fn arrayInitExprRlPtrInner( |
| 1513 | 1518 | }); |
| 1514 | 1519 | astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; |
| 1515 | 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 | } |
| 1518 | 1523 | |
| 1519 | 1524 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -1631,7 +1636,7 @@ fn structInitExpr( |
| 1631 | 1636 | const result = try structInitExprRlTy(gz, scope, node, struct_init, inner_ty_inst, .struct_init); |
| 1632 | 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 | 1640 | .inferred_ptr => |ptr_inst| { |
| 1636 | 1641 | if (struct_init.ast.type_expr == 0) { |
| 1637 | 1642 | // We treat this case differently so that we don't get a crash when |
| ... | ... | @@ -1739,7 +1744,7 @@ fn structInitExprRlPtrInner( |
| 1739 | 1744 | }); |
| 1740 | 1745 | astgen.extra.items[extra_index] = refToIndex(field_ptr).?; |
| 1741 | 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 | } |
| 1744 | 1749 | |
| 1745 | 1750 | const tag: Zir.Inst.Tag = if (gz.force_comptime) |
| ... | ... | @@ -2998,7 +3003,7 @@ fn varDecl( |
| 2998 | 3003 | } |
| 2999 | 3004 | }; |
| 3000 | 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 | 3007 | } else a: { |
| 3003 | 3008 | const alloc = alloc: { |
| 3004 | 3009 | if (align_inst == .none) { |
| ... | ... | @@ -3098,7 +3103,10 @@ fn assign(gz: *GenZir, scope: *Scope, infix_node: Ast.Node.Index) InnerError!voi |
| 3098 | 3103 | } |
| 3099 | 3104 | } |
| 3100 | 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 | } |
| 3103 | 3111 | |
| 3104 | 3112 | fn assignOp( |
| ... | ... | @@ -6729,7 +6737,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6729 | 6737 | } |
| 6730 | 6738 | |
| 6731 | 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 | 6741 | } else .{ |
| 6734 | 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 | 6756 | }, |
| 6749 | 6757 | .always => { |
| 6750 | 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 | 6760 | try genDefers(gz, defer_outer, scope, .{ .both = err_code }); |
| 6753 | 6761 | try emitDbgStmt(gz, ret_line, ret_column); |
| 6754 | 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 | 6773 | } |
| 6766 | 6774 | |
| 6767 | 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 | 6777 | const is_non_err = try gz.addUnNode(.is_non_err, result, node); |
| 6770 | 6778 | const condbr = try gz.addCondBr(.condbr, node); |
| 6771 | 6779 | |
| ... | ... | @@ -7336,7 +7344,10 @@ fn as( |
| 7336 | 7344 | const result = try reachableExpr(gz, scope, .{ .ty = dest_type }, rhs, node); |
| 7337 | 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 | 7351 | return asRlPtr(gz, scope, rl, node, result_ptr, rhs, dest_type); |
| 7341 | 7352 | }, |
| 7342 | 7353 | .block_ptr => |block_scope| { |
| ... | ... | @@ -9569,9 +9580,9 @@ fn rvalue( |
| 9569 | 9580 | }), |
| 9570 | 9581 | } |
| 9571 | 9582 | }, |
| 9572 | .ptr => |ptr_inst| { | |
| 9573 | _ = try gz.addPlNode(.store_node, src_node, Zir.Inst.Bin{ | |
| 9574 | .lhs = ptr_inst, | |
| 9583 | .ptr => |ptr_res| { | |
| 9584 | _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{ | |
| 9585 | .lhs = ptr_res.inst, | |
| 9575 | 9586 | .rhs = result, |
| 9576 | 9587 | }); |
| 9577 | 9588 | return result; |
| ... | ... | @@ -10444,11 +10455,16 @@ const GenZir = struct { |
| 10444 | 10455 | gz.break_result_loc = parent_rl; |
| 10445 | 10456 | }, |
| 10446 | 10457 | |
| 10447 | .discard, .none, .ptr, .ref => { | |
| 10458 | .discard, .none, .ref => { | |
| 10448 | 10459 | gz.rl_ty_inst = .none; |
| 10449 | 10460 | gz.break_result_loc = parent_rl; |
| 10450 | 10461 | }, |
| 10451 | 10462 | |
| 10463 | .ptr => |ptr_res| { | |
| 10464 | gz.rl_ty_inst = .none; | |
| 10465 | gz.break_result_loc = .{ .ptr = .{ .inst = ptr_res.inst } }; | |
| 10466 | }, | |
| 10467 | ||
| 10452 | 10468 | .inferred_ptr => |ptr| { |
| 10453 | 10469 | gz.rl_ty_inst = .none; |
| 10454 | 10470 | gz.rl_ptr = ptr; |
| ... | ... | @@ -11610,7 +11626,7 @@ const GenZir = struct { |
| 11610 | 11626 | |
| 11611 | 11627 | fn addRet(gz: *GenZir, rl: ResultLoc, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { |
| 11612 | 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 | 11630 | .ty, .ty_shift_operand => _ = try gz.addUnNode(.ret_node, operand, node), |
| 11615 | 11631 | else => unreachable, |
| 11616 | 11632 | } |
src/Module.zig+46| ... | ... | @@ -2878,6 +2878,32 @@ pub const SrcLoc = struct { |
| 2878 | 2878 | }; |
| 2879 | 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 | } |
| 2883 | 2909 | |
| ... | ... | @@ -3213,6 +3239,12 @@ pub const LazySrcLoc = union(enum) { |
| 3213 | 3239 | /// The source location points to the type of an array or struct initializer. |
| 3214 | 3240 | /// The Decl is determined contextually. |
| 3215 | 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, | |
| 3216 | 3248 | |
| 3217 | 3249 | pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
| 3218 | 3250 | |
| ... | ... | @@ -3296,6 +3328,8 @@ pub const LazySrcLoc = union(enum) { |
| 3296 | 3328 | .node_offset_container_tag, |
| 3297 | 3329 | .node_offset_field_default, |
| 3298 | 3330 | .node_offset_init_ty, |
| 3331 | .node_offset_store_ptr, | |
| 3332 | .node_offset_store_operand, | |
| 3299 | 3333 | => .{ |
| 3300 | 3334 | .file_scope = decl.getFileScope(), |
| 3301 | 3335 | .parent_decl_node = decl.src_node, |
| ... | ... | @@ -5607,6 +5641,18 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { |
| 5607 | 5641 | else => |e| return e, |
| 5608 | 5642 | }; |
| 5609 | 5643 | |
| 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 | 5656 | // If we don't get an error return trace from a caller, create our own. |
| 5611 | 5657 | if (func.calls_or_awaits_errorable_fn and |
| 5612 | 5658 | mod.comp.bin_file.options.error_return_tracing and |
src/Sema.zig+82-44| ... | ... | @@ -82,6 +82,8 @@ is_generic_instantiation: bool = false, |
| 82 | 82 | /// function types will emit generic poison instead of a partial type. |
| 83 | 83 | no_partial_func_ty: bool = false, |
| 84 | 84 | |
| 85 | unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{}, | |
| 86 | ||
| 85 | 87 | const std = @import("std"); |
| 86 | 88 | const math = std.math; |
| 87 | 89 | const mem = std.mem; |
| ... | ... | @@ -579,6 +581,7 @@ pub fn deinit(sema: *Sema) void { |
| 579 | 581 | } |
| 580 | 582 | sema.post_hoc_blocks.deinit(gpa); |
| 581 | 583 | } |
| 584 | sema.unresolved_inferred_allocs.deinit(gpa); | |
| 582 | 585 | sema.* = undefined; |
| 583 | 586 | } |
| 584 | 587 | |
| ... | ... | @@ -1235,9 +1238,6 @@ fn analyzeBodyInner( |
| 1235 | 1238 | i = 0; |
| 1236 | 1239 | continue; |
| 1237 | 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 | 1241 | break always_noreturn; |
| 1242 | 1242 | } |
| 1243 | 1243 | }, |
| ... | ... | @@ -2186,7 +2186,6 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 2186 | 2186 | defer trash_block.instructions.deinit(sema.gpa); |
| 2187 | 2187 | const operand = try trash_block.addBitCast(pointee_ty, .void_value); |
| 2188 | 2188 | |
| 2189 | try sema.requireFunctionBlock(block, src); | |
| 2190 | 2189 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 2191 | 2190 | .pointee_type = pointee_ty, |
| 2192 | 2191 | .@"align" = inferred_alloc.alignment, |
| ... | ... | @@ -3219,7 +3218,6 @@ fn zirAllocExtended( |
| 3219 | 3218 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 3220 | 3219 | } |
| 3221 | 3220 | const target = sema.mod.getTarget(); |
| 3222 | try sema.requireFunctionBlock(block, src); | |
| 3223 | 3221 | try sema.resolveTypeLayout(block, src, var_ty); |
| 3224 | 3222 | const ptr_type = try Type.ptr(sema.arena, sema.mod, .{ |
| 3225 | 3223 | .pointee_type = var_ty, |
| ... | ... | @@ -3237,8 +3235,8 @@ fn zirAllocExtended( |
| 3237 | 3235 | inferred_alloc_ty, |
| 3238 | 3236 | try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }), |
| 3239 | 3237 | ); |
| 3240 | try sema.requireFunctionBlock(block, src); | |
| 3241 | 3238 | try block.instructions.append(sema.gpa, Air.refToIndex(result).?); |
| 3239 | try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {}); | |
| 3242 | 3240 | return result; |
| 3243 | 3241 | } |
| 3244 | 3242 | |
| ... | ... | @@ -3318,7 +3316,6 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3318 | 3316 | return sema.addConstant(const_ptr_ty, val); |
| 3319 | 3317 | } |
| 3320 | 3318 | |
| 3321 | try sema.requireFunctionBlock(block, src); | |
| 3322 | 3319 | return block.addBitCast(const_ptr_ty, alloc); |
| 3323 | 3320 | } |
| 3324 | 3321 | |
| ... | ... | @@ -3345,7 +3342,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 3345 | 3342 | |
| 3346 | 3343 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3347 | 3344 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 3348 | const var_decl_src = inst_data.src(); | |
| 3349 | 3345 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 3350 | 3346 | if (block.is_comptime) { |
| 3351 | 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 | 3351 | .pointee_type = var_ty, |
| 3356 | 3352 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 3357 | 3353 | }); |
| 3358 | try sema.requireFunctionBlock(block, var_decl_src); | |
| 3359 | 3354 | try sema.queueFullTypeResolution(var_ty); |
| 3360 | 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 | 3360 | defer tracy.end(); |
| 3366 | 3361 | |
| 3367 | 3362 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 3368 | const var_decl_src = inst_data.src(); | |
| 3369 | 3363 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 3370 | 3364 | const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); |
| 3371 | 3365 | if (block.is_comptime) { |
| ... | ... | @@ -3377,7 +3371,6 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 3377 | 3371 | .pointee_type = var_ty, |
| 3378 | 3372 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 3379 | 3373 | }); |
| 3380 | try sema.requireFunctionBlock(block, var_decl_src); | |
| 3381 | 3374 | try sema.queueFullTypeResolution(var_ty); |
| 3382 | 3375 | return block.addTy(.alloc, ptr_type); |
| 3383 | 3376 | } |
| ... | ... | @@ -3413,8 +3406,8 @@ fn zirAllocInferred( |
| 3413 | 3406 | inferred_alloc_ty, |
| 3414 | 3407 | try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }), |
| 3415 | 3408 | ); |
| 3416 | try sema.requireFunctionBlock(block, src); | |
| 3417 | 3409 | try block.instructions.append(sema.gpa, Air.refToIndex(result).?); |
| 3410 | try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {}); | |
| 3418 | 3411 | return result; |
| 3419 | 3412 | } |
| 3420 | 3413 | |
| ... | ... | @@ -3464,6 +3457,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3464 | 3457 | } |
| 3465 | 3458 | }, |
| 3466 | 3459 | .inferred_alloc => { |
| 3460 | assert(sema.unresolved_inferred_allocs.remove(ptr_inst)); | |
| 3467 | 3461 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 3468 | 3462 | const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst); |
| 3469 | 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 | 3560 | return; |
| 3567 | 3561 | } |
| 3568 | 3562 | |
| 3569 | try sema.requireFunctionBlock(block, src); | |
| 3570 | 3563 | try sema.queueFullTypeResolution(final_elem_ty); |
| 3571 | 3564 | |
| 3572 | 3565 | // Change it to a normal alloc. |
| ... | ... | @@ -3912,7 +3905,6 @@ fn validateUnionInit( |
| 3912 | 3905 | return; |
| 3913 | 3906 | } |
| 3914 | 3907 | |
| 3915 | try sema.requireFunctionBlock(block, init_src); | |
| 3916 | 3908 | const new_tag = try sema.addConstant(tag_ty, tag_val); |
| 3917 | 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 | 4640 | try sema.addToInferredErrorSet(operand); |
| 4649 | 4641 | } |
| 4650 | 4642 | |
| 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 | } |
| 4653 | 4648 | |
| 4654 | 4649 | fn 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 | 4803 | if (block.is_comptime or force_comptime) { |
| 4809 | 4804 | return sema.fail(block, src, "encountered @panic at comptime", .{}); |
| 4810 | 4805 | } |
| 4811 | try sema.requireFunctionBlock(block, src); | |
| 4812 | 4806 | return sema.panicWithMsg(block, src, msg_inst); |
| 4813 | 4807 | } |
| 4814 | 4808 | |
| ... | ... | @@ -6288,7 +6282,6 @@ fn analyzeCall( |
| 6288 | 6282 | break :res res2; |
| 6289 | 6283 | } else res: { |
| 6290 | 6284 | assert(!func_ty_info.is_generic); |
| 6291 | try sema.requireFunctionBlock(block, call_src); | |
| 6292 | 6285 | |
| 6293 | 6286 | const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len); |
| 6294 | 6287 | for (uncasted_args) |uncasted_arg, i| { |
| ... | ... | @@ -6414,9 +6407,9 @@ fn analyzeInlineCallArg( |
| 6414 | 6407 | }; |
| 6415 | 6408 | } |
| 6416 | 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); | |
| 6418 | 6410 | |
| 6419 | 6411 | if (is_comptime_call) { |
| 6412 | try sema.inst_map.putNoClobber(sema.gpa, inst, casted_arg); | |
| 6420 | 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 | 6414 | if (err == error.AnalysisFail and sema.err != null) { |
| 6422 | 6415 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| ... | ... | @@ -6441,6 +6434,20 @@ fn analyzeInlineCallArg( |
| 6441 | 6434 | .ty = param_ty, |
| 6442 | 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 | } |
| 6445 | 6452 | |
| 6446 | 6453 | arg_i.* += 1; |
| ... | ... | @@ -6449,9 +6456,10 @@ fn analyzeInlineCallArg( |
| 6449 | 6456 | // No coercion needed. |
| 6450 | 6457 | const uncasted_arg = uncasted_args[arg_i.*]; |
| 6451 | 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); | |
| 6453 | 6460 | |
| 6454 | 6461 | if (is_comptime_call) { |
| 6462 | try sema.inst_map.putNoClobber(sema.gpa, inst, uncasted_arg); | |
| 6455 | 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 | 6464 | if (err == error.AnalysisFail and sema.err != null) { |
| 6457 | 6465 | try sema.addComptimeReturnTypeNote(arg_block, func, func_src, ret_ty, sema.err.?, comptime_only_ret_ty); |
| ... | ... | @@ -6476,6 +6484,20 @@ fn analyzeInlineCallArg( |
| 6476 | 6484 | .ty = sema.typeOf(uncasted_arg), |
| 6477 | 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 | } |
| 6480 | 6502 | |
| 6481 | 6503 | arg_i.* += 1; |
| ... | ... | @@ -6588,6 +6610,11 @@ fn instantiateGenericCall( |
| 6588 | 6610 | } |
| 6589 | 6611 | |
| 6590 | 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 | } | |
| 6591 | 6618 | |
| 6592 | 6619 | if (is_comptime) { |
| 6593 | 6620 | const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) { |
| ... | ... | @@ -6892,8 +6919,6 @@ fn instantiateGenericCall( |
| 6892 | 6919 | const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl); |
| 6893 | 6920 | |
| 6894 | 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 | 6922 | const comptime_args = callee.comptime_args.?; |
| 6898 | 6923 | const func_ty = mod.declPtr(callee.owner_decl).ty; |
| 6899 | 6924 | const new_fn_info = func_ty.fnInfo(); |
| ... | ... | @@ -6963,6 +6988,16 @@ fn instantiateGenericCall( |
| 6963 | 6988 | return result; |
| 6964 | 6989 | } |
| 6965 | 6990 | |
| 6991 | fn 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 | ||
| 6966 | 7001 | fn emitDbgInline( |
| 6967 | 7002 | sema: *Sema, |
| 6968 | 7003 | block: *Block, |
| ... | ... | @@ -7441,7 +7476,6 @@ fn analyzeOptionalPayloadPtr( |
| 7441 | 7476 | // If the pointer resulting from this function was stored at comptime, |
| 7442 | 7477 | // the optional non-null bit would be set that way. But in this case, |
| 7443 | 7478 | // we need to emit a runtime instruction to do it. |
| 7444 | try sema.requireFunctionBlock(block, src); | |
| 7445 | 7479 | _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); |
| 7446 | 7480 | } |
| 7447 | 7481 | return sema.addConstant( |
| ... | ... | @@ -14499,6 +14533,12 @@ fn zirClosureGet( |
| 14499 | 14533 | return sema.failWithOwnedErrorMsg(msg); |
| 14500 | 14534 | } |
| 14501 | 14535 | |
| 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 | 14542 | return sema.addConstant(tv.ty, tv.val); |
| 14503 | 14543 | } |
| 14504 | 14544 | |
| ... | ... | @@ -15664,7 +15704,9 @@ fn zirBoolBr( |
| 15664 | 15704 | _ = try lhs_block.addBr(block_inst, lhs_result); |
| 15665 | 15705 | |
| 15666 | 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 | } | |
| 15668 | 15710 | |
| 15669 | 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 | 16038 | if (block.is_comptime or inst_data.force_comptime) { |
| 15997 | 16039 | return sema.fail(block, src, "reached unreachable code", .{}); |
| 15998 | 16040 | } |
| 15999 | try sema.requireFunctionBlock(block, src); | |
| 16000 | 16041 | // TODO Add compile error for @optimizeFor occurring too late in a scope. |
| 16001 | 16042 | try block.addUnreachable(src, true); |
| 16002 | 16043 | return always_noreturn; |
| ... | ... | @@ -16171,6 +16212,7 @@ fn analyzeRet( |
| 16171 | 16212 | |
| 16172 | 16213 | if (block.inlining) |inlining| { |
| 16173 | 16214 | if (block.is_comptime) { |
| 16215 | _ = try sema.resolveConstMaybeUndefVal(block, src, operand, "value being returned at comptime must be comptime-known"); | |
| 16174 | 16216 | inlining.comptime_result = operand; |
| 16175 | 16217 | return error.ComptimeReturn; |
| 16176 | 16218 | } |
| ... | ... | @@ -21117,14 +21159,6 @@ fn zirBuiltinExtern( |
| 21117 | 21159 | return block.addBitCast(ty, ref); |
| 21118 | 21160 | } |
| 21119 | 21161 | |
| 21120 | /// Asserts that the block is not comptime. | |
| 21121 | fn 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 | ||
| 21128 | 21162 | fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { |
| 21129 | 21163 | if (block.is_comptime) { |
| 21130 | 21164 | const msg = msg: { |
| ... | ... | @@ -21138,7 +21172,6 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: |
| 21138 | 21172 | }; |
| 21139 | 21173 | return sema.failWithOwnedErrorMsg(msg); |
| 21140 | 21174 | } |
| 21141 | try sema.requireFunctionBlock(block, src); | |
| 21142 | 21175 | } |
| 21143 | 21176 | |
| 21144 | 21177 | /// Emit a compile error if type cannot be used for a runtime variable. |
| ... | ... | @@ -25111,11 +25144,6 @@ fn storePtr2( |
| 25111 | 25144 | return; |
| 25112 | 25145 | } |
| 25113 | 25146 | |
| 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 | 25147 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 25120 | 25148 | try sema.queueFullTypeResolution(elem_ty); |
| 25121 | 25149 | if (is_ret) { |
| ... | ... | @@ -27023,12 +27051,6 @@ fn analyzeLoad( |
| 27023 | 27051 | } |
| 27024 | 27052 | } |
| 27025 | 27053 | |
| 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 | 27054 | return block.addTyOp(.load, elem_ty, ptr); |
| 27033 | 27055 | } |
| 27034 | 27056 | |
| ... | ... | @@ -28581,6 +28603,20 @@ fn resolveLazyValue( |
| 28581 | 28603 | const ty = val.castTag(.lazy_size).?.data; |
| 28582 | 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 | 28620 | else => return, |
| 28585 | 28621 | } |
| 28586 | 28622 | } |
| ... | ... | @@ -28751,6 +28787,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi |
| 28751 | 28787 | |
| 28752 | 28788 | try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); |
| 28753 | 28789 | struct_obj.backing_int_ty = try backing_int_ty.copy(decl_arena_allocator); |
| 28790 | try wip_captures.finalize(); | |
| 28754 | 28791 | } else { |
| 28755 | 28792 | var buf: Type.Payload.Bits = .{ |
| 28756 | 28793 | .base = .{ .tag = .int_unsigned }, |
| ... | ... | @@ -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(); | |
| 29365 | 29403 | |
| 29366 | 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 | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 6 | 6 | const Type = @import("../../type.zig").Type; |
| 7 | 7 | |
| 8 | pub const Class = enum { memory, integer, none, float_array }; | |
| 8 | pub const Class = enum(u8) { memory, integer, none, float_array, _ }; | |
| 9 | 9 | |
| 10 | /// For `float_array` the second element will be the amount of floats. | |
| 10 | 11 | pub 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 | ||
| 18 | fn classifyTypeInner(ty: Type, target: std.Target) [2]Class { | |
| 11 | 19 | if (!ty.hasRuntimeBitsIgnoreComptime()) return .{ .none, .none }; |
| 12 | 20 | switch (ty.zigTypeTag()) { |
| 13 | 21 | .Struct => { |
| 14 | 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 | 23 | const bit_size = ty.bitSize(target); |
| 32 | 24 | if (bit_size > 128) return .{ .memory, .none }; |
| 33 | 25 | if (bit_size > 64) return .{ .integer, .integer }; |
| ... | ... | @@ -67,6 +59,70 @@ pub fn classifyType(ty: Type, target: std.Target) [2]Class { |
| 67 | 59 | } |
| 68 | 60 | } |
| 69 | 61 | |
| 62 | const sret_float_count = 4; | |
| 63 | fn 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 | ||
| 103 | pub 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 | ||
| 70 | 126 | const callee_preserved_regs_impl = if (builtin.os.tag.isDarwin()) struct { |
| 71 | 127 | pub const callee_preserved_regs = [_]Register{ |
| 72 | 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 | 388 | } |
| 389 | 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 | 404 | else => unreachable, |
| 392 | 405 | } |
| 393 | 406 | } |
src/codegen/llvm.zig+9-10| ... | ... | @@ -3125,10 +3125,10 @@ pub const DeclGen = struct { |
| 3125 | 3125 | .as_u16 => { |
| 3126 | 3126 | try llvm_params.append(dg.context.intType(16)); |
| 3127 | 3127 | }, |
| 3128 | .float_array => { | |
| 3128 | .float_array => |count| { | |
| 3129 | 3129 | const param_ty = fn_info.param_types[it.zig_index - 1]; |
| 3130 | const float_ty = try dg.lowerType(param_ty.structFieldType(0)); | |
| 3131 | const field_count = @intCast(c_uint, param_ty.structFieldCount()); | |
| 3130 | const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty).?); | |
| 3131 | const field_count = @intCast(c_uint, count); | |
| 3132 | 3132 | const arr_ty = float_ty.arrayType(field_count); |
| 3133 | 3133 | try llvm_params.append(arr_ty); |
| 3134 | 3134 | }, |
| ... | ... | @@ -4801,7 +4801,7 @@ pub const FuncGen = struct { |
| 4801 | 4801 | const casted = self.builder.buildBitCast(llvm_arg, self.dg.context.intType(16), ""); |
| 4802 | 4802 | try llvm_args.append(casted); |
| 4803 | 4803 | }, |
| 4804 | .float_array => { | |
| 4804 | .float_array => |count| { | |
| 4805 | 4805 | const arg = args[it.zig_index - 1]; |
| 4806 | 4806 | const arg_ty = self.air.typeOf(arg); |
| 4807 | 4807 | var llvm_arg = try self.resolveInst(arg); |
| ... | ... | @@ -4812,9 +4812,8 @@ pub const FuncGen = struct { |
| 4812 | 4812 | llvm_arg = store_inst; |
| 4813 | 4813 | } |
| 4814 | 4814 | |
| 4815 | const float_ty = try self.dg.lowerType(arg_ty.structFieldType(0)); | |
| 4816 | const field_count = @intCast(u32, arg_ty.structFieldCount()); | |
| 4817 | const array_llvm_ty = float_ty.arrayType(field_count); | |
| 4815 | const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty).?); | |
| 4816 | const array_llvm_ty = float_ty.arrayType(count); | |
| 4818 | 4817 | |
| 4819 | 4818 | const casted = self.builder.buildBitCast(llvm_arg, array_llvm_ty.pointerType(0), ""); |
| 4820 | 4819 | const alignment = arg_ty.abiAlignment(target); |
| ... | ... | @@ -10214,7 +10213,7 @@ const ParamTypeIterator = struct { |
| 10214 | 10213 | llvm_types_buffer: [8]u16, |
| 10215 | 10214 | byval_attr: bool, |
| 10216 | 10215 | |
| 10217 | const Lowering = enum { | |
| 10216 | const Lowering = union(enum) { | |
| 10218 | 10217 | no_bits, |
| 10219 | 10218 | byval, |
| 10220 | 10219 | byref, |
| ... | ... | @@ -10223,7 +10222,7 @@ const ParamTypeIterator = struct { |
| 10223 | 10222 | multiple_llvm_float, |
| 10224 | 10223 | slice, |
| 10225 | 10224 | as_u16, |
| 10226 | float_array, | |
| 10225 | float_array: u8, | |
| 10227 | 10226 | }; |
| 10228 | 10227 | |
| 10229 | 10228 | pub fn next(it: *ParamTypeIterator) ?Lowering { |
| ... | ... | @@ -10400,7 +10399,7 @@ const ParamTypeIterator = struct { |
| 10400 | 10399 | return .byref; |
| 10401 | 10400 | } |
| 10402 | 10401 | if (classes[0] == .float_array) { |
| 10403 | return .float_array; | |
| 10402 | return Lowering{ .float_array = @enumToInt(classes[1]) }; | |
| 10404 | 10403 | } |
| 10405 | 10404 | if (classes[1] == .none) { |
| 10406 | 10405 | it.llvm_types_len = 1; |
src/type.zig+9| ... | ... | @@ -3619,6 +3619,9 @@ pub const Type = extern union { |
| 3619 | 3619 | |
| 3620 | 3620 | .@"struct" => { |
| 3621 | 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 | 3625 | var total: u64 = 0; |
| 3623 | 3626 | for (ty.structFields().values()) |field| { |
| 3624 | 3627 | total += try bitSizeAdvanced(field.ty, target, sema_kit); |
| ... | ... | @@ -3628,6 +3631,9 @@ pub const Type = extern union { |
| 3628 | 3631 | |
| 3629 | 3632 | .tuple, .anon_struct => { |
| 3630 | 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 | 3637 | var total: u64 = 0; |
| 3632 | 3638 | for (ty.tupleFields().types) |field_ty| { |
| 3633 | 3639 | total += try bitSizeAdvanced(field_ty, target, sema_kit); |
| ... | ... | @@ -3643,6 +3649,9 @@ pub const Type = extern union { |
| 3643 | 3649 | |
| 3644 | 3650 | .@"union", .union_safety_tagged, .union_tagged => { |
| 3645 | 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 | 3655 | const union_obj = ty.cast(Payload.Union).?.data; |
| 3647 | 3656 | assert(union_obj.haveFieldTypes()); |
| 3648 | 3657 |
src/value.zig+3| ... | ... | @@ -2632,6 +2632,9 @@ pub const Value = extern union { |
| 2632 | 2632 | .lazy_size, |
| 2633 | 2633 | => return hashInt(ptr_val, hasher, target), |
| 2634 | 2634 | |
| 2635 | // The value is runtime-known and shouldn't affect the hash. | |
| 2636 | .runtime_int => {}, | |
| 2637 | ||
| 2635 | 2638 | else => unreachable, |
| 2636 | 2639 | } |
| 2637 | 2640 | } |
test/behavior.zig+5| ... | ... | @@ -41,6 +41,7 @@ test { |
| 41 | 41 | _ = @import("behavior/bugs/2006.zig"); |
| 42 | 42 | _ = @import("behavior/bugs/2114.zig"); |
| 43 | 43 | _ = @import("behavior/bugs/2346.zig"); |
| 44 | _ = @import("behavior/bugs/2557.zig"); | |
| 44 | 45 | _ = @import("behavior/bugs/2578.zig"); |
| 45 | 46 | _ = @import("behavior/bugs/2692.zig"); |
| 46 | 47 | _ = @import("behavior/bugs/2889.zig"); |
| ... | ... | @@ -87,6 +88,7 @@ test { |
| 87 | 88 | _ = @import("behavior/bugs/12033.zig"); |
| 88 | 89 | _ = @import("behavior/bugs/12430.zig"); |
| 89 | 90 | _ = @import("behavior/bugs/12486.zig"); |
| 91 | _ = @import("behavior/bugs/12488.zig"); | |
| 90 | 92 | _ = @import("behavior/bugs/12551.zig"); |
| 91 | 93 | _ = @import("behavior/bugs/12644.zig"); |
| 92 | 94 | _ = @import("behavior/bugs/12680.zig"); |
| ... | ... | @@ -103,7 +105,10 @@ test { |
| 103 | 105 | _ = @import("behavior/bugs/12972.zig"); |
| 104 | 106 | _ = @import("behavior/bugs/12984.zig"); |
| 105 | 107 | _ = @import("behavior/bugs/13068.zig"); |
| 108 | _ = @import("behavior/bugs/13112.zig"); | |
| 106 | 109 | _ = @import("behavior/bugs/13128.zig"); |
| 110 | _ = @import("behavior/bugs/13164.zig"); | |
| 111 | _ = @import("behavior/bugs/13171.zig"); | |
| 107 | 112 | _ = @import("behavior/byteswap.zig"); |
| 108 | 113 | _ = @import("behavior/byval_arg_var.zig"); |
| 109 | 114 | _ = @import("behavior/call.zig"); |
test/behavior/bugs/12488.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | const expect = @import("std").testing.expect; | |
| 2 | ||
| 3 | const A = struct { | |
| 4 | a: u32, | |
| 5 | }; | |
| 6 | ||
| 7 | fn foo(comptime a: anytype) !void { | |
| 8 | try expect(a[0][0] == @sizeOf(A)); | |
| 9 | } | |
| 10 | ||
| 11 | test { | |
| 12 | try foo(.{[_]usize{@sizeOf(A)}}); | |
| 13 | } |
test/behavior/bugs/13112.zig created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | fn nice(a: u32, b: u32) bool { | |
| 2 | return a == 5 or b == 2 or @panic("oh no"); | |
| 3 | } | |
| 4 | ||
| 5 | test { | |
| 6 | _ = nice(2, 2); | |
| 7 | } |
test/behavior/bugs/13164.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | inline fn setLimits(min: ?u32, max: ?u32) !void { | |
| 5 | if (min != null and max != null) { | |
| 6 | try std.testing.expect(min.? <= max.?); | |
| 7 | } | |
| 8 | } | |
| 9 | ||
| 10 | test { | |
| 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expect = std.testing.expect; | |
| 3 | ||
| 4 | fn BuildType(comptime T: type) type { | |
| 5 | return struct { | |
| 6 | val: union { | |
| 7 | b: T, | |
| 8 | }, | |
| 9 | }; | |
| 10 | } | |
| 11 | ||
| 12 | test { | |
| 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 @@ |
| 1 | test { | |
| 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 | 1414 | } |
| 1415 | 1415 | try expect(a == 2); |
| 1416 | 1416 | } |
| 1417 | ||
| 1418 | test "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 | 218 | try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); |
| 219 | 219 | try expect(@bitSizeOf(struct { |
| 220 | 220 | a: u2, |
| 221 | }) == 2); | |
| 221 | }) == 8); | |
| 222 | 222 | try expect(@bitSizeOf(packed struct { |
| 223 | 223 | a: u2, |
| 224 | 224 | }) == 2); |
| ... | ... | @@ -314,3 +314,27 @@ test "lazy size cast to float" { |
| 314 | 314 | test "bitSizeOf comptime_int" { |
| 315 | 315 | try expect(@bitSizeOf(comptime_int) == 0); |
| 316 | 316 | } |
| 317 | ||
| 318 | test "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 | 20 | |
| 21 | 21 | try doTheTest(); |
| 22 | 22 | } |
| 23 | ||
| 24 | test "@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 | 12 | } |
| 13 | 13 | } |
| 14 | 14 | |
| 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 | |
| 15 | 36 | struct i128 { |
| 16 | 37 | __int128 value; |
| 17 | 38 | }; |
| ... | ... | @@ -19,17 +40,22 @@ struct i128 { |
| 19 | 40 | struct u128 { |
| 20 | 41 | unsigned __int128 value; |
| 21 | 42 | }; |
| 43 | #endif | |
| 22 | 44 | |
| 23 | 45 | void zig_u8(uint8_t); |
| 24 | 46 | void zig_u16(uint16_t); |
| 25 | 47 | void zig_u32(uint32_t); |
| 26 | 48 | void zig_u64(uint64_t); |
| 49 | #ifndef ZIG_NO_I128 | |
| 27 | 50 | void zig_struct_u128(struct u128); |
| 51 | #endif | |
| 28 | 52 | void zig_i8(int8_t); |
| 29 | 53 | void zig_i16(int16_t); |
| 30 | 54 | void zig_i32(int32_t); |
| 31 | 55 | void zig_i64(int64_t); |
| 56 | #ifndef ZIG_NO_I128 | |
| 32 | 57 | void zig_struct_i128(struct i128); |
| 58 | #endif | |
| 33 | 59 | void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); |
| 34 | 60 | |
| 35 | 61 | void zig_f32(float); |
| ... | ... | @@ -95,7 +121,9 @@ void zig_med_struct_mixed(struct MedStructMixed); |
| 95 | 121 | struct MedStructMixed zig_ret_med_struct_mixed(); |
| 96 | 122 | |
| 97 | 123 | void zig_small_packed_struct(uint8_t); |
| 124 | #ifndef ZIG_NO_I128 | |
| 98 | 125 | void zig_big_packed_struct(__int128); |
| 126 | #endif | |
| 99 | 127 | |
| 100 | 128 | struct SplitStructInts { |
| 101 | 129 | uint64_t a; |
| ... | ... | @@ -151,19 +179,26 @@ void run_c_tests(void) { |
| 151 | 179 | zig_u16(0xfffe); |
| 152 | 180 | zig_u32(0xfffffffd); |
| 153 | 181 | zig_u64(0xfffffffffffffffc); |
| 182 | ||
| 183 | #ifndef ZIG_NO_I128 | |
| 154 | 184 | { |
| 155 | 185 | struct u128 s = {0xfffffffffffffffc}; |
| 156 | 186 | zig_struct_u128(s); |
| 157 | 187 | } |
| 188 | #endif | |
| 158 | 189 | |
| 159 | 190 | zig_i8(-1); |
| 160 | 191 | zig_i16(-2); |
| 161 | 192 | zig_i32(-3); |
| 162 | 193 | zig_i64(-4); |
| 194 | ||
| 195 | #ifndef ZIG_NO_I128 | |
| 163 | 196 | { |
| 164 | 197 | struct i128 s = {-6}; |
| 165 | 198 | zig_struct_i128(s); |
| 166 | 199 | } |
| 200 | #endif | |
| 201 | ||
| 167 | 202 | zig_five_integers(12, 34, 56, 78, 90); |
| 168 | 203 | |
| 169 | 204 | zig_f32(12.34f); |
| ... | ... | @@ -175,6 +210,7 @@ void run_c_tests(void) { |
| 175 | 210 | |
| 176 | 211 | zig_bool(true); |
| 177 | 212 | |
| 213 | #ifndef ZIG_NO_COMPLEX | |
| 178 | 214 | // TODO: Resolve https://github.com/ziglang/zig/issues/8465 |
| 179 | 215 | //{ |
| 180 | 216 | // float complex a = 1.25f + I * 2.6f; |
| ... | ... | @@ -211,23 +247,30 @@ void run_c_tests(void) { |
| 211 | 247 | assert_or_panic(creal(z) == 1.5); |
| 212 | 248 | assert_or_panic(cimag(z) == 13.5); |
| 213 | 249 | } |
| 250 | #endif | |
| 214 | 251 | |
| 252 | #if !defined __mips__ && !defined __riscv | |
| 215 | 253 | { |
| 216 | 254 | struct BigStruct s = {1, 2, 3, 4, 5}; |
| 217 | 255 | zig_big_struct(s); |
| 218 | 256 | } |
| 257 | #endif | |
| 219 | 258 | |
| 259 | #if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv | |
| 220 | 260 | { |
| 221 | 261 | struct SmallStructInts s = {1, 2, 3, 4}; |
| 222 | 262 | zig_small_struct_ints(s); |
| 223 | 263 | } |
| 264 | #endif | |
| 224 | 265 | |
| 266 | #ifndef ZIG_NO_I128 | |
| 225 | 267 | { |
| 226 | 268 | __int128 s = 0; |
| 227 | 269 | s |= 1 << 0; |
| 228 | 270 | s |= (__int128)2 << 64; |
| 229 | 271 | zig_big_packed_struct(s); |
| 230 | 272 | } |
| 273 | #endif | |
| 231 | 274 | |
| 232 | 275 | { |
| 233 | 276 | uint8_t s = 0; |
| ... | ... | @@ -238,21 +281,28 @@ void run_c_tests(void) { |
| 238 | 281 | zig_small_packed_struct(s); |
| 239 | 282 | } |
| 240 | 283 | |
| 284 | #if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv | |
| 241 | 285 | { |
| 242 | 286 | struct SplitStructInts s = {1234, 100, 1337}; |
| 243 | 287 | zig_split_struct_ints(s); |
| 244 | 288 | } |
| 289 | #endif | |
| 245 | 290 | |
| 291 | #if !defined __arm__ && !defined __riscv | |
| 246 | 292 | { |
| 247 | 293 | struct MedStructMixed s = {1234, 100.0f, 1337.0f}; |
| 248 | 294 | zig_med_struct_mixed(s); |
| 249 | 295 | } |
| 296 | #endif | |
| 250 | 297 | |
| 298 | #if !defined __i386__ && !defined __arm__ && !defined __mips__ && !defined __riscv | |
| 251 | 299 | { |
| 252 | 300 | struct SplitStructMixed s = {1234, 100, 1337.0f}; |
| 253 | 301 | zig_split_struct_mixed(s); |
| 254 | 302 | } |
| 303 | #endif | |
| 255 | 304 | |
| 305 | #if !defined __mips__ && !defined __riscv | |
| 256 | 306 | { |
| 257 | 307 | struct BigStruct s = {30, 31, 32, 33, 34}; |
| 258 | 308 | struct BigStruct res = zig_big_struct_both(s); |
| ... | ... | @@ -262,25 +312,32 @@ void run_c_tests(void) { |
| 262 | 312 | assert_or_panic(res.d == 23); |
| 263 | 313 | assert_or_panic(res.e == 24); |
| 264 | 314 | } |
| 315 | #endif | |
| 265 | 316 | |
| 317 | #ifndef __riscv | |
| 266 | 318 | { |
| 267 | 319 | struct Rect r1 = {1, 21, 16, 4}; |
| 268 | 320 | struct Rect r2 = {178, 189, 21, 15}; |
| 269 | 321 | zig_multiple_struct_ints(r1, r2); |
| 270 | 322 | } |
| 323 | #endif | |
| 271 | 324 | |
| 325 | #if !defined __mips__ && !defined __riscv | |
| 272 | 326 | { |
| 273 | 327 | struct FloatRect r1 = {1, 21, 16, 4}; |
| 274 | 328 | struct FloatRect r2 = {178, 189, 21, 15}; |
| 275 | 329 | zig_multiple_struct_floats(r1, r2); |
| 276 | 330 | } |
| 331 | #endif | |
| 277 | 332 | |
| 278 | 333 | { |
| 279 | 334 | assert_or_panic(zig_ret_bool() == 1); |
| 280 | 335 | |
| 281 | 336 | assert_or_panic(zig_ret_u8() == 0xff); |
| 282 | 337 | assert_or_panic(zig_ret_u16() == 0xffff); |
| 338 | #ifndef __riscv | |
| 283 | 339 | assert_or_panic(zig_ret_u32() == 0xffffffff); |
| 340 | #endif | |
| 284 | 341 | assert_or_panic(zig_ret_u64() == 0xffffffffffffffff); |
| 285 | 342 | |
| 286 | 343 | assert_or_panic(zig_ret_i8() == -1); |
| ... | ... | @@ -306,9 +363,11 @@ void c_u64(uint64_t x) { |
| 306 | 363 | assert_or_panic(x == 0xfffffffffffffffcULL); |
| 307 | 364 | } |
| 308 | 365 | |
| 366 | #ifndef ZIG_NO_I128 | |
| 309 | 367 | void c_struct_u128(struct u128 x) { |
| 310 | 368 | assert_or_panic(x.value == 0xfffffffffffffffcULL); |
| 311 | 369 | } |
| 370 | #endif | |
| 312 | 371 | |
| 313 | 372 | void c_i8(int8_t x) { |
| 314 | 373 | assert_or_panic(x == -1); |
| ... | ... | @@ -326,9 +385,11 @@ void c_i64(int64_t x) { |
| 326 | 385 | assert_or_panic(x == -4); |
| 327 | 386 | } |
| 328 | 387 | |
| 388 | #ifndef ZIG_NO_I128 | |
| 329 | 389 | void c_struct_i128(struct i128 x) { |
| 330 | 390 | assert_or_panic(x.value == -6); |
| 331 | 391 | } |
| 392 | #endif | |
| 332 | 393 | |
| 333 | 394 | void c_f32(float x) { |
| 334 | 395 | assert_or_panic(x == 12.34f); |
| ... | ... | @@ -495,6 +556,7 @@ void c_small_packed_struct(uint8_t x) { |
| 495 | 556 | assert_or_panic(((x >> 6) & 0x3) == 3); |
| 496 | 557 | } |
| 497 | 558 | |
| 559 | #ifndef ZIG_NO_I128 | |
| 498 | 560 | __int128 c_ret_big_packed_struct() { |
| 499 | 561 | __int128 s = 0; |
| 500 | 562 | s |= 1 << 0; |
| ... | ... | @@ -506,6 +568,7 @@ void c_big_packed_struct(__int128 x) { |
| 506 | 568 | assert_or_panic(((x >> 0) & 0xFFFFFFFFFFFFFFFF) == 1); |
| 507 | 569 | assert_or_panic(((x >> 64) & 0xFFFFFFFFFFFFFFFF) == 2); |
| 508 | 570 | } |
| 571 | #endif | |
| 509 | 572 | |
| 510 | 573 | struct SplitStructMixed c_ret_split_struct_mixed() { |
| 511 | 574 | struct SplitStructMixed s = { |
| ... | ... | @@ -596,3 +659,45 @@ int32_t c_ret_i32() { |
| 596 | 659 | int64_t c_ret_i64() { |
| 597 | 660 | return -1; |
| 598 | 661 | } |
| 662 | ||
| 663 | typedef struct { | |
| 664 | uint32_t a; | |
| 665 | uint8_t padding[4]; | |
| 666 | uint64_t b; | |
| 667 | } StructWithArray; | |
| 668 | ||
| 669 | void c_struct_with_array(StructWithArray x) { | |
| 670 | assert_or_panic(x.a == 1); | |
| 671 | assert_or_panic(x.b == 2); | |
| 672 | } | |
| 673 | ||
| 674 | StructWithArray c_ret_struct_with_array() { | |
| 675 | return (StructWithArray) { 4, {}, 155 }; | |
| 676 | } | |
| 677 | ||
| 678 | typedef 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 | ||
| 689 | void 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 | ||
| 696 | FloatArrayStruct 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 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const print = std.debug.print; |
| 4 | 4 | const expect = std.testing.expect; |
| 5 | const has_i128 = builtin.cpu.arch != .i386 and !builtin.cpu.arch.isARM() and | |
| 6 | !builtin.cpu.arch.isMIPS(); | |
| 5 | 7 | |
| 6 | 8 | extern fn run_c_tests() void; |
| 7 | 9 | |
| ... | ... | @@ -40,13 +42,13 @@ test "C ABI integers" { |
| 40 | 42 | c_u16(0xfffe); |
| 41 | 43 | c_u32(0xfffffffd); |
| 42 | 44 | c_u64(0xfffffffffffffffc); |
| 43 | c_struct_u128(.{ .value = 0xfffffffffffffffc }); | |
| 45 | if (has_i128) c_struct_u128(.{ .value = 0xfffffffffffffffc }); | |
| 44 | 46 | |
| 45 | 47 | c_i8(-1); |
| 46 | 48 | c_i16(-2); |
| 47 | 49 | c_i32(-3); |
| 48 | 50 | c_i64(-4); |
| 49 | c_struct_i128(.{ .value = -6 }); | |
| 51 | if (has_i128) c_struct_i128(.{ .value = -6 }); | |
| 50 | 52 | c_five_integers(12, 34, 56, 78, 90); |
| 51 | 53 | } |
| 52 | 54 | |
| ... | ... | @@ -110,7 +112,6 @@ test "C ABI floats" { |
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | test "C ABI long double" { |
| 113 | if (!builtin.cpu.arch.isWasm() and !builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; | |
| 114 | 115 | c_long_double(12.34); |
| 115 | 116 | } |
| 116 | 117 | |
| ... | ... | @@ -166,8 +167,11 @@ extern fn c_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble; |
| 166 | 167 | extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat; |
| 167 | 168 | extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble; |
| 168 | 169 | |
| 170 | const complex_abi_compatible = builtin.cpu.arch != .i386 and !builtin.cpu.arch.isMIPS(); | |
| 171 | ||
| 169 | 172 | test "C ABI complex float" { |
| 170 | if (true) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465 | |
| 173 | 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 | |
| 171 | 175 | |
| 172 | 176 | const a = ComplexFloat{ .real = 1.25, .imag = 2.6 }; |
| 173 | 177 | const b = ComplexFloat{ .real = 11.3, .imag = -1.5 }; |
| ... | ... | @@ -178,6 +182,8 @@ test "C ABI complex float" { |
| 178 | 182 | } |
| 179 | 183 | |
| 180 | 184 | test "C ABI complex float by component" { |
| 185 | if (!complex_abi_compatible) return error.SkipZigTest; | |
| 186 | ||
| 181 | 187 | const a = ComplexFloat{ .real = 1.25, .imag = 2.6 }; |
| 182 | 188 | const b = ComplexFloat{ .real = 11.3, .imag = -1.5 }; |
| 183 | 189 | |
| ... | ... | @@ -187,6 +193,8 @@ test "C ABI complex float by component" { |
| 187 | 193 | } |
| 188 | 194 | |
| 189 | 195 | test "C ABI complex double" { |
| 196 | if (!complex_abi_compatible) return error.SkipZigTest; | |
| 197 | ||
| 190 | 198 | const a = ComplexDouble{ .real = 1.25, .imag = 2.6 }; |
| 191 | 199 | const b = ComplexDouble{ .real = 11.3, .imag = -1.5 }; |
| 192 | 200 | |
| ... | ... | @@ -196,6 +204,8 @@ test "C ABI complex double" { |
| 196 | 204 | } |
| 197 | 205 | |
| 198 | 206 | test "C ABI complex double by component" { |
| 207 | if (!complex_abi_compatible) return error.SkipZigTest; | |
| 208 | ||
| 199 | 209 | const a = ComplexDouble{ .real = 1.25, .imag = 2.6 }; |
| 200 | 210 | const b = ComplexDouble{ .real = 11.3, .imag = -1.5 }; |
| 201 | 211 | |
| ... | ... | @@ -250,6 +260,9 @@ const BigStruct = extern struct { |
| 250 | 260 | extern fn c_big_struct(BigStruct) void; |
| 251 | 261 | |
| 252 | 262 | test "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 | 266 | var s = BigStruct{ |
| 254 | 267 | .a = 1, |
| 255 | 268 | .b = 2, |
| ... | ... | @@ -274,6 +287,8 @@ const BigUnion = extern union { |
| 274 | 287 | extern fn c_big_union(BigUnion) void; |
| 275 | 288 | |
| 276 | 289 | test "C ABI big union" { |
| 290 | if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest; | |
| 291 | ||
| 277 | 292 | var x = BigUnion{ |
| 278 | 293 | .a = BigStruct{ |
| 279 | 294 | .a = 1, |
| ... | ... | @@ -304,6 +319,11 @@ extern fn c_med_struct_mixed(MedStructMixed) void; |
| 304 | 319 | extern fn c_ret_med_struct_mixed() MedStructMixed; |
| 305 | 320 | |
| 306 | 321 | test "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 | 327 | var s = MedStructMixed{ |
| 308 | 328 | .a = 1234, |
| 309 | 329 | .b = 100.0, |
| ... | ... | @@ -332,6 +352,11 @@ extern fn c_small_struct_ints(SmallStructInts) void; |
| 332 | 352 | extern fn c_ret_small_struct_ints() SmallStructInts; |
| 333 | 353 | |
| 334 | 354 | test "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 | 360 | var s = SmallStructInts{ |
| 336 | 361 | .a = 1, |
| 337 | 362 | .b = 2, |
| ... | ... | @@ -392,6 +417,8 @@ export fn zig_big_packed_struct(x: BigPackedStruct) void { |
| 392 | 417 | } |
| 393 | 418 | |
| 394 | 419 | test "C ABI big packed struct" { |
| 420 | if (!has_i128) return error.SkipZigTest; | |
| 421 | ||
| 395 | 422 | var s = BigPackedStruct{ .a = 1, .b = 2 }; |
| 396 | 423 | c_big_packed_struct(s); |
| 397 | 424 | var s2 = c_ret_big_packed_struct(); |
| ... | ... | @@ -407,6 +434,11 @@ const SplitStructInt = extern struct { |
| 407 | 434 | extern fn c_split_struct_ints(SplitStructInt) void; |
| 408 | 435 | |
| 409 | 436 | test "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 | 442 | var s = SplitStructInt{ |
| 411 | 443 | .a = 1234, |
| 412 | 444 | .b = 100, |
| ... | ... | @@ -430,6 +462,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void; |
| 430 | 462 | extern fn c_ret_split_struct_mixed() SplitStructMixed; |
| 431 | 463 | |
| 432 | 464 | test "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 | 470 | var s = SplitStructMixed{ |
| 434 | 471 | .a = 1234, |
| 435 | 472 | .b = 100, |
| ... | ... | @@ -454,6 +491,9 @@ extern fn c_multiple_struct_ints(Rect, Rect) void; |
| 454 | 491 | extern fn c_multiple_struct_floats(FloatRect, FloatRect) void; |
| 455 | 492 | |
| 456 | 493 | test "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 | 497 | var s = BigStruct{ |
| 458 | 498 | .a = 1, |
| 459 | 499 | .b = 2, |
| ... | ... | @@ -503,6 +543,10 @@ const Vector5 = extern struct { |
| 503 | 543 | extern fn c_big_struct_floats(Vector5) void; |
| 504 | 544 | |
| 505 | 545 | test "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 | 550 | var v3 = Vector3{ |
| 507 | 551 | .x = 3.0, |
| 508 | 552 | .y = 6.0, |
| ... | ... | @@ -540,6 +584,8 @@ export fn zig_multiple_struct_ints(x: Rect, y: Rect) void { |
| 540 | 584 | } |
| 541 | 585 | |
| 542 | 586 | test "C ABI structs of ints as multiple parameters" { |
| 587 | if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest; | |
| 588 | ||
| 543 | 589 | var r1 = Rect{ |
| 544 | 590 | .left = 1, |
| 545 | 591 | .right = 21, |
| ... | ... | @@ -574,6 +620,9 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void { |
| 574 | 620 | } |
| 575 | 621 | |
| 576 | 622 | test "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 | 626 | var r1 = FloatRect{ |
| 578 | 627 | .left = 1, |
| 579 | 628 | .right = 21, |
| ... | ... | @@ -665,3 +714,60 @@ test "C ABI integer return types" { |
| 665 | 714 | try expect(c_ret_i32() == -1); |
| 666 | 715 | try expect(c_ret_i64() == -1); |
| 667 | 716 | } |
| 717 | ||
| 718 | const StructWithArray = extern struct { | |
| 719 | a: i32, | |
| 720 | padding: [4]u8, | |
| 721 | b: i64, | |
| 722 | }; | |
| 723 | extern fn c_struct_with_array(StructWithArray) void; | |
| 724 | extern fn c_ret_struct_with_array() StructWithArray; | |
| 725 | ||
| 726 | test "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 | ||
| 739 | const 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 | ||
| 750 | extern fn c_float_array_struct(FloatArrayStruct) void; | |
| 751 | extern fn c_ret_float_array_struct() FloatArrayStruct; | |
| 752 | ||
| 753 | test "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 @@ |
| 1 | pub fn main() void { | |
| 2 | var x: usize = 3; | |
| 3 | const y = add(10, 2, x); | |
| 4 | if (y - 6 != 0) unreachable; | |
| 5 | } | |
| 6 | ||
| 7 | inline 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 @@ |
| 1 | pub fn main() void { | |
| 2 | var x: usize = 3; | |
| 3 | const y = add(1, 2, x); | |
| 4 | if (y - 6 != 0) unreachable; | |
| 5 | } | |
| 6 | ||
| 7 | inline 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 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:21: error: expected type '?*anyopaque', found '?usize' | |
| 11 | // :3:21: note: optional type child 'usize' cannot cast into optional type child '*anyopaque' | |
| 10 | // :3:9: error: expected type '?*anyopaque', found '?usize' | |
| 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 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:13: error: cannot assign to constant | |
| 10 | // :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 | 7 | // backend=stage2 |
| 8 | 8 | // target=native |
| 9 | 9 | // |
| 10 | // :3:13: error: cannot assign to constant | |
| 10 | // :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 | 10 | // backend=stage2 |
| 11 | 11 | // target=native |
| 12 | 12 | // |
| 13 | // :6:15: error: cannot assign to constant | |
| 13 | // :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 | 75 | // backend=stage2 |
| 76 | 76 | // target=native |
| 77 | 77 | // |
| 78 | // :3:9: error: cannot assign to constant | |
| 78 | // :3:5: error: cannot assign to constant | |
| 79 | 79 | // :7:7: error: cannot assign to constant |
| 80 | 80 | // :11:7: error: cannot assign to constant |
| 81 | 81 | // :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 @@ |
| 1 | export fn entry() void { | |
| 2 | bad(bound_fn() == 1237); | |
| 3 | } | |
| 4 | const SimpleStruct = struct { | |
| 5 | field: i32, | |
| 6 | ||
| 7 | fn method(self: *const SimpleStruct) i32 { | |
| 8 | return self.field + 3; | |
| 9 | } | |
| 10 | }; | |
| 11 | var simple_struct = SimpleStruct{ .field = 1234 }; | |
| 12 | const bound_fn = simple_struct.method; | |
| 13 | fn 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 | 20 | // backend=stage2 |
| 21 | 21 | // target=native |
| 22 | 22 | // |
| 23 | // :12:14: error: cannot assign to constant | |
| 24 | // :16:14: error: cannot assign to constant | |
| 23 | // :12:5: error: cannot assign to constant | |
| 24 | // :16:5: error: cannot assign to constant |
test/cases/compile_errors/callconv_from_global_variable.zig created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | var cc: @import("std").builtin.CallingConvention = .C; | |
| 2 | export 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 | 21 | // backend=stage2 |
| 22 | 22 | // target=native |
| 23 | 23 | // |
| 24 | // :13:27: error: store to comptime variable depends on runtime condition | |
| 24 | // :13:25: error: store to comptime variable depends on runtime condition | |
| 25 | 25 | // :11:16: note: runtime condition here |
test/cases/compile_errors/global_var_struct_init_in_comptim_block.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const Foo = struct { | |
| 2 | x: i32, | |
| 3 | }; | |
| 4 | var x: Foo = .{ .x = 2 }; | |
| 5 | comptime { | |
| 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 | 14 | // backend=llvm |
| 15 | 15 | // target=native |
| 16 | 16 | // |
| 17 | // :2:14: error: cannot load runtime value in comptime block | |
| 17 | // :2:14: error: expected type 'f32', found 'f64' | |
| 18 | 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 | 14 | // backend=stage2 |
| 15 | 15 | // target=native |
| 16 | 16 | // |
| 17 | // :6:26: error: cannot store to runtime value in comptime block | |
| 17 | // :6:24: error: unable to evaluate comptime expression | |
| 18 | // :6:5: note: operation is runtime due to this operand | |
| 18 | 19 | // :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 | 21 | // backend=stage2 |
| 22 | 22 | // target=native |
| 23 | 23 | // |
| 24 | // :3:7: error: cannot load runtime value in comptime block | |
| 24 | // :3:7: error: unable to evaluate comptime expression | |
| 25 | // :3:5: note: operation is runtime due to this operand | |
| 25 | 26 | // :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 | 10 | // backend=stage2 |
| 11 | 11 | // target=native |
| 12 | 12 | // |
| 13 | // :5:25: error: cannot load runtime value in comptime block | |
| 13 | // :5:18: error: unable to resolve comptime value | |
| 14 | // :5:18: note: value being returned at comptime must be comptime-known | |
| 14 | 15 | // :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 | 9 | // backend=llvm |
| 10 | 10 | // target=native |
| 11 | 11 | // |
| 12 | // :2:10: error: cannot assign to constant | |
| 12 | // :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 | 23 | // backend=stage2 |
| 24 | 24 | // target=native |
| 25 | 25 | // |
| 26 | // :3:14: error: cannot assign to constant | |
| 27 | // :7:13: error: cannot assign to constant | |
| 28 | // :11:13: error: cannot assign to constant | |
| 29 | // :19:13: error: cannot assign to constant | |
| 26 | // :3:8: error: cannot assign to constant | |
| 27 | // :7:8: error: cannot assign to constant | |
| 28 | // :11:8: error: cannot assign to constant | |
| 29 | // :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 | 8 | // backend=stage2 |
| 9 | 9 | // target=native |
| 10 | 10 | // |
| 11 | // :3:9: error: cannot assign to constant | |
| 11 | // :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 | 6 | |
| 7 | 7 | // error |
| 8 | 8 | // |
| 9 | // :2:15: error: cannot load runtime value in comptime block | |
| 9 | // :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 @@ |
| 1 | pub fn main() void { | |
| 2 | const y = fibonacci(7); | |
| 3 | if (y - 21 != 0) unreachable; | |
| 4 | } | |
| 5 | ||
| 6 | inline 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"). | |
| 4 | pub fn main() void { | |
| 5 | const y = fibonacci(999); | |
| 6 | if (y - 21 != 0) unreachable; | |
| 7 | } | |
| 8 | ||
| 9 | inline 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 | 8 | // output_mode=Exe |
| 9 | 9 | // target=x86_64-linux |
| 10 | 10 | // |
| 11 | // :4:21: error: store to comptime variable depends on runtime condition | |
| 11 | // :4:19: error: store to comptime variable depends on runtime condition | |
| 12 | 12 | // :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 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :6:21: error: store to comptime variable depends on runtime condition | |
| 12 | // :6:19: error: store to comptime variable depends on runtime condition | |
| 13 | 13 | // :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 | 8 | // output_mode=Exe |
| 9 | 9 | // target=x86_64-macos |
| 10 | 10 | // |
| 11 | // :4:21: error: store to comptime variable depends on runtime condition | |
| 11 | // :4:19: error: store to comptime variable depends on runtime condition | |
| 12 | 12 | // :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 | 9 | |
| 10 | 10 | // error |
| 11 | 11 | // |
| 12 | // :6:21: error: store to comptime variable depends on runtime condition | |
| 12 | // :6:19: error: store to comptime variable depends on runtime condition | |
| 13 | 13 | // :4:13: note: runtime condition here |
test/stage2/cbe.zig+3-2| ... | ... | @@ -51,8 +51,9 @@ pub fn addCases(ctx: *TestContext) !void { |
| 51 | 51 | \\} |
| 52 | 52 | \\var y: @import("std").builtin.CallingConvention = .C; |
| 53 | 53 | , &.{ |
| 54 | ":2:22: error: cannot load runtime value in comptime block", | |
| 55 | ":5:26: error: cannot load runtime value in comptime block", | |
| 54 | ":2:22: error: expected type 'type', found 'i32'", | |
| 55 | ":5:26: error: unable to resolve comptime value", | |
| 56 | ":5:26: note: calling convention must be comptime-known", | |
| 56 | 57 | }); |
| 57 | 58 | } |
| 58 | 59 |