stage2: fix some of the compilation errors in this branch

This commit is contained in:
Andrew Kelley
2021-02-17 22:22:10 -07:00
parent c66481f9bc
commit 5a2620fcca
4 changed files with 114 additions and 50 deletions

View File

@@ -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", .{});

View File

@@ -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", .{});

View File

@@ -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 {

View File

@@ -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 {