stage2: fix @compileLog.

This commit is contained in:
Andrew Kelley 2021-03-25 20:11:23 -07:00
parent 4fd3a2e8e8
commit 4bfcd105ef
4 changed files with 98 additions and 52 deletions

View File

@ -283,6 +283,10 @@ pub fn analyzeBody(
try sema.zirStore(block, inst);
continue;
},
.store_node => {
try sema.zirStoreNode(block, inst);
continue;
},
.store_to_block_ptr => {
try sema.zirStoreToBlockPtr(block, inst);
continue;
@ -712,7 +716,19 @@ fn zirStore(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!v
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
const ptr = try sema.resolveInst(bin_inst.lhs);
const value = try sema.resolveInst(bin_inst.rhs);
return sema.storePtr(block, .unneeded, ptr, value);
return sema.storePtr(block, sema.src, ptr, value);
}
fn zirStoreNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
const tracy = trace(@src());
defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
const ptr = try sema.resolveInst(extra.lhs);
const value = try sema.resolveInst(extra.rhs);
return sema.storePtr(block, src, ptr, value);
}
fn zirParamType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
@ -3630,7 +3646,7 @@ fn storePtr(
return sema.mod.fail(&block.base, src, "cannot assign to constant", .{});
const elem_ty = ptr.ty.elemType();
const value = try sema.coerce(block, elem_ty, uncasted_value, uncasted_value.src);
const value = try sema.coerce(block, elem_ty, uncasted_value, src);
if (elem_ty.onePossibleValue() != null)
return;

View File

@ -1130,6 +1130,7 @@ fn blockExprStmts(
.@"unreachable",
.elided,
.store,
.store_node,
.store_to_block_ptr,
.store_to_inferred_ptr,
.resolve_inferred_alloc,
@ -3198,7 +3199,9 @@ fn typeOf(
items[param_i] = try expr(mod, scope, .none, param);
}
const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{ .operands_len = @intCast(u32, params.len) });
const result = try gz.addPlNode(.typeof_peer, node, zir.Inst.MultiOp{
.operands_len = @intCast(u32, params.len),
});
try gz.zir_code.appendRefs(items);
return rvalue(mod, scope, rl, result, node);
@ -3279,12 +3282,15 @@ fn builtinCall(
return rvalue(mod, scope, rl, result, node);
},
.compile_log => {
if (true) @panic("TODO update for zir-memory-layout");
const arena = scope.arena();
var targets = try arena.alloc(zir.Inst.Ref, params.len);
for (params) |param, param_i|
targets[param_i] = try expr(mod, scope, .none, param);
const result = try addZIRInst(mod, scope, src, zir.Inst.CompileLog, .{ .to_log = targets }, .{});
const arg_refs = try mod.gpa.alloc(zir.Inst.Ref, params.len);
defer mod.gpa.free(arg_refs);
for (params) |param, i| arg_refs[i] = try expr(mod, scope, .none, param);
const result = try gz.addPlNode(.compile_log, node, zir.Inst.MultiOp{
.operands_len = @intCast(u32, params.len),
});
try gz.zir_code.appendRefs(arg_refs);
return rvalue(mod, scope, rl, result, node);
},
.field => {
@ -3742,7 +3748,10 @@ fn rvalue(
.operand = result,
}),
.ptr => |ptr_inst| {
_ = try gz.addBin(.store, ptr_inst, result);
_ = try gz.addPlNode(.store_node, src_node, zir.Inst.Bin{
.lhs = ptr_inst,
.rhs = result,
});
return result;
},
.bitcasted_ptr => |bitcasted_ptr| {

View File

@ -276,7 +276,7 @@ pub const Inst = struct {
/// Represents a pointer to a global decl.
/// Uses the `decl` union field.
decl_ref,
/// Equivalent to a decl_ref followed by deref.
/// Equivalent to a decl_ref followed by load.
/// Uses the `decl` union field.
decl_val,
/// Load the value from a pointer. Assumes `x.*` syntax.
@ -470,9 +470,13 @@ pub const Inst = struct {
/// Slice operation `array_ptr[start..end:sentinel]`.
/// Uses the `pl_node` field. AST node is the slice syntax. Payload is `SliceSentinel`.
slice_sentinel,
/// Write a value to a pointer. For loading, see `deref`.
/// Write a value to a pointer. For loading, see `load`.
/// Source location is assumed to be same as previous instruction.
/// Uses the `bin` union field.
store,
/// Same as `store` except provides a source location.
/// Uses the `pl_node` union field. Payload is `Bin`.
store_node,
/// Same as `store` but the type of the value being stored will be used to infer
/// the block type. The LHS is the pointer to store to.
/// Uses the `bin` union field.
@ -698,6 +702,7 @@ pub const Inst = struct {
.shl,
.shr,
.store,
.store_node,
.store_to_block_ptr,
.store_to_inferred_ptr,
.str,
@ -1444,7 +1449,6 @@ const Writer = struct {
.@"asm",
.asm_volatile,
.compile_log,
.elem_ptr_node,
.elem_val_node,
.field_ptr,
@ -1455,7 +1459,6 @@ const Writer = struct {
.slice_start,
.slice_end,
.slice_sentinel,
.typeof_peer,
=> try self.writePlNode(stream, inst),
.add,
@ -1479,6 +1482,7 @@ const Writer = struct {
.shl,
.shr,
.xor,
.store_node,
=> try self.writePlNodeBin(stream, inst),
.call,
@ -1495,6 +1499,10 @@ const Writer = struct {
.condbr_inline,
=> try self.writePlNodeCondBr(stream, inst),
.compile_log,
.typeof_peer,
=> try self.writePlNodeMultiOp(stream, inst),
.as_node => try self.writeAs(stream, inst),
.breakpoint,
@ -1694,6 +1702,19 @@ const Writer = struct {
try self.writeSrc(stream, inst_data.src());
}
fn writePlNodeMultiOp(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.MultiOp, inst_data.payload_index);
const operands = self.code.refSlice(extra.end, extra.data.operands_len);
for (operands) |operand, i| {
if (i != 0) try stream.writeAll(", ");
try self.writeInstRef(stream, operand);
}
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;

View File

@ -1072,45 +1072,45 @@ pub fn addCases(ctx: *TestContext) !void {
, &[_][]const u8{":3:9: error: redefinition of 'testing'"});
}
//{
// // TODO make the test harness support checking the compile log output too
// var case = ctx.obj("@compileLog", linux_x64);
// // The other compile error prevents emission of a "found compile log" statement.
// case.addError(
// \\export fn _start() noreturn {
// \\ const b = true;
// \\ var f: u32 = 1;
// \\ @compileLog(b, 20, f, x);
// \\ @compileLog(1000);
// \\ var bruh: usize = true;
// \\ unreachable;
// \\}
// \\export fn other() void {
// \\ @compileLog(1234);
// \\}
// \\fn x() void {}
// , &[_][]const u8{
// ":6:23: error: expected usize, found bool",
// });
{
// TODO make the test harness support checking the compile log output too
var case = ctx.obj("@compileLog", linux_x64);
// The other compile error prevents emission of a "found compile log" statement.
case.addError(
\\export fn _start() noreturn {
\\ const b = true;
\\ var f: u32 = 1;
\\ @compileLog(b, 20, f, x);
\\ @compileLog(1000);
\\ var bruh: usize = true;
\\ unreachable;
\\}
\\export fn other() void {
\\ @compileLog(1234);
\\}
\\fn x() void {}
, &[_][]const u8{
":6:23: error: expected usize, found bool",
});
// // Now only compile log statements remain. One per Decl.
// case.addError(
// \\export fn _start() noreturn {
// \\ const b = true;
// \\ var f: u32 = 1;
// \\ @compileLog(b, 20, f, x);
// \\ @compileLog(1000);
// \\ unreachable;
// \\}
// \\export fn other() void {
// \\ @compileLog(1234);
// \\}
// \\fn x() void {}
// , &[_][]const u8{
// ":11:8: error: found compile log statement",
// ":4:5: note: also here",
// });
//}
// Now only compile log statements remain. One per Decl.
case.addError(
\\export fn _start() noreturn {
\\ const b = true;
\\ var f: u32 = 1;
\\ @compileLog(b, 20, f, x);
\\ @compileLog(1000);
\\ unreachable;
\\}
\\export fn other() void {
\\ @compileLog(1234);
\\}
\\fn x() void {}
, &[_][]const u8{
":9:5: error: found compile log statement",
":4:5: note: also here",
});
}
//{
// var case = ctx.obj("extern variable has no type", linux_x64);