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 @@
55 * modify stage2 CBE tests so that only 1 uses pub export main and the
66 rest use pub fn main
77
8 * get the test runner and `zig test` working
9 * get behavior tests passing for stage2
10
811 * use a hash map for instructions because the array is too big
912 - no, actually modify the Zir.Inst.Ref strategy so that each decl gets
1013 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 {
2828 // self-hosted is capable enough to handle all of the real start.zig logic.
2929 if (builtin.zig_is_stage2) {
3030 if (builtin.output_mode == .Exe) {
31 if (builtin.link_libc or builtin.object_format == .c) {
32 @export(main2, .{ .name = "main" });
31 if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) {
32 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
33 @export(main2, .{ .name = "main" });
34 }
3335 } else {
3436 if (!@hasDecl(root, "_start")) {
3537 @export(_start2, .{ .name = "_start" });
src/Sema.zig+38-1
......@@ -4708,7 +4708,44 @@ fn zirBuiltinSrc(
47084708fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
47094709 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
47104710 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 }
47124749}
47134750
47144751fn 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 {
12141214 if (ptr_info.@"align" != 0) {
12151215 return ptr_info.@"align";
12161216 } else {
1217 return ptr_info.pointee_type.abiAlignment();
1217 return ptr_info.pointee_type.abiAlignment(target);
12181218 }
12191219 },
12201220
src/value.zig+20
......@@ -120,6 +120,8 @@ pub const Value = extern union {
120120 error_union,
121121 /// An instance of a struct.
122122 @"struct",
123 /// An instance of a union.
124 @"union",
123125 /// This is a special value that tracks a set of types that have been stored
124126 /// to an inferred allocation. It does not support any of the normal value queries.
125127 inferred_alloc,
......@@ -228,6 +230,7 @@ pub const Value = extern union {
228230 .@"error" => Payload.Error,
229231 .inferred_alloc => Payload.InferredAlloc,
230232 .@"struct" => Payload.Struct,
233 .@"union" => Payload.Union,
231234 };
232235 }
233236
......@@ -446,6 +449,7 @@ pub const Value = extern union {
446449 return Value{ .ptr_otherwise = &new_payload.base };
447450 },
448451 .@"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
450454 .inferred_alloc => unreachable,
451455 }
......@@ -528,6 +532,9 @@ pub const Value = extern union {
528532 .@"struct" => {
529533 return out_stream.writeAll("(struct value)");
530534 },
535 .@"union" => {
536 return out_stream.writeAll("(union value)");
537 },
531538 .null_value => return out_stream.writeAll("null"),
532539 .undef => return out_stream.writeAll("undefined"),
533540 .zero => return out_stream.writeAll("0"),
......@@ -709,6 +716,7 @@ pub const Value = extern union {
709716 .error_union,
710717 .empty_struct_value,
711718 .@"struct",
719 .@"union",
712720 .inferred_alloc,
713721 .abi_align_default,
714722 => unreachable,
......@@ -1225,6 +1233,7 @@ pub const Value = extern union {
12251233 .export_options_type,
12261234 .extern_options_type,
12271235 .@"struct",
1236 .@"union",
12281237 => @panic("TODO this hash function looks pretty broken. audit it"),
12291238 }
12301239 return hasher.final();
......@@ -1413,6 +1422,7 @@ pub const Value = extern union {
14131422 .error_union,
14141423 .empty_struct_value,
14151424 .@"struct",
1425 .@"union",
14161426 .null_value,
14171427 .abi_align_default,
14181428 => false,
......@@ -1564,6 +1574,16 @@ pub const Value = extern union {
15641574 /// Field values. The number and type are according to the struct type.
15651575 data: [*]Value,
15661576 };
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 };
15671587 };
15681588
15691589 /// Big enough to fit any non-BigInt value