mirror of
https://github.com/ziglang/zig.git
synced 2026-01-01 19:13:16 +00:00
stage2: further cleanups regarding zir.Inst.Ref
* Introduce helper functions on Module.WipZirCode and zir.Code
* Move some logic around
* re-introduce ref_start_index
* prefer usize for local variables + `@intCast` at the end.
Empirically this is easier to optimize.
* Avoid using mem.{bytesAsSlice,sliceAsBytes} because it incurs an
unnecessary multiplication/division which may cause problems for the
optimizer.
* Use a regular enum, not packed, for `Ref`. Memory layout is
guaranteed for enums which specify their tag type. Packed enums have
ABI alignment of 1 byte which is too small.
This commit is contained in:
parent
0c601965ab
commit
180dae4196
@ -34,3 +34,4 @@ Performance optimizations to look into:
|
||||
* enum literals can use small strings
|
||||
* string literals can use small strings
|
||||
* don't need the Sema coercion on condbr condition, it's done with result locations
|
||||
* remove unreachable_value
|
||||
|
||||
@ -1013,7 +1013,7 @@ pub const Scope = struct {
|
||||
.cc = args.cc,
|
||||
.param_types_len = @intCast(u32, args.param_types.len),
|
||||
});
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args.param_types)));
|
||||
gz.zir_code.appendRefsAssumeCapacity(args.param_types);
|
||||
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
@ -1024,7 +1024,7 @@ pub const Scope = struct {
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addFnType(
|
||||
@ -1043,7 +1043,7 @@ pub const Scope = struct {
|
||||
const payload_index = gz.zir_code.addExtraAssumeCapacity(zir.Inst.FnType{
|
||||
.param_types_len = @intCast(u32, param_types.len),
|
||||
});
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(param_types)));
|
||||
gz.zir_code.appendRefsAssumeCapacity(param_types);
|
||||
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
@ -1054,7 +1054,7 @@ pub const Scope = struct {
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addCall(
|
||||
@ -1077,7 +1077,7 @@ pub const Scope = struct {
|
||||
.callee = callee,
|
||||
.args_len = @intCast(u32, args.len),
|
||||
});
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args)));
|
||||
gz.zir_code.appendRefsAssumeCapacity(args);
|
||||
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{
|
||||
@ -1088,7 +1088,7 @@ pub const Scope = struct {
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
|
||||
/// Note that this returns a `zir.Inst.Index` not a ref.
|
||||
@ -1160,7 +1160,7 @@ pub const Scope = struct {
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addArrayTypeSentinel(
|
||||
@ -1186,7 +1186,7 @@ pub const Scope = struct {
|
||||
} },
|
||||
});
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
|
||||
pub fn addUnTok(
|
||||
@ -1317,7 +1317,7 @@ pub const Scope = struct {
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(inst);
|
||||
gz.instructions.appendAssumeCapacity(new_index);
|
||||
return zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(new_index);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1366,9 +1366,9 @@ pub const WipZirCode = struct {
|
||||
instructions: std.MultiArrayList(zir.Inst) = .{},
|
||||
string_bytes: std.ArrayListUnmanaged(u8) = .{},
|
||||
extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
/// We need to keep track of this count in order to convert between
|
||||
/// `zir.Inst.Ref` and `zir.Inst.Index` types.
|
||||
param_count: u32 = 0,
|
||||
/// The end of special indexes. `zir.Inst.Ref` subtracts against this number to convert
|
||||
/// to `zir.Inst.Index`. The default here is correct if there are 0 parameters.
|
||||
ref_start_index: u32 = zir.Inst.Ref.typed_value_map.len,
|
||||
decl: *Decl,
|
||||
gpa: *Allocator,
|
||||
arena: *Allocator,
|
||||
@ -1386,20 +1386,43 @@ pub const WipZirCode = struct {
|
||||
wzc.extra.appendAssumeCapacity(switch (field.field_type) {
|
||||
u32 => @field(extra, field.name),
|
||||
zir.Inst.Ref => @enumToInt(@field(extra, field.name)),
|
||||
else => unreachable,
|
||||
else => @compileError("bad field type"),
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn refIsNoReturn(wzc: WipZirCode, zir_inst_ref: zir.Inst.Ref) bool {
|
||||
if (zir_inst_ref == .unreachable_value) return true;
|
||||
if (zir_inst_ref.toIndex(wzc.param_count)) |zir_inst| {
|
||||
return wzc.instructions.items(.tag)[zir_inst].isNoReturn();
|
||||
pub fn appendRefs(wzc: *WipZirCode, refs: []const zir.Inst.Ref) !void {
|
||||
const coerced = @bitCast([]const u32, refs);
|
||||
return wzc.extra.appendSlice(wzc.gpa, coerced);
|
||||
}
|
||||
|
||||
pub fn appendRefsAssumeCapacity(wzc: *WipZirCode, refs: []const zir.Inst.Ref) void {
|
||||
const coerced = @bitCast([]const u32, refs);
|
||||
wzc.extra.appendSliceAssumeCapacity(coerced);
|
||||
}
|
||||
|
||||
pub fn refIsNoReturn(wzc: WipZirCode, inst_ref: zir.Inst.Ref) bool {
|
||||
if (inst_ref == .unreachable_value) return true;
|
||||
if (wzc.refToIndex(inst_ref)) |inst_index| {
|
||||
return wzc.instructions.items(.tag)[inst_index].isNoReturn();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn indexToRef(wzc: WipZirCode, inst: zir.Inst.Index) zir.Inst.Ref {
|
||||
return @intToEnum(zir.Inst.Ref, wzc.ref_start_index + inst);
|
||||
}
|
||||
|
||||
pub fn refToIndex(wzc: WipZirCode, inst: zir.Inst.Ref) ?zir.Inst.Index {
|
||||
const ref_int = @enumToInt(inst);
|
||||
if (ref_int >= wzc.ref_start_index) {
|
||||
return ref_int - wzc.ref_start_index;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(wzc: *WipZirCode) void {
|
||||
wzc.instructions.deinit(wzc.gpa);
|
||||
wzc.extra.deinit(wzc.gpa);
|
||||
@ -2075,7 +2098,7 @@ fn astgenAndSemaFn(
|
||||
// The AST params array does not contain anytype and ... parameters.
|
||||
// We must iterate to count how many param types to allocate.
|
||||
const param_count = blk: {
|
||||
var count: u32 = 0;
|
||||
var count: usize = 0;
|
||||
var it = fn_proto.iterate(tree);
|
||||
while (it.next()) |param| {
|
||||
if (param.anytype_ellipsis3) |some| if (token_tags[some] == .ellipsis3) break;
|
||||
@ -2297,7 +2320,7 @@ fn astgenAndSemaFn(
|
||||
.decl = decl,
|
||||
.arena = &decl_arena.allocator,
|
||||
.gpa = mod.gpa,
|
||||
.param_count = param_count,
|
||||
.ref_start_index = @intCast(u32, zir.Inst.Ref.typed_value_map.len + param_count),
|
||||
};
|
||||
defer wip_zir_code.deinit();
|
||||
|
||||
@ -2314,7 +2337,7 @@ fn astgenAndSemaFn(
|
||||
try wip_zir_code.extra.ensureCapacity(mod.gpa, param_count);
|
||||
|
||||
var params_scope = &gen_scope.base;
|
||||
var i: u32 = 0;
|
||||
var i: usize = 0;
|
||||
var it = fn_proto.iterate(tree);
|
||||
while (it.next()) |param| : (i += 1) {
|
||||
const name_token = param.name_token.?;
|
||||
@ -2325,7 +2348,7 @@ fn astgenAndSemaFn(
|
||||
.gen_zir = &gen_scope,
|
||||
.name = param_name,
|
||||
// Implicit const list first, then implicit arg list.
|
||||
.inst = zir.Inst.Ref.fromParam(i),
|
||||
.inst = @intToEnum(zir.Inst.Ref, @intCast(u32, zir.Inst.Ref.typed_value_map.len + i)),
|
||||
.src = decl.tokSrcLoc(name_token),
|
||||
};
|
||||
params_scope = &sub_scope.base;
|
||||
|
||||
41
src/Sema.zig
41
src/Sema.zig
@ -300,18 +300,28 @@ 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.
|
||||
/// Until then we allocate memory for a new, mutable `ir.Inst` to match what TZIR expects.
|
||||
pub fn resolveInst(sema: *Sema, zir_ref: zir.Inst.Ref) error{OutOfMemory}!*ir.Inst {
|
||||
if (zir_ref.toTypedValue()) |typed_value| {
|
||||
return sema.mod.constInst(sema.arena, .unneeded, typed_value);
|
||||
}
|
||||
var i: usize = @enumToInt(zir_ref);
|
||||
|
||||
const param_count = @intCast(u32, sema.param_inst_list.len);
|
||||
if (zir_ref.toParam(param_count)) |param| {
|
||||
return sema.param_inst_list[param];
|
||||
// First section of indexes correspond to a set number of constant values.
|
||||
if (i < zir.Inst.Ref.typed_value_map.len) {
|
||||
// TODO when we rework TZIR memory layout, this function can be as simple as:
|
||||
// if (zir_ref < zir.const_inst_list.len + sema.param_count)
|
||||
// return zir_ref;
|
||||
// Until then we allocate memory for a new, mutable `ir.Inst` to match what
|
||||
// TZIR expects.
|
||||
return sema.mod.constInst(sema.arena, .unneeded, zir.Inst.Ref.typed_value_map[i]);
|
||||
}
|
||||
i -= zir.Inst.Ref.typed_value_map.len;
|
||||
|
||||
return sema.inst_map[zir_ref.toIndex(param_count).?];
|
||||
// Next section of indexes correspond to function parameters, if any.
|
||||
if (i < sema.param_inst_list.len) {
|
||||
return sema.param_inst_list[i];
|
||||
}
|
||||
i -= sema.param_inst_list.len;
|
||||
|
||||
// Finally, the last section of indexes refers to the map of ZIR=>TZIR.
|
||||
return sema.inst_map[i];
|
||||
}
|
||||
|
||||
fn resolveConstString(
|
||||
@ -753,8 +763,7 @@ fn zirCompileLog(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);
|
||||
const raw_args = sema.code.extra[extra.end..][0..extra.data.operands_len];
|
||||
const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args));
|
||||
const args = sema.code.refSlice(extra.end, extra.data.operands_len);
|
||||
|
||||
for (args) |arg_ref, i| {
|
||||
if (i != 0) try writer.print(", ", .{});
|
||||
@ -1105,8 +1114,7 @@ fn zirCall(
|
||||
const func_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
|
||||
const call_src = inst_data.src();
|
||||
const extra = sema.code.extraData(zir.Inst.Call, inst_data.payload_index);
|
||||
const raw_args = sema.code.extra[extra.end..][0..extra.data.args_len];
|
||||
const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args));
|
||||
const args = sema.code.refSlice(extra.end, extra.data.args_len);
|
||||
|
||||
return sema.analyzeCall(block, extra.data.callee, func_src, call_src, modifier, ensure_result_used, args);
|
||||
}
|
||||
@ -1733,8 +1741,7 @@ fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: b
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].fn_type;
|
||||
const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index);
|
||||
const raw_param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len];
|
||||
const param_types = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_param_types));
|
||||
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
|
||||
return sema.fnTypeCommon(
|
||||
block,
|
||||
@ -1752,8 +1759,7 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args:
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].fn_type;
|
||||
const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index);
|
||||
const raw_param_types = sema.code.extra[extra.end..][0..extra.data.param_types_len];
|
||||
const param_types = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_param_types));
|
||||
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
|
||||
const cc_tv = try sema.resolveInstConst(block, .todo, extra.data.cc);
|
||||
// TODO once we're capable of importing and analyzing decls from
|
||||
@ -2768,8 +2774,7 @@ fn zirTypeofPeer(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const src = inst_data.src();
|
||||
const extra = sema.code.extraData(zir.Inst.MultiOp, inst_data.payload_index);
|
||||
const raw_args = sema.code.extra[extra.end..][0..extra.data.operands_len];
|
||||
const args = mem.bytesAsSlice(zir.Inst.Ref, mem.sliceAsBytes(raw_args));
|
||||
const args = sema.code.refSlice(extra.end, extra.data.operands_len);
|
||||
|
||||
const inst_list = try sema.gpa.alloc(*ir.Inst, extra.data.operands_len);
|
||||
defer sema.gpa.free(inst_list);
|
||||
|
||||
@ -926,7 +926,7 @@ fn labeledBlockExpr(
|
||||
// would be better still to elide the ones that are in this list.
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
|
||||
return zir.Inst.Ref.fromIndex(block_inst, gz.zir_code.param_count);
|
||||
return gz.zir_code.indexToRef(block_inst);
|
||||
},
|
||||
.break_operand => {
|
||||
// All break operands are values that did not use the result location pointer.
|
||||
@ -939,7 +939,7 @@ fn labeledBlockExpr(
|
||||
// would be better still to elide the ones that are in this list.
|
||||
}
|
||||
try block_scope.setBlockBody(block_inst);
|
||||
const block_ref = zir.Inst.Ref.fromIndex(block_inst, gz.zir_code.param_count);
|
||||
const block_ref = gz.zir_code.indexToRef(block_inst);
|
||||
switch (rl) {
|
||||
.ref => return block_ref,
|
||||
else => return rvalue(mod, parent_scope, rl, block_ref, block_node),
|
||||
@ -991,7 +991,7 @@ fn blockExprStmts(
|
||||
// We need to emit an error if the result is not `noreturn` or `void`, but
|
||||
// we want to avoid adding the ZIR instruction if possible for performance.
|
||||
const maybe_unused_result = try expr(mod, scope, .none, statement);
|
||||
const elide_check = if (maybe_unused_result.toIndex(gz.zir_code.param_count)) |inst| b: {
|
||||
const elide_check = if (gz.zir_code.refToIndex(maybe_unused_result)) |inst| b: {
|
||||
// Note that this array becomes invalid after appending more items to it
|
||||
// in the above while loop.
|
||||
const zir_tags = gz.zir_code.instructions.items(.tag);
|
||||
@ -1292,7 +1292,7 @@ fn varDecl(
|
||||
const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2;
|
||||
try parent_zir.ensureCapacity(mod.gpa, expected_len);
|
||||
for (init_scope.instructions.items) |src_inst| {
|
||||
if (zir.Inst.Ref.fromIndex(src_inst, wzc.param_count) == init_scope.rl_ptr) continue;
|
||||
if (wzc.indexToRef(src_inst) == init_scope.rl_ptr) continue;
|
||||
if (zir_tags[src_inst] == .store_to_block_ptr) {
|
||||
if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue;
|
||||
}
|
||||
@ -1525,7 +1525,7 @@ fn ptrType(
|
||||
}
|
||||
|
||||
const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
|
||||
const result = zir.Inst.Ref.fromIndex(new_index, gz.zir_code.param_count);
|
||||
const result = gz.zir_code.indexToRef(new_index);
|
||||
gz.zir_code.instructions.appendAssumeCapacity(.{ .tag = .ptr_type, .data = .{
|
||||
.ptr_type = .{
|
||||
.flags = .{
|
||||
@ -1782,7 +1782,7 @@ fn finishThenElseBlock(
|
||||
}
|
||||
assert(!strat.elide_store_to_block_ptr_instructions);
|
||||
try setCondBrPayload(condbr, cond, then_scope, else_scope);
|
||||
return zir.Inst.Ref.fromIndex(main_block, wzc.param_count);
|
||||
return wzc.indexToRef(main_block);
|
||||
},
|
||||
.break_operand => {
|
||||
if (!wzc.refIsNoReturn(then_result)) {
|
||||
@ -1818,7 +1818,7 @@ fn finishThenElseBlock(
|
||||
} else {
|
||||
try setCondBrPayload(condbr, cond, then_scope, else_scope);
|
||||
}
|
||||
const block_ref = zir.Inst.Ref.fromIndex(main_block, wzc.param_count);
|
||||
const block_ref = wzc.indexToRef(main_block);
|
||||
switch (rl) {
|
||||
.ref => return block_ref,
|
||||
else => return rvalue(mod, parent_scope, rl, block_ref, node),
|
||||
@ -1981,7 +1981,7 @@ fn boolBinOp(
|
||||
_ = try rhs_scope.addUnNode(.break_flat, rhs, node);
|
||||
try rhs_scope.setBoolBrBody(bool_br);
|
||||
|
||||
const block_ref = zir.Inst.Ref.fromIndex(bool_br, gz.zir_code.param_count);
|
||||
const block_ref = gz.zir_code.indexToRef(bool_br);
|
||||
return rvalue(mod, scope, rl, block_ref, node);
|
||||
}
|
||||
|
||||
@ -3092,7 +3092,7 @@ fn asmExpr(
|
||||
|
||||
try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len +
|
||||
args.len + constraints.len);
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(mem.bytesAsSlice(u32, mem.sliceAsBytes(args)));
|
||||
gz.zir_code.appendRefsAssumeCapacity(args);
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(constraints);
|
||||
|
||||
return rvalue(mod, scope, rl, result, node);
|
||||
@ -3164,7 +3164,7 @@ fn asRlPtr(
|
||||
const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2;
|
||||
try parent_zir.ensureCapacity(mod.gpa, expected_len);
|
||||
for (as_scope.instructions.items) |src_inst| {
|
||||
if (zir.Inst.Ref.fromIndex(src_inst, wzc.param_count) == as_scope.rl_ptr) continue;
|
||||
if (wzc.indexToRef(src_inst) == as_scope.rl_ptr) continue;
|
||||
if (zir_tags[src_inst] == .store_to_block_ptr) {
|
||||
if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue;
|
||||
}
|
||||
@ -3256,7 +3256,7 @@ fn typeOf(
|
||||
}
|
||||
|
||||
const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{ .operands_len = @intCast(u32, params.len) });
|
||||
try gz.zir_code.extra.appendSlice(gz.zir_code.gpa, mem.bytesAsSlice(u32, mem.sliceAsBytes(items)));
|
||||
try gz.zir_code.appendRefs(items);
|
||||
|
||||
return rvalue(mod, scope, rl, result, node);
|
||||
}
|
||||
|
||||
60
src/zir.zig
60
src/zir.zig
@ -70,6 +70,11 @@ pub const Code = struct {
|
||||
return code.string_bytes[index..end :0];
|
||||
}
|
||||
|
||||
pub fn refSlice(code: Code, start: usize, len: usize) []Inst.Ref {
|
||||
const raw_slice = code.extra[start..][0..len];
|
||||
return @bitCast([]Inst.Ref, raw_slice);
|
||||
}
|
||||
|
||||
pub fn deinit(code: *Code, gpa: *Allocator) void {
|
||||
code.instructions.deinit(gpa);
|
||||
gpa.free(code.string_bytes);
|
||||
@ -767,16 +772,17 @@ pub const Inst = struct {
|
||||
/// of the current function or a ZIR instruction.
|
||||
///
|
||||
/// The first values after the the last tag refer to parameters which may be
|
||||
/// derived by subtracting typed_value_count.
|
||||
/// derived by subtracting typed_value_map.len.
|
||||
///
|
||||
/// All further values refer to ZIR instructions which may be derived by
|
||||
/// subtracting typed_value_count and the number of parameters.
|
||||
/// subtracting typed_value_map.len and the number of parameters.
|
||||
///
|
||||
/// When adding a tag to this enum, consider adding a corresponding entry to
|
||||
/// `simple_types` in astgen.
|
||||
///
|
||||
/// This is packed so that it is safe to cast between `[]u32` and `[]Ref`.
|
||||
pub const Ref = packed enum(u32) {
|
||||
/// The tag type is specified so that it is safe to bitcast between `[]u32`
|
||||
/// and `[]Ref`.
|
||||
pub const Ref = enum(u32) {
|
||||
/// This Ref does not correspond to any ZIR instruction or constant
|
||||
/// value and may instead be used as a sentinel to indicate null.
|
||||
none,
|
||||
@ -841,8 +847,7 @@ pub const Inst = struct {
|
||||
|
||||
_,
|
||||
|
||||
pub const typed_value_count = @as(u32, typed_value_map.len);
|
||||
const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
|
||||
pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
|
||||
.none = undefined,
|
||||
|
||||
.u8_type = .{
|
||||
@ -1039,36 +1044,6 @@ pub const Inst = struct {
|
||||
.val = Value.initTag(.bool_false),
|
||||
},
|
||||
});
|
||||
|
||||
pub fn fromParam(param: u32) Ref {
|
||||
return @intToEnum(Ref, typed_value_count + param);
|
||||
}
|
||||
|
||||
pub fn fromIndex(index: Index, param_count: u32) Ref {
|
||||
return @intToEnum(Ref, typed_value_count + param_count + index);
|
||||
}
|
||||
|
||||
pub fn toTypedValue(ref: Ref) ?TypedValue {
|
||||
assert(ref != .none);
|
||||
if (@enumToInt(ref) >= typed_value_count) return null;
|
||||
return typed_value_map[@enumToInt(ref)];
|
||||
}
|
||||
|
||||
pub fn toParam(ref: Ref, param_count: u32) ?u32 {
|
||||
assert(ref != .none);
|
||||
if (@enumToInt(ref) < typed_value_count or
|
||||
@enumToInt(ref) >= typed_value_count + param_count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return @enumToInt(ref) - typed_value_count;
|
||||
}
|
||||
|
||||
pub fn toIndex(ref: Ref, param_count: u32) ?Index {
|
||||
assert(ref != .none);
|
||||
if (@enumToInt(ref) < typed_value_count + param_count) return null;
|
||||
return @enumToInt(ref) - typed_value_count - param_count;
|
||||
}
|
||||
};
|
||||
|
||||
/// All instructions have an 8-byte payload, which is contained within
|
||||
@ -1672,8 +1647,7 @@ const Writer = struct {
|
||||
fn writePlNodeCall(self: *Writer, stream: anytype, inst: Inst.Index) !void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = self.code.extraData(Inst.Call, inst_data.payload_index);
|
||||
const raw_args = self.code.extra[extra.end..][0..extra.data.args_len];
|
||||
const args = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_args));
|
||||
const args = self.code.refSlice(extra.end, extra.data.args_len);
|
||||
|
||||
try self.writeInstRef(stream, extra.data.callee);
|
||||
try stream.writeAll(", [");
|
||||
@ -1767,8 +1741,7 @@ const Writer = struct {
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].fn_type;
|
||||
const extra = self.code.extraData(Inst.FnType, inst_data.payload_index);
|
||||
const raw_param_types = self.code.extra[extra.end..][0..extra.data.param_types_len];
|
||||
const param_types = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_param_types));
|
||||
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, .none);
|
||||
}
|
||||
|
||||
@ -1793,8 +1766,7 @@ const Writer = struct {
|
||||
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
|
||||
const inst_data = self.code.instructions.items(.data)[inst].fn_type;
|
||||
const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index);
|
||||
const raw_param_types = self.code.extra[extra.end..][0..extra.data.param_types_len];
|
||||
const param_types = mem.bytesAsSlice(Inst.Ref, mem.sliceAsBytes(raw_param_types));
|
||||
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
|
||||
const cc = extra.data.cc;
|
||||
return self.writeFnTypeCommon(stream, param_types, inst_data.return_type, var_args, cc);
|
||||
}
|
||||
@ -1864,10 +1836,10 @@ const Writer = struct {
|
||||
fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {
|
||||
var i: usize = @enumToInt(ref);
|
||||
|
||||
if (i < Inst.Ref.typed_value_count) {
|
||||
if (i < Inst.Ref.typed_value_map.len) {
|
||||
return stream.print("@{}", .{ref});
|
||||
}
|
||||
i -= Inst.Ref.typed_value_count;
|
||||
i -= Inst.Ref.typed_value_map.len;
|
||||
|
||||
if (i < self.param_count) {
|
||||
return stream.print("${d}", .{i});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user