stage2: get Module and Sema compiling again
There are some `@panic("TODO")` in there but I'm trying to get the
branch to the point where collaborators can jump in.
Next is to repair the seam between LazySrcLoc and codegen's expected
absolute file offsets.
This commit is contained in:
@@ -27,6 +27,8 @@ Performance optimizations to look into:
|
||||
and have it reference source code bytes. Another idea: null terminated
|
||||
string variants which avoid having to store the length.
|
||||
- Look into this for enum literals too
|
||||
* make ret_type and ret_ptr instructions be implied indexes; no need to have
|
||||
tags associated with them.
|
||||
|
||||
|
||||
Random snippets of code that I deleted and need to make sure get
|
||||
|
||||
229
src/Module.zig
229
src/Module.zig
@@ -462,11 +462,11 @@ pub const Scope = struct {
|
||||
switch (scope.tag) {
|
||||
.file => return &scope.cast(File).?.tree,
|
||||
.block => return &scope.cast(Block).?.src_decl.container.file_scope.tree,
|
||||
.gen_zir => return &scope.cast(GenZir).?.decl.container.file_scope.tree,
|
||||
.gen_zir => return &scope.cast(GenZir).?.zir_code.decl.container.file_scope.tree,
|
||||
.local_val => return &scope.cast(LocalVal).?.gen_zir.zir_code.decl.container.file_scope.tree,
|
||||
.local_ptr => return &scope.cast(LocalPtr).?.gen_zir.zir_code.decl.container.file_scope.tree,
|
||||
.container => return &scope.cast(Container).?.file_scope.tree,
|
||||
.gen_suspend => return &scope.cast(GenZir).?.decl.container.file_scope.tree,
|
||||
.gen_suspend => return &scope.cast(GenZir).?.zir_code.decl.container.file_scope.tree,
|
||||
.gen_nosuspend => return &scope.cast(Nosuspend).?.gen_zir.zir_code.decl.container.file_scope.tree,
|
||||
.decl_ref => return &scope.cast(DeclRef).?.decl.container.file_scope.tree,
|
||||
}
|
||||
@@ -968,18 +968,42 @@ pub const Scope = struct {
|
||||
used: bool = false,
|
||||
};
|
||||
|
||||
/// Only valid to call on the top of the `GenZir` stack. Completes the
|
||||
/// `WipZirCode` into a `zir.Code`. Leaves the `WipZirCode` in an
|
||||
/// initialized, but empty, state.
|
||||
pub fn finish(gz: *GenZir) !zir.Code {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
const root_start = @intCast(u32, gz.zir_code.extra.items.len);
|
||||
const root_len = @intCast(u32, gz.instructions.items.len);
|
||||
try gz.zir_code.extra.appendSlice(gpa, gz.instructions.items);
|
||||
return zir.Code{
|
||||
.instructions = gz.zir_code.instructions.toOwnedSlice(),
|
||||
.string_bytes = gz.zir_code.string_bytes.toOwnedSlice(gpa),
|
||||
.extra = gz.zir_code.extra.toOwnedSlice(gpa),
|
||||
.root_start = root_start,
|
||||
.root_len = root_len,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn tokSrcLoc(gz: *GenZir, token_index: ast.TokenIndex) LazySrcLoc {
|
||||
const decl_token = gz.zir_code.decl.srcToken();
|
||||
return .{ .token_offset = token_index - decl_token };
|
||||
}
|
||||
|
||||
pub fn addFnTypeCc(gz: *GenZir, args: struct {
|
||||
param_types: []const zir.Inst.Ref,
|
||||
ret_ty: zir.Inst.Ref,
|
||||
cc: zir.Inst.Ref,
|
||||
}) !zir.Inst.Index {
|
||||
assert(args.ret_ty != 0);
|
||||
assert(args.cc != 0);
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.len +
|
||||
try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.items.len +
|
||||
@typeInfo(zir.Inst.FnTypeCc).Struct.fields.len + args.param_types.len);
|
||||
|
||||
const payload_index = gz.addExtra(zir.Inst.FnTypeCc, .{
|
||||
const payload_index = gz.zir_code.addExtra(zir.Inst.FnTypeCc{
|
||||
.cc = args.cc,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
}) catch unreachable; // Capacity is ensured above.
|
||||
@@ -989,7 +1013,7 @@ pub const Scope = struct {
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
.tag = .fn_type_cc,
|
||||
.data = .{ .fn_type = .{
|
||||
.return_type = ret_ty,
|
||||
.return_type = args.ret_ty,
|
||||
.payload_index = payload_index,
|
||||
} },
|
||||
});
|
||||
@@ -1003,13 +1027,14 @@ pub const Scope = struct {
|
||||
ret_ty: zir.Inst.Ref,
|
||||
param_types: []const zir.Inst.Ref,
|
||||
) !zir.Inst.Index {
|
||||
assert(ret_ty != 0);
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.len +
|
||||
try gz.zir_code.extra.ensureCapacity(gpa, gz.zir_code.extra.items.len +
|
||||
@typeInfo(zir.Inst.FnType).Struct.fields.len + param_types.len);
|
||||
|
||||
const payload_index = gz.addExtra(zir.Inst.FnTypeCc, .{
|
||||
const payload_index = gz.zir_code.addExtra(zir.Inst.FnType{
|
||||
.param_types_len = @intCast(u32, param_types.len),
|
||||
}) catch unreachable; // Capacity is ensured above.
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(param_types);
|
||||
@@ -1027,42 +1052,11 @@ pub const Scope = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addRetTok(
|
||||
gz: *GenZir,
|
||||
operand: zir.Inst.Ref,
|
||||
/// Absolute token index. This function does the conversion to Decl offset.
|
||||
abs_tok_index: ast.TokenIndex,
|
||||
) !zir.Inst.Index {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
.tag = .ret_tok,
|
||||
.data = .{ .fn_type = .{
|
||||
.operand = operand,
|
||||
.src_tok = abs_tok_index - gz.zir_code.decl.srcToken(),
|
||||
} },
|
||||
});
|
||||
const result = @intCast(zir.Inst.Ref, new_index + gz.zir_code.ref_start_index);
|
||||
gz.instructions.appendAssumeCapacity(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addInt(gz: *GenZir, integer: u64) !zir.Inst.Index {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
return gz.add(.{
|
||||
.tag = .int,
|
||||
.data = .{ .int = integer },
|
||||
});
|
||||
const result = @intCast(zir.Inst.Ref, new_index + gz.zir_code.ref_start_index);
|
||||
gz.instructions.appendAssumeCapacity(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addUnNode(
|
||||
@@ -1072,21 +1066,14 @@ pub const Scope = struct {
|
||||
/// Absolute node index. This function does the conversion to offset from Decl.
|
||||
abs_node_index: ast.Node.Index,
|
||||
) !zir.Inst.Ref {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
assert(operand != 0);
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .un_node = .{
|
||||
.operand = operand,
|
||||
.src_node = abs_node_index - gz.zir_code.decl.srcNode(),
|
||||
} },
|
||||
});
|
||||
const result = @intCast(zir.Inst.Ref, new_index + gz.zir_code.ref_start_index);
|
||||
gz.instructions.appendAssumeCapacity(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addUnTok(
|
||||
@@ -1096,21 +1083,14 @@ pub const Scope = struct {
|
||||
/// Absolute token index. This function does the conversion to Decl offset.
|
||||
abs_tok_index: ast.TokenIndex,
|
||||
) !zir.Inst.Ref {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
assert(operand != 0);
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .un_tok = .{
|
||||
.operand = operand,
|
||||
.src_tok = abs_tok_index - gz.zir_code.decl.srcToken(),
|
||||
} },
|
||||
});
|
||||
const result = @intCast(zir.Inst.Ref, new_index + gz.zir_code.ref_start_index);
|
||||
gz.instructions.appendAssumeCapacity(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn addBin(
|
||||
@@ -1119,18 +1099,52 @@ pub const Scope = struct {
|
||||
lhs: zir.Inst.Ref,
|
||||
rhs: zir.Inst.Ref,
|
||||
) !zir.Inst.Ref {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
assert(lhs != 0);
|
||||
assert(rhs != 0);
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .bin = .{
|
||||
.lhs = lhs,
|
||||
.rhs = rhs,
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addNode(
|
||||
gz: *GenZir,
|
||||
tag: zir.Inst.Tag,
|
||||
/// Absolute node index. This function does the conversion to offset from Decl.
|
||||
abs_node_index: ast.Node.Index,
|
||||
) !zir.Inst.Ref {
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .node = abs_node_index - gz.zir_code.decl.srcNode() },
|
||||
});
|
||||
}
|
||||
|
||||
/// Asserts that `str` is 8 or fewer bytes.
|
||||
pub fn addSmallStr(
|
||||
gz: *GenZir,
|
||||
tag: zir.Inst.Tag,
|
||||
str: []const u8,
|
||||
) !zir.Inst.Ref {
|
||||
var buf: [9]u8 = undefined;
|
||||
mem.copy(u8, &buf, str);
|
||||
buf[str.len] = 0;
|
||||
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .small_str = .{ .bytes = buf[0..8].* } },
|
||||
});
|
||||
}
|
||||
|
||||
fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
|
||||
const gpa = gz.zir_code.gpa;
|
||||
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
|
||||
try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
|
||||
|
||||
const new_index = gz.zir_code.instructions.len;
|
||||
gz.zir_code.instructions.appendAssumeCapacity(inst);
|
||||
const result = @intCast(zir.Inst.Ref, new_index + gz.zir_code.ref_start_index);
|
||||
gz.instructions.appendAssumeCapacity(result);
|
||||
return result;
|
||||
@@ -1183,6 +1197,7 @@ pub const Scope = struct {
|
||||
/// A Work-In-Progress `zir.Code`. This is a shared parent of all
|
||||
/// `GenZir` scopes. Once the `zir.Code` is produced, this struct
|
||||
/// is deinitialized.
|
||||
/// The `GenZir.finish` function converts this to a `zir.Code`.
|
||||
pub const WipZirCode = struct {
|
||||
instructions: std.MultiArrayList(zir.Inst) = .{},
|
||||
string_bytes: std.ArrayListUnmanaged(u8) = .{},
|
||||
@@ -1194,9 +1209,20 @@ pub const WipZirCode = struct {
|
||||
gpa: *Allocator,
|
||||
arena: *Allocator,
|
||||
|
||||
fn deinit(wip_zir_code: *WipZirCode) void {
|
||||
wip_zir_code.instructions.deinit(wip_zir_code.gpa);
|
||||
wip_zir_code.extra.deinit(wip_zir_code.gpa);
|
||||
pub fn addExtra(wzc: *WipZirCode, extra: anytype) Allocator.Error!u32 {
|
||||
const fields = std.meta.fields(@TypeOf(extra));
|
||||
try wzc.extra.ensureCapacity(wzc.gpa, wzc.extra.items.len + fields.len);
|
||||
const result = @intCast(u32, wzc.extra.items.len);
|
||||
inline for (fields) |field| {
|
||||
comptime assert(field.field_type == u32);
|
||||
wzc.extra.appendAssumeCapacity(@field(extra, field.name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn deinit(wzc: *WipZirCode) void {
|
||||
wzc.instructions.deinit(wzc.gpa);
|
||||
wzc.extra.deinit(wzc.gpa);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1763,18 +1789,22 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
|
||||
.gpa = mod.gpa,
|
||||
};
|
||||
defer wip_zir_code.deinit();
|
||||
|
||||
var gen_scope: Scope.GenZir = .{
|
||||
.force_comptime = true,
|
||||
.parent = &decl.container.base,
|
||||
.zir_code = &wip_zir_code,
|
||||
};
|
||||
defer gen_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const block_expr = node_datas[decl_node].lhs;
|
||||
_ = try astgen.comptimeExpr(mod, &gen_scope.base, .none, block_expr);
|
||||
|
||||
const code = try gen_scope.finish();
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "comptime_block", decl.name, gen_scope.instructions.items) catch {};
|
||||
zir.dumpZir(mod.gpa, "comptime_block", decl.name, code) catch {};
|
||||
}
|
||||
break :blk wip_zir_code.finish();
|
||||
break :blk code;
|
||||
};
|
||||
|
||||
var sema: Sema = .{
|
||||
@@ -1836,11 +1866,13 @@ fn astgenAndSemaFn(
|
||||
.gpa = mod.gpa,
|
||||
};
|
||||
defer fn_type_wip_zir_exec.deinit();
|
||||
|
||||
var fn_type_scope: Scope.GenZir = .{
|
||||
.force_comptime = true,
|
||||
.parent = &decl.container.base,
|
||||
.zir_code = &fn_type_wip_zir_exec,
|
||||
};
|
||||
defer fn_type_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
decl.is_pub = fn_proto.visib_token != null;
|
||||
|
||||
@@ -1855,7 +1887,7 @@ fn astgenAndSemaFn(
|
||||
}
|
||||
break :blk count;
|
||||
};
|
||||
const param_types = try fn_type_scope_arena.allocator.alloc(zir.Inst.Index, param_count);
|
||||
const param_types = try fn_type_scope_arena.allocator.alloc(zir.Inst.Ref, param_count);
|
||||
const type_type_rl: astgen.ResultLoc = .{ .ty = @enumToInt(zir.Const.type_type) };
|
||||
|
||||
var is_var_args = false;
|
||||
@@ -1970,11 +2002,11 @@ fn astgenAndSemaFn(
|
||||
.ty = @enumToInt(zir.Const.enum_literal_type),
|
||||
}, fn_proto.ast.callconv_expr)
|
||||
else if (is_extern) // note: https://github.com/ziglang/zig/issues/5269
|
||||
try fn_type_scope.addStrBytes(.enum_literal, "C")
|
||||
try fn_type_scope.addSmallStr(.enum_literal_small, "C")
|
||||
else
|
||||
0;
|
||||
|
||||
const fn_type_inst: zir.Inst.Index = if (cc != 0) fn_type: {
|
||||
const fn_type_inst: zir.Inst.Ref = if (cc != 0) fn_type: {
|
||||
const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc;
|
||||
break :fn_type try fn_type_scope.addFnTypeCc(.{
|
||||
.ret_ty = return_type_inst,
|
||||
@@ -1983,22 +2015,19 @@ fn astgenAndSemaFn(
|
||||
});
|
||||
} else fn_type: {
|
||||
const tag: zir.Inst.Tag = if (is_var_args) .fn_type_var_args else .fn_type;
|
||||
break :fn_type try fn_type_scope.addFnType(.{
|
||||
.ret_ty = return_type_inst,
|
||||
.param_types = param_types,
|
||||
});
|
||||
break :fn_type try fn_type_scope.addFnType(return_type_inst, param_types);
|
||||
};
|
||||
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {};
|
||||
}
|
||||
|
||||
// We need the memory for the Type to go into the arena for the Decl
|
||||
var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
|
||||
errdefer decl_arena.deinit();
|
||||
const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
|
||||
|
||||
const fn_type_code = fn_type_wip_zir_exec.finish();
|
||||
const fn_type_code = try fn_type_scope.finish();
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_code) catch {};
|
||||
}
|
||||
|
||||
var fn_type_sema: Sema = .{
|
||||
.mod = mod,
|
||||
.gpa = mod.gpa,
|
||||
@@ -2021,7 +2050,7 @@ fn astgenAndSemaFn(
|
||||
};
|
||||
defer block_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const fn_type = try fn_type_sema.rootAsType(mod, &block_scope, fn_type_inst);
|
||||
const fn_type = try fn_type_sema.rootAsType(&block_scope, fn_type_inst);
|
||||
if (body_node == 0) {
|
||||
if (!is_extern) {
|
||||
return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function has no body", .{});
|
||||
@@ -2063,13 +2092,12 @@ fn astgenAndSemaFn(
|
||||
const new_func = try decl_arena.allocator.create(Fn);
|
||||
const fn_payload = try decl_arena.allocator.create(Value.Payload.Function);
|
||||
|
||||
const fn_zir: zir.Body = blk: {
|
||||
const fn_zir: zir.Code = blk: {
|
||||
// We put the ZIR inside the Decl arena.
|
||||
var wip_zir_code: WipZirCode = .{
|
||||
.decl = decl,
|
||||
.arena = &decl_arena.allocator,
|
||||
.gpa = mod.gpa,
|
||||
.arg_count = param_count,
|
||||
};
|
||||
defer wip_zir_code.deinit();
|
||||
|
||||
@@ -2078,6 +2106,8 @@ fn astgenAndSemaFn(
|
||||
.parent = &decl.container.base,
|
||||
.zir_code = &wip_zir_code,
|
||||
};
|
||||
defer gen_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
// Iterate over the parameters. We put the param names as the first N
|
||||
// items inside `extra` so that debug info later can refer to the parameter names
|
||||
// even while the respective source code is unloaded.
|
||||
@@ -2095,7 +2125,7 @@ fn astgenAndSemaFn(
|
||||
.gen_zir = &gen_scope,
|
||||
.name = param_name,
|
||||
// Implicit const list first, then implicit arg list.
|
||||
.inst = zir.const_inst_list.len + i,
|
||||
.inst = @intCast(u32, zir.const_inst_list.len + i),
|
||||
};
|
||||
params_scope = &sub_scope.base;
|
||||
|
||||
@@ -2111,18 +2141,19 @@ fn astgenAndSemaFn(
|
||||
_ = try astgen.expr(mod, params_scope, .none, body_node);
|
||||
|
||||
if (gen_scope.instructions.items.len == 0 or
|
||||
!gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
|
||||
!wip_zir_code.instructions.items(.tag)[gen_scope.instructions.items.len - 1]
|
||||
.isNoReturn())
|
||||
{
|
||||
_ = try gen_scope.addRetTok(@enumToInt(zir.Const.void_value), tree.lastToken(body_node));
|
||||
const void_operand = @enumToInt(zir.Const.void_value);
|
||||
_ = try gen_scope.addUnTok(.ret_tok, void_operand, tree.lastToken(body_node));
|
||||
}
|
||||
|
||||
const code = try gen_scope.finish();
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "fn_body", decl.name, gen_scope.instructions.items) catch {};
|
||||
zir.dumpZir(mod.gpa, "fn_body", decl.name, code) catch {};
|
||||
}
|
||||
|
||||
break :blk .{
|
||||
.instructions = try gen_scope.arena.dupe(*zir.Inst, gen_scope.instructions.items),
|
||||
};
|
||||
break :blk code;
|
||||
};
|
||||
|
||||
const is_inline = fn_type.fnCallingConvention() == .Inline;
|
||||
@@ -2190,7 +2221,8 @@ fn astgenAndSemaFn(
|
||||
.{},
|
||||
);
|
||||
}
|
||||
const export_src = token_starts[maybe_export_token];
|
||||
// TODO use a Decl-local source location instead.
|
||||
const export_src: LazySrcLoc = .{ .token_abs = maybe_export_token };
|
||||
const name = tree.tokenSlice(fn_proto.name_token.?); // TODO identifierTokenString
|
||||
// The scope needs to have the decl in it.
|
||||
try mod.analyzeExport(&block_scope.base, export_src, name, decl);
|
||||
@@ -2294,7 +2326,7 @@ fn astgenAndSemaVarDecl(
|
||||
init_result_loc,
|
||||
var_decl.ast.init_node,
|
||||
);
|
||||
const code = wip_zir_code.finish();
|
||||
const code = try gen_scope.finish();
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "var_init", decl.name, code) catch {};
|
||||
}
|
||||
@@ -2324,13 +2356,13 @@ fn astgenAndSemaVarDecl(
|
||||
try sema.root(&block_scope);
|
||||
|
||||
// The result location guarantees the type coercion.
|
||||
const analyzed_init_inst = sema.resolveInst(&block_scope, init_inst);
|
||||
const analyzed_init_inst = try sema.resolveInst(init_inst);
|
||||
// The is_comptime in the Scope.Block guarantees the result is comptime-known.
|
||||
const val = analyzed_init_inst.value().?;
|
||||
|
||||
break :vi .{
|
||||
.ty = try analyzed_init_inst.ty.copy(decl_arena),
|
||||
.val = try val.copy(decl_arena),
|
||||
.ty = try analyzed_init_inst.ty.copy(&decl_arena.allocator),
|
||||
.val = try val.copy(&decl_arena.allocator),
|
||||
};
|
||||
} else if (!is_extern) {
|
||||
return mod.failTok(
|
||||
@@ -2358,7 +2390,7 @@ fn astgenAndSemaVarDecl(
|
||||
defer type_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const var_type = try astgen.typeExpr(mod, &type_scope.base, var_decl.ast.type_node);
|
||||
const code = wip_zir_code.finish();
|
||||
const code = try type_scope.finish();
|
||||
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
|
||||
zir.dumpZir(mod.gpa, "var_type", decl.name, code) catch {};
|
||||
}
|
||||
@@ -2388,7 +2420,7 @@ fn astgenAndSemaVarDecl(
|
||||
const ty = try sema.rootAsType(&block_scope, var_type);
|
||||
|
||||
break :vi .{
|
||||
.ty = try ty.copy(decl_arena),
|
||||
.ty = try ty.copy(&decl_arena.allocator),
|
||||
.val = null,
|
||||
};
|
||||
} else {
|
||||
@@ -2441,7 +2473,8 @@ fn astgenAndSemaVarDecl(
|
||||
|
||||
if (var_decl.extern_export_token) |maybe_export_token| {
|
||||
if (token_tags[maybe_export_token] == .keyword_export) {
|
||||
const export_src = token_starts[maybe_export_token];
|
||||
// TODO make this src relative to containing Decl
|
||||
const export_src: LazySrcLoc = .{ .token_abs = maybe_export_token };
|
||||
const name_token = var_decl.ast.mut_token + 1;
|
||||
const name = tree.tokenSlice(name_token); // TODO identifierTokenString
|
||||
// The scope needs to have the decl in it.
|
||||
|
||||
25
src/Sema.zig
25
src/Sema.zig
@@ -12,7 +12,7 @@ gpa: *Allocator,
|
||||
arena: *Allocator,
|
||||
code: zir.Code,
|
||||
/// Maps ZIR to TZIR.
|
||||
inst_map: []*const Inst,
|
||||
inst_map: []*Inst,
|
||||
/// When analyzing an inline function call, owner_decl is the Decl of the caller
|
||||
/// and `src_decl` of `Scope.Block` is the `Decl` of the callee.
|
||||
/// This `Decl` owns the arena memory of this `Sema`.
|
||||
@@ -58,15 +58,10 @@ pub fn root(sema: *Sema, root_block: *Scope.Block) !void {
|
||||
return sema.analyzeBody(root_block, root_body);
|
||||
}
|
||||
|
||||
pub fn rootAsType(
|
||||
sema: *Sema,
|
||||
root_block: *Scope.Block,
|
||||
zir_result_inst: zir.Inst.Index,
|
||||
) !Type {
|
||||
pub fn rootAsType(sema: *Sema, root_block: *Scope.Block, result_inst: zir.Inst.Ref) !Type {
|
||||
const root_body = sema.code.extra[sema.code.root_start..][0..sema.code.root_len];
|
||||
try sema.analyzeBody(root_block, root_body);
|
||||
|
||||
const result_inst = sema.inst_map[zir_result_inst];
|
||||
// Source location is unneeded because resolveConstValue must have already
|
||||
// been successfully called when coercing the value to a type, from the
|
||||
// result location.
|
||||
@@ -203,6 +198,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde
|
||||
.array_type => try sema.zirArrayType(block, zir_inst),
|
||||
.array_type_sentinel => try sema.zirArrayTypeSentinel(block, zir_inst),
|
||||
.enum_literal => try sema.zirEnumLiteral(block, zir_inst),
|
||||
.enum_literal_small => try sema.zirEnumLiteralSmall(block, zir_inst),
|
||||
.merge_error_sets => try sema.zirMergeErrorSets(block, zir_inst),
|
||||
.error_union_type => try sema.zirErrorUnionType(block, zir_inst),
|
||||
.anyframe_type => try sema.zirAnyframeType(block, zir_inst),
|
||||
@@ -232,7 +228,7 @@ pub fn analyzeBody(sema: *Sema, block: *Scope.Block, body: []const zir.Inst.Inde
|
||||
|
||||
/// TODO when we rework TZIR memory layout, this function will no longer have a possible error.
|
||||
pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {
|
||||
var i = zir_ref;
|
||||
var i: usize = zir_ref;
|
||||
|
||||
// First section of indexes correspond to a set number of constant values.
|
||||
if (i < zir.const_inst_list.len) {
|
||||
@@ -1435,6 +1431,19 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
|
||||
});
|
||||
}
|
||||
|
||||
fn zirEnumLiteralSmall(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const name = sema.code.instructions.items(.data)[inst].small_str.get();
|
||||
const src: LazySrcLoc = .unneeded;
|
||||
const duped_name = try sema.arena.dupe(u8, name);
|
||||
return sema.mod.constInst(sema.arena, src, .{
|
||||
.ty = Type.initTag(.enum_literal),
|
||||
.val = try Value.Tag.enum_literal.create(sema.arena, duped_name),
|
||||
});
|
||||
}
|
||||
|
||||
/// Pointer in, pointer out.
|
||||
fn zirOptionalPayloadPtr(
|
||||
sema: *Sema,
|
||||
|
||||
562
src/astgen.zig
562
src/astgen.zig
File diff suppressed because it is too large
Load Diff
@@ -499,7 +499,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
defer function.stack.deinit(bin_file.allocator);
|
||||
defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
|
||||
|
||||
var call_info = function.resolveCallingConventionValues(src_loc.byte_offset, fn_type) catch |err| switch (err) {
|
||||
var call_info = function.resolveCallingConventionValues(src_loc.lazy, fn_type) catch |err| switch (err) {
|
||||
error.CodegenFail => return Result{ .fail = function.err_msg.? },
|
||||
else => |e| return e,
|
||||
};
|
||||
@@ -2850,7 +2850,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
return self.fail(inst.base.src, "TODO implement support for more x86 assembly instructions", .{});
|
||||
}
|
||||
|
||||
if (inst.output) |output| {
|
||||
if (inst.output_name) |output| {
|
||||
if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
|
||||
return self.fail(inst.base.src, "unrecognized asm output constraint: '{s}'", .{output});
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ const TypedValue = @import("../TypedValue.zig");
|
||||
const C = link.File.C;
|
||||
const Decl = Module.Decl;
|
||||
const trace = @import("../tracy.zig").trace;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
|
||||
const Mutability = enum { Const, Mut };
|
||||
|
||||
@@ -145,11 +146,10 @@ pub const DeclGen = struct {
|
||||
error_msg: ?*Module.ErrorMsg,
|
||||
typedefs: TypedefMap,
|
||||
|
||||
fn fail(dg: *DeclGen, src: usize, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
|
||||
dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, .{
|
||||
.file_scope = dg.decl.getFileScope(),
|
||||
.byte_offset = src,
|
||||
}, format, args);
|
||||
fn fail(dg: *DeclGen, src: LazySrcLoc, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
|
||||
@setCold(true);
|
||||
const src_loc = src.toSrcLocWithDecl(dg.decl);
|
||||
dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args);
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ pub const DeclGen = struct {
|
||||
val: Value,
|
||||
) error{ OutOfMemory, AnalysisFail }!void {
|
||||
if (val.isUndef()) {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: properly handle undefined in all cases (with debug safety?)", .{});
|
||||
}
|
||||
switch (t.zigTypeTag()) {
|
||||
.Int => {
|
||||
@@ -193,7 +193,7 @@ pub const DeclGen = struct {
|
||||
try writer.print("{s}", .{decl.name});
|
||||
},
|
||||
else => |e| return dg.fail(
|
||||
dg.decl.src(),
|
||||
.{ .node_offset = 0 },
|
||||
"TODO: C backend: implement Pointer value {s}",
|
||||
.{@tagName(e)},
|
||||
),
|
||||
@@ -276,7 +276,7 @@ pub const DeclGen = struct {
|
||||
try writer.writeAll(", .error = 0 }");
|
||||
}
|
||||
},
|
||||
else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement value {s}", .{
|
||||
@tagName(e),
|
||||
}),
|
||||
}
|
||||
@@ -350,7 +350,7 @@ pub const DeclGen = struct {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: implement integer types larger than 128 bits", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement integer types larger than 128 bits", .{});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
@@ -358,7 +358,7 @@ pub const DeclGen = struct {
|
||||
},
|
||||
.Pointer => {
|
||||
if (t.isSlice()) {
|
||||
return dg.fail(dg.decl.src(), "TODO: C backend: implement slices", .{});
|
||||
return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement slices", .{});
|
||||
} else {
|
||||
try dg.renderType(w, t.elemType());
|
||||
try w.writeAll(" *");
|
||||
@@ -431,7 +431,7 @@ pub const DeclGen = struct {
|
||||
dg.typedefs.putAssumeCapacityNoClobber(t, .{ .name = name, .rendered = rendered });
|
||||
},
|
||||
.Null, .Undefined => unreachable, // must be const or comptime
|
||||
else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{
|
||||
else => |e| return dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement type {s}", .{
|
||||
@tagName(e),
|
||||
}),
|
||||
}
|
||||
@@ -575,7 +575,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
|
||||
.unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?),
|
||||
.wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?),
|
||||
.wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
|
||||
else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
|
||||
else => |e| return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for {}", .{e}),
|
||||
};
|
||||
switch (result_value) {
|
||||
.none => {},
|
||||
@@ -756,7 +756,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
|
||||
try writer.writeAll(");\n");
|
||||
return result_local;
|
||||
} else {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement function pointers", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement function pointers", .{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,13 +913,13 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
|
||||
try o.writeCValue(writer, arg_c_value);
|
||||
try writer.writeAll(";\n");
|
||||
} else {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO non-explicit inline asm regs", .{});
|
||||
}
|
||||
}
|
||||
const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
|
||||
try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
|
||||
if (as.output) |_| {
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO inline asm output", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO inline asm output", .{});
|
||||
}
|
||||
if (as.inputs.len > 0) {
|
||||
if (as.output == null) {
|
||||
@@ -945,7 +945,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
|
||||
if (as.base.isUnused())
|
||||
return CValue.none;
|
||||
|
||||
return o.dg.fail(o.dg.decl.src(), "TODO: C backend: inline asm expression result used", .{});
|
||||
return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: inline asm expression result used", .{});
|
||||
}
|
||||
|
||||
fn genIsNull(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
|
||||
@@ -14,6 +14,7 @@ const Type = @import("../type.zig").Type;
|
||||
const Value = @import("../value.zig").Value;
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const AnyMCValue = @import("../codegen.zig").AnyMCValue;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
|
||||
/// Wasm Value, created when generating an instruction
|
||||
const WValue = union(enum) {
|
||||
@@ -70,11 +71,9 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
/// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig
|
||||
fn fail(self: *Context, src: usize, comptime fmt: []const u8, args: anytype) InnerError {
|
||||
self.err_msg = try Module.ErrorMsg.create(self.gpa, .{
|
||||
.file_scope = self.decl.getFileScope(),
|
||||
.byte_offset = src,
|
||||
}, fmt, args);
|
||||
fn fail(self: *Context, src: LazySrcLoc, comptime fmt: []const u8, args: anytype) InnerError {
|
||||
const src_loc = src.toSrcLocWithDecl(self.decl);
|
||||
self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args);
|
||||
return error.CodegenFail;
|
||||
}
|
||||
|
||||
@@ -91,7 +90,7 @@ pub const Context = struct {
|
||||
}
|
||||
|
||||
/// Using a given `Type`, returns the corresponding wasm value type
|
||||
fn genValtype(self: *Context, src: usize, ty: Type) InnerError!u8 {
|
||||
fn genValtype(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
|
||||
return switch (ty.tag()) {
|
||||
.f32 => wasm.valtype(.f32),
|
||||
.f64 => wasm.valtype(.f64),
|
||||
@@ -104,7 +103,7 @@ pub const Context = struct {
|
||||
/// Using a given `Type`, returns the corresponding wasm value type
|
||||
/// Differently from `genValtype` this also allows `void` to create a block
|
||||
/// with no return type
|
||||
fn genBlockType(self: *Context, src: usize, ty: Type) InnerError!u8 {
|
||||
fn genBlockType(self: *Context, src: LazySrcLoc, ty: Type) InnerError!u8 {
|
||||
return switch (ty.tag()) {
|
||||
.void, .noreturn => wasm.block_empty,
|
||||
else => self.genValtype(src, ty),
|
||||
@@ -139,7 +138,7 @@ pub const Context = struct {
|
||||
ty.fnParamTypes(params);
|
||||
for (params) |param_type| {
|
||||
// Can we maybe get the source index of each param?
|
||||
const val_type = try self.genValtype(self.decl.src(), param_type);
|
||||
const val_type = try self.genValtype(.{ .node_offset = 0 }, param_type);
|
||||
try writer.writeByte(val_type);
|
||||
}
|
||||
}
|
||||
@@ -151,7 +150,7 @@ pub const Context = struct {
|
||||
else => |ret_type| {
|
||||
try leb.writeULEB128(writer, @as(u32, 1));
|
||||
// Can we maybe get the source index of the return type?
|
||||
const val_type = try self.genValtype(self.decl.src(), return_type);
|
||||
const val_type = try self.genValtype(.{ .node_offset = 0 }, return_type);
|
||||
try writer.writeByte(val_type);
|
||||
},
|
||||
}
|
||||
@@ -168,7 +167,7 @@ pub const Context = struct {
|
||||
const mod_fn = blk: {
|
||||
if (tv.val.castTag(.function)) |func| break :blk func.data;
|
||||
if (tv.val.castTag(.extern_fn)) |ext_fn| return; // don't need codegen for extern functions
|
||||
return self.fail(self.decl.src(), "TODO: Wasm codegen for decl type '{s}'", .{tv.ty.tag()});
|
||||
return self.fail(.{ .node_offset = 0 }, "TODO: Wasm codegen for decl type '{s}'", .{tv.ty.tag()});
|
||||
};
|
||||
|
||||
// Reserve space to write the size after generating the code as well as space for locals count
|
||||
|
||||
@@ -3150,7 +3150,7 @@ pub const Type = extern union {
|
||||
=> unreachable,
|
||||
|
||||
.empty_struct => self.castTag(.empty_struct).?.data,
|
||||
.@"opaque" => &self.castTag(.@"opaque").?.scope,
|
||||
.@"opaque" => &self.castTag(.@"opaque").?.data,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
248
src/zir.zig
248
src/zir.zig
@@ -35,7 +35,7 @@ pub const Code = struct {
|
||||
extra: []u32,
|
||||
/// First ZIR instruction in this `Code`.
|
||||
/// `extra` at this index contains a `Ref` for every root member.
|
||||
root_start: Inst.Index,
|
||||
root_start: u32,
|
||||
/// Number of ZIR instructions in the implicit root block of the `Code`.
|
||||
root_len: u32,
|
||||
|
||||
@@ -138,204 +138,205 @@ pub const Const = enum {
|
||||
bool_false,
|
||||
};
|
||||
|
||||
pub const const_inst_list = enumArray(Const, .{
|
||||
.u8_type = @as(TypedValue, .{
|
||||
pub const const_inst_list = std.enums.directEnumArray(Const, TypedValue, 0, .{
|
||||
.unused = undefined,
|
||||
.u8_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.u8_type),
|
||||
}),
|
||||
.i8_type = @as(TypedValue, .{
|
||||
},
|
||||
.i8_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i8_type),
|
||||
}),
|
||||
.u16_type = @as(TypedValue, .{
|
||||
},
|
||||
.u16_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.u16_type),
|
||||
}),
|
||||
.i16_type = @as(TypedValue, .{
|
||||
},
|
||||
.i16_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i16_type),
|
||||
}),
|
||||
.u32_type = @as(TypedValue, .{
|
||||
},
|
||||
.u32_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.u32_type),
|
||||
}),
|
||||
.i32_type = @as(TypedValue, .{
|
||||
},
|
||||
.i32_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i32_type),
|
||||
}),
|
||||
.u64_type = @as(TypedValue, .{
|
||||
},
|
||||
.u64_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.u64_type),
|
||||
}),
|
||||
.i64_type = @as(TypedValue, .{
|
||||
},
|
||||
.i64_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.i64_type),
|
||||
}),
|
||||
.usize_type = @as(TypedValue, .{
|
||||
},
|
||||
.usize_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.usize_type),
|
||||
}),
|
||||
.isize_type = @as(TypedValue, .{
|
||||
},
|
||||
.isize_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.isize_type),
|
||||
}),
|
||||
.c_short_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_short_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_short_type),
|
||||
}),
|
||||
.c_ushort_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_ushort_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_ushort_type),
|
||||
}),
|
||||
.c_int_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_int_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_int_type),
|
||||
}),
|
||||
.c_uint_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_uint_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_uint_type),
|
||||
}),
|
||||
.c_long_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_long_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_long_type),
|
||||
}),
|
||||
.c_ulong_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_ulong_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_ulong_type),
|
||||
}),
|
||||
.c_longlong_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_longlong_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_longlong_type),
|
||||
}),
|
||||
.c_ulonglong_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_ulonglong_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_ulonglong_type),
|
||||
}),
|
||||
.c_longdouble_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_longdouble_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_longdouble_type),
|
||||
}),
|
||||
.f16_type = @as(TypedValue, .{
|
||||
},
|
||||
.f16_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.f16_type),
|
||||
}),
|
||||
.f32_type = @as(TypedValue, .{
|
||||
},
|
||||
.f32_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.f32_type),
|
||||
}),
|
||||
.f64_type = @as(TypedValue, .{
|
||||
},
|
||||
.f64_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.f64_type),
|
||||
}),
|
||||
.f128_type = @as(TypedValue, .{
|
||||
},
|
||||
.f128_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.f128_type),
|
||||
}),
|
||||
.c_void_type = @as(TypedValue, .{
|
||||
},
|
||||
.c_void_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.c_void_type),
|
||||
}),
|
||||
.bool_type = @as(TypedValue, .{
|
||||
},
|
||||
.bool_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.bool_type),
|
||||
}),
|
||||
.void_type = @as(TypedValue, .{
|
||||
},
|
||||
.void_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.void_type),
|
||||
}),
|
||||
.type_type = @as(TypedValue, .{
|
||||
},
|
||||
.type_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.type_type),
|
||||
}),
|
||||
.anyerror_type = @as(TypedValue, .{
|
||||
},
|
||||
.anyerror_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.anyerror_type),
|
||||
}),
|
||||
.comptime_int_type = @as(TypedValue, .{
|
||||
},
|
||||
.comptime_int_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.comptime_int_type),
|
||||
}),
|
||||
.comptime_float_type = @as(TypedValue, .{
|
||||
},
|
||||
.comptime_float_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.comptime_float_type),
|
||||
}),
|
||||
.noreturn_type = @as(TypedValue, .{
|
||||
},
|
||||
.noreturn_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.noreturn_type),
|
||||
}),
|
||||
.null_type = @as(TypedValue, .{
|
||||
},
|
||||
.null_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.null_type),
|
||||
}),
|
||||
.undefined_type = @as(TypedValue, .{
|
||||
},
|
||||
.undefined_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.undefined_type),
|
||||
}),
|
||||
.fn_noreturn_no_args_type = @as(TypedValue, .{
|
||||
},
|
||||
.fn_noreturn_no_args_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.fn_noreturn_no_args_type),
|
||||
}),
|
||||
.fn_void_no_args_type = @as(TypedValue, .{
|
||||
},
|
||||
.fn_void_no_args_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.fn_void_no_args_type),
|
||||
}),
|
||||
.fn_naked_noreturn_no_args_type = @as(TypedValue, .{
|
||||
},
|
||||
.fn_naked_noreturn_no_args_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.fn_naked_noreturn_no_args_type),
|
||||
}),
|
||||
.fn_ccc_void_no_args_type = @as(TypedValue, .{
|
||||
},
|
||||
.fn_ccc_void_no_args_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.fn_ccc_void_no_args_type),
|
||||
}),
|
||||
.single_const_pointer_to_comptime_int_type = @as(TypedValue, .{
|
||||
},
|
||||
.single_const_pointer_to_comptime_int_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.single_const_pointer_to_comptime_int_type),
|
||||
}),
|
||||
.const_slice_u8_type = @as(TypedValue, .{
|
||||
},
|
||||
.const_slice_u8_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.const_slice_u8_type),
|
||||
}),
|
||||
.enum_literal_type = @as(TypedValue, .{
|
||||
},
|
||||
.enum_literal_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.enum_literal_type),
|
||||
}),
|
||||
.anyframe_type = @as(TypedValue, .{
|
||||
},
|
||||
.anyframe_type = .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.anyframe_type),
|
||||
}),
|
||||
},
|
||||
|
||||
.undef = @as(TypedValue, .{
|
||||
.undef = .{
|
||||
.ty = Type.initTag(.@"undefined"),
|
||||
.val = Value.initTag(.undef),
|
||||
}),
|
||||
.zero = @as(TypedValue, .{
|
||||
},
|
||||
.zero = .{
|
||||
.ty = Type.initTag(.comptime_int),
|
||||
.val = Value.initTag(.zero),
|
||||
}),
|
||||
.one = @as(TypedValue, .{
|
||||
},
|
||||
.one = .{
|
||||
.ty = Type.initTag(.comptime_int),
|
||||
.val = Value.initTag(.one),
|
||||
}),
|
||||
.void_value = @as(TypedValue, .{
|
||||
},
|
||||
.void_value = .{
|
||||
.ty = Type.initTag(.void),
|
||||
.val = Value.initTag(.void_value),
|
||||
}),
|
||||
.unreachable_value = @as(TypedValue, .{
|
||||
},
|
||||
.unreachable_value = .{
|
||||
.ty = Type.initTag(.noreturn),
|
||||
.val = Value.initTag(.unreachable_value),
|
||||
}),
|
||||
.null_value = @as(TypedValue, .{
|
||||
},
|
||||
.null_value = .{
|
||||
.ty = Type.initTag(.@"null"),
|
||||
.val = Value.initTag(.null_value),
|
||||
}),
|
||||
.bool_true = @as(TypedValue, .{
|
||||
},
|
||||
.bool_true = .{
|
||||
.ty = Type.initTag(.bool),
|
||||
.val = Value.initTag(.bool_true),
|
||||
}),
|
||||
.bool_false = @as(TypedValue, .{
|
||||
},
|
||||
.bool_false = .{
|
||||
.ty = Type.initTag(.bool),
|
||||
.val = Value.initTag(.bool_false),
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
/// These are untyped instructions generated from an Abstract Syntax Tree.
|
||||
@@ -633,7 +634,7 @@ pub const Inst = struct {
|
||||
/// Sends control flow back to the function's callee.
|
||||
/// Includes an operand as the return value.
|
||||
/// Includes a token source location.
|
||||
/// Uses the un_tok union field.
|
||||
/// Uses the `un_tok` union field.
|
||||
ret_tok,
|
||||
/// Changes the maximum number of backwards branches that compile-time
|
||||
/// code execution can use before giving up and making a compile error.
|
||||
@@ -755,6 +756,9 @@ pub const Inst = struct {
|
||||
ensure_err_payload_void,
|
||||
/// An enum literal. Uses the `str_tok` union field.
|
||||
enum_literal,
|
||||
/// An enum literal 8 or fewer bytes. No source location.
|
||||
/// Uses the `small_str` field.
|
||||
enum_literal_small,
|
||||
/// Suspend an async function. The suspend block has 0 or 1 statements in it.
|
||||
/// Uses the `un_node` union field.
|
||||
suspend_block_one,
|
||||
@@ -816,6 +820,7 @@ pub const Inst = struct {
|
||||
.indexable_ptr_len,
|
||||
.as,
|
||||
.@"asm",
|
||||
.asm_volatile,
|
||||
.bit_and,
|
||||
.bitcast,
|
||||
.bitcast_ref,
|
||||
@@ -831,12 +836,9 @@ pub const Inst = struct {
|
||||
.breakpoint,
|
||||
.call,
|
||||
.call_async_kw,
|
||||
.call_never_tail,
|
||||
.call_never_inline,
|
||||
.call_no_async,
|
||||
.call_always_tail,
|
||||
.call_always_inline,
|
||||
.call_compile_time,
|
||||
.call_none,
|
||||
.cmp_lt,
|
||||
.cmp_lte,
|
||||
.cmp_eq,
|
||||
@@ -845,13 +847,15 @@ pub const Inst = struct {
|
||||
.cmp_neq,
|
||||
.coerce_result_ptr,
|
||||
.@"const",
|
||||
.dbg_stmt,
|
||||
.dbg_stmt_node,
|
||||
.decl_ref,
|
||||
.decl_val,
|
||||
.deref_node,
|
||||
.div,
|
||||
.elem_ptr,
|
||||
.elem_val,
|
||||
.elem_ptr_node,
|
||||
.elem_val_node,
|
||||
.ensure_result_used,
|
||||
.ensure_result_non_error,
|
||||
.floatcast,
|
||||
@@ -882,14 +886,6 @@ pub const Inst = struct {
|
||||
.ret_type,
|
||||
.shl,
|
||||
.shr,
|
||||
.single_const_ptr_type,
|
||||
.single_mut_ptr_type,
|
||||
.many_const_ptr_type,
|
||||
.many_mut_ptr_type,
|
||||
.c_const_ptr_type,
|
||||
.c_mut_ptr_type,
|
||||
.mut_slice_type,
|
||||
.const_slice_type,
|
||||
.store,
|
||||
.store_to_block_ptr,
|
||||
.store_to_inferred_ptr,
|
||||
@@ -914,20 +910,21 @@ pub const Inst = struct {
|
||||
.ptr_type_simple,
|
||||
.ensure_err_payload_void,
|
||||
.enum_literal,
|
||||
.enum_literal_small,
|
||||
.merge_error_sets,
|
||||
.anyframe_type,
|
||||
.error_union_type,
|
||||
.bit_not,
|
||||
.error_set,
|
||||
.error_value,
|
||||
.slice,
|
||||
.slice_start,
|
||||
.slice_end,
|
||||
.slice_sentinel,
|
||||
.import,
|
||||
.typeof_peer,
|
||||
.resolve_inferred_alloc,
|
||||
.set_eval_branch_quota,
|
||||
.compile_log,
|
||||
.switch_range,
|
||||
.@"resume",
|
||||
.@"await",
|
||||
.nosuspend_await,
|
||||
@@ -942,11 +939,8 @@ pub const Inst = struct {
|
||||
.unreachable_unsafe,
|
||||
.unreachable_safe,
|
||||
.loop,
|
||||
.container_field_named,
|
||||
.container_field_typed,
|
||||
.container_field,
|
||||
.@"suspend",
|
||||
.suspend_block,
|
||||
.suspend_block_one,
|
||||
=> true,
|
||||
};
|
||||
}
|
||||
@@ -1017,6 +1011,17 @@ pub const Inst = struct {
|
||||
return code.string_bytes[self.start..][0..self.len];
|
||||
}
|
||||
},
|
||||
/// Strings 8 or fewer bytes which may not contain null bytes.
|
||||
small_str: struct {
|
||||
bytes: [8]u8,
|
||||
|
||||
pub fn get(self: @This()) []const u8 {
|
||||
const end = for (self.bytes) |byte, i| {
|
||||
if (byte == 0) break i;
|
||||
} else self.bytes.len;
|
||||
return self.bytes[0..end];
|
||||
}
|
||||
},
|
||||
str_tok: struct {
|
||||
/// Offset into `string_bytes`. Null-terminated.
|
||||
start: u32,
|
||||
@@ -1205,7 +1210,8 @@ pub const Inst = struct {
|
||||
};
|
||||
|
||||
/// For debugging purposes, like dumpFn but for unanalyzed zir blocks
|
||||
pub fn dumpZir(gpa: *Allocator, kind: []const u8, decl_name: [*:0]const u8, instructions: []*Inst) !void {
|
||||
pub fn dumpZir(gpa: *Allocator, kind: []const u8, decl_name: [*:0]const u8, code: Code) !void {
|
||||
if (true) @panic("TODO fix this function for zir-memory-layout branch");
|
||||
var fib = std.heap.FixedBufferAllocator.init(&[_]u8{});
|
||||
var module = Module{
|
||||
.decls = &[_]*Module.Decl{},
|
||||
|
||||
Reference in New Issue
Block a user