stage2: fix some of the compilation errors in this branch
This commit is contained in:
@@ -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", .{});
|
||||
|
||||
@@ -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);
|
||||
|
||||
try checkLabelRedefinition(mod, parent_scope, block_node.label);
|
||||
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, 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", .{});
|
||||
|
||||
25
src/zir.zig
25
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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user