authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-06 22:30:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-06 22:30:44-07:00
loga7221ef4e902e63e72524559a067afcf6c1dfd17
treee3cbbbd7bd87409c8da573ecefa7174939ed8020
parent3acd98fa3423d67cdce7118bc6abe736309e71df

Sema: implement `@typeInfo` for functions

The goal is to get start code to be able to inspect the calling convention of `main` in order to determine whether to export a main for libc to call, or to allow the root source file to do it.

5 files changed, 66 insertions(+), 4 deletions(-)

BRANCH_TODO+3
...@@ -5,6 +5,9 @@...@@ -5,6 +5,9 @@
5 * modify stage2 CBE tests so that only 1 uses pub export main and the5 * modify stage2 CBE tests so that only 1 uses pub export main and the
6 rest use pub fn main6 rest use pub fn main
77
8 * get the test runner and `zig test` working
9 * get behavior tests passing for stage2
10
8 * use a hash map for instructions because the array is too big11 * use a hash map for instructions because the array is too big
9 - no, actually modify the Zir.Inst.Ref strategy so that each decl gets12 - no, actually modify the Zir.Inst.Ref strategy so that each decl gets
10 their indexes starting at 0 so that we can use an array to store Sema13 their indexes starting at 0 so that we can use an array to store Sema
lib/std/start.zig+4-2
...@@ -28,8 +28,10 @@ comptime {...@@ -28,8 +28,10 @@ comptime {
28 // self-hosted is capable enough to handle all of the real start.zig logic.28 // self-hosted is capable enough to handle all of the real start.zig logic.
29 if (builtin.zig_is_stage2) {29 if (builtin.zig_is_stage2) {
30 if (builtin.output_mode == .Exe) {30 if (builtin.output_mode == .Exe) {
31 if (builtin.link_libc or builtin.object_format == .c) {31 if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) {
32 @export(main2, .{ .name = "main" });32 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
33 @export(main2, .{ .name = "main" });
34 }
33 } else {35 } else {
34 if (!@hasDecl(root, "_start")) {36 if (!@hasDecl(root, "_start")) {
35 @export(_start2, .{ .name = "_start" });37 @export(_start2, .{ .name = "_start" });
src/Sema.zig+38-1
...@@ -4708,7 +4708,44 @@ fn zirBuiltinSrc(...@@ -4708,7 +4708,44 @@ fn zirBuiltinSrc(
4708fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {4708fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
4709 const inst_data = sema.code.instructions.items(.data)[inst].un_node;4709 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
4710 const src = inst_data.src();4710 const src = inst_data.src();
4711 return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeInfo", .{});4711 const ty = try sema.resolveType(block, src, inst_data.operand);
4712 const type_info_ty = try sema.getBuiltinType(block, src, "TypeInfo");
4713 const target = sema.mod.getTarget();
4714
4715 switch (ty.zigTypeTag()) {
4716 .Fn => {
4717 const field_values = try sema.arena.alloc(Value, 6);
4718 // calling_convention: CallingConvention,
4719 field_values[0] = try Value.Tag.enum_field_index.create(
4720 sema.arena,
4721 @enumToInt(ty.fnCallingConvention()),
4722 );
4723 // alignment: comptime_int,
4724 field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.ptrAlignment(target));
4725 // is_generic: bool,
4726 field_values[2] = Value.initTag(.bool_false); // TODO
4727 // is_var_args: bool,
4728 field_values[3] = Value.initTag(.bool_false); // TODO
4729 // return_type: ?type,
4730 field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
4731 // args: []const FnArg,
4732 field_values[5] = Value.initTag(.null_value); // TODO
4733
4734 return sema.mod.constInst(sema.arena, src, .{
4735 .ty = type_info_ty,
4736 .val = try Value.Tag.@"union".create(sema.arena, .{
4737 .tag = try Value.Tag.enum_field_index.create(
4738 sema.arena,
4739 @enumToInt(@typeInfo(std.builtin.TypeInfo).Union.tag_type.?.Fn),
4740 ),
4741 .val = try Value.Tag.@"struct".create(sema.arena, field_values.ptr),
4742 }),
4743 });
4744 },
4745 else => |t| return sema.mod.fail(&block.base, src, "TODO: implement zirTypeInfo for {s}", .{
4746 @tagName(t),
4747 }),
4748 }
4712}4749}
47134750
4714fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {4751fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
src/type.zig+1-1
...@@ -1214,7 +1214,7 @@ pub const Type = extern union {...@@ -1214,7 +1214,7 @@ pub const Type = extern union {
1214 if (ptr_info.@"align" != 0) {1214 if (ptr_info.@"align" != 0) {
1215 return ptr_info.@"align";1215 return ptr_info.@"align";
1216 } else {1216 } else {
1217 return ptr_info.pointee_type.abiAlignment();1217 return ptr_info.pointee_type.abiAlignment(target);
1218 }1218 }
1219 },1219 },
12201220
src/value.zig+20
...@@ -120,6 +120,8 @@ pub const Value = extern union {...@@ -120,6 +120,8 @@ pub const Value = extern union {
120 error_union,120 error_union,
121 /// An instance of a struct.121 /// An instance of a struct.
122 @"struct",122 @"struct",
123 /// An instance of a union.
124 @"union",
123 /// This is a special value that tracks a set of types that have been stored125 /// This is a special value that tracks a set of types that have been stored
124 /// to an inferred allocation. It does not support any of the normal value queries.126 /// to an inferred allocation. It does not support any of the normal value queries.
125 inferred_alloc,127 inferred_alloc,
...@@ -228,6 +230,7 @@ pub const Value = extern union {...@@ -228,6 +230,7 @@ pub const Value = extern union {
228 .@"error" => Payload.Error,230 .@"error" => Payload.Error,
229 .inferred_alloc => Payload.InferredAlloc,231 .inferred_alloc => Payload.InferredAlloc,
230 .@"struct" => Payload.Struct,232 .@"struct" => Payload.Struct,
233 .@"union" => Payload.Union,
231 };234 };
232 }235 }
233236
...@@ -446,6 +449,7 @@ pub const Value = extern union {...@@ -446,6 +449,7 @@ pub const Value = extern union {
446 return Value{ .ptr_otherwise = &new_payload.base };449 return Value{ .ptr_otherwise = &new_payload.base };
447 },450 },
448 .@"struct" => @panic("TODO can't copy struct value without knowing the type"),451 .@"struct" => @panic("TODO can't copy struct value without knowing the type"),
452 .@"union" => @panic("TODO can't copy union value without knowing the type"),
449453
450 .inferred_alloc => unreachable,454 .inferred_alloc => unreachable,
451 }455 }
...@@ -528,6 +532,9 @@ pub const Value = extern union {...@@ -528,6 +532,9 @@ pub const Value = extern union {
528 .@"struct" => {532 .@"struct" => {
529 return out_stream.writeAll("(struct value)");533 return out_stream.writeAll("(struct value)");
530 },534 },
535 .@"union" => {
536 return out_stream.writeAll("(union value)");
537 },
531 .null_value => return out_stream.writeAll("null"),538 .null_value => return out_stream.writeAll("null"),
532 .undef => return out_stream.writeAll("undefined"),539 .undef => return out_stream.writeAll("undefined"),
533 .zero => return out_stream.writeAll("0"),540 .zero => return out_stream.writeAll("0"),
...@@ -709,6 +716,7 @@ pub const Value = extern union {...@@ -709,6 +716,7 @@ pub const Value = extern union {
709 .error_union,716 .error_union,
710 .empty_struct_value,717 .empty_struct_value,
711 .@"struct",718 .@"struct",
719 .@"union",
712 .inferred_alloc,720 .inferred_alloc,
713 .abi_align_default,721 .abi_align_default,
714 => unreachable,722 => unreachable,
...@@ -1225,6 +1233,7 @@ pub const Value = extern union {...@@ -1225,6 +1233,7 @@ pub const Value = extern union {
1225 .export_options_type,1233 .export_options_type,
1226 .extern_options_type,1234 .extern_options_type,
1227 .@"struct",1235 .@"struct",
1236 .@"union",
1228 => @panic("TODO this hash function looks pretty broken. audit it"),1237 => @panic("TODO this hash function looks pretty broken. audit it"),
1229 }1238 }
1230 return hasher.final();1239 return hasher.final();
...@@ -1413,6 +1422,7 @@ pub const Value = extern union {...@@ -1413,6 +1422,7 @@ pub const Value = extern union {
1413 .error_union,1422 .error_union,
1414 .empty_struct_value,1423 .empty_struct_value,
1415 .@"struct",1424 .@"struct",
1425 .@"union",
1416 .null_value,1426 .null_value,
1417 .abi_align_default,1427 .abi_align_default,
1418 => false,1428 => false,
...@@ -1564,6 +1574,16 @@ pub const Value = extern union {...@@ -1564,6 +1574,16 @@ pub const Value = extern union {
1564 /// Field values. The number and type are according to the struct type.1574 /// Field values. The number and type are according to the struct type.
1565 data: [*]Value,1575 data: [*]Value,
1566 };1576 };
1577
1578 pub const Union = struct {
1579 pub const base_tag = Tag.@"union";
1580
1581 base: Payload = .{ .tag = base_tag },
1582 data: struct {
1583 tag: Value,
1584 val: Value,
1585 },
1586 };
1567 };1587 };
15681588
1569 /// Big enough to fit any non-BigInt value1589 /// Big enough to fit any non-BigInt value