| 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 | 21 | std.testing.zig_exe_path = args[1]; |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | pub fn main() anyerror!void { | |
| 24 | pub fn main() void { | |
| 25 | 25 | if (builtin.zig_is_stage2) { |
| 26 | return main2(); | |
| 26 | return main2() catch @panic("test failure"); | |
| 27 | 27 | } |
| 28 | 28 | processArgs(); |
| 29 | 29 | const test_fn_list = builtin.test_functions; |
src/Air.zig+29-1| ... | ... | @@ -247,6 +247,21 @@ pub const Inst = struct { |
| 247 | 247 | /// Given a pointer to a struct and a field index, returns a pointer to the field. |
| 248 | 248 | /// Uses the `ty_pl` field, payload is `StructField`. |
| 249 | 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 | 266 | pub fn fromCmpOp(op: std.math.CompareOperator) Tag { |
| 252 | 267 | return switch (op) { |
| ... | ... | @@ -450,6 +465,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 450 | 465 | .unwrap_errunion_err_ptr, |
| 451 | 466 | .wrap_errunion_payload, |
| 452 | 467 | .wrap_errunion_err, |
| 468 | .slice_ptr, | |
| 453 | 469 | => return air.getRefType(datas[inst].ty_op.ty), |
| 454 | 470 | |
| 455 | 471 | .loop, |
| ... | ... | @@ -465,12 +481,24 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 465 | 481 | .store, |
| 466 | 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 | 488 | .call => { |
| 471 | 489 | const callee_ty = air.typeOf(datas[inst].pl_op.operand); |
| 472 | 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 | 3470 | .fields_len = 0, |
| 3471 | 3471 | .body_len = 0, |
| 3472 | 3472 | .decls_len = 0, |
| 3473 | .known_has_bits = false, | |
| 3473 | 3474 | }); |
| 3474 | 3475 | return indexToRef(decl_inst); |
| 3475 | 3476 | } |
| ... | ... | @@ -3510,6 +3511,7 @@ fn structDeclInner( |
| 3510 | 3511 | var bit_bag = ArrayListUnmanaged(u32){}; |
| 3511 | 3512 | defer bit_bag.deinit(gpa); |
| 3512 | 3513 | |
| 3514 | var known_has_bits = false; | |
| 3513 | 3515 | var cur_bit_bag: u32 = 0; |
| 3514 | 3516 | var field_index: usize = 0; |
| 3515 | 3517 | for (container_decl.ast.members) |member_node| { |
| ... | ... | @@ -3657,6 +3659,8 @@ fn structDeclInner( |
| 3657 | 3659 | try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr); |
| 3658 | 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 | 3664 | const have_align = member.ast.align_expr != 0; |
| 3661 | 3665 | const have_value = member.ast.value_expr != 0; |
| 3662 | 3666 | const is_comptime = member.comptime_token != null; |
| ... | ... | @@ -3706,6 +3710,7 @@ fn structDeclInner( |
| 3706 | 3710 | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| 3707 | 3711 | .fields_len = @intCast(u32, field_index), |
| 3708 | 3712 | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 3713 | .known_has_bits = known_has_bits, | |
| 3709 | 3714 | }); |
| 3710 | 3715 | |
| 3711 | 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 | 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 | 8341 | /// Applies `rl` semantics to `inst`. Expressions which do not do their own handling of |
| 8154 | 8342 | /// result locations must call this function on their result. |
| 8155 | 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 | 9744 | fields_len: u32, |
| 9557 | 9745 | decls_len: u32, |
| 9558 | 9746 | layout: std.builtin.TypeInfo.ContainerLayout, |
| 9747 | known_has_bits: bool, | |
| 9559 | 9748 | }) !void { |
| 9560 | 9749 | const astgen = gz.astgen; |
| 9561 | 9750 | const gpa = astgen.gpa; |
| ... | ... | @@ -9585,6 +9774,7 @@ const GenZir = struct { |
| 9585 | 9774 | .has_body_len = args.body_len != 0, |
| 9586 | 9775 | .has_fields_len = args.fields_len != 0, |
| 9587 | 9776 | .has_decls_len = args.decls_len != 0, |
| 9777 | .known_has_bits = args.known_has_bits, | |
| 9588 | 9778 | .name_strategy = gz.anon_name_strategy, |
| 9589 | 9779 | .layout = args.layout, |
| 9590 | 9780 | }), |
src/Compilation.zig+44-26| ... | ... | @@ -622,7 +622,7 @@ pub const InitOptions = struct { |
| 622 | 622 | global_cache_directory: Directory, |
| 623 | 623 | target: Target, |
| 624 | 624 | root_name: []const u8, |
| 625 | root_pkg: ?*Package, | |
| 625 | main_pkg: ?*Package, | |
| 626 | 626 | output_mode: std.builtin.OutputMode, |
| 627 | 627 | thread_pool: *ThreadPool, |
| 628 | 628 | dynamic_linker: ?[]const u8 = null, |
| ... | ... | @@ -826,7 +826,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 826 | 826 | const ofmt = options.object_format orelse options.target.getObjectFormat(); |
| 827 | 827 | |
| 828 | 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 | 830 | // we may need to use stage1 for building compiler-rt and other dependencies. |
| 831 | 831 | |
| 832 | 832 | if (build_options.omit_stage2) |
| ... | ... | @@ -846,7 +846,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 846 | 846 | break :blk explicit; |
| 847 | 847 | |
| 848 | 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 | 850 | break :blk false; |
| 851 | 851 | |
| 852 | 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 | 929 | if (use_llvm) { |
| 930 | 930 | // If stage1 generates an object file, self-hosted linker is not |
| 931 | 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 | 935 | break :blk false; |
| ... | ... | @@ -1159,7 +1159,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1159 | 1159 | if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model); |
| 1160 | 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 | 1163 | // Options that are specific to zig source files, that cannot be |
| 1164 | 1164 | // modified between incremental updates. |
| 1165 | 1165 | var hash = cache.hash; |
| ... | ... | @@ -1169,13 +1169,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1169 | 1169 | // incremental compilation will handle it, but we do want to namespace different |
| 1170 | 1170 | // source file names because they are likely different compilations and therefore this |
| 1171 | 1171 | // would be likely to cause cache hits. |
| 1172 | hash.addBytes(root_pkg.root_src_path); | |
| 1173 | hash.addOptionalBytes(root_pkg.root_src_directory.path); | |
| 1172 | hash.addBytes(main_pkg.root_src_path); | |
| 1173 | hash.addOptionalBytes(main_pkg.root_src_directory.path); | |
| 1174 | 1174 | { |
| 1175 | 1175 | var local_arena = std.heap.ArenaAllocator.init(gpa); |
| 1176 | 1176 | defer local_arena.deinit(); |
| 1177 | 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 | 1180 | hash.add(valgrind); |
| 1181 | 1181 | hash.add(single_threaded); |
| ... | ... | @@ -1212,9 +1212,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1212 | 1212 | ); |
| 1213 | 1213 | errdefer std_pkg.destroy(gpa); |
| 1214 | 1214 | |
| 1215 | try root_pkg.addAndAdopt(gpa, "builtin", builtin_pkg); | |
| 1216 | try root_pkg.add(gpa, "root", root_pkg); | |
| 1217 | try root_pkg.addAndAdopt(gpa, "std", std_pkg); | |
| 1215 | const root_pkg = if (options.is_test) root_pkg: { | |
| 1216 | const test_pkg = try Package.createWithDir( | |
| 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 | 1236 | try std_pkg.add(gpa, "builtin", builtin_pkg); |
| 1220 | 1237 | try std_pkg.add(gpa, "root", root_pkg); |
| ... | ... | @@ -1258,6 +1275,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1258 | 1275 | module.* = .{ |
| 1259 | 1276 | .gpa = gpa, |
| 1260 | 1277 | .comp = comp, |
| 1278 | .main_pkg = main_pkg, | |
| 1261 | 1279 | .root_pkg = root_pkg, |
| 1262 | 1280 | .zig_cache_artifact_directory = zig_cache_artifact_directory, |
| 1263 | 1281 | .global_zir_cache = global_zir_cache, |
| ... | ... | @@ -1684,7 +1702,7 @@ pub fn update(self: *Compilation) !void { |
| 1684 | 1702 | |
| 1685 | 1703 | // Make sure std.zig is inside the import_table. We unconditionally need |
| 1686 | 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 | 1706 | _ = try module.importPkg(std_pkg); |
| 1689 | 1707 | |
| 1690 | 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 | 1710 | // so in order to run AstGen on the root source file we put it into the |
| 1693 | 1711 | // import_table here. |
| 1694 | 1712 | if (use_stage1) { |
| 1695 | _ = try module.importPkg(module.root_pkg); | |
| 1713 | _ = try module.importPkg(module.main_pkg); | |
| 1696 | 1714 | } |
| 1697 | 1715 | |
| 1698 | 1716 | // Put a work item in for every known source file to detect if |
| ... | ... | @@ -3873,7 +3891,7 @@ fn buildOutputFromZig( |
| 3873 | 3891 | var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{}); |
| 3874 | 3892 | defer special_dir.close(); |
| 3875 | 3893 | |
| 3876 | var root_pkg: Package = .{ | |
| 3894 | var main_pkg: Package = .{ | |
| 3877 | 3895 | .root_src_directory = .{ |
| 3878 | 3896 | .path = special_path, |
| 3879 | 3897 | .handle = special_dir, |
| ... | ... | @@ -3899,7 +3917,7 @@ fn buildOutputFromZig( |
| 3899 | 3917 | .zig_lib_directory = comp.zig_lib_directory, |
| 3900 | 3918 | .target = target, |
| 3901 | 3919 | .root_name = root_name, |
| 3902 | .root_pkg = &root_pkg, | |
| 3920 | .main_pkg = &main_pkg, | |
| 3903 | 3921 | .output_mode = output_mode, |
| 3904 | 3922 | .thread_pool = comp.thread_pool, |
| 3905 | 3923 | .libc_installation = comp.bin_file.options.libc_installation, |
| ... | ... | @@ -3969,8 +3987,8 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 3969 | 3987 | // Here we use the legacy stage1 C++ compiler to compile Zig code. |
| 3970 | 3988 | const mod = comp.bin_file.options.module.?; |
| 3971 | 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{ | |
| 3973 | mod.root_pkg.root_src_path, | |
| 3990 | const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{ | |
| 3991 | mod.main_pkg.root_src_path, | |
| 3974 | 3992 | }); |
| 3975 | 3993 | const zig_lib_dir = comp.zig_lib_directory.path.?; |
| 3976 | 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 | 4020 | _ = try man.addFile(main_zig_file, null); |
| 4003 | 4021 | { |
| 4004 | 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 | 4025 | man.hash.add(comp.bin_file.options.valgrind); |
| 4008 | 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 | 4063 | &prev_digest_buf, |
| 4046 | 4064 | ) catch |err| blk: { |
| 4047 | 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 | 4067 | std.fmt.fmtSliceHexLower(&digest), |
| 4050 | 4068 | @errorName(err), |
| 4051 | 4069 | }); |
| ... | ... | @@ -4057,7 +4075,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4057 | 4075 | break :hit; |
| 4058 | 4076 | |
| 4059 | 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 | 4079 | std.fmt.fmtSliceHexLower(&digest), |
| 4062 | 4080 | }); |
| 4063 | 4081 | var flags_bytes: [1]u8 = undefined; |
| ... | ... | @@ -4083,7 +4101,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4083 | 4101 | return; |
| 4084 | 4102 | } |
| 4085 | 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 | 4105 | std.fmt.fmtSliceHexLower(prev_digest), |
| 4088 | 4106 | std.fmt.fmtSliceHexLower(&digest), |
| 4089 | 4107 | }); |
| ... | ... | @@ -4109,7 +4127,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4109 | 4127 | |
| 4110 | 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 | 4132 | const stage1_module = stage1.create( |
| 4115 | 4133 | @enumToInt(comp.bin_file.options.optimize_mode), |
| ... | ... | @@ -4142,7 +4160,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4142 | 4160 | const emit_llvm_bc_path = try stage1LocPath(arena, comp.emit_llvm_bc, directory); |
| 4143 | 4161 | const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory); |
| 4144 | 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 | 4164 | const test_filter = comp.test_filter orelse ""[0..0]; |
| 4147 | 4165 | const test_name_prefix = comp.test_name_prefix orelse ""[0..0]; |
| 4148 | 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 | 4191 | .test_name_prefix_ptr = test_name_prefix.ptr, |
| 4174 | 4192 | .test_name_prefix_len = test_name_prefix.len, |
| 4175 | 4193 | .userdata = @ptrToInt(comp), |
| 4176 | .root_pkg = stage1_pkg, | |
| 4194 | .main_pkg = stage1_pkg, | |
| 4177 | 4195 | .code_model = @enumToInt(comp.bin_file.options.machine_code_model), |
| 4178 | 4196 | .subsystem = subsystem, |
| 4179 | 4197 | .err_color = @enumToInt(comp.color), |
| ... | ... | @@ -4239,7 +4257,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node |
| 4239 | 4257 | // means that the next invocation will have an unnecessary cache miss. |
| 4240 | 4258 | const stage1_flags_byte = @bitCast(u8, mod.stage1_flags); |
| 4241 | 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 | 4262 | var digest_plus_flags: [digest.len + 2]u8 = undefined; |
| 4245 | 4263 | digest_plus_flags[0..digest.len].* = digest; |
| ... | ... | @@ -4333,7 +4351,7 @@ pub fn build_crt_file( |
| 4333 | 4351 | .zig_lib_directory = comp.zig_lib_directory, |
| 4334 | 4352 | .target = target, |
| 4335 | 4353 | .root_name = root_name, |
| 4336 | .root_pkg = null, | |
| 4354 | .main_pkg = null, | |
| 4337 | 4355 | .output_mode = output_mode, |
| 4338 | 4356 | .thread_pool = comp.thread_pool, |
| 4339 | 4357 | .libc_installation = comp.bin_file.options.libc_installation, |
src/Liveness.zig+4| ... | ... | @@ -243,6 +243,8 @@ fn analyzeInst( |
| 243 | 243 | .bool_and, |
| 244 | 244 | .bool_or, |
| 245 | 245 | .store, |
| 246 | .slice_elem_val, | |
| 247 | .ptr_slice_elem_val, | |
| 246 | 248 | => { |
| 247 | 249 | const o = inst_datas[inst].bin_op; |
| 248 | 250 | return trackOperands(a, new_set, inst, main_tomb, .{ o.lhs, o.rhs, .none }); |
| ... | ... | @@ -273,6 +275,8 @@ fn analyzeInst( |
| 273 | 275 | .unwrap_errunion_err_ptr, |
| 274 | 276 | .wrap_errunion_payload, |
| 275 | 277 | .wrap_errunion_err, |
| 278 | .slice_ptr, | |
| 279 | .slice_len, | |
| 276 | 280 | => { |
| 277 | 281 | const o = inst_datas[inst].ty_op; |
| 278 | 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 | 35 | |
| 36 | 36 | /// Where our incremental compilation metadata serialization will go. |
| 37 | 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 | 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 | 44 | /// Used by AstGen worker to load and store ZIR cache. |
| 42 | 45 | global_zir_cache: Compilation.Directory, |
| ... | ... | @@ -598,6 +601,9 @@ pub const Struct = struct { |
| 598 | 601 | layout_wip, |
| 599 | 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 | 608 | pub const Field = struct { |
| 603 | 609 | /// Uses `noreturn` to indicate `anytype`. |
| ... | ... | @@ -2048,19 +2054,22 @@ pub fn deinit(mod: *Module) void { |
| 2048 | 2054 | |
| 2049 | 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 | 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 | 2060 | gpa.free(kv.key); |
| 2055 | 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 | 2064 | gpa.free(kv.key); |
| 2059 | 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 | 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 | 2074 | mod.compile_log_text.deinit(gpa); |
| 2066 | 2075 | |
| ... | ... | @@ -2148,7 +2157,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void { |
| 2148 | 2157 | |
| 2149 | 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 | 2161 | const digest = hash: { |
| 2153 | 2162 | var path_hash: Cache.HashHelper = .{}; |
| 2154 | 2163 | path_hash.addBytes(build_options.version); |
| ... | ... | @@ -2792,6 +2801,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { |
| 2792 | 2801 | .zir_index = undefined, // set below |
| 2793 | 2802 | .layout = .Auto, |
| 2794 | 2803 | .status = .none, |
| 2804 | .known_has_bits = undefined, | |
| 2795 | 2805 | .namespace = .{ |
| 2796 | 2806 | .parent = null, |
| 2797 | 2807 | .ty = struct_ty, |
| ... | ... | @@ -3301,10 +3311,23 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi |
| 3301 | 3311 | gop.value_ptr.* = new_decl; |
| 3302 | 3312 | // Exported decls, comptime decls, usingnamespace decls, and |
| 3303 | 3313 | // test decls if in test mode, get analyzed. |
| 3314 | const decl_pkg = namespace.file_scope.pkg; | |
| 3304 | 3315 | const want_analysis = is_exported or switch (decl_name_index) { |
| 3305 | 3316 | 0 => true, // comptime decl |
| 3306 | 1 => mod.comp.bin_file.options.is_test, // test decl | |
| 3307 | else => is_named_test and mod.comp.bin_file.options.is_test, | |
| 3317 | 1 => blk: { | |
| 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 | 3332 | if (want_analysis) { |
| 3310 | 3333 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
src/Sema.zig+125-49| ... | ... | @@ -768,6 +768,8 @@ pub fn analyzeStructDecl( |
| 768 | 768 | assert(extended.opcode == .struct_decl); |
| 769 | 769 | const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); |
| 770 | 770 | |
| 771 | struct_obj.known_has_bits = small.known_has_bits; | |
| 772 | ||
| 771 | 773 | var extra_index: usize = extended.operand; |
| 772 | 774 | extra_index += @boolToInt(small.has_src_node); |
| 773 | 775 | extra_index += @boolToInt(small.has_body_len); |
| ... | ... | @@ -812,6 +814,7 @@ fn zirStructDecl( |
| 812 | 814 | .zir_index = inst, |
| 813 | 815 | .layout = small.layout, |
| 814 | 816 | .status = .none, |
| 817 | .known_has_bits = undefined, | |
| 815 | 818 | .namespace = .{ |
| 816 | 819 | .parent = sema.owner_decl.namespace, |
| 817 | 820 | .ty = struct_ty, |
| ... | ... | @@ -1259,8 +1262,13 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1259 | 1262 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 1260 | 1263 | const src = inst_data.src(); |
| 1261 | 1264 | const array_ptr = sema.resolveInst(inst_data.operand); |
| 1265 | const array_ptr_src = src; | |
| 1262 | 1266 | |
| 1263 | 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 | 1272 | if (!elem_ty.isIndexable()) { |
| 1265 | 1273 | const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node }; |
| 1266 | 1274 | const msg = msg: { |
| ... | ... | @@ -1283,7 +1291,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 1283 | 1291 | return sema.mod.failWithOwnedErrorMsg(&block.base, msg); |
| 1284 | 1292 | } |
| 1285 | 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 | 1295 | return sema.analyzeLoad(block, src, result_ptr, result_ptr_src); |
| 1288 | 1296 | } |
| 1289 | 1297 | |
| ... | ... | @@ -2928,17 +2936,15 @@ fn zirErrUnionPayload( |
| 2928 | 2936 | return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name}); |
| 2929 | 2937 | } |
| 2930 | 2938 | const data = val.castTag(.error_union).?.data; |
| 2931 | return sema.addConstant( | |
| 2932 | operand_ty.castTag(.error_union).?.data.payload, | |
| 2933 | data, | |
| 2934 | ); | |
| 2939 | const result_ty = operand_ty.errorUnionPayload(); | |
| 2940 | return sema.addConstant(result_ty, data); | |
| 2935 | 2941 | } |
| 2936 | 2942 | try sema.requireRuntimeBlock(block, src); |
| 2937 | 2943 | if (safety_check and block.wantSafety()) { |
| 2938 | 2944 | const is_non_err = try block.addUnOp(.is_err, operand); |
| 2939 | 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 | 2948 | return block.addTyOp(.unwrap_errunion_payload, result_ty, operand); |
| 2943 | 2949 | } |
| 2944 | 2950 | |
| ... | ... | @@ -2961,7 +2967,8 @@ fn zirErrUnionPayloadPtr( |
| 2961 | 2967 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) |
| 2962 | 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 | 2973 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 2967 | 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 | 3006 | if (operand_ty.zigTypeTag() != .ErrorUnion) |
| 3000 | 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 | 3011 | if (try sema.resolveDefinedValue(block, src, operand)) |val| { |
| 3005 | 3012 | assert(val.getError() != null); |
| ... | ... | @@ -3025,7 +3032,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co |
| 3025 | 3032 | if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) |
| 3026 | 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 | 3037 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 3031 | 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 | 3055 | const operand_ty = sema.typeOf(operand); |
| 3049 | 3056 | if (operand_ty.zigTypeTag() != .ErrorUnion) |
| 3050 | 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 | 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 | 3467 | |
| 3461 | 3468 | const bin_inst = sema.code.instructions.items(.data)[inst].bin; |
| 3462 | 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 | 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); | |
| 3470 | return sema.analyzeLoad(block, sema.src, result_ptr, sema.src); | |
| 3471 | return sema.elemVal(block, sema.src, array, elem_index, sema.src); | |
| 3471 | 3472 | } |
| 3472 | 3473 | |
| 3473 | 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 | 3480 | const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node }; |
| 3480 | 3481 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 3481 | 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 | 3483 | const elem_index = sema.resolveInst(extra.rhs); |
| 3488 | const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | |
| 3489 | return sema.analyzeLoad(block, src, result_ptr, src); | |
| 3484 | return sema.elemVal(block, src, array, elem_index, elem_index_src); | |
| 3490 | 3485 | } |
| 3491 | 3486 | |
| 3492 | 3487 | fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | ... | @@ -5338,7 +5333,7 @@ fn zirBoolBr( |
| 5338 | 5333 | |
| 5339 | 5334 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + |
| 5340 | 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 | 5338 | const cond_br_payload = sema.addExtraAssumeCapacity(Air.CondBr{ |
| 5344 | 5339 | .then_body_len = @intCast(u32, then_block.instructions.items.len), |
| ... | ... | @@ -6217,8 +6212,9 @@ fn zirVarExtended( |
| 6217 | 6212 | const init_val: Value = if (small.has_init) blk: { |
| 6218 | 6213 | const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 6219 | 6214 | extra_index += 1; |
| 6220 | const init_tv = try sema.resolveInstConst(block, init_src, init_ref); | |
| 6221 | break :blk init_tv.val; | |
| 6215 | const init_air_inst = sema.resolveInst(init_ref); | |
| 6216 | break :blk (try sema.resolvePossiblyUndefinedValue(block, init_src, init_air_inst)) orelse | |
| 6217 | return sema.failWithNeededComptime(block, init_src); | |
| 6222 | 6218 | } else Value.initTag(.unreachable_value); |
| 6223 | 6219 | |
| 6224 | 6220 | if (!var_ty.isValidVarType(small.is_extern)) { |
| ... | ... | @@ -6586,7 +6582,30 @@ fn namedFieldPtr( |
| 6586 | 6582 | }, |
| 6587 | 6583 | .Pointer => { |
| 6588 | 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 | 6609 | .Array => { |
| 6591 | 6610 | if (mem.eql(u8, field_name, "len")) { |
| 6592 | 6611 | return sema.addConstant( |
| ... | ... | @@ -6836,6 +6855,50 @@ fn elemPtr( |
| 6836 | 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 | 6902 | fn elemPtrArray( |
| 6840 | 6903 | sema: *Sema, |
| 6841 | 6904 | block: *Scope.Block, |
| ... | ... | @@ -6896,11 +6959,6 @@ fn coerce( |
| 6896 | 6959 | } |
| 6897 | 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 | 6962 | // comptime known number to other number |
| 6905 | 6963 | if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| |
| 6906 | 6964 | return some; |
| ... | ... | @@ -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 | 7093 | else => {}, |
| 7032 | 7094 | } |
| 7033 | 7095 | |
| ... | ... | @@ -7257,16 +7319,13 @@ fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedVal |
| 7257 | 7319 | const gpa = sema.gpa; |
| 7258 | 7320 | try sema.requireRuntimeBlock(block, src); |
| 7259 | 7321 | try sema.air_variables.append(gpa, variable); |
| 7260 | const result_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); | |
| 7261 | try sema.air_instructions.append(gpa, .{ | |
| 7322 | return block.addInst(.{ | |
| 7262 | 7323 | .tag = .varptr, |
| 7263 | 7324 | .data = .{ .ty_pl = .{ |
| 7264 | 7325 | .ty = try sema.addType(ty), |
| 7265 | 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 | 7331 | fn analyzeRef( |
| ... | ... | @@ -7309,6 +7368,22 @@ fn analyzeLoad( |
| 7309 | 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 | 7387 | fn analyzeIsNull( |
| 7313 | 7388 | sema: *Sema, |
| 7314 | 7389 | block: *Scope.Block, |
| ... | ... | @@ -7645,27 +7720,28 @@ fn wrapErrorUnion( |
| 7645 | 7720 | inst_src: LazySrcLoc, |
| 7646 | 7721 | ) !Air.Inst.Ref { |
| 7647 | 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 | 7725 | if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| { |
| 7650 | 7726 | if (inst_ty.zigTypeTag() != .ErrorSet) { |
| 7651 | _ = try sema.coerce(block, err_union.data.payload, inst, inst_src); | |
| 7652 | } else switch (err_union.data.error_set.tag()) { | |
| 7727 | _ = try sema.coerce(block, dest_payload_ty, inst, inst_src); | |
| 7728 | } else switch (dest_err_set_ty.tag()) { | |
| 7653 | 7729 | .anyerror => {}, |
| 7654 | 7730 | .error_set_single => { |
| 7655 | 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 | 7733 | if (!mem.eql(u8, expected_name, n)) { |
| 7658 | 7734 | return sema.mod.fail( |
| 7659 | 7735 | &block.base, |
| 7660 | 7736 | inst_src, |
| 7661 | 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 | 7742 | .error_set => { |
| 7667 | 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 | 7745 | const names = error_set.names_ptr[0..error_set.names_len]; |
| 7670 | 7746 | // TODO this is O(N). I'm putting off solving this until we solve inferred |
| 7671 | 7747 | // error sets at the same time. |
| ... | ... | @@ -7677,19 +7753,19 @@ fn wrapErrorUnion( |
| 7677 | 7753 | &block.base, |
| 7678 | 7754 | inst_src, |
| 7679 | 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 | 7760 | .error_set_inferred => { |
| 7685 | 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 | 7763 | if (!map.contains(expected_name)) { |
| 7688 | 7764 | return sema.mod.fail( |
| 7689 | 7765 | &block.base, |
| 7690 | 7766 | inst_src, |
| 7691 | 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 | 7780 | |
| 7705 | 7781 | // we are coercing from E to E!T |
| 7706 | 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 | 7784 | return block.addTyOp(.wrap_errunion_err, dest_type, coerced); |
| 7709 | 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 | 7787 | return block.addTyOp(.wrap_errunion_payload, dest_type, coerced); |
| 7712 | 7788 | } |
| 7713 | 7789 | } |
| ... | ... | @@ -7857,7 +7933,7 @@ fn getBuiltin( |
| 7857 | 7933 | name: []const u8, |
| 7858 | 7934 | ) CompileError!Air.Inst.Ref { |
| 7859 | 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 | 7937 | const std_file = (mod.importPkg(std_pkg) catch unreachable).file; |
| 7862 | 7938 | const opt_builtin_inst = try sema.analyzeNamespaceLookup( |
| 7863 | 7939 | block, |
src/Zir.zig+3-1| ... | ... | @@ -2462,9 +2462,10 @@ pub const Inst = struct { |
| 2462 | 2462 | has_body_len: bool, |
| 2463 | 2463 | has_fields_len: bool, |
| 2464 | 2464 | has_decls_len: bool, |
| 2465 | known_has_bits: bool, | |
| 2465 | 2466 | name_strategy: NameStrategy, |
| 2466 | 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 | 3544 | break :blk decls_len; |
| 3544 | 3545 | } else 0; |
| 3545 | 3546 | |
| 3547 | try self.writeFlag(stream, "known_has_bits, ", small.known_has_bits); | |
| 3546 | 3548 | try stream.print("{s}, {s}, ", .{ |
| 3547 | 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 | 853 | .struct_field_ptr=> try self.airStructFieldPtr(inst), |
| 854 | 854 | .switch_br => try self.airSwitch(inst), |
| 855 | 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 | 862 | .constant => unreachable, // excluded from function bodies |
| 858 | 863 | .const_ty => unreachable, // excluded from function bodies |
| ... | ... | @@ -1333,6 +1338,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1333 | 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 | 1373 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { |
| 1337 | 1374 | if (!self.liveness.operandDies(inst, op_index)) |
| 1338 | 1375 | return false; |
src/codegen/c.zig+89-41| ... | ... | @@ -237,7 +237,8 @@ pub const DeclGen = struct { |
| 237 | 237 | // This should lower to 0xaa bytes in safe modes, and for unsafe modes should |
| 238 | 238 | // lower to leaving variables uninitialized (that might need to be implemented |
| 239 | 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 | 243 | switch (t.zigTypeTag()) { |
| 243 | 244 | .Int => { |
| ... | ... | @@ -361,18 +362,27 @@ pub const DeclGen = struct { |
| 361 | 362 | } |
| 362 | 363 | }, |
| 363 | 364 | .ErrorSet => { |
| 364 | const payload = val.castTag(.@"error").?; | |
| 365 | // error values will be #defined at the top of the file | |
| 366 | return writer.print("zig_error_{s}", .{payload.data.name}); | |
| 365 | switch (val.tag()) { | |
| 366 | .@"error" => { | |
| 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 | 378 | .ErrorUnion => { |
| 369 | 379 | const error_type = t.errorUnionSet(); |
| 370 | const payload_type = t.errorUnionChild(); | |
| 371 | const data = val.castTag(.error_union).?.data; | |
| 380 | const payload_type = t.errorUnionPayload(); | |
| 381 | const sub_val = val.castTag(.error_union).?.data; | |
| 372 | 382 | |
| 373 | 383 | if (!payload_type.hasCodeGenBits()) { |
| 374 | 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 | 388 | try writer.writeByte('('); |
| ... | ... | @@ -383,7 +393,7 @@ pub const DeclGen = struct { |
| 383 | 393 | try dg.renderValue( |
| 384 | 394 | writer, |
| 385 | 395 | error_type, |
| 386 | data, | |
| 396 | sub_val, | |
| 387 | 397 | ); |
| 388 | 398 | try writer.writeAll(" }"); |
| 389 | 399 | } else { |
| ... | ... | @@ -391,7 +401,7 @@ pub const DeclGen = struct { |
| 391 | 401 | try dg.renderValue( |
| 392 | 402 | writer, |
| 393 | 403 | payload_type, |
| 394 | data, | |
| 404 | sub_val, | |
| 395 | 405 | ); |
| 396 | 406 | try writer.writeAll(", .error = 0 }"); |
| 397 | 407 | } |
| ... | ... | @@ -616,7 +626,7 @@ pub const DeclGen = struct { |
| 616 | 626 | if (dg.typedefs.get(t)) |some| { |
| 617 | 627 | return w.writeAll(some.name); |
| 618 | 628 | } |
| 619 | const child_type = t.errorUnionChild(); | |
| 629 | const child_type = t.errorUnionPayload(); | |
| 620 | 630 | const err_set_type = t.errorUnionSet(); |
| 621 | 631 | |
| 622 | 632 | if (!child_type.hasCodeGenBits()) { |
| ... | ... | @@ -926,6 +936,11 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM |
| 926 | 936 | .ref => try airRef(o, inst), |
| 927 | 937 | .struct_field_ptr => try airStructFieldPtr(o, inst), |
| 928 | 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 | 945 | .unwrap_errunion_payload => try airUnwrapErrUnionPay(o, inst), |
| 931 | 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 | 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 | 997 | fn airVarPtr(o: *Object, inst: Air.Inst.Index) !CValue { |
| 952 | 998 | const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; |
| 953 | 999 | const variable = o.air.variables[ty_pl.payload]; |
| ... | ... | @@ -1233,6 +1279,20 @@ fn airCall(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1233 | 1279 | const pl_op = o.air.instructions.items(.data)[inst].pl_op; |
| 1234 | 1280 | const extra = o.air.extraData(Air.Call, pl_op.payload); |
| 1235 | 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 | 1297 | if (o.air.value(pl_op.operand)) |func_val| { |
| 1238 | 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 | 1302 | else |
| 1243 | 1303 | unreachable; |
| 1244 | 1304 | |
| 1245 | const fn_ty = fn_decl.ty; | |
| 1246 | const ret_ty = fn_ty.fnReturnType(); | |
| 1247 | const unused_result = o.liveness.isUnused(inst); | |
| 1248 | var result_local: CValue = .none; | |
| 1305 | try writer.writeAll(mem.spanZ(fn_decl.name)); | |
| 1306 | } else { | |
| 1307 | const callee = try o.resolveInst(pl_op.operand); | |
| 1308 | try o.writeCValue(writer, callee); | |
| 1309 | } | |
| 1249 | 1310 | |
| 1250 | const writer = o.writer(); | |
| 1251 | if (unused_result) { | |
| 1252 | if (ret_ty.hasCodeGenBits()) { | |
| 1253 | try writer.print("(void)", .{}); | |
| 1254 | } | |
| 1255 | } else { | |
| 1256 | result_local = try o.allocLocal(ret_ty, .Const); | |
| 1257 | try writer.writeAll(" = "); | |
| 1311 | try writer.writeAll("("); | |
| 1312 | for (args) |arg, i| { | |
| 1313 | if (i != 0) { | |
| 1314 | try writer.writeAll(", "); | |
| 1258 | 1315 | } |
| 1259 | const fn_name = mem.spanZ(fn_decl.name); | |
| 1260 | try writer.print("{s}(", .{fn_name}); | |
| 1261 | for (args) |arg, i| { | |
| 1262 | if (i != 0) { | |
| 1263 | try writer.writeAll(", "); | |
| 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 | } | |
| 1316 | if (o.air.value(arg)) |val| { | |
| 1317 | try o.dg.renderValue(writer, o.air.typeOf(arg), val); | |
| 1318 | } else { | |
| 1319 | const val = try o.resolveInst(arg); | |
| 1320 | try o.writeCValue(writer, val); | |
| 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 | 1327 | fn airDbgStmt(o: *Object, inst: Air.Inst.Index) !CValue { |
| ... | ... | @@ -1643,7 +1691,7 @@ fn airUnwrapErrUnionErr(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1643 | 1691 | const operand = try o.resolveInst(ty_op.operand); |
| 1644 | 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 | 1695 | if (!payload_ty.hasCodeGenBits()) { |
| 1648 | 1696 | if (operand_ty.zigTypeTag() == .Pointer) { |
| 1649 | 1697 | const local = try o.allocLocal(inst_ty, .Const); |
| ... | ... | @@ -1675,7 +1723,7 @@ fn airUnwrapErrUnionPay(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1675 | 1723 | const operand = try o.resolveInst(ty_op.operand); |
| 1676 | 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 | 1727 | if (!payload_ty.hasCodeGenBits()) { |
| 1680 | 1728 | return CValue.none; |
| 1681 | 1729 | } |
| ... | ... | @@ -1760,7 +1808,7 @@ fn airIsErr( |
| 1760 | 1808 | const operand = try o.resolveInst(un_op); |
| 1761 | 1809 | const operand_ty = o.air.typeOf(un_op); |
| 1762 | 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 | 1812 | if (!payload_ty.hasCodeGenBits()) { |
| 1765 | 1813 | try writer.print(" = {s}", .{deref_prefix}); |
| 1766 | 1814 | try o.writeCValue(writer, operand); |
src/codegen/wasm.zig+3-3| ... | ... | @@ -646,7 +646,7 @@ pub const Context = struct { |
| 646 | 646 | } }; |
| 647 | 647 | }, |
| 648 | 648 | .ErrorUnion => { |
| 649 | const payload_type = ty.errorUnionChild(); | |
| 649 | const payload_type = ty.errorUnionPayload(); | |
| 650 | 650 | const val_type = try self.genValtype(payload_type); |
| 651 | 651 | |
| 652 | 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 | 699 | .Struct => return self.fail("TODO: Implement struct as return type for wasm", .{}), |
| 700 | 700 | .Optional => return self.fail("TODO: Implement optionals as return type for wasm", .{}), |
| 701 | 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 | 704 | // write down the amount of return values |
| 705 | 705 | try leb.writeULEB128(writer, @as(u32, 2)); |
| ... | ... | @@ -1055,7 +1055,7 @@ pub const Context = struct { |
| 1055 | 1055 | .ErrorUnion => { |
| 1056 | 1056 | const data = value.castTag(.error_union).?.data; |
| 1057 | 1057 | const error_type = ty.errorUnionSet(); |
| 1058 | const payload_type = ty.errorUnionChild(); | |
| 1058 | const payload_type = ty.errorUnionPayload(); | |
| 1059 | 1059 | if (value.getError()) |_| { |
| 1060 | 1060 | // write the error value |
| 1061 | 1061 | try self.emitConstant(data, error_type); |
src/glibc.zig+1-1| ... | ... | @@ -943,7 +943,7 @@ fn buildSharedLib( |
| 943 | 943 | .zig_lib_directory = comp.zig_lib_directory, |
| 944 | 944 | .target = comp.getTarget(), |
| 945 | 945 | .root_name = lib.name, |
| 946 | .root_pkg = null, | |
| 946 | .main_pkg = null, | |
| 947 | 947 | .output_mode = .Lib, |
| 948 | 948 | .link_mode = .Dynamic, |
| 949 | 949 | .thread_pool = comp.thread_pool, |
src/libcxx.zig+2-2| ... | ... | @@ -169,7 +169,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { |
| 169 | 169 | .zig_lib_directory = comp.zig_lib_directory, |
| 170 | 170 | .target = target, |
| 171 | 171 | .root_name = root_name, |
| 172 | .root_pkg = null, | |
| 172 | .main_pkg = null, | |
| 173 | 173 | .output_mode = output_mode, |
| 174 | 174 | .thread_pool = comp.thread_pool, |
| 175 | 175 | .libc_installation = comp.bin_file.options.libc_installation, |
| ... | ... | @@ -301,7 +301,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { |
| 301 | 301 | .zig_lib_directory = comp.zig_lib_directory, |
| 302 | 302 | .target = target, |
| 303 | 303 | .root_name = root_name, |
| 304 | .root_pkg = null, | |
| 304 | .main_pkg = null, | |
| 305 | 305 | .output_mode = output_mode, |
| 306 | 306 | .thread_pool = comp.thread_pool, |
| 307 | 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 | 201 | .zig_lib_directory = comp.zig_lib_directory, |
| 202 | 202 | .target = target, |
| 203 | 203 | .root_name = root_name, |
| 204 | .root_pkg = null, | |
| 204 | .main_pkg = null, | |
| 205 | 205 | .output_mode = output_mode, |
| 206 | 206 | .thread_pool = comp.thread_pool, |
| 207 | 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 | 101 | .zig_lib_directory = comp.zig_lib_directory, |
| 102 | 102 | .target = target, |
| 103 | 103 | .root_name = root_name, |
| 104 | .root_pkg = null, | |
| 104 | .main_pkg = null, | |
| 105 | 105 | .output_mode = output_mode, |
| 106 | 106 | .thread_pool = comp.thread_pool, |
| 107 | 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 | 263 | } |
| 264 | 264 | |
| 265 | 265 | const usage_build_generic = |
| 266 | \\Usage: zig build-exe <options> [files] | |
| 267 | \\ zig build-lib <options> [files] | |
| 268 | \\ zig build-obj <options> [files] | |
| 269 | \\ zig test <options> [files] | |
| 270 | \\ zig run <options> [file] [-- [args]] | |
| 271 | \\ zig translate-c <options> [file] | |
| 266 | \\Usage: zig build-exe [options] [files] | |
| 267 | \\ zig build-lib [options] [files] | |
| 268 | \\ zig build-obj [options] [files] | |
| 269 | \\ zig test [options] [files] | |
| 270 | \\ zig run [options] [files] [-- [args]] | |
| 271 | \\ zig translate-c [options] [file] | |
| 272 | 272 | \\ |
| 273 | 273 | \\Supported file types: |
| 274 | 274 | \\ .zig Zig source code |
| ... | ... | @@ -1915,7 +1915,7 @@ fn buildOutputType( |
| 1915 | 1915 | }; |
| 1916 | 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 | 1919 | if (main_pkg_path) |p| { |
| 1920 | 1920 | const rel_src_path = try fs.path.relative(gpa, p, src_path); |
| 1921 | 1921 | defer gpa.free(rel_src_path); |
| ... | ... | @@ -1924,10 +1924,10 @@ fn buildOutputType( |
| 1924 | 1924 | break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path)); |
| 1925 | 1925 | } |
| 1926 | 1926 | } else null; |
| 1927 | defer if (root_pkg) |p| p.destroy(gpa); | |
| 1927 | defer if (main_pkg) |p| p.destroy(gpa); | |
| 1928 | 1928 | |
| 1929 | 1929 | // Transfer packages added with --pkg-begin/--pkg-end to the root package |
| 1930 | if (root_pkg) |pkg| { | |
| 1930 | if (main_pkg) |pkg| { | |
| 1931 | 1931 | pkg.table = pkg_tree_root.table; |
| 1932 | 1932 | pkg_tree_root.table = .{}; |
| 1933 | 1933 | } |
| ... | ... | @@ -1980,7 +1980,7 @@ fn buildOutputType( |
| 1980 | 1980 | if (arg_mode == .run) { |
| 1981 | 1981 | break :l global_cache_directory; |
| 1982 | 1982 | } |
| 1983 | if (root_pkg) |pkg| { | |
| 1983 | if (main_pkg) |pkg| { | |
| 1984 | 1984 | const cache_dir_path = try pkg.root_src_directory.join(arena, &[_][]const u8{"zig-cache"}); |
| 1985 | 1985 | const dir = try pkg.root_src_directory.handle.makeOpenPath("zig-cache", .{}); |
| 1986 | 1986 | cleanup_local_cache_dir = dir; |
| ... | ... | @@ -2018,7 +2018,7 @@ fn buildOutputType( |
| 2018 | 2018 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 2019 | 2019 | .sysroot = sysroot, |
| 2020 | 2020 | .output_mode = output_mode, |
| 2021 | .root_pkg = root_pkg, | |
| 2021 | .main_pkg = main_pkg, | |
| 2022 | 2022 | .emit_bin = emit_bin_loc, |
| 2023 | 2023 | .emit_h = emit_h_resolved.data, |
| 2024 | 2024 | .emit_asm = emit_asm_resolved.data, |
| ... | ... | @@ -2823,7 +2823,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 2823 | 2823 | const std_special = "std" ++ fs.path.sep_str ++ "special"; |
| 2824 | 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 | 2827 | .root_src_directory = .{ |
| 2828 | 2828 | .path = special_dir_path, |
| 2829 | 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 | 2832 | }, |
| 2833 | 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 | 2837 | var cleanup_build_dir: ?fs.Dir = null; |
| 2838 | 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 | 2881 | .root_src_directory = build_directory, |
| 2882 | 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 | 2886 | var global_cache_directory: Compilation.Directory = l: { |
| 2887 | 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 | 2938 | .is_native_abi = cross_target.isNativeAbi(), |
| 2939 | 2939 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 2940 | 2940 | .output_mode = .Exe, |
| 2941 | .root_pkg = &root_pkg, | |
| 2941 | .main_pkg = &main_pkg, | |
| 2942 | 2942 | .emit_bin = emit_bin, |
| 2943 | 2943 | .emit_h = null, |
| 2944 | 2944 | .optimize_mode = .Debug, |
src/musl.zig+1-1| ... | ... | @@ -197,7 +197,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 197 | 197 | .zig_lib_directory = comp.zig_lib_directory, |
| 198 | 198 | .target = comp.getTarget(), |
| 199 | 199 | .root_name = "c", |
| 200 | .root_pkg = null, | |
| 200 | .main_pkg = null, | |
| 201 | 201 | .output_mode = .Lib, |
| 202 | 202 | .link_mode = .Dynamic, |
| 203 | 203 | .thread_pool = comp.thread_pool, |
src/print_air.zig+4| ... | ... | @@ -124,6 +124,8 @@ const Writer = struct { |
| 124 | 124 | .bool_and, |
| 125 | 125 | .bool_or, |
| 126 | 126 | .store, |
| 127 | .slice_elem_val, | |
| 128 | .ptr_slice_elem_val, | |
| 127 | 129 | => try w.writeBinOp(s, inst), |
| 128 | 130 | |
| 129 | 131 | .is_null, |
| ... | ... | @@ -161,6 +163,8 @@ const Writer = struct { |
| 161 | 163 | .unwrap_errunion_err_ptr, |
| 162 | 164 | .wrap_errunion_payload, |
| 163 | 165 | .wrap_errunion_err, |
| 166 | .slice_ptr, | |
| 167 | .slice_len, | |
| 164 | 168 | => try w.writeTyOp(s, inst), |
| 165 | 169 | |
| 166 | 170 | .block, |
src/stage1.zig+1-1| ... | ... | @@ -107,7 +107,7 @@ pub const Module = extern struct { |
| 107 | 107 | test_name_prefix_ptr: [*]const u8, |
| 108 | 108 | test_name_prefix_len: usize, |
| 109 | 109 | userdata: usize, |
| 110 | root_pkg: *Pkg, | |
| 110 | main_pkg: *Pkg, | |
| 111 | 111 | main_progress_node: ?*std.Progress.Node, |
| 112 | 112 | code_model: CodeModel, |
| 113 | 113 | subsystem: TargetSubsystem, |
src/stage1/stage1.cpp+1-1| ... | ... | @@ -126,7 +126,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { |
| 126 | 126 | |
| 127 | 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 | 131 | codegen_build_object(g); |
| 132 | 132 | } |
src/stage1/stage1.h+1-1| ... | ... | @@ -176,7 +176,7 @@ struct ZigStage1 { |
| 176 | 176 | size_t test_name_prefix_len; |
| 177 | 177 | |
| 178 | 178 | void *userdata; |
| 179 | struct ZigStage1Pkg *root_pkg; | |
| 179 | struct ZigStage1Pkg *main_pkg; | |
| 180 | 180 | struct Stage2ProgressNode *main_progress_node; |
| 181 | 181 | |
| 182 | 182 | enum CodeModel code_model; |
src/stage1/zig0.cpp+1-1| ... | ... | @@ -465,7 +465,7 @@ int main(int argc, char **argv) { |
| 465 | 465 | stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features; |
| 466 | 466 | stage1->emit_o_ptr = emit_bin_path; |
| 467 | 467 | stage1->emit_o_len = strlen(emit_bin_path); |
| 468 | stage1->root_pkg = cur_pkg; | |
| 468 | stage1->main_pkg = cur_pkg; | |
| 469 | 469 | stage1->err_color = color; |
| 470 | 470 | stage1->link_libc = link_libc; |
| 471 | 471 | stage1->link_libcpp = link_libcpp; |
src/test.zig+3-3| ... | ... | @@ -848,11 +848,11 @@ pub const TestContext = struct { |
| 848 | 848 | .path = local_cache_path, |
| 849 | 849 | }; |
| 850 | 850 | |
| 851 | var root_pkg: Package = .{ | |
| 851 | var main_pkg: Package = .{ | |
| 852 | 852 | .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir }, |
| 853 | 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 | 857 | const bin_name = try std.zig.binNameAlloc(arena, .{ |
| 858 | 858 | .root_name = "test_case", |
| ... | ... | @@ -896,7 +896,7 @@ pub const TestContext = struct { |
| 896 | 896 | .optimize_mode = case.optimize_mode, |
| 897 | 897 | .emit_bin = emit_bin, |
| 898 | 898 | .emit_h = emit_h, |
| 899 | .root_pkg = &root_pkg, | |
| 899 | .main_pkg = &main_pkg, | |
| 900 | 900 | .keep_source_files_loaded = true, |
| 901 | 901 | .object_format = case.object_format, |
| 902 | 902 | .is_native_os = case.target.isNativeOs(), |
src/type.zig+20-13| ... | ... | @@ -525,9 +525,19 @@ pub const Type = extern union { |
| 525 | 525 | const b_data = b.castTag(.error_union).?.data; |
| 526 | 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 | 539 | .Opaque, |
| 529 | 540 | .Float, |
| 530 | .ErrorSet, | |
| 531 | 541 | .BoundFn, |
| 532 | 542 | .Frame, |
| 533 | 543 | => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }), |
| ... | ... | @@ -1190,6 +1200,9 @@ pub const Type = extern union { |
| 1190 | 1200 | .@"struct" => { |
| 1191 | 1201 | // TODO introduce lazy value mechanism |
| 1192 | 1202 | const struct_obj = self.castTag(.@"struct").?.data; |
| 1203 | if (struct_obj.known_has_bits) { | |
| 1204 | return true; | |
| 1205 | } | |
| 1193 | 1206 | assert(struct_obj.status == .have_field_types or |
| 1194 | 1207 | struct_obj.status == .layout_wip or |
| 1195 | 1208 | struct_obj.status == .have_layout); |
| ... | ... | @@ -1645,7 +1658,7 @@ pub const Type = extern union { |
| 1645 | 1658 | } else if (!payload.payload.hasCodeGenBits()) { |
| 1646 | 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 | 2051 | return ty.optionalChild(&buf).isValidVarType(is_extern); |
| 2039 | 2052 | }, |
| 2040 | 2053 | .Pointer, .Array, .Vector => ty = ty.elemType(), |
| 2041 | .ErrorUnion => ty = ty.errorUnionChild(), | |
| 2054 | .ErrorUnion => ty = ty.errorUnionPayload(), | |
| 2042 | 2055 | |
| 2043 | 2056 | .Fn => @panic("TODO fn isValidVarType"), |
| 2044 | 2057 | .Struct => { |
| ... | ... | @@ -2119,13 +2132,10 @@ pub const Type = extern union { |
| 2119 | 2132 | } |
| 2120 | 2133 | |
| 2121 | 2134 | /// Asserts that the type is an error union. |
| 2122 | pub fn errorUnionChild(self: Type) Type { | |
| 2135 | pub fn errorUnionPayload(self: Type) Type { | |
| 2123 | 2136 | return switch (self.tag()) { |
| 2124 | .anyerror_void_error_union => Type.initTag(.anyerror), | |
| 2125 | .error_union => { | |
| 2126 | const payload = self.castTag(.error_union).?; | |
| 2127 | return payload.data.payload; | |
| 2128 | }, | |
| 2137 | .anyerror_void_error_union => Type.initTag(.void), | |
| 2138 | .error_union => self.castTag(.error_union).?.data.payload, | |
| 2129 | 2139 | else => unreachable, |
| 2130 | 2140 | }; |
| 2131 | 2141 | } |
| ... | ... | @@ -2133,10 +2143,7 @@ pub const Type = extern union { |
| 2133 | 2143 | pub fn errorUnionSet(self: Type) Type { |
| 2134 | 2144 | return switch (self.tag()) { |
| 2135 | 2145 | .anyerror_void_error_union => Type.initTag(.anyerror), |
| 2136 | .error_union => { | |
| 2137 | const payload = self.castTag(.error_union).?; | |
| 2138 | return payload.data.error_set; | |
| 2139 | }, | |
| 2146 | .error_union => self.castTag(.error_union).?.data.error_set, | |
| 2140 | 2147 | else => unreachable, |
| 2141 | 2148 | }; |
| 2142 | 2149 | } |
test/behavior.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | |
| 3 | comptime { | |
| 3 | test { | |
| 4 | 4 | // Tests that pass for both. |
| 5 | 5 | {} |
| 6 | 6 |