| author | |
| committer | |
| log | 7b8cb881df7e034a8626caabf355055ee81a0fef |
| tree | e56858cd22ccf90217a49c51c7d8ff7df49ab0f3 |
| parent | f9798108f8434f277de6089502446f2544ee98b3 |
* There is now a main_pkg in addition to root_pkg. They are usually the
same. When using `zig test`, main_pkg is the user's source file and
root_pkg has the test runner.
* scanDecl no longer looks for test decls outside the package being
tested. honoring `--test-filter` is still TODO.
* test runner main function has a void return value rather than
`anyerror!void`
* Sema is improved to generate better AIR for for loops on slices.
* Sema: fix incorrect capacity calculation in zirBoolBr
* Sema: add compile errors for trying to use slice fields as an lvalue.
* Sema: fix type coercion for error unions
* Sema: fix analyzeVarRef generating garbage AIR
* C codegen: fix renderValue for error unions with 0 bit payload
* C codegen: implement function pointer calls
* CLI: fix usage text
Adds 4 new AIR instructions:
* slice_len, slice_ptr: to get the ptr and len fields of a slice.
* slice_elem_val, ptr_slice_elem_val: to get the element value of
a slice, and a pointer to a slice.
AstGen gains a new functionality:
* One of the unused flags of struct decls is now used to indicate
structs that are known to have non-zero size based on the AST alone.25 files changed, 610 insertions(+), 173 deletions(-)
lib/std/special/test_runner.zig+2-2| ... | @@ -21,9 +21,9 @@ fn processArgs() void { | ... | @@ -21,9 +21,9 @@ fn processArgs() void { |
| 21 | std.testing.zig_exe_path = args[1]; | 21 | std.testing.zig_exe_path = args[1]; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | pub fn main() anyerror!void { | 24 | pub fn main() void { |
| 25 | if (builtin.zig_is_stage2) { | 25 | if (builtin.zig_is_stage2) { |
| 26 | return main2(); | 26 | return main2() catch @panic("test failure"); |
| 27 | } | 27 | } |
| 28 | processArgs(); | 28 | processArgs(); |
| 29 | const test_fn_list = builtin.test_functions; | 29 | const test_fn_list = builtin.test_functions; |
src/Air.zig+29-1| ... | @@ -247,6 +247,21 @@ pub const Inst = struct { | ... | @@ -247,6 +247,21 @@ pub const Inst = struct { |
| 247 | /// Given a pointer to a struct and a field index, returns a pointer to the field. | 247 | /// Given a pointer to a struct and a field index, returns a pointer to the field. |
| 248 | /// Uses the `ty_pl` field, payload is `StructField`. | 248 | /// Uses the `ty_pl` field, payload is `StructField`. |
| 249 | struct_field_ptr, | 249 | struct_field_ptr, |
| 250 | /// Given a slice value, return the length. | ||
| 251 | /// Result type is always usize. | ||
| 252 | /// Uses the `ty_op` field. | ||
| 253 | slice_len, | ||
| 254 | /// Given a slice value, return the pointer. | ||
| 255 | /// Uses the `ty_op` field. | ||
| 256 | slice_ptr, | ||
| 257 | /// Given a slice value, and element index, return the element value at that index. | ||
| 258 | /// Result type is the element type of the slice operand. | ||
| 259 | /// Uses the `bin_op` field. | ||
| 260 | slice_elem_val, | ||
| 261 | /// Given a pointer to a slice, and element index, return the element value at that index. | ||
| 262 | /// Result type is the element type of the slice operand (2 element type operations). | ||
| 263 | /// Uses the `bin_op` field. | ||
| 264 | ptr_slice_elem_val, | ||
| 250 | 265 | ||
| 251 | pub fn fromCmpOp(op: std.math.CompareOperator) Tag { | 266 | pub fn fromCmpOp(op: std.math.CompareOperator) Tag { |
| 252 | return switch (op) { | 267 | return switch (op) { |
| ... | @@ -450,6 +465,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -450,6 +465,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 450 | .unwrap_errunion_err_ptr, | 465 | .unwrap_errunion_err_ptr, |
| 451 | .wrap_errunion_payload, | 466 | .wrap_errunion_payload, |
| 452 | .wrap_errunion_err, | 467 | .wrap_errunion_err, |
| 468 | .slice_ptr, | ||
| 453 | => return air.getRefType(datas[inst].ty_op.ty), | 469 | => return air.getRefType(datas[inst].ty_op.ty), |
| 454 | 470 | ||
| 455 | .loop, | 471 | .loop, |
| ... | @@ -465,12 +481,24 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -465,12 +481,24 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 465 | .store, | 481 | .store, |
| 466 | => return Type.initTag(.void), | 482 | => return Type.initTag(.void), |
| 467 | 483 | ||
| 468 | .ptrtoint => return Type.initTag(.usize), | 484 | .ptrtoint, |
| 485 | .slice_len, | ||
| 486 | => return Type.initTag(.usize), | ||
| 469 | 487 | ||
| 470 | .call => { | 488 | .call => { |
| 471 | const callee_ty = air.typeOf(datas[inst].pl_op.operand); | 489 | const callee_ty = air.typeOf(datas[inst].pl_op.operand); |
| 472 | return callee_ty.fnReturnType(); | 490 | return callee_ty.fnReturnType(); |
| 473 | }, | 491 | }, |
| 492 | |||
| 493 | .slice_elem_val => { | ||
| 494 | const slice_ty = air.typeOf(datas[inst].bin_op.lhs); | ||
| 495 | return slice_ty.elemType(); | ||
| 496 | }, | ||
| 497 | .ptr_slice_elem_val => { | ||
| 498 | const ptr_slice_ty = air.typeOf(datas[inst].bin_op.lhs); | ||
| 499 | const slice_ty = ptr_slice_ty.elemType(); | ||
| 500 | return slice_ty.elemType(); | ||
| 501 | }, | ||
| 474 | } | 502 | } |
| 475 | } | 503 | } |
| 476 | 504 |
src/AstGen.zig+190| ... | @@ -3470,6 +3470,7 @@ fn structDeclInner( | ... | @@ -3470,6 +3470,7 @@ fn structDeclInner( |
| 3470 | .fields_len = 0, | 3470 | .fields_len = 0, |
| 3471 | .body_len = 0, | 3471 | .body_len = 0, |
| 3472 | .decls_len = 0, | 3472 | .decls_len = 0, |
| 3473 | .known_has_bits = false, | ||
| 3473 | }); | 3474 | }); |
| 3474 | return indexToRef(decl_inst); | 3475 | return indexToRef(decl_inst); |
| 3475 | } | 3476 | } |
| ... | @@ -3510,6 +3511,7 @@ fn structDeclInner( | ... | @@ -3510,6 +3511,7 @@ fn structDeclInner( |
| 3510 | var bit_bag = ArrayListUnmanaged(u32){}; | 3511 | var bit_bag = ArrayListUnmanaged(u32){}; |
| 3511 | defer bit_bag.deinit(gpa); | 3512 | defer bit_bag.deinit(gpa); |
| 3512 | 3513 | ||
| 3514 | var known_has_bits = false; | ||
| 3513 | var cur_bit_bag: u32 = 0; | 3515 | var cur_bit_bag: u32 = 0; |
| 3514 | var field_index: usize = 0; | 3516 | var field_index: usize = 0; |
| 3515 | for (container_decl.ast.members) |member_node| { | 3517 | for (container_decl.ast.members) |member_node| { |
| ... | @@ -3657,6 +3659,8 @@ fn structDeclInner( | ... | @@ -3657,6 +3659,8 @@ fn structDeclInner( |
| 3657 | try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr); | 3659 | try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr); |
| 3658 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); | 3660 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 3659 | 3661 | ||
| 3662 | known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); | ||
| 3663 | |||
| 3660 | const have_align = member.ast.align_expr != 0; | 3664 | const have_align = member.ast.align_expr != 0; |
| 3661 | const have_value = member.ast.value_expr != 0; | 3665 | const have_value = member.ast.value_expr != 0; |
| 3662 | const is_comptime = member.comptime_token != null; | 3666 | const is_comptime = member.comptime_token != null; |
| ... | @@ -3706,6 +3710,7 @@ fn structDeclInner( | ... | @@ -3706,6 +3710,7 @@ fn structDeclInner( |
| 3706 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 3710 | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| 3707 | .fields_len = @intCast(u32, field_index), | 3711 | .fields_len = @intCast(u32, field_index), |
| 3708 | .decls_len = @intCast(u32, wip_decls.decl_index), | 3712 | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 3713 | .known_has_bits = known_has_bits, | ||
| 3709 | }); | 3714 | }); |
| 3710 | 3715 | ||
| 3711 | try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len + | 3716 | try astgen.extra.ensureUnusedCapacity(gpa, bit_bag.items.len + |
| ... | @@ -8150,6 +8155,189 @@ fn nodeMayEvalToError(tree: *const ast.Tree, start_node: ast.Node.Index) enum { | ... | @@ -8150,6 +8155,189 @@ fn nodeMayEvalToError(tree: *const ast.Tree, start_node: ast.Node.Index) enum { |
| 8150 | } | 8155 | } |
| 8151 | } | 8156 | } |
| 8152 | 8157 | ||
| 8158 | fn nodeImpliesRuntimeBits(tree: *const ast.Tree, start_node: ast.Node.Index) bool { | ||
| 8159 | const node_tags = tree.nodes.items(.tag); | ||
| 8160 | const node_datas = tree.nodes.items(.data); | ||
| 8161 | |||
| 8162 | var node = start_node; | ||
| 8163 | while (true) { | ||
| 8164 | switch (node_tags[node]) { | ||
| 8165 | .root, | ||
| 8166 | .@"usingnamespace", | ||
| 8167 | .test_decl, | ||
| 8168 | .switch_case, | ||
| 8169 | .switch_case_one, | ||
| 8170 | .container_field_init, | ||
| 8171 | .container_field_align, | ||
| 8172 | .container_field, | ||
| 8173 | .asm_output, | ||
| 8174 | .asm_input, | ||
| 8175 | .global_var_decl, | ||
| 8176 | .local_var_decl, | ||
| 8177 | .simple_var_decl, | ||
| 8178 | .aligned_var_decl, | ||
| 8179 | => unreachable, | ||
| 8180 | |||
| 8181 | .@"return", | ||
| 8182 | .@"break", | ||
| 8183 | .@"continue", | ||
| 8184 | .bit_not, | ||
| 8185 | .bool_not, | ||
| 8186 | .@"defer", | ||
| 8187 | .@"errdefer", | ||
| 8188 | .address_of, | ||
| 8189 | .negation, | ||
| 8190 | .negation_wrap, | ||
| 8191 | .@"resume", | ||
| 8192 | .array_type, | ||
| 8193 | .@"suspend", | ||
| 8194 | .@"anytype", | ||
| 8195 | .fn_decl, | ||
| 8196 | .anyframe_literal, | ||
| 8197 | .integer_literal, | ||
| 8198 | .float_literal, | ||
| 8199 | .enum_literal, | ||
| 8200 | .string_literal, | ||
| 8201 | .multiline_string_literal, | ||
| 8202 | .char_literal, | ||
| 8203 | .true_literal, | ||
| 8204 | .false_literal, | ||
| 8205 | .null_literal, | ||
| 8206 | .undefined_literal, | ||
| 8207 | .unreachable_literal, | ||
| 8208 | .identifier, | ||
| 8209 | .error_set_decl, | ||
| 8210 | .container_decl, | ||
| 8211 | .container_decl_trailing, | ||
| 8212 | .container_decl_two, | ||
| 8213 | .container_decl_two_trailing, | ||
| 8214 | .container_decl_arg, | ||
| 8215 | .container_decl_arg_trailing, | ||
| 8216 | .tagged_union, | ||
| 8217 | .tagged_union_trailing, | ||
| 8218 | .tagged_union_two, | ||
| 8219 | .tagged_union_two_trailing, | ||
| 8220 | .tagged_union_enum_tag, | ||
| 8221 | .tagged_union_enum_tag_trailing, | ||
| 8222 | .@"asm", | ||
| 8223 | .asm_simple, | ||
| 8224 | .add, | ||
| 8225 | .add_wrap, | ||
| 8226 | .array_cat, | ||
| 8227 | .array_mult, | ||
| 8228 | .assign, | ||
| 8229 | .assign_bit_and, | ||
| 8230 | .assign_bit_or, | ||
| 8231 | .assign_bit_shift_left, | ||
| 8232 | .assign_bit_shift_right, | ||
| 8233 | .assign_bit_xor, | ||
| 8234 | .assign_div, | ||
| 8235 | .assign_sub, | ||
| 8236 | .assign_sub_wrap, | ||
| 8237 | .assign_mod, | ||
| 8238 | .assign_add, | ||
| 8239 | .assign_add_wrap, | ||
| 8240 | .assign_mul, | ||
| 8241 | .assign_mul_wrap, | ||
| 8242 | .bang_equal, | ||
| 8243 | .bit_and, | ||
| 8244 | .bit_or, | ||
| 8245 | .bit_shift_left, | ||
| 8246 | .bit_shift_right, | ||
| 8247 | .bit_xor, | ||
| 8248 | .bool_and, | ||
| 8249 | .bool_or, | ||
| 8250 | .div, | ||
| 8251 | .equal_equal, | ||
| 8252 | .error_union, | ||
| 8253 | .greater_or_equal, | ||
| 8254 | .greater_than, | ||
| 8255 | .less_or_equal, | ||
| 8256 | .less_than, | ||
| 8257 | .merge_error_sets, | ||
| 8258 | .mod, | ||
| 8259 | .mul, | ||
| 8260 | .mul_wrap, | ||
| 8261 | .switch_range, | ||
| 8262 | .field_access, | ||
| 8263 | .sub, | ||
| 8264 | .sub_wrap, | ||
| 8265 | .slice, | ||
| 8266 | .slice_open, | ||
| 8267 | .slice_sentinel, | ||
| 8268 | .deref, | ||
| 8269 | .array_access, | ||
| 8270 | .error_value, | ||
| 8271 | .while_simple, | ||
| 8272 | .while_cont, | ||
| 8273 | .for_simple, | ||
| 8274 | .if_simple, | ||
| 8275 | .@"catch", | ||
| 8276 | .@"orelse", | ||
| 8277 | .array_init_one, | ||
| 8278 | .array_init_one_comma, | ||
| 8279 | .array_init_dot_two, | ||
| 8280 | .array_init_dot_two_comma, | ||
| 8281 | .array_init_dot, | ||
| 8282 | .array_init_dot_comma, | ||
| 8283 | .array_init, | ||
| 8284 | .array_init_comma, | ||
| 8285 | .struct_init_one, | ||
| 8286 | .struct_init_one_comma, | ||
| 8287 | .struct_init_dot_two, | ||
| 8288 | .struct_init_dot_two_comma, | ||
| 8289 | .struct_init_dot, | ||
| 8290 | .struct_init_dot_comma, | ||
| 8291 | .struct_init, | ||
| 8292 | .struct_init_comma, | ||
| 8293 | .@"while", | ||
| 8294 | .@"if", | ||
| 8295 | .@"for", | ||
| 8296 | .@"switch", | ||
| 8297 | .switch_comma, | ||
| 8298 | .call_one, | ||
| 8299 | .call_one_comma, | ||
| 8300 | .async_call_one, | ||
| 8301 | .async_call_one_comma, | ||
| 8302 | .call, | ||
| 8303 | .call_comma, | ||
| 8304 | .async_call, | ||
| 8305 | .async_call_comma, | ||
| 8306 | .block_two, | ||
| 8307 | .block_two_semicolon, | ||
| 8308 | .block, | ||
| 8309 | .block_semicolon, | ||
| 8310 | .builtin_call, | ||
| 8311 | .builtin_call_comma, | ||
| 8312 | .builtin_call_two, | ||
| 8313 | .builtin_call_two_comma, | ||
| 8314 | => return false, | ||
| 8315 | |||
| 8316 | // Forward the question to the LHS sub-expression. | ||
| 8317 | .grouped_expression, | ||
| 8318 | .@"try", | ||
| 8319 | .@"await", | ||
| 8320 | .@"comptime", | ||
| 8321 | .@"nosuspend", | ||
| 8322 | .unwrap_optional, | ||
| 8323 | => node = node_datas[node].lhs, | ||
| 8324 | |||
| 8325 | .fn_proto_simple, | ||
| 8326 | .fn_proto_multi, | ||
| 8327 | .fn_proto_one, | ||
| 8328 | .fn_proto, | ||
| 8329 | .ptr_type_aligned, | ||
| 8330 | .ptr_type_sentinel, | ||
| 8331 | .ptr_type, | ||
| 8332 | .ptr_type_bit_range, | ||
| 8333 | .optional_type, | ||
| 8334 | .anyframe_type, | ||
| 8335 | .array_type_sentinel, | ||
| 8336 | => return true, | ||
| 8337 | } | ||
| 8338 | } | ||
| 8339 | } | ||
| 8340 | |||
| 8153 | /// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of | 8341 | /// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of |
| 8154 | /// result locations must call this function on their result. | 8342 | /// result locations must call this function on their result. |
| 8155 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. | 8343 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. |
| ... | @@ -9556,6 +9744,7 @@ const GenZir = struct { | ... | @@ -9556,6 +9744,7 @@ const GenZir = struct { |
| 9556 | fields_len: u32, | 9744 | fields_len: u32, |
| 9557 | decls_len: u32, | 9745 | decls_len: u32, |
| 9558 | layout: std.builtin.TypeInfo.ContainerLayout, | 9746 | layout: std.builtin.TypeInfo.ContainerLayout, |
| 9747 | known_has_bits: bool, | ||
| 9559 | }) !void { | 9748 | }) !void { |
| 9560 | const astgen = gz.astgen; | 9749 | const astgen = gz.astgen; |
| 9561 | const gpa = astgen.gpa; | 9750 | const gpa = astgen.gpa; |
| ... | @@ -9585,6 +9774,7 @@ const GenZir = struct { | ... | @@ -9585,6 +9774,7 @@ const GenZir = struct { |
| 9585 | .has_body_len = args.body_len != 0, | 9774 | .has_body_len = args.body_len != 0, |
| 9586 | .has_fields_len = args.fields_len != 0, | 9775 | .has_fields_len = args.fields_len != 0, |
| 9587 | .has_decls_len = args.decls_len != 0, | 9776 | .has_decls_len = args.decls_len != 0, |
| 9777 | .known_has_bits = args.known_has_bits, | ||
| 9588 | .name_strategy = gz.anon_name_strategy, | 9778 | .name_strategy = gz.anon_name_strategy, |
| 9589 | .layout = args.layout, | 9779 | .layout = args.layout, |
| 9590 | }), | 9780 | }), |
src/Compilation.zig+44-26| ... | @@ -622,7 +622,7 @@ pub const InitOptions = struct { | ... | @@ -622,7 +622,7 @@ pub const InitOptions = struct { |
| 622 | global_cache_directory: Directory, | 622 | global_cache_directory: Directory, |
| 623 | target: Target, | 623 | target: Target, |
| 624 | root_name: []const u8, | 624 | root_name: []const u8, |
| 625 | root_pkg: ?*Package, | 625 | main_pkg: ?*Package, |
| 626 | output_mode: std.builtin.OutputMode, | 626 | output_mode: std.builtin.OutputMode, |
| 627 | thread_pool: *ThreadPool, | 627 | thread_pool: *ThreadPool, |
| 628 | dynamic_linker: ?[]const u8 = null, | 628 | dynamic_linker: ?[]const u8 = null, |
| ... | @@ -826,7 +826,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -826,7 +826,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 826 | const ofmt = options.object_format orelse options.target.getObjectFormat(); | 826 | const ofmt = options.object_format orelse options.target.getObjectFormat(); |
| 827 | 827 | ||
| 828 | const use_stage1 = options.use_stage1 orelse blk: { | 828 | const use_stage1 = options.use_stage1 orelse blk: { |
| 829 | // Even though we may have no Zig code to compile (depending on `options.root_pkg`), | 829 | // Even though we may have no Zig code to compile (depending on `options.main_pkg`), |
| 830 | // we may need to use stage1 for building compiler-rt and other dependencies. | 830 | // we may need to use stage1 for building compiler-rt and other dependencies. |
| 831 | 831 | ||
| 832 | if (build_options.omit_stage2) | 832 | if (build_options.omit_stage2) |
| ... | @@ -846,7 +846,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -846,7 +846,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 846 | break :blk explicit; | 846 | break :blk explicit; |
| 847 | 847 | ||
| 848 | // If we have no zig code to compile, no need for LLVM. | 848 | // If we have no zig code to compile, no need for LLVM. |
| 849 | if (options.root_pkg == null) | 849 | if (options.main_pkg == null) |
| 850 | break :blk false; | 850 | break :blk false; |
| 851 | 851 | ||
| 852 | // If we are outputting .c code we must use Zig backend. | 852 | // If we are outputting .c code we must use Zig backend. |
| ... | @@ -929,7 +929,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -929,7 +929,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 929 | if (use_llvm) { | 929 | if (use_llvm) { |
| 930 | // If stage1 generates an object file, self-hosted linker is not | 930 | // If stage1 generates an object file, self-hosted linker is not |
| 931 | // yet sophisticated enough to handle that. | 931 | // yet sophisticated enough to handle that. |
| 932 | break :blk options.root_pkg != null; | 932 | break :blk options.main_pkg != null; |
| 933 | } | 933 | } |
| 934 | 934 | ||
| 935 | break :blk false; | 935 | break :blk false; |
| ... | @@ -1159,7 +1159,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1159,7 +1159,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1159 | if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model); | 1159 | if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model); |
| 1160 | // TODO audit this and make sure everything is in it | 1160 | // TODO audit this and make sure everything is in it |
| 1161 | 1161 | ||
| 1162 | const module: ?*Module = if (options.root_pkg) |root_pkg| blk: { | 1162 | const module: ?*Module = if (options.main_pkg) |main_pkg| blk: { |
| 1163 | // Options that are specific to zig source files, that cannot be | 1163 | // Options that are specific to zig source files, that cannot be |
| 1164 | // modified between incremental updates. | 1164 | // modified between incremental updates. |
| 1165 | var hash = cache.hash; | 1165 | var hash = cache.hash; |
| ... | @@ -1169,13 +1169,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1169,13 +1169,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1169 | // incremental compilation will handle it, but we do want to namespace different | 1169 | // incremental compilation will handle it, but we do want to namespace different |
| 1170 | // source file names because they are likely different compilations and therefore this | 1170 | // source file names because they are likely different compilations and therefore this |
| 1171 | // would be likely to cause cache hits. | 1171 | // would be likely to cause cache hits. |
| 1172 | hash.addBytes(root_pkg.root_src_path); | 1172 | hash.addBytes(main_pkg.root_src_path); |
| 1173 | hash.addOptionalBytes(root_pkg.root_src_directory.path); | 1173 | hash.addOptionalBytes(main_pkg.root_src_directory.path); |
| 1174 | { | 1174 | { |
| 1175 | var local_arena = std.heap.ArenaAllocator.init(gpa); | 1175 | var local_arena = std.heap.ArenaAllocator.init(gpa); |
| 1176 | defer local_arena.deinit(); | 1176 | defer local_arena.deinit(); |
| 1177 | var seen_table = std.AutoHashMap(*Package, void).init(&local_arena.allocator); | 1177 | var seen_table = std.AutoHashMap(*Package, void).init(&local_arena.allocator); |
| 1178 | try addPackageTableToCacheHash(&hash, &local_arena, root_pkg.table, &seen_table, .path_bytes); | 1178 | try addPackageTableToCacheHash(&hash, &local_arena, main_pkg.table, &seen_table, .path_bytes); |
| 1179 | } | 1179 | } |
| 1180 | hash.add(valgrind); | 1180 | hash.add(valgrind); |
| 1181 | hash.add(single_threaded); | 1181 | hash.add(single_threaded); |
| ... | @@ -1212,9 +1212,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1212,9 +1212,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1212 | ); | 1212 | ); |
| 1213 | errdefer std_pkg.destroy(gpa); | 1213 | errdefer std_pkg.destroy(gpa); |
| 1214 | 1214 | ||
| 1215 | try root_pkg.addAndAdopt(gpa, "builtin", builtin_pkg); | 1215 | const root_pkg = if (options.is_test) root_pkg: { |
| 1216 | try root_pkg.add(gpa, "root", root_pkg); | 1216 | const test_pkg = try Package.createWithDir( |
| 1217 | try root_pkg.addAndAdopt(gpa, "std", std_pkg); | 1217 | gpa, |
| 1218 | options.zig_lib_directory, | ||
| 1219 | "std" ++ std.fs.path.sep_str ++ "special", | ||
| 1220 | "test_runner.zig", | ||
| 1221 | ); | ||
| 1222 | errdefer test_pkg.destroy(gpa); | ||
| 1223 | |||
| 1224 | try test_pkg.add(gpa, "builtin", builtin_pkg); | ||
| 1225 | try test_pkg.add(gpa, "root", test_pkg); | ||
| 1226 | try test_pkg.add(gpa, "std", std_pkg); | ||
| 1227 | |||
| 1228 | break :root_pkg test_pkg; | ||
| 1229 | } else main_pkg; | ||
| 1230 | errdefer if (options.is_test) root_pkg.destroy(gpa); | ||
| 1231 | |||
| 1232 | try main_pkg.addAndAdopt(gpa, "builtin", builtin_pkg); | ||
| 1233 | try main_pkg.add(gpa, "root", root_pkg); | ||
| 1234 | try main_pkg.addAndAdopt(gpa, "std", std_pkg); | ||
| 1218 | 1235 | ||
| 1219 | try std_pkg.add(gpa, "builtin", builtin_pkg); | 1236 | try std_pkg.add(gpa, "builtin", builtin_pkg); |
| 1220 | try std_pkg.add(gpa, "root", root_pkg); | 1237 | try std_pkg.add(gpa, "root", root_pkg); |
| ... | @@ -1258,6 +1275,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1258,6 +1275,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1258 | module.* = .{ | 1275 | module.* = .{ |
| 1259 | .gpa = gpa, | 1276 | .gpa = gpa, |
| 1260 | .comp = comp, | 1277 | .comp = comp, |
| 1278 | .main_pkg = main_pkg, | ||
| 1261 | .root_pkg = root_pkg, | 1279 | .root_pkg = root_pkg, |
| 1262 | .zig_cache_artifact_directory = zig_cache_artifact_directory, | 1280 | .zig_cache_artifact_directory = zig_cache_artifact_directory, |
| 1263 | .global_zir_cache = global_zir_cache, | 1281 | .global_zir_cache = global_zir_cache, |
| ... | @@ -1684,7 +1702,7 @@ pub fn update(self: *Compilation) !void { | ... | @@ -1684,7 +1702,7 @@ pub fn update(self: *Compilation) !void { |
| 1684 | 1702 | ||
| 1685 | // Make sure std.zig is inside the import_table. We unconditionally need | 1703 | // Make sure std.zig is inside the import_table. We unconditionally need |
| 1686 | // it for start.zig. | 1704 | // it for start.zig. |
| 1687 | const std_pkg = module.root_pkg.table.get("std").?; | 1705 | const std_pkg = module.main_pkg.table.get("std").?; |
| 1688 | _ = try module.importPkg(std_pkg); | 1706 | _ = try module.importPkg(std_pkg); |
| 1689 | 1707 | ||
| 1690 | // Normally we rely on importing std to in turn import the root source file | 1708 | // Normally we rely on importing std to in turn import the root source file |
| ... | @@ -1692,7 +1710,7 @@ pub fn update(self: *Compilation) !void { | ... | @@ -1692,7 +1710,7 @@ pub fn update(self: *Compilation) !void { |
| 1692 | // so in order to run AstGen on the root source file we put it into the | 1710 | // so in order to run AstGen on the root source file we put it into the |
| 1693 | // import_table here. | 1711 | // import_table here. |
| 1694 | if (use_stage1) { | 1712 | if (use_stage1) { |
| 1695 | _ = try module.importPkg(module.root_pkg); | 1713 | _ = try module.importPkg(module.main_pkg); |
| 1696 | } | 1714 | } |
| 1697 | 1715 | ||
| 1698 | // Put a work item in for every known source file to detect if | 1716 | // Put a work item in for every known source file to detect if |
| ... | @@ -3873,7 +3891,7 @@ fn buildOutputFromZig( | ... | @@ -3873,7 +3891,7 @@ fn buildOutputFromZig( |
| 3873 | var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{}); | 3891 | var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{}); |
| 3874 | defer special_dir.close(); | 3892 | defer special_dir.close(); |
| 3875 | 3893 | ||
| 3876 | var root_pkg: Package = .{ | 3894 | var main_pkg: Package = .{ |
| 3877 | .root_src_directory = .{ | 3895 | .root_src_directory = .{ |
| 3878 | .path = special_path, | 3896 | .path = special_path, |
| 3879 | .handle = special_dir, | 3897 | .handle = special_dir, |
| ... | @@ -3899,7 +3917,7 @@ fn buildOutputFromZig( | ... | @@ -3899,7 +3917,7 @@ fn buildOutputFromZig( |
| 3899 | .zig_lib_directory = comp.zig_lib_directory, | 3917 | .zig_lib_directory = comp.zig_lib_directory, |
| 3900 | .target = target, | 3918 | .target = target, |
| 3901 | .root_name = root_name, | 3919 | .root_name = root_name, |
| 3902 | .root_pkg = &root_pkg, | 3920 | .main_pkg = &main_pkg, |
| 3903 | .output_mode = output_mode, | 3921 | .output_mode = output_mode, |
| 3904 | .thread_pool = comp.thread_pool, | 3922 | .thread_pool = comp.thread_pool, |
| 3905 | .libc_installation = comp.bin_file.options.libc_installation, | 3923 | .libc_installation = comp.bin_file.options.libc_installation, |
| ... | @@ -3969,8 +3987,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -3969,8 +3987,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 3969 | // Here we use the legacy stage1 C++ compiler to compile Zig code. | 3987 | // Here we use the legacy stage1 C++ compiler to compile Zig code. |
| 3970 | const mod = comp.bin_file.options.module.?; | 3988 | const mod = comp.bin_file.options.module.?; |
| 3971 | const directory = mod.zig_cache_artifact_directory; // Just an alias to make it shorter to type. | 3989 | const directory = mod.zig_cache_artifact_directory; // Just an alias to make it shorter to type. |
| 3972 | const main_zig_file = try mod.root_pkg.root_src_directory.join(arena, &[_][]const u8{ | 3990 | const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{ |
| 3973 | mod.root_pkg.root_src_path, | 3991 | mod.main_pkg.root_src_path, |
| 3974 | }); | 3992 | }); |
| 3975 | const zig_lib_dir = comp.zig_lib_directory.path.?; | 3993 | const zig_lib_dir = comp.zig_lib_directory.path.?; |
| 3976 | const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"}); | 3994 | const builtin_zig_path = try directory.join(arena, &[_][]const u8{"builtin.zig"}); |
| ... | @@ -4002,7 +4020,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4002,7 +4020,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4002 | _ = try man.addFile(main_zig_file, null); | 4020 | _ = try man.addFile(main_zig_file, null); |
| 4003 | { | 4021 | { |
| 4004 | var seen_table = std.AutoHashMap(*Package, void).init(&arena_allocator.allocator); | 4022 | var seen_table = std.AutoHashMap(*Package, void).init(&arena_allocator.allocator); |
| 4005 | try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.root_pkg.table, &seen_table, .{ .files = &man }); | 4023 | try addPackageTableToCacheHash(&man.hash, &arena_allocator, mod.main_pkg.table, &seen_table, .{ .files = &man }); |
| 4006 | } | 4024 | } |
| 4007 | man.hash.add(comp.bin_file.options.valgrind); | 4025 | man.hash.add(comp.bin_file.options.valgrind); |
| 4008 | man.hash.add(comp.bin_file.options.single_threaded); | 4026 | man.hash.add(comp.bin_file.options.single_threaded); |
| ... | @@ -4045,7 +4063,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4045,7 +4063,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4045 | &prev_digest_buf, | 4063 | &prev_digest_buf, |
| 4046 | ) catch |err| blk: { | 4064 | ) catch |err| blk: { |
| 4047 | log.debug("stage1 {s} new_digest={s} error: {s}", .{ | 4065 | log.debug("stage1 {s} new_digest={s} error: {s}", .{ |
| 4048 | mod.root_pkg.root_src_path, | 4066 | mod.main_pkg.root_src_path, |
| 4049 | std.fmt.fmtSliceHexLower(&digest), | 4067 | std.fmt.fmtSliceHexLower(&digest), |
| 4050 | @errorName(err), | 4068 | @errorName(err), |
| 4051 | }); | 4069 | }); |
| ... | @@ -4057,7 +4075,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4057,7 +4075,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4057 | break :hit; | 4075 | break :hit; |
| 4058 | 4076 | ||
| 4059 | log.debug("stage1 {s} digest={s} match - skipping invocation", .{ | 4077 | log.debug("stage1 {s} digest={s} match - skipping invocation", .{ |
| 4060 | mod.root_pkg.root_src_path, | 4078 | mod.main_pkg.root_src_path, |
| 4061 | std.fmt.fmtSliceHexLower(&digest), | 4079 | std.fmt.fmtSliceHexLower(&digest), |
| 4062 | }); | 4080 | }); |
| 4063 | var flags_bytes: [1]u8 = undefined; | 4081 | var flags_bytes: [1]u8 = undefined; |
| ... | @@ -4083,7 +4101,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4083,7 +4101,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4083 | return; | 4101 | return; |
| 4084 | } | 4102 | } |
| 4085 | log.debug("stage1 {s} prev_digest={s} new_digest={s}", .{ | 4103 | log.debug("stage1 {s} prev_digest={s} new_digest={s}", .{ |
| 4086 | mod.root_pkg.root_src_path, | 4104 | mod.main_pkg.root_src_path, |
| 4087 | std.fmt.fmtSliceHexLower(prev_digest), | 4105 | std.fmt.fmtSliceHexLower(prev_digest), |
| 4088 | std.fmt.fmtSliceHexLower(&digest), | 4106 | std.fmt.fmtSliceHexLower(&digest), |
| 4089 | }); | 4107 | }); |
| ... | @@ -4109,7 +4127,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4109,7 +4127,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4109 | 4127 | ||
| 4110 | comp.stage1_cache_manifest = &man; | 4128 | comp.stage1_cache_manifest = &man; |
| 4111 | 4129 | ||
| 4112 | const main_pkg_path = mod.root_pkg.root_src_directory.path orelse ""; | 4130 | const main_pkg_path = mod.main_pkg.root_src_directory.path orelse ""; |
| 4113 | 4131 | ||
| 4114 | const stage1_module = stage1.create( | 4132 | const stage1_module = stage1.create( |
| 4115 | @enumToInt(comp.bin_file.options.optimize_mode), | 4133 | @enumToInt(comp.bin_file.options.optimize_mode), |
| ... | @@ -4142,7 +4160,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4142,7 +4160,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4142 | const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory); | 4160 | const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory); |
| 4143 | const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory); | 4161 | const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory); |
| 4144 | const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory); | 4162 | const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory); |
| 4145 | const stage1_pkg = try createStage1Pkg(arena, "root", mod.root_pkg, null); | 4163 | const stage1_pkg = try createStage1Pkg(arena, "root", mod.main_pkg, null); |
| 4146 | const test_filter = comp.test_filter orelse ""[0..0]; | 4164 | const test_filter = comp.test_filter orelse ""[0..0]; |
| 4147 | const test_name_prefix = comp.test_name_prefix orelse ""[0..0]; | 4165 | const test_name_prefix = comp.test_name_prefix orelse ""[0..0]; |
| 4148 | const subsystem = if (comp.bin_file.options.subsystem) |s| | 4166 | const subsystem = if (comp.bin_file.options.subsystem) |s| |
| ... | @@ -4173,7 +4191,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4173,7 +4191,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4173 | .test_name_prefix_ptr = test_name_prefix.ptr, | 4191 | .test_name_prefix_ptr = test_name_prefix.ptr, |
| 4174 | .test_name_prefix_len = test_name_prefix.len, | 4192 | .test_name_prefix_len = test_name_prefix.len, |
| 4175 | .userdata = @ptrToInt(comp), | 4193 | .userdata = @ptrToInt(comp), |
| 4176 | .root_pkg = stage1_pkg, | 4194 | .main_pkg = stage1_pkg, |
| 4177 | .code_model = @enumToInt(comp.bin_file.options.machine_code_model), | 4195 | .code_model = @enumToInt(comp.bin_file.options.machine_code_model), |
| 4178 | .subsystem = subsystem, | 4196 | .subsystem = subsystem, |
| 4179 | .err_color = @enumToInt(comp.color), | 4197 | .err_color = @enumToInt(comp.color), |
| ... | @@ -4239,7 +4257,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node | ... | @@ -4239,7 +4257,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4239 | // means that the next invocation will have an unnecessary cache miss. | 4257 | // means that the next invocation will have an unnecessary cache miss. |
| 4240 | const stage1_flags_byte = @bitCast(u8, mod.stage1_flags); | 4258 | const stage1_flags_byte = @bitCast(u8, mod.stage1_flags); |
| 4241 | log.debug("stage1 {s} final digest={s} flags={x}", .{ | 4259 | log.debug("stage1 {s} final digest={s} flags={x}", .{ |
| 4242 | mod.root_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte, | 4260 | mod.main_pkg.root_src_path, std.fmt.fmtSliceHexLower(&digest), stage1_flags_byte, |
| 4243 | }); | 4261 | }); |
| 4244 | var digest_plus_flags: [digest.len + 2]u8 = undefined; | 4262 | var digest_plus_flags: [digest.len + 2]u8 = undefined; |
| 4245 | digest_plus_flags[0..digest.len].* = digest; | 4263 | digest_plus_flags[0..digest.len].* = digest; |
| ... | @@ -4333,7 +4351,7 @@ pub fn build_crt_file( | ... | @@ -4333,7 +4351,7 @@ pub fn build_crt_file( |
| 4333 | .zig_lib_directory = comp.zig_lib_directory, | 4351 | .zig_lib_directory = comp.zig_lib_directory, |
| 4334 | .target = target, | 4352 | .target = target, |
| 4335 | .root_name = root_name, | 4353 | .root_name = root_name, |
| 4336 | .root_pkg = null, | 4354 | .main_pkg = null, |
| 4337 | .output_mode = output_mode, | 4355 | .output_mode = output_mode, |
| 4338 | .thread_pool = comp.thread_pool, | 4356 | .thread_pool = comp.thread_pool, |
| 4339 | .libc_installation = comp.bin_file.options.libc_installation, | 4357 | .libc_installation = comp.bin_file.options.libc_installation, |
src/Liveness.zig+4| ... | @@ -243,6 +243,8 @@ fn analyzeInst( | ... | @@ -243,6 +243,8 @@ fn analyzeInst( |
| 243 | .bool_and, | 243 | .bool_and, |
| 244 | .bool_or, | 244 | .bool_or, |
| 245 | .store, | 245 | .store, |
| 246 | .slice_elem_val, | ||
| 247 | .ptr_slice_elem_val, | ||
| 246 | => { | 248 | => { |
| 247 | const o = inst_datas[inst].bin_op; | 249 | const o = inst_datas[inst].bin_op; |
| 248 | return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none }); | 250 | return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none }); |
| ... | @@ -273,6 +275,8 @@ fn analyzeInst( | ... | @@ -273,6 +275,8 @@ fn analyzeInst( |
| 273 | .unwrap_errunion_err_ptr, | 275 | .unwrap_errunion_err_ptr, |
| 274 | .wrap_errunion_payload, | 276 | .wrap_errunion_payload, |
| 275 | .wrap_errunion_err, | 277 | .wrap_errunion_err, |
| 278 | .slice_ptr, | ||
| 279 | .slice_len, | ||
| 276 | => { | 280 | => { |
| 277 | const o = inst_datas[inst].ty_op; | 281 | const o = inst_datas[inst].ty_op; |
| 278 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); | 282 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); |
src/Module.zig+31-8| ... | @@ -35,8 +35,11 @@ comp: *Compilation, | ... | @@ -35,8 +35,11 @@ comp: *Compilation, |
| 35 | 35 | ||
| 36 | /// Where our incremental compilation metadata serialization will go. | 36 | /// Where our incremental compilation metadata serialization will go. |
| 37 | zig_cache_artifact_directory: Compilation.Directory, | 37 | zig_cache_artifact_directory: Compilation.Directory, |
| 38 | /// Pointer to externally managed resource. `null` if there is no zig file being compiled. | 38 | /// Pointer to externally managed resource. |
| 39 | root_pkg: *Package, | 39 | root_pkg: *Package, |
| 40 | /// Normally, `main_pkg` and `root_pkg` are the same. The exception is `zig test`, in which | ||
| 41 | /// `root_pkg` is the test runner, and `main_pkg` is the user's source file which has the tests. | ||
| 42 | main_pkg: *Package, | ||
| 40 | 43 | ||
| 41 | /// Used by AstGen worker to load and store ZIR cache. | 44 | /// Used by AstGen worker to load and store ZIR cache. |
| 42 | global_zir_cache: Compilation.Directory, | 45 | global_zir_cache: Compilation.Directory, |
| ... | @@ -598,6 +601,9 @@ pub const Struct = struct { | ... | @@ -598,6 +601,9 @@ pub const Struct = struct { |
| 598 | layout_wip, | 601 | layout_wip, |
| 599 | have_layout, | 602 | have_layout, |
| 600 | }, | 603 | }, |
| 604 | /// If true, definitely nonzero size at runtime. If false, resolving the fields | ||
| 605 | /// is necessary to determine whether it has bits at runtime. | ||
| 606 | known_has_bits: bool, | ||
| 601 | 607 | ||
| 602 | pub const Field = struct { | 608 | pub const Field = struct { |
| 603 | /// Uses `noreturn` to indicate `anytype`. | 609 | /// Uses `noreturn` to indicate `anytype`. |
| ... | @@ -2048,19 +2054,22 @@ pub fn deinit(mod: *Module) void { | ... | @@ -2048,19 +2054,22 @@ pub fn deinit(mod: *Module) void { |
| 2048 | 2054 | ||
| 2049 | mod.deletion_set.deinit(gpa); | 2055 | mod.deletion_set.deinit(gpa); |
| 2050 | 2056 | ||
| 2051 | // The callsite of `Compilation.create` owns the `root_pkg`, however | 2057 | // The callsite of `Compilation.create` owns the `main_pkg`, however |
| 2052 | // Module owns the builtin and std packages that it adds. | 2058 | // Module owns the builtin and std packages that it adds. |
| 2053 | if (mod.root_pkg.table.fetchRemove("builtin")) |kv| { | 2059 | if (mod.main_pkg.table.fetchRemove("builtin")) |kv| { |
| 2054 | gpa.free(kv.key); | 2060 | gpa.free(kv.key); |
| 2055 | kv.value.destroy(gpa); | 2061 | kv.value.destroy(gpa); |
| 2056 | } | 2062 | } |
| 2057 | if (mod.root_pkg.table.fetchRemove("std")) |kv| { | 2063 | if (mod.main_pkg.table.fetchRemove("std")) |kv| { |
| 2058 | gpa.free(kv.key); | 2064 | gpa.free(kv.key); |
| 2059 | kv.value.destroy(gpa); | 2065 | kv.value.destroy(gpa); |
| 2060 | } | 2066 | } |
| 2061 | if (mod.root_pkg.table.fetchRemove("root")) |kv| { | 2067 | if (mod.main_pkg.table.fetchRemove("root")) |kv| { |
| 2062 | gpa.free(kv.key); | 2068 | gpa.free(kv.key); |
| 2063 | } | 2069 | } |
| 2070 | if (mod.root_pkg != mod.main_pkg) { | ||
| 2071 | mod.root_pkg.destroy(gpa); | ||
| 2072 | } | ||
| 2064 | 2073 | ||
| 2065 | mod.compile_log_text.deinit(gpa); | 2074 | mod.compile_log_text.deinit(gpa); |
| 2066 | 2075 | ||
| ... | @@ -2148,7 +2157,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void { | ... | @@ -2148,7 +2157,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void { |
| 2148 | 2157 | ||
| 2149 | const stat = try source_file.stat(); | 2158 | const stat = try source_file.stat(); |
| 2150 | 2159 | ||
| 2151 | const want_local_cache = file.pkg == mod.root_pkg; | 2160 | const want_local_cache = file.pkg == mod.main_pkg; |
| 2152 | const digest = hash: { | 2161 | const digest = hash: { |
| 2153 | var path_hash: Cache.HashHelper = .{}; | 2162 | var path_hash: Cache.HashHelper = .{}; |
| 2154 | path_hash.addBytes(build_options.version); | 2163 | path_hash.addBytes(build_options.version); |
| ... | @@ -2792,6 +2801,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { | ... | @@ -2792,6 +2801,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { |
| 2792 | .zir_index = undefined, // set below | 2801 | .zir_index = undefined, // set below |
| 2793 | .layout = .Auto, | 2802 | .layout = .Auto, |
| 2794 | .status = .none, | 2803 | .status = .none, |
| 2804 | .known_has_bits = undefined, | ||
| 2795 | .namespace = .{ | 2805 | .namespace = .{ |
| 2796 | .parent = null, | 2806 | .parent = null, |
| 2797 | .ty = struct_ty, | 2807 | .ty = struct_ty, |
| ... | @@ -3301,10 +3311,23 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi | ... | @@ -3301,10 +3311,23 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3301 | gop.value_ptr.* = new_decl; | 3311 | gop.value_ptr.* = new_decl; |
| 3302 | // Exported decls, comptime decls, usingnamespace decls, and | 3312 | // Exported decls, comptime decls, usingnamespace decls, and |
| 3303 | // test decls if in test mode, get analyzed. | 3313 | // test decls if in test mode, get analyzed. |
| 3314 | const decl_pkg = namespace.file_scope.pkg; | ||
| 3304 | const want_analysis = is_exported or switch (decl_name_index) { | 3315 | const want_analysis = is_exported or switch (decl_name_index) { |
| 3305 | 0 => true, // comptime decl | 3316 | 0 => true, // comptime decl |
| 3306 | 1 => mod.comp.bin_file.options.is_test, // test decl | 3317 | 1 => blk: { |
| 3307 | else => is_named_test and mod.comp.bin_file.options.is_test, | 3318 | // test decl with no name. Skip the part where we check against |
| 3319 | // the test name filter. | ||
| 3320 | if (!mod.comp.bin_file.options.is_test) break :blk false; | ||
| 3321 | if (decl_pkg != mod.main_pkg) break :blk false; | ||
| 3322 | break :blk true; | ||
| 3323 | }, | ||
| 3324 | else => blk: { | ||
| 3325 | if (!is_named_test) break :blk false; | ||
| 3326 | if (!mod.comp.bin_file.options.is_test) break :blk false; | ||
| 3327 | if (decl_pkg != mod.main_pkg) break :blk false; | ||
| 3328 | // TODO check the name against --test-filter | ||
| 3329 | break :blk true; | ||
| 3330 | }, | ||
| 3308 | }; | 3331 | }; |
| 3309 | if (want_analysis) { | 3332 | if (want_analysis) { |
| 3310 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); | 3333 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
src/Sema.zig+125-49| ... | @@ -768,6 +768,8 @@ pub fn analyzeStructDecl( | ... | @@ -768,6 +768,8 @@ pub fn analyzeStructDecl( |
| 768 | assert(extended.opcode == .struct_decl); | 768 | assert(extended.opcode == .struct_decl); |
| 769 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); | 769 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 770 | 770 | ||
| 771 | struct_obj.known_has_bits = small.known_has_bits; | ||
| 772 | |||
| 771 | var extra_index: usize = extended.operand; | 773 | var extra_index: usize = extended.operand; |
| 772 | extra_index += @boolToInt(small.has_src_node); | 774 | extra_index += @boolToInt(small.has_src_node); |
| 773 | extra_index += @boolToInt(small.has_body_len); | 775 | extra_index += @boolToInt(small.has_body_len); |
| ... | @@ -812,6 +814,7 @@ fn zirStructDecl( | ... | @@ -812,6 +814,7 @@ fn zirStructDecl( |
| 812 | .zir_index = inst, | 814 | .zir_index = inst, |
| 813 | .layout = small.layout, | 815 | .layout = small.layout, |
| 814 | .status = .none, | 816 | .status = .none, |
| 817 | .known_has_bits = undefined, | ||
| 815 | .namespace = .{ | 818 | .namespace = .{ |
| 816 | .parent = sema.owner_decl.namespace, | 819 | .parent = sema.owner_decl.namespace, |
| 817 | .ty = struct_ty, | 820 | .ty = struct_ty, |
| ... | @@ -1259,8 +1262,13 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co | ... | @@ -1259,8 +1262,13 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1259 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 1262 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 1260 | const src = inst_data.src(); | 1263 | const src = inst_data.src(); |
| 1261 | const array_ptr = sema.resolveInst(inst_data.operand); | 1264 | const array_ptr = sema.resolveInst(inst_data.operand); |
| 1265 | const array_ptr_src = src; | ||
| 1262 | 1266 | ||
| 1263 | const elem_ty = sema.typeOf(array_ptr).elemType(); | 1267 | const elem_ty = sema.typeOf(array_ptr).elemType(); |
| 1268 | if (elem_ty.isSlice()) { | ||
| 1269 | const slice_inst = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src); | ||
| 1270 | return sema.analyzeSliceLen(block, src, slice_inst); | ||
| 1271 | } | ||
| 1264 | if (!elem_ty.isIndexable()) { | 1272 | if (!elem_ty.isIndexable()) { |
| 1265 | const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node }; | 1273 | const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node }; |
| 1266 | const msg = msg: { | 1274 | const msg = msg: { |
| ... | @@ -1283,7 +1291,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co | ... | @@ -1283,7 +1291,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1283 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); | 1291 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); |
| 1284 | } | 1292 | } |
| 1285 | const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src); | 1293 | const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src); |
| 1286 | const result_ptr_src = src; | 1294 | const result_ptr_src = array_ptr_src; |
| 1287 | return sema.analyzeLoad(block, src, result_ptr, result_ptr_src); | 1295 | return sema.analyzeLoad(block, src, result_ptr, result_ptr_src); |
| 1288 | } | 1296 | } |
| 1289 | 1297 | ||
| ... | @@ -2928,17 +2936,15 @@ fn zirErrUnionPayload( | ... | @@ -2928,17 +2936,15 @@ fn zirErrUnionPayload( |
| 2928 | return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name}); | 2936 | return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name}); |
| 2929 | } | 2937 | } |
| 2930 | const data = val.castTag(.error_union).?.data; | 2938 | const data = val.castTag(.error_union).?.data; |
| 2931 | return sema.addConstant( | 2939 | const result_ty = operand_ty.errorUnionPayload(); |
| 2932 | operand_ty.castTag(.error_union).?.data.payload, | 2940 | return sema.addConstant(result_ty, data); |
| 2933 | data, | ||
| 2934 | ); | ||
| 2935 | } | 2941 | } |
| 2936 | try sema.requireRuntimeBlock(block, src); | 2942 | try sema.requireRuntimeBlock(block, src); |
| 2937 | if (safety_check and block.wantSafety()) { | 2943 | if (safety_check and block.wantSafety()) { |
| 2938 | const is_non_err = try block.addUnOp(.is_err, operand); | 2944 | const is_non_err = try block.addUnOp(.is_err, operand); |
| 2939 | try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion); | 2945 | try sema.addSafetyCheck(block, is_non_err, .unwrap_errunion); |
| 2940 | } | 2946 | } |
| 2941 | const result_ty = operand_ty.castTag(.error_union).?.data.payload; | 2947 | const result_ty = operand_ty.errorUnionPayload(); |
| 2942 | return block.addTyOp(.unwrap_errunion_payload, result_ty, operand); | 2948 | return block.addTyOp(.unwrap_errunion_payload, result_ty, operand); |
| 2943 | } | 2949 | } |
| 2944 | 2950 | ||
| ... | @@ -2961,7 +2967,8 @@ fn zirErrUnionPayloadPtr( | ... | @@ -2961,7 +2967,8 @@ fn zirErrUnionPayloadPtr( |
| 2961 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) | 2967 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) |
| 2962 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); | 2968 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); |
| 2963 | 2969 | ||
| 2964 | const operand_pointer_ty = try Module.simplePtrType(sema.arena, operand_ty.elemType().castTag(.error_union).?.data.payload, !operand_ty.isConstPtr(), .One); | 2970 | const payload_ty = operand_ty.elemType().errorUnionPayload(); |
| 2971 | const operand_pointer_ty = try Module.simplePtrType(sema.arena, payload_ty, !operand_ty.isConstPtr(), .One); | ||
| 2965 | 2972 | ||
| 2966 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { | 2973 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 2967 | const val = try pointer_val.pointerDeref(sema.arena); | 2974 | const val = try pointer_val.pointerDeref(sema.arena); |
| ... | @@ -2999,7 +3006,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi | ... | @@ -2999,7 +3006,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi |
| 2999 | if (operand_ty.zigTypeTag() != .ErrorUnion) | 3006 | if (operand_ty.zigTypeTag() != .ErrorUnion) |
| 3000 | return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); | 3007 | return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); |
| 3001 | 3008 | ||
| 3002 | const result_ty = operand_ty.castTag(.error_union).?.data.error_set; | 3009 | const result_ty = operand_ty.errorUnionSet(); |
| 3003 | 3010 | ||
| 3004 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { | 3011 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 3005 | assert(val.getError() != null); | 3012 | assert(val.getError() != null); |
| ... | @@ -3025,7 +3032,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co | ... | @@ -3025,7 +3032,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 3025 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) | 3032 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) |
| 3026 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); | 3033 | return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); |
| 3027 | 3034 | ||
| 3028 | const result_ty = operand_ty.elemType().castTag(.error_union).?.data.error_set; | 3035 | const result_ty = operand_ty.elemType().errorUnionSet(); |
| 3029 | 3036 | ||
| 3030 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { | 3037 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 3031 | const val = try pointer_val.pointerDeref(sema.arena); | 3038 | const val = try pointer_val.pointerDeref(sema.arena); |
| ... | @@ -3048,7 +3055,7 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde | ... | @@ -3048,7 +3055,7 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde |
| 3048 | const operand_ty = sema.typeOf(operand); | 3055 | const operand_ty = sema.typeOf(operand); |
| 3049 | if (operand_ty.zigTypeTag() != .ErrorUnion) | 3056 | if (operand_ty.zigTypeTag() != .ErrorUnion) |
| 3050 | return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); | 3057 | return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); |
| 3051 | if (operand_ty.castTag(.error_union).?.data.payload.zigTypeTag() != .Void) { | 3058 | if (operand_ty.errorUnionPayload().zigTypeTag() != .Void) { |
| 3052 | return sema.mod.fail(&block.base, src, "expression value is ignored", .{}); | 3059 | return sema.mod.fail(&block.base, src, "expression value is ignored", .{}); |
| 3053 | } | 3060 | } |
| 3054 | } | 3061 | } |
| ... | @@ -3460,14 +3467,8 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -3460,14 +3467,8 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 3460 | 3467 | ||
| 3461 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; | 3468 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3462 | const array = sema.resolveInst(bin_inst.lhs); | 3469 | const array = sema.resolveInst(bin_inst.lhs); |
| 3463 | const array_ty = sema.typeOf(array); | ||
| 3464 | const array_ptr = if (array_ty.zigTypeTag() == .Pointer) | ||
| 3465 | array | ||
| 3466 | else | ||
| 3467 | try sema.analyzeRef(block, sema.src, array); | ||
| 3468 | const elem_index = sema.resolveInst(bin_inst.rhs); | 3470 | const elem_index = sema.resolveInst(bin_inst.rhs); |
| 3469 | const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); | 3471 | return sema.elemVal(block, sema.src, array, elem_index, sema.src); |
| 3470 | return sema.analyzeLoad(block, sema.src, result_ptr, sema.src); | ||
| 3471 | } | 3472 | } |
| 3472 | 3473 | ||
| 3473 | fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 3474 | fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -3479,14 +3480,8 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil | ... | @@ -3479,14 +3480,8 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil |
| 3479 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; | 3480 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; |
| 3480 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 3481 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 3481 | const array = sema.resolveInst(extra.lhs); | 3482 | const array = sema.resolveInst(extra.lhs); |
| 3482 | const array_ty = sema.typeOf(array); | ||
| 3483 | const array_ptr = if (array_ty.zigTypeTag() == .Pointer) | ||
| 3484 | array | ||
| 3485 | else | ||
| 3486 | try sema.analyzeRef(block, src, array); | ||
| 3487 | const elem_index = sema.resolveInst(extra.rhs); | 3483 | const elem_index = sema.resolveInst(extra.rhs); |
| 3488 | const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | 3484 | return sema.elemVal(block, src, array, elem_index, elem_index_src); |
| 3489 | return sema.analyzeLoad(block, src, result_ptr, src); | ||
| 3490 | } | 3485 | } |
| 3491 | 3486 | ||
| 3492 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 3487 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -5338,7 +5333,7 @@ fn zirBoolBr( | ... | @@ -5338,7 +5333,7 @@ fn zirBoolBr( |
| 5338 | 5333 | ||
| 5339 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + | 5334 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + |
| 5340 | then_block.instructions.items.len + else_block.instructions.items.len + | 5335 | then_block.instructions.items.len + else_block.instructions.items.len + |
| 5341 | @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len); | 5336 | @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len + 1); |
| 5342 | 5337 | ||
| 5343 | const cond_br_payload = sema.addExtraAssumeCapacity(Air.CondBr{ | 5338 | const cond_br_payload = sema.addExtraAssumeCapacity(Air.CondBr{ |
| 5344 | .then_body_len = @intCast(u32, then_block.instructions.items.len), | 5339 | .then_body_len = @intCast(u32, then_block.instructions.items.len), |
| ... | @@ -6217,8 +6212,9 @@ fn zirVarExtended( | ... | @@ -6217,8 +6212,9 @@ fn zirVarExtended( |
| 6217 | const init_val: Value = if (small.has_init) blk: { | 6212 | const init_val: Value = if (small.has_init) blk: { |
| 6218 | const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); | 6213 | const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 6219 | extra_index += 1; | 6214 | extra_index += 1; |
| 6220 | const init_tv = try sema.resolveInstConst(block, init_src, init_ref); | 6215 | const init_air_inst = sema.resolveInst(init_ref); |
| 6221 | break :blk init_tv.val; | 6216 | break :blk (try sema.resolvePossiblyUndefinedValue(block, init_src, init_air_inst)) orelse |
| 6217 | return sema.failWithNeededComptime(block, init_src); | ||
| 6222 | } else Value.initTag(.unreachable_value); | 6218 | } else Value.initTag(.unreachable_value); |
| 6223 | 6219 | ||
| 6224 | if (!var_ty.isValidVarType(small.is_extern)) { | 6220 | if (!var_ty.isValidVarType(small.is_extern)) { |
| ... | @@ -6586,7 +6582,30 @@ fn namedFieldPtr( | ... | @@ -6586,7 +6582,30 @@ fn namedFieldPtr( |
| 6586 | }, | 6582 | }, |
| 6587 | .Pointer => { | 6583 | .Pointer => { |
| 6588 | const ptr_child = elem_ty.elemType(); | 6584 | const ptr_child = elem_ty.elemType(); |
| 6589 | switch (ptr_child.zigTypeTag()) { | 6585 | if (ptr_child.isSlice()) { |
| 6586 | if (mem.eql(u8, field_name, "ptr")) { | ||
| 6587 | return mod.fail( | ||
| 6588 | &block.base, | ||
| 6589 | field_name_src, | ||
| 6590 | "cannot obtain reference to pointer field of slice '{}'", | ||
| 6591 | .{elem_ty}, | ||
| 6592 | ); | ||
| 6593 | } else if (mem.eql(u8, field_name, "len")) { | ||
| 6594 | return mod.fail( | ||
| 6595 | &block.base, | ||
| 6596 | field_name_src, | ||
| 6597 | "cannot obtain reference to length field of slice '{}'", | ||
| 6598 | .{elem_ty}, | ||
| 6599 | ); | ||
| 6600 | } else { | ||
| 6601 | return mod.fail( | ||
| 6602 | &block.base, | ||
| 6603 | field_name_src, | ||
| 6604 | "no member named '{s}' in '{}'", | ||
| 6605 | .{ field_name, elem_ty }, | ||
| 6606 | ); | ||
| 6607 | } | ||
| 6608 | } else switch (ptr_child.zigTypeTag()) { | ||
| 6590 | .Array => { | 6609 | .Array => { |
| 6591 | if (mem.eql(u8, field_name, "len")) { | 6610 | if (mem.eql(u8, field_name, "len")) { |
| 6592 | return sema.addConstant( | 6611 | return sema.addConstant( |
| ... | @@ -6836,6 +6855,50 @@ fn elemPtr( | ... | @@ -6836,6 +6855,50 @@ fn elemPtr( |
| 6836 | return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{}); | 6855 | return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{}); |
| 6837 | } | 6856 | } |
| 6838 | 6857 | ||
| 6858 | fn elemVal( | ||
| 6859 | sema: *Sema, | ||
| 6860 | block: *Scope.Block, | ||
| 6861 | src: LazySrcLoc, | ||
| 6862 | array_maybe_ptr: Air.Inst.Ref, | ||
| 6863 | elem_index: Air.Inst.Ref, | ||
| 6864 | elem_index_src: LazySrcLoc, | ||
| 6865 | ) CompileError!Air.Inst.Ref { | ||
| 6866 | const array_ptr_src = src; // TODO better source location | ||
| 6867 | const maybe_ptr_ty = sema.typeOf(array_maybe_ptr); | ||
| 6868 | if (maybe_ptr_ty.isSinglePointer()) { | ||
| 6869 | const indexable_ty = maybe_ptr_ty.elemType(); | ||
| 6870 | if (indexable_ty.isSlice()) { | ||
| 6871 | // We have a pointer to a slice and we want an element value. | ||
| 6872 | if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) { | ||
| 6873 | const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); | ||
| 6874 | if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| { | ||
| 6875 | _ = slice_val; | ||
| 6876 | return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{}); | ||
| 6877 | } | ||
| 6878 | try sema.requireRuntimeBlock(block, src); | ||
| 6879 | return block.addBinOp(.slice_elem_val, slice, elem_index); | ||
| 6880 | } | ||
| 6881 | try sema.requireRuntimeBlock(block, src); | ||
| 6882 | return block.addBinOp(.ptr_slice_elem_val, array_maybe_ptr, elem_index); | ||
| 6883 | } | ||
| 6884 | } | ||
| 6885 | if (maybe_ptr_ty.isSlice()) { | ||
| 6886 | if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |slice_val| { | ||
| 6887 | _ = slice_val; | ||
| 6888 | return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{}); | ||
| 6889 | } | ||
| 6890 | try sema.requireRuntimeBlock(block, src); | ||
| 6891 | return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index); | ||
| 6892 | } | ||
| 6893 | |||
| 6894 | const array_ptr = if (maybe_ptr_ty.zigTypeTag() == .Pointer) | ||
| 6895 | array_maybe_ptr | ||
| 6896 | else | ||
| 6897 | try sema.analyzeRef(block, src, array_maybe_ptr); | ||
| 6898 | const ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | ||
| 6899 | return sema.analyzeLoad(block, src, ptr, elem_index_src); | ||
| 6900 | } | ||
| 6901 | |||
| 6839 | fn elemPtrArray( | 6902 | fn elemPtrArray( |
| 6840 | sema: *Sema, | 6903 | sema: *Sema, |
| 6841 | block: *Scope.Block, | 6904 | block: *Scope.Block, |
| ... | @@ -6896,11 +6959,6 @@ fn coerce( | ... | @@ -6896,11 +6959,6 @@ fn coerce( |
| 6896 | } | 6959 | } |
| 6897 | assert(inst_ty.zigTypeTag() != .Undefined); | 6960 | assert(inst_ty.zigTypeTag() != .Undefined); |
| 6898 | 6961 | ||
| 6899 | // T to E!T or E to E!T | ||
| 6900 | if (dest_type.tag() == .error_union) { | ||
| 6901 | return try sema.wrapErrorUnion(block, dest_type, inst, inst_src); | ||
| 6902 | } | ||
| 6903 | |||
| 6904 | // comptime known number to other number | 6962 | // comptime known number to other number |
| 6905 | if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| | 6963 | if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| |
| 6906 | return some; | 6964 | return some; |
| ... | @@ -7028,6 +7086,10 @@ fn coerce( | ... | @@ -7028,6 +7086,10 @@ fn coerce( |
| 7028 | ); | 7086 | ); |
| 7029 | } | 7087 | } |
| 7030 | }, | 7088 | }, |
| 7089 | .ErrorUnion => { | ||
| 7090 | // T to E!T or E to E!T | ||
| 7091 | return sema.wrapErrorUnion(block, dest_type, inst, inst_src); | ||
| 7092 | }, | ||
| 7031 | else => {}, | 7093 | else => {}, |
| 7032 | } | 7094 | } |
| 7033 | 7095 | ||
| ... | @@ -7257,16 +7319,13 @@ fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedVal | ... | @@ -7257,16 +7319,13 @@ fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedVal |
| 7257 | const gpa = sema.gpa; | 7319 | const gpa = sema.gpa; |
| 7258 | try sema.requireRuntimeBlock(block, src); | 7320 | try sema.requireRuntimeBlock(block, src); |
| 7259 | try sema.air_variables.append(gpa, variable); | 7321 | try sema.air_variables.append(gpa, variable); |
| 7260 | const result_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); | 7322 | return block.addInst(.{ |
| 7261 | try sema.air_instructions.append(gpa, .{ | ||
| 7262 | .tag = .varptr, | 7323 | .tag = .varptr, |
| 7263 | .data = .{ .ty_pl = .{ | 7324 | .data = .{ .ty_pl = .{ |
| 7264 | .ty = try sema.addType(ty), | 7325 | .ty = try sema.addType(ty), |
| 7265 | .payload = @intCast(u32, sema.air_variables.items.len - 1), | 7326 | .payload = @intCast(u32, sema.air_variables.items.len - 1), |
| 7266 | } }, | 7327 | } }, |
| 7267 | }); | 7328 | }); |
| 7268 | try block.instructions.append(gpa, result_inst); | ||
| 7269 | return Air.indexToRef(result_inst); | ||
| 7270 | } | 7329 | } |
| 7271 | 7330 | ||
| 7272 | fn analyzeRef( | 7331 | fn analyzeRef( |
| ... | @@ -7309,6 +7368,22 @@ fn analyzeLoad( | ... | @@ -7309,6 +7368,22 @@ fn analyzeLoad( |
| 7309 | return block.addTyOp(.load, elem_ty, ptr); | 7368 | return block.addTyOp(.load, elem_ty, ptr); |
| 7310 | } | 7369 | } |
| 7311 | 7370 | ||
| 7371 | fn analyzeSliceLen( | ||
| 7372 | sema: *Sema, | ||
| 7373 | block: *Scope.Block, | ||
| 7374 | src: LazySrcLoc, | ||
| 7375 | slice_inst: Air.Inst.Ref, | ||
| 7376 | ) CompileError!Air.Inst.Ref { | ||
| 7377 | if (try sema.resolvePossiblyUndefinedValue(block, src, slice_inst)) |slice_val| { | ||
| 7378 | if (slice_val.isUndef()) { | ||
| 7379 | return sema.addConstUndef(Type.initTag(.usize)); | ||
| 7380 | } | ||
| 7381 | return sema.mod.fail(&block.base, src, "TODO implement Sema analyzeSliceLen on comptime slice", .{}); | ||
| 7382 | } | ||
| 7383 | try sema.requireRuntimeBlock(block, src); | ||
| 7384 | return block.addTyOp(.slice_len, Type.initTag(.usize), slice_inst); | ||
| 7385 | } | ||
| 7386 | |||
| 7312 | fn analyzeIsNull( | 7387 | fn analyzeIsNull( |
| 7313 | sema: *Sema, | 7388 | sema: *Sema, |
| 7314 | block: *Scope.Block, | 7389 | block: *Scope.Block, |
| ... | @@ -7645,27 +7720,28 @@ fn wrapErrorUnion( | ... | @@ -7645,27 +7720,28 @@ fn wrapErrorUnion( |
| 7645 | inst_src: LazySrcLoc, | 7720 | inst_src: LazySrcLoc, |
| 7646 | ) !Air.Inst.Ref { | 7721 | ) !Air.Inst.Ref { |
| 7647 | const inst_ty = sema.typeOf(inst); | 7722 | const inst_ty = sema.typeOf(inst); |
| 7648 | const err_union = dest_type.castTag(.error_union).?; | 7723 | const dest_err_set_ty = dest_type.errorUnionSet(); |
| 7724 | const dest_payload_ty = dest_type.errorUnionPayload(); | ||
| 7649 | if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| { | 7725 | if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| { |
| 7650 | if (inst_ty.zigTypeTag() != .ErrorSet) { | 7726 | if (inst_ty.zigTypeTag() != .ErrorSet) { |
| 7651 | _ = try sema.coerce(block, err_union.data.payload, inst, inst_src); | 7727 | _ = try sema.coerce(block, dest_payload_ty, inst, inst_src); |
| 7652 | } else switch (err_union.data.error_set.tag()) { | 7728 | } else switch (dest_err_set_ty.tag()) { |
| 7653 | .anyerror => {}, | 7729 | .anyerror => {}, |
| 7654 | .error_set_single => { | 7730 | .error_set_single => { |
| 7655 | const expected_name = val.castTag(.@"error").?.data.name; | 7731 | const expected_name = val.castTag(.@"error").?.data.name; |
| 7656 | const n = err_union.data.error_set.castTag(.error_set_single).?.data; | 7732 | const n = dest_err_set_ty.castTag(.error_set_single).?.data; |
| 7657 | if (!mem.eql(u8, expected_name, n)) { | 7733 | if (!mem.eql(u8, expected_name, n)) { |
| 7658 | return sema.mod.fail( | 7734 | return sema.mod.fail( |
| 7659 | &block.base, | 7735 | &block.base, |
| 7660 | inst_src, | 7736 | inst_src, |
| 7661 | "expected type '{}', found type '{}'", | 7737 | "expected type '{}', found type '{}'", |
| 7662 | .{ err_union.data.error_set, inst_ty }, | 7738 | .{ dest_err_set_ty, inst_ty }, |
| 7663 | ); | 7739 | ); |
| 7664 | } | 7740 | } |
| 7665 | }, | 7741 | }, |
| 7666 | .error_set => { | 7742 | .error_set => { |
| 7667 | const expected_name = val.castTag(.@"error").?.data.name; | 7743 | const expected_name = val.castTag(.@"error").?.data.name; |
| 7668 | const error_set = err_union.data.error_set.castTag(.error_set).?.data; | 7744 | const error_set = dest_err_set_ty.castTag(.error_set).?.data; |
| 7669 | const names = error_set.names_ptr[0..error_set.names_len]; | 7745 | const names = error_set.names_ptr[0..error_set.names_len]; |
| 7670 | // TODO this is O(N). I'm putting off solving this until we solve inferred | 7746 | // TODO this is O(N). I'm putting off solving this until we solve inferred |
| 7671 | // error sets at the same time. | 7747 | // error sets at the same time. |
| ... | @@ -7677,19 +7753,19 @@ fn wrapErrorUnion( | ... | @@ -7677,19 +7753,19 @@ fn wrapErrorUnion( |
| 7677 | &block.base, | 7753 | &block.base, |
| 7678 | inst_src, | 7754 | inst_src, |
| 7679 | "expected type '{}', found type '{}'", | 7755 | "expected type '{}', found type '{}'", |
| 7680 | .{ err_union.data.error_set, inst_ty }, | 7756 | .{ dest_err_set_ty, inst_ty }, |
| 7681 | ); | 7757 | ); |
| 7682 | } | 7758 | } |
| 7683 | }, | 7759 | }, |
| 7684 | .error_set_inferred => { | 7760 | .error_set_inferred => { |
| 7685 | const expected_name = val.castTag(.@"error").?.data.name; | 7761 | const expected_name = val.castTag(.@"error").?.data.name; |
| 7686 | const map = &err_union.data.error_set.castTag(.error_set_inferred).?.data.map; | 7762 | const map = &dest_err_set_ty.castTag(.error_set_inferred).?.data.map; |
| 7687 | if (!map.contains(expected_name)) { | 7763 | if (!map.contains(expected_name)) { |
| 7688 | return sema.mod.fail( | 7764 | return sema.mod.fail( |
| 7689 | &block.base, | 7765 | &block.base, |
| 7690 | inst_src, | 7766 | inst_src, |
| 7691 | "expected type '{}', found type '{}'", | 7767 | "expected type '{}', found type '{}'", |
| 7692 | .{ err_union.data.error_set, inst_ty }, | 7768 | .{ dest_err_set_ty, inst_ty }, |
| 7693 | ); | 7769 | ); |
| 7694 | } | 7770 | } |
| 7695 | }, | 7771 | }, |
| ... | @@ -7704,10 +7780,10 @@ fn wrapErrorUnion( | ... | @@ -7704,10 +7780,10 @@ fn wrapErrorUnion( |
| 7704 | 7780 | ||
| 7705 | // we are coercing from E to E!T | 7781 | // we are coercing from E to E!T |
| 7706 | if (inst_ty.zigTypeTag() == .ErrorSet) { | 7782 | if (inst_ty.zigTypeTag() == .ErrorSet) { |
| 7707 | var coerced = try sema.coerce(block, err_union.data.error_set, inst, inst_src); | 7783 | var coerced = try sema.coerce(block, dest_err_set_ty, inst, inst_src); |
| 7708 | return block.addTyOp(.wrap_errunion_err, dest_type, coerced); | 7784 | return block.addTyOp(.wrap_errunion_err, dest_type, coerced); |
| 7709 | } else { | 7785 | } else { |
| 7710 | var coerced = try sema.coerce(block, err_union.data.payload, inst, inst_src); | 7786 | var coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src); |
| 7711 | return block.addTyOp(.wrap_errunion_payload, dest_type, coerced); | 7787 | return block.addTyOp(.wrap_errunion_payload, dest_type, coerced); |
| 7712 | } | 7788 | } |
| 7713 | } | 7789 | } |
| ... | @@ -7857,7 +7933,7 @@ fn getBuiltin( | ... | @@ -7857,7 +7933,7 @@ fn getBuiltin( |
| 7857 | name: []const u8, | 7933 | name: []const u8, |
| 7858 | ) CompileError!Air.Inst.Ref { | 7934 | ) CompileError!Air.Inst.Ref { |
| 7859 | const mod = sema.mod; | 7935 | const mod = sema.mod; |
| 7860 | const std_pkg = mod.root_pkg.table.get("std").?; | 7936 | const std_pkg = mod.main_pkg.table.get("std").?; |
| 7861 | const std_file = (mod.importPkg(std_pkg) catch unreachable).file; | 7937 | const std_file = (mod.importPkg(std_pkg) catch unreachable).file; |
| 7862 | const opt_builtin_inst = try sema.analyzeNamespaceLookup( | 7938 | const opt_builtin_inst = try sema.analyzeNamespaceLookup( |
| 7863 | block, | 7939 | block, |
src/Zir.zig+3-1| ... | @@ -2462,9 +2462,10 @@ pub const Inst = struct { | ... | @@ -2462,9 +2462,10 @@ pub const Inst = struct { |
| 2462 | has_body_len: bool, | 2462 | has_body_len: bool, |
| 2463 | has_fields_len: bool, | 2463 | has_fields_len: bool, |
| 2464 | has_decls_len: bool, | 2464 | has_decls_len: bool, |
| 2465 | known_has_bits: bool, | ||
| 2465 | name_strategy: NameStrategy, | 2466 | name_strategy: NameStrategy, |
| 2466 | layout: std.builtin.TypeInfo.ContainerLayout, | 2467 | layout: std.builtin.TypeInfo.ContainerLayout, |
| 2467 | _: u8 = undefined, | 2468 | _: u7 = undefined, |
| 2468 | }; | 2469 | }; |
| 2469 | }; | 2470 | }; |
| 2470 | 2471 | ||
| ... | @@ -3543,6 +3544,7 @@ const Writer = struct { | ... | @@ -3543,6 +3544,7 @@ const Writer = struct { |
| 3543 | break :blk decls_len; | 3544 | break :blk decls_len; |
| 3544 | } else 0; | 3545 | } else 0; |
| 3545 | 3546 | ||
| 3547 | try self.writeFlag(stream, "known_has_bits, ", small.known_has_bits); | ||
| 3546 | try stream.print("{s}, {s}, ", .{ | 3548 | try stream.print("{s}, {s}, ", .{ |
| 3547 | @tagName(small.name_strategy), @tagName(small.layout), | 3549 | @tagName(small.name_strategy), @tagName(small.layout), |
| 3548 | }); | 3550 | }); |
src/codegen.zig+37| ... | @@ -853,6 +853,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -853,6 +853,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 853 | .struct_field_ptr=> try self.airStructFieldPtr(inst), | 853 | .struct_field_ptr=> try self.airStructFieldPtr(inst), |
| 854 | .switch_br => try self.airSwitch(inst), | 854 | .switch_br => try self.airSwitch(inst), |
| 855 | .varptr => try self.airVarPtr(inst), | 855 | .varptr => try self.airVarPtr(inst), |
| 856 | .slice_ptr => try self.airSlicePtr(inst), | ||
| 857 | .slice_len => try self.airSliceLen(inst), | ||
| 858 | |||
| 859 | .slice_elem_val => try self.airSliceElemVal(inst), | ||
| 860 | .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), | ||
| 856 | 861 | ||
| 857 | .constant => unreachable, // excluded from function bodies | 862 | .constant => unreachable, // excluded from function bodies |
| 858 | .const_ty => unreachable, // excluded from function bodies | 863 | .const_ty => unreachable, // excluded from function bodies |
| ... | @@ -1333,6 +1338,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1333,6 +1338,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1333 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 1338 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 1334 | } | 1339 | } |
| 1335 | 1340 | ||
| 1341 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1342 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 1343 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1344 | else => return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch}), | ||
| 1345 | }; | ||
| 1346 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1350 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | ||
| 1351 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1352 | else => return self.fail("TODO implement slice_len for {}", .{self.target.cpu.arch}), | ||
| 1353 | }; | ||
| 1354 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1358 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | ||
| 1359 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1360 | else => return self.fail("TODO implement slice_elem_val for {}", .{self.target.cpu.arch}), | ||
| 1361 | }; | ||
| 1362 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | fn airPtrSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1366 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | ||
| 1367 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1368 | else => return self.fail("TODO implement ptr_slice_elem_val for {}", .{self.target.cpu.arch}), | ||
| 1369 | }; | ||
| 1370 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | ||
| 1371 | } | ||
| 1372 | |||
| 1336 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { | 1373 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1337 | if (!self.liveness.operandDies(inst, op_index)) | 1374 | if (!self.liveness.operandDies(inst, op_index)) |
| 1338 | return false; | 1375 | return false; |
src/codegen/c.zig+89-41| ... | @@ -237,7 +237,8 @@ pub const DeclGen = struct { | ... | @@ -237,7 +237,8 @@ pub const DeclGen = struct { |
| 237 | // This should lower to 0xaa bytes in safe modes, and for unsafe modes should | 237 | // This should lower to 0xaa bytes in safe modes, and for unsafe modes should |
| 238 | // lower to leaving variables uninitialized (that might need to be implemented | 238 | // lower to leaving variables uninitialized (that might need to be implemented |
| 239 | // outside of this function). | 239 | // outside of this function). |
| 240 | return dg.fail("TODO: C backend: implement renderValue undef", .{}); | 240 | return writer.writeAll("{}"); |
| 241 | //return dg.fail("TODO: C backend: implement renderValue undef", .{}); | ||
| 241 | } | 242 | } |
| 242 | switch (t.zigTypeTag()) { | 243 | switch (t.zigTypeTag()) { |
| 243 | .Int => { | 244 | .Int => { |
| ... | @@ -361,18 +362,27 @@ pub const DeclGen = struct { | ... | @@ -361,18 +362,27 @@ pub const DeclGen = struct { |
| 361 | } | 362 | } |
| 362 | }, | 363 | }, |
| 363 | .ErrorSet => { | 364 | .ErrorSet => { |
| 364 | const payload = val.castTag(.@"error").?; | 365 | switch (val.tag()) { |
| 365 | // error values will be #defined at the top of the file | 366 | .@"error" => { |
| 366 | return writer.print("zig_error_{s}", .{payload.data.name}); | 367 | const payload = val.castTag(.@"error").?; |
| 368 | // error values will be #defined at the top of the file | ||
| 369 | return writer.print("zig_error_{s}", .{payload.data.name}); | ||
| 370 | }, | ||
| 371 | else => { | ||
| 372 | // In this case we are rendering an error union which has a | ||
| 373 | // 0 bits payload. | ||
| 374 | return writer.writeAll("0"); | ||
| 375 | }, | ||
| 376 | } | ||
| 367 | }, | 377 | }, |
| 368 | .ErrorUnion => { | 378 | .ErrorUnion => { |
| 369 | const error_type = t.errorUnionSet(); | 379 | const error_type = t.errorUnionSet(); |
| 370 | const payload_type = t.errorUnionChild(); | 380 | const payload_type = t.errorUnionPayload(); |
| 371 | const data = val.castTag(.error_union).?.data; | 381 | const sub_val = val.castTag(.error_union).?.data; |
| 372 | 382 | ||
| 373 | if (!payload_type.hasCodeGenBits()) { | 383 | if (!payload_type.hasCodeGenBits()) { |
| 374 | // We use the error type directly as the type. | 384 | // We use the error type directly as the type. |
| 375 | return dg.renderValue(writer, error_type, data); | 385 | return dg.renderValue(writer, error_type, sub_val); |
| 376 | } | 386 | } |
| 377 | 387 | ||
| 378 | try writer.writeByte('('); | 388 | try writer.writeByte('('); |
| ... | @@ -383,7 +393,7 @@ pub const DeclGen = struct { | ... | @@ -383,7 +393,7 @@ pub const DeclGen = struct { |
| 383 | try dg.renderValue( | 393 | try dg.renderValue( |
| 384 | writer, | 394 | writer, |
| 385 | error_type, | 395 | error_type, |
| 386 | data, | 396 | sub_val, |
| 387 | ); | 397 | ); |
| 388 | try writer.writeAll(" }"); | 398 | try writer.writeAll(" }"); |
| 389 | } else { | 399 | } else { |
| ... | @@ -391,7 +401,7 @@ pub const DeclGen = struct { | ... | @@ -391,7 +401,7 @@ pub const DeclGen = struct { |
| 391 | try dg.renderValue( | 401 | try dg.renderValue( |
| 392 | writer, | 402 | writer, |
| 393 | payload_type, | 403 | payload_type, |
| 394 | data, | 404 | sub_val, |
| 395 | ); | 405 | ); |
| 396 | try writer.writeAll(", .error = 0 }"); | 406 | try writer.writeAll(", .error = 0 }"); |
| 397 | } | 407 | } |
| ... | @@ -616,7 +626,7 @@ pub const DeclGen = struct { | ... | @@ -616,7 +626,7 @@ pub const DeclGen = struct { |
| 616 | if (dg.typedefs.get(t)) |some| { | 626 | if (dg.typedefs.get(t)) |some| { |
| 617 | return w.writeAll(some.name); | 627 | return w.writeAll(some.name); |
| 618 | } | 628 | } |
| 619 | const child_type = t.errorUnionChild(); | 629 | const child_type = t.errorUnionPayload(); |
| 620 | const err_set_type = t.errorUnionSet(); | 630 | const err_set_type = t.errorUnionSet(); |
| 621 | 631 | ||
| 622 | if (!child_type.hasCodeGenBits()) { | 632 | if (!child_type.hasCodeGenBits()) { |
| ... | @@ -926,6 +936,11 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM | ... | @@ -926,6 +936,11 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM |
| 926 | .ref => try airRef(o, inst), | 936 | .ref => try airRef(o, inst), |
| 927 | .struct_field_ptr => try airStructFieldPtr(o, inst), | 937 | .struct_field_ptr => try airStructFieldPtr(o, inst), |
| 928 | .varptr => try airVarPtr(o, inst), | 938 | .varptr => try airVarPtr(o, inst), |
| 939 | .slice_ptr => try airSliceField(o, inst, ".ptr;\n"), | ||
| 940 | .slice_len => try airSliceField(o, inst, ".len;\n"), | ||
| 941 | |||
| 942 | .slice_elem_val => try airSliceElemVal(o, inst, "["), | ||
| 943 | .ptr_slice_elem_val => try airSliceElemVal(o, inst, "[0]["), | ||
| 929 | 944 | ||
| 930 | .unwrap_errunion_payload => try airUnwrapErrUnionPay(o, inst), | 945 | .unwrap_errunion_payload => try airUnwrapErrUnionPay(o, inst), |
| 931 | .unwrap_errunion_err => try airUnwrapErrUnionErr(o, inst), | 946 | .unwrap_errunion_err => try airUnwrapErrUnionErr(o, inst), |
| ... | @@ -948,6 +963,37 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM | ... | @@ -948,6 +963,37 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM |
| 948 | try writer.writeAll("}"); | 963 | try writer.writeAll("}"); |
| 949 | } | 964 | } |
| 950 | 965 | ||
| 966 | fn airSliceField(o: *Object, inst: Air.Inst.Index, suffix: []const u8) !CValue { | ||
| 967 | if (o.liveness.isUnused(inst)) | ||
| 968 | return CValue.none; | ||
| 969 | |||
| 970 | const ty_op = o.air.instructions.items(.data)[inst].ty_op; | ||
| 971 | const operand = try o.resolveInst(ty_op.operand); | ||
| 972 | const writer = o.writer(); | ||
| 973 | const local = try o.allocLocal(Type.initTag(.usize), .Const); | ||
| 974 | try writer.writeAll(" = "); | ||
| 975 | try o.writeCValue(writer, operand); | ||
| 976 | try writer.writeAll(suffix); | ||
| 977 | return local; | ||
| 978 | } | ||
| 979 | |||
| 980 | fn airSliceElemVal(o: *Object, inst: Air.Inst.Index, prefix: []const u8) !CValue { | ||
| 981 | if (o.liveness.isUnused(inst)) | ||
| 982 | return CValue.none; | ||
| 983 | |||
| 984 | const bin_op = o.air.instructions.items(.data)[inst].bin_op; | ||
| 985 | const slice = try o.resolveInst(bin_op.lhs); | ||
| 986 | const index = try o.resolveInst(bin_op.rhs); | ||
| 987 | const writer = o.writer(); | ||
| 988 | const local = try o.allocLocal(o.air.typeOfIndex(inst), .Const); | ||
| 989 | try writer.writeAll(" = "); | ||
| 990 | try o.writeCValue(writer, slice); | ||
| 991 | try writer.writeAll(prefix); | ||
| 992 | try o.writeCValue(writer, index); | ||
| 993 | try writer.writeAll("];\n"); | ||
| 994 | return local; | ||
| 995 | } | ||
| 996 | |||
| 951 | fn airVarPtr(o: *Object, inst: Air.Inst.Index) !CValue { | 997 | fn airVarPtr(o: *Object, inst: Air.Inst.Index) !CValue { |
| 952 | const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; | 998 | const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; |
| 953 | const variable = o.air.variables[ty_pl.payload]; | 999 | const variable = o.air.variables[ty_pl.payload]; |
| ... | @@ -1233,6 +1279,20 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue { | ... | @@ -1233,6 +1279,20 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1233 | const pl_op = o.air.instructions.items(.data)[inst].pl_op; | 1279 | const pl_op = o.air.instructions.items(.data)[inst].pl_op; |
| 1234 | const extra = o.air.extraData(Air.Call, pl_op.payload); | 1280 | const extra = o.air.extraData(Air.Call, pl_op.payload); |
| 1235 | const args = @bitCast([]const Air.Inst.Ref, o.air.extra[extra.end..][0..extra.data.args_len]); | 1281 | const args = @bitCast([]const Air.Inst.Ref, o.air.extra[extra.end..][0..extra.data.args_len]); |
| 1282 | const fn_ty = o.air.typeOf(pl_op.operand); | ||
| 1283 | const ret_ty = fn_ty.fnReturnType(); | ||
| 1284 | const unused_result = o.liveness.isUnused(inst); | ||
| 1285 | const writer = o.writer(); | ||
| 1286 | |||
| 1287 | var result_local: CValue = .none; | ||
| 1288 | if (unused_result) { | ||
| 1289 | if (ret_ty.hasCodeGenBits()) { | ||
| 1290 | try writer.print("(void)", .{}); | ||
| 1291 | } | ||
| 1292 | } else { | ||
| 1293 | result_local = try o.allocLocal(ret_ty, .Const); | ||
| 1294 | try writer.writeAll(" = "); | ||
| 1295 | } | ||
| 1236 | 1296 | ||
| 1237 | if (o.air.value(pl_op.operand)) |func_val| { | 1297 | if (o.air.value(pl_op.operand)) |func_val| { |
| 1238 | const fn_decl = if (func_val.castTag(.extern_fn)) |extern_fn| | 1298 | const fn_decl = if (func_val.castTag(.extern_fn)) |extern_fn| |
| ... | @@ -1242,38 +1302,26 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue { | ... | @@ -1242,38 +1302,26 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1242 | else | 1302 | else |
| 1243 | unreachable; | 1303 | unreachable; |
| 1244 | 1304 | ||
| 1245 | const fn_ty = fn_decl.ty; | 1305 | try writer.writeAll(mem.spanZ(fn_decl.name)); |
| 1246 | const ret_ty = fn_ty.fnReturnType(); | 1306 | } else { |
| 1247 | const unused_result = o.liveness.isUnused(inst); | 1307 | const callee = try o.resolveInst(pl_op.operand); |
| 1248 | var result_local: CValue = .none; | 1308 | try o.writeCValue(writer, callee); |
| 1309 | } | ||
| 1249 | 1310 | ||
| 1250 | const writer = o.writer(); | 1311 | try writer.writeAll("("); |
| 1251 | if (unused_result) { | 1312 | for (args) |arg, i| { |
| 1252 | if (ret_ty.hasCodeGenBits()) { | 1313 | if (i != 0) { |
| 1253 | try writer.print("(void)", .{}); | 1314 | try writer.writeAll(", "); |
| 1254 | } | ||
| 1255 | } else { | ||
| 1256 | result_local = try o.allocLocal(ret_ty, .Const); | ||
| 1257 | try writer.writeAll(" = "); | ||
| 1258 | } | 1315 | } |
| 1259 | const fn_name = mem.spanZ(fn_decl.name); | 1316 | if (o.air.value(arg)) |val| { |
| 1260 | try writer.print("{s}(", .{fn_name}); | 1317 | try o.dg.renderValue(writer, o.air.typeOf(arg), val); |
| 1261 | for (args) |arg, i| { | 1318 | } else { |
| 1262 | if (i != 0) { | 1319 | const val = try o.resolveInst(arg); |
| 1263 | try writer.writeAll(", "); | 1320 | try o.writeCValue(writer, val); |
| 1264 | } | ||
| 1265 | if (o.air.value(arg)) |val| { | ||
| 1266 | try o.dg.renderValue(writer, o.air.typeOf(arg), val); | ||
| 1267 | } else { | ||
| 1268 | const val = try o.resolveInst(arg); | ||
| 1269 | try o.writeCValue(writer, val); | ||
| 1270 | } | ||
| 1271 | } | 1321 | } |
| 1272 | try writer.writeAll(");\n"); | ||
| 1273 | return result_local; | ||
| 1274 | } else { | ||
| 1275 | return o.dg.fail("TODO: C backend: implement function pointers", .{}); | ||
| 1276 | } | 1322 | } |
| 1323 | try writer.writeAll(");\n"); | ||
| 1324 | return result_local; | ||
| 1277 | } | 1325 | } |
| 1278 | 1326 | ||
| 1279 | fn airDbgStmt(o: *Object, inst: Air.Inst.Index) !CValue { | 1327 | fn airDbgStmt(o: *Object, inst: Air.Inst.Index) !CValue { |
| ... | @@ -1643,7 +1691,7 @@ fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue { | ... | @@ -1643,7 +1691,7 @@ fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1643 | const operand = try o.resolveInst(ty_op.operand); | 1691 | const operand = try o.resolveInst(ty_op.operand); |
| 1644 | const operand_ty = o.air.typeOf(ty_op.operand); | 1692 | const operand_ty = o.air.typeOf(ty_op.operand); |
| 1645 | 1693 | ||
| 1646 | const payload_ty = operand_ty.errorUnionChild(); | 1694 | const payload_ty = operand_ty.errorUnionPayload(); |
| 1647 | if (!payload_ty.hasCodeGenBits()) { | 1695 | if (!payload_ty.hasCodeGenBits()) { |
| 1648 | if (operand_ty.zigTypeTag() == .Pointer) { | 1696 | if (operand_ty.zigTypeTag() == .Pointer) { |
| 1649 | const local = try o.allocLocal(inst_ty, .Const); | 1697 | const local = try o.allocLocal(inst_ty, .Const); |
| ... | @@ -1675,7 +1723,7 @@ fn airUnwrapErrUnionPay(o: *Object, inst: Air.Inst.Index) !CValue { | ... | @@ -1675,7 +1723,7 @@ fn airUnwrapErrUnionPay(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1675 | const operand = try o.resolveInst(ty_op.operand); | 1723 | const operand = try o.resolveInst(ty_op.operand); |
| 1676 | const operand_ty = o.air.typeOf(ty_op.operand); | 1724 | const operand_ty = o.air.typeOf(ty_op.operand); |
| 1677 | 1725 | ||
| 1678 | const payload_ty = operand_ty.errorUnionChild(); | 1726 | const payload_ty = operand_ty.errorUnionPayload(); |
| 1679 | if (!payload_ty.hasCodeGenBits()) { | 1727 | if (!payload_ty.hasCodeGenBits()) { |
| 1680 | return CValue.none; | 1728 | return CValue.none; |
| 1681 | } | 1729 | } |
| ... | @@ -1760,7 +1808,7 @@ fn airIsErr( | ... | @@ -1760,7 +1808,7 @@ fn airIsErr( |
| 1760 | const operand = try o.resolveInst(un_op); | 1808 | const operand = try o.resolveInst(un_op); |
| 1761 | const operand_ty = o.air.typeOf(un_op); | 1809 | const operand_ty = o.air.typeOf(un_op); |
| 1762 | const local = try o.allocLocal(Type.initTag(.bool), .Const); | 1810 | const local = try o.allocLocal(Type.initTag(.bool), .Const); |
| 1763 | const payload_ty = operand_ty.errorUnionChild(); | 1811 | const payload_ty = operand_ty.errorUnionPayload(); |
| 1764 | if (!payload_ty.hasCodeGenBits()) { | 1812 | if (!payload_ty.hasCodeGenBits()) { |
| 1765 | try writer.print(" = {s}", .{deref_prefix}); | 1813 | try writer.print(" = {s}", .{deref_prefix}); |
| 1766 | try o.writeCValue(writer, operand); | 1814 | try o.writeCValue(writer, operand); |
src/codegen/wasm.zig+3-3| ... | @@ -646,7 +646,7 @@ pub const Context = struct { | ... | @@ -646,7 +646,7 @@ pub const Context = struct { |
| 646 | } }; | 646 | } }; |
| 647 | }, | 647 | }, |
| 648 | .ErrorUnion => { | 648 | .ErrorUnion => { |
| 649 | const payload_type = ty.errorUnionChild(); | 649 | const payload_type = ty.errorUnionPayload(); |
| 650 | const val_type = try self.genValtype(payload_type); | 650 | const val_type = try self.genValtype(payload_type); |
| 651 | 651 | ||
| 652 | // we emit the error value as the first local, and the payload as the following. | 652 | // we emit the error value as the first local, and the payload as the following. |
| ... | @@ -699,7 +699,7 @@ pub const Context = struct { | ... | @@ -699,7 +699,7 @@ pub const Context = struct { |
| 699 | .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}), | 699 | .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}), |
| 700 | .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}), | 700 | .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}), |
| 701 | .ErrorUnion => { | 701 | .ErrorUnion => { |
| 702 | const val_type = try self.genValtype(return_type.errorUnionChild()); | 702 | const val_type = try self.genValtype(return_type.errorUnionPayload()); |
| 703 | 703 | ||
| 704 | // write down the amount of return values | 704 | // write down the amount of return values |
| 705 | try leb.writeULEB128(writer, @as(u32, 2)); | 705 | try leb.writeULEB128(writer, @as(u32, 2)); |
| ... | @@ -1055,7 +1055,7 @@ pub const Context = struct { | ... | @@ -1055,7 +1055,7 @@ pub const Context = struct { |
| 1055 | .ErrorUnion => { | 1055 | .ErrorUnion => { |
| 1056 | const data = value.castTag(.error_union).?.data; | 1056 | const data = value.castTag(.error_union).?.data; |
| 1057 | const error_type = ty.errorUnionSet(); | 1057 | const error_type = ty.errorUnionSet(); |
| 1058 | const payload_type = ty.errorUnionChild(); | 1058 | const payload_type = ty.errorUnionPayload(); |
| 1059 | if (value.getError()) |_| { | 1059 | if (value.getError()) |_| { |
| 1060 | // write the error value | 1060 | // write the error value |
| 1061 | try self.emitConstant(data, error_type); | 1061 | try self.emitConstant(data, error_type); |
src/glibc.zig+1-1| ... | @@ -943,7 +943,7 @@ fn buildSharedLib( | ... | @@ -943,7 +943,7 @@ fn buildSharedLib( |
| 943 | .zig_lib_directory = comp.zig_lib_directory, | 943 | .zig_lib_directory = comp.zig_lib_directory, |
| 944 | .target = comp.getTarget(), | 944 | .target = comp.getTarget(), |
| 945 | .root_name = lib.name, | 945 | .root_name = lib.name, |
| 946 | .root_pkg = null, | 946 | .main_pkg = null, |
| 947 | .output_mode = .Lib, | 947 | .output_mode = .Lib, |
| 948 | .link_mode = .Dynamic, | 948 | .link_mode = .Dynamic, |
| 949 | .thread_pool = comp.thread_pool, | 949 | .thread_pool = comp.thread_pool, |
src/libcxx.zig+2-2| ... | @@ -169,7 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { | ... | @@ -169,7 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 169 | .zig_lib_directory = comp.zig_lib_directory, | 169 | .zig_lib_directory = comp.zig_lib_directory, |
| 170 | .target = target, | 170 | .target = target, |
| 171 | .root_name = root_name, | 171 | .root_name = root_name, |
| 172 | .root_pkg = null, | 172 | .main_pkg = null, |
| 173 | .output_mode = output_mode, | 173 | .output_mode = output_mode, |
| 174 | .thread_pool = comp.thread_pool, | 174 | .thread_pool = comp.thread_pool, |
| 175 | .libc_installation = comp.bin_file.options.libc_installation, | 175 | .libc_installation = comp.bin_file.options.libc_installation, |
| ... | @@ -301,7 +301,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { | ... | @@ -301,7 +301,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 301 | .zig_lib_directory = comp.zig_lib_directory, | 301 | .zig_lib_directory = comp.zig_lib_directory, |
| 302 | .target = target, | 302 | .target = target, |
| 303 | .root_name = root_name, | 303 | .root_name = root_name, |
| 304 | .root_pkg = null, | 304 | .main_pkg = null, |
| 305 | .output_mode = output_mode, | 305 | .output_mode = output_mode, |
| 306 | .thread_pool = comp.thread_pool, | 306 | .thread_pool = comp.thread_pool, |
| 307 | .libc_installation = comp.bin_file.options.libc_installation, | 307 | .libc_installation = comp.bin_file.options.libc_installation, |
src/libtsan.zig+1-1| ... | @@ -201,7 +201,7 @@ pub fn buildTsan(comp: *Compilation) !void { | ... | @@ -201,7 +201,7 @@ pub fn buildTsan(comp: *Compilation) !void { |
| 201 | .zig_lib_directory = comp.zig_lib_directory, | 201 | .zig_lib_directory = comp.zig_lib_directory, |
| 202 | .target = target, | 202 | .target = target, |
| 203 | .root_name = root_name, | 203 | .root_name = root_name, |
| 204 | .root_pkg = null, | 204 | .main_pkg = null, |
| 205 | .output_mode = output_mode, | 205 | .output_mode = output_mode, |
| 206 | .thread_pool = comp.thread_pool, | 206 | .thread_pool = comp.thread_pool, |
| 207 | .libc_installation = comp.bin_file.options.libc_installation, | 207 | .libc_installation = comp.bin_file.options.libc_installation, |
src/libunwind.zig+1-1| ... | @@ -101,7 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { | ... | @@ -101,7 +101,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { |
| 101 | .zig_lib_directory = comp.zig_lib_directory, | 101 | .zig_lib_directory = comp.zig_lib_directory, |
| 102 | .target = target, | 102 | .target = target, |
| 103 | .root_name = root_name, | 103 | .root_name = root_name, |
| 104 | .root_pkg = null, | 104 | .main_pkg = null, |
| 105 | .output_mode = output_mode, | 105 | .output_mode = output_mode, |
| 106 | .thread_pool = comp.thread_pool, | 106 | .thread_pool = comp.thread_pool, |
| 107 | .libc_installation = comp.bin_file.options.libc_installation, | 107 | .libc_installation = comp.bin_file.options.libc_installation, |
src/main.zig+15-15| ... | @@ -263,12 +263,12 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -263,12 +263,12 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | const usage_build_generic = | 265 | const usage_build_generic = |
| 266 | \\Usage: zig build-exe <options> [files] | 266 | \\Usage: zig build-exe [options] [files] |
| 267 | \\ zig build-lib <options> [files] | 267 | \\ zig build-lib [options] [files] |
| 268 | \\ zig build-obj <options> [files] | 268 | \\ zig build-obj [options] [files] |
| 269 | \\ zig test <options> [files] | 269 | \\ zig test [options] [files] |
| 270 | \\ zig run <options> [file] [-- [args]] | 270 | \\ zig run [options] [files] [-- [args]] |
| 271 | \\ zig translate-c <options> [file] | 271 | \\ zig translate-c [options] [file] |
| 272 | \\ | 272 | \\ |
| 273 | \\Supported file types: | 273 | \\Supported file types: |
| 274 | \\ .zig Zig source code | 274 | \\ .zig Zig source code |
| ... | @@ -1915,7 +1915,7 @@ fn buildOutputType( | ... | @@ -1915,7 +1915,7 @@ fn buildOutputType( |
| 1915 | }; | 1915 | }; |
| 1916 | defer emit_docs_resolved.deinit(); | 1916 | defer emit_docs_resolved.deinit(); |
| 1917 | 1917 | ||
| 1918 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { | 1918 | const main_pkg: ?*Package = if (root_src_file) |src_path| blk: { |
| 1919 | if (main_pkg_path) |p| { | 1919 | if (main_pkg_path) |p| { |
| 1920 | const rel_src_path = try fs.path.relative(gpa, p, src_path); | 1920 | const rel_src_path = try fs.path.relative(gpa, p, src_path); |
| 1921 | defer gpa.free(rel_src_path); | 1921 | defer gpa.free(rel_src_path); |
| ... | @@ -1924,10 +1924,10 @@ fn buildOutputType( | ... | @@ -1924,10 +1924,10 @@ fn buildOutputType( |
| 1924 | break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path)); | 1924 | break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path)); |
| 1925 | } | 1925 | } |
| 1926 | } else null; | 1926 | } else null; |
| 1927 | defer if (root_pkg) |p| p.destroy(gpa); | 1927 | defer if (main_pkg) |p| p.destroy(gpa); |
| 1928 | 1928 | ||
| 1929 | // Transfer packages added with --pkg-begin/--pkg-end to the root package | 1929 | // Transfer packages added with --pkg-begin/--pkg-end to the root package |
| 1930 | if (root_pkg) |pkg| { | 1930 | if (main_pkg) |pkg| { |
| 1931 | pkg.table = pkg_tree_root.table; | 1931 | pkg.table = pkg_tree_root.table; |
| 1932 | pkg_tree_root.table = .{}; | 1932 | pkg_tree_root.table = .{}; |
| 1933 | } | 1933 | } |
| ... | @@ -1980,7 +1980,7 @@ fn buildOutputType( | ... | @@ -1980,7 +1980,7 @@ fn buildOutputType( |
| 1980 | if (arg_mode == .run) { | 1980 | if (arg_mode == .run) { |
| 1981 | break :l global_cache_directory; | 1981 | break :l global_cache_directory; |
| 1982 | } | 1982 | } |
| 1983 | if (root_pkg) |pkg| { | 1983 | if (main_pkg) |pkg| { |
| 1984 | const cache_dir_path = try pkg.root_src_directory.join(arena, &[_][]const u8{"zig-cache"}); | 1984 | const cache_dir_path = try pkg.root_src_directory.join(arena, &[_][]const u8{"zig-cache"}); |
| 1985 | const dir = try pkg.root_src_directory.handle.makeOpenPath("zig-cache", .{}); | 1985 | const dir = try pkg.root_src_directory.handle.makeOpenPath("zig-cache", .{}); |
| 1986 | cleanup_local_cache_dir = dir; | 1986 | cleanup_local_cache_dir = dir; |
| ... | @@ -2018,7 +2018,7 @@ fn buildOutputType( | ... | @@ -2018,7 +2018,7 @@ fn buildOutputType( |
| 2018 | .dynamic_linker = target_info.dynamic_linker.get(), | 2018 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 2019 | .sysroot = sysroot, | 2019 | .sysroot = sysroot, |
| 2020 | .output_mode = output_mode, | 2020 | .output_mode = output_mode, |
| 2021 | .root_pkg = root_pkg, | 2021 | .main_pkg = main_pkg, |
| 2022 | .emit_bin = emit_bin_loc, | 2022 | .emit_bin = emit_bin_loc, |
| 2023 | .emit_h = emit_h_resolved.data, | 2023 | .emit_h = emit_h_resolved.data, |
| 2024 | .emit_asm = emit_asm_resolved.data, | 2024 | .emit_asm = emit_asm_resolved.data, |
| ... | @@ -2823,7 +2823,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2823,7 +2823,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2823 | const std_special = "std" ++ fs.path.sep_str ++ "special"; | 2823 | const std_special = "std" ++ fs.path.sep_str ++ "special"; |
| 2824 | const special_dir_path = try zig_lib_directory.join(arena, &[_][]const u8{std_special}); | 2824 | const special_dir_path = try zig_lib_directory.join(arena, &[_][]const u8{std_special}); |
| 2825 | 2825 | ||
| 2826 | var root_pkg: Package = .{ | 2826 | var main_pkg: Package = .{ |
| 2827 | .root_src_directory = .{ | 2827 | .root_src_directory = .{ |
| 2828 | .path = special_dir_path, | 2828 | .path = special_dir_path, |
| 2829 | .handle = zig_lib_directory.handle.openDir(std_special, .{}) catch |err| { | 2829 | .handle = zig_lib_directory.handle.openDir(std_special, .{}) catch |err| { |
| ... | @@ -2832,7 +2832,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2832,7 +2832,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2832 | }, | 2832 | }, |
| 2833 | .root_src_path = "build_runner.zig", | 2833 | .root_src_path = "build_runner.zig", |
| 2834 | }; | 2834 | }; |
| 2835 | defer root_pkg.root_src_directory.handle.close(); | 2835 | defer main_pkg.root_src_directory.handle.close(); |
| 2836 | 2836 | ||
| 2837 | var cleanup_build_dir: ?fs.Dir = null; | 2837 | var cleanup_build_dir: ?fs.Dir = null; |
| 2838 | defer if (cleanup_build_dir) |*dir| dir.close(); | 2838 | defer if (cleanup_build_dir) |*dir| dir.close(); |
| ... | @@ -2881,7 +2881,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2881,7 +2881,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2881 | .root_src_directory = build_directory, | 2881 | .root_src_directory = build_directory, |
| 2882 | .root_src_path = build_zig_basename, | 2882 | .root_src_path = build_zig_basename, |
| 2883 | }; | 2883 | }; |
| 2884 | try root_pkg.addAndAdopt(arena, "@build", &build_pkg); | 2884 | try main_pkg.addAndAdopt(arena, "@build", &build_pkg); |
| 2885 | 2885 | ||
| 2886 | var global_cache_directory: Compilation.Directory = l: { | 2886 | var global_cache_directory: Compilation.Directory = l: { |
| 2887 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); | 2887 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); |
| ... | @@ -2938,7 +2938,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -2938,7 +2938,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2938 | .is_native_abi = cross_target.isNativeAbi(), | 2938 | .is_native_abi = cross_target.isNativeAbi(), |
| 2939 | .dynamic_linker = target_info.dynamic_linker.get(), | 2939 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 2940 | .output_mode = .Exe, | 2940 | .output_mode = .Exe, |
| 2941 | .root_pkg = &root_pkg, | 2941 | .main_pkg = &main_pkg, |
| 2942 | .emit_bin = emit_bin, | 2942 | .emit_bin = emit_bin, |
| 2943 | .emit_h = null, | 2943 | .emit_h = null, |
| 2944 | .optimize_mode = .Debug, | 2944 | .optimize_mode = .Debug, |
src/musl.zig+1-1| ... | @@ -197,7 +197,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -197,7 +197,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 197 | .zig_lib_directory = comp.zig_lib_directory, | 197 | .zig_lib_directory = comp.zig_lib_directory, |
| 198 | .target = comp.getTarget(), | 198 | .target = comp.getTarget(), |
| 199 | .root_name = "c", | 199 | .root_name = "c", |
| 200 | .root_pkg = null, | 200 | .main_pkg = null, |
| 201 | .output_mode = .Lib, | 201 | .output_mode = .Lib, |
| 202 | .link_mode = .Dynamic, | 202 | .link_mode = .Dynamic, |
| 203 | .thread_pool = comp.thread_pool, | 203 | .thread_pool = comp.thread_pool, |
src/print_air.zig+4| ... | @@ -124,6 +124,8 @@ const Writer = struct { | ... | @@ -124,6 +124,8 @@ const Writer = struct { |
| 124 | .bool_and, | 124 | .bool_and, |
| 125 | .bool_or, | 125 | .bool_or, |
| 126 | .store, | 126 | .store, |
| 127 | .slice_elem_val, | ||
| 128 | .ptr_slice_elem_val, | ||
| 127 | => try w.writeBinOp(s, inst), | 129 | => try w.writeBinOp(s, inst), |
| 128 | 130 | ||
| 129 | .is_null, | 131 | .is_null, |
| ... | @@ -161,6 +163,8 @@ const Writer = struct { | ... | @@ -161,6 +163,8 @@ const Writer = struct { |
| 161 | .unwrap_errunion_err_ptr, | 163 | .unwrap_errunion_err_ptr, |
| 162 | .wrap_errunion_payload, | 164 | .wrap_errunion_payload, |
| 163 | .wrap_errunion_err, | 165 | .wrap_errunion_err, |
| 166 | .slice_ptr, | ||
| 167 | .slice_len, | ||
| 164 | => try w.writeTyOp(s, inst), | 168 | => try w.writeTyOp(s, inst), |
| 165 | 169 | ||
| 166 | .block, | 170 | .block, |
src/stage1.zig+1-1| ... | @@ -107,7 +107,7 @@ pub const Module = extern struct { | ... | @@ -107,7 +107,7 @@ pub const Module = extern struct { |
| 107 | test_name_prefix_ptr: [*]const u8, | 107 | test_name_prefix_ptr: [*]const u8, |
| 108 | test_name_prefix_len: usize, | 108 | test_name_prefix_len: usize, |
| 109 | userdata: usize, | 109 | userdata: usize, |
| 110 | root_pkg: *Pkg, | 110 | main_pkg: *Pkg, |
| 111 | main_progress_node: ?*std.Progress.Node, | 111 | main_progress_node: ?*std.Progress.Node, |
| 112 | code_model: CodeModel, | 112 | code_model: CodeModel, |
| 113 | subsystem: TargetSubsystem, | 113 | subsystem: TargetSubsystem, |
src/stage1/stage1.cpp+1-1| ... | @@ -126,7 +126,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { | ... | @@ -126,7 +126,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { |
| 126 | 126 | ||
| 127 | g->main_progress_node = stage1->main_progress_node; | 127 | g->main_progress_node = stage1->main_progress_node; |
| 128 | 128 | ||
| 129 | add_package(g, stage1->root_pkg, g->main_pkg); | 129 | add_package(g, stage1->main_pkg, g->main_pkg); |
| 130 | 130 | ||
| 131 | codegen_build_object(g); | 131 | codegen_build_object(g); |
| 132 | } | 132 | } |
src/stage1/stage1.h+1-1| ... | @@ -176,7 +176,7 @@ struct ZigStage1 { | ... | @@ -176,7 +176,7 @@ struct ZigStage1 { |
| 176 | size_t test_name_prefix_len; | 176 | size_t test_name_prefix_len; |
| 177 | 177 | ||
| 178 | void *userdata; | 178 | void *userdata; |
| 179 | struct ZigStage1Pkg *root_pkg; | 179 | struct ZigStage1Pkg *main_pkg; |
| 180 | struct Stage2ProgressNode *main_progress_node; | 180 | struct Stage2ProgressNode *main_progress_node; |
| 181 | 181 | ||
| 182 | enum CodeModel code_model; | 182 | enum CodeModel code_model; |
src/stage1/zig0.cpp+1-1| ... | @@ -465,7 +465,7 @@ int main(int argc, char **argv) { | ... | @@ -465,7 +465,7 @@ int main(int argc, char **argv) { |
| 465 | stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features; | 465 | stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features; |
| 466 | stage1->emit_o_ptr = emit_bin_path; | 466 | stage1->emit_o_ptr = emit_bin_path; |
| 467 | stage1->emit_o_len = strlen(emit_bin_path); | 467 | stage1->emit_o_len = strlen(emit_bin_path); |
| 468 | stage1->root_pkg = cur_pkg; | 468 | stage1->main_pkg = cur_pkg; |
| 469 | stage1->err_color = color; | 469 | stage1->err_color = color; |
| 470 | stage1->link_libc = link_libc; | 470 | stage1->link_libc = link_libc; |
| 471 | stage1->link_libcpp = link_libcpp; | 471 | stage1->link_libcpp = link_libcpp; |
src/test.zig+3-3| ... | @@ -848,11 +848,11 @@ pub const TestContext = struct { | ... | @@ -848,11 +848,11 @@ pub const TestContext = struct { |
| 848 | .path = local_cache_path, | 848 | .path = local_cache_path, |
| 849 | }; | 849 | }; |
| 850 | 850 | ||
| 851 | var root_pkg: Package = .{ | 851 | var main_pkg: Package = .{ |
| 852 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, | 852 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, |
| 853 | .root_src_path = tmp_src_path, | 853 | .root_src_path = tmp_src_path, |
| 854 | }; | 854 | }; |
| 855 | defer root_pkg.table.deinit(allocator); | 855 | defer main_pkg.table.deinit(allocator); |
| 856 | 856 | ||
| 857 | const bin_name = try std.zig.binNameAlloc(arena, .{ | 857 | const bin_name = try std.zig.binNameAlloc(arena, .{ |
| 858 | .root_name = "test_case", | 858 | .root_name = "test_case", |
| ... | @@ -896,7 +896,7 @@ pub const TestContext = struct { | ... | @@ -896,7 +896,7 @@ pub const TestContext = struct { |
| 896 | .optimize_mode = case.optimize_mode, | 896 | .optimize_mode = case.optimize_mode, |
| 897 | .emit_bin = emit_bin, | 897 | .emit_bin = emit_bin, |
| 898 | .emit_h = emit_h, | 898 | .emit_h = emit_h, |
| 899 | .root_pkg = &root_pkg, | 899 | .main_pkg = &main_pkg, |
| 900 | .keep_source_files_loaded = true, | 900 | .keep_source_files_loaded = true, |
| 901 | .object_format = case.object_format, | 901 | .object_format = case.object_format, |
| 902 | .is_native_os = case.target.isNativeOs(), | 902 | .is_native_os = case.target.isNativeOs(), |
src/type.zig+20-13| ... | @@ -525,9 +525,19 @@ pub const Type = extern union { | ... | @@ -525,9 +525,19 @@ pub const Type = extern union { |
| 525 | const b_data = b.castTag(.error_union).?.data; | 525 | const b_data = b.castTag(.error_union).?.data; |
| 526 | return a_data.error_set.eql(b_data.error_set) and a_data.payload.eql(b_data.payload); | 526 | return a_data.error_set.eql(b_data.error_set) and a_data.payload.eql(b_data.payload); |
| 527 | }, | 527 | }, |
| 528 | .ErrorSet => { | ||
| 529 | const a_is_anyerror = a.tag() == .anyerror; | ||
| 530 | const b_is_anyerror = b.tag() == .anyerror; | ||
| 531 | |||
| 532 | if (a_is_anyerror and b_is_anyerror) return true; | ||
| 533 | if (a_is_anyerror or b_is_anyerror) return false; | ||
| 534 | |||
| 535 | std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ | ||
| 536 | a.tag(), b.tag(), | ||
| 537 | }); | ||
| 538 | }, | ||
| 528 | .Opaque, | 539 | .Opaque, |
| 529 | .Float, | 540 | .Float, |
| 530 | .ErrorSet, | ||
| 531 | .BoundFn, | 541 | .BoundFn, |
| 532 | .Frame, | 542 | .Frame, |
| 533 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), | 543 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), |
| ... | @@ -1190,6 +1200,9 @@ pub const Type = extern union { | ... | @@ -1190,6 +1200,9 @@ pub const Type = extern union { |
| 1190 | .@"struct" => { | 1200 | .@"struct" => { |
| 1191 | // TODO introduce lazy value mechanism | 1201 | // TODO introduce lazy value mechanism |
| 1192 | const struct_obj = self.castTag(.@"struct").?.data; | 1202 | const struct_obj = self.castTag(.@"struct").?.data; |
| 1203 | if (struct_obj.known_has_bits) { | ||
| 1204 | return true; | ||
| 1205 | } | ||
| 1193 | assert(struct_obj.status == .have_field_types or | 1206 | assert(struct_obj.status == .have_field_types or |
| 1194 | struct_obj.status == .layout_wip or | 1207 | struct_obj.status == .layout_wip or |
| 1195 | struct_obj.status == .have_layout); | 1208 | struct_obj.status == .have_layout); |
| ... | @@ -1645,7 +1658,7 @@ pub const Type = extern union { | ... | @@ -1645,7 +1658,7 @@ pub const Type = extern union { |
| 1645 | } else if (!payload.payload.hasCodeGenBits()) { | 1658 | } else if (!payload.payload.hasCodeGenBits()) { |
| 1646 | return payload.error_set.abiSize(target); | 1659 | return payload.error_set.abiSize(target); |
| 1647 | } | 1660 | } |
| 1648 | @panic("TODO abiSize error union"); | 1661 | std.debug.panic("TODO abiSize error union {}", .{self}); |
| 1649 | }, | 1662 | }, |
| 1650 | }; | 1663 | }; |
| 1651 | } | 1664 | } |
| ... | @@ -2038,7 +2051,7 @@ pub const Type = extern union { | ... | @@ -2038,7 +2051,7 @@ pub const Type = extern union { |
| 2038 | return ty.optionalChild(&buf).isValidVarType(is_extern); | 2051 | return ty.optionalChild(&buf).isValidVarType(is_extern); |
| 2039 | }, | 2052 | }, |
| 2040 | .Pointer, .Array, .Vector => ty = ty.elemType(), | 2053 | .Pointer, .Array, .Vector => ty = ty.elemType(), |
| 2041 | .ErrorUnion => ty = ty.errorUnionChild(), | 2054 | .ErrorUnion => ty = ty.errorUnionPayload(), |
| 2042 | 2055 | ||
| 2043 | .Fn => @panic("TODO fn isValidVarType"), | 2056 | .Fn => @panic("TODO fn isValidVarType"), |
| 2044 | .Struct => { | 2057 | .Struct => { |
| ... | @@ -2119,13 +2132,10 @@ pub const Type = extern union { | ... | @@ -2119,13 +2132,10 @@ pub const Type = extern union { |
| 2119 | } | 2132 | } |
| 2120 | 2133 | ||
| 2121 | /// Asserts that the type is an error union. | 2134 | /// Asserts that the type is an error union. |
| 2122 | pub fn errorUnionChild(self: Type) Type { | 2135 | pub fn errorUnionPayload(self: Type) Type { |
| 2123 | return switch (self.tag()) { | 2136 | return switch (self.tag()) { |
| 2124 | .anyerror_void_error_union => Type.initTag(.anyerror), | 2137 | .anyerror_void_error_union => Type.initTag(.void), |
| 2125 | .error_union => { | 2138 | .error_union => self.castTag(.error_union).?.data.payload, |
| 2126 | const payload = self.castTag(.error_union).?; | ||
| 2127 | return payload.data.payload; | ||
| 2128 | }, | ||
| 2129 | else => unreachable, | 2139 | else => unreachable, |
| 2130 | }; | 2140 | }; |
| 2131 | } | 2141 | } |
| ... | @@ -2133,10 +2143,7 @@ pub const Type = extern union { | ... | @@ -2133,10 +2143,7 @@ pub const Type = extern union { |
| 2133 | pub fn errorUnionSet(self: Type) Type { | 2143 | pub fn errorUnionSet(self: Type) Type { |
| 2134 | return switch (self.tag()) { | 2144 | return switch (self.tag()) { |
| 2135 | .anyerror_void_error_union => Type.initTag(.anyerror), | 2145 | .anyerror_void_error_union => Type.initTag(.anyerror), |
| 2136 | .error_union => { | 2146 | .error_union => self.castTag(.error_union).?.data.error_set, |
| 2137 | const payload = self.castTag(.error_union).?; | ||
| 2138 | return payload.data.error_set; | ||
| 2139 | }, | ||
| 2140 | else => unreachable, | 2147 | else => unreachable, |
| 2141 | }; | 2148 | }; |
| 2142 | } | 2149 | } |
test/behavior.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | 2 | ||
| 3 | comptime { | 3 | test { |
| 4 | // Tests that pass for both. | 4 | // Tests that pass for both. |
| 5 | {} | 5 | {} |
| 6 | 6 |