| author | |
| committer | |
| log | a7221ef4e902e63e72524559a067afcf6c1dfd17 |
| tree | e3cbbbd7bd87409c8da573ecefa7174939ed8020 |
| parent | 3acd98fa3423d67cdce7118bc6abe736309e71df |
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 | 5 | * modify stage2 CBE tests so that only 1 uses pub export main and the |
| 6 | 6 | rest use pub fn main |
| 7 | 7 | |
| 8 | * get the test runner and `zig test` working | |
| 9 | * get behavior tests passing for stage2 | |
| 10 | ||
| 8 | 11 | * use a hash map for instructions because the array is too big |
| 9 | 12 | - no, actually modify the Zir.Inst.Ref strategy so that each decl gets |
| 10 | 13 | 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 | 28 | // self-hosted is capable enough to handle all of the real start.zig logic. |
| 29 | 29 | if (builtin.zig_is_stage2) { |
| 30 | 30 | 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 | } | |
| 33 | 35 | } else { |
| 34 | 36 | if (!@hasDecl(root, "_start")) { |
| 35 | 37 | @export(_start2, .{ .name = "_start" }); |
src/Sema.zig+38-1| ... | ... | @@ -4708,7 +4708,44 @@ fn zirBuiltinSrc( |
| 4708 | 4708 | fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { |
| 4709 | 4709 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 4710 | 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 | } |
| 4713 | 4750 | |
| 4714 | 4751 | fn 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 | 1214 | if (ptr_info.@"align" != 0) { |
| 1215 | 1215 | return ptr_info.@"align"; |
| 1216 | 1216 | } else { |
| 1217 | return ptr_info.pointee_type.abiAlignment(); | |
| 1217 | return ptr_info.pointee_type.abiAlignment(target); | |
| 1218 | 1218 | } |
| 1219 | 1219 | }, |
| 1220 | 1220 |
src/value.zig+20| ... | ... | @@ -120,6 +120,8 @@ pub const Value = extern union { |
| 120 | 120 | error_union, |
| 121 | 121 | /// An instance of a struct. |
| 122 | 122 | @"struct", |
| 123 | /// An instance of a union. | |
| 124 | @"union", | |
| 123 | 125 | /// This is a special value that tracks a set of types that have been stored |
| 124 | 126 | /// to an inferred allocation. It does not support any of the normal value queries. |
| 125 | 127 | inferred_alloc, |
| ... | ... | @@ -228,6 +230,7 @@ pub const Value = extern union { |
| 228 | 230 | .@"error" => Payload.Error, |
| 229 | 231 | .inferred_alloc => Payload.InferredAlloc, |
| 230 | 232 | .@"struct" => Payload.Struct, |
| 233 | .@"union" => Payload.Union, | |
| 231 | 234 | }; |
| 232 | 235 | } |
| 233 | 236 | |
| ... | ... | @@ -446,6 +449,7 @@ pub const Value = extern union { |
| 446 | 449 | return Value{ .ptr_otherwise = &new_payload.base }; |
| 447 | 450 | }, |
| 448 | 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"), | |
| 449 | 453 | |
| 450 | 454 | .inferred_alloc => unreachable, |
| 451 | 455 | } |
| ... | ... | @@ -528,6 +532,9 @@ pub const Value = extern union { |
| 528 | 532 | .@"struct" => { |
| 529 | 533 | return out_stream.writeAll("(struct value)"); |
| 530 | 534 | }, |
| 535 | .@"union" => { | |
| 536 | return out_stream.writeAll("(union value)"); | |
| 537 | }, | |
| 531 | 538 | .null_value => return out_stream.writeAll("null"), |
| 532 | 539 | .undef => return out_stream.writeAll("undefined"), |
| 533 | 540 | .zero => return out_stream.writeAll("0"), |
| ... | ... | @@ -709,6 +716,7 @@ pub const Value = extern union { |
| 709 | 716 | .error_union, |
| 710 | 717 | .empty_struct_value, |
| 711 | 718 | .@"struct", |
| 719 | .@"union", | |
| 712 | 720 | .inferred_alloc, |
| 713 | 721 | .abi_align_default, |
| 714 | 722 | => unreachable, |
| ... | ... | @@ -1225,6 +1233,7 @@ pub const Value = extern union { |
| 1225 | 1233 | .export_options_type, |
| 1226 | 1234 | .extern_options_type, |
| 1227 | 1235 | .@"struct", |
| 1236 | .@"union", | |
| 1228 | 1237 | => @panic("TODO this hash function looks pretty broken. audit it"), |
| 1229 | 1238 | } |
| 1230 | 1239 | return hasher.final(); |
| ... | ... | @@ -1413,6 +1422,7 @@ pub const Value = extern union { |
| 1413 | 1422 | .error_union, |
| 1414 | 1423 | .empty_struct_value, |
| 1415 | 1424 | .@"struct", |
| 1425 | .@"union", | |
| 1416 | 1426 | .null_value, |
| 1417 | 1427 | .abi_align_default, |
| 1418 | 1428 | => false, |
| ... | ... | @@ -1564,6 +1574,16 @@ pub const Value = extern union { |
| 1564 | 1574 | /// Field values. The number and type are according to the struct type. |
| 1565 | 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 | }; |
| 1568 | 1588 | |
| 1569 | 1589 | /// Big enough to fit any non-BigInt value |