mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
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.
This commit is contained in:
parent
3acd98fa34
commit
a7221ef4e9
@ -5,6 +5,9 @@
|
||||
* modify stage2 CBE tests so that only 1 uses pub export main and the
|
||||
rest use pub fn main
|
||||
|
||||
* get the test runner and `zig test` working
|
||||
* get behavior tests passing for stage2
|
||||
|
||||
* use a hash map for instructions because the array is too big
|
||||
- no, actually modify the Zir.Inst.Ref strategy so that each decl gets
|
||||
their indexes starting at 0 so that we can use an array to store Sema
|
||||
|
||||
@ -28,8 +28,10 @@ comptime {
|
||||
// self-hosted is capable enough to handle all of the real start.zig logic.
|
||||
if (builtin.zig_is_stage2) {
|
||||
if (builtin.output_mode == .Exe) {
|
||||
if (builtin.link_libc or builtin.object_format == .c) {
|
||||
@export(main2, .{ .name = "main" });
|
||||
if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) {
|
||||
if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
|
||||
@export(main2, .{ .name = "main" });
|
||||
}
|
||||
} else {
|
||||
if (!@hasDecl(root, "_start")) {
|
||||
@export(_start2, .{ .name = "_start" });
|
||||
|
||||
39
src/Sema.zig
39
src/Sema.zig
@ -4708,7 +4708,44 @@ fn zirBuiltinSrc(
|
||||
fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeInfo", .{});
|
||||
const ty = try sema.resolveType(block, src, inst_data.operand);
|
||||
const type_info_ty = try sema.getBuiltinType(block, src, "TypeInfo");
|
||||
const target = sema.mod.getTarget();
|
||||
|
||||
switch (ty.zigTypeTag()) {
|
||||
.Fn => {
|
||||
const field_values = try sema.arena.alloc(Value, 6);
|
||||
// calling_convention: CallingConvention,
|
||||
field_values[0] = try Value.Tag.enum_field_index.create(
|
||||
sema.arena,
|
||||
@enumToInt(ty.fnCallingConvention()),
|
||||
);
|
||||
// alignment: comptime_int,
|
||||
field_values[1] = try Value.Tag.int_u64.create(sema.arena, ty.ptrAlignment(target));
|
||||
// is_generic: bool,
|
||||
field_values[2] = Value.initTag(.bool_false); // TODO
|
||||
// is_var_args: bool,
|
||||
field_values[3] = Value.initTag(.bool_false); // TODO
|
||||
// return_type: ?type,
|
||||
field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
|
||||
// args: []const FnArg,
|
||||
field_values[5] = Value.initTag(.null_value); // TODO
|
||||
|
||||
return sema.mod.constInst(sema.arena, src, .{
|
||||
.ty = type_info_ty,
|
||||
.val = try Value.Tag.@"union".create(sema.arena, .{
|
||||
.tag = try Value.Tag.enum_field_index.create(
|
||||
sema.arena,
|
||||
@enumToInt(@typeInfo(std.builtin.TypeInfo).Union.tag_type.?.Fn),
|
||||
),
|
||||
.val = try Value.Tag.@"struct".create(sema.arena, field_values.ptr),
|
||||
}),
|
||||
});
|
||||
},
|
||||
else => |t| return sema.mod.fail(&block.base, src, "TODO: implement zirTypeInfo for {s}", .{
|
||||
@tagName(t),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
|
||||
|
||||
@ -1214,7 +1214,7 @@ pub const Type = extern union {
|
||||
if (ptr_info.@"align" != 0) {
|
||||
return ptr_info.@"align";
|
||||
} else {
|
||||
return ptr_info.pointee_type.abiAlignment();
|
||||
return ptr_info.pointee_type.abiAlignment(target);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -120,6 +120,8 @@ pub const Value = extern union {
|
||||
error_union,
|
||||
/// An instance of a struct.
|
||||
@"struct",
|
||||
/// An instance of a union.
|
||||
@"union",
|
||||
/// This is a special value that tracks a set of types that have been stored
|
||||
/// to an inferred allocation. It does not support any of the normal value queries.
|
||||
inferred_alloc,
|
||||
@ -228,6 +230,7 @@ pub const Value = extern union {
|
||||
.@"error" => Payload.Error,
|
||||
.inferred_alloc => Payload.InferredAlloc,
|
||||
.@"struct" => Payload.Struct,
|
||||
.@"union" => Payload.Union,
|
||||
};
|
||||
}
|
||||
|
||||
@ -446,6 +449,7 @@ pub const Value = extern union {
|
||||
return Value{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
.@"struct" => @panic("TODO can't copy struct value without knowing the type"),
|
||||
.@"union" => @panic("TODO can't copy union value without knowing the type"),
|
||||
|
||||
.inferred_alloc => unreachable,
|
||||
}
|
||||
@ -528,6 +532,9 @@ pub const Value = extern union {
|
||||
.@"struct" => {
|
||||
return out_stream.writeAll("(struct value)");
|
||||
},
|
||||
.@"union" => {
|
||||
return out_stream.writeAll("(union value)");
|
||||
},
|
||||
.null_value => return out_stream.writeAll("null"),
|
||||
.undef => return out_stream.writeAll("undefined"),
|
||||
.zero => return out_stream.writeAll("0"),
|
||||
@ -709,6 +716,7 @@ pub const Value = extern union {
|
||||
.error_union,
|
||||
.empty_struct_value,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
.inferred_alloc,
|
||||
.abi_align_default,
|
||||
=> unreachable,
|
||||
@ -1225,6 +1233,7 @@ pub const Value = extern union {
|
||||
.export_options_type,
|
||||
.extern_options_type,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
=> @panic("TODO this hash function looks pretty broken. audit it"),
|
||||
}
|
||||
return hasher.final();
|
||||
@ -1413,6 +1422,7 @@ pub const Value = extern union {
|
||||
.error_union,
|
||||
.empty_struct_value,
|
||||
.@"struct",
|
||||
.@"union",
|
||||
.null_value,
|
||||
.abi_align_default,
|
||||
=> false,
|
||||
@ -1564,6 +1574,16 @@ pub const Value = extern union {
|
||||
/// Field values. The number and type are according to the struct type.
|
||||
data: [*]Value,
|
||||
};
|
||||
|
||||
pub const Union = struct {
|
||||
pub const base_tag = Tag.@"union";
|
||||
|
||||
base: Payload = .{ .tag = base_tag },
|
||||
data: struct {
|
||||
tag: Value,
|
||||
val: Value,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/// Big enough to fit any non-BigInt value
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user