| author | |
| committer | |
| log | 55e7c099caa7cf8dc253dac21765bb994e06b741 |
| tree | 8bca8b4f585bc0beb70e78346d704fbeb2b3eadd |
| parent | d64d5cfc0a72a9989ed58548dd806a663f847ef5 |
10 files changed, 304 insertions(+), 250 deletions(-)
src/AstGen.zig+2-3| ... | @@ -7082,7 +7082,7 @@ fn builtinCall( | ... | @@ -7082,7 +7082,7 @@ fn builtinCall( |
| 7082 | .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), | 7082 | .bit_cast => return bitCast( gz, scope, rl, node, params[0], params[1]), |
| 7083 | .TypeOf => return typeOf( gz, scope, rl, node, params), | 7083 | .TypeOf => return typeOf( gz, scope, rl, node, params), |
| 7084 | .union_init => return unionInit(gz, scope, rl, node, params), | 7084 | .union_init => return unionInit(gz, scope, rl, node, params), |
| 7085 | .c_import => return cImport( gz, scope, rl, node, params[0]), | 7085 | .c_import => return cImport( gz, scope, node, params[0]), |
| 7086 | 7086 | ||
| 7087 | .@"export" => { | 7087 | .@"export" => { |
| 7088 | const node_tags = tree.nodes.items(.tag); | 7088 | const node_tags = tree.nodes.items(.tag); |
| ... | @@ -7692,7 +7692,6 @@ fn shiftOp( | ... | @@ -7692,7 +7692,6 @@ fn shiftOp( |
| 7692 | fn cImport( | 7692 | fn cImport( |
| 7693 | gz: *GenZir, | 7693 | gz: *GenZir, |
| 7694 | scope: *Scope, | 7694 | scope: *Scope, |
| 7695 | rl: ResultLoc, | ||
| 7696 | node: Ast.Node.Index, | 7695 | node: Ast.Node.Index, |
| 7697 | body_node: Ast.Node.Index, | 7696 | body_node: Ast.Node.Index, |
| 7698 | ) InnerError!Zir.Inst.Ref { | 7697 | ) InnerError!Zir.Inst.Ref { |
| ... | @@ -7712,7 +7711,7 @@ fn cImport( | ... | @@ -7712,7 +7711,7 @@ fn cImport( |
| 7712 | try block_scope.setBlockBody(block_inst); | 7711 | try block_scope.setBlockBody(block_inst); |
| 7713 | try gz.instructions.append(gpa, block_inst); | 7712 | try gz.instructions.append(gpa, block_inst); |
| 7714 | 7713 | ||
| 7715 | return rvalue(gz, rl, .void_value, node); | 7714 | return indexToRef(block_inst); |
| 7716 | } | 7715 | } |
| 7717 | 7716 | ||
| 7718 | fn overflowArithmetic( | 7717 | fn overflowArithmetic( |
src/Compilation.zig+1-1| ... | @@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { | ... | @@ -2644,7 +2644,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { |
| 2644 | 2644 | ||
| 2645 | const dep_basename = std.fs.path.basename(out_dep_path); | 2645 | const dep_basename = std.fs.path.basename(out_dep_path); |
| 2646 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); | 2646 | try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 2647 | if (build_options.is_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); | 2647 | if (build_options.is_stage1 and comp.bin_file.options.use_stage1) try comp.stage1_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); |
| 2648 | 2648 | ||
| 2649 | const digest = man.final(); | 2649 | const digest = man.final(); |
| 2650 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); | 2650 | const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest }); |
src/Sema.zig+37-4| ... | @@ -2183,11 +2183,10 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com | ... | @@ -2183,11 +2183,10 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com |
| 2183 | @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len); | 2183 | @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len); |
| 2184 | return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg); | 2184 | return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg); |
| 2185 | } | 2185 | } |
| 2186 | const c_import_pkg = @import("Package.zig").createWithDir( | 2186 | const c_import_pkg = @import("Package.zig").create( |
| 2187 | sema.gpa, | 2187 | sema.gpa, |
| 2188 | sema.mod.comp.local_cache_directory, | ||
| 2189 | null, | 2188 | null, |
| 2190 | std.fs.path.basename(c_import_res.out_zig_path), | 2189 | c_import_res.out_zig_path, |
| 2191 | ) catch |err| switch (err) { | 2190 | ) catch |err| switch (err) { |
| 2192 | error.OutOfMemory => return error.OutOfMemory, | 2191 | error.OutOfMemory => return error.OutOfMemory, |
| 2193 | else => unreachable, // we pass null for root_src_dir_path | 2192 | else => unreachable, // we pass null for root_src_dir_path |
| ... | @@ -2200,6 +2199,9 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com | ... | @@ -2200,6 +2199,9 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com |
| 2200 | const result = sema.mod.importPkg(c_import_pkg) catch |err| | 2199 | const result = sema.mod.importPkg(c_import_pkg) catch |err| |
| 2201 | return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); | 2200 | return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); |
| 2202 | 2201 | ||
| 2202 | sema.mod.astGenFile(result.file) catch |err| | ||
| 2203 | return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); | ||
| 2204 | |||
| 2203 | try sema.mod.semaFile(result.file); | 2205 | try sema.mod.semaFile(result.file); |
| 2204 | const file_root_decl = result.file.root_decl.?; | 2206 | const file_root_decl = result.file.root_decl.?; |
| 2205 | try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl); | 2207 | try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl); |
| ... | @@ -6467,10 +6469,41 @@ fn runtimeBoolCmp( | ... | @@ -6467,10 +6469,41 @@ fn runtimeBoolCmp( |
| 6467 | 6469 | ||
| 6468 | fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6470 | fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 6469 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 6471 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 6472 | const src = inst_data.src(); | ||
| 6470 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 6473 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 6471 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); | 6474 | const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); |
| 6472 | const target = sema.mod.getTarget(); | 6475 | const target = sema.mod.getTarget(); |
| 6473 | const abi_size = operand_ty.abiSize(target); | 6476 | const abi_size = switch (operand_ty.zigTypeTag()) { |
| 6477 | .Fn => unreachable, | ||
| 6478 | .NoReturn, | ||
| 6479 | .Undefined, | ||
| 6480 | .Null, | ||
| 6481 | .BoundFn, | ||
| 6482 | .Opaque, | ||
| 6483 | => return sema.mod.fail(&block.base, src, "no size available for type '{}'", .{operand_ty}), | ||
| 6484 | .Type, | ||
| 6485 | .EnumLiteral, | ||
| 6486 | .ComptimeFloat, | ||
| 6487 | .ComptimeInt, | ||
| 6488 | .Void, | ||
| 6489 | => 0, | ||
| 6490 | |||
| 6491 | .Bool, | ||
| 6492 | .Int, | ||
| 6493 | .Float, | ||
| 6494 | .Pointer, | ||
| 6495 | .Array, | ||
| 6496 | .Struct, | ||
| 6497 | .Optional, | ||
| 6498 | .ErrorUnion, | ||
| 6499 | .ErrorSet, | ||
| 6500 | .Enum, | ||
| 6501 | .Union, | ||
| 6502 | .Vector, | ||
| 6503 | .Frame, | ||
| 6504 | .AnyFrame, | ||
| 6505 | => operand_ty.abiSize(target), | ||
| 6506 | }; | ||
| 6474 | return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size); | 6507 | return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size); |
| 6475 | } | 6508 | } |
| 6476 | 6509 |
src/print_zir.zig+15-3| ... | @@ -407,15 +407,27 @@ const Writer = struct { | ... | @@ -407,15 +407,27 @@ const Writer = struct { |
| 407 | .mul_with_saturation, | 407 | .mul_with_saturation, |
| 408 | .shl_with_saturation, | 408 | .shl_with_saturation, |
| 409 | => try self.writeSaturatingArithmetic(stream, extended), | 409 | => try self.writeSaturatingArithmetic(stream, extended), |
| 410 | |||
| 410 | .struct_decl => try self.writeStructDecl(stream, extended), | 411 | .struct_decl => try self.writeStructDecl(stream, extended), |
| 411 | .union_decl => try self.writeUnionDecl(stream, extended), | 412 | .union_decl => try self.writeUnionDecl(stream, extended), |
| 412 | .enum_decl => try self.writeEnumDecl(stream, extended), | 413 | .enum_decl => try self.writeEnumDecl(stream, extended), |
| 413 | 414 | ||
| 415 | .c_undef, .c_include => { | ||
| 416 | const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; | ||
| 417 | try self.writeInstRef(stream, inst_data.operand); | ||
| 418 | try stream.writeAll(") "); | ||
| 419 | }, | ||
| 420 | |||
| 421 | .c_define => { | ||
| 422 | const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; | ||
| 423 | try self.writeInstRef(stream, inst_data.lhs); | ||
| 424 | try stream.writeAll(", "); | ||
| 425 | try self.writeInstRef(stream, inst_data.rhs); | ||
| 426 | try stream.writeByte(')'); | ||
| 427 | }, | ||
| 428 | |||
| 414 | .alloc, | 429 | .alloc, |
| 415 | .builtin_extern, | 430 | .builtin_extern, |
| 416 | .c_undef, | ||
| 417 | .c_include, | ||
| 418 | .c_define, | ||
| 419 | .wasm_memory_size, | 431 | .wasm_memory_size, |
| 420 | .wasm_memory_grow, | 432 | .wasm_memory_grow, |
| 421 | => try stream.writeAll("TODO))"), | 433 | => try stream.writeAll("TODO))"), |
src/type.zig+1-1| ... | @@ -602,8 +602,8 @@ pub const Type = extern union { | ... | @@ -602,8 +602,8 @@ pub const Type = extern union { |
| 602 | } | 602 | } |
| 603 | return false; | 603 | return false; |
| 604 | }, | 604 | }, |
| 605 | .Float => return a.tag() == b.tag(), | ||
| 605 | .Opaque, | 606 | .Opaque, |
| 606 | .Float, | ||
| 607 | .BoundFn, | 607 | .BoundFn, |
| 608 | .Frame, | 608 | .Frame, |
| 609 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), | 609 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), |
test/behavior.zig+4-2| ... | @@ -11,6 +11,8 @@ test { | ... | @@ -11,6 +11,8 @@ test { |
| 11 | _ = @import("behavior/array.zig"); | 11 | _ = @import("behavior/array.zig"); |
| 12 | _ = @import("behavior/usingnamespace.zig"); | 12 | _ = @import("behavior/usingnamespace.zig"); |
| 13 | _ = @import("behavior/atomics.zig"); | 13 | _ = @import("behavior/atomics.zig"); |
| 14 | _ = @import("behavior/sizeof_and_typeof.zig"); | ||
| 15 | _ = @import("behavior/translate_c_macros.zig"); | ||
| 14 | 16 | ||
| 15 | if (builtin.zig_is_stage2) { | 17 | if (builtin.zig_is_stage2) { |
| 16 | // When all comptime_memory.zig tests pass, #9646 can be closed. | 18 | // When all comptime_memory.zig tests pass, #9646 can be closed. |
| ... | @@ -128,7 +130,7 @@ test { | ... | @@ -128,7 +130,7 @@ test { |
| 128 | _ = @import("behavior/saturating_arithmetic.zig"); | 130 | _ = @import("behavior/saturating_arithmetic.zig"); |
| 129 | _ = @import("behavior/shuffle.zig"); | 131 | _ = @import("behavior/shuffle.zig"); |
| 130 | _ = @import("behavior/select.zig"); | 132 | _ = @import("behavior/select.zig"); |
| 131 | _ = @import("behavior/sizeof_and_typeof.zig"); | 133 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); |
| 132 | _ = @import("behavior/slice.zig"); | 134 | _ = @import("behavior/slice.zig"); |
| 133 | _ = @import("behavior/slice_sentinel_comptime.zig"); | 135 | _ = @import("behavior/slice_sentinel_comptime.zig"); |
| 134 | _ = @import("behavior/struct.zig"); | 136 | _ = @import("behavior/struct.zig"); |
| ... | @@ -157,6 +159,6 @@ test { | ... | @@ -157,6 +159,6 @@ test { |
| 157 | _ = @import("behavior/while.zig"); | 159 | _ = @import("behavior/while.zig"); |
| 158 | _ = @import("behavior/widening.zig"); | 160 | _ = @import("behavior/widening.zig"); |
| 159 | _ = @import("behavior/src.zig"); | 161 | _ = @import("behavior/src.zig"); |
| 160 | _ = @import("behavior/translate_c_macros.zig"); | 162 | _ = @import("behavior/translate_c_macros_stage1.zig"); |
| 161 | } | 163 | } |
| 162 | } | 164 | } |
test/behavior/sizeof_and_typeof.zig-214| ... | @@ -10,118 +10,6 @@ test "@sizeOf and @TypeOf" { | ... | @@ -10,118 +10,6 @@ test "@sizeOf and @TypeOf" { |
| 10 | const x: u16 = 13; | 10 | const x: u16 = 13; |
| 11 | const z: @TypeOf(x) = 19; | 11 | const z: @TypeOf(x) = 19; |
| 12 | 12 | ||
| 13 | const A = struct { | ||
| 14 | a: u8, | ||
| 15 | b: u32, | ||
| 16 | c: u8, | ||
| 17 | d: u3, | ||
| 18 | e: u5, | ||
| 19 | f: u16, | ||
| 20 | g: u16, | ||
| 21 | h: u9, | ||
| 22 | i: u7, | ||
| 23 | }; | ||
| 24 | |||
| 25 | const P = packed struct { | ||
| 26 | a: u8, | ||
| 27 | b: u32, | ||
| 28 | c: u8, | ||
| 29 | d: u3, | ||
| 30 | e: u5, | ||
| 31 | f: u16, | ||
| 32 | g: u16, | ||
| 33 | h: u9, | ||
| 34 | i: u7, | ||
| 35 | }; | ||
| 36 | |||
| 37 | test "@offsetOf" { | ||
| 38 | // Packed structs have fixed memory layout | ||
| 39 | try expect(@offsetOf(P, "a") == 0); | ||
| 40 | try expect(@offsetOf(P, "b") == 1); | ||
| 41 | try expect(@offsetOf(P, "c") == 5); | ||
| 42 | try expect(@offsetOf(P, "d") == 6); | ||
| 43 | try expect(@offsetOf(P, "e") == 6); | ||
| 44 | try expect(@offsetOf(P, "f") == 7); | ||
| 45 | try expect(@offsetOf(P, "g") == 9); | ||
| 46 | try expect(@offsetOf(P, "h") == 11); | ||
| 47 | try expect(@offsetOf(P, "i") == 12); | ||
| 48 | |||
| 49 | // Normal struct fields can be moved/padded | ||
| 50 | var a: A = undefined; | ||
| 51 | try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a")); | ||
| 52 | try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b")); | ||
| 53 | try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c")); | ||
| 54 | try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d")); | ||
| 55 | try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e")); | ||
| 56 | try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f")); | ||
| 57 | try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g")); | ||
| 58 | try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h")); | ||
| 59 | try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i")); | ||
| 60 | } | ||
| 61 | |||
| 62 | test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" { | ||
| 63 | const p3a_len = 3; | ||
| 64 | const P3 = packed struct { | ||
| 65 | a: [p3a_len]u8, | ||
| 66 | b: usize, | ||
| 67 | }; | ||
| 68 | try std.testing.expectEqual(0, @offsetOf(P3, "a")); | ||
| 69 | try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b")); | ||
| 70 | |||
| 71 | const p5a_len = 5; | ||
| 72 | const P5 = packed struct { | ||
| 73 | a: [p5a_len]u8, | ||
| 74 | b: usize, | ||
| 75 | }; | ||
| 76 | try std.testing.expectEqual(0, @offsetOf(P5, "a")); | ||
| 77 | try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b")); | ||
| 78 | |||
| 79 | const p6a_len = 6; | ||
| 80 | const P6 = packed struct { | ||
| 81 | a: [p6a_len]u8, | ||
| 82 | b: usize, | ||
| 83 | }; | ||
| 84 | try std.testing.expectEqual(0, @offsetOf(P6, "a")); | ||
| 85 | try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b")); | ||
| 86 | |||
| 87 | const p7a_len = 7; | ||
| 88 | const P7 = packed struct { | ||
| 89 | a: [p7a_len]u8, | ||
| 90 | b: usize, | ||
| 91 | }; | ||
| 92 | try std.testing.expectEqual(0, @offsetOf(P7, "a")); | ||
| 93 | try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b")); | ||
| 94 | |||
| 95 | const p9a_len = 9; | ||
| 96 | const P9 = packed struct { | ||
| 97 | a: [p9a_len]u8, | ||
| 98 | b: usize, | ||
| 99 | }; | ||
| 100 | try std.testing.expectEqual(0, @offsetOf(P9, "a")); | ||
| 101 | try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b")); | ||
| 102 | |||
| 103 | // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases | ||
| 104 | } | ||
| 105 | |||
| 106 | test "@bitOffsetOf" { | ||
| 107 | // Packed structs have fixed memory layout | ||
| 108 | try expect(@bitOffsetOf(P, "a") == 0); | ||
| 109 | try expect(@bitOffsetOf(P, "b") == 8); | ||
| 110 | try expect(@bitOffsetOf(P, "c") == 40); | ||
| 111 | try expect(@bitOffsetOf(P, "d") == 48); | ||
| 112 | try expect(@bitOffsetOf(P, "e") == 51); | ||
| 113 | try expect(@bitOffsetOf(P, "f") == 56); | ||
| 114 | try expect(@bitOffsetOf(P, "g") == 72); | ||
| 115 | |||
| 116 | try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | ||
| 117 | try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | ||
| 118 | try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | ||
| 119 | try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | ||
| 120 | try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | ||
| 121 | try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | ||
| 122 | try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | ||
| 123 | } | ||
| 124 | |||
| 125 | test "@sizeOf on compile-time types" { | 13 | test "@sizeOf on compile-time types" { |
| 126 | try expect(@sizeOf(comptime_int) == 0); | 14 | try expect(@sizeOf(comptime_int) == 0); |
| 127 | try expect(@sizeOf(comptime_float) == 0); | 15 | try expect(@sizeOf(comptime_float) == 0); |
| ... | @@ -129,34 +17,6 @@ test "@sizeOf on compile-time types" { | ... | @@ -129,34 +17,6 @@ test "@sizeOf on compile-time types" { |
| 129 | try expect(@sizeOf(@TypeOf(type)) == 0); | 17 | try expect(@sizeOf(@TypeOf(type)) == 0); |
| 130 | } | 18 | } |
| 131 | 19 | ||
| 132 | test "@sizeOf(T) == 0 doesn't force resolving struct size" { | ||
| 133 | const S = struct { | ||
| 134 | const Foo = struct { | ||
| 135 | y: if (@sizeOf(Foo) == 0) u64 else u32, | ||
| 136 | }; | ||
| 137 | const Bar = struct { | ||
| 138 | x: i32, | ||
| 139 | y: if (0 == @sizeOf(Bar)) u64 else u32, | ||
| 140 | }; | ||
| 141 | }; | ||
| 142 | |||
| 143 | try expect(@sizeOf(S.Foo) == 4); | ||
| 144 | try expect(@sizeOf(S.Bar) == 8); | ||
| 145 | } | ||
| 146 | |||
| 147 | test "@TypeOf() has no runtime side effects" { | ||
| 148 | const S = struct { | ||
| 149 | fn foo(comptime T: type, ptr: *T) T { | ||
| 150 | ptr.* += 1; | ||
| 151 | return ptr.*; | ||
| 152 | } | ||
| 153 | }; | ||
| 154 | var data: i32 = 0; | ||
| 155 | const T = @TypeOf(S.foo(i32, &data)); | ||
| 156 | comptime try expect(T == i32); | ||
| 157 | try expect(data == 0); | ||
| 158 | } | ||
| 159 | |||
| 160 | test "@TypeOf() with multiple arguments" { | 20 | test "@TypeOf() with multiple arguments" { |
| 161 | { | 21 | { |
| 162 | var var_1: u32 = undefined; | 22 | var var_1: u32 = undefined; |
| ... | @@ -180,19 +40,6 @@ test "@TypeOf() with multiple arguments" { | ... | @@ -180,19 +40,6 @@ test "@TypeOf() with multiple arguments" { |
| 180 | } | 40 | } |
| 181 | } | 41 | } |
| 182 | 42 | ||
| 183 | test "branching logic inside @TypeOf" { | ||
| 184 | const S = struct { | ||
| 185 | var data: i32 = 0; | ||
| 186 | fn foo() anyerror!i32 { | ||
| 187 | data += 1; | ||
| 188 | return undefined; | ||
| 189 | } | ||
| 190 | }; | ||
| 191 | const T = @TypeOf(S.foo() catch undefined); | ||
| 192 | comptime try expect(T == i32); | ||
| 193 | try expect(S.data == 0); | ||
| 194 | } | ||
| 195 | |||
| 196 | fn fn1(alpha: bool) void { | 43 | fn fn1(alpha: bool) void { |
| 197 | const n: usize = 7; | 44 | const n: usize = 7; |
| 198 | _ = if (alpha) n else @sizeOf(usize); | 45 | _ = if (alpha) n else @sizeOf(usize); |
| ... | @@ -201,64 +48,3 @@ fn fn1(alpha: bool) void { | ... | @@ -201,64 +48,3 @@ fn fn1(alpha: bool) void { |
| 201 | test "lazy @sizeOf result is checked for definedness" { | 48 | test "lazy @sizeOf result is checked for definedness" { |
| 202 | _ = fn1; | 49 | _ = fn1; |
| 203 | } | 50 | } |
| 204 | |||
| 205 | test "@bitSizeOf" { | ||
| 206 | try expect(@bitSizeOf(u2) == 2); | ||
| 207 | try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); | ||
| 208 | try expect(@bitSizeOf(struct { | ||
| 209 | a: u2, | ||
| 210 | }) == 8); | ||
| 211 | try expect(@bitSizeOf(packed struct { | ||
| 212 | a: u2, | ||
| 213 | }) == 2); | ||
| 214 | } | ||
| 215 | |||
| 216 | test "@sizeOf comparison against zero" { | ||
| 217 | const S0 = struct { | ||
| 218 | f: *@This(), | ||
| 219 | }; | ||
| 220 | const U0 = union { | ||
| 221 | f: *@This(), | ||
| 222 | }; | ||
| 223 | const S1 = struct { | ||
| 224 | fn H(comptime T: type) type { | ||
| 225 | return struct { | ||
| 226 | x: T, | ||
| 227 | }; | ||
| 228 | } | ||
| 229 | f0: H(*@This()), | ||
| 230 | f1: H(**@This()), | ||
| 231 | f2: H(***@This()), | ||
| 232 | }; | ||
| 233 | const U1 = union { | ||
| 234 | fn H(comptime T: type) type { | ||
| 235 | return struct { | ||
| 236 | x: T, | ||
| 237 | }; | ||
| 238 | } | ||
| 239 | f0: H(*@This()), | ||
| 240 | f1: H(**@This()), | ||
| 241 | f2: H(***@This()), | ||
| 242 | }; | ||
| 243 | const S = struct { | ||
| 244 | fn doTheTest(comptime T: type, comptime result: bool) !void { | ||
| 245 | try expectEqual(result, @sizeOf(T) > 0); | ||
| 246 | } | ||
| 247 | }; | ||
| 248 | // Zero-sized type | ||
| 249 | try S.doTheTest(u0, false); | ||
| 250 | try S.doTheTest(*u0, false); | ||
| 251 | // Non byte-sized type | ||
| 252 | try S.doTheTest(u1, true); | ||
| 253 | try S.doTheTest(*u1, true); | ||
| 254 | // Regular type | ||
| 255 | try S.doTheTest(u8, true); | ||
| 256 | try S.doTheTest(*u8, true); | ||
| 257 | try S.doTheTest(f32, true); | ||
| 258 | try S.doTheTest(*f32, true); | ||
| 259 | // Container with ptr pointing to themselves | ||
| 260 | try S.doTheTest(S0, true); | ||
| 261 | try S.doTheTest(U0, true); | ||
| 262 | try S.doTheTest(S1, true); | ||
| 263 | try S.doTheTest(U1, true); | ||
| 264 | } |
test/behavior/sizeof_and_typeof_stage1.zig created+218| ... | @@ -0,0 +1,218 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = std.builtin; | ||
| 3 | const expect = std.testing.expect; | ||
| 4 | const expectEqual = std.testing.expectEqual; | ||
| 5 | |||
| 6 | const A = struct { | ||
| 7 | a: u8, | ||
| 8 | b: u32, | ||
| 9 | c: u8, | ||
| 10 | d: u3, | ||
| 11 | e: u5, | ||
| 12 | f: u16, | ||
| 13 | g: u16, | ||
| 14 | h: u9, | ||
| 15 | i: u7, | ||
| 16 | }; | ||
| 17 | |||
| 18 | const P = packed struct { | ||
| 19 | a: u8, | ||
| 20 | b: u32, | ||
| 21 | c: u8, | ||
| 22 | d: u3, | ||
| 23 | e: u5, | ||
| 24 | f: u16, | ||
| 25 | g: u16, | ||
| 26 | h: u9, | ||
| 27 | i: u7, | ||
| 28 | }; | ||
| 29 | |||
| 30 | test "@offsetOf" { | ||
| 31 | // Packed structs have fixed memory layout | ||
| 32 | try expect(@offsetOf(P, "a") == 0); | ||
| 33 | try expect(@offsetOf(P, "b") == 1); | ||
| 34 | try expect(@offsetOf(P, "c") == 5); | ||
| 35 | try expect(@offsetOf(P, "d") == 6); | ||
| 36 | try expect(@offsetOf(P, "e") == 6); | ||
| 37 | try expect(@offsetOf(P, "f") == 7); | ||
| 38 | try expect(@offsetOf(P, "g") == 9); | ||
| 39 | try expect(@offsetOf(P, "h") == 11); | ||
| 40 | try expect(@offsetOf(P, "i") == 12); | ||
| 41 | |||
| 42 | // Normal struct fields can be moved/padded | ||
| 43 | var a: A = undefined; | ||
| 44 | try expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @offsetOf(A, "a")); | ||
| 45 | try expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @offsetOf(A, "b")); | ||
| 46 | try expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @offsetOf(A, "c")); | ||
| 47 | try expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @offsetOf(A, "d")); | ||
| 48 | try expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @offsetOf(A, "e")); | ||
| 49 | try expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @offsetOf(A, "f")); | ||
| 50 | try expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @offsetOf(A, "g")); | ||
| 51 | try expect(@ptrToInt(&a.h) - @ptrToInt(&a) == @offsetOf(A, "h")); | ||
| 52 | try expect(@ptrToInt(&a.i) - @ptrToInt(&a) == @offsetOf(A, "i")); | ||
| 53 | } | ||
| 54 | |||
| 55 | test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" { | ||
| 56 | const p3a_len = 3; | ||
| 57 | const P3 = packed struct { | ||
| 58 | a: [p3a_len]u8, | ||
| 59 | b: usize, | ||
| 60 | }; | ||
| 61 | try std.testing.expectEqual(0, @offsetOf(P3, "a")); | ||
| 62 | try std.testing.expectEqual(p3a_len, @offsetOf(P3, "b")); | ||
| 63 | |||
| 64 | const p5a_len = 5; | ||
| 65 | const P5 = packed struct { | ||
| 66 | a: [p5a_len]u8, | ||
| 67 | b: usize, | ||
| 68 | }; | ||
| 69 | try std.testing.expectEqual(0, @offsetOf(P5, "a")); | ||
| 70 | try std.testing.expectEqual(p5a_len, @offsetOf(P5, "b")); | ||
| 71 | |||
| 72 | const p6a_len = 6; | ||
| 73 | const P6 = packed struct { | ||
| 74 | a: [p6a_len]u8, | ||
| 75 | b: usize, | ||
| 76 | }; | ||
| 77 | try std.testing.expectEqual(0, @offsetOf(P6, "a")); | ||
| 78 | try std.testing.expectEqual(p6a_len, @offsetOf(P6, "b")); | ||
| 79 | |||
| 80 | const p7a_len = 7; | ||
| 81 | const P7 = packed struct { | ||
| 82 | a: [p7a_len]u8, | ||
| 83 | b: usize, | ||
| 84 | }; | ||
| 85 | try std.testing.expectEqual(0, @offsetOf(P7, "a")); | ||
| 86 | try std.testing.expectEqual(p7a_len, @offsetOf(P7, "b")); | ||
| 87 | |||
| 88 | const p9a_len = 9; | ||
| 89 | const P9 = packed struct { | ||
| 90 | a: [p9a_len]u8, | ||
| 91 | b: usize, | ||
| 92 | }; | ||
| 93 | try std.testing.expectEqual(0, @offsetOf(P9, "a")); | ||
| 94 | try std.testing.expectEqual(p9a_len, @offsetOf(P9, "b")); | ||
| 95 | |||
| 96 | // 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 25 etc. are further cases | ||
| 97 | } | ||
| 98 | |||
| 99 | test "@bitOffsetOf" { | ||
| 100 | // Packed structs have fixed memory layout | ||
| 101 | try expect(@bitOffsetOf(P, "a") == 0); | ||
| 102 | try expect(@bitOffsetOf(P, "b") == 8); | ||
| 103 | try expect(@bitOffsetOf(P, "c") == 40); | ||
| 104 | try expect(@bitOffsetOf(P, "d") == 48); | ||
| 105 | try expect(@bitOffsetOf(P, "e") == 51); | ||
| 106 | try expect(@bitOffsetOf(P, "f") == 56); | ||
| 107 | try expect(@bitOffsetOf(P, "g") == 72); | ||
| 108 | |||
| 109 | try expect(@offsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | ||
| 110 | try expect(@offsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | ||
| 111 | try expect(@offsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | ||
| 112 | try expect(@offsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | ||
| 113 | try expect(@offsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | ||
| 114 | try expect(@offsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | ||
| 115 | try expect(@offsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | ||
| 116 | } | ||
| 117 | |||
| 118 | test "@sizeOf(T) == 0 doesn't force resolving struct size" { | ||
| 119 | const S = struct { | ||
| 120 | const Foo = struct { | ||
| 121 | y: if (@sizeOf(Foo) == 0) u64 else u32, | ||
| 122 | }; | ||
| 123 | const Bar = struct { | ||
| 124 | x: i32, | ||
| 125 | y: if (0 == @sizeOf(Bar)) u64 else u32, | ||
| 126 | }; | ||
| 127 | }; | ||
| 128 | |||
| 129 | try expect(@sizeOf(S.Foo) == 4); | ||
| 130 | try expect(@sizeOf(S.Bar) == 8); | ||
| 131 | } | ||
| 132 | |||
| 133 | test "@TypeOf() has no runtime side effects" { | ||
| 134 | const S = struct { | ||
| 135 | fn foo(comptime T: type, ptr: *T) T { | ||
| 136 | ptr.* += 1; | ||
| 137 | return ptr.*; | ||
| 138 | } | ||
| 139 | }; | ||
| 140 | var data: i32 = 0; | ||
| 141 | const T = @TypeOf(S.foo(i32, &data)); | ||
| 142 | comptime try expect(T == i32); | ||
| 143 | try expect(data == 0); | ||
| 144 | } | ||
| 145 | |||
| 146 | test "branching logic inside @TypeOf" { | ||
| 147 | const S = struct { | ||
| 148 | var data: i32 = 0; | ||
| 149 | fn foo() anyerror!i32 { | ||
| 150 | data += 1; | ||
| 151 | return undefined; | ||
| 152 | } | ||
| 153 | }; | ||
| 154 | const T = @TypeOf(S.foo() catch undefined); | ||
| 155 | comptime try expect(T == i32); | ||
| 156 | try expect(S.data == 0); | ||
| 157 | } | ||
| 158 | |||
| 159 | test "@bitSizeOf" { | ||
| 160 | try expect(@bitSizeOf(u2) == 2); | ||
| 161 | try expect(@bitSizeOf(u8) == @sizeOf(u8) * 8); | ||
| 162 | try expect(@bitSizeOf(struct { | ||
| 163 | a: u2, | ||
| 164 | }) == 8); | ||
| 165 | try expect(@bitSizeOf(packed struct { | ||
| 166 | a: u2, | ||
| 167 | }) == 2); | ||
| 168 | } | ||
| 169 | |||
| 170 | test "@sizeOf comparison against zero" { | ||
| 171 | const S0 = struct { | ||
| 172 | f: *@This(), | ||
| 173 | }; | ||
| 174 | const U0 = union { | ||
| 175 | f: *@This(), | ||
| 176 | }; | ||
| 177 | const S1 = struct { | ||
| 178 | fn H(comptime T: type) type { | ||
| 179 | return struct { | ||
| 180 | x: T, | ||
| 181 | }; | ||
| 182 | } | ||
| 183 | f0: H(*@This()), | ||
| 184 | f1: H(**@This()), | ||
| 185 | f2: H(***@This()), | ||
| 186 | }; | ||
| 187 | const U1 = union { | ||
| 188 | fn H(comptime T: type) type { | ||
| 189 | return struct { | ||
| 190 | x: T, | ||
| 191 | }; | ||
| 192 | } | ||
| 193 | f0: H(*@This()), | ||
| 194 | f1: H(**@This()), | ||
| 195 | f2: H(***@This()), | ||
| 196 | }; | ||
| 197 | const S = struct { | ||
| 198 | fn doTheTest(comptime T: type, comptime result: bool) !void { | ||
| 199 | try expectEqual(result, @sizeOf(T) > 0); | ||
| 200 | } | ||
| 201 | }; | ||
| 202 | // Zero-sized type | ||
| 203 | try S.doTheTest(u0, false); | ||
| 204 | try S.doTheTest(*u0, false); | ||
| 205 | // Non byte-sized type | ||
| 206 | try S.doTheTest(u1, true); | ||
| 207 | try S.doTheTest(*u1, true); | ||
| 208 | // Regular type | ||
| 209 | try S.doTheTest(u8, true); | ||
| 210 | try S.doTheTest(*u8, true); | ||
| 211 | try S.doTheTest(f32, true); | ||
| 212 | try S.doTheTest(*f32, true); | ||
| 213 | // Container with ptr pointing to themselves | ||
| 214 | try S.doTheTest(S0, true); | ||
| 215 | try S.doTheTest(U0, true); | ||
| 216 | try S.doTheTest(S1, true); | ||
| 217 | try S.doTheTest(U1, true); | ||
| 218 | } | ||
test/behavior/translate_c_macros.zig-22| ... | @@ -3,28 +3,6 @@ const expectEqual = @import("std").testing.expectEqual; | ... | @@ -3,28 +3,6 @@ const expectEqual = @import("std").testing.expectEqual; |
| 3 | 3 | ||
| 4 | const h = @cImport(@cInclude("behavior/translate_c_macros.h")); | 4 | const h = @cImport(@cInclude("behavior/translate_c_macros.h")); |
| 5 | 5 | ||
| 6 | test "initializer list expression" { | ||
| 7 | try expectEqual(h.Color{ | ||
| 8 | .r = 200, | ||
| 9 | .g = 200, | ||
| 10 | .b = 200, | ||
| 11 | .a = 255, | ||
| 12 | }, h.LIGHTGRAY); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "sizeof in macros" { | ||
| 16 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32)); | ||
| 17 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32)); | ||
| 18 | } | ||
| 19 | |||
| 20 | test "reference to a struct type" { | ||
| 21 | try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "cast negative integer to pointer" { | ||
| 25 | try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED); | ||
| 26 | } | ||
| 27 | |||
| 28 | test "casting to void with a macro" { | 6 | test "casting to void with a macro" { |
| 29 | h.IGNORE_ME_1(42); | 7 | h.IGNORE_ME_1(42); |
| 30 | h.IGNORE_ME_2(42); | 8 | h.IGNORE_ME_2(42); |
test/behavior/translate_c_macros_stage1.zig created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const expectEqual = @import("std").testing.expectEqual; | ||
| 3 | |||
| 4 | const h = @cImport(@cInclude("behavior/translate_c_macros.h")); | ||
| 5 | |||
| 6 | test "initializer list expression" { | ||
| 7 | try expectEqual(h.Color{ | ||
| 8 | .r = 200, | ||
| 9 | .g = 200, | ||
| 10 | .b = 200, | ||
| 11 | .a = 255, | ||
| 12 | }, h.LIGHTGRAY); | ||
| 13 | } | ||
| 14 | |||
| 15 | test "sizeof in macros" { | ||
| 16 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32)); | ||
| 17 | try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32)); | ||
| 18 | } | ||
| 19 | |||
| 20 | test "reference to a struct type" { | ||
| 21 | try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO); | ||
| 22 | } | ||
| 23 | |||
| 24 | test "cast negative integer to pointer" { | ||
| 25 | try expectEqual(@intToPtr(?*c_void, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED); | ||
| 26 | } | ||