Commit 5a2620fcca
Changed files (4)
src/astgen.zig
@@ -539,17 +539,6 @@ pub fn comptimeExpr(
}
const tree = parent_scope.tree();
- const main_tokens = tree.nodes.items(.main_token);
- const token_tags = tree.tokens.items(.tag);
-
- // Optimization for labeled blocks: don't need to have 2 layers of blocks,
- // we can reuse the existing one.
- const lbrace = main_tokens[node];
- if (token_tags[lbrace - 1] == .colon and
- token_tags[lbrace - 2] == .identifier)
- {
- return labeledBlockExpr(mod, parent_scope, rl, node, .block_comptime);
- }
// Make a scope to collect generated instructions in the sub-expression.
var block_scope: Scope.GenZIR = .{
@@ -708,9 +697,13 @@ pub fn blockExpr(
const tracy = trace(@src());
defer tracy.end();
+ const tree = scope.tree();
+ const main_tokens = tree.nodes.items(.main_token);
+ const token_tags = tree.tokens.items(.tag);
+
const lbrace = main_tokens[node];
if (token_tags[lbrace - 1] == .colon) {
- return labeledBlockExpr(mod, scope, rl, block_node, .block);
+ return labeledBlockExpr(mod, scope, rl, block_node, statements, .block);
}
try blockExprStmts(mod, scope, block_node, statements);
@@ -766,7 +759,8 @@ fn labeledBlockExpr(
mod: *Module,
parent_scope: *Scope,
rl: ResultLoc,
- block_node: *ast.Node.labeled_block,
+ block_node: ast.Node.Index,
+ statements: []const ast.Node.Index,
zir_tag: zir.Inst.Tag,
) InnerError!*zir.Inst {
const tracy = trace(@src());
@@ -777,9 +771,14 @@ fn labeledBlockExpr(
const tree = parent_scope.tree();
const node_datas = tree.nodes.items(.data);
const main_tokens = tree.nodes.items(.main_token);
- const src = token_starts[block_node.lbrace];
+ const token_starts = tree.tokens.items(.start);
+
+ const lbrace = main_tokens[block_node];
+ const label_token = lbrace - 1;
+ assert(token_tags[label_token] == .identifier);
+ const src = token_starts[lbrace];
- try checkLabelRedefinition(mod, parent_scope, block_node.label);
+ try checkLabelRedefinition(mod, parent_scope, label_token);
// Create the Block ZIR instruction so that we can put it into the GenZIR struct
// so that break statements can reference it.
@@ -804,7 +803,7 @@ fn labeledBlockExpr(
.instructions = .{},
// TODO @as here is working around a stage1 miscompilation bug :(
.label = @as(?Scope.GenZIR.Label, Scope.GenZIR.Label{
- .token = block_node.label,
+ .token = label_token,
.block_inst = block_inst,
}),
};
@@ -813,7 +812,7 @@ fn labeledBlockExpr(
defer block_scope.labeled_breaks.deinit(mod.gpa);
defer block_scope.labeled_store_to_block_ptr_list.deinit(mod.gpa);
- try blockExprStmts(mod, &block_scope.base, &block_node.base, block_node.statements());
+ try blockExprStmts(mod, &block_scope.base, block_node, block_node.statements());
if (!block_scope.label.?.used) {
return mod.fail(parent_scope, token_starts[block_node.label], "unused block label", .{});
src/Module.zig
@@ -1223,14 +1223,20 @@ fn astgenAndSemaFn(
.{},
);
}
- if (fn_proto.ast.callconv_expr != 0) {
- return mod.failNode(
- &fn_type_scope.base,
- fn_proto.ast.callconv_expr,
- "TODO implement function calling convention expression",
- .{},
- );
- }
+ const opt_cc: ?*zir.Inst = if (fn_proto.ast.callconv_expr != 0) cc: {
+ // TODO instead of enum literal type, this needs to be the
+ // std.builtin.CallingConvention enum. We need to implement importing other files
+ // and enums in order to fix this.
+ const src = token_starts[tree.firstToken(fn_proto.ast.callconv_expr)];
+ const enum_lit_ty = try astgen.addZIRInstConst(mod, &fn_type_scope.base, src, .{
+ .ty = Type.initTag(.type),
+ .val = Value.initTag(.enum_literal_type),
+ });
+ break :cc try astgen.comptimeExpr(mod, &fn_type_scope.base, .{
+ .ty = enum_lit_ty,
+ }, fn_proto.ast.callconv_expr);
+ } else null;
+
const maybe_bang = tree.firstToken(fn_proto.ast.return_type) - 1;
if (token_tags[maybe_bang] == .bang) {
return mod.failTok(&fn_type_scope.base, maybe_bang, "TODO implement inferred error sets", .{});
@@ -1241,10 +1247,17 @@ fn astgenAndSemaFn(
type_type_rl,
fn_proto.ast.return_type,
);
- const fn_type_inst = try astgen.addZIRInst(mod, &fn_type_scope.base, fn_src, zir.Inst.FnType, .{
- .return_type = return_type_inst,
- .param_types = param_types,
- }, .{});
+ const fn_type_inst = if (opt_cc) |cc|
+ try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type_cc, .{
+ .return_type = return_type_inst,
+ .param_types = param_types,
+ .cc = cc,
+ })
+ else
+ try astgen.addZirInstTag(mod, &fn_type_scope.base, fn_src, .fn_type, .{
+ .return_type = return_type_inst,
+ .param_types = param_types,
+ });
if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
zir.dumpZir(mod.gpa, "fn_type", decl.name, fn_type_scope.instructions.items) catch {};
@@ -1316,6 +1329,7 @@ fn astgenAndSemaFn(
.decl = decl,
.arena = &decl_arena.allocator,
.parent = &decl.container.base,
+ .force_comptime = false,
};
defer gen_scope.instructions.deinit(mod.gpa);
@@ -1348,7 +1362,7 @@ fn astgenAndSemaFn(
params_scope = &sub_scope.base;
}
- try astgen.blockExpr(mod, params_scope, body_node);
+ try astgen.expr(mod, params_scope, .none, body_node);
if (gen_scope.instructions.items.len == 0 or
!gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())
@@ -1496,7 +1510,7 @@ fn astgenAndSemaVarDecl(
assert(is_extern);
return mod.failTok(&block_scope.base, lib_name, "TODO implement function library name", .{});
}
- const is_mutable = token_tags[var_decl.mut_token] == .keyword_var;
+ const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
const is_threadlocal = if (var_decl.threadlocal_token) |some| blk: {
if (!is_mutable) {
return mod.failTok(&block_scope.base, some, "threadlocal variable cannot be constant", .{});
src/zir.zig
@@ -172,8 +172,10 @@ pub const Inst = struct {
floatcast,
/// Declare a function body.
@"fn",
- /// Returns a function type.
- fntype,
+ /// Returns a function type, assuming unspecified calling convention.
+ fn_type,
+ /// Returns a function type, with a calling convention instruction operand.
+ fn_type_cc,
/// @import(operand)
import,
/// Integer literal.
@@ -478,7 +480,8 @@ pub const Inst = struct {
.@"export" => Export,
.param_type => ParamType,
.primitive => Primitive,
- .fntype => FnType,
+ .fn_type => FnType,
+ .fn_type_cc => FnTypeCc,
.elem_ptr, .elem_val => Elem,
.condbr => CondBr,
.ptr_type => PtrType,
@@ -552,7 +555,8 @@ pub const Inst = struct {
.field_ptr_named,
.field_val_named,
.@"fn",
- .fntype,
+ .fn_type,
+ .fn_type_cc,
.int,
.intcast,
.int_type,
@@ -877,7 +881,18 @@ pub const Inst = struct {
};
pub const FnType = struct {
- pub const base_tag = Tag.fntype;
+ pub const base_tag = Tag.fn_type;
+ base: Inst,
+
+ positionals: struct {
+ param_types: []*Inst,
+ return_type: *Inst,
+ },
+ kw_args: struct {},
+ };
+
+ pub const FnTypeCc = struct {
+ pub const base_tag = Tag.fn_type_cc;
base: Inst,
positionals: struct {
src/zir_sema.zig
@@ -91,7 +91,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
.@"fn" => return zirFn(mod, scope, old_inst.castTag(.@"fn").?),
.@"export" => return zirExport(mod, scope, old_inst.castTag(.@"export").?),
.primitive => return zirPrimitive(mod, scope, old_inst.castTag(.primitive).?),
- .fntype => return zirFnType(mod, scope, old_inst.castTag(.fntype).?),
+ .fn_type => return zirFnType(mod, scope, old_inst.castTag(.fn_type).?),
+ .fn_type_cc => return zirFnTypeCc(mod, scope, old_inst.castTag(.fn_type_cc).?),
.intcast => return zirIntcast(mod, scope, old_inst.castTag(.intcast).?),
.bitcast => return zirBitcast(mod, scope, old_inst.castTag(.bitcast).?),
.floatcast => return zirFloatcast(mod, scope, old_inst.castTag(.floatcast).?),
@@ -155,7 +156,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
.bool_or => return zirBoolOp(mod, scope, old_inst.castTag(.bool_or).?),
.void_value => return mod.constVoid(scope, old_inst.src),
.switchbr => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, false),
- .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr).?, true),
+ .switchbr_ref => return zirSwitchBr(mod, scope, old_inst.castTag(.switchbr_ref).?, true),
.switch_range => return zirSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
.container_field_named,
@@ -958,11 +959,11 @@ fn zirCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
);
}
- if (inst.kw_args.modifier == .compile_time) {
+ if (inst.positionals.modifier == .compile_time) {
return mod.fail(scope, inst.base.src, "TODO implement comptime function calls", .{});
}
- if (inst.kw_args.modifier != .auto) {
- return mod.fail(scope, inst.base.src, "TODO implement call with modifier {}", .{inst.kw_args.modifier});
+ if (inst.positionals.modifier != .auto) {
+ return mod.fail(scope, inst.base.src, "TODO implement call with modifier {}", .{inst.positionals.modifier});
}
// TODO handle function calls of generic functions
@@ -1295,34 +1296,69 @@ fn zirEnsureErrPayloadVoid(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp)
fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
- const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
+
+ return fnTypeCommon(
+ mod,
+ scope,
+ &fntype.base,
+ fntype.positionals.param_types,
+ fntype.positionals.return_type,
+ .Unspecified,
+ );
+}
+
+fn zirFnTypeCc(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnTypeCc) InnerError!*Inst {
+ const tracy = trace(@src());
+ defer tracy.end();
+
const cc_tv = try resolveInstConst(mod, scope, fntype.positionals.cc);
+ // TODO once we're capable of importing and analyzing decls from
+ // std.builtin, this needs to change
const cc_str = cc_tv.val.castTag(.enum_literal).?.data;
const cc = std.meta.stringToEnum(std.builtin.CallingConvention, cc_str) orelse
return mod.fail(scope, fntype.positionals.cc.src, "Unknown calling convention {s}", .{cc_str});
+ return fnTypeCommon(
+ mod,
+ scope,
+ &fntype.base,
+ fntype.positionals.param_types,
+ fntype.positionals.return_type,
+ cc,
+ );
+}
+
+fn fnTypeCommon(
+ mod: *Module,
+ scope: *Scope,
+ zir_inst: *zir.Inst,
+ zir_param_types: []*zir.Inst,
+ zir_return_type: *zir.Inst,
+ cc: std.builtin.CallingConvention,
+) InnerError!*Inst {
+ const return_type = try resolveType(mod, scope, zir_return_type);
// Hot path for some common function types.
- if (fntype.positionals.param_types.len == 0) {
+ if (zir_param_types.len == 0) {
if (return_type.zigTypeTag() == .NoReturn and cc == .Unspecified) {
- return mod.constType(scope, fntype.base.src, Type.initTag(.fn_noreturn_no_args));
+ return mod.constType(scope, zir_inst.src, Type.initTag(.fn_noreturn_no_args));
}
if (return_type.zigTypeTag() == .Void and cc == .Unspecified) {
- return mod.constType(scope, fntype.base.src, Type.initTag(.fn_void_no_args));
+ return mod.constType(scope, zir_inst.src, Type.initTag(.fn_void_no_args));
}
if (return_type.zigTypeTag() == .NoReturn and cc == .Naked) {
- return mod.constType(scope, fntype.base.src, Type.initTag(.fn_naked_noreturn_no_args));
+ return mod.constType(scope, zir_inst.src, Type.initTag(.fn_naked_noreturn_no_args));
}
if (return_type.zigTypeTag() == .Void and cc == .C) {
- return mod.constType(scope, fntype.base.src, Type.initTag(.fn_ccc_void_no_args));
+ return mod.constType(scope, zir_inst.src, Type.initTag(.fn_ccc_void_no_args));
}
}
const arena = scope.arena();
- const param_types = try arena.alloc(Type, fntype.positionals.param_types.len);
- for (fntype.positionals.param_types) |param_type, i| {
+ const param_types = try arena.alloc(Type, zir_param_types.len);
+ for (zir_param_types) |param_type, i| {
const resolved = try resolveType(mod, scope, param_type);
// TODO skip for comptime params
if (!resolved.isValidVarType(false)) {
@@ -1336,7 +1372,7 @@ fn zirFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*
.return_type = return_type,
.cc = cc,
});
- return mod.constType(scope, fntype.base.src, fn_ty);
+ return mod.constType(scope, zir_inst.src, fn_ty);
}
fn zirPrimitive(mod: *Module, scope: *Scope, primitive: *zir.Inst.Primitive) InnerError!*Inst {