Commit 5769c963e0
Changed files (4)
src/astgen.zig
@@ -3000,19 +3000,18 @@ fn as(
lhs: ast.Node.Index,
rhs: ast.Node.Index,
) InnerError!zir.Inst.Ref {
- if (true) @panic("TODO update for zir-memory-layout");
const dest_type = try typeExpr(mod, scope, lhs);
switch (rl) {
.none, .discard, .ref, .ty => {
const result = try expr(mod, scope, .{ .ty = dest_type }, rhs);
- return rvalue(mod, scope, rl, result);
+ return rvalue(mod, scope, rl, result, node);
},
.ptr => |result_ptr| {
- return asRlPtr(mod, scope, rl, src, result_ptr, rhs, dest_type);
+ return asRlPtr(mod, scope, rl, result_ptr, rhs, dest_type);
},
.block_ptr => |block_scope| {
- return asRlPtr(mod, scope, rl, src, block_scope.rl_ptr.?, rhs, dest_type);
+ return asRlPtr(mod, scope, rl, block_scope.rl_ptr, rhs, dest_type);
},
.bitcasted_ptr => |bitcasted_ptr| {
@@ -3030,7 +3029,6 @@ fn asRlPtr(
mod: *Module,
scope: *Scope,
rl: ResultLoc,
- src: usize,
result_ptr: zir.Inst.Ref,
operand_node: ast.Node.Index,
dest_type: zir.Inst.Ref,
@@ -3038,32 +3036,35 @@ fn asRlPtr(
// Detect whether this expr() call goes into rvalue() to store the result into the
// result location. If it does, elide the coerce_result_ptr instruction
// as well as the store instruction, instead passing the result as an rvalue.
+ const parent_gz = scope.getGenZir();
+
var as_scope: Scope.GenZir = .{
.parent = scope,
- .decl = scope.ownerDecl().?,
- .arena = scope.arena(),
+ .zir_code = parent_gz.zir_code,
.force_comptime = scope.isComptime(),
.instructions = .{},
};
defer as_scope.instructions.deinit(mod.gpa);
- as_scope.rl_ptr = try addZIRBinOp(mod, &as_scope.base, src, .coerce_result_ptr, dest_type, result_ptr);
+ as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr);
const result = try expr(mod, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node);
- const parent_zir = &scope.getGenZir().instructions;
+ const parent_zir = &parent_gz.instructions;
if (as_scope.rvalue_rl_count == 1) {
// Busted! This expression didn't actually need a pointer.
+ const zir_tags = parent_gz.zir_code.instructions.items(.tag);
+ const zir_datas = parent_gz.zir_code.instructions.items(.data);
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 (src_inst == as_scope.rl_ptr.?) continue;
- if (src_inst.castTag(.store_to_block_ptr)) |store| {
- if (store.positionals.lhs == as_scope.rl_ptr.?) continue;
+ if (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;
}
parent_zir.appendAssumeCapacity(src_inst);
}
assert(parent_zir.items.len == expected_len);
- const casted_result = try addZIRBinOp(mod, scope, dest_type.src, .as, dest_type, result);
- return rvalue(mod, scope, rl, casted_result);
+ const casted_result = try parent_gz.addBin(.as, dest_type, result);
+ return rvalue(mod, scope, rl, casted_result, operand_node);
} else {
try parent_zir.appendSlice(mod.gpa, as_scope.instructions.items);
return result;
src/Module.zig
@@ -1667,6 +1667,9 @@ pub const SrcLoc = struct {
.node_offset_asm_ret_ty,
.node_offset_if_cond,
.node_offset_anyframe_type,
+ .node_offset_bin_op,
+ .node_offset_bin_lhs,
+ .node_offset_bin_rhs,
=> src_loc.container.decl.container.file_scope,
};
}
@@ -1722,6 +1725,9 @@ pub const SrcLoc = struct {
.node_offset_asm_ret_ty => @panic("TODO"),
.node_offset_if_cond => @panic("TODO"),
.node_offset_anyframe_type => @panic("TODO"),
+ .node_offset_bin_op => @panic("TODO"),
+ .node_offset_bin_lhs => @panic("TODO"),
+ .node_offset_bin_rhs => @panic("TODO"),
}
}
};
@@ -1846,6 +1852,20 @@ pub const LazySrcLoc = union(enum) {
/// to the type expression.
/// The Decl is determined contextually.
node_offset_anyframe_type: i32,
+ /// The source location points to a binary expression, such as `a + b`, found
+ /// by taking this AST node index offset from the containing Decl AST node.
+ /// The Decl is determined contextually.
+ node_offset_bin_op: i32,
+ /// The source location points to the LHS of a binary expression, found
+ /// by taking this AST node index offset from the containing Decl AST node,
+ /// which points to a binary expression AST node. Next, nagivate to the LHS.
+ /// The Decl is determined contextually.
+ node_offset_bin_lhs: i32,
+ /// The source location points to the RHS of a binary expression, found
+ /// by taking this AST node index offset from the containing Decl AST node,
+ /// which points to a binary expression AST node. Next, nagivate to the RHS.
+ /// The Decl is determined contextually.
+ node_offset_bin_rhs: i32,
/// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
@@ -1877,6 +1897,9 @@ pub const LazySrcLoc = union(enum) {
.node_offset_asm_ret_ty,
.node_offset_if_cond,
.node_offset_anyframe_type,
+ .node_offset_bin_op,
+ .node_offset_bin_lhs,
+ .node_offset_bin_rhs,
=> .{
.container = .{ .decl = scope.srcDecl().? },
.lazy = lazy,
@@ -1914,6 +1937,9 @@ pub const LazySrcLoc = union(enum) {
.node_offset_asm_ret_ty,
.node_offset_if_cond,
.node_offset_anyframe_type,
+ .node_offset_bin_op,
+ .node_offset_bin_lhs,
+ .node_offset_bin_rhs,
=> .{
.container = .{ .decl = decl },
.lazy = lazy,
src/Sema.zig
@@ -2419,17 +2419,18 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
const tracy = trace(@src());
defer tracy.end();
- if (true) @panic("TODO rework with zir-memory-layout in mind");
-
- const bin_inst = sema.code.instructions.items(.data)[inst].bin;
- const src: LazySrcLoc = .todo;
- const lhs = try sema.resolveInst(bin_inst.lhs);
- const rhs = try sema.resolveInst(bin_inst.rhs);
+ const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
+ const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
+ const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+ const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+ const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
+ const lhs = try sema.resolveInst(extra.lhs);
+ const rhs = try sema.resolveInst(extra.rhs);
const instructions = &[_]*Inst{ lhs, rhs };
const resolved_type = try sema.resolvePeerTypes(block, instructions);
- const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs.src);
- const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs.src);
+ const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
+ const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
const scalar_type = if (resolved_type.zigTypeTag() == .Vector)
resolved_type.elemType()
@@ -2455,8 +2456,9 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat;
+ const zir_tags = block.sema.code.instructions.items(.tag);
- if (!is_int and !(is_float and floatOpAllowed(inst.base.tag))) {
+ if (!is_int and !(is_float and floatOpAllowed(zir_tags[inst]))) {
return sema.mod.fail(&block.base, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ @tagName(lhs.ty.zigTypeTag()), @tagName(rhs.ty.zigTypeTag()) });
}
@@ -2468,71 +2470,56 @@ fn zirArithmetic(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerEr
.val = Value.initTag(.undef),
});
}
- return sema.analyzeInstComptimeOp(block, scalar_type, inst, lhs_val, rhs_val);
+ // incase rhs is 0, simply return lhs without doing any calculations
+ // TODO Once division is implemented we should throw an error when dividing by 0.
+ if (rhs_val.compareWithZero(.eq)) {
+ return sema.mod.constInst(sema.arena, src, .{
+ .ty = scalar_type,
+ .val = lhs_val,
+ });
+ }
+
+ const value = switch (zir_tags[inst]) {
+ .add => blk: {
+ const val = if (is_int)
+ try Module.intAdd(sema.arena, lhs_val, rhs_val)
+ else
+ try Module.floatAdd(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ break :blk val;
+ },
+ .sub => blk: {
+ const val = if (is_int)
+ try Module.intSub(sema.arena, lhs_val, rhs_val)
+ else
+ try Module.floatSub(sema.arena, scalar_type, src, lhs_val, rhs_val);
+ break :blk val;
+ },
+ else => return sema.mod.fail(&block.base, src, "TODO Implement arithmetic operand '{s}'", .{@tagName(zir_tags[inst])}),
+ };
+
+ log.debug("{s}({}, {}) result: {}", .{ @tagName(zir_tags[inst]), lhs_val, rhs_val, value });
+
+ return sema.mod.constInst(sema.arena, src, .{
+ .ty = scalar_type,
+ .val = value,
+ });
}
}
try sema.requireRuntimeBlock(block, src);
- const ir_tag: Inst.Tag = switch (inst.base.tag) {
+ const ir_tag: Inst.Tag = switch (zir_tags[inst]) {
.add => .add,
.addwrap => .addwrap,
.sub => .sub,
.subwrap => .subwrap,
.mul => .mul,
.mulwrap => .mulwrap,
- else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}''", .{@tagName(inst.base.tag)}),
+ else => return sema.mod.fail(&block.base, src, "TODO implement arithmetic for operand '{s}''", .{@tagName(zir_tags[inst])}),
};
return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
}
-/// Analyzes operands that are known at comptime
-fn analyzeInstComptimeOp(
- sema: *Sema,
- block: *Scope.Block,
- res_type: Type,
- inst: zir.Inst.Index,
- lhs_val: Value,
- rhs_val: Value,
-) InnerError!*Inst {
- if (true) @panic("TODO rework analyzeInstComptimeOp for zir-memory-layout");
-
- // incase rhs is 0, simply return lhs without doing any calculations
- // TODO Once division is implemented we should throw an error when dividing by 0.
- if (rhs_val.compareWithZero(.eq)) {
- return sema.mod.constInst(sema.arena, inst.base.src, .{
- .ty = res_type,
- .val = lhs_val,
- });
- }
- const is_int = res_type.isInt() or res_type.zigTypeTag() == .ComptimeInt;
-
- const value = switch (inst.base.tag) {
- .add => blk: {
- const val = if (is_int)
- try Module.intAdd(sema.arena, lhs_val, rhs_val)
- else
- try Module.floatAdd(sema.arena, res_type, inst.base.src, lhs_val, rhs_val);
- break :blk val;
- },
- .sub => blk: {
- const val = if (is_int)
- try Module.intSub(sema.arena, lhs_val, rhs_val)
- else
- try Module.floatSub(sema.arena, res_type, inst.base.src, lhs_val, rhs_val);
- break :blk val;
- },
- else => return sema.mod.fail(&block.base, inst.base.src, "TODO Implement arithmetic operand '{s}'", .{@tagName(inst.base.tag)}),
- };
-
- log.debug("{s}({}, {}) result: {}", .{ @tagName(inst.base.tag), lhs_val, rhs_val, value });
-
- return sema.mod.constInst(sema.arena, inst.base.src, .{
- .ty = res_type,
- .val = value,
- });
-}
-
fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
src/zir.zig
@@ -524,6 +524,7 @@ pub const Inst = struct {
cmp_neq,
/// Coerces a result location pointer to a new element type. It is evaluated "backwards"-
/// as type coercion from the new element type to the old element type.
+ /// Uses the `bin` union field.
/// LHS is destination element type, RHS is result pointer.
coerce_result_ptr,
/// Emit an error message and fail compilation.
@@ -1327,33 +1328,12 @@ const Writer = struct {
const tag = tags[inst];
try stream.print("= {s}(", .{@tagName(tags[inst])});
switch (tag) {
- .add,
- .addwrap,
- .array_cat,
- .array_mul,
- .mul,
- .mulwrap,
- .sub,
- .subwrap,
.array_type,
.bit_and,
.bit_or,
.as,
- .bool_and,
- .bool_or,
.@"break",
- .cmp_lt,
- .cmp_lte,
- .cmp_eq,
- .cmp_gte,
- .cmp_gt,
- .cmp_neq,
.coerce_result_ptr,
- .div,
- .mod_rem,
- .shl,
- .shr,
- .xor,
.elem_ptr,
.elem_val,
.intcast,
@@ -1447,6 +1427,29 @@ const Writer = struct {
.suspend_block,
=> try self.writePlNode(stream, inst),
+ .add,
+ .addwrap,
+ .array_cat,
+ .array_mul,
+ .mul,
+ .mulwrap,
+ .sub,
+ .subwrap,
+ .bool_and,
+ .bool_or,
+ .cmp_lt,
+ .cmp_lte,
+ .cmp_eq,
+ .cmp_gte,
+ .cmp_gt,
+ .cmp_neq,
+ .div,
+ .mod_rem,
+ .shl,
+ .shr,
+ .xor,
+ => try self.writePlNodeBin(stream, inst),
+
.as_node => try self.writeAs(stream, inst),
.breakpoint,
@@ -1589,6 +1592,16 @@ const Writer = struct {
try self.writeSrc(stream, inst_data.src());
}
+ fn writePlNodeBin(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.Bin, inst_data.payload_index).data;
+ try self.writeInstRef(stream, extra.lhs);
+ try stream.writeAll(", ");
+ try self.writeInstRef(stream, extra.rhs);
+ try stream.writeAll(") ");
+ try self.writeSrc(stream, inst_data.src());
+ }
+
fn writeAs(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.As, inst_data.payload_index).data;