authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-03 20:05:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-03 20:05:29-07:00
log2ae72c6f091716a4c1a30928dc1a49c9a1ed312a
tree5dffbaf4d43bab0e2a2835fa0b978cc4b738ac36
parent69d18ad7f05f093b06388877aa4a7b3d6f2664a6

Sema: implement ExportOptions support in `@export`

Also fix switch blocks not emitting their AIR code.

5 files changed, 87 insertions(+), 59 deletions(-)

BRANCH_TODO-2
...@@ -1,5 +1,3 @@...@@ -1,5 +1,3 @@
1 * implement lazy struct field resolution; don't resolve struct fields until
2 they are needed.
3 * AstGen threadlocal1 * AstGen threadlocal
4 * extern "foo" for vars and for functions2 * extern "foo" for vars and for functions
5 * namespace decls table can't reference ZIR memory because it can get modified on updates3 * namespace decls table can't reference ZIR memory because it can get modified on updates
lib/std/start.zig+1-1
...@@ -83,7 +83,7 @@ fn _start2() callconv(.Naked) noreturn {...@@ -83,7 +83,7 @@ fn _start2() callconv(.Naked) noreturn {
83 exit2(0);83 exit2(0);
84}84}
8585
86fn exit2(code: u8) noreturn {86fn exit2(code: usize) noreturn {
87 switch (builtin.stage2_arch) {87 switch (builtin.stage2_arch) {
88 .x86_64 => {88 .x86_64 => {
89 asm volatile ("syscall"89 asm volatile ("syscall"
src/Module.zig+4
...@@ -3273,6 +3273,10 @@ pub fn analyzeExport(...@@ -3273,6 +3273,10 @@ pub fn analyzeExport(
32733273
3274 const owner_decl = scope.ownerDecl().?;3274 const owner_decl = scope.ownerDecl().?;
32753275
3276 log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{
3277 exported_decl.name, borrowed_symbol_name, owner_decl.name,
3278 });
3279
3276 new_export.* = .{3280 new_export.* = .{
3277 .options = .{ .name = symbol_name },3281 .options = .{ .name = symbol_name },
3278 .src = src,3282 .src = src,
src/Sema.zig+73-56
...@@ -1617,6 +1617,18 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner...@@ -1617,6 +1617,18 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner
1617 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);1617 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
1618}1618}
16191619
1620fn resolveBlockBody(
1621 sema: *Sema,
1622 parent_block: *Scope.Block,
1623 src: LazySrcLoc,
1624 child_block: *Scope.Block,
1625 body: []const Zir.Inst.Index,
1626 merges: *Scope.Block.Merges,
1627) InnerError!*Inst {
1628 _ = try sema.analyzeBody(child_block, body);
1629 return sema.analyzeBlockBody(parent_block, src, child_block, merges);
1630}
1631
1620fn analyzeBlockBody(1632fn analyzeBlockBody(
1621 sema: *Sema,1633 sema: *Sema,
1622 parent_block: *Scope.Block,1634 parent_block: *Scope.Block,
...@@ -1711,11 +1723,23 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!...@@ -1711,11 +1723,23 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
1711 const decl_name = sema.code.nullTerminatedString(extra.decl_name);1723 const decl_name = sema.code.nullTerminatedString(extra.decl_name);
1712 const decl = try sema.lookupIdentifier(block, lhs_src, decl_name);1724 const decl = try sema.lookupIdentifier(block, lhs_src, decl_name);
1713 const options = try sema.resolveInstConst(block, rhs_src, extra.options);1725 const options = try sema.resolveInstConst(block, rhs_src, extra.options);
1726 const struct_obj = options.ty.castTag(.@"struct").?.data;
1727 const fields = options.val.castTag(.@"struct").?.data[0..struct_obj.fields.count()];
1728 const name_index = struct_obj.fields.getIndex("name").?;
1729 const linkage_index = struct_obj.fields.getIndex("linkage").?;
1730 const section_index = struct_obj.fields.getIndex("section").?;
1731 const export_name = try fields[name_index].toAllocatedBytes(sema.arena);
1732 const linkage = fields[linkage_index].toEnum(
1733 struct_obj.fields.items()[linkage_index].value.ty,
1734 std.builtin.GlobalLinkage,
1735 );
17141736
1715 // TODO respect the name, linkage, and section options. Until then we export1737 if (linkage != .Strong) {
1716 // as the decl name.1738 return sema.mod.fail(&block.base, src, "TODO: implement exporting with non-strong linkage", .{});
1717 _ = options;1739 }
1718 const export_name = mem.spanZ(decl.name);1740 if (!fields[section_index].isNull()) {
1741 return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{});
1742 }
17191743
1720 try sema.mod.analyzeExport(&block.base, src, export_name, decl);1744 try sema.mod.analyzeExport(&block.base, src, export_name, decl);
1721}1745}
...@@ -3600,7 +3624,39 @@ fn analyzeSwitch(...@@ -3600,7 +3624,39 @@ fn analyzeSwitch(
3600 }),3624 }),
3601 }3625 }
36023626
3603 if (try sema.resolveDefinedValue(block, src, operand)) |operand_val| {3627 const block_inst = try sema.arena.create(Inst.Block);
3628 block_inst.* = .{
3629 .base = .{
3630 .tag = Inst.Block.base_tag,
3631 .ty = undefined, // Set after analysis.
3632 .src = src,
3633 },
3634 .body = undefined,
3635 };
3636
3637 var child_block: Scope.Block = .{
3638 .parent = block,
3639 .sema = sema,
3640 .src_decl = block.src_decl,
3641 .instructions = .{},
3642 // TODO @as here is working around a stage1 miscompilation bug :(
3643 .label = @as(?Scope.Block.Label, Scope.Block.Label{
3644 .zir_block = switch_inst,
3645 .merges = .{
3646 .results = .{},
3647 .br_list = .{},
3648 .block_inst = block_inst,
3649 },
3650 }),
3651 .inlining = block.inlining,
3652 .is_comptime = block.is_comptime,
3653 };
3654 const merges = &child_block.label.?.merges;
3655 defer child_block.instructions.deinit(gpa);
3656 defer merges.results.deinit(gpa);
3657 defer merges.br_list.deinit(gpa);
3658
3659 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {
3604 var extra_index: usize = special.end;3660 var extra_index: usize = special.end;
3605 {3661 {
3606 var scalar_i: usize = 0;3662 var scalar_i: usize = 0;
...@@ -3614,9 +3670,9 @@ fn analyzeSwitch(...@@ -3614,9 +3670,9 @@ fn analyzeSwitch(
36143670
3615 // Validation above ensured these will succeed.3671 // Validation above ensured these will succeed.
3616 const item = sema.resolveInst(item_ref) catch unreachable;3672 const item = sema.resolveInst(item_ref) catch unreachable;
3617 const item_val = sema.resolveConstValue(block, .unneeded, item) catch unreachable;3673 const item_val = sema.resolveConstValue(&child_block, .unneeded, item) catch unreachable;
3618 if (operand_val.eql(item_val)) {3674 if (operand_val.eql(item_val)) {
3619 return sema.resolveBody(block, body);3675 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3620 }3676 }
3621 }3677 }
3622 }3678 }
...@@ -3636,9 +3692,9 @@ fn analyzeSwitch(...@@ -3636,9 +3692,9 @@ fn analyzeSwitch(
3636 for (items) |item_ref| {3692 for (items) |item_ref| {
3637 // Validation above ensured these will succeed.3693 // Validation above ensured these will succeed.
3638 const item = sema.resolveInst(item_ref) catch unreachable;3694 const item = sema.resolveInst(item_ref) catch unreachable;
3639 const item_val = sema.resolveConstValue(block, item.src, item) catch unreachable;3695 const item_val = sema.resolveConstValue(&child_block, item.src, item) catch unreachable;
3640 if (operand_val.eql(item_val)) {3696 if (operand_val.eql(item_val)) {
3641 return sema.resolveBody(block, body);3697 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3642 }3698 }
3643 }3699 }
36443700
...@@ -3650,59 +3706,27 @@ fn analyzeSwitch(...@@ -3650,59 +3706,27 @@ fn analyzeSwitch(
3650 extra_index += 1;3706 extra_index += 1;
36513707
3652 // Validation above ensured these will succeed.3708 // Validation above ensured these will succeed.
3653 const first_tv = sema.resolveInstConst(block, .unneeded, item_first) catch unreachable;3709 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable;
3654 const last_tv = sema.resolveInstConst(block, .unneeded, item_last) catch unreachable;3710 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable;
3655 if (Value.compare(operand_val, .gte, first_tv.val) and3711 if (Value.compare(operand_val, .gte, first_tv.val) and
3656 Value.compare(operand_val, .lte, last_tv.val))3712 Value.compare(operand_val, .lte, last_tv.val))
3657 {3713 {
3658 return sema.resolveBody(block, body);3714 return sema.resolveBlockBody(block, src, &child_block, body, merges);
3659 }3715 }
3660 }3716 }
36613717
3662 extra_index += body_len;3718 extra_index += body_len;
3663 }3719 }
3664 }3720 }
3665 return sema.resolveBody(block, special.body);3721 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
3666 }3722 }
36673723
3668 if (scalar_cases_len + multi_cases_len == 0) {3724 if (scalar_cases_len + multi_cases_len == 0) {
3669 return sema.resolveBody(block, special.body);3725 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
3670 }3726 }
36713727
3672 try sema.requireRuntimeBlock(block, src);3728 try sema.requireRuntimeBlock(block, src);
36733729
3674 const block_inst = try sema.arena.create(Inst.Block);
3675 block_inst.* = .{
3676 .base = .{
3677 .tag = Inst.Block.base_tag,
3678 .ty = undefined, // Set after analysis.
3679 .src = src,
3680 },
3681 .body = undefined,
3682 };
3683
3684 var child_block: Scope.Block = .{
3685 .parent = block,
3686 .sema = sema,
3687 .src_decl = block.src_decl,
3688 .instructions = .{},
3689 // TODO @as here is working around a stage1 miscompilation bug :(
3690 .label = @as(?Scope.Block.Label, Scope.Block.Label{
3691 .zir_block = switch_inst,
3692 .merges = .{
3693 .results = .{},
3694 .br_list = .{},
3695 .block_inst = block_inst,
3696 },
3697 }),
3698 .inlining = block.inlining,
3699 .is_comptime = block.is_comptime,
3700 };
3701 const merges = &child_block.label.?.merges;
3702 defer child_block.instructions.deinit(gpa);
3703 defer merges.results.deinit(gpa);
3704 defer merges.br_list.deinit(gpa);
3705
3706 // TODO when reworking AIR memory layout make multi cases get generated as cases,3730 // TODO when reworking AIR memory layout make multi cases get generated as cases,
3707 // not as part of the "else" block.3731 // not as part of the "else" block.
3708 const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len);3732 const cases = try sema.arena.alloc(Inst.SwitchBr.Case, scalar_cases_len);
...@@ -4614,7 +4638,8 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro...@@ -4614,7 +4638,8 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro
4614}4638}
46154639
4616fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {4640fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4617 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4641 const zir_datas = sema.code.instructions.items(.data);
4642 const inst_data = zir_datas[inst].un_node;
4618 const src = inst_data.src();4643 const src = inst_data.src();
4619 const operand = try sema.resolveInst(inst_data.operand);4644 const operand = try sema.resolveInst(inst_data.operand);
4620 return sema.mod.constType(sema.arena, src, operand.ty);4645 return sema.mod.constType(sema.arena, src, operand.ty);
...@@ -5555,15 +5580,7 @@ fn zirFuncExtended(...@@ -5555,15 +5580,7 @@ fn zirFuncExtended(
5555 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);5580 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
5556 extra_index += 1;5581 extra_index += 1;
5557 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);5582 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
5558 // TODO this needs to resolve other kinds of Value tags rather than5583 break :blk cc_tv.val.toEnum(cc_tv.ty, std.builtin.CallingConvention);
5559 // assuming the tag will be .enum_field_index.
5560 const cc_field_index = cc_tv.val.castTag(.enum_field_index).?.data;
5561 // TODO should `@intToEnum` do this `@intCast` for you?
5562 const cc = @intToEnum(
5563 std.builtin.CallingConvention,
5564 @intCast(@typeInfo(std.builtin.CallingConvention).Enum.tag_type, cc_field_index),
5565 );
5566 break :blk cc;
5567 } else .Unspecified;5584 } else .Unspecified;
55685585
5569 const align_val: Value = if (small.has_align) blk: {5586 const align_val: Value = if (small.has_align) blk: {
src/value.zig+9
...@@ -715,6 +715,15 @@ pub const Value = extern union {...@@ -715,6 +715,15 @@ pub const Value = extern union {
715 };715 };
716 }716 }
717717
718 /// Asserts the type is an enum type.
719 pub fn toEnum(val: Value, enum_ty: Type, comptime E: type) E {
720 // TODO this needs to resolve other kinds of Value tags rather than
721 // assuming the tag will be .enum_field_index.
722 const field_index = val.castTag(.enum_field_index).?.data;
723 // TODO should `@intToEnum` do this `@intCast` for you?
724 return @intToEnum(E, @intCast(@typeInfo(E).Enum.tag_type, field_index));
725 }
726
718 /// Asserts the value is an integer.727 /// Asserts the value is an integer.
719 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {728 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {
720 switch (self.tag()) {729 switch (self.tag()) {