Commit 5a2620fcca

Andrew Kelley <andrew@ziglang.org>
2021-02-18 06:22:10
stage2: fix some of the compilation errors in this branch
1 parent c66481f
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 {