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 * implement lazy struct field resolution; don't resolve struct fields until
2 they are needed.
31 * AstGen threadlocal
42 * extern "foo" for vars and for functions
53 * 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 {
8383 exit2(0);
8484}
8585
86fn exit2(code: u8) noreturn {
86fn exit2(code: usize) noreturn {
8787 switch (builtin.stage2_arch) {
8888 .x86_64 => {
8989 asm volatile ("syscall"
src/Module.zig+4
......@@ -3273,6 +3273,10 @@ pub fn analyzeExport(
32733273
32743274 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
32763280 new_export.* = .{
32773281 .options = .{ .name = symbol_name },
32783282 .src = src,
src/Sema.zig+73-56
......@@ -1617,6 +1617,18 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Inner
16171617 return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
16181618}
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
16201632fn analyzeBlockBody(
16211633 sema: *Sema,
16221634 parent_block: *Scope.Block,
......@@ -1711,11 +1723,23 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
17111723 const decl_name = sema.code.nullTerminatedString(extra.decl_name);
17121724 const decl = try sema.lookupIdentifier(block, lhs_src, decl_name);
17131725 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 export
1716 // as the decl name.
1717 _ = options;
1718 const export_name = mem.spanZ(decl.name);
1737 if (linkage != .Strong) {
1738 return sema.mod.fail(&block.base, src, "TODO: implement exporting with non-strong linkage", .{});
1739 }
1740 if (!fields[section_index].isNull()) {
1741 return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{});
1742 }
17191743
17201744 try sema.mod.analyzeExport(&block.base, src, export_name, decl);
17211745}
......@@ -3600,7 +3624,39 @@ fn analyzeSwitch(
36003624 }),
36013625 }
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| {
36043660 var extra_index: usize = special.end;
36053661 {
36063662 var scalar_i: usize = 0;
......@@ -3614,9 +3670,9 @@ fn analyzeSwitch(
36143670
36153671 // Validation above ensured these will succeed.
36163672 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;
36183674 if (operand_val.eql(item_val)) {
3619 return sema.resolveBody(block, body);
3675 return sema.resolveBlockBody(block, src, &child_block, body, merges);
36203676 }
36213677 }
36223678 }
......@@ -3636,9 +3692,9 @@ fn analyzeSwitch(
36363692 for (items) |item_ref| {
36373693 // Validation above ensured these will succeed.
36383694 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;
36403696 if (operand_val.eql(item_val)) {
3641 return sema.resolveBody(block, body);
3697 return sema.resolveBlockBody(block, src, &child_block, body, merges);
36423698 }
36433699 }
36443700
......@@ -3650,59 +3706,27 @@ fn analyzeSwitch(
36503706 extra_index += 1;
36513707
36523708 // Validation above ensured these will succeed.
3653 const first_tv = sema.resolveInstConst(block, .unneeded, item_first) catch unreachable;
3654 const last_tv = sema.resolveInstConst(block, .unneeded, item_last) catch unreachable;
3709 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first) catch unreachable;
3710 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last) catch unreachable;
36553711 if (Value.compare(operand_val, .gte, first_tv.val) and
36563712 Value.compare(operand_val, .lte, last_tv.val))
36573713 {
3658 return sema.resolveBody(block, body);
3714 return sema.resolveBlockBody(block, src, &child_block, body, merges);
36593715 }
36603716 }
36613717
36623718 extra_index += body_len;
36633719 }
36643720 }
3665 return sema.resolveBody(block, special.body);
3721 return sema.resolveBlockBody(block, src, &child_block, special.body, merges);
36663722 }
36673723
36683724 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);
36703726 }
36713727
36723728 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
37063730 // TODO when reworking AIR memory layout make multi cases get generated as cases,
37073731 // not as part of the "else" block.
37083732 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
46144638}
46154639
46164640fn 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;
46184643 const src = inst_data.src();
46194644 const operand = try sema.resolveInst(inst_data.operand);
46204645 return sema.mod.constType(sema.arena, src, operand.ty);
......@@ -5555,15 +5580,7 @@ fn zirFuncExtended(
55555580 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
55565581 extra_index += 1;
55575582 const cc_tv = try sema.resolveInstConst(block, cc_src, cc_ref);
5558 // TODO this needs to resolve other kinds of Value tags rather than
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;
5583 break :blk cc_tv.val.toEnum(cc_tv.ty, std.builtin.CallingConvention);
55675584 } else .Unspecified;
55685585
55695586 const align_val: Value = if (small.has_align) blk: {
src/value.zig+9
......@@ -715,6 +715,15 @@ pub const Value = extern union {
715715 };
716716 }
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
718727 /// Asserts the value is an integer.
719728 pub fn toBigInt(self: Value, space: *BigIntSpace) BigIntConst {
720729 switch (self.tag()) {