self-hosted: refactor some code out of Module.zig into zir_sema.zig

This makes sense from an organizational point of view, as explained by
this new doc comment at the top of the new file:

//! Semantic analysis of ZIR instructions.
//! This file operates on a `Module` instance, transforming untyped ZIR
//! instructions into semantically-analyzed IR instructions. It does type
//! checking, comptime control flow, and safety-check generation. This is the
//! the heart of the Zig compiler.
//! When deciding if something goes into this file or into Module, here is a
//! guiding principle: if it has to do with (untyped) ZIR instructions, it goes
//! here. If the analysis operates on typed IR instructions, it goes in Module.

Before:
   4009 src-self-hosted/Module.zig

After:
   2776 src-self-hosted/Module.zig
   1128 src-self-hosted/zir_sema.zig

This should be sufficient to avoid the situation we have in stage1 where
ir.cpp is 32,516 lines.
This commit is contained in:
Andrew Kelley 2020-07-27 22:44:18 -07:00
parent 5f0bde6358
commit 0965724e31
3 changed files with 1364 additions and 1351 deletions

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ pub const ResultLoc = union(enum) {
pub fn typeExpr(mod: *Module, scope: *Scope, type_node: *ast.Node) InnerError!*zir.Inst {
const type_src = scope.tree().token_locs[type_node.firstToken()].start;
const type_type = try mod.addZIRInstConst(scope, type_src, .{
const type_type = try addZIRInstConst(mod, scope, type_src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.type_type),
});
@ -146,7 +146,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
else => {
const possibly_unused_result = try expr(mod, scope, .none, statement);
const src = scope.tree().token_locs[statement.firstToken()].start;
_ = try mod.addZIRUnOp(scope, src, .ensure_result_used, possibly_unused_result);
_ = try addZIRUnOp(mod, scope, src, .ensure_result_used, possibly_unused_result);
},
}
}
@ -177,7 +177,7 @@ fn varDecl(
if (nodeMayNeedMemoryLocation(init_node)) {
if (node.getTrailer("type_node")) |type_node| {
const type_inst = try typeExpr(mod, scope, type_node);
const alloc = try mod.addZIRUnOp(scope, name_src, .alloc, type_inst);
const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst);
const result_loc: ResultLoc = .{ .ptr = alloc };
const init_inst = try expr(mod, scope, result_loc, init_node);
const sub_scope = try block_arena.create(Scope.LocalVal);
@ -189,7 +189,7 @@ fn varDecl(
};
return &sub_scope.base;
} else {
const alloc = try mod.addZIRNoOpT(scope, name_src, .alloc_inferred);
const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred);
const result_loc: ResultLoc = .{ .inferred_ptr = alloc };
const init_inst = try expr(mod, scope, result_loc, init_node);
const sub_scope = try block_arena.create(Scope.LocalVal);
@ -220,7 +220,7 @@ fn varDecl(
.Keyword_var => {
if (node.getTrailer("type_node")) |type_node| {
const type_inst = try typeExpr(mod, scope, type_node);
const alloc = try mod.addZIRUnOp(scope, name_src, .alloc, type_inst);
const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst);
const result_loc: ResultLoc = .{ .ptr = alloc };
const init_inst = try expr(mod, scope, result_loc, init_node);
const sub_scope = try block_arena.create(Scope.LocalPtr);
@ -232,7 +232,7 @@ fn varDecl(
};
return &sub_scope.base;
} else {
const alloc = try mod.addZIRNoOp(scope, name_src, .alloc_inferred);
const alloc = try addZIRNoOp(mod, scope, name_src, .alloc_inferred);
const result_loc = .{ .inferred_ptr = alloc.castTag(.alloc_inferred).? };
const init_inst = try expr(mod, scope, result_loc, init_node);
const sub_scope = try block_arena.create(Scope.LocalPtr);
@ -269,26 +269,26 @@ fn assignOp(
op_inst_tag: zir.Inst.Tag,
) InnerError!void {
const lhs_ptr = try expr(mod, scope, .lvalue, infix_node.lhs);
const lhs = try mod.addZIRUnOp(scope, lhs_ptr.src, .deref, lhs_ptr);
const lhs_type = try mod.addZIRUnOp(scope, lhs_ptr.src, .typeof, lhs);
const lhs = try addZIRUnOp(mod, scope, lhs_ptr.src, .deref, lhs_ptr);
const lhs_type = try addZIRUnOp(mod, scope, lhs_ptr.src, .typeof, lhs);
const rhs = try expr(mod, scope, .{ .ty = lhs_type }, infix_node.rhs);
const tree = scope.tree();
const src = tree.token_locs[infix_node.op_token].start;
const result = try mod.addZIRBinOp(scope, src, op_inst_tag, lhs, rhs);
_ = try mod.addZIRBinOp(scope, src, .store, lhs_ptr, result);
const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
_ = try addZIRBinOp(mod, scope, src, .store, lhs_ptr, result);
}
fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
const tree = scope.tree();
const src = tree.token_locs[node.op_token].start;
const bool_type = try mod.addZIRInstConst(scope, src, .{
const bool_type = try addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.bool_type),
});
const operand = try expr(mod, scope, .{ .ty = bool_type }, node.rhs);
return mod.addZIRUnOp(scope, src, .boolnot, operand);
return addZIRUnOp(mod, scope, src, .boolnot, operand);
}
/// Identifier token -> String (allocated in scope.arena())
@ -317,7 +317,7 @@ pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.OneToke
const ident_name = try identifierTokenString(mod, scope, node.token);
return mod.addZIRInst(scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});
return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});
}
fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
@ -328,15 +328,15 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!
const lhs = try expr(mod, scope, .none, node.lhs);
const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);
const pointer = try mod.addZIRInst(scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});
return mod.addZIRUnOp(scope, src, .deref, pointer);
const pointer = try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});
return addZIRUnOp(mod, scope, src, .deref, pointer);
}
fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
const tree = scope.tree();
const src = tree.token_locs[node.rtoken].start;
const lhs = try expr(mod, scope, .none, node.lhs);
return mod.addZIRUnOp(scope, src, .deref, lhs);
return addZIRUnOp(mod, scope, src, .deref, lhs);
}
fn simpleBinOp(
@ -352,7 +352,7 @@ fn simpleBinOp(
const lhs = try expr(mod, scope, .none, infix_node.lhs);
const rhs = try expr(mod, scope, .none, infix_node.rhs);
const result = try mod.addZIRBinOp(scope, src, op_inst_tag, lhs, rhs);
const result = try addZIRBinOp(mod, scope, src, op_inst_tag, lhs, rhs);
return rlWrap(mod, scope, rl, result);
}
@ -375,19 +375,19 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
const tree = scope.tree();
const if_src = tree.token_locs[if_node.if_token].start;
const bool_type = try mod.addZIRInstConst(scope, if_src, .{
const bool_type = try addZIRInstConst(mod, scope, if_src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.bool_type),
});
const cond = try expr(mod, &block_scope.base, .{ .ty = bool_type }, if_node.condition);
const condbr = try mod.addZIRInstSpecial(&block_scope.base, if_src, zir.Inst.CondBr, .{
const condbr = try addZIRInstSpecial(mod, &block_scope.base, if_src, zir.Inst.CondBr, .{
.condition = cond,
.then_body = undefined, // populated below
.else_body = undefined, // populated below
}, .{});
const block = try mod.addZIRInstBlock(scope, if_src, .{
const block = try addZIRInstBlock(mod, scope, if_src, .{
.instructions = try block_scope.arena.dupe(*zir.Inst, block_scope.instructions.items),
});
var then_scope: Scope.GenZIR = .{
@ -410,7 +410,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
const then_result = try expr(mod, &then_scope.base, branch_rl, if_node.body);
if (!then_result.tag.isNoReturn()) {
const then_src = tree.token_locs[if_node.body.lastToken()].start;
_ = try mod.addZIRInst(&then_scope.base, then_src, zir.Inst.Break, .{
_ = try addZIRInst(mod, &then_scope.base, then_src, zir.Inst.Break, .{
.block = block,
.operand = then_result,
}, .{});
@ -431,7 +431,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);
if (!else_result.tag.isNoReturn()) {
const else_src = tree.token_locs[else_node.body.lastToken()].start;
_ = try mod.addZIRInst(&else_scope.base, else_src, zir.Inst.Break, .{
_ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{
.block = block,
.operand = else_result,
}, .{});
@ -440,7 +440,7 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
// TODO Optimization opportunity: we can avoid an allocation and a memcpy here
// by directly allocating the body for this one instruction.
const else_src = tree.token_locs[if_node.lastToken()].start;
_ = try mod.addZIRInst(&else_scope.base, else_src, zir.Inst.BreakVoid, .{
_ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
.block = block,
}, .{});
}
@ -456,16 +456,16 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE
const src = tree.token_locs[cfe.ltoken].start;
if (cfe.getRHS()) |rhs_node| {
if (nodeMayNeedMemoryLocation(rhs_node)) {
const ret_ptr = try mod.addZIRNoOp(scope, src, .ret_ptr);
const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr);
const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node);
return mod.addZIRUnOp(scope, src, .@"return", operand);
return addZIRUnOp(mod, scope, src, .@"return", operand);
} else {
const fn_ret_ty = try mod.addZIRNoOp(scope, src, .ret_type);
const fn_ret_ty = try addZIRNoOp(mod, scope, src, .ret_type);
const operand = try expr(mod, scope, .{ .ty = fn_ret_ty }, rhs_node);
return mod.addZIRUnOp(scope, src, .@"return", operand);
return addZIRUnOp(mod, scope, src, .@"return", operand);
}
} else {
return mod.addZIRNoOp(scope, src, .returnvoid);
return addZIRNoOp(mod, scope, src, .returnvoid);
}
}
@ -481,7 +481,7 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.OneToken) InnerError
}
if (getSimplePrimitiveValue(ident_name)) |typed_value| {
return mod.addZIRInstConst(scope, src, typed_value);
return addZIRInstConst(mod, scope, src, typed_value);
}
if (ident_name.len >= 2) integer: {
@ -505,13 +505,13 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.OneToken) InnerError
else => {
const int_type_payload = try scope.arena().create(Value.Payload.IntType);
int_type_payload.* = .{ .signed = is_signed, .bits = bit_count };
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.comptime_int),
.val = Value.initPayload(&int_type_payload.base),
});
},
};
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = val,
});
@ -532,7 +532,7 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.OneToken) InnerError
.local_ptr => {
const local_ptr = s.cast(Scope.LocalPtr).?;
if (mem.eql(u8, local_ptr.name, ident_name)) {
return try mod.addZIRUnOp(scope, src, .deref, local_ptr.ptr);
return try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
}
s = local_ptr.parent;
},
@ -542,7 +542,7 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.OneToken) InnerError
}
if (mod.lookupDeclName(scope, ident_name)) |decl| {
return try mod.addZIRInst(scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
return try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{});
}
return mod.failNode(scope, &ident.base, "use of undeclared identifier '{}'", .{ident_name});
@ -564,7 +564,7 @@ fn stringLiteral(mod: *Module, scope: *Scope, str_lit: *ast.Node.OneToken) Inner
};
const src = tree.token_locs[str_lit.token].start;
return mod.addZIRInst(scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = bytes }, .{});
}
fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) InnerError!*zir.Inst {
@ -589,7 +589,7 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.OneToken) Inne
const int_payload = try arena.create(Value.Payload.Int_u64);
int_payload.* = .{ .int = small_int };
const src = tree.token_locs[int_lit.token].start;
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.comptime_int),
.val = Value.initPayload(&int_payload.base),
});
@ -612,7 +612,7 @@ fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.OneToken) Inne
const float_payload = try arena.create(Value.Payload.Float_128);
float_payload.* = .{ .val = val };
const src = tree.token_locs[float_lit.token].start;
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.comptime_float),
.val = Value.initPayload(&float_payload.base),
});
@ -622,7 +622,7 @@ fn undefLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerErro
const arena = scope.arena();
const tree = scope.tree();
const src = tree.token_locs[node.token].start;
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.@"undefined"),
.val = Value.initTag(.undef),
});
@ -632,7 +632,7 @@ fn boolLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError
const arena = scope.arena();
const tree = scope.tree();
const src = tree.token_locs[node.token].start;
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.bool),
.val = switch (tree.token_ids[node.token]) {
.Keyword_true => Value.initTag(.bool_true),
@ -646,7 +646,7 @@ fn nullLiteral(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError
const arena = scope.arena();
const tree = scope.tree();
const src = tree.token_locs[node.token].start;
return mod.addZIRInstConst(scope, src, .{
return addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.@"null"),
.val = Value.initTag(.null_value),
});
@ -664,7 +664,7 @@ fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zi
const src = tree.token_locs[asm_node.asm_token].start;
const str_type = try mod.addZIRInstConst(scope, src, .{
const str_type = try addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.const_slice_u8_type),
});
@ -676,11 +676,11 @@ fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zi
args[i] = try expr(mod, scope, .none, input.expr);
}
const return_type = try mod.addZIRInstConst(scope, src, .{
const return_type = try addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.void_type),
});
const asm_inst = try mod.addZIRInst(scope, src, zir.Inst.Asm, .{
const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{
.asm_source = try expr(mod, scope, str_type_rl, asm_node.template),
.return_type = return_type,
}, .{
@ -710,14 +710,14 @@ fn simpleCast(
try ensureBuiltinParamCount(mod, scope, call, 2);
const tree = scope.tree();
const src = tree.token_locs[call.builtin_token].start;
const type_type = try mod.addZIRInstConst(scope, src, .{
const type_type = try addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.type_type),
});
const params = call.params();
const dest_type = try expr(mod, scope, .{ .ty = type_type }, params[0]);
const rhs = try expr(mod, scope, .none, params[1]);
const result = try mod.addZIRBinOp(scope, src, inst_tag, dest_type, rhs);
const result = try addZIRBinOp(mod, scope, src, inst_tag, dest_type, rhs);
return rlWrap(mod, scope, rl, result);
}
@ -726,7 +726,7 @@ fn ptrToInt(mod: *Module, scope: *Scope, call: *ast.Node.BuiltinCall) InnerError
const operand = try expr(mod, scope, .none, call.params()[0]);
const tree = scope.tree();
const src = tree.token_locs[call.builtin_token].start;
return mod.addZIRUnOp(scope, src, .ptrtoint, operand);
return addZIRUnOp(mod, scope, src, .ptrtoint, operand);
}
fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) InnerError!*zir.Inst {
@ -739,19 +739,19 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
.none => return try expr(mod, scope, .{ .ty = dest_type }, params[1]),
.discard => {
const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
_ = try mod.addZIRUnOp(scope, result.src, .ensure_result_non_error, result);
_ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
return result;
},
.lvalue => {
const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
return mod.addZIRUnOp(scope, result.src, .ref, result);
return addZIRUnOp(mod, scope, result.src, .ref, result);
},
.ty => |result_ty| {
const result = try expr(mod, scope, .{ .ty = dest_type }, params[1]);
return mod.addZIRBinOp(scope, src, .as, result_ty, result);
return addZIRBinOp(mod, scope, src, .as, result_ty, result);
},
.ptr => |result_ptr| {
const casted_result_ptr = try mod.addZIRBinOp(scope, src, .coerce_result_ptr, dest_type, result_ptr);
const casted_result_ptr = try addZIRBinOp(mod, scope, src, .coerce_result_ptr, dest_type, result_ptr);
return expr(mod, scope, .{ .ptr = casted_result_ptr }, params[1]);
},
.bitcasted_ptr => |bitcasted_ptr| {
@ -763,7 +763,7 @@ fn as(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCall) I
return mod.failTok(scope, call.builtin_token, "TODO implement @as with inferred-type result location pointer", .{});
},
.block_ptr => |block_ptr| {
const casted_block_ptr = try mod.addZIRInst(scope, src, zir.Inst.CoerceResultBlockPtr, .{
const casted_block_ptr = try addZIRInst(mod, scope, src, zir.Inst.CoerceResultBlockPtr, .{
.dest_type = dest_type,
.block = block_ptr,
}, .{});
@ -776,7 +776,7 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
try ensureBuiltinParamCount(mod, scope, call, 2);
const tree = scope.tree();
const src = tree.token_locs[call.builtin_token].start;
const type_type = try mod.addZIRInstConst(scope, src, .{
const type_type = try addZIRInstConst(mod, scope, src, .{
.ty = Type.initTag(.type),
.val = Value.initTag(.type_type),
});
@ -785,26 +785,26 @@ fn bitCast(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.BuiltinCa
switch (rl) {
.none => {
const operand = try expr(mod, scope, .none, params[1]);
return mod.addZIRBinOp(scope, src, .bitcast, dest_type, operand);
return addZIRBinOp(mod, scope, src, .bitcast, dest_type, operand);
},
.discard => {
const operand = try expr(mod, scope, .none, params[1]);
const result = try mod.addZIRBinOp(scope, src, .bitcast, dest_type, operand);
_ = try mod.addZIRUnOp(scope, result.src, .ensure_result_non_error, result);
const result = try addZIRBinOp(mod, scope, src, .bitcast, dest_type, operand);
_ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
return result;
},
.lvalue => {
const operand = try expr(mod, scope, .lvalue, params[1]);
const result = try mod.addZIRBinOp(scope, src, .bitcast_lvalue, dest_type, operand);
const result = try addZIRBinOp(mod, scope, src, .bitcast_lvalue, dest_type, operand);
return result;
},
.ty => |result_ty| {
const result = try expr(mod, scope, .none, params[1]);
const bitcasted = try mod.addZIRBinOp(scope, src, .bitcast, dest_type, result);
return mod.addZIRBinOp(scope, src, .as, result_ty, bitcasted);
const bitcasted = try addZIRBinOp(mod, scope, src, .bitcast, dest_type, result);
return addZIRBinOp(mod, scope, src, .as, result_ty, bitcasted);
},
.ptr => |result_ptr| {
const casted_result_ptr = try mod.addZIRUnOp(scope, src, .bitcast_result_ptr, result_ptr);
const casted_result_ptr = try addZIRUnOp(mod, scope, src, .bitcast_result_ptr, result_ptr);
return expr(mod, scope, .{ .bitcasted_ptr = casted_result_ptr.castTag(.bitcast_result_ptr).? }, params[1]);
},
.bitcasted_ptr => |bitcasted_ptr| {
@ -852,7 +852,7 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In
const args = try scope.getGenZIR().arena.alloc(*zir.Inst, param_nodes.len);
for (param_nodes) |param_node, i| {
const param_src = tree.token_locs[param_node.firstToken()].start;
const param_type = try mod.addZIRInst(scope, param_src, zir.Inst.ParamType, .{
const param_type = try addZIRInst(mod, scope, param_src, zir.Inst.ParamType, .{
.func = lhs,
.arg_index = i,
}, .{});
@ -860,7 +860,7 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In
}
const src = tree.token_locs[node.lhs.firstToken()].start;
const result = try mod.addZIRInst(scope, src, zir.Inst.Call, .{
const result = try addZIRInst(mod, scope, src, zir.Inst.Call, .{
.func = lhs,
.args = args,
}, .{});
@ -871,7 +871,7 @@ fn callExpr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Call) In
fn unreach(mod: *Module, scope: *Scope, unreach_node: *ast.Node.OneToken) InnerError!*zir.Inst {
const tree = scope.tree();
const src = tree.token_locs[unreach_node.token].start;
return mod.addZIRNoOp(scope, src, .@"unreachable");
return addZIRNoOp(mod, scope, src, .@"unreachable");
}
fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
@ -1053,20 +1053,20 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
.none => return result,
.discard => {
// Emit a compile error for discarding error values.
_ = try mod.addZIRUnOp(scope, result.src, .ensure_result_non_error, result);
_ = try addZIRUnOp(mod, scope, result.src, .ensure_result_non_error, result);
return result;
},
.lvalue => {
// We need a pointer but we have a value.
return mod.addZIRUnOp(scope, result.src, .ref, result);
return addZIRUnOp(mod, scope, result.src, .ref, result);
},
.ty => |ty_inst| return mod.addZIRBinOp(scope, result.src, .as, ty_inst, result),
.ty => |ty_inst| return addZIRBinOp(mod, scope, result.src, .as, ty_inst, result),
.ptr => |ptr_inst| {
const casted_result = try mod.addZIRInst(scope, result.src, zir.Inst.CoerceToPtrElem, .{
const casted_result = try addZIRInst(mod, scope, result.src, zir.Inst.CoerceToPtrElem, .{
.ptr = ptr_inst,
.value = result,
}, .{});
_ = try mod.addZIRInst(scope, result.src, zir.Inst.Store, .{
_ = try addZIRInst(mod, scope, result.src, zir.Inst.Store, .{
.ptr = ptr_inst,
.value = casted_result,
}, .{});
@ -1083,3 +1083,121 @@ fn rlWrap(mod: *Module, scope: *Scope, rl: ResultLoc, result: *zir.Inst) InnerEr
},
}
}
pub fn addZIRInstSpecial(
mod: *Module,
scope: *Scope,
src: usize,
comptime T: type,
positionals: std.meta.fieldInfo(T, "positionals").field_type,
kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
) !*T {
const gen_zir = scope.getGenZIR();
try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
const inst = try gen_zir.arena.create(T);
inst.* = .{
.base = .{
.tag = T.base_tag,
.src = src,
},
.positionals = positionals,
.kw_args = kw_args,
};
gen_zir.instructions.appendAssumeCapacity(&inst.base);
return inst;
}
pub fn addZIRNoOpT(mod: *Module, scope: *Scope, src: usize, tag: zir.Inst.Tag) !*zir.Inst.NoOp {
const gen_zir = scope.getGenZIR();
try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
const inst = try gen_zir.arena.create(zir.Inst.NoOp);
inst.* = .{
.base = .{
.tag = tag,
.src = src,
},
.positionals = .{},
.kw_args = .{},
};
gen_zir.instructions.appendAssumeCapacity(&inst.base);
return inst;
}
pub fn addZIRNoOp(mod: *Module, scope: *Scope, src: usize, tag: zir.Inst.Tag) !*zir.Inst {
const inst = try addZIRNoOpT(mod, scope, src, tag);
return &inst.base;
}
pub fn addZIRUnOp(
mod: *Module,
scope: *Scope,
src: usize,
tag: zir.Inst.Tag,
operand: *zir.Inst,
) !*zir.Inst {
const gen_zir = scope.getGenZIR();
try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
const inst = try gen_zir.arena.create(zir.Inst.UnOp);
inst.* = .{
.base = .{
.tag = tag,
.src = src,
},
.positionals = .{
.operand = operand,
},
.kw_args = .{},
};
gen_zir.instructions.appendAssumeCapacity(&inst.base);
return &inst.base;
}
pub fn addZIRBinOp(
mod: *Module,
scope: *Scope,
src: usize,
tag: zir.Inst.Tag,
lhs: *zir.Inst,
rhs: *zir.Inst,
) !*zir.Inst {
const gen_zir = scope.getGenZIR();
try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
const inst = try gen_zir.arena.create(zir.Inst.BinOp);
inst.* = .{
.base = .{
.tag = tag,
.src = src,
},
.positionals = .{
.lhs = lhs,
.rhs = rhs,
},
.kw_args = .{},
};
gen_zir.instructions.appendAssumeCapacity(&inst.base);
return &inst.base;
}
pub fn addZIRInst(
mod: *Module,
scope: *Scope,
src: usize,
comptime T: type,
positionals: std.meta.fieldInfo(T, "positionals").field_type,
kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
) !*zir.Inst {
const inst_special = try addZIRInstSpecial(mod, scope, src, T, positionals, kw_args);
return &inst_special.base;
}
/// TODO The existence of this function is a workaround for a bug in stage1.
pub fn addZIRInstConst(mod: *Module, scope: *Scope, src: usize, typed_value: TypedValue) !*zir.Inst {
const P = std.meta.fieldInfo(zir.Inst.Const, "positionals").field_type;
return addZIRInst(mod, scope, src, zir.Inst.Const, P{ .typed_value = typed_value }, .{});
}
/// TODO The existence of this function is a workaround for a bug in stage1.
pub fn addZIRInstBlock(mod: *Module, scope: *Scope, src: usize, body: zir.Module.Body) !*zir.Inst.Block {
const P = std.meta.fieldInfo(zir.Inst.Block, "positionals").field_type;
return addZIRInstSpecial(mod, scope, src, zir.Inst.Block, P{ .body = body }, .{});
}

1128
src-self-hosted/zir_sema.zig Normal file

File diff suppressed because it is too large Load Diff