Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Merged If and InlineIf nodes (but does not allow unwrap in inline if) #205

Merged
merged 3 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn get_buzz_prefix(b: *Build) []const u8 {
pub fn build(b: *Build) !void {
// Check minimum zig version
const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse("0.12.0-dev.790+ad6f8e3a5") catch return;
const min_zig = std.SemanticVersion.parse("0.12.0-dev.878+7abf9b3a8") catch return;
if (current_zig.order(min_zig).compare(.lt)) {
@panic(b.fmt("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig }));
}
Expand Down Expand Up @@ -322,7 +322,7 @@ pub fn build(b: *Build) !void {
if (build_options.needLibC()) {
exe.linkLibC();
}
exe.main_pkg_path = .{ .path = "." };
exe.main_mod_path = .{ .path = "." };

exe.addOptions("build_options", build_options.step(b));

Expand All @@ -345,7 +345,7 @@ pub fn build(b: *Build) !void {
if (build_options.needLibC()) {
lib.linkLibC();
}
lib.main_pkg_path = .{ .path = "src" };
lib.main_mod_path = .{ .path = "src" };

lib.addOptions("build_options", build_options.step(b));

Expand Down Expand Up @@ -427,7 +427,7 @@ pub fn build(b: *Build) !void {
if (build_options.needLibC()) {
std_lib.linkLibC();
}
std_lib.main_pkg_path = .{ .path = "src" };
std_lib.main_mod_path = .{ .path = "src" };
std_lib.linkLibrary(lib);
std_lib.addOptions("build_options", build_options.step(b));

Expand Down
183 changes: 83 additions & 100 deletions src/mirjit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,13 @@ fn buildPush(self: *Self, value: m.MIR_op_t) !void {
const stack_top_base = try self.REG("stack_top_base", m.MIR_T_I64);
const index = try self.REG("index", m.MIR_T_I64);

// Avoid intertwining the push and its value expression
const value_reg = m.MIR_new_reg_op(
self.ctx,
try self.REG("value", m.MIR_T_I64),
);
self.MOV(value_reg, value);

self.MOV(
m.MIR_new_reg_op(self.ctx, index),
m.MIR_new_uint_op(self.ctx, 0),
Expand Down Expand Up @@ -1457,7 +1464,7 @@ fn buildPush(self: *Self, value: m.MIR_op_t) !void {

self.MOV(
top,
value,
value_reg,
);

// Increment stack top
Expand All @@ -1468,6 +1475,7 @@ fn buildPush(self: *Self, value: m.MIR_op_t) !void {
);
}

// FIXME: we should not need 3 MOV to get to the value?
fn buildPop(self: *Self, dest: ?m.MIR_op_t) !void {
const ctx_reg = self.state.?.ctx_reg.?;
const stack_top_ptr_base = try self.REG("stack_top_ptr_base", m.MIR_T_I64);
Expand Down Expand Up @@ -1522,22 +1530,21 @@ fn buildPop(self: *Self, dest: ?m.MIR_op_t) !void {
);

// Store new top in result reg
const top = m.MIR_new_mem_op(
self.ctx,
m.MIR_T_P,
0,
stack_top_base,
index,
1,
);

self.MOV(
dest orelse m.MIR_new_reg_op(
if (dest) |into| {
const top = m.MIR_new_mem_op(
self.ctx,
try self.REG("dismiss", m.MIR_T_I64),
),
top,
);
m.MIR_T_P,
0,
stack_top_base,
index,
1,
);

self.MOV(
into,
top,
);
}
}

fn buildPeek(self: *Self, distance: u32, dest: m.MIR_op_t) !void {
Expand Down Expand Up @@ -1621,21 +1628,38 @@ fn buildGetLocal(self: *Self, slot: usize) !m.MIR_op_t {
m.MIR_new_uint_op(self.ctx, slot),
);

return m.MIR_new_mem_op(
// Avoid intertwining the get local and its value expression
const value_reg = m.MIR_new_reg_op(
self.ctx,
m.MIR_T_U64,
0,
base,
index,
@sizeOf(u64),
try self.REG("value", m.MIR_T_I64),
);
self.MOV(
value_reg,
m.MIR_new_mem_op(
self.ctx,
m.MIR_T_U64,
0,
base,
index,
@sizeOf(u64),
),
);

return value_reg;
}

fn buildSetLocal(self: *Self, slot: usize, value: m.MIR_op_t) !void {
const ctx_reg = self.state.?.ctx_reg.?;
const index = try self.REG("index", m.MIR_T_I64);
const base = try self.REG("base", m.MIR_T_I64);

// Avoid intertwining the set local and its value expression
const value_reg = m.MIR_new_reg_op(
self.ctx,
try self.REG("value", m.MIR_T_I64),
);
self.MOV(value_reg, value);

self.MOV(
m.MIR_new_reg_op(self.ctx, index),
m.MIR_new_uint_op(self.ctx, 0),
Expand Down Expand Up @@ -1667,7 +1691,7 @@ fn buildSetLocal(self: *Self, slot: usize, value: m.MIR_op_t) !void {
@sizeOf(u64),
);

self.MOV(local, value);
self.MOV(local, value_reg);
}

fn buildGetGlobal(self: *Self, slot: usize) !m.MIR_op_t {
Expand Down Expand Up @@ -2251,7 +2275,6 @@ fn generateNode(self: *Self, node: *n.ParseNode) Error!?m.MIR_op_t {
.Unary => try self.generateUnary(n.UnaryNode.cast(node).?),
.Pattern => try self.generatePattern(n.PatternNode.cast(node).?),
.ForEach => try self.generateForEach(n.ForEachNode.cast(node).?),
.InlineIf => try self.generateInlineIf(n.InlineIfNode.cast(node).?),
.TypeExpression => try self.generateTypeExpression(n.TypeExpressionNode.cast(node).?),
.TypeOfExpression => try self.generateTypeOfExpression(n.TypeOfExpressionNode.cast(node).?),
.AsyncCall,
Expand Down Expand Up @@ -2928,6 +2951,11 @@ fn generateIf(self: *Self, if_node: *n.IfNode) Error!?m.MIR_op_t {
try self.REG("condition", m.MIR_T_I64),
);

const resolved = if (!if_node.is_statement)
try self.REG("resolved", m.MIR_T_I64)
else
null;

// Is it `if (opt -> unwrapped)`?
if (if_node.unwrapped_identifier != null) {
try self.buildExternApiCall(
Expand All @@ -2939,6 +2967,7 @@ fn generateIf(self: *Self, if_node: *n.IfNode) Error!?m.MIR_op_t {
},
);

// TODO: replace with condition ^ (MIR_OR, MIR_XOR?) 1
const true_label = m.MIR_new_label(self.ctx);
const out_label = m.MIR_new_label(self.ctx);

Expand Down Expand Up @@ -3022,10 +3051,22 @@ fn generateIf(self: *Self, if_node: *n.IfNode) Error!?m.MIR_op_t {

// Push unwrapped value as local of the then block
if (if_node.unwrapped_identifier != null or if_node.casted_type != null) {
try self.buildPush(condition_value.?);
try self.buildPush(
if (constant_condition) |constant|
m.MIR_new_uint_op(self.ctx, constant.val)
else
condition_value.?,
);
}

_ = try self.generateNode(if_node.body);
if (if_node.is_statement) {
_ = try self.generateNode(if_node.body);
} else {
self.MOV(
m.MIR_new_reg_op(self.ctx, resolved.?),
(try self.generateNode(if_node.body)).?,
);
}

self.JMP(out_label);
}
Expand All @@ -3034,13 +3075,23 @@ fn generateIf(self: *Self, if_node: *n.IfNode) Error!?m.MIR_op_t {
if (if_node.else_branch) |else_branch| {
self.append(else_label);

_ = try self.generateNode(else_branch);
if (if_node.is_statement) {
_ = try self.generateNode(else_branch);
} else {
self.MOV(
m.MIR_new_reg_op(self.ctx, resolved.?),
(try self.generateNode(else_branch)).?,
);
}
}
}

self.append(out_label);

return null;
return if (if_node.is_statement)
null
else
m.MIR_new_reg_op(self.ctx, resolved.?);
}

fn generateTypeExpression(self: *Self, type_expression_node: *n.TypeExpressionNode) Error!?m.MIR_op_t {
Expand Down Expand Up @@ -3069,78 +3120,6 @@ fn generateTypeOfExpression(self: *Self, typeof_expression_node: *n.TypeOfExpres
return result;
}

fn generateInlineIf(self: *Self, inline_if_node: *n.InlineIfNode) Error!?m.MIR_op_t {
const constant_condition = if (inline_if_node.condition.isConstant(inline_if_node.condition))
inline_if_node.condition.toValue(inline_if_node.condition, self.vm.gc) catch unreachable
else
null;

// Generate condition
const condition = (try self.generateNode(inline_if_node.condition)).?;

const resolved = try self.REG("resolved", m.MIR_T_I64);

const out_label = m.MIR_new_label(self.ctx);
const then_label = m.MIR_new_label(self.ctx);
const else_label = m.MIR_new_label(self.ctx);

if (constant_condition != null) {
self.JMP(
if (constant_condition.?.boolean())
then_label
else
else_label,
);
} else {
const unwrapped_condition = m.MIR_new_reg_op(
self.ctx,
try self.REG("ucond", m.MIR_T_I64),
);

try self.unwrap(
.Bool,
condition,
unwrapped_condition,
);

self.BEQ(
m.MIR_new_label_op(self.ctx, then_label),
unwrapped_condition,
m.MIR_new_uint_op(self.ctx, 1),
);

self.JMP(else_label);
}

if (constant_condition == null or constant_condition.?.boolean()) {
self.append(
then_label,
);

self.MOV(
m.MIR_new_reg_op(self.ctx, resolved),
(try self.generateNode(inline_if_node.body)).?,
);

self.JMP(out_label);
}

if (constant_condition == null or !constant_condition.?.boolean()) {
self.append(
else_label,
);

self.MOV(
m.MIR_new_reg_op(self.ctx, resolved),
(try self.generateNode(inline_if_node.else_branch)).?,
);
}

self.append(out_label);

return m.MIR_new_reg_op(self.ctx, resolved);
}

fn generateBinary(self: *Self, binary_node: *n.BinaryNode) Error!?m.MIR_op_t {
const left_type_def = binary_node.left.type_def.?.def_type;
const right_type_def = binary_node.right.type_def.?.def_type;
Expand Down Expand Up @@ -4535,6 +4514,10 @@ fn generateTry(self: *Self, try_node: *n.TryNode) Error!?m.MIR_op_t {
}

fn generateThrow(self: *Self, throw_node: *n.ThrowNode) Error!?m.MIR_op_t {
if (throw_node.unconditional) {
self.state.?.return_emitted = true;
}

try self.buildExternApiCall(
.bz_throw,
null,
Expand Down
Loading