| author | |
| committer | |
| log | 93bb1d93cd18e739410009e7c77048d151a93b10 |
| tree | 67b36291211919b9751785eecf8858195bce42d6 |
| parent | 6c2e0c2046a4c1d01587cc15ea2f59af32743eb4 |
| parent | 982acc22fd8674a9efbe1e65e037c464ba610882 |
| signature |
stage2: inferred local variables12 files changed, 347 insertions(+), 71 deletions(-)
src/Module.zig+14-1| ... | @@ -3189,7 +3189,14 @@ pub fn floatSub( | ... | @@ -3189,7 +3189,14 @@ pub fn floatSub( |
| 3189 | } | 3189 | } |
| 3190 | } | 3190 | } |
| 3191 | 3191 | ||
| 3192 | pub fn simplePtrType(self: *Module, scope: *Scope, src: usize, elem_ty: Type, mutable: bool, size: std.builtin.TypeInfo.Pointer.Size) Allocator.Error!Type { | 3192 | pub fn simplePtrType( |
| 3193 | self: *Module, | ||
| 3194 | scope: *Scope, | ||
| 3195 | src: usize, | ||
| 3196 | elem_ty: Type, | ||
| 3197 | mutable: bool, | ||
| 3198 | size: std.builtin.TypeInfo.Pointer.Size, | ||
| 3199 | ) Allocator.Error!Type { | ||
| 3193 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { | 3200 | if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) { |
| 3194 | return Type.initTag(.const_slice_u8); | 3201 | return Type.initTag(.const_slice_u8); |
| 3195 | } | 3202 | } |
| ... | @@ -3414,3 +3421,9 @@ pub fn getTarget(self: Module) Target { | ... | @@ -3414,3 +3421,9 @@ pub fn getTarget(self: Module) Target { |
| 3414 | pub fn optimizeMode(self: Module) std.builtin.Mode { | 3421 | pub fn optimizeMode(self: Module) std.builtin.Mode { |
| 3415 | return self.comp.bin_file.options.optimize_mode; | 3422 | return self.comp.bin_file.options.optimize_mode; |
| 3416 | } | 3423 | } |
| 3424 | |||
| 3425 | pub fn validateVarType(mod: *Module, scope: *Scope, src: usize, ty: Type) !void { | ||
| 3426 | if (!ty.isValidVarType(false)) { | ||
| 3427 | return mod.fail(scope, src, "variable of type '{}' must be const or comptime", .{ty}); | ||
| 3428 | } | ||
| 3429 | } |
src/astgen.zig+14-3| ... | @@ -585,6 +585,7 @@ fn varDecl( | ... | @@ -585,6 +585,7 @@ fn varDecl( |
| 585 | 585 | ||
| 586 | switch (tree.token_ids[node.mut_token]) { | 586 | switch (tree.token_ids[node.mut_token]) { |
| 587 | .Keyword_const => { | 587 | .Keyword_const => { |
| 588 | var resolve_inferred_alloc: ?*zir.Inst = null; | ||
| 588 | // Depending on the type of AST the initialization expression is, we may need an lvalue | 589 | // Depending on the type of AST the initialization expression is, we may need an lvalue |
| 589 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | 590 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as |
| 590 | // the variable, no memory location needed. | 591 | // the variable, no memory location needed. |
| ... | @@ -595,6 +596,7 @@ fn varDecl( | ... | @@ -595,6 +596,7 @@ fn varDecl( |
| 595 | break :r ResultLoc{ .ptr = alloc }; | 596 | break :r ResultLoc{ .ptr = alloc }; |
| 596 | } else { | 597 | } else { |
| 597 | const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred); | 598 | const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred); |
| 599 | resolve_inferred_alloc = &alloc.base; | ||
| 598 | break :r ResultLoc{ .inferred_ptr = alloc }; | 600 | break :r ResultLoc{ .inferred_ptr = alloc }; |
| 599 | } | 601 | } |
| 600 | } else r: { | 602 | } else r: { |
| ... | @@ -604,6 +606,9 @@ fn varDecl( | ... | @@ -604,6 +606,9 @@ fn varDecl( |
| 604 | break :r .none; | 606 | break :r .none; |
| 605 | }; | 607 | }; |
| 606 | const init_inst = try expr(mod, scope, result_loc, init_node); | 608 | const init_inst = try expr(mod, scope, result_loc, init_node); |
| 609 | if (resolve_inferred_alloc) |inst| { | ||
| 610 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); | ||
| 611 | } | ||
| 607 | const sub_scope = try block_arena.create(Scope.LocalVal); | 612 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 608 | sub_scope.* = .{ | 613 | sub_scope.* = .{ |
| 609 | .parent = scope, | 614 | .parent = scope, |
| ... | @@ -614,15 +619,20 @@ fn varDecl( | ... | @@ -614,15 +619,20 @@ fn varDecl( |
| 614 | return &sub_scope.base; | 619 | return &sub_scope.base; |
| 615 | }, | 620 | }, |
| 616 | .Keyword_var => { | 621 | .Keyword_var => { |
| 622 | var resolve_inferred_alloc: ?*zir.Inst = null; | ||
| 617 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: { | 623 | const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTypeNode()) |type_node| a: { |
| 618 | const type_inst = try typeExpr(mod, scope, type_node); | 624 | const type_inst = try typeExpr(mod, scope, type_node); |
| 619 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst); | 625 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc_mut, type_inst); |
| 620 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; | 626 | break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } }; |
| 621 | } else a: { | 627 | } else a: { |
| 622 | const alloc = try addZIRNoOp(mod, scope, name_src, .alloc_inferred_mut); | 628 | const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred_mut); |
| 623 | break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc.castTag(.alloc_inferred_mut).? } }; | 629 | resolve_inferred_alloc = &alloc.base; |
| 630 | break :a .{ .alloc = &alloc.base, .result_loc = .{ .inferred_ptr = alloc } }; | ||
| 624 | }; | 631 | }; |
| 625 | const init_inst = try expr(mod, scope, var_data.result_loc, init_node); | 632 | const init_inst = try expr(mod, scope, var_data.result_loc, init_node); |
| 633 | if (resolve_inferred_alloc) |inst| { | ||
| 634 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); | ||
| 635 | } | ||
| 626 | const sub_scope = try block_arena.create(Scope.LocalPtr); | 636 | const sub_scope = try block_arena.create(Scope.LocalPtr); |
| 627 | sub_scope.* = .{ | 637 | sub_scope.* = .{ |
| 628 | .parent = scope, | 638 | .parent = scope, |
| ... | @@ -2717,7 +2727,8 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr | ... | @@ -2717,7 +2727,8 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr |
| 2717 | return mod.fail(scope, result.src, "TODO implement rlWrap .bitcasted_ptr", .{}); | 2727 | return mod.fail(scope, result.src, "TODO implement rlWrap .bitcasted_ptr", .{}); |
| 2718 | }, | 2728 | }, |
| 2719 | .inferred_ptr => |alloc| { | 2729 | .inferred_ptr => |alloc| { |
| 2720 | return addZIRBinOp(mod, scope, result.src, .store, &alloc.base, result); | 2730 | _ = try addZIRBinOp(mod, scope, result.src, .store_to_inferred_ptr, &alloc.base, result); |
| 2731 | return result; | ||
| 2721 | }, | 2732 | }, |
| 2722 | .block_ptr => |block_ptr| { | 2733 | .block_ptr => |block_ptr| { |
| 2723 | return mod.fail(scope, result.src, "TODO implement rlWrap .block_ptr", .{}); | 2734 | return mod.fail(scope, result.src, "TODO implement rlWrap .block_ptr", .{}); |
src/codegen/c.zig+30-1| ... | @@ -285,6 +285,7 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void { | ... | @@ -285,6 +285,7 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void { |
| 285 | .arg => try genArg(&ctx), | 285 | .arg => try genArg(&ctx), |
| 286 | .assembly => try genAsm(&ctx, file, inst.castTag(.assembly).?), | 286 | .assembly => try genAsm(&ctx, file, inst.castTag(.assembly).?), |
| 287 | .block => try genBlock(&ctx, file, inst.castTag(.block).?), | 287 | .block => try genBlock(&ctx, file, inst.castTag(.block).?), |
| 288 | .bitcast => try genBitcast(&ctx, file, inst.castTag(.bitcast).?), | ||
| 288 | .breakpoint => try genBreakpoint(file, inst.castTag(.breakpoint).?), | 289 | .breakpoint => try genBreakpoint(file, inst.castTag(.breakpoint).?), |
| 289 | .call => try genCall(&ctx, file, inst.castTag(.call).?), | 290 | .call => try genCall(&ctx, file, inst.castTag(.call).?), |
| 290 | .cmp_eq => try genBinOp(&ctx, file, inst.castTag(.cmp_eq).?, "=="), | 291 | .cmp_eq => try genBinOp(&ctx, file, inst.castTag(.cmp_eq).?, "=="), |
| ... | @@ -295,6 +296,7 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void { | ... | @@ -295,6 +296,7 @@ pub fn generate(file: *C, module: *Module, decl: *Decl) !void { |
| 295 | .cmp_neq => try genBinOp(&ctx, file, inst.castTag(.cmp_neq).?, "!="), | 296 | .cmp_neq => try genBinOp(&ctx, file, inst.castTag(.cmp_neq).?, "!="), |
| 296 | .dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?), | 297 | .dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?), |
| 297 | .intcast => try genIntCast(&ctx, file, inst.castTag(.intcast).?), | 298 | .intcast => try genIntCast(&ctx, file, inst.castTag(.intcast).?), |
| 299 | .load => try genLoad(&ctx, file, inst.castTag(.load).?), | ||
| 298 | .ret => try genRet(&ctx, file, inst.castTag(.ret).?), | 300 | .ret => try genRet(&ctx, file, inst.castTag(.ret).?), |
| 299 | .retvoid => try genRetVoid(file), | 301 | .retvoid => try genRetVoid(file), |
| 300 | .store => try genStore(&ctx, file, inst.castTag(.store).?), | 302 | .store => try genStore(&ctx, file, inst.castTag(.store).?), |
| ... | @@ -429,6 +431,16 @@ fn genRetVoid(file: *C) !?[]u8 { | ... | @@ -429,6 +431,16 @@ fn genRetVoid(file: *C) !?[]u8 { |
| 429 | return null; | 431 | return null; |
| 430 | } | 432 | } |
| 431 | 433 | ||
| 434 | fn genLoad(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { | ||
| 435 | const operand = try ctx.resolveInst(inst.operand); | ||
| 436 | const writer = file.main.writer(); | ||
| 437 | try indent(file); | ||
| 438 | const local_name = try ctx.name(); | ||
| 439 | try renderTypeAndName(ctx, writer, inst.base.ty, local_name, .Const); | ||
| 440 | try writer.print(" = *{s};\n", .{operand}); | ||
| 441 | return local_name; | ||
| 442 | } | ||
| 443 | |||
| 432 | fn genRet(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { | 444 | fn genRet(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { |
| 433 | try indent(file); | 445 | try indent(file); |
| 434 | const writer = file.main.writer(); | 446 | const writer = file.main.writer(); |
| ... | @@ -440,7 +452,6 @@ fn genIntCast(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { | ... | @@ -440,7 +452,6 @@ fn genIntCast(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { |
| 440 | if (inst.base.isUnused()) | 452 | if (inst.base.isUnused()) |
| 441 | return null; | 453 | return null; |
| 442 | try indent(file); | 454 | try indent(file); |
| 443 | const op = inst.operand; | ||
| 444 | const writer = file.main.writer(); | 455 | const writer = file.main.writer(); |
| 445 | const name = try ctx.name(); | 456 | const name = try ctx.name(); |
| 446 | const from = try ctx.resolveInst(inst.operand); | 457 | const from = try ctx.resolveInst(inst.operand); |
| ... | @@ -537,6 +548,24 @@ fn genBlock(ctx: *Context, file: *C, inst: *Inst.Block) !?[]u8 { | ... | @@ -537,6 +548,24 @@ fn genBlock(ctx: *Context, file: *C, inst: *Inst.Block) !?[]u8 { |
| 537 | return ctx.fail(ctx.decl.src(), "TODO: C backend: implement blocks", .{}); | 548 | return ctx.fail(ctx.decl.src(), "TODO: C backend: implement blocks", .{}); |
| 538 | } | 549 | } |
| 539 | 550 | ||
| 551 | fn genBitcast(ctx: *Context, file: *C, inst: *Inst.UnOp) !?[]u8 { | ||
| 552 | const writer = file.main.writer(); | ||
| 553 | try indent(file); | ||
| 554 | const local_name = try ctx.name(); | ||
| 555 | const operand = try ctx.resolveInst(inst.operand); | ||
| 556 | try renderTypeAndName(ctx, writer, inst.base.ty, local_name, .Const); | ||
| 557 | if (inst.base.ty.zigTypeTag() == .Pointer and inst.operand.ty.zigTypeTag() == .Pointer) { | ||
| 558 | try writer.writeAll(" = ("); | ||
| 559 | try renderType(ctx, writer, inst.base.ty); | ||
| 560 | try writer.print("){s};\n", .{operand}); | ||
| 561 | } else { | ||
| 562 | try writer.writeAll(";\n"); | ||
| 563 | try indent(file); | ||
| 564 | try writer.print("memcpy(&{s}, &{s}, sizeof {s});\n", .{ local_name, operand, local_name }); | ||
| 565 | } | ||
| 566 | return local_name; | ||
| 567 | } | ||
| 568 | |||
| 540 | fn genBreakpoint(file: *C, inst: *Inst.NoOp) !?[]u8 { | 569 | fn genBreakpoint(file: *C, inst: *Inst.NoOp) !?[]u8 { |
| 541 | try indent(file); | 570 | try indent(file); |
| 542 | try file.main.writer().writeAll("zig_breakpoint();\n"); | 571 | try file.main.writer().writeAll("zig_breakpoint();\n"); |
src/ir.zig+1-1| ... | @@ -196,7 +196,7 @@ pub const Inst = struct { | ... | @@ -196,7 +196,7 @@ pub const Inst = struct { |
| 196 | pub fn value(base: *Inst) ?Value { | 196 | pub fn value(base: *Inst) ?Value { |
| 197 | if (base.ty.onePossibleValue()) |opv| return opv; | 197 | if (base.ty.onePossibleValue()) |opv| return opv; |
| 198 | 198 | ||
| 199 | const inst = base.cast(Constant) orelse return null; | 199 | const inst = base.castTag(.constant) orelse return null; |
| 200 | return inst.val; | 200 | return inst.val; |
| 201 | } | 201 | } |
| 202 | 202 |
src/link/cbe.h+1-1| ... | @@ -41,4 +41,4 @@ | ... | @@ -41,4 +41,4 @@ |
| 41 | #include <stdint.h> | 41 | #include <stdint.h> |
| 42 | #define int128_t __int128 | 42 | #define int128_t __int128 |
| 43 | #define uint128_t unsigned __int128 | 43 | #define uint128_t unsigned __int128 |
| 44 | 44 | #include <string.h> |
src/test.zig+1| ... | @@ -782,6 +782,7 @@ pub const TestContext = struct { | ... | @@ -782,6 +782,7 @@ pub const TestContext = struct { |
| 782 | "-std=c89", | 782 | "-std=c89", |
| 783 | "-pedantic", | 783 | "-pedantic", |
| 784 | "-Werror", | 784 | "-Werror", |
| 785 | "-Wno-declaration-after-statement", | ||
| 785 | "--", | 786 | "--", |
| 786 | "-lc", | 787 | "-lc", |
| 787 | exe_path, | 788 | exe_path, |
src/type.zig+125-54| ... | @@ -78,6 +78,8 @@ pub const Type = extern union { | ... | @@ -78,6 +78,8 @@ pub const Type = extern union { |
| 78 | .const_slice, | 78 | .const_slice, |
| 79 | .mut_slice, | 79 | .mut_slice, |
| 80 | .pointer, | 80 | .pointer, |
| 81 | .inferred_alloc_const, | ||
| 82 | .inferred_alloc_mut, | ||
| 81 | => return .Pointer, | 83 | => return .Pointer, |
| 82 | 84 | ||
| 83 | .optional, | 85 | .optional, |
| ... | @@ -158,6 +160,9 @@ pub const Type = extern union { | ... | @@ -158,6 +160,9 @@ pub const Type = extern union { |
| 158 | .optional_single_mut_pointer, | 160 | .optional_single_mut_pointer, |
| 159 | => self.cast(Payload.ElemType), | 161 | => self.cast(Payload.ElemType), |
| 160 | 162 | ||
| 163 | .inferred_alloc_const => unreachable, | ||
| 164 | .inferred_alloc_mut => unreachable, | ||
| 165 | |||
| 161 | else => null, | 166 | else => null, |
| 162 | }; | 167 | }; |
| 163 | } | 168 | } |
| ... | @@ -384,6 +389,8 @@ pub const Type = extern union { | ... | @@ -384,6 +389,8 @@ pub const Type = extern union { |
| 384 | .enum_literal, | 389 | .enum_literal, |
| 385 | .anyerror_void_error_union, | 390 | .anyerror_void_error_union, |
| 386 | .@"anyframe", | 391 | .@"anyframe", |
| 392 | .inferred_alloc_const, | ||
| 393 | .inferred_alloc_mut, | ||
| 387 | => unreachable, | 394 | => unreachable, |
| 388 | 395 | ||
| 389 | .array_u8, | 396 | .array_u8, |
| ... | @@ -686,6 +693,8 @@ pub const Type = extern union { | ... | @@ -686,6 +693,8 @@ pub const Type = extern union { |
| 686 | const name = ty.castTag(.error_set_single).?.data; | 693 | const name = ty.castTag(.error_set_single).?.data; |
| 687 | return out_stream.print("error{{{s}}}", .{name}); | 694 | return out_stream.print("error{{{s}}}", .{name}); |
| 688 | }, | 695 | }, |
| 696 | .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"), | ||
| 697 | .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"), | ||
| 689 | } | 698 | } |
| 690 | unreachable; | 699 | unreachable; |
| 691 | } | 700 | } |
| ... | @@ -733,6 +742,8 @@ pub const Type = extern union { | ... | @@ -733,6 +742,8 @@ pub const Type = extern union { |
| 733 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), | 742 | .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), |
| 734 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), | 743 | .const_slice_u8 => return Value.initTag(.const_slice_u8_type), |
| 735 | .enum_literal => return Value.initTag(.enum_literal_type), | 744 | .enum_literal => return Value.initTag(.enum_literal_type), |
| 745 | .inferred_alloc_const => unreachable, | ||
| 746 | .inferred_alloc_mut => unreachable, | ||
| 736 | else => return Value.Tag.ty.create(allocator, self), | 747 | else => return Value.Tag.ty.create(allocator, self), |
| 737 | } | 748 | } |
| 738 | } | 749 | } |
| ... | @@ -803,6 +814,9 @@ pub const Type = extern union { | ... | @@ -803,6 +814,9 @@ pub const Type = extern union { |
| 803 | .enum_literal, | 814 | .enum_literal, |
| 804 | .empty_struct, | 815 | .empty_struct, |
| 805 | => false, | 816 | => false, |
| 817 | |||
| 818 | .inferred_alloc_const => unreachable, | ||
| 819 | .inferred_alloc_mut => unreachable, | ||
| 806 | }; | 820 | }; |
| 807 | } | 821 | } |
| 808 | 822 | ||
| ... | @@ -920,6 +934,8 @@ pub const Type = extern union { | ... | @@ -920,6 +934,8 @@ pub const Type = extern union { |
| 920 | .@"undefined", | 934 | .@"undefined", |
| 921 | .enum_literal, | 935 | .enum_literal, |
| 922 | .empty_struct, | 936 | .empty_struct, |
| 937 | .inferred_alloc_const, | ||
| 938 | .inferred_alloc_mut, | ||
| 923 | => unreachable, | 939 | => unreachable, |
| 924 | }; | 940 | }; |
| 925 | } | 941 | } |
| ... | @@ -943,6 +959,8 @@ pub const Type = extern union { | ... | @@ -943,6 +959,8 @@ pub const Type = extern union { |
| 943 | .enum_literal => unreachable, | 959 | .enum_literal => unreachable, |
| 944 | .single_const_pointer_to_comptime_int => unreachable, | 960 | .single_const_pointer_to_comptime_int => unreachable, |
| 945 | .empty_struct => unreachable, | 961 | .empty_struct => unreachable, |
| 962 | .inferred_alloc_const => unreachable, | ||
| 963 | .inferred_alloc_mut => unreachable, | ||
| 946 | 964 | ||
| 947 | .u8, | 965 | .u8, |
| 948 | .i8, | 966 | .i8, |
| ... | @@ -1121,6 +1139,8 @@ pub const Type = extern union { | ... | @@ -1121,6 +1139,8 @@ pub const Type = extern union { |
| 1121 | .single_const_pointer, | 1139 | .single_const_pointer, |
| 1122 | .single_mut_pointer, | 1140 | .single_mut_pointer, |
| 1123 | .single_const_pointer_to_comptime_int, | 1141 | .single_const_pointer_to_comptime_int, |
| 1142 | .inferred_alloc_const, | ||
| 1143 | .inferred_alloc_mut, | ||
| 1124 | => true, | 1144 | => true, |
| 1125 | 1145 | ||
| 1126 | .pointer => self.castTag(.pointer).?.data.size == .One, | 1146 | .pointer => self.castTag(.pointer).?.data.size == .One, |
| ... | @@ -1203,6 +1223,8 @@ pub const Type = extern union { | ... | @@ -1203,6 +1223,8 @@ pub const Type = extern union { |
| 1203 | .single_const_pointer, | 1223 | .single_const_pointer, |
| 1204 | .single_mut_pointer, | 1224 | .single_mut_pointer, |
| 1205 | .single_const_pointer_to_comptime_int, | 1225 | .single_const_pointer_to_comptime_int, |
| 1226 | .inferred_alloc_const, | ||
| 1227 | .inferred_alloc_mut, | ||
| 1206 | => .One, | 1228 | => .One, |
| 1207 | 1229 | ||
| 1208 | .pointer => self.castTag(.pointer).?.data.size, | 1230 | .pointer => self.castTag(.pointer).?.data.size, |
| ... | @@ -1273,6 +1295,8 @@ pub const Type = extern union { | ... | @@ -1273,6 +1295,8 @@ pub const Type = extern union { |
| 1273 | .error_set, | 1295 | .error_set, |
| 1274 | .error_set_single, | 1296 | .error_set_single, |
| 1275 | .empty_struct, | 1297 | .empty_struct, |
| 1298 | .inferred_alloc_const, | ||
| 1299 | .inferred_alloc_mut, | ||
| 1276 | => false, | 1300 | => false, |
| 1277 | 1301 | ||
| 1278 | .const_slice, | 1302 | .const_slice, |
| ... | @@ -1345,6 +1369,8 @@ pub const Type = extern union { | ... | @@ -1345,6 +1369,8 @@ pub const Type = extern union { |
| 1345 | .error_set, | 1369 | .error_set, |
| 1346 | .error_set_single, | 1370 | .error_set_single, |
| 1347 | .empty_struct, | 1371 | .empty_struct, |
| 1372 | .inferred_alloc_const, | ||
| 1373 | .inferred_alloc_mut, | ||
| 1348 | => false, | 1374 | => false, |
| 1349 | 1375 | ||
| 1350 | .single_const_pointer, | 1376 | .single_const_pointer, |
| ... | @@ -1426,6 +1452,8 @@ pub const Type = extern union { | ... | @@ -1426,6 +1452,8 @@ pub const Type = extern union { |
| 1426 | .error_set, | 1452 | .error_set, |
| 1427 | .error_set_single, | 1453 | .error_set_single, |
| 1428 | .empty_struct, | 1454 | .empty_struct, |
| 1455 | .inferred_alloc_const, | ||
| 1456 | .inferred_alloc_mut, | ||
| 1429 | => false, | 1457 | => false, |
| 1430 | 1458 | ||
| 1431 | .pointer => { | 1459 | .pointer => { |
| ... | @@ -1502,6 +1530,8 @@ pub const Type = extern union { | ... | @@ -1502,6 +1530,8 @@ pub const Type = extern union { |
| 1502 | .error_set, | 1530 | .error_set, |
| 1503 | .error_set_single, | 1531 | .error_set_single, |
| 1504 | .empty_struct, | 1532 | .empty_struct, |
| 1533 | .inferred_alloc_const, | ||
| 1534 | .inferred_alloc_mut, | ||
| 1505 | => false, | 1535 | => false, |
| 1506 | 1536 | ||
| 1507 | .pointer => { | 1537 | .pointer => { |
| ... | @@ -1569,58 +1599,59 @@ pub const Type = extern union { | ... | @@ -1569,58 +1599,59 @@ pub const Type = extern union { |
| 1569 | /// Asserts the type is a pointer or array type. | 1599 | /// Asserts the type is a pointer or array type. |
| 1570 | pub fn elemType(self: Type) Type { | 1600 | pub fn elemType(self: Type) Type { |
| 1571 | return switch (self.tag()) { | 1601 | return switch (self.tag()) { |
| 1572 | .u8, | 1602 | .u8 => unreachable, |
| 1573 | .i8, | 1603 | .i8 => unreachable, |
| 1574 | .u16, | 1604 | .u16 => unreachable, |
| 1575 | .i16, | 1605 | .i16 => unreachable, |
| 1576 | .u32, | 1606 | .u32 => unreachable, |
| 1577 | .i32, | 1607 | .i32 => unreachable, |
| 1578 | .u64, | 1608 | .u64 => unreachable, |
| 1579 | .i64, | 1609 | .i64 => unreachable, |
| 1580 | .usize, | 1610 | .usize => unreachable, |
| 1581 | .isize, | 1611 | .isize => unreachable, |
| 1582 | .c_short, | 1612 | .c_short => unreachable, |
| 1583 | .c_ushort, | 1613 | .c_ushort => unreachable, |
| 1584 | .c_int, | 1614 | .c_int => unreachable, |
| 1585 | .c_uint, | 1615 | .c_uint => unreachable, |
| 1586 | .c_long, | 1616 | .c_long => unreachable, |
| 1587 | .c_ulong, | 1617 | .c_ulong => unreachable, |
| 1588 | .c_longlong, | 1618 | .c_longlong => unreachable, |
| 1589 | .c_ulonglong, | 1619 | .c_ulonglong => unreachable, |
| 1590 | .c_longdouble, | 1620 | .c_longdouble => unreachable, |
| 1591 | .f16, | 1621 | .f16 => unreachable, |
| 1592 | .f32, | 1622 | .f32 => unreachable, |
| 1593 | .f64, | 1623 | .f64 => unreachable, |
| 1594 | .f128, | 1624 | .f128 => unreachable, |
| 1595 | .c_void, | 1625 | .c_void => unreachable, |
| 1596 | .bool, | 1626 | .bool => unreachable, |
| 1597 | .void, | 1627 | .void => unreachable, |
| 1598 | .type, | 1628 | .type => unreachable, |
| 1599 | .anyerror, | 1629 | .anyerror => unreachable, |
| 1600 | .comptime_int, | 1630 | .comptime_int => unreachable, |
| 1601 | .comptime_float, | 1631 | .comptime_float => unreachable, |
| 1602 | .noreturn, | 1632 | .noreturn => unreachable, |
| 1603 | .@"null", | 1633 | .@"null" => unreachable, |
| 1604 | .@"undefined", | 1634 | .@"undefined" => unreachable, |
| 1605 | .fn_noreturn_no_args, | 1635 | .fn_noreturn_no_args => unreachable, |
| 1606 | .fn_void_no_args, | 1636 | .fn_void_no_args => unreachable, |
| 1607 | .fn_naked_noreturn_no_args, | 1637 | .fn_naked_noreturn_no_args => unreachable, |
| 1608 | .fn_ccc_void_no_args, | 1638 | .fn_ccc_void_no_args => unreachable, |
| 1609 | .function, | 1639 | .function => unreachable, |
| 1610 | .int_unsigned, | 1640 | .int_unsigned => unreachable, |
| 1611 | .int_signed, | 1641 | .int_signed => unreachable, |
| 1612 | .optional, | 1642 | .optional => unreachable, |
| 1613 | .optional_single_const_pointer, | 1643 | .optional_single_const_pointer => unreachable, |
| 1614 | .optional_single_mut_pointer, | 1644 | .optional_single_mut_pointer => unreachable, |
| 1615 | .enum_literal, | 1645 | .enum_literal => unreachable, |
| 1616 | .error_union, | 1646 | .error_union => unreachable, |
| 1617 | .@"anyframe", | 1647 | .@"anyframe" => unreachable, |
| 1618 | .anyframe_T, | 1648 | .anyframe_T => unreachable, |
| 1619 | .anyerror_void_error_union, | 1649 | .anyerror_void_error_union => unreachable, |
| 1620 | .error_set, | 1650 | .error_set => unreachable, |
| 1621 | .error_set_single, | 1651 | .error_set_single => unreachable, |
| 1622 | .empty_struct, | 1652 | .empty_struct => unreachable, |
| 1623 | => unreachable, | 1653 | .inferred_alloc_const => unreachable, |
| 1654 | .inferred_alloc_mut => unreachable, | ||
| 1624 | 1655 | ||
| 1625 | .array => self.castTag(.array).?.data.elem_type, | 1656 | .array => self.castTag(.array).?.data.elem_type, |
| 1626 | .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, | 1657 | .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, |
| ... | @@ -1742,6 +1773,8 @@ pub const Type = extern union { | ... | @@ -1742,6 +1773,8 @@ pub const Type = extern union { |
| 1742 | .error_set, | 1773 | .error_set, |
| 1743 | .error_set_single, | 1774 | .error_set_single, |
| 1744 | .empty_struct, | 1775 | .empty_struct, |
| 1776 | .inferred_alloc_const, | ||
| 1777 | .inferred_alloc_mut, | ||
| 1745 | => unreachable, | 1778 | => unreachable, |
| 1746 | 1779 | ||
| 1747 | .array => self.castTag(.array).?.data.len, | 1780 | .array => self.castTag(.array).?.data.len, |
| ... | @@ -1808,6 +1841,8 @@ pub const Type = extern union { | ... | @@ -1808,6 +1841,8 @@ pub const Type = extern union { |
| 1808 | .error_set, | 1841 | .error_set, |
| 1809 | .error_set_single, | 1842 | .error_set_single, |
| 1810 | .empty_struct, | 1843 | .empty_struct, |
| 1844 | .inferred_alloc_const, | ||
| 1845 | .inferred_alloc_mut, | ||
| 1811 | => unreachable, | 1846 | => unreachable, |
| 1812 | 1847 | ||
| 1813 | .single_const_pointer, | 1848 | .single_const_pointer, |
| ... | @@ -1891,6 +1926,8 @@ pub const Type = extern union { | ... | @@ -1891,6 +1926,8 @@ pub const Type = extern union { |
| 1891 | .error_set, | 1926 | .error_set, |
| 1892 | .error_set_single, | 1927 | .error_set_single, |
| 1893 | .empty_struct, | 1928 | .empty_struct, |
| 1929 | .inferred_alloc_const, | ||
| 1930 | .inferred_alloc_mut, | ||
| 1894 | => false, | 1931 | => false, |
| 1895 | 1932 | ||
| 1896 | .int_signed, | 1933 | .int_signed, |
| ... | @@ -1966,6 +2003,8 @@ pub const Type = extern union { | ... | @@ -1966,6 +2003,8 @@ pub const Type = extern union { |
| 1966 | .error_set, | 2003 | .error_set, |
| 1967 | .error_set_single, | 2004 | .error_set_single, |
| 1968 | .empty_struct, | 2005 | .empty_struct, |
| 2006 | .inferred_alloc_const, | ||
| 2007 | .inferred_alloc_mut, | ||
| 1969 | => false, | 2008 | => false, |
| 1970 | 2009 | ||
| 1971 | .int_unsigned, | 2010 | .int_unsigned, |
| ... | @@ -2031,6 +2070,8 @@ pub const Type = extern union { | ... | @@ -2031,6 +2070,8 @@ pub const Type = extern union { |
| 2031 | .error_set, | 2070 | .error_set, |
| 2032 | .error_set_single, | 2071 | .error_set_single, |
| 2033 | .empty_struct, | 2072 | .empty_struct, |
| 2073 | .inferred_alloc_const, | ||
| 2074 | .inferred_alloc_mut, | ||
| 2034 | => unreachable, | 2075 | => unreachable, |
| 2035 | 2076 | ||
| 2036 | .int_unsigned => .{ | 2077 | .int_unsigned => .{ |
| ... | @@ -2120,6 +2161,8 @@ pub const Type = extern union { | ... | @@ -2120,6 +2161,8 @@ pub const Type = extern union { |
| 2120 | .error_set, | 2161 | .error_set, |
| 2121 | .error_set_single, | 2162 | .error_set_single, |
| 2122 | .empty_struct, | 2163 | .empty_struct, |
| 2164 | .inferred_alloc_const, | ||
| 2165 | .inferred_alloc_mut, | ||
| 2123 | => false, | 2166 | => false, |
| 2124 | 2167 | ||
| 2125 | .usize, | 2168 | .usize, |
| ... | @@ -2232,6 +2275,8 @@ pub const Type = extern union { | ... | @@ -2232,6 +2275,8 @@ pub const Type = extern union { |
| 2232 | .error_set, | 2275 | .error_set, |
| 2233 | .error_set_single, | 2276 | .error_set_single, |
| 2234 | .empty_struct, | 2277 | .empty_struct, |
| 2278 | .inferred_alloc_const, | ||
| 2279 | .inferred_alloc_mut, | ||
| 2235 | => unreachable, | 2280 | => unreachable, |
| 2236 | }; | 2281 | }; |
| 2237 | } | 2282 | } |
| ... | @@ -2310,6 +2355,8 @@ pub const Type = extern union { | ... | @@ -2310,6 +2355,8 @@ pub const Type = extern union { |
| 2310 | .error_set, | 2355 | .error_set, |
| 2311 | .error_set_single, | 2356 | .error_set_single, |
| 2312 | .empty_struct, | 2357 | .empty_struct, |
| 2358 | .inferred_alloc_const, | ||
| 2359 | .inferred_alloc_mut, | ||
| 2313 | => unreachable, | 2360 | => unreachable, |
| 2314 | } | 2361 | } |
| 2315 | } | 2362 | } |
| ... | @@ -2387,6 +2434,8 @@ pub const Type = extern union { | ... | @@ -2387,6 +2434,8 @@ pub const Type = extern union { |
| 2387 | .error_set, | 2434 | .error_set, |
| 2388 | .error_set_single, | 2435 | .error_set_single, |
| 2389 | .empty_struct, | 2436 | .empty_struct, |
| 2437 | .inferred_alloc_const, | ||
| 2438 | .inferred_alloc_mut, | ||
| 2390 | => unreachable, | 2439 | => unreachable, |
| 2391 | } | 2440 | } |
| 2392 | } | 2441 | } |
| ... | @@ -2464,6 +2513,8 @@ pub const Type = extern union { | ... | @@ -2464,6 +2513,8 @@ pub const Type = extern union { |
| 2464 | .error_set, | 2513 | .error_set, |
| 2465 | .error_set_single, | 2514 | .error_set_single, |
| 2466 | .empty_struct, | 2515 | .empty_struct, |
| 2516 | .inferred_alloc_const, | ||
| 2517 | .inferred_alloc_mut, | ||
| 2467 | => unreachable, | 2518 | => unreachable, |
| 2468 | }; | 2519 | }; |
| 2469 | } | 2520 | } |
| ... | @@ -2538,6 +2589,8 @@ pub const Type = extern union { | ... | @@ -2538,6 +2589,8 @@ pub const Type = extern union { |
| 2538 | .error_set, | 2589 | .error_set, |
| 2539 | .error_set_single, | 2590 | .error_set_single, |
| 2540 | .empty_struct, | 2591 | .empty_struct, |
| 2592 | .inferred_alloc_const, | ||
| 2593 | .inferred_alloc_mut, | ||
| 2541 | => unreachable, | 2594 | => unreachable, |
| 2542 | }; | 2595 | }; |
| 2543 | } | 2596 | } |
| ... | @@ -2612,6 +2665,8 @@ pub const Type = extern union { | ... | @@ -2612,6 +2665,8 @@ pub const Type = extern union { |
| 2612 | .error_set, | 2665 | .error_set, |
| 2613 | .error_set_single, | 2666 | .error_set_single, |
| 2614 | .empty_struct, | 2667 | .empty_struct, |
| 2668 | .inferred_alloc_const, | ||
| 2669 | .inferred_alloc_mut, | ||
| 2615 | => unreachable, | 2670 | => unreachable, |
| 2616 | }; | 2671 | }; |
| 2617 | } | 2672 | } |
| ... | @@ -2686,6 +2741,8 @@ pub const Type = extern union { | ... | @@ -2686,6 +2741,8 @@ pub const Type = extern union { |
| 2686 | .error_set, | 2741 | .error_set, |
| 2687 | .error_set_single, | 2742 | .error_set_single, |
| 2688 | .empty_struct, | 2743 | .empty_struct, |
| 2744 | .inferred_alloc_const, | ||
| 2745 | .inferred_alloc_mut, | ||
| 2689 | => false, | 2746 | => false, |
| 2690 | }; | 2747 | }; |
| 2691 | } | 2748 | } |
| ... | @@ -2778,6 +2835,8 @@ pub const Type = extern union { | ... | @@ -2778,6 +2835,8 @@ pub const Type = extern union { |
| 2778 | ty = ty.castTag(.pointer).?.data.pointee_type; | 2835 | ty = ty.castTag(.pointer).?.data.pointee_type; |
| 2779 | continue; | 2836 | continue; |
| 2780 | }, | 2837 | }, |
| 2838 | .inferred_alloc_const => unreachable, | ||
| 2839 | .inferred_alloc_mut => unreachable, | ||
| 2781 | }; | 2840 | }; |
| 2782 | } | 2841 | } |
| 2783 | 2842 | ||
| ... | @@ -2846,6 +2905,8 @@ pub const Type = extern union { | ... | @@ -2846,6 +2905,8 @@ pub const Type = extern union { |
| 2846 | .error_set, | 2905 | .error_set, |
| 2847 | .error_set_single, | 2906 | .error_set_single, |
| 2848 | .empty_struct, | 2907 | .empty_struct, |
| 2908 | .inferred_alloc_const, | ||
| 2909 | .inferred_alloc_mut, | ||
| 2849 | => return false, | 2910 | => return false, |
| 2850 | 2911 | ||
| 2851 | .c_const_pointer, | 2912 | .c_const_pointer, |
| ... | @@ -2931,6 +2992,8 @@ pub const Type = extern union { | ... | @@ -2931,6 +2992,8 @@ pub const Type = extern union { |
| 2931 | .c_const_pointer, | 2992 | .c_const_pointer, |
| 2932 | .c_mut_pointer, | 2993 | .c_mut_pointer, |
| 2933 | .pointer, | 2994 | .pointer, |
| 2995 | .inferred_alloc_const, | ||
| 2996 | .inferred_alloc_mut, | ||
| 2934 | => unreachable, | 2997 | => unreachable, |
| 2935 | 2998 | ||
| 2936 | .empty_struct => self.castTag(.empty_struct).?.data, | 2999 | .empty_struct => self.castTag(.empty_struct).?.data, |
| ... | @@ -3041,7 +3104,13 @@ pub const Type = extern union { | ... | @@ -3041,7 +3104,13 @@ pub const Type = extern union { |
| 3041 | single_const_pointer_to_comptime_int, | 3104 | single_const_pointer_to_comptime_int, |
| 3042 | anyerror_void_error_union, | 3105 | anyerror_void_error_union, |
| 3043 | @"anyframe", | 3106 | @"anyframe", |
| 3044 | const_slice_u8, // See last_no_payload_tag below. | 3107 | const_slice_u8, |
| 3108 | /// This is a special value that tracks a set of types that have been stored | ||
| 3109 | /// to an inferred allocation. It does not support most of the normal type queries. | ||
| 3110 | /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. | ||
| 3111 | inferred_alloc_mut, | ||
| 3112 | /// Same as `inferred_alloc_mut` but the local is `var` not `const`. | ||
| 3113 | inferred_alloc_const, // See last_no_payload_tag below. | ||
| 3045 | // After this, the tag requires a payload. | 3114 | // After this, the tag requires a payload. |
| 3046 | 3115 | ||
| 3047 | array_u8, | 3116 | array_u8, |
| ... | @@ -3069,7 +3138,7 @@ pub const Type = extern union { | ... | @@ -3069,7 +3138,7 @@ pub const Type = extern union { |
| 3069 | error_set_single, | 3138 | error_set_single, |
| 3070 | empty_struct, | 3139 | empty_struct, |
| 3071 | 3140 | ||
| 3072 | pub const last_no_payload_tag = Tag.const_slice_u8; | 3141 | pub const last_no_payload_tag = Tag.inferred_alloc_const; |
| 3073 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 3142 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| 3074 | 3143 | ||
| 3075 | pub fn Type(comptime t: Tag) type { | 3144 | pub fn Type(comptime t: Tag) type { |
| ... | @@ -3116,6 +3185,8 @@ pub const Type = extern union { | ... | @@ -3116,6 +3185,8 @@ pub const Type = extern union { |
| 3116 | .anyerror_void_error_union, | 3185 | .anyerror_void_error_union, |
| 3117 | .@"anyframe", | 3186 | .@"anyframe", |
| 3118 | .const_slice_u8, | 3187 | .const_slice_u8, |
| 3188 | .inferred_alloc_const, | ||
| 3189 | .inferred_alloc_mut, | ||
| 3119 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), | 3190 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), |
| 3120 | 3191 | ||
| 3121 | .array_u8, | 3192 | .array_u8, |
src/value.zig+36| ... | @@ -7,6 +7,7 @@ const BigIntMutable = std.math.big.int.Mutable; | ... | @@ -7,6 +7,7 @@ const BigIntMutable = std.math.big.int.Mutable; |
| 7 | const Target = std.Target; | 7 | const Target = std.Target; |
| 8 | const Allocator = std.mem.Allocator; | 8 | const Allocator = std.mem.Allocator; |
| 9 | const Module = @import("Module.zig"); | 9 | const Module = @import("Module.zig"); |
| 10 | const ir = @import("ir.zig"); | ||
| 10 | 11 | ||
| 11 | /// This is the raw data, with no bookkeeping, no memory awareness, | 12 | /// This is the raw data, with no bookkeeping, no memory awareness, |
| 12 | /// no de-duplication, and no type system awareness. | 13 | /// no de-duplication, and no type system awareness. |
| ... | @@ -101,6 +102,9 @@ pub const Value = extern union { | ... | @@ -101,6 +102,9 @@ pub const Value = extern union { |
| 101 | enum_literal, | 102 | enum_literal, |
| 102 | error_set, | 103 | error_set, |
| 103 | @"error", | 104 | @"error", |
| 105 | /// This is a special value that tracks a set of types that have been stored | ||
| 106 | /// to an inferred allocation. It does not support any of the normal value queries. | ||
| 107 | inferred_alloc, | ||
| 104 | 108 | ||
| 105 | pub const last_no_payload_tag = Tag.bool_false; | 109 | pub const last_no_payload_tag = Tag.bool_false; |
| 106 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 110 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| ... | @@ -189,6 +193,7 @@ pub const Value = extern union { | ... | @@ -189,6 +193,7 @@ pub const Value = extern union { |
| 189 | .float_128 => Payload.Float_128, | 193 | .float_128 => Payload.Float_128, |
| 190 | .error_set => Payload.ErrorSet, | 194 | .error_set => Payload.ErrorSet, |
| 191 | .@"error" => Payload.Error, | 195 | .@"error" => Payload.Error, |
| 196 | .inferred_alloc => Payload.InferredAlloc, | ||
| 192 | }; | 197 | }; |
| 193 | } | 198 | } |
| 194 | 199 | ||
| ... | @@ -383,6 +388,8 @@ pub const Value = extern union { | ... | @@ -383,6 +388,8 @@ pub const Value = extern union { |
| 383 | 388 | ||
| 384 | // memory is managed by the declaration | 389 | // memory is managed by the declaration |
| 385 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | 390 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), |
| 391 | |||
| 392 | .inferred_alloc => unreachable, | ||
| 386 | } | 393 | } |
| 387 | } | 394 | } |
| 388 | 395 | ||
| ... | @@ -501,6 +508,7 @@ pub const Value = extern union { | ... | @@ -501,6 +508,7 @@ pub const Value = extern union { |
| 501 | return out_stream.writeAll("}"); | 508 | return out_stream.writeAll("}"); |
| 502 | }, | 509 | }, |
| 503 | .@"error" => return out_stream.print("error.{}", .{val.castTag(.@"error").?.data.name}), | 510 | .@"error" => return out_stream.print("error.{}", .{val.castTag(.@"error").?.data.name}), |
| 511 | .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"), | ||
| 504 | }; | 512 | }; |
| 505 | } | 513 | } |
| 506 | 514 | ||
| ... | @@ -613,6 +621,7 @@ pub const Value = extern union { | ... | @@ -613,6 +621,7 @@ pub const Value = extern union { |
| 613 | .enum_literal, | 621 | .enum_literal, |
| 614 | .@"error", | 622 | .@"error", |
| 615 | .empty_struct_value, | 623 | .empty_struct_value, |
| 624 | .inferred_alloc, | ||
| 616 | => unreachable, | 625 | => unreachable, |
| 617 | }; | 626 | }; |
| 618 | } | 627 | } |
| ... | @@ -683,6 +692,7 @@ pub const Value = extern union { | ... | @@ -683,6 +692,7 @@ pub const Value = extern union { |
| 683 | .error_set, | 692 | .error_set, |
| 684 | .@"error", | 693 | .@"error", |
| 685 | .empty_struct_value, | 694 | .empty_struct_value, |
| 695 | .inferred_alloc, | ||
| 686 | => unreachable, | 696 | => unreachable, |
| 687 | 697 | ||
| 688 | .undef => unreachable, | 698 | .undef => unreachable, |
| ... | @@ -768,6 +778,7 @@ pub const Value = extern union { | ... | @@ -768,6 +778,7 @@ pub const Value = extern union { |
| 768 | .error_set, | 778 | .error_set, |
| 769 | .@"error", | 779 | .@"error", |
| 770 | .empty_struct_value, | 780 | .empty_struct_value, |
| 781 | .inferred_alloc, | ||
| 771 | => unreachable, | 782 | => unreachable, |
| 772 | 783 | ||
| 773 | .undef => unreachable, | 784 | .undef => unreachable, |
| ... | @@ -853,6 +864,7 @@ pub const Value = extern union { | ... | @@ -853,6 +864,7 @@ pub const Value = extern union { |
| 853 | .error_set, | 864 | .error_set, |
| 854 | .@"error", | 865 | .@"error", |
| 855 | .empty_struct_value, | 866 | .empty_struct_value, |
| 867 | .inferred_alloc, | ||
| 856 | => unreachable, | 868 | => unreachable, |
| 857 | 869 | ||
| 858 | .undef => unreachable, | 870 | .undef => unreachable, |
| ... | @@ -966,6 +978,7 @@ pub const Value = extern union { | ... | @@ -966,6 +978,7 @@ pub const Value = extern union { |
| 966 | .error_set, | 978 | .error_set, |
| 967 | .@"error", | 979 | .@"error", |
| 968 | .empty_struct_value, | 980 | .empty_struct_value, |
| 981 | .inferred_alloc, | ||
| 969 | => unreachable, | 982 | => unreachable, |
| 970 | 983 | ||
| 971 | .zero, | 984 | .zero, |
| ... | @@ -1055,6 +1068,7 @@ pub const Value = extern union { | ... | @@ -1055,6 +1068,7 @@ pub const Value = extern union { |
| 1055 | .error_set, | 1068 | .error_set, |
| 1056 | .@"error", | 1069 | .@"error", |
| 1057 | .empty_struct_value, | 1070 | .empty_struct_value, |
| 1071 | .inferred_alloc, | ||
| 1058 | => unreachable, | 1072 | => unreachable, |
| 1059 | 1073 | ||
| 1060 | .zero, | 1074 | .zero, |
| ... | @@ -1213,6 +1227,7 @@ pub const Value = extern union { | ... | @@ -1213,6 +1227,7 @@ pub const Value = extern union { |
| 1213 | .error_set, | 1227 | .error_set, |
| 1214 | .@"error", | 1228 | .@"error", |
| 1215 | .empty_struct_value, | 1229 | .empty_struct_value, |
| 1230 | .inferred_alloc, | ||
| 1216 | => unreachable, | 1231 | => unreachable, |
| 1217 | 1232 | ||
| 1218 | .zero, | 1233 | .zero, |
| ... | @@ -1289,6 +1304,7 @@ pub const Value = extern union { | ... | @@ -1289,6 +1304,7 @@ pub const Value = extern union { |
| 1289 | .error_set, | 1304 | .error_set, |
| 1290 | .@"error", | 1305 | .@"error", |
| 1291 | .empty_struct_value, | 1306 | .empty_struct_value, |
| 1307 | .inferred_alloc, | ||
| 1292 | => unreachable, | 1308 | => unreachable, |
| 1293 | 1309 | ||
| 1294 | .zero, | 1310 | .zero, |
| ... | @@ -1525,6 +1541,8 @@ pub const Value = extern union { | ... | @@ -1525,6 +1541,8 @@ pub const Value = extern union { |
| 1525 | hasher.update(payload.name); | 1541 | hasher.update(payload.name); |
| 1526 | std.hash.autoHash(&hasher, payload.value); | 1542 | std.hash.autoHash(&hasher, payload.value); |
| 1527 | }, | 1543 | }, |
| 1544 | |||
| 1545 | .inferred_alloc => unreachable, | ||
| 1528 | } | 1546 | } |
| 1529 | return hasher.final(); | 1547 | return hasher.final(); |
| 1530 | } | 1548 | } |
| ... | @@ -1602,6 +1620,7 @@ pub const Value = extern union { | ... | @@ -1602,6 +1620,7 @@ pub const Value = extern union { |
| 1602 | .error_set, | 1620 | .error_set, |
| 1603 | .@"error", | 1621 | .@"error", |
| 1604 | .empty_struct_value, | 1622 | .empty_struct_value, |
| 1623 | .inferred_alloc, | ||
| 1605 | => unreachable, | 1624 | => unreachable, |
| 1606 | 1625 | ||
| 1607 | .ref_val => self.castTag(.ref_val).?.data, | 1626 | .ref_val => self.castTag(.ref_val).?.data, |
| ... | @@ -1687,6 +1706,7 @@ pub const Value = extern union { | ... | @@ -1687,6 +1706,7 @@ pub const Value = extern union { |
| 1687 | .error_set, | 1706 | .error_set, |
| 1688 | .@"error", | 1707 | .@"error", |
| 1689 | .empty_struct_value, | 1708 | .empty_struct_value, |
| 1709 | .inferred_alloc, | ||
| 1690 | => unreachable, | 1710 | => unreachable, |
| 1691 | 1711 | ||
| 1692 | .empty_array => unreachable, // out of bounds array index | 1712 | .empty_array => unreachable, // out of bounds array index |
| ... | @@ -1793,6 +1813,7 @@ pub const Value = extern union { | ... | @@ -1793,6 +1813,7 @@ pub const Value = extern union { |
| 1793 | 1813 | ||
| 1794 | .undef => unreachable, | 1814 | .undef => unreachable, |
| 1795 | .unreachable_value => unreachable, | 1815 | .unreachable_value => unreachable, |
| 1816 | .inferred_alloc => unreachable, | ||
| 1796 | .null_value => true, | 1817 | .null_value => true, |
| 1797 | }; | 1818 | }; |
| 1798 | } | 1819 | } |
| ... | @@ -1801,6 +1822,7 @@ pub const Value = extern union { | ... | @@ -1801,6 +1822,7 @@ pub const Value = extern union { |
| 1801 | pub fn isFloat(self: Value) bool { | 1822 | pub fn isFloat(self: Value) bool { |
| 1802 | return switch (self.tag()) { | 1823 | return switch (self.tag()) { |
| 1803 | .undef => unreachable, | 1824 | .undef => unreachable, |
| 1825 | .inferred_alloc => unreachable, | ||
| 1804 | 1826 | ||
| 1805 | .float_16, | 1827 | .float_16, |
| 1806 | .float_32, | 1828 | .float_32, |
| ... | @@ -1890,6 +1912,7 @@ pub const Value = extern union { | ... | @@ -1890,6 +1912,7 @@ pub const Value = extern union { |
| 1890 | 1912 | ||
| 1891 | .undef => unreachable, | 1913 | .undef => unreachable, |
| 1892 | .unreachable_value => unreachable, | 1914 | .unreachable_value => unreachable, |
| 1915 | .inferred_alloc => unreachable, | ||
| 1893 | }; | 1916 | }; |
| 1894 | } | 1917 | } |
| 1895 | 1918 | ||
| ... | @@ -2020,6 +2043,19 @@ pub const Value = extern union { | ... | @@ -2020,6 +2043,19 @@ pub const Value = extern union { |
| 2020 | value: u16, | 2043 | value: u16, |
| 2021 | }, | 2044 | }, |
| 2022 | }; | 2045 | }; |
| 2046 | |||
| 2047 | pub const InferredAlloc = struct { | ||
| 2048 | pub const base_tag = Tag.inferred_alloc; | ||
| 2049 | |||
| 2050 | base: Payload = .{ .tag = base_tag }, | ||
| 2051 | data: struct { | ||
| 2052 | /// The value stored in the inferred allocation. This will go into | ||
| 2053 | /// peer type resolution. This is stored in a separate list so that | ||
| 2054 | /// the items are contiguous in memory and thus can be passed to | ||
| 2055 | /// `Module.resolvePeerTypes`. | ||
| 2056 | stored_inst_list: std.ArrayListUnmanaged(*ir.Inst) = .{}, | ||
| 2057 | }, | ||
| 2058 | }; | ||
| 2023 | }; | 2059 | }; |
| 2024 | 2060 | ||
| 2025 | /// Big enough to fit any non-BigInt value | 2061 | /// Big enough to fit any non-BigInt value |
src/zir.zig+12| ... | @@ -241,12 +241,20 @@ pub const Inst = struct { | ... | @@ -241,12 +241,20 @@ pub const Inst = struct { |
| 241 | const_slice_type, | 241 | const_slice_type, |
| 242 | /// Create a pointer type with attributes | 242 | /// Create a pointer type with attributes |
| 243 | ptr_type, | 243 | ptr_type, |
| 244 | /// Each `store_to_inferred_ptr` puts the type of the stored value into a set, | ||
| 245 | /// and then `resolve_inferred_alloc` triggers peer type resolution on the set. | ||
| 246 | /// The operand is a `alloc_inferred` or `alloc_inferred_mut` instruction, which | ||
| 247 | /// is the allocation that needs to have its type inferred. | ||
| 248 | resolve_inferred_alloc, | ||
| 244 | /// Slice operation `array_ptr[start..end:sentinel]` | 249 | /// Slice operation `array_ptr[start..end:sentinel]` |
| 245 | slice, | 250 | slice, |
| 246 | /// Slice operation with just start `lhs[rhs..]` | 251 | /// Slice operation with just start `lhs[rhs..]` |
| 247 | slice_start, | 252 | slice_start, |
| 248 | /// Write a value to a pointer. For loading, see `deref`. | 253 | /// Write a value to a pointer. For loading, see `deref`. |
| 249 | store, | 254 | store, |
| 255 | /// Same as `store` but the type of the value being stored will be used to infer | ||
| 256 | /// the pointer type. | ||
| 257 | store_to_inferred_ptr, | ||
| 250 | /// String Literal. Makes an anonymous Decl and then takes a pointer to it. | 258 | /// String Literal. Makes an anonymous Decl and then takes a pointer to it. |
| 251 | str, | 259 | str, |
| 252 | /// Arithmetic subtraction. Asserts no integer overflow. | 260 | /// Arithmetic subtraction. Asserts no integer overflow. |
| ... | @@ -319,6 +327,7 @@ pub const Inst = struct { | ... | @@ -319,6 +327,7 @@ pub const Inst = struct { |
| 319 | .ref, | 327 | .ref, |
| 320 | .bitcast_ref, | 328 | .bitcast_ref, |
| 321 | .typeof, | 329 | .typeof, |
| 330 | .resolve_inferred_alloc, | ||
| 322 | .single_const_ptr_type, | 331 | .single_const_ptr_type, |
| 323 | .single_mut_ptr_type, | 332 | .single_mut_ptr_type, |
| 324 | .many_const_ptr_type, | 333 | .many_const_ptr_type, |
| ... | @@ -355,6 +364,7 @@ pub const Inst = struct { | ... | @@ -355,6 +364,7 @@ pub const Inst = struct { |
| 355 | .shl, | 364 | .shl, |
| 356 | .shr, | 365 | .shr, |
| 357 | .store, | 366 | .store, |
| 367 | .store_to_inferred_ptr, | ||
| 358 | .sub, | 368 | .sub, |
| 359 | .subwrap, | 369 | .subwrap, |
| 360 | .cmp_lt, | 370 | .cmp_lt, |
| ... | @@ -498,6 +508,7 @@ pub const Inst = struct { | ... | @@ -498,6 +508,7 @@ pub const Inst = struct { |
| 498 | .mut_slice_type, | 508 | .mut_slice_type, |
| 499 | .const_slice_type, | 509 | .const_slice_type, |
| 500 | .store, | 510 | .store, |
| 511 | .store_to_inferred_ptr, | ||
| 501 | .str, | 512 | .str, |
| 502 | .sub, | 513 | .sub, |
| 503 | .subwrap, | 514 | .subwrap, |
| ... | @@ -522,6 +533,7 @@ pub const Inst = struct { | ... | @@ -522,6 +533,7 @@ pub const Inst = struct { |
| 522 | .import, | 533 | .import, |
| 523 | .switch_range, | 534 | .switch_range, |
| 524 | .typeof_peer, | 535 | .typeof_peer, |
| 536 | .resolve_inferred_alloc, | ||
| 525 | => false, | 537 | => false, |
| 526 | 538 | ||
| 527 | .@"break", | 539 | .@"break", |
src/zir_sema.zig+87-10| ... | @@ -10,10 +10,12 @@ | ... | @@ -10,10 +10,12 @@ |
| 10 | const std = @import("std"); | 10 | const std = @import("std"); |
| 11 | const mem = std.mem; | 11 | const mem = std.mem; |
| 12 | const Allocator = std.mem.Allocator; | 12 | const Allocator = std.mem.Allocator; |
| 13 | const assert = std.debug.assert; | ||
| 14 | const log = std.log.scoped(.sema); | ||
| 15 | |||
| 13 | const Value = @import("value.zig").Value; | 16 | const Value = @import("value.zig").Value; |
| 14 | const Type = @import("type.zig").Type; | 17 | const Type = @import("type.zig").Type; |
| 15 | const TypedValue = @import("TypedValue.zig"); | 18 | const TypedValue = @import("TypedValue.zig"); |
| 16 | const assert = std.debug.assert; | ||
| 17 | const ir = @import("ir.zig"); | 19 | const ir = @import("ir.zig"); |
| 18 | const zir = @import("zir.zig"); | 20 | const zir = @import("zir.zig"); |
| 19 | const Module = @import("Module.zig"); | 21 | const Module = @import("Module.zig"); |
| ... | @@ -28,8 +30,18 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -28,8 +30,18 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 28 | switch (old_inst.tag) { | 30 | switch (old_inst.tag) { |
| 29 | .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?), | 31 | .alloc => return analyzeInstAlloc(mod, scope, old_inst.castTag(.alloc).?), |
| 30 | .alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?), | 32 | .alloc_mut => return analyzeInstAllocMut(mod, scope, old_inst.castTag(.alloc_mut).?), |
| 31 | .alloc_inferred => return analyzeInstAllocInferred(mod, scope, old_inst.castTag(.alloc_inferred).?), | 33 | .alloc_inferred => return analyzeInstAllocInferred( |
| 32 | .alloc_inferred_mut => return analyzeInstAllocInferredMut(mod, scope, old_inst.castTag(.alloc_inferred_mut).?), | 34 | mod, |
| 35 | scope, | ||
| 36 | old_inst.castTag(.alloc_inferred).?, | ||
| 37 | .inferred_alloc_const, | ||
| 38 | ), | ||
| 39 | .alloc_inferred_mut => return analyzeInstAllocInferred( | ||
| 40 | mod, | ||
| 41 | scope, | ||
| 42 | old_inst.castTag(.alloc_inferred_mut).?, | ||
| 43 | .inferred_alloc_mut, | ||
| 44 | ), | ||
| 33 | .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?), | 45 | .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?), |
| 34 | .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?), | 46 | .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?), |
| 35 | .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?), | 47 | .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?), |
| ... | @@ -55,8 +67,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! | ... | @@ -55,8 +67,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! |
| 55 | .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?), | 67 | .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?), |
| 56 | .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?), | 68 | .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?), |
| 57 | .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), | 69 | .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), |
| 70 | .resolve_inferred_alloc => return analyzeInstResolveInferredAlloc(mod, scope, old_inst.castTag(.resolve_inferred_alloc).?), | ||
| 58 | .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), | 71 | .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), |
| 59 | .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), | 72 | .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), |
| 73 | .store_to_inferred_ptr => return analyzeInstStoreToInferredPtr(mod, scope, old_inst.castTag(.store_to_inferred_ptr).?), | ||
| 60 | .single_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One), | 74 | .single_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?, false, .One), |
| 61 | .single_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One), | 75 | .single_mut_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?, true, .One), |
| 62 | .many_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many), | 76 | .many_const_ptr_type => return analyzeInstSimplePtrType(mod, scope, old_inst.castTag(.many_const_ptr_type).?, false, .Many), |
| ... | @@ -419,20 +433,83 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro | ... | @@ -419,20 +433,83 @@ fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerErro |
| 419 | 433 | ||
| 420 | fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | 434 | fn analyzeInstAllocMut(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { |
| 421 | const var_type = try resolveType(mod, scope, inst.positionals.operand); | 435 | const var_type = try resolveType(mod, scope, inst.positionals.operand); |
| 422 | if (!var_type.isValidVarType(false)) { | 436 | try mod.validateVarType(scope, inst.base.src, var_type); |
| 423 | return mod.fail(scope, inst.base.src, "variable of type '{}' must be const or comptime", .{var_type}); | ||
| 424 | } | ||
| 425 | const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One); | 437 | const ptr_type = try mod.simplePtrType(scope, inst.base.src, var_type, true, .One); |
| 426 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); | 438 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); |
| 427 | return mod.addNoOp(b, inst.base.src, ptr_type, .alloc); | 439 | return mod.addNoOp(b, inst.base.src, ptr_type, .alloc); |
| 428 | } | 440 | } |
| 429 | 441 | ||
| 430 | fn analyzeInstAllocInferred(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | 442 | fn analyzeInstAllocInferred( |
| 431 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstAllocInferred", .{}); | 443 | mod: *Module, |
| 444 | scope: *Scope, | ||
| 445 | inst: *zir.Inst.NoOp, | ||
| 446 | mut_tag: Type.Tag, | ||
| 447 | ) InnerError!*Inst { | ||
| 448 | const val_payload = try scope.arena().create(Value.Payload.InferredAlloc); | ||
| 449 | val_payload.* = .{ | ||
| 450 | .data = .{}, | ||
| 451 | }; | ||
| 452 | // `Module.constInst` does not add the instruction to the block because it is | ||
| 453 | // not needed in the case of constant values. However here, we plan to "downgrade" | ||
| 454 | // to a normal instruction when we hit `resolve_inferred_alloc`. So we append | ||
| 455 | // to the block even though it is currently a `.constant`. | ||
| 456 | const result = try mod.constInst(scope, inst.base.src, .{ | ||
| 457 | .ty = switch (mut_tag) { | ||
| 458 | .inferred_alloc_const => Type.initTag(.inferred_alloc_const), | ||
| 459 | .inferred_alloc_mut => Type.initTag(.inferred_alloc_mut), | ||
| 460 | else => unreachable, | ||
| 461 | }, | ||
| 462 | .val = Value.initPayload(&val_payload.base), | ||
| 463 | }); | ||
| 464 | const block = try mod.requireFunctionBlock(scope, inst.base.src); | ||
| 465 | try block.instructions.append(mod.gpa, result); | ||
| 466 | return result; | ||
| 467 | } | ||
| 468 | |||
| 469 | fn analyzeInstResolveInferredAlloc( | ||
| 470 | mod: *Module, | ||
| 471 | scope: *Scope, | ||
| 472 | inst: *zir.Inst.UnOp, | ||
| 473 | ) InnerError!*Inst { | ||
| 474 | const ptr = try resolveInst(mod, scope, inst.positionals.operand); | ||
| 475 | const ptr_val = ptr.castTag(.constant).?.val; | ||
| 476 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; | ||
| 477 | const peer_inst_list = inferred_alloc.data.stored_inst_list.items; | ||
| 478 | const final_elem_ty = try mod.resolvePeerTypes(scope, peer_inst_list); | ||
| 479 | const var_is_mut = switch (ptr.ty.tag()) { | ||
| 480 | .inferred_alloc_const => false, | ||
| 481 | .inferred_alloc_mut => true, | ||
| 482 | else => unreachable, | ||
| 483 | }; | ||
| 484 | if (var_is_mut) { | ||
| 485 | try mod.validateVarType(scope, inst.base.src, final_elem_ty); | ||
| 486 | } | ||
| 487 | const final_ptr_ty = try mod.simplePtrType(scope, inst.base.src, final_elem_ty, true, .One); | ||
| 488 | |||
| 489 | // Change it to a normal alloc. | ||
| 490 | ptr.ty = final_ptr_ty; | ||
| 491 | ptr.tag = .alloc; | ||
| 492 | |||
| 493 | return mod.constVoid(scope, inst.base.src); | ||
| 432 | } | 494 | } |
| 433 | 495 | ||
| 434 | fn analyzeInstAllocInferredMut(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | 496 | fn analyzeInstStoreToInferredPtr( |
| 435 | return mod.fail(scope, inst.base.src, "TODO implement analyzeInstAllocInferredMut", .{}); | 497 | mod: *Module, |
| 498 | scope: *Scope, | ||
| 499 | inst: *zir.Inst.BinOp, | ||
| 500 | ) InnerError!*Inst { | ||
| 501 | const ptr = try resolveInst(mod, scope, inst.positionals.lhs); | ||
| 502 | const value = try resolveInst(mod, scope, inst.positionals.rhs); | ||
| 503 | const inferred_alloc = ptr.castTag(.constant).?.val.castTag(.inferred_alloc).?; | ||
| 504 | // Add the stored instruction to the set we will use to resolve peer types | ||
| 505 | // for the inferred allocation. | ||
| 506 | try inferred_alloc.data.stored_inst_list.append(scope.arena(), value); | ||
| 507 | // Create a new alloc with exactly the type the pointer wants. | ||
| 508 | // Later it gets cleaned up by aliasing the alloc we are supposed to be storing to. | ||
| 509 | const ptr_ty = try mod.simplePtrType(scope, inst.base.src, value.ty, true, .One); | ||
| 510 | const b = try mod.requireRuntimeBlock(scope, inst.base.src); | ||
| 511 | const bitcasted_ptr = try mod.addUnOp(b, inst.base.src, ptr_ty, .bitcast, ptr); | ||
| 512 | return mod.storePtr(scope, inst.base.src, bitcasted_ptr, value); | ||
| 436 | } | 513 | } |
| 437 | 514 | ||
| 438 | fn analyzeInstStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { | 515 | fn analyzeInstStore(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { |
test/stage2/cbe.zig+17| ... | @@ -51,6 +51,23 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -51,6 +51,23 @@ pub fn addCases(ctx: *TestContext) !void { |
| 51 | , ""); | 51 | , ""); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | { | ||
| 55 | var case = ctx.exeFromCompiledC("inferred local const and var", .{}); | ||
| 56 | |||
| 57 | case.addCompareOutput( | ||
| 58 | \\fn add(a: i32, b: i32) i32 { | ||
| 59 | \\ return a + b; | ||
| 60 | \\} | ||
| 61 | \\ | ||
| 62 | \\export fn main() c_int { | ||
| 63 | \\ const x = add(1, 2); | ||
| 64 | \\ var y = add(3, 0); | ||
| 65 | \\ y -= x; | ||
| 66 | \\ return y; | ||
| 67 | \\} | ||
| 68 | , ""); | ||
| 69 | } | ||
| 70 | |||
| 54 | ctx.c("empty start function", linux_x64, | 71 | ctx.c("empty start function", linux_x64, |
| 55 | \\export fn _start() noreturn { | 72 | \\export fn _start() noreturn { |
| 56 | \\ unreachable; | 73 | \\ unreachable; |
test/stage2/test.zig+9| ... | @@ -1322,4 +1322,13 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -1322,4 +1322,13 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1322 | \\} | 1322 | \\} |
| 1323 | , &[_][]const u8{":2:5: error: unused for label"}); | 1323 | , &[_][]const u8{":2:5: error: unused for label"}); |
| 1324 | } | 1324 | } |
| 1325 | |||
| 1326 | { | ||
| 1327 | var case = ctx.exe("bad inferred variable type", linux_x64); | ||
| 1328 | case.addError( | ||
| 1329 | \\export fn foo() void { | ||
| 1330 | \\ var x = null; | ||
| 1331 | \\} | ||
| 1332 | , &[_][]const u8{":2:9: error: variable of type '@Type(.Null)' must be const or comptime"}); | ||
| 1333 | } | ||
| 1325 | } | 1334 | } |