stage2: finish source location reworkings in the branch

* remove the LazySrcLoc.todo tag
 * finish updating Sema and AstGen, remove the last of the
   `@panic("TODO")`.
This commit is contained in:
Andrew Kelley 2021-03-31 21:36:32 -07:00
parent e8143f6cbe
commit b27d052676
7 changed files with 158 additions and 159 deletions

View File

@ -1,9 +1,6 @@
this is my WIP branch scratch pad, to be deleted before merging into master this is my WIP branch scratch pad, to be deleted before merging into master
Merge TODO list: Merge TODO list:
* remove the LazySrcLoc.todo tag
* update astgen.zig
* finish updating Sema.zig
* finish implementing SrcLoc byteOffset function * finish implementing SrcLoc byteOffset function
* audit all the .unneeded src locations * audit all the .unneeded src locations
* audit the calls in codegen toSrcLocWithDecl specifically if there is inlined function * audit the calls in codegen toSrcLocWithDecl specifically if there is inlined function

View File

@ -1252,6 +1252,7 @@ pub const Tree = struct {
buffer[0] = data.lhs; buffer[0] = data.lhs;
const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1]; const params = if (data.lhs == 0) buffer[0..0] else buffer[0..1];
return tree.fullFnProto(.{ return tree.fullFnProto(.{
.proto_node = node,
.fn_token = tree.nodes.items(.main_token)[node], .fn_token = tree.nodes.items(.main_token)[node],
.return_type = data.rhs, .return_type = data.rhs,
.params = params, .params = params,
@ -1267,6 +1268,7 @@ pub const Tree = struct {
const params_range = tree.extraData(data.lhs, Node.SubRange); const params_range = tree.extraData(data.lhs, Node.SubRange);
const params = tree.extra_data[params_range.start..params_range.end]; const params = tree.extra_data[params_range.start..params_range.end];
return tree.fullFnProto(.{ return tree.fullFnProto(.{
.proto_node = node,
.fn_token = tree.nodes.items(.main_token)[node], .fn_token = tree.nodes.items(.main_token)[node],
.return_type = data.rhs, .return_type = data.rhs,
.params = params, .params = params,
@ -1283,6 +1285,7 @@ pub const Tree = struct {
buffer[0] = extra.param; buffer[0] = extra.param;
const params = if (extra.param == 0) buffer[0..0] else buffer[0..1]; const params = if (extra.param == 0) buffer[0..0] else buffer[0..1];
return tree.fullFnProto(.{ return tree.fullFnProto(.{
.proto_node = node,
.fn_token = tree.nodes.items(.main_token)[node], .fn_token = tree.nodes.items(.main_token)[node],
.return_type = data.rhs, .return_type = data.rhs,
.params = params, .params = params,
@ -1298,6 +1301,7 @@ pub const Tree = struct {
const extra = tree.extraData(data.lhs, Node.FnProto); const extra = tree.extraData(data.lhs, Node.FnProto);
const params = tree.extra_data[extra.params_start..extra.params_end]; const params = tree.extra_data[extra.params_start..extra.params_end];
return tree.fullFnProto(.{ return tree.fullFnProto(.{
.proto_node = node,
.fn_token = tree.nodes.items(.main_token)[node], .fn_token = tree.nodes.items(.main_token)[node],
.return_type = data.rhs, .return_type = data.rhs,
.params = params, .params = params,
@ -2120,6 +2124,7 @@ pub const full = struct {
ast: Ast, ast: Ast,
pub const Ast = struct { pub const Ast = struct {
proto_node: Node.Index,
fn_token: TokenIndex, fn_token: TokenIndex,
return_type: Node.Index, return_type: Node.Index,
params: []const Node.Index, params: []const Node.Index,

View File

@ -133,10 +133,6 @@ pub const ResultLoc = union(enum) {
/// The result instruction from the expression must be ignored. /// The result instruction from the expression must be ignored.
/// Always an instruction with tag `alloc_inferred`. /// Always an instruction with tag `alloc_inferred`.
inferred_ptr: zir.Inst.Ref, inferred_ptr: zir.Inst.Ref,
/// The expression must store its result into this pointer, which is a typed pointer that
/// has been bitcasted to whatever the expression's type is.
/// The result instruction from the expression must be ignored.
bitcasted_ptr: zir.Inst.Ref,
/// There is a pointer for the expression to store its result into, however, its type /// There is a pointer for the expression to store its result into, however, its type
/// is inferred based on peer type resolution for a `zir.Inst.Block`. /// is inferred based on peer type resolution for a `zir.Inst.Block`.
/// The result instruction from the expression must be ignored. /// The result instruction from the expression must be ignored.
@ -172,7 +168,7 @@ pub const ResultLoc = union(enum) {
.tag = .break_void, .tag = .break_void,
.elide_store_to_block_ptr_instructions = false, .elide_store_to_block_ptr_instructions = false,
}, },
.inferred_ptr, .bitcasted_ptr, .block_ptr => { .inferred_ptr, .block_ptr => {
if (block_scope.rvalue_rl_count == block_scope.break_count) { if (block_scope.rvalue_rl_count == block_scope.break_count) {
// Neither prong of the if consumed the result location, so we can // Neither prong of the if consumed the result location, so we can
// use break instructions to create an rvalue. // use break instructions to create an rvalue.
@ -388,7 +384,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!zir.Ins
} }
/// Turn Zig AST into untyped ZIR istructions. /// Turn Zig AST into untyped ZIR istructions.
/// When `rl` is discard, ptr, inferred_ptr, bitcasted_ptr, or inferred_ptr, the /// When `rl` is discard, ptr, inferred_ptr, or inferred_ptr, the
/// result instruction can be used to inspect whether it is isNoReturn() but that is it, /// result instruction can be used to inspect whether it is isNoReturn() but that is it,
/// it must otherwise not be used. /// it must otherwise not be used.
pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref { pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerError!zir.Inst.Ref {
@ -1155,7 +1151,6 @@ fn blockExprStmts(
.asm_volatile, .asm_volatile,
.bit_and, .bit_and,
.bitcast, .bitcast,
.bitcast_ref,
.bitcast_result_ptr, .bitcast_result_ptr,
.bit_or, .bit_or,
.block, .block,
@ -1804,7 +1799,7 @@ fn orelseCatchExpr(
// TODO handle catch // TODO handle catch
const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
.ref => .ref, .ref => .ref,
.discard, .none, .block_ptr, .inferred_ptr, .bitcasted_ptr => .none, .discard, .none, .block_ptr, .inferred_ptr => .none,
.ty => |elem_ty| blk: { .ty => |elem_ty| blk: {
const wrapped_ty = try block_scope.addUnNode(.optional_type, elem_ty, node); const wrapped_ty = try block_scope.addUnNode(.optional_type, elem_ty, node);
break :blk .{ .ty = wrapped_ty }; break :blk .{ .ty = wrapped_ty };
@ -3519,7 +3514,6 @@ fn as(
gz: *GenZir, gz: *GenZir,
scope: *Scope, scope: *Scope,
rl: ResultLoc, rl: ResultLoc,
builtin_token: ast.TokenIndex,
node: ast.Node.Index, node: ast.Node.Index,
lhs: ast.Node.Index, lhs: ast.Node.Index,
rhs: ast.Node.Index, rhs: ast.Node.Index,
@ -3538,13 +3532,9 @@ fn as(
return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type); return asRlPtr(gz, scope, rl, block_scope.rl_ptr, rhs, dest_type);
}, },
.bitcasted_ptr => |bitcasted_ptr| {
// TODO here we should be able to resolve the inference; we now have a type for the result.
return gz.astgen.mod.failTok(scope, builtin_token, "TODO implement @as with result location @bitCast", .{});
},
.inferred_ptr => |result_alloc| { .inferred_ptr => |result_alloc| {
// TODO here we should be able to resolve the inference; we now have a type for the result. // TODO here we should be able to resolve the inference; we now have a type for the result.
return gz.astgen.mod.failTok(scope, builtin_token, "TODO implement @as with inferred-type result location pointer", .{}); return gz.astgen.mod.failNode(scope, node, "TODO implement @as with inferred-type result location pointer", .{});
}, },
} }
} }
@ -3599,47 +3589,32 @@ fn bitCast(
gz: *GenZir, gz: *GenZir,
scope: *Scope, scope: *Scope,
rl: ResultLoc, rl: ResultLoc,
builtin_token: ast.TokenIndex,
node: ast.Node.Index, node: ast.Node.Index,
lhs: ast.Node.Index, lhs: ast.Node.Index,
rhs: ast.Node.Index, rhs: ast.Node.Index,
) InnerError!zir.Inst.Ref { ) InnerError!zir.Inst.Ref {
if (true) @panic("TODO update for zir-memory-layout"); const mod = gz.astgen.mod;
const dest_type = try typeExpr(gz, scope, lhs); const dest_type = try typeExpr(gz, scope, lhs);
switch (rl) { switch (rl) {
.none => { .none, .discard, .ty => {
const operand = try expr(gz, scope, .none, rhs); const operand = try expr(gz, scope, .none, rhs);
return addZIRBinOp(mod, scope, src, .bitcast, dest_type, operand); const result = try gz.addPlNode(.bitcast, node, zir.Inst.Bin{
}, .lhs = dest_type,
.discard => { .rhs = operand,
const operand = try expr(gz, scope, .none, rhs); });
const result = try addZIRBinOp(mod, scope, src, .bitcast, dest_type, operand); return rvalue(gz, scope, rl, result, node);
_ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
return result;
},
.ref => {
const operand = try expr(gz, scope, .ref, rhs);
const result = try addZIRBinOp(mod, scope, src, .bitcast_ref, dest_type, operand);
return result;
},
.ty => |result_ty| {
const result = try expr(gz, scope, .none, rhs);
const bitcasted = try addZIRBinOp(mod, scope, src, .bitcast, dest_type, result);
return addZIRBinOp(mod, scope, src, .as, result_ty, bitcasted);
}, },
.ref => unreachable, // `@bitCast` is not allowed as an r-value.
.ptr => |result_ptr| { .ptr => |result_ptr| {
const casted_result_ptr = try addZIRUnOp(mod, scope, src, .bitcast_result_ptr, result_ptr); const casted_result_ptr = try gz.addUnNode(.bitcast_result_ptr, result_ptr, node);
return expr(gz, scope, .{ .bitcasted_ptr = casted_result_ptr.castTag(.bitcast_result_ptr).? }, rhs); return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);
},
.bitcasted_ptr => |bitcasted_ptr| {
return mod.failTok(scope, builtin_token, "TODO implement @bitCast with result location another @bitCast", .{});
}, },
.block_ptr => |block_ptr| { .block_ptr => |block_ptr| {
return mod.failTok(scope, builtin_token, "TODO implement @bitCast with result location inferred peer types", .{}); return mod.failNode(scope, node, "TODO implement @bitCast with result location inferred peer types", .{});
}, },
.inferred_ptr => |result_alloc| { .inferred_ptr => |result_alloc| {
// TODO here we should be able to resolve the inference; we now have a type for the result. // TODO here we should be able to resolve the inference; we now have a type for the result.
return mod.failTok(scope, builtin_token, "TODO implement @bitCast with inferred-type result location pointer", .{}); return mod.failNode(scope, node, "TODO implement @bitCast with inferred-type result location pointer", .{});
}, },
} }
} }
@ -3648,12 +3623,11 @@ fn typeOf(
gz: *GenZir, gz: *GenZir,
scope: *Scope, scope: *Scope,
rl: ResultLoc, rl: ResultLoc,
builtin_token: ast.TokenIndex,
node: ast.Node.Index, node: ast.Node.Index,
params: []const ast.Node.Index, params: []const ast.Node.Index,
) InnerError!zir.Inst.Ref { ) InnerError!zir.Inst.Ref {
if (params.len < 1) { if (params.len < 1) {
return gz.astgen.mod.failTok(scope, builtin_token, "expected at least 1 argument, found 0", .{}); return gz.astgen.mod.failNode(scope, node, "expected at least 1 argument, found 0", .{});
} }
if (params.len == 1) { if (params.len == 1) {
const result = try gz.addUnNode(.typeof, try expr(gz, scope, .none, params[0]), node); const result = try gz.addUnNode(.typeof, try expr(gz, scope, .none, params[0]), node);
@ -3693,14 +3667,14 @@ fn builtinCall(
// Also, some builtins have a variable number of parameters. // Also, some builtins have a variable number of parameters.
const info = BuiltinFn.list.get(builtin_name) orelse { const info = BuiltinFn.list.get(builtin_name) orelse {
return mod.failTok(scope, builtin_token, "invalid builtin function: '{s}'", .{ return mod.failNode(scope, node, "invalid builtin function: '{s}'", .{
builtin_name, builtin_name,
}); });
}; };
if (info.param_count) |expected| { if (info.param_count) |expected| {
if (expected != params.len) { if (expected != params.len) {
const s = if (expected == 1) "" else "s"; const s = if (expected == 1) "" else "s";
return mod.failTok(scope, builtin_token, "expected {d} parameter{s}, found {d}", .{ return mod.failNode(scope, node, "expected {d} parameter{s}, found {d}", .{
expected, s, params.len, expected, s, params.len,
}); });
} }
@ -3788,9 +3762,9 @@ fn builtinCall(
}); });
return rvalue(gz, scope, rl, result, node); return rvalue(gz, scope, rl, result, node);
}, },
.as => return as(gz, scope, rl, builtin_token, node, params[0], params[1]), .as => return as(gz, scope, rl, node, params[0], params[1]),
.bit_cast => return bitCast(gz, scope, rl, builtin_token, node, params[0], params[1]), .bit_cast => return bitCast(gz, scope, rl, node, params[0], params[1]),
.TypeOf => return typeOf(gz, scope, rl, builtin_token, node, params), .TypeOf => return typeOf(gz, scope, rl, node, params),
.add_with_overflow, .add_with_overflow,
.align_cast, .align_cast,
@ -3875,7 +3849,7 @@ fn builtinCall(
.type_info, .type_info,
.type_name, .type_name,
.union_init, .union_init,
=> return mod.failTok(scope, builtin_token, "TODO: implement builtin function {s}", .{ => return mod.failNode(scope, node, "TODO: implement builtin function {s}", .{
builtin_name, builtin_name,
}), }),
@ -3884,7 +3858,7 @@ fn builtinCall(
.Frame, .Frame,
.frame_address, .frame_address,
.frame_size, .frame_size,
=> return mod.failTok(scope, builtin_token, "async and related features are not yet supported", .{}), => return mod.failNode(scope, node, "async and related features are not yet supported", .{}),
} }
} }
@ -4286,9 +4260,6 @@ fn rvalue(
}); });
return result; return result;
}, },
.bitcasted_ptr => |bitcasted_ptr| {
return gz.astgen.mod.failNode(scope, src_node, "TODO implement rvalue .bitcasted_ptr", .{});
},
.inferred_ptr => |alloc| { .inferred_ptr => |alloc| {
_ = try gz.addBin(.store_to_inferred_ptr, alloc, result); _ = try gz.addBin(.store_to_inferred_ptr, alloc, result);
return result; return result;

View File

@ -1016,11 +1016,6 @@ pub const Scope = struct {
gz.break_result_loc = .{ .block_ptr = gz }; gz.break_result_loc = .{ .block_ptr = gz };
}, },
.bitcasted_ptr => |ptr| {
gz.rl_ptr = ptr;
gz.break_result_loc = .{ .block_ptr = gz };
},
.block_ptr => |parent_block_scope| { .block_ptr => |parent_block_scope| {
gz.rl_ty_inst = parent_block_scope.rl_ty_inst; gz.rl_ty_inst = parent_block_scope.rl_ty_inst;
gz.rl_ptr = parent_block_scope.rl_ptr; gz.rl_ptr = parent_block_scope.rl_ptr;
@ -1052,10 +1047,12 @@ pub const Scope = struct {
} }
pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct { pub fn addFnTypeCc(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
src_node: ast.Node.Index,
param_types: []const zir.Inst.Ref, param_types: []const zir.Inst.Ref,
ret_ty: zir.Inst.Ref, ret_ty: zir.Inst.Ref,
cc: zir.Inst.Ref, cc: zir.Inst.Ref,
}) !zir.Inst.Ref { }) !zir.Inst.Ref {
assert(args.src_node != 0);
assert(args.ret_ty != .none); assert(args.ret_ty != .none);
assert(args.cc != .none); assert(args.cc != .none);
const gpa = gz.astgen.mod.gpa; const gpa = gz.astgen.mod.gpa;
@ -1065,6 +1062,7 @@ pub const Scope = struct {
@typeInfo(zir.Inst.FnTypeCc).Struct.fields.len + args.param_types.len); @typeInfo(zir.Inst.FnTypeCc).Struct.fields.len + args.param_types.len);
const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnTypeCc{ const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnTypeCc{
.return_type = args.ret_ty,
.cc = args.cc, .cc = args.cc,
.param_types_len = @intCast(u32, args.param_types.len), .param_types_len = @intCast(u32, args.param_types.len),
}); });
@ -1073,8 +1071,8 @@ pub const Scope = struct {
const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len); const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
gz.astgen.instructions.appendAssumeCapacity(.{ gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag, .tag = tag,
.data = .{ .fn_type = .{ .data = .{ .pl_node = .{
.return_type = args.ret_ty, .src_node = gz.astgen.decl.nodeIndexToRelative(args.src_node),
.payload_index = payload_index, .payload_index = payload_index,
} }, } },
}); });
@ -1082,29 +1080,30 @@ pub const Scope = struct {
return gz.astgen.indexToRef(new_index); return gz.astgen.indexToRef(new_index);
} }
pub fn addFnType( pub fn addFnType(gz: *GenZir, tag: zir.Inst.Tag, args: struct {
gz: *GenZir, src_node: ast.Node.Index,
tag: zir.Inst.Tag,
ret_ty: zir.Inst.Ref, ret_ty: zir.Inst.Ref,
param_types: []const zir.Inst.Ref, param_types: []const zir.Inst.Ref,
) !zir.Inst.Ref { }) !zir.Inst.Ref {
assert(ret_ty != .none); assert(args.src_node != 0);
assert(args.ret_ty != .none);
const gpa = gz.astgen.mod.gpa; const gpa = gz.astgen.mod.gpa;
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1); try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1); try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len + try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
@typeInfo(zir.Inst.FnType).Struct.fields.len + param_types.len); @typeInfo(zir.Inst.FnType).Struct.fields.len + args.param_types.len);
const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnType{ const payload_index = gz.astgen.addExtraAssumeCapacity(zir.Inst.FnType{
.param_types_len = @intCast(u32, param_types.len), .return_type = args.ret_ty,
.param_types_len = @intCast(u32, args.param_types.len),
}); });
gz.astgen.appendRefsAssumeCapacity(param_types); gz.astgen.appendRefsAssumeCapacity(args.param_types);
const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len); const new_index = @intCast(zir.Inst.Index, gz.astgen.instructions.len);
gz.astgen.instructions.appendAssumeCapacity(.{ gz.astgen.instructions.appendAssumeCapacity(.{
.tag = tag, .tag = tag,
.data = .{ .fn_type = .{ .data = .{ .pl_node = .{
.return_type = ret_ty, .src_node = gz.astgen.decl.nodeIndexToRelative(args.src_node),
.payload_index = payload_index, .payload_index = payload_index,
} }, } },
}); });
@ -1513,7 +1512,6 @@ pub const SrcLoc = struct {
pub fn fileScope(src_loc: SrcLoc) *Scope.File { pub fn fileScope(src_loc: SrcLoc) *Scope.File {
return switch (src_loc.lazy) { return switch (src_loc.lazy) {
.unneeded => unreachable, .unneeded => unreachable,
.todo => unreachable,
.byte_abs, .byte_abs,
.token_abs, .token_abs,
@ -1542,6 +1540,8 @@ pub const SrcLoc = struct {
.node_offset_switch_operand, .node_offset_switch_operand,
.node_offset_switch_special_prong, .node_offset_switch_special_prong,
.node_offset_switch_range, .node_offset_switch_range,
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
=> src_loc.container.decl.container.file_scope, => src_loc.container.decl.container.file_scope,
}; };
} }
@ -1549,7 +1549,6 @@ pub const SrcLoc = struct {
pub fn byteOffset(src_loc: SrcLoc) !u32 { pub fn byteOffset(src_loc: SrcLoc) !u32 {
switch (src_loc.lazy) { switch (src_loc.lazy) {
.unneeded => unreachable, .unneeded => unreachable,
.todo => unreachable,
.byte_abs => |byte_index| return byte_index, .byte_abs => |byte_index| return byte_index,
@ -1676,6 +1675,8 @@ pub const SrcLoc = struct {
.node_offset_switch_operand => @panic("TODO"), .node_offset_switch_operand => @panic("TODO"),
.node_offset_switch_special_prong => @panic("TODO"), .node_offset_switch_special_prong => @panic("TODO"),
.node_offset_switch_range => @panic("TODO"), .node_offset_switch_range => @panic("TODO"),
.node_offset_fn_type_cc => @panic("TODO"),
.node_offset_fn_type_ret_ty => @panic("TODO"),
} }
} }
}; };
@ -1695,11 +1696,6 @@ pub const LazySrcLoc = union(enum) {
/// look into using reverse-continue with a memory watchpoint to see where the /// look into using reverse-continue with a memory watchpoint to see where the
/// value is being set to this tag. /// value is being set to this tag.
unneeded, unneeded,
/// Same as `unneeded`, except the code setting up this tag knew that actually
/// the source location was needed, and I wanted to get other stuff compiling
/// and working before coming back to messing with source locations.
/// TODO delete this tag before merging the zir-memory-layout branch.
todo,
/// The source location points to a byte offset within a source file, /// The source location points to a byte offset within a source file,
/// offset from 0. The source file is determined contextually. /// offset from 0. The source file is determined contextually.
/// Inside a `SrcLoc`, the `file_scope` union field will be active. /// Inside a `SrcLoc`, the `file_scope` union field will be active.
@ -1824,12 +1820,23 @@ pub const LazySrcLoc = union(enum) {
/// range nodes. The error applies to all of them. /// range nodes. The error applies to all of them.
/// The Decl is determined contextually. /// The Decl is determined contextually.
node_offset_switch_range: i32, node_offset_switch_range: i32,
/// The source location points to the calling convention of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, nagivate to
/// the calling convention node.
/// The Decl is determined contextually.
node_offset_fn_type_cc: i32,
/// The source location points to the return type of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, nagivate to
/// the return type node.
/// The Decl is determined contextually.
node_offset_fn_type_ret_ty: i32,
/// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope. /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc { pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
return switch (lazy) { return switch (lazy) {
.unneeded, .unneeded,
.todo,
.byte_abs, .byte_abs,
.token_abs, .token_abs,
.node_abs, .node_abs,
@ -1860,6 +1867,8 @@ pub const LazySrcLoc = union(enum) {
.node_offset_switch_operand, .node_offset_switch_operand,
.node_offset_switch_special_prong, .node_offset_switch_special_prong,
.node_offset_switch_range, .node_offset_switch_range,
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
=> .{ => .{
.container = .{ .decl = scope.srcDecl().? }, .container = .{ .decl = scope.srcDecl().? },
.lazy = lazy, .lazy = lazy,
@ -1871,7 +1880,6 @@ pub const LazySrcLoc = union(enum) {
pub fn toSrcLocWithDecl(lazy: LazySrcLoc, decl: *Decl) SrcLoc { pub fn toSrcLocWithDecl(lazy: LazySrcLoc, decl: *Decl) SrcLoc {
return switch (lazy) { return switch (lazy) {
.unneeded, .unneeded,
.todo,
.byte_abs, .byte_abs,
.token_abs, .token_abs,
.node_abs, .node_abs,
@ -1902,6 +1910,8 @@ pub const LazySrcLoc = union(enum) {
.node_offset_switch_operand, .node_offset_switch_operand,
.node_offset_switch_special_prong, .node_offset_switch_special_prong,
.node_offset_switch_range, .node_offset_switch_range,
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
=> .{ => .{
.container = .{ .decl = decl }, .container = .{ .decl = decl },
.lazy = lazy, .lazy = lazy,
@ -2340,13 +2350,18 @@ fn astgenAndSemaFn(
const fn_type_inst: zir.Inst.Ref = if (cc != .none) fn_type: { const fn_type_inst: zir.Inst.Ref = if (cc != .none) fn_type: {
const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc; const tag: zir.Inst.Tag = if (is_var_args) .fn_type_cc_var_args else .fn_type_cc;
break :fn_type try fn_type_scope.addFnTypeCc(tag, .{ break :fn_type try fn_type_scope.addFnTypeCc(tag, .{
.src_node = fn_proto.ast.proto_node,
.ret_ty = return_type_inst, .ret_ty = return_type_inst,
.param_types = param_types, .param_types = param_types,
.cc = cc, .cc = cc,
}); });
} else fn_type: { } else fn_type: {
const tag: zir.Inst.Tag = if (is_var_args) .fn_type_var_args else .fn_type; const tag: zir.Inst.Tag = if (is_var_args) .fn_type_var_args else .fn_type;
break :fn_type try fn_type_scope.addFnType(tag, return_type_inst, param_types); break :fn_type try fn_type_scope.addFnType(tag, .{
.src_node = fn_proto.ast.proto_node,
.ret_ty = return_type_inst,
.param_types = param_types,
});
}; };
_ = try fn_type_scope.addBreak(.break_inline, 0, fn_type_inst); _ = try fn_type_scope.addBreak(.break_inline, 0, fn_type_inst);

View File

@ -148,7 +148,6 @@ pub fn analyzeBody(
.bit_not => try sema.zirBitNot(block, inst), .bit_not => try sema.zirBitNot(block, inst),
.bit_or => try sema.zirBitwise(block, inst, .bit_or), .bit_or => try sema.zirBitwise(block, inst, .bit_or),
.bitcast => try sema.zirBitcast(block, inst), .bitcast => try sema.zirBitcast(block, inst),
.bitcast_ref => try sema.zirBitcastRef(block, inst),
.bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst), .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
.block => try sema.zirBlock(block, inst), .block => try sema.zirBlock(block, inst),
.bool_not => try sema.zirBoolNot(block, inst), .bool_not => try sema.zirBoolNot(block, inst),
@ -498,12 +497,6 @@ fn zirConst(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*
return sema.mod.constInst(sema.arena, .unneeded, typed_value_copy); return sema.mod.constInst(sema.arena, .unneeded, typed_value_copy);
} }
fn zirBitcastRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
return sema.mod.fail(&block.base, sema.src, "TODO implement zir_sema.zirBitcastRef", .{});
}
fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
@ -942,7 +935,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerE
try child_block.instructions.append(sema.gpa, &loop_inst.base); try child_block.instructions.append(sema.gpa, &loop_inst.base);
loop_inst.body = .{ .instructions = try sema.arena.dupe(*Inst, loop_block.instructions.items) }; loop_inst.body = .{ .instructions = try sema.arena.dupe(*Inst, loop_block.instructions.items) };
return sema.analyzeBlockBody(parent_block, &child_block, merges); return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
} }
fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst { fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
@ -992,12 +985,13 @@ fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: zir.Inst.Index) Inner
_ = try sema.analyzeBody(&child_block, body); _ = try sema.analyzeBody(&child_block, body);
return sema.analyzeBlockBody(parent_block, &child_block, merges); return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
} }
fn analyzeBlockBody( fn analyzeBlockBody(
sema: *Sema, sema: *Sema,
parent_block: *Scope.Block, parent_block: *Scope.Block,
src: LazySrcLoc,
child_block: *Scope.Block, child_block: *Scope.Block,
merges: *Scope.Block.Merges, merges: *Scope.Block.Merges,
) InnerError!*Inst { ) InnerError!*Inst {
@ -1034,7 +1028,7 @@ fn analyzeBlockBody(
// Need to set the type and emit the Block instruction. This allows machine code generation // Need to set the type and emit the Block instruction. This allows machine code generation
// to emit a jump instruction to after the block when it encounters the break. // to emit a jump instruction to after the block when it encounters the break.
try parent_block.instructions.append(sema.gpa, &merges.block_inst.base); try parent_block.instructions.append(sema.gpa, &merges.block_inst.base);
const resolved_ty = try sema.resolvePeerTypes(parent_block, .todo, merges.results.items); const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items);
merges.block_inst.base.ty = resolved_ty; merges.block_inst.base.ty = resolved_ty;
merges.block_inst.body = .{ merges.block_inst.body = .{
.instructions = try sema.arena.dupe(*Inst, child_block.instructions.items), .instructions = try sema.arena.dupe(*Inst, child_block.instructions.items),
@ -1048,7 +1042,7 @@ fn analyzeBlockBody(
} }
var coerce_block = parent_block.makeSubBlock(); var coerce_block = parent_block.makeSubBlock();
defer coerce_block.instructions.deinit(sema.gpa); defer coerce_block.instructions.deinit(sema.gpa);
const coerced_operand = try sema.coerce(&coerce_block, resolved_ty, br.operand, .todo); const coerced_operand = try sema.coerce(&coerce_block, resolved_ty, br.operand, br.operand.src);
// If no instructions were produced, such as in the case of a coercion of a // If no instructions were produced, such as in the case of a coercion of a
// constant value to a new type, we can simply point the br operand to it. // constant value to a new type, we can simply point the br operand to it.
if (coerce_block.instructions.items.len == 0) { if (coerce_block.instructions.items.len == 0) {
@ -1334,7 +1328,7 @@ fn analyzeCall(
// the block_inst above. // the block_inst above.
_ = try inline_sema.root(&child_block); _ = try inline_sema.root(&child_block);
const result = try inline_sema.analyzeBlockBody(block, &child_block, merges); const result = try inline_sema.analyzeBlockBody(block, call_src, &child_block, merges);
sema.branch_quota = inline_sema.branch_quota; sema.branch_quota = inline_sema.branch_quota;
sema.branch_count = inline_sema.branch_count; sema.branch_count = inline_sema.branch_count;
@ -1845,15 +1839,16 @@ fn zirFnType(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args: b
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].fn_type; const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index); const extra = sema.code.extraData(zir.Inst.FnType, inst_data.payload_index);
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
return sema.fnTypeCommon( return sema.fnTypeCommon(
block, block,
.unneeded, inst_data.src_node,
param_types, param_types,
inst_data.return_type, extra.data.return_type,
.Unspecified, .Unspecified,
var_args, var_args,
); );
@ -1863,21 +1858,23 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args:
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].fn_type; const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = inst_data.src_node };
const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index); const extra = sema.code.extraData(zir.Inst.FnTypeCc, inst_data.payload_index);
const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len); const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
const cc_tv = try sema.resolveInstConst(block, .todo, extra.data.cc); const cc_tv = try sema.resolveInstConst(block, cc_src, extra.data.cc);
// TODO once we're capable of importing and analyzing decls from // TODO once we're capable of importing and analyzing decls from
// std.builtin, this needs to change // std.builtin, this needs to change
const cc_str = cc_tv.val.castTag(.enum_literal).?.data; const cc_str = cc_tv.val.castTag(.enum_literal).?.data;
const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse
return sema.mod.fail(&block.base, .todo, "Unknown calling convention {s}", .{cc_str}); return sema.mod.fail(&block.base, cc_src, "Unknown calling convention {s}", .{cc_str});
return sema.fnTypeCommon( return sema.fnTypeCommon(
block, block,
.unneeded, inst_data.src_node,
param_types, param_types,
inst_data.return_type, extra.data.return_type,
cc, cc,
var_args, var_args,
); );
@ -1886,13 +1883,15 @@ fn zirFnTypeCc(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index, var_args:
fn fnTypeCommon( fn fnTypeCommon(
sema: *Sema, sema: *Sema,
block: *Scope.Block, block: *Scope.Block,
src: LazySrcLoc, src_node_offset: i32,
zir_param_types: []const zir.Inst.Ref, zir_param_types: []const zir.Inst.Ref,
zir_return_type: zir.Inst.Ref, zir_return_type: zir.Inst.Ref,
cc: std.builtin.CallingConvention, cc: std.builtin.CallingConvention,
var_args: bool, var_args: bool,
) InnerError!*Inst { ) InnerError!*Inst {
const return_type = try sema.resolveType(block, src, zir_return_type); const src: LazySrcLoc = .{ .node_offset = src_node_offset };
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
// Hot path for some common function types. // Hot path for some common function types.
if (zir_param_types.len == 0 and !var_args) { if (zir_param_types.len == 0 and !var_args) {
@ -1915,12 +1914,11 @@ fn fnTypeCommon(
const param_types = try sema.arena.alloc(Type, zir_param_types.len); const param_types = try sema.arena.alloc(Type, zir_param_types.len);
for (zir_param_types) |param_type, i| { for (zir_param_types) |param_type, i| {
const resolved = try sema.resolveType(block, src, param_type); // TODO make a compile error from `resolveType` report the source location
// TODO skip for comptime params // of the specific parameter. Will need to take a similar strategy as
if (!resolved.isValidVarType(false)) { // `resolveSwitchItemVal` to avoid resolving the source location unless
return sema.mod.fail(&block.base, .todo, "parameter of type '{}' must be declared comptime", .{resolved}); // we actually need to report an error.
} param_types[i] = try sema.resolveType(block, src, param_type);
param_types[i] = resolved;
} }
const fn_ty = try Type.Tag.function.create(sema.arena, .{ const fn_ty = try Type.Tag.function.create(sema.arena, .{
@ -2082,9 +2080,14 @@ fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
const bin_inst = sema.code.instructions.items(.data)[inst].bin; const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const dest_type = try sema.resolveType(block, .todo, bin_inst.lhs); const src = inst_data.src();
const operand = try sema.resolveInst(bin_inst.rhs); const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
const dest_type = try sema.resolveType(block, dest_ty_src, extra.lhs);
const operand = try sema.resolveInst(extra.rhs);
return sema.bitcast(block, dest_type, operand); return sema.bitcast(block, dest_type, operand);
} }
@ -2234,7 +2237,12 @@ fn zirSwitchCapture(
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
@panic("TODO implement Sema for zirSwitchCapture"); const zir_datas = sema.code.instructions.items(.data);
const capture_info = zir_datas[inst].switch_capture;
const switch_info = zir_datas[capture_info.switch_inst].pl_node;
const src = switch_info.src();
return sema.mod.fail(&block.base, src, "TODO implement Sema for zirSwitchCapture", .{});
} }
fn zirSwitchCaptureElse( fn zirSwitchCaptureElse(
@ -2246,7 +2254,12 @@ fn zirSwitchCaptureElse(
const tracy = trace(@src()); const tracy = trace(@src());
defer tracy.end(); defer tracy.end();
@panic("TODO implement Sema for zirSwitchCaptureElse"); const zir_datas = sema.code.instructions.items(.data);
const capture_info = zir_datas[inst].switch_capture;
const switch_info = zir_datas[capture_info.switch_inst].pl_node;
const src = switch_info.src();
return sema.mod.fail(&block.base, src, "TODO implement Sema for zirSwitchCaptureElse", .{});
} }
fn zirSwitchBlock( fn zirSwitchBlock(
@ -2631,8 +2644,9 @@ fn analyzeSwitch(
const body = sema.code.extra[extra_index..][0..body_len]; const body = sema.code.extra[extra_index..][0..body_len];
extra_index += body_len; extra_index += body_len;
const item = try sema.resolveInst(item_ref); // Validation above ensured these will succeed.
const item_val = try sema.resolveConstValue(block, item.src, item); const item = sema.resolveInst(item_ref) catch unreachable;
const item_val = sema.resolveConstValue(block, .unneeded, item) catch unreachable;
if (operand_val.eql(item_val)) { if (operand_val.eql(item_val)) {
return sema.resolveBody(block, body); return sema.resolveBody(block, body);
} }
@ -2652,8 +2666,9 @@ fn analyzeSwitch(
const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..body_len]; const body = sema.code.extra[extra_index + 2 * ranges_len ..][0..body_len];
for (items) |item_ref| { for (items) |item_ref| {
const item = try sema.resolveInst(item_ref); // Validation above ensured these will succeed.
const item_val = try sema.resolveConstValue(block, item.src, item); const item = sema.resolveInst(item_ref) catch unreachable;
const item_val = sema.resolveConstValue(block, item.src, item) catch unreachable;
if (operand_val.eql(item_val)) { if (operand_val.eql(item_val)) {
return sema.resolveBody(block, body); return sema.resolveBody(block, body);
} }
@ -2666,8 +2681,9 @@ fn analyzeSwitch(
const item_last = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]); const item_last = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1; extra_index += 1;
const first_tv = try sema.resolveInstConst(block, .todo, item_first); // Validation above ensured these will succeed.
const last_tv = try sema.resolveInstConst(block, .todo, item_last); const first_tv = sema.resolveInstConst(block, .unneeded, item_first) catch unreachable;
const last_tv = sema.resolveInstConst(block, .unneeded, item_last) catch unreachable;
if (Value.compare(operand_val, .gte, first_tv.val) and if (Value.compare(operand_val, .gte, first_tv.val) and
Value.compare(operand_val, .lte, last_tv.val)) Value.compare(operand_val, .lte, last_tv.val))
{ {
@ -2876,7 +2892,7 @@ fn analyzeSwitch(
}; };
_ = try child_block.addSwitchBr(src, operand, cases, final_else_body); _ = try child_block.addSwitchBr(src, operand, cases, final_else_body);
return sema.analyzeBlockBody(block, &child_block, merges); return sema.analyzeBlockBody(block, src, &child_block, merges);
} }
fn resolveSwitchItemVal( fn resolveSwitchItemVal(

View File

@ -1487,7 +1487,7 @@ fn buildOutputType(
for (diags.arch.?.allCpuModels()) |cpu| { for (diags.arch.?.allCpuModels()) |cpu| {
help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help; help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help;
} }
std.log.info("Available CPUs for architecture '{s}': {s}", .{ std.log.info("Available CPUs for architecture '{s}':\n{s}", .{
@tagName(diags.arch.?), help_text.items, @tagName(diags.arch.?), help_text.items,
}); });
} }
@ -1499,7 +1499,7 @@ fn buildOutputType(
for (diags.arch.?.allFeaturesList()) |feature| { for (diags.arch.?.allFeaturesList()) |feature| {
help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help;
} }
std.log.info("Available CPU features for architecture '{s}': {s}", .{ std.log.info("Available CPU features for architecture '{s}':\n{s}", .{
@tagName(diags.arch.?), help_text.items, @tagName(diags.arch.?), help_text.items,
}); });
} }

View File

@ -168,15 +168,12 @@ pub const Inst = struct {
asm_volatile, asm_volatile,
/// Bitwise AND. `&` /// Bitwise AND. `&`
bit_and, bit_and,
/// TODO delete this instruction, it has no purpose. /// Bitcast a value to a different type.
/// Uses the pl_node field with payload `Bin`.
bitcast, bitcast,
/// An arbitrary typed pointer is pointer-casted to a new Pointer.
/// The destination type is given by LHS. The cast is to be evaluated
/// as if it were a bit-cast operation from the operand pointer element type to the
/// provided destination type.
bitcast_ref,
/// A typed result location pointer is bitcasted to a new result location pointer. /// A typed result location pointer is bitcasted to a new result location pointer.
/// The new result location pointer has an inferred type. /// The new result location pointer has an inferred type.
/// Uses the un_node field.
bitcast_result_ptr, bitcast_result_ptr,
/// Bitwise NOT. `~` /// Bitwise NOT. `~`
/// Uses `un_node`. /// Uses `un_node`.
@ -338,12 +335,12 @@ pub const Inst = struct {
/// Payload is `Bin` with lhs as the dest type, rhs the operand. /// Payload is `Bin` with lhs as the dest type, rhs the operand.
floatcast, floatcast,
/// Returns a function type, assuming unspecified calling convention. /// Returns a function type, assuming unspecified calling convention.
/// Uses the `fn_type` union field. `payload_index` points to a `FnType`. /// Uses the `pl_node` union field. `payload_index` points to a `FnType`.
fn_type, fn_type,
/// Same as `fn_type` but the function is variadic. /// Same as `fn_type` but the function is variadic.
fn_type_var_args, fn_type_var_args,
/// Returns a function type, with a calling convention instruction operand. /// Returns a function type, with a calling convention instruction operand.
/// Uses the `fn_type` union field. `payload_index` points to a `FnTypeCc`. /// Uses the `pl_node` union field. `payload_index` points to a `FnTypeCc`.
fn_type_cc, fn_type_cc,
/// Same as `fn_type_cc` but the function is variadic. /// Same as `fn_type_cc` but the function is variadic.
fn_type_cc_var_args, fn_type_cc_var_args,
@ -662,7 +659,6 @@ pub const Inst = struct {
.asm_volatile, .asm_volatile,
.bit_and, .bit_and,
.bitcast, .bitcast,
.bitcast_ref,
.bitcast_result_ptr, .bitcast_result_ptr,
.bit_or, .bit_or,
.block, .block,
@ -1212,12 +1208,6 @@ pub const Inst = struct {
/// Index into extra. See `PtrType`. /// Index into extra. See `PtrType`.
payload_index: u32, payload_index: u32,
}, },
fn_type: struct {
return_type: Ref,
/// For `fn_type` this points to a `FnType` in `extra`.
/// For `fn_type_cc` this points to `FnTypeCc` in `extra`.
payload_index: u32,
},
int_type: struct { int_type: struct {
/// Offset from Decl AST node index. /// Offset from Decl AST node index.
/// `Tag` determines which kind of AST node this points to. /// `Tag` determines which kind of AST node this points to.
@ -1289,6 +1279,7 @@ pub const Inst = struct {
/// according to `param_types_len`. /// according to `param_types_len`.
/// Each param type is a `Ref`. /// Each param type is a `Ref`.
pub const FnTypeCc = struct { pub const FnTypeCc = struct {
return_type: Ref,
cc: Ref, cc: Ref,
param_types_len: u32, param_types_len: u32,
}; };
@ -1297,6 +1288,7 @@ pub const Inst = struct {
/// according to `param_types_len`. /// according to `param_types_len`.
/// Each param type is a `Ref`. /// Each param type is a `Ref`.
pub const FnType = struct { pub const FnType = struct {
return_type: Ref,
param_types_len: u32, param_types_len: u32,
}; };
@ -1640,7 +1632,6 @@ const Writer = struct {
=> try self.writeSwitchCapture(stream, inst), => try self.writeSwitchCapture(stream, inst),
.bitcast, .bitcast,
.bitcast_ref,
.bitcast_result_ptr, .bitcast_result_ptr,
.store_to_inferred_ptr, .store_to_inferred_ptr,
=> try stream.writeAll("TODO)"), => try stream.writeAll("TODO)"),
@ -2044,11 +2035,26 @@ const Writer = struct {
stream: anytype, stream: anytype,
inst: Inst.Index, inst: Inst.Index,
var_args: bool, var_args: bool,
) (@TypeOf(stream).Error || error{OutOfMemory})!void { ) !void {
const inst_data = self.code.instructions.items(.data)[inst].fn_type; const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = self.code.extraData(Inst.FnType, inst_data.payload_index); const extra = self.code.extraData(Inst.FnType, inst_data.payload_index);
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len); 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); return self.writeFnTypeCommon(stream, param_types, extra.data.return_type, var_args, .none, src);
}
fn writeFnTypeCc(
self: *Writer,
stream: anytype,
inst: Inst.Index,
var_args: bool,
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
const extra = self.code.extraData(Inst.FnTypeCc, inst_data.payload_index);
const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
const cc = extra.data.cc;
return self.writeFnTypeCommon(stream, param_types, extra.data.return_type, var_args, cc, src);
} }
fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void {
@ -2064,19 +2070,6 @@ const Writer = struct {
try stream.writeAll("})"); try stream.writeAll("})");
} }
fn writeFnTypeCc(
self: *Writer,
stream: anytype,
inst: Inst.Index,
var_args: bool,
) (@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 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);
}
fn writeIntType(self: *Writer, stream: anytype, inst: Inst.Index) !void { fn writeIntType(self: *Writer, stream: anytype, inst: Inst.Index) !void {
const int_type = self.code.instructions.items(.data)[inst].int_type; const int_type = self.code.instructions.items(.data)[inst].int_type;
const prefix: u8 = switch (int_type.signedness) { const prefix: u8 = switch (int_type.signedness) {
@ -2110,7 +2103,8 @@ const Writer = struct {
ret_ty: Inst.Ref, ret_ty: Inst.Ref,
var_args: bool, var_args: bool,
cc: Inst.Ref, cc: Inst.Ref,
) (@TypeOf(stream).Error || error{OutOfMemory})!void { src: LazySrcLoc,
) !void {
try stream.writeAll("["); try stream.writeAll("[");
for (param_types) |param_type, i| { for (param_types) |param_type, i| {
if (i != 0) try stream.writeAll(", "); if (i != 0) try stream.writeAll(", ");
@ -2120,7 +2114,8 @@ const Writer = struct {
try self.writeInstRef(stream, ret_ty); try self.writeInstRef(stream, ret_ty);
try self.writeOptionalInstRef(stream, ", cc=", cc); try self.writeOptionalInstRef(stream, ", cc=", cc);
try self.writeFlag(stream, ", var_args", var_args); try self.writeFlag(stream, ", var_args", var_args);
try stream.writeAll(")"); try stream.writeAll(") ");
try self.writeSrc(stream, src);
} }
fn writeSmallStr( fn writeSmallStr(