astgen: fix for loop expressions
also rename the ZIR instruction `deref_node` to `load`.
This commit is contained in:
@@ -35,3 +35,6 @@ 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
|
||||
* astgen for loops using pointer arithmetic because it's faster and if the programmer
|
||||
wants an index capture, that will just be a convenience variable that zig sets up
|
||||
independently.
|
||||
|
||||
30
src/Sema.zig
30
src/Sema.zig
@@ -160,7 +160,7 @@ pub fn analyzeBody(
|
||||
.@"const" => try sema.zirConst(block, inst),
|
||||
.decl_ref => try sema.zirDeclRef(block, inst),
|
||||
.decl_val => try sema.zirDeclVal(block, inst),
|
||||
.deref_node => try sema.zirDerefNode(block, inst),
|
||||
.load => try sema.zirLoad(block, inst),
|
||||
.div => try sema.zirArithmetic(block, inst),
|
||||
.elem_ptr => try sema.zirElemPtr(block, inst),
|
||||
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
|
||||
@@ -576,7 +576,7 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
|
||||
return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
|
||||
}
|
||||
const result_ptr = try sema.namedFieldPtr(block, src, array_ptr, "len", src);
|
||||
return sema.analyzeDeref(block, src, result_ptr, result_ptr.src);
|
||||
return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
|
||||
}
|
||||
|
||||
fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
@@ -1911,7 +1911,7 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
|
||||
const object = try sema.resolveInst(extra.lhs);
|
||||
const object_ptr = try sema.analyzeRef(block, src, object);
|
||||
const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
|
||||
return sema.analyzeDeref(block, src, result_ptr, result_ptr.src);
|
||||
return sema.analyzeLoad(block, src, result_ptr, result_ptr.src);
|
||||
}
|
||||
|
||||
fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
@@ -1939,7 +1939,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) Inne
|
||||
const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name);
|
||||
const object_ptr = try sema.analyzeRef(block, src, object);
|
||||
const result_ptr = try sema.namedFieldPtr(block, src, object_ptr, field_name, field_name_src);
|
||||
return sema.analyzeDeref(block, src, result_ptr, src);
|
||||
return sema.analyzeLoad(block, src, result_ptr, src);
|
||||
}
|
||||
|
||||
fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
@@ -2060,7 +2060,7 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
|
||||
const array_ptr = try sema.analyzeRef(block, sema.src, array);
|
||||
const elem_index = try sema.resolveInst(bin_inst.rhs);
|
||||
const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);
|
||||
return sema.analyzeDeref(block, sema.src, result_ptr, sema.src);
|
||||
return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);
|
||||
}
|
||||
|
||||
fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
@@ -2075,7 +2075,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
|
||||
const array_ptr = try sema.analyzeRef(block, src, array);
|
||||
const elem_index = try sema.resolveInst(extra.rhs);
|
||||
const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
|
||||
return sema.analyzeDeref(block, src, result_ptr, src);
|
||||
return sema.analyzeLoad(block, src, result_ptr, src);
|
||||
}
|
||||
|
||||
fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
@@ -2183,7 +2183,7 @@ fn zirSwitchBr(
|
||||
|
||||
const target_ptr = try sema.resolveInst(inst.positionals.target);
|
||||
const target = if (ref)
|
||||
try sema.analyzeDeref(parent_block, inst.base.src, target_ptr, inst.positionals.target.src)
|
||||
try sema.analyzeLoad(parent_block, inst.base.src, target_ptr, inst.positionals.target.src)
|
||||
else
|
||||
target_ptr;
|
||||
try sema.validateSwitch(parent_block, target, inst);
|
||||
@@ -2639,7 +2639,7 @@ fn analyzeArithmetic(
|
||||
return block.addBinOp(src, scalar_type, ir_tag, casted_lhs, casted_rhs);
|
||||
}
|
||||
|
||||
fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
fn zirLoad(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@@ -2647,7 +2647,7 @@ fn zirDerefNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErr
|
||||
const src = inst_data.src();
|
||||
const ptr_src: LazySrcLoc = .{ .node_offset_deref_ptr = inst_data.src_node };
|
||||
const ptr = try sema.resolveInst(inst_data.operand);
|
||||
return sema.analyzeDeref(block, src, ptr, ptr_src);
|
||||
return sema.analyzeLoad(block, src, ptr, ptr_src);
|
||||
}
|
||||
|
||||
fn zirAsm(
|
||||
@@ -2958,7 +2958,7 @@ fn zirIsNullPtr(
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const ptr = try sema.resolveInst(inst_data.operand);
|
||||
const loaded = try sema.analyzeDeref(block, src, ptr, src);
|
||||
const loaded = try sema.analyzeLoad(block, src, ptr, src);
|
||||
return sema.analyzeIsNull(block, src, loaded, invert_logic);
|
||||
}
|
||||
|
||||
@@ -2978,7 +2978,7 @@ fn zirIsErrPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerErro
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const ptr = try sema.resolveInst(inst_data.operand);
|
||||
const loaded = try sema.analyzeDeref(block, src, ptr, src);
|
||||
const loaded = try sema.analyzeLoad(block, src, ptr, src);
|
||||
return sema.analyzeIsErr(block, src, loaded);
|
||||
}
|
||||
|
||||
@@ -3343,7 +3343,7 @@ fn namedFieldPtr(
|
||||
},
|
||||
.Type => {
|
||||
_ = try sema.resolveConstValue(block, object_ptr.src, object_ptr);
|
||||
const result = try sema.analyzeDeref(block, src, object_ptr, object_ptr.src);
|
||||
const result = try sema.analyzeLoad(block, src, object_ptr, object_ptr.src);
|
||||
const val = result.value().?;
|
||||
const child_type = try val.toType(sema.arena);
|
||||
switch (child_type.zigTypeTag()) {
|
||||
@@ -3409,7 +3409,7 @@ fn elemPtr(
|
||||
|
||||
if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
|
||||
// we have to deref the ptr operand to get the actual array pointer
|
||||
const array_ptr_deref = try sema.analyzeDeref(block, src, array_ptr, array_ptr.src);
|
||||
const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr.src);
|
||||
if (array_ptr_deref.value()) |array_ptr_val| {
|
||||
if (elem_index.value()) |index_val| {
|
||||
// Both array pointer and index are compile-time known.
|
||||
@@ -3669,7 +3669,7 @@ fn coerceArrayPtrToMany(sema: *Sema, block: *Scope.Block, dest_type: Type, inst:
|
||||
|
||||
fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
|
||||
const decl_ref = try sema.analyzeDeclRef(block, src, decl);
|
||||
return sema.analyzeDeref(block, src, decl_ref, src);
|
||||
return sema.analyzeLoad(block, src, decl_ref, src);
|
||||
}
|
||||
|
||||
fn analyzeDeclRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) InnerError!*Inst {
|
||||
@@ -3737,7 +3737,7 @@ fn analyzeRef(
|
||||
return block.addUnOp(src, ptr_type, .ref, operand);
|
||||
}
|
||||
|
||||
fn analyzeDeref(
|
||||
fn analyzeLoad(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
|
||||
135
src/astgen.zig
135
src/astgen.zig
@@ -443,7 +443,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
|
||||
.deref => {
|
||||
const lhs = try expr(mod, scope, .none, node_datas[node].lhs);
|
||||
const result = try gz.addUnNode(.deref_node, lhs, node);
|
||||
const result = try gz.addUnNode(.load, lhs, node);
|
||||
return rvalue(mod, scope, rl, result, node);
|
||||
},
|
||||
.address_of => {
|
||||
@@ -1042,7 +1042,7 @@ fn blockExprStmts(
|
||||
.coerce_result_ptr,
|
||||
.decl_ref,
|
||||
.decl_val,
|
||||
.deref_node,
|
||||
.load,
|
||||
.div,
|
||||
.elem_ptr,
|
||||
.elem_val,
|
||||
@@ -1396,7 +1396,7 @@ fn assignOp(
|
||||
const gz = scope.getGenZir();
|
||||
|
||||
const lhs_ptr = try lvalExpr(mod, scope, node_datas[infix_node].lhs);
|
||||
const lhs = try gz.addUnNode(.deref_node, lhs_ptr, infix_node);
|
||||
const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
|
||||
const lhs_type = try gz.addUnTok(.typeof, lhs, infix_node);
|
||||
const rhs = try expr(mod, scope, .{ .ty = lhs_type }, node_datas[infix_node].rhs);
|
||||
|
||||
@@ -2105,7 +2105,7 @@ fn whileExpr(
|
||||
try checkLabelRedefinition(mod, scope, label_token);
|
||||
}
|
||||
const parent_gz = scope.getGenZir();
|
||||
const is_inline = while_full.inline_token != null;
|
||||
const is_inline = parent_gz.force_comptime or while_full.inline_token != null;
|
||||
const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;
|
||||
const loop_block = try parent_gz.addBlock(loop_tag, node);
|
||||
try parent_gz.instructions.append(mod.gpa, loop_block);
|
||||
@@ -2149,7 +2149,6 @@ fn whileExpr(
|
||||
// TODO avoid emitting the continue expr when there
|
||||
// are no jumps to it. This happens when the last statement of a while body is noreturn
|
||||
// and there are no `continue` statements.
|
||||
// The "repeat" at the end of a loop body is implied.
|
||||
if (while_full.ast.cont_expr != 0) {
|
||||
_ = try expr(mod, &loop_scope.base, .{ .ty = .void_type }, while_full.ast.cont_expr);
|
||||
}
|
||||
@@ -2236,44 +2235,32 @@ fn forExpr(
|
||||
node: ast.Node.Index,
|
||||
for_full: ast.full.While,
|
||||
) InnerError!zir.Inst.Ref {
|
||||
if (true) @panic("TODO update for zir-memory-layout");
|
||||
if (for_full.label_token) |label_token| {
|
||||
try checkLabelRedefinition(mod, scope, label_token);
|
||||
}
|
||||
|
||||
if (for_full.inline_token) |inline_token| {
|
||||
return mod.failTok(scope, inline_token, "TODO inline for", .{});
|
||||
}
|
||||
|
||||
// Set up variables and constants.
|
||||
const parent_gz = scope.getGenZir();
|
||||
const is_inline = parent_gz.force_comptime or for_full.inline_token != null;
|
||||
const tree = parent_gz.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const for_src = token_starts[for_full.ast.while_token];
|
||||
const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr);
|
||||
const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
|
||||
|
||||
const index_ptr = blk: {
|
||||
const usize_type = try addZIRInstConst(mod, scope, for_src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.usize_type),
|
||||
});
|
||||
const index_ptr = try addZIRUnOp(mod, scope, for_src, .alloc, usize_type);
|
||||
const index_ptr = try parent_gz.addUnNode(.alloc, .usize_type, node);
|
||||
// initialize to zero
|
||||
const zero = try addZIRInstConst(mod, scope, for_src, .{
|
||||
.ty = Type.initTag(.usize),
|
||||
.val = Value.initTag(.zero),
|
||||
});
|
||||
_ = try addZIRBinOp(mod, scope, for_src, .store, index_ptr, zero);
|
||||
_ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
|
||||
break :blk index_ptr;
|
||||
};
|
||||
const array_ptr = try expr(mod, scope, .ref, for_full.ast.cond_expr);
|
||||
const cond_src = token_starts[tree.firstToken(for_full.ast.cond_expr)];
|
||||
const len = try addZIRUnOp(mod, scope, cond_src, .indexable_ptr_len, array_ptr);
|
||||
|
||||
const loop_tag: zir.Inst.Tag = if (is_inline) .block_inline else .loop;
|
||||
const loop_block = try parent_gz.addBlock(loop_tag, node);
|
||||
try parent_gz.instructions.append(mod.gpa, loop_block);
|
||||
|
||||
var loop_scope: Scope.GenZir = .{
|
||||
.parent = scope,
|
||||
.decl = scope.ownerDecl().?,
|
||||
.arena = scope.arena(),
|
||||
.zir_code = parent_gz.zir_code,
|
||||
.force_comptime = parent_gz.force_comptime,
|
||||
.instructions = .{},
|
||||
};
|
||||
@@ -2282,66 +2269,49 @@ fn forExpr(
|
||||
|
||||
var cond_scope: Scope.GenZir = .{
|
||||
.parent = &loop_scope.base,
|
||||
.decl = loop_scope.decl,
|
||||
.arena = loop_scope.arena,
|
||||
.zir_code = parent_gz.zir_code,
|
||||
.force_comptime = loop_scope.force_comptime,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer cond_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
// check condition i < array_expr.len
|
||||
const index = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, index_ptr);
|
||||
const cond = try addZIRBinOp(mod, &cond_scope.base, cond_src, .cmp_lt, index, len);
|
||||
|
||||
const condbr = try addZIRInstSpecial(mod, &cond_scope.base, for_src, zir.Inst.CondBr, .{
|
||||
.condition = cond,
|
||||
.then_body = undefined, // populated below
|
||||
.else_body = undefined, // populated below
|
||||
}, .{});
|
||||
const cond_block = try addZIRInstBlock(mod, &loop_scope.base, for_src, .block, .{
|
||||
.instructions = try loop_scope.arena.dupe(zir.Inst.Ref, cond_scope.instructions.items),
|
||||
const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
|
||||
const cond = try cond_scope.addPlNode(.cmp_lt, for_full.ast.cond_expr, zir.Inst.Bin{
|
||||
.lhs = index,
|
||||
.rhs = len,
|
||||
});
|
||||
|
||||
// increment index variable
|
||||
const one = try addZIRInstConst(mod, &loop_scope.base, for_src, .{
|
||||
.ty = Type.initTag(.usize),
|
||||
.val = Value.initTag(.one),
|
||||
});
|
||||
const index_2 = try addZIRUnOp(mod, &loop_scope.base, cond_src, .deref, index_ptr);
|
||||
const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index_2, one);
|
||||
_ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);
|
||||
const condbr_tag: zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
|
||||
const condbr = try cond_scope.addCondBr(condbr_tag, node);
|
||||
const block_tag: zir.Inst.Tag = if (is_inline) .block_inline else .block;
|
||||
const cond_block = try loop_scope.addBlock(block_tag, node);
|
||||
try loop_scope.instructions.append(mod.gpa, cond_block);
|
||||
try cond_scope.setBlockBody(cond_block);
|
||||
|
||||
const loop = try scope.arena().create(zir.Inst.Loop);
|
||||
loop.* = .{
|
||||
.base = .{
|
||||
.tag = .loop,
|
||||
.src = for_src,
|
||||
},
|
||||
.positionals = .{
|
||||
.body = .{
|
||||
.instructions = try scope.arena().dupe(zir.Inst.Ref, loop_scope.instructions.items),
|
||||
},
|
||||
},
|
||||
.kw_args = .{},
|
||||
};
|
||||
const for_block = try addZIRInstBlock(mod, scope, for_src, .block, .{
|
||||
.instructions = try scope.arena().dupe(zir.Inst.Ref, &[1]zir.Inst.Ref{&loop.base}),
|
||||
// Increment the index variable.
|
||||
const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr);
|
||||
const index_plus_one = try loop_scope.addPlNode(.add, node, zir.Inst.Bin{
|
||||
.lhs = index_2,
|
||||
.rhs = .one_usize,
|
||||
});
|
||||
loop_scope.break_block = for_block;
|
||||
_ = try loop_scope.addBin(.store, index_ptr, index_plus_one);
|
||||
const repeat_tag: zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
|
||||
_ = try loop_scope.addNode(repeat_tag, node);
|
||||
|
||||
try loop_scope.setBlockBody(loop_block);
|
||||
loop_scope.break_block = loop_block;
|
||||
loop_scope.continue_block = cond_block;
|
||||
if (for_full.label_token) |label_token| {
|
||||
loop_scope.label = @as(?Scope.GenZir.Label, Scope.GenZir.Label{
|
||||
.token = label_token,
|
||||
.block_inst = for_block,
|
||||
.block_inst = loop_block,
|
||||
});
|
||||
}
|
||||
|
||||
// while body
|
||||
const then_src = token_starts[tree.lastToken(for_full.ast.then_expr)];
|
||||
var then_scope: Scope.GenZir = .{
|
||||
.parent = &cond_scope.base,
|
||||
.decl = cond_scope.decl,
|
||||
.arena = cond_scope.arena,
|
||||
.zir_code = parent_gz.zir_code,
|
||||
.force_comptime = cond_scope.force_comptime,
|
||||
.instructions = .{},
|
||||
};
|
||||
@@ -2375,6 +2345,7 @@ fn forExpr(
|
||||
.gen_zir = &then_scope,
|
||||
.name = index_name,
|
||||
.ptr = index_ptr,
|
||||
.src = parent_gz.tokSrcLoc(index_token),
|
||||
};
|
||||
break :blk &index_scope.base;
|
||||
};
|
||||
@@ -2382,34 +2353,36 @@ fn forExpr(
|
||||
loop_scope.break_count += 1;
|
||||
const then_result = try expr(mod, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr);
|
||||
|
||||
// else branch
|
||||
var else_scope: Scope.GenZir = .{
|
||||
.parent = &cond_scope.base,
|
||||
.decl = cond_scope.decl,
|
||||
.arena = cond_scope.arena,
|
||||
.zir_code = parent_gz.zir_code,
|
||||
.force_comptime = cond_scope.force_comptime,
|
||||
.instructions = .{},
|
||||
};
|
||||
defer else_scope.instructions.deinit(mod.gpa);
|
||||
|
||||
const else_node = for_full.ast.else_expr;
|
||||
const else_info: struct { src: usize, result: ?*zir.Inst } = if (else_node != 0) blk: {
|
||||
const else_info: struct {
|
||||
src: ast.Node.Index,
|
||||
result: zir.Inst.Ref,
|
||||
} = if (else_node != 0) blk: {
|
||||
loop_scope.break_count += 1;
|
||||
const sub_scope = &else_scope.base;
|
||||
break :blk .{
|
||||
.src = token_starts[tree.lastToken(else_node)],
|
||||
.src = else_node,
|
||||
.result = try expr(mod, sub_scope, loop_scope.break_result_loc, else_node),
|
||||
};
|
||||
} else .{
|
||||
.src = token_starts[tree.lastToken(for_full.ast.then_expr)],
|
||||
.result = null,
|
||||
.src = for_full.ast.then_expr,
|
||||
.result = .none,
|
||||
};
|
||||
|
||||
if (loop_scope.label) |some| {
|
||||
if (!some.used) {
|
||||
return mod.fail(scope, token_starts[some.token], "unused for loop label", .{});
|
||||
return mod.failTok(scope, some.token, "unused for loop label", .{});
|
||||
}
|
||||
}
|
||||
const break_tag: zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
|
||||
return finishThenElseBlock(
|
||||
mod,
|
||||
scope,
|
||||
@@ -2420,13 +2393,13 @@ fn forExpr(
|
||||
&else_scope,
|
||||
condbr,
|
||||
cond,
|
||||
then_src,
|
||||
for_full.ast.then_expr,
|
||||
else_info.src,
|
||||
then_result,
|
||||
else_info.result,
|
||||
for_block,
|
||||
loop_block,
|
||||
cond_block,
|
||||
.@"break",
|
||||
break_tag,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2862,7 +2835,7 @@ fn identifier(
|
||||
const local_ptr = s.cast(Scope.LocalPtr).?;
|
||||
if (mem.eql(u8, local_ptr.name, ident_name)) {
|
||||
if (rl == .ref) return local_ptr.ptr;
|
||||
const loaded = try gz.addUnNode(.deref_node, local_ptr.ptr, ident);
|
||||
const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
|
||||
return rvalue(mod, scope, rl, loaded, ident);
|
||||
}
|
||||
s = local_ptr.parent;
|
||||
|
||||
18
src/zir.zig
18
src/zir.zig
@@ -281,7 +281,7 @@ pub const Inst = struct {
|
||||
decl_val,
|
||||
/// Load the value from a pointer. Assumes `x.*` syntax.
|
||||
/// Uses `un_node` field. AST node is the `x.*` syntax.
|
||||
deref_node,
|
||||
load,
|
||||
/// Arithmetic division. Asserts no integer overflow.
|
||||
/// Uses the `pl_node` union field. Payload is `Bin`.
|
||||
div,
|
||||
@@ -661,7 +661,7 @@ pub const Inst = struct {
|
||||
.dbg_stmt_node,
|
||||
.decl_ref,
|
||||
.decl_val,
|
||||
.deref_node,
|
||||
.load,
|
||||
.div,
|
||||
.elem_ptr,
|
||||
.elem_val,
|
||||
@@ -841,6 +841,10 @@ pub const Inst = struct {
|
||||
bool_true,
|
||||
/// `false`
|
||||
bool_false,
|
||||
/// `0` (usize)
|
||||
zero_usize,
|
||||
/// `1` (usize)
|
||||
one_usize,
|
||||
|
||||
_,
|
||||
|
||||
@@ -1016,10 +1020,18 @@ pub const Inst = struct {
|
||||
.ty = Type.initTag(.comptime_int),
|
||||
.val = Value.initTag(.zero),
|
||||
},
|
||||
.zero_usize = .{
|
||||
.ty = Type.initTag(.usize),
|
||||
.val = Value.initTag(.zero),
|
||||
},
|
||||
.one = .{
|
||||
.ty = Type.initTag(.comptime_int),
|
||||
.val = Value.initTag(.one),
|
||||
},
|
||||
.one_usize = .{
|
||||
.ty = Type.initTag(.usize),
|
||||
.val = Value.initTag(.one),
|
||||
},
|
||||
.void_value = .{
|
||||
.ty = Type.initTag(.void),
|
||||
.val = Value.initTag(.void_value),
|
||||
@@ -1377,7 +1389,7 @@ const Writer = struct {
|
||||
.call_none,
|
||||
.call_none_chkused,
|
||||
.compile_error,
|
||||
.deref_node,
|
||||
.load,
|
||||
.ensure_result_used,
|
||||
.ensure_result_non_error,
|
||||
.import,
|
||||
|
||||
@@ -968,37 +968,37 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
);
|
||||
|
||||
// Basic for loop
|
||||
//case.addCompareOutput(
|
||||
// \\export fn _start() noreturn {
|
||||
// \\ for ("hello") |_| print();
|
||||
// \\
|
||||
// \\ exit();
|
||||
// \\}
|
||||
// \\
|
||||
// \\fn print() void {
|
||||
// \\ asm volatile ("syscall"
|
||||
// \\ :
|
||||
// \\ : [number] "{rax}" (1),
|
||||
// \\ [arg1] "{rdi}" (1),
|
||||
// \\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
|
||||
// \\ [arg3] "{rdx}" (6)
|
||||
// \\ : "rcx", "r11", "memory"
|
||||
// \\ );
|
||||
// \\ return;
|
||||
// \\}
|
||||
// \\
|
||||
// \\fn exit() noreturn {
|
||||
// \\ asm volatile ("syscall"
|
||||
// \\ :
|
||||
// \\ : [number] "{rax}" (231),
|
||||
// \\ [arg1] "{rdi}" (0)
|
||||
// \\ : "rcx", "r11", "memory"
|
||||
// \\ );
|
||||
// \\ unreachable;
|
||||
// \\}
|
||||
//,
|
||||
// "hello\nhello\nhello\nhello\nhello\n",
|
||||
//);
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ for ("hello") |_| print();
|
||||
\\
|
||||
\\ exit();
|
||||
\\}
|
||||
\\
|
||||
\\fn print() void {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (1),
|
||||
\\ [arg1] "{rdi}" (1),
|
||||
\\ [arg2] "{rsi}" (@ptrToInt("hello\n")),
|
||||
\\ [arg3] "{rdx}" (6)
|
||||
\\ : "rcx", "r11", "memory"
|
||||
\\ );
|
||||
\\ return;
|
||||
\\}
|
||||
\\
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (231),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ : "rcx", "r11", "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
,
|
||||
"hello\nhello\nhello\nhello\nhello\n",
|
||||
);
|
||||
}
|
||||
|
||||
//{
|
||||
|
||||
Reference in New Issue
Block a user