mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
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:
parent
5f0bde6358
commit
0965724e31
File diff suppressed because it is too large
Load Diff
@ -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
1128
src-self-hosted/zir_sema.zig
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user