diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 418 | ||||
| -rw-r--r-- | src/Module.zig | 97 | ||||
| -rw-r--r-- | src/Sema.zig | 85 | ||||
| -rw-r--r-- | src/Zir.zig | 210 | ||||
| -rw-r--r-- | src/type.zig | 44 | ||||
| -rw-r--r-- | src/value.zig | 23 |
6 files changed, 513 insertions, 364 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index 9b957a8d4f..7e3eff48ea 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -723,8 +723,12 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn }, .enum_literal => return simpleStrTok(gz, scope, rl, main_tokens[node], node, .enum_literal), .error_value => return simpleStrTok(gz, scope, rl, node_datas[node].rhs, node, .error_value), - .anyframe_literal => return astgen.failNode(node, "async and related features are not yet supported", .{}), - .anyframe_type => return astgen.failNode(node, "async and related features are not yet supported", .{}), + .anyframe_literal => return rvalue(gz, scope, rl, .anyframe_type, node), + .anyframe_type => { + const return_type = try typeExpr(gz, scope, node_datas[node].rhs); + const result = try gz.addUnNode(.anyframe_type, return_type, node); + return rvalue(gz, scope, rl, result, node); + }, .@"catch" => { const catch_token = main_tokens[node]; const payload_token: ?ast.TokenIndex = if (token_tags[catch_token + 1] == .pipe) @@ -1546,18 +1550,10 @@ fn labeledBlockExpr( const block_inst = try gz.addBlock(zir_tag, block_node); try gz.instructions.append(astgen.gpa, block_inst); - var block_scope: GenZir = .{ - .parent = parent_scope, - .decl_node_index = gz.decl_node_index, - .astgen = gz.astgen, - .force_comptime = gz.force_comptime, - .ref_start_index = gz.ref_start_index, - .instructions = .{}, - // TODO @as here is working around a stage1 miscompilation bug :( - .label = @as(?GenZir.Label, GenZir.Label{ - .token = label_token, - .block_inst = block_inst, - }), + var block_scope = gz.makeSubBlock(parent_scope); + block_scope.label = GenZir.Label{ + .token = label_token, + .block_inst = block_inst, }; block_scope.setBreakResultLoc(rl); defer block_scope.instructions.deinit(astgen.gpa); @@ -1695,10 +1691,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner .array_type_sentinel, .elem_type, .indexable_ptr_len, + .anyframe_type, .as, .as_node, - .@"asm", - .asm_volatile, .bit_and, .bitcast, .bitcast_result_ptr, @@ -2095,13 +2090,7 @@ fn varDecl( // Detect whether the initialization expression actually uses the // result location pointer. - var init_scope: GenZir = .{ - .parent = scope, - .decl_node_index = gz.decl_node_index, - .force_comptime = gz.force_comptime, - .ref_start_index = gz.ref_start_index, - .astgen = astgen, - }; + var init_scope = gz.makeSubBlock(scope); defer init_scope.instructions.deinit(gpa); var resolve_inferred_alloc: Zir.Inst.Ref = .none; @@ -3778,14 +3767,7 @@ fn tryExpr( return astgen.failNode(node, "invalid 'try' outside function scope", .{}); }; - var block_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var block_scope = parent_gz.makeSubBlock(scope); block_scope.setBreakResultLoc(rl); defer block_scope.instructions.deinit(astgen.gpa); @@ -3811,28 +3793,14 @@ fn tryExpr( try parent_gz.instructions.append(astgen.gpa, block); try block_scope.setBlockBody(block); - var then_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var then_scope = parent_gz.makeSubBlock(scope); defer then_scope.instructions.deinit(astgen.gpa); const err_code = try then_scope.addUnNode(err_ops[1], operand, node); try genDefers(&then_scope, &fn_block.base, scope, err_code); const then_result = try then_scope.addUnNode(.ret_node, err_code, node); - var else_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var else_scope = parent_gz.makeSubBlock(scope); defer else_scope.instructions.deinit(astgen.gpa); block_scope.break_count += 1; @@ -3878,14 +3846,7 @@ fn orelseCatchExpr( const astgen = parent_gz.astgen; const tree = &astgen.file.tree; - var block_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var block_scope = parent_gz.makeSubBlock(scope); block_scope.setBreakResultLoc(rl); defer block_scope.instructions.deinit(astgen.gpa); @@ -3906,14 +3867,7 @@ fn orelseCatchExpr( try parent_gz.instructions.append(astgen.gpa, block); try block_scope.setBlockBody(block); - var then_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var then_scope = parent_gz.makeSubBlock(scope); defer then_scope.instructions.deinit(astgen.gpa); var err_val_scope: Scope.LocalVal = undefined; @@ -3939,14 +3893,7 @@ fn orelseCatchExpr( // instructions into place until we know whether to keep store_to_block_ptr // instructions or not. - var else_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var else_scope = parent_gz.makeSubBlock(scope); defer else_scope.instructions.deinit(astgen.gpa); // This could be a pointer or value depending on `unwrap_op`. @@ -4140,13 +4087,7 @@ fn boolBinOp( const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs); const bool_br = try gz.addBoolBr(zir_tag, lhs); - var rhs_scope: GenZir = .{ - .parent = scope, - .decl_node_index = gz.decl_node_index, - .astgen = gz.astgen, - .force_comptime = gz.force_comptime, - .ref_start_index = gz.ref_start_index, - }; + var rhs_scope = gz.makeSubBlock(scope); defer rhs_scope.instructions.deinit(gz.astgen.gpa); const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); @@ -4167,14 +4108,7 @@ fn ifExpr( const tree = &astgen.file.tree; const token_tags = tree.tokens.items(.tag); - var block_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var block_scope = parent_gz.makeSubBlock(scope); block_scope.setBreakResultLoc(rl); defer block_scope.instructions.deinit(astgen.gpa); @@ -4218,14 +4152,7 @@ fn ifExpr( try parent_gz.instructions.append(astgen.gpa, block); try block_scope.setBlockBody(block); - var then_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var then_scope = parent_gz.makeSubBlock(scope); defer then_scope.instructions.deinit(astgen.gpa); var payload_val_scope: Scope.LocalVal = undefined; @@ -4273,14 +4200,7 @@ fn ifExpr( // instructions into place until we know whether to keep store_to_block_ptr // instructions or not. - var else_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = block_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var else_scope = parent_gz.makeSubBlock(scope); defer else_scope.instructions.deinit(astgen.gpa); const else_node = if_full.ast.else_expr; @@ -4424,25 +4344,11 @@ fn whileExpr( const loop_block = try parent_gz.addBlock(loop_tag, node); try parent_gz.instructions.append(astgen.gpa, loop_block); - var loop_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var loop_scope = parent_gz.makeSubBlock(scope); loop_scope.setBreakResultLoc(rl); defer loop_scope.instructions.deinit(astgen.gpa); - var continue_scope: GenZir = .{ - .parent = &loop_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = loop_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); defer continue_scope.instructions.deinit(astgen.gpa); const payload_is_ref = if (while_full.payload_token) |payload_token| @@ -4505,14 +4411,7 @@ fn whileExpr( }); } - var then_scope: GenZir = .{ - .parent = &continue_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = continue_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var then_scope = parent_gz.makeSubBlock(&continue_scope.base); defer then_scope.instructions.deinit(astgen.gpa); var payload_val_scope: Scope.LocalVal = undefined; @@ -4557,14 +4456,7 @@ fn whileExpr( loop_scope.break_count += 1; const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); - var else_scope: GenZir = .{ - .parent = &continue_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = continue_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var else_scope = parent_gz.makeSubBlock(&continue_scope.base); defer else_scope.instructions.deinit(astgen.gpa); const else_node = while_full.ast.else_expr; @@ -4659,25 +4551,11 @@ fn forExpr( const loop_block = try parent_gz.addBlock(loop_tag, node); try parent_gz.instructions.append(astgen.gpa, loop_block); - var loop_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var loop_scope = parent_gz.makeSubBlock(scope); loop_scope.setBreakResultLoc(rl); defer loop_scope.instructions.deinit(astgen.gpa); - var cond_scope: GenZir = .{ - .parent = &loop_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = loop_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); defer cond_scope.instructions.deinit(astgen.gpa); // check condition i < array_expr.len @@ -4714,14 +4592,7 @@ fn forExpr( }); } - var then_scope: GenZir = .{ - .parent = &cond_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = cond_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var then_scope = parent_gz.makeSubBlock(&cond_scope.base); defer then_scope.instructions.deinit(astgen.gpa); var payload_val_scope: Scope.LocalVal = undefined; @@ -4773,14 +4644,7 @@ fn forExpr( loop_scope.break_count += 1; const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, for_full.ast.then_expr); - var else_scope: GenZir = .{ - .parent = &cond_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = cond_scope.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var else_scope = parent_gz.makeSubBlock(&cond_scope.base); defer else_scope.instructions.deinit(astgen.gpa); const else_node = for_full.ast.else_expr; @@ -5076,14 +4940,7 @@ fn switchExpr( var multi_cases_payload = ArrayListUnmanaged(u32){}; defer multi_cases_payload.deinit(gpa); - var block_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var block_scope = parent_gz.makeSubBlock(scope); block_scope.setBreakResultLoc(rl); defer block_scope.instructions.deinit(gpa); @@ -5091,14 +4948,7 @@ fn switchExpr( const switch_block = try parent_gz.addBlock(undefined, switch_node); // We re-use this same scope for all cases, including the special prong, if any. - var case_scope: GenZir = .{ - .parent = &block_scope.base, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var case_scope = parent_gz.makeSubBlock(&block_scope.base); defer case_scope.instructions.deinit(gpa); // Do the else/`_` first because it goes first in the payload. @@ -5846,57 +5696,109 @@ fn asmExpr( const tree = &astgen.file.tree; const main_tokens = tree.nodes.items(.main_token); const node_datas = tree.nodes.items(.data); + const token_tags = tree.tokens.items(.tag); const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template); // See https://github.com/ziglang/zig/issues/215 and related issues discussing - // possible inline assembly improvements. Until this is settled, I am avoiding - // potentially wasting time implementing status quo assembly that is not used by - // any of the standard library. - if (full.outputs.len > 1) { - return astgen.failNode(node, "TODO more than 1 asm output", .{}); + // possible inline assembly improvements. Until then here is status quo AstGen + // for assembly syntax. It's used by std lib crypto aesni.zig. + + if (full.outputs.len > 32) { + return astgen.failNode(full.outputs[32], "too many asm outputs", .{}); } - const output: struct { - ty: Zir.Inst.Ref = .none, - constraint: u32 = 0, - } = if (full.outputs.len == 0) .{} else blk: { - const output_node = full.outputs[0]; - const out_type_node = node_datas[output_node].lhs; - if (out_type_node == 0) { - return astgen.failNode(out_type_node, "TODO asm with non -> output", .{}); + var outputs_buffer: [32]Zir.Inst.Asm.Output = undefined; + const outputs = outputs_buffer[0..full.outputs.len]; + + var output_type_bits: u32 = 0; + + for (full.outputs) |output_node, i| { + const symbolic_name = main_tokens[output_node]; + const name = try gz.identAsString(symbolic_name); + const constraint_token = symbolic_name + 2; + const constraint = (try gz.strLitAsString(constraint_token)).index; + const has_arrow = token_tags[symbolic_name + 4] == .arrow; + if (has_arrow) { + output_type_bits |= @as(u32, 1) << @intCast(u5, i); + const out_type_node = node_datas[output_node].lhs; + const out_type_inst = try typeExpr(gz, scope, out_type_node); + outputs[i] = .{ + .name = name, + .constraint = constraint, + .operand = out_type_inst, + }; + } else { + const ident_token = symbolic_name + 4; + const str_index = try gz.identAsString(ident_token); + // TODO this needs extra code for local variables. Have a look at #215 and related + // issues and decide how to handle outputs. Do we want this to be identifiers? + // Or maybe we want to force this to be expressions with a pointer type. + // Until that is figured out this is only hooked up for referencing Decls. + const operand = try gz.addStrTok(.decl_ref, str_index, ident_token); + outputs[i] = .{ + .name = name, + .constraint = constraint, + .operand = operand, + }; } - const constraint_token = main_tokens[output_node] + 2; - break :blk .{ - .ty = try typeExpr(gz, scope, out_type_node), - .constraint = (try gz.strLitAsString(constraint_token)).index, - }; - }; + } - const constraints = try arena.alloc(u32, full.inputs.len); - const args = try arena.alloc(Zir.Inst.Ref, full.inputs.len); + if (full.inputs.len > 32) { + return astgen.failNode(full.inputs[32], "too many asm inputs", .{}); + } + var inputs_buffer: [32]Zir.Inst.Asm.Input = undefined; + const inputs = inputs_buffer[0..full.inputs.len]; + + for (full.inputs) |input_node, i| { + const symbolic_name = main_tokens[input_node]; + const name = try gz.identAsString(symbolic_name); + const constraint_token = symbolic_name + 2; + const constraint = (try gz.strLitAsString(constraint_token)).index; + const has_arrow = token_tags[symbolic_name + 4] == .arrow; + const operand = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input_node].lhs); + inputs[i] = .{ + .name = name, + .constraint = constraint, + .operand = operand, + }; + } - for (full.inputs) |input, i| { - const constraint_token = main_tokens[input] + 2; - constraints[i] = (try gz.strLitAsString(constraint_token)).index; - args[i] = try expr(gz, scope, .{ .ty = .usize_type }, node_datas[input].lhs); + var clobbers_buffer: [32]u32 = undefined; + var clobber_i: usize = 0; + if (full.first_clobber) |first_clobber| clobbers: { + // asm ("foo" ::: "a", "b") + // asm ("foo" ::: "a", "b",) + var tok_i = first_clobber; + while (true) : (tok_i += 1) { + if (clobber_i >= clobbers_buffer.len) { + return astgen.failTok(tok_i, "too many asm clobbers", .{}); + } + clobbers_buffer[clobber_i] = (try gz.strLitAsString(tok_i)).index; + clobber_i += 1; + tok_i += 1; + switch (token_tags[tok_i]) { + .r_paren => break :clobbers, + .comma => { + if (token_tags[tok_i + 1] == .r_paren) { + break :clobbers; + } else { + continue; + } + }, + else => unreachable, + } + } } - const tag: Zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm"; - const result = try gz.addPlNode(tag, node, Zir.Inst.Asm{ + const result = try gz.addAsm(.{ + .node = node, .asm_source = asm_source, - .output_type = output.ty, - .args_len = @intCast(u32, full.inputs.len), - .clobbers_len = 0, // TODO implement asm clobbers + .is_volatile = full.volatile_token != null, + .output_type_bits = output_type_bits, + .outputs = outputs, + .inputs = inputs, + .clobbers = clobbers_buffer[0..clobber_i], }); - - try astgen.extra.ensureCapacity(astgen.gpa, astgen.extra.items.len + - args.len + constraints.len + @boolToInt(output.ty != .none)); - if (output.ty != .none) { - astgen.extra.appendAssumeCapacity(output.constraint); - } - astgen.appendRefsAssumeCapacity(args); - astgen.extra.appendSliceAssumeCapacity(constraints); - return rvalue(gz, scope, rl, result, node); } @@ -5982,14 +5884,7 @@ fn asRlPtr( // as well as the store instruction, instead passing the result as an rvalue. const astgen = parent_gz.astgen; - var as_scope: GenZir = .{ - .parent = scope, - .decl_node_index = parent_gz.decl_node_index, - .astgen = astgen, - .force_comptime = parent_gz.force_comptime, - .ref_start_index = parent_gz.ref_start_index, - .instructions = .{}, - }; + var as_scope = parent_gz.makeSubBlock(scope); defer as_scope.instructions.deinit(astgen.gpa); as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); @@ -6701,14 +6596,8 @@ fn cImport( const astgen = gz.astgen; const gpa = astgen.gpa; - var block_scope: GenZir = .{ - .parent = scope, - .decl_node_index = gz.decl_node_index, - .astgen = astgen, - .force_comptime = true, - .ref_start_index = gz.ref_start_index, - .instructions = .{}, - }; + var block_scope = gz.makeSubBlock(scope); + block_scope.force_comptime = true; defer block_scope.instructions.deinit(gpa); const block_inst = try gz.addBlock(.c_import, node); @@ -6802,43 +6691,44 @@ fn callExpr( } pub const simple_types = std.ComptimeStringMap(Zir.Inst.Ref, .{ - .{ "u8", .u8_type }, - .{ "i8", .i8_type }, - .{ "u16", .u16_type }, - .{ "i16", .i16_type }, - .{ "u32", .u32_type }, - .{ "i32", .i32_type }, - .{ "u64", .u64_type }, - .{ "i64", .i64_type }, - .{ "usize", .usize_type }, - .{ "isize", .isize_type }, - .{ "c_short", .c_short_type }, - .{ "c_ushort", .c_ushort_type }, + .{ "anyerror", .anyerror_type }, + .{ "anyframe", .anyframe_type }, + .{ "bool", .bool_type }, .{ "c_int", .c_int_type }, - .{ "c_uint", .c_uint_type }, .{ "c_long", .c_long_type }, - .{ "c_ulong", .c_ulong_type }, + .{ "c_longdouble", .c_longdouble_type }, .{ "c_longlong", .c_longlong_type }, + .{ "c_short", .c_short_type }, + .{ "c_uint", .c_uint_type }, + .{ "c_ulong", .c_ulong_type }, .{ "c_ulonglong", .c_ulonglong_type }, - .{ "c_longdouble", .c_longdouble_type }, + .{ "c_ushort", .c_ushort_type }, + .{ "c_void", .c_void_type }, + .{ "comptime_float", .comptime_float_type }, + .{ "comptime_int", .comptime_int_type }, + .{ "f128", .f128_type }, .{ "f16", .f16_type }, .{ "f32", .f32_type }, .{ "f64", .f64_type }, - .{ "f128", .f128_type }, - .{ "c_void", .c_void_type }, - .{ "bool", .bool_type }, - .{ "void", .void_type }, - .{ "type", .type_type }, - .{ "anyerror", .anyerror_type }, - .{ "comptime_int", .comptime_int_type }, - .{ "comptime_float", .comptime_float_type }, + .{ "false", .bool_false }, + .{ "i16", .i16_type }, + .{ "i32", .i32_type }, + .{ "i64", .i64_type }, + .{ "i128", .i128_type }, + .{ "i8", .i8_type }, + .{ "isize", .isize_type }, .{ "noreturn", .noreturn_type }, - .{ "null", .null_type }, - .{ "undefined", .undefined_type }, - .{ "undefined", .undef }, .{ "null", .null_value }, .{ "true", .bool_true }, - .{ "false", .bool_false }, + .{ "type", .type_type }, + .{ "u16", .u16_type }, + .{ "u32", .u32_type }, + .{ "u64", .u64_type }, + .{ "u128", .u128_type }, + .{ "u8", .u8_type }, + .{ "undefined", .undef }, + .{ "usize", .usize_type }, + .{ "void", .void_type }, }); fn nodeMayNeedMemoryLocation(tree: *const ast.Tree, start_node: ast.Node.Index) bool { diff --git a/src/Module.zig b/src/Module.zig index 502f94367a..4e69d301f3 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1085,6 +1085,21 @@ pub const Scope = struct { /// a result location pointer. labeled_store_to_block_ptr_list: ArrayListUnmanaged(Zir.Inst.Index) = .{}, + suspend_node: ast.Node.Index = 0, + nosuspend_node: ast.Node.Index = 0, + + pub fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { + return .{ + .force_comptime = gz.force_comptime, + .ref_start_index = gz.ref_start_index, + .decl_node_index = gz.decl_node_index, + .parent = scope, + .astgen = gz.astgen, + .suspend_node = gz.suspend_node, + .nosuspend_node = gz.nosuspend_node, + }; + } + pub const Label = struct { token: ast.TokenIndex, block_inst: Zir.Inst.Index, @@ -1674,9 +1689,9 @@ pub const Scope = struct { @as(usize, @boolToInt(args.type_inst != .none)) + @as(usize, @boolToInt(args.align_inst != .none)), ); - const payload_index = gz.astgen.addExtra(Zir.Inst.AllocExtended{ + const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.AllocExtended{ .src_node = gz.nodeIndexToRelative(args.node), - }) catch unreachable; // ensureUnusedCapacity above + }); if (args.type_inst != .none) { astgen.extra.appendAssumeCapacity(@enumToInt(args.type_inst)); } @@ -1703,6 +1718,64 @@ pub const Scope = struct { return gz.indexToRef(new_index); } + pub fn addAsm( + gz: *GenZir, + args: struct { + /// Absolute node index. This function does the conversion to offset from Decl. + node: ast.Node.Index, + asm_source: Zir.Inst.Ref, + output_type_bits: u32, + is_volatile: bool, + outputs: []const Zir.Inst.Asm.Output, + inputs: []const Zir.Inst.Asm.Input, + clobbers: []const u32, + }, + ) !Zir.Inst.Ref { + const astgen = gz.astgen; + const gpa = astgen.gpa; + + try gz.instructions.ensureUnusedCapacity(gpa, 1); + try astgen.instructions.ensureUnusedCapacity(gpa, 1); + try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Asm).Struct.fields.len + + args.outputs.len * @typeInfo(Zir.Inst.Asm.Output).Struct.fields.len + + args.inputs.len * @typeInfo(Zir.Inst.Asm.Input).Struct.fields.len + + args.clobbers.len); + + const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Asm{ + .src_node = gz.nodeIndexToRelative(args.node), + .asm_source = args.asm_source, + .output_type_bits = args.output_type_bits, + }); + for (args.outputs) |output| { + _ = gz.astgen.addExtraAssumeCapacity(output); + } + for (args.inputs) |input| { + _ = gz.astgen.addExtraAssumeCapacity(input); + } + gz.astgen.extra.appendSliceAssumeCapacity(args.clobbers); + + // * 0b00000000_000XXXXX - `outputs_len`. + // * 0b000000XX_XXX00000 - `inputs_len`. + // * 0b0XXXXX00_00000000 - `clobbers_len`. + // * 0bX0000000_00000000 - is volatile + const small: u16 = @intCast(u16, args.outputs.len) | + @intCast(u16, args.inputs.len << 5) | + @intCast(u16, args.clobbers.len << 10) | + (@as(u16, @boolToInt(args.is_volatile)) << 15); + + const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); + astgen.instructions.appendAssumeCapacity(.{ + .tag = .extended, + .data = .{ .extended = .{ + .opcode = .@"asm", + .small = small, + .operand = payload_index, + } }, + }); + gz.instructions.appendAssumeCapacity(new_index); + return gz.indexToRef(new_index); + } + /// Note that this returns a `Zir.Inst.Index` not a ref. /// Does *not* append the block instruction to the scope. /// Leaves the `payload_index` field undefined. @@ -2209,6 +2282,18 @@ pub const SrcLoc = struct { const token_starts = tree.tokens.items(.start); return token_starts[tok_index]; }, + + .node_offset_anyframe_type => |node_off| { + const tree = src_loc.file_scope.tree; + const node_datas = tree.nodes.items(.data); + const node_tags = tree.nodes.items(.tag); + const parent_node = src_loc.declRelativeToNodeIndex(node_off); + const node = node_datas[parent_node].rhs; + const main_tokens = tree.nodes.items(.main_token); + const tok_index = main_tokens[node]; + const token_starts = tree.tokens.items(.start); + return token_starts[tok_index]; + }, } } }; @@ -2368,6 +2453,12 @@ pub const LazySrcLoc = union(enum) { /// the return type node. /// The Decl is determined contextually. node_offset_fn_type_ret_ty: i32, + /// The source location points to the type expression of an `anyframe->T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate + /// to the type expression. + /// The Decl is determined contextually. + node_offset_anyframe_type: i32, /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope. pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc { @@ -2407,6 +2498,7 @@ pub const LazySrcLoc = union(enum) { .node_offset_switch_range, .node_offset_fn_type_cc, .node_offset_fn_type_ret_ty, + .node_offset_anyframe_type, => .{ .file_scope = scope.getFileScope(), .parent_decl_node = scope.srcDecl().?.src_node, @@ -2453,6 +2545,7 @@ pub const LazySrcLoc = union(enum) { .node_offset_switch_range, .node_offset_fn_type_cc, .node_offset_fn_type_ret_ty, + .node_offset_anyframe_type, => .{ .file_scope = decl.getFileScope(), .parent_decl_node = decl.src_node, diff --git a/src/Sema.zig b/src/Sema.zig index 6b9bf5cc1e..fd9bc39fd9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -138,14 +138,13 @@ pub fn analyzeBody( .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst), .alloc_mut => try sema.zirAllocMut(block, inst), .alloc_comptime => try sema.zirAllocComptime(block, inst), + .anyframe_type => try sema.zirAnyframeType(block, inst), .array_cat => try sema.zirArrayCat(block, inst), .array_mul => try sema.zirArrayMul(block, inst), .array_type => try sema.zirArrayType(block, inst), .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), .as => try sema.zirAs(block, inst), .as_node => try sema.zirAsNode(block, inst), - .@"asm" => try sema.zirAsm(block, inst, false), - .asm_volatile => try sema.zirAsm(block, inst, true), .bit_and => try sema.zirBitwise(block, inst, .bit_and), .bit_not => try sema.zirBitNot(block, inst), .bit_or => try sema.zirBitwise(block, inst, .bit_or), @@ -518,6 +517,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErro .frame_address => return sema.zirFrameAddress( block, extended), .alloc => return sema.zirAllocExtended( block, extended), .builtin_extern => return sema.zirBuiltinExtern( block, extended), + .@"asm" => return sema.zirAsm( block, extended), .c_undef => return sema.zirCUndef( block, extended), .c_include => return sema.zirCInclude( block, extended), .c_define => return sema.zirCDefine( block, extended), @@ -2173,6 +2173,19 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) return sema.mod.constType(sema.arena, .unneeded, array_ty); } +fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { + const tracy = trace(@src()); + defer tracy.end(); + + const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const src = inst_data.src(); + const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node }; + const return_type = try sema.resolveType(block, operand_src, inst_data.operand); + const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type); + + return sema.mod.constType(sema.arena, src, anyframe_type); +} + fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst { const tracy = trace(@src()); defer tracy.end(); @@ -4394,42 +4407,62 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*I fn zirAsm( sema: *Sema, block: *Scope.Block, - inst: Zir.Inst.Index, - is_volatile: bool, + extended: Zir.Inst.Extended.InstData, ) InnerError!*Inst { const tracy = trace(@src()); defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[inst].pl_node; - const src = inst_data.src(); - const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = inst_data.src_node }; - const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = inst_data.src_node }; - const extra = sema.code.extraData(Zir.Inst.Asm, inst_data.payload_index); + const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = extra.data.src_node }; + const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node }; const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source); + const outputs_len = @truncate(u5, extended.small); + const inputs_len = @truncate(u5, extended.small >> 5); + const clobbers_len = @truncate(u5, extended.small >> 10); + const is_volatile = @truncate(u1, extended.small >> 15) != 0; + + if (outputs_len > 1) { + return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{}); + } var extra_i = extra.end; + var output_type_bits = extra.data.output_type_bits; + const Output = struct { constraint: []const u8, ty: Type }; - const output: ?Output = if (extra.data.output_type != .none) blk: { - const constraint = sema.code.nullTerminatedString(sema.code.extra[extra_i]); - extra_i += 1; + const output: ?Output = if (outputs_len == 0) null else blk: { + const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i); + extra_i = output.end; + + const is_type = @truncate(u1, output_type_bits) != 0; + output_type_bits >>= 1; + + if (!is_type) { + return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with non `->` output", .{}); + } + + const constraint = sema.code.nullTerminatedString(output.data.constraint); break :blk Output{ .constraint = constraint, - .ty = try sema.resolveType(block, ret_ty_src, extra.data.output_type), + .ty = try sema.resolveType(block, ret_ty_src, output.data.operand), }; - } else null; + }; - const args = try sema.arena.alloc(*Inst, extra.data.args_len); - const inputs = try sema.arena.alloc([]const u8, extra.data.args_len); - const clobbers = try sema.arena.alloc([]const u8, extra.data.clobbers_len); + const args = try sema.arena.alloc(*Inst, inputs_len); + const inputs = try sema.arena.alloc([]const u8, inputs_len); - for (args) |*arg| { - arg.* = try sema.resolveInst(@intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i])); - extra_i += 1; - } - for (inputs) |*name| { - name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]); - extra_i += 1; + for (args) |*arg, arg_i| { + const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); + extra_i = input.end; + + const name = sema.code.nullTerminatedString(input.data.name); + _ = name; // TODO: use the name + + arg.* = try sema.resolveInst(input.data.operand); + inputs[arg_i] = sema.code.nullTerminatedString(input.data.constraint); } + + const clobbers = try sema.arena.alloc([]const u8, clobbers_len); for (clobbers) |*name| { name.* = sema.code.nullTerminatedString(sema.code.extra[extra_i]); extra_i += 1; @@ -5408,7 +5441,7 @@ fn zirFuncExtended( var extra_index: usize = extra.end; if (small.has_lib_name) { - const lib_name = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); + const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]); extra_index += 1; return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{}); } @@ -5428,7 +5461,7 @@ fn zirFuncExtended( } else .Unspecified; const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); - extra_index += 1; + extra_index += param_types.len; const body = sema.code.extra[extra_index..][0..extra.data.body_len]; diff --git a/src/Zir.zig b/src/Zir.zig index 898b3089f8..dfa845ce13 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -60,7 +60,8 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en @field(result, field.name) = switch (field.field_type) { u32 => code.extra[i], Inst.Ref => @intToEnum(Inst.Ref, code.extra[i]), - else => unreachable, + i32 => @bitCast(i32, code.extra[i]), + else => @compileError("bad field type"), }; i += 1; } @@ -165,18 +166,15 @@ pub const Inst = struct { /// error if the indexable object is not indexable. /// Uses the `un_node` field. The AST node is the for loop node. indexable_ptr_len, + /// Create a `anyframe->T` type. + /// Uses the `un_node` field. + anyframe_type, /// Type coercion. No source location attached. /// Uses the `bin` field. as, /// Type coercion to the function's return type. /// Uses the `pl_node` field. Payload is `As`. AST node could be many things. as_node, - /// Inline assembly. Non-volatile. - /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node. - @"asm", - /// Inline assembly with the volatile attribute. - /// Uses the `pl_node` union field. Payload is `Asm`. AST node is the assembly node. - asm_volatile, /// Bitwise AND. `&` bit_and, /// Bitcast a value to a different type. @@ -967,10 +965,9 @@ pub const Inst = struct { .array_type_sentinel, .elem_type, .indexable_ptr_len, + .anyframe_type, .as, .as_node, - .@"asm", - .asm_volatile, .bit_and, .bitcast, .bitcast_result_ptr, @@ -1259,6 +1256,14 @@ pub const Inst = struct { /// The `@extern` builtin. /// `operand` is payload index to `BinNode`. builtin_extern, + /// Inline assembly. + /// `small`: + /// * 0b00000000_000XXXXX - `outputs_len`. + /// * 0b000000XX_XXX00000 - `inputs_len`. + /// * 0b0XXXXX00_00000000 - `clobbers_len`. + /// * 0bX0000000_00000000 - is volatile + /// `operand` is payload index to `Asm`. + @"asm", /// `operand` is payload index to `UnNode`. c_undef, /// `operand` is payload index to `UnNode`. @@ -1313,6 +1318,8 @@ pub const Inst = struct { i32_type, u64_type, i64_type, + u128_type, + i128_type, usize_type, isize_type, c_short_type, @@ -1336,17 +1343,10 @@ pub const Inst = struct { comptime_int_type, comptime_float_type, noreturn_type, + anyframe_type, null_type, undefined_type, - fn_noreturn_no_args_type, - fn_void_no_args_type, - fn_naked_noreturn_no_args_type, - fn_ccc_void_no_args_type, - single_const_pointer_to_comptime_int_type, - const_slice_u8_type, enum_literal_type, - manyptr_u8_type, - manyptr_const_u8_type, atomic_ordering_type, atomic_rmw_op_type, calling_convention_type, @@ -1355,6 +1355,14 @@ pub const Inst = struct { call_options_type, export_options_type, extern_options_type, + manyptr_u8_type, + manyptr_const_u8_type, + fn_noreturn_no_args_type, + fn_void_no_args_type, + fn_naked_noreturn_no_args_type, + fn_ccc_void_no_args_type, + single_const_pointer_to_comptime_int_type, + const_slice_u8_type, /// `undefined` (untyped) undef, @@ -1418,6 +1426,14 @@ pub const Inst = struct { .ty = Type.initTag(.type), .val = Value.initTag(.i64_type), }, + .u128_type = .{ + .ty = Type.initTag(.type), + .val = Value.initTag(.u128_type), + }, + .i128_type = .{ + .ty = Type.initTag(.type), + .val = Value.initTag(.i128_type), + }, .usize_type = .{ .ty = Type.initTag(.type), .val = Value.initTag(.usize_type), @@ -1510,6 +1526,10 @@ pub const Inst = struct { .ty = Type.initTag(.type), .val = Value.initTag(.noreturn_type), }, + .anyframe_type = .{ + .ty = Type.initTag(.type), + .val = Value.initTag(.anyframe_type), + }, .null_type = .{ .ty = Type.initTag(.type), .val = Value.initTag(.null_type), @@ -1806,17 +1826,35 @@ pub const Inst = struct { } }; - /// Stored in extra. Trailing is: - /// * output_constraint: u32 // index into string_bytes (null terminated) if output is present - /// * arg: Ref // for every args_len. - /// * constraint: u32 // index into string_bytes (null terminated) for every args_len. - /// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len. + /// Trailing: + /// 0. Output for every outputs_len + /// 1. Input for every inputs_len + /// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len. pub const Asm = struct { + src_node: i32, asm_source: Ref, - /// May be omitted. - output_type: Ref, - args_len: u32, - clobbers_len: u32, + /// 1 bit for each outputs_len: whether it uses `-> T` or not. + /// 0b0 - operand is a pointer to where to store the output. + /// 0b1 - operand is a type; asm expression has the output as the result. + /// 0b0X is the first output, 0bX0 is the second, etc. + output_type_bits: u32, + + pub const Output = struct { + /// index into string_bytes (null terminated) + name: u32, + /// index into string_bytes (null terminated) + constraint: u32, + /// How to interpret this is determined by `output_type_bits`. + operand: Ref, + }; + + pub const Input = struct { + /// index into string_bytes (null terminated) + name: u32, + /// index into string_bytes (null terminated) + constraint: u32, + operand: Ref, + }; }; /// Trailing: @@ -2298,6 +2336,7 @@ const Writer = struct { .alloc_mut, .alloc_comptime, .indexable_ptr_len, + .anyframe_type, .bit_not, .bool_not, .negate, @@ -2430,10 +2469,6 @@ const Writer = struct { .builtin_async_call, => try self.writePlNode(stream, inst), - .@"asm", - .asm_volatile, - => try self.writePlNodeAsm(stream, inst), - .error_set_decl => try self.writePlNodeErrorSetDecl(stream, inst), .add_with_overflow, @@ -2603,7 +2638,9 @@ const Writer = struct { .builtin_src, => try self.writeExtNode(stream, extended), - .func, + .@"asm" => try self.writeAsm(stream, extended), + .func => try self.writeFuncExtended(stream, extended), + .alloc, .builtin_extern, .c_undef, @@ -2794,49 +2831,74 @@ const Writer = struct { try self.writeSrc(stream, inst_data.src()); } - fn writePlNodeAsm(self: *Writer, stream: anytype, inst: Inst.Index) !void { - const inst_data = self.code.instructions.items(.data)[inst].pl_node; - const extra = self.code.extraData(Inst.Asm, inst_data.payload_index); - var extra_i: usize = extra.end; + fn writeAsm(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { + const extra = self.code.extraData(Inst.Asm, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const outputs_len = @truncate(u5, extended.small); + const inputs_len = @truncate(u5, extended.small >> 5); + const clobbers_len = @truncate(u5, extended.small >> 10); + const is_volatile = @truncate(u1, extended.small >> 15) != 0; - if (extra.data.output_type != .none) { - const constraint_str_index = self.code.extra[extra_i]; - extra_i += 1; - const constraint = self.code.nullTerminatedString(constraint_str_index); - try stream.print("\"{}\"->", .{std.zig.fmtEscapes(constraint)}); - try self.writeInstRef(stream, extra.data.output_type); - try stream.writeAll(", "); - } + try self.writeFlag(stream, "volatile, ", is_volatile); + try self.writeInstRef(stream, extra.data.asm_source); + try stream.writeAll(", "); + + var extra_i: usize = extra.end; + var output_type_bits = extra.data.output_type_bits; { var i: usize = 0; - while (i < extra.data.args_len) : (i += 1) { - const arg = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_i]); - extra_i += 1; - try self.writeInstRef(stream, arg); - try stream.writeAll(", "); + while (i < outputs_len) : (i += 1) { + const output = self.code.extraData(Inst.Asm.Output, extra_i); + extra_i = output.end; + + const is_type = @truncate(u1, output_type_bits) != 0; + output_type_bits >>= 1; + + const name = self.code.nullTerminatedString(output.data.name); + const constraint = self.code.nullTerminatedString(output.data.constraint); + try stream.print("output({}, \"{}\", ", .{ + std.zig.fmtId(name), std.zig.fmtEscapes(constraint), + }); + try self.writeFlag(stream, "->", is_type); + try self.writeInstRef(stream, output.data.operand); + try stream.writeAll(")"); + if (i + 1 < outputs_len) { + try stream.writeAll("), "); + } } } { var i: usize = 0; - while (i < extra.data.args_len) : (i += 1) { - const str_index = self.code.extra[extra_i]; - extra_i += 1; - const constraint = self.code.nullTerminatedString(str_index); - try stream.print("\"{}\", ", .{std.zig.fmtEscapes(constraint)}); + while (i < inputs_len) : (i += 1) { + const input = self.code.extraData(Inst.Asm.Input, extra_i); + extra_i = input.end; + + const name = self.code.nullTerminatedString(input.data.name); + const constraint = self.code.nullTerminatedString(input.data.constraint); + try stream.print("input({}, \"{}\", ", .{ + std.zig.fmtId(name), std.zig.fmtEscapes(constraint), + }); + try self.writeInstRef(stream, input.data.operand); + try stream.writeAll(")"); + if (i + 1 < inputs_len) { + try stream.writeAll(", "); + } } } { var i: usize = 0; - while (i < extra.data.clobbers_len) : (i += 1) { + while (i < clobbers_len) : (i += 1) { const str_index = self.code.extra[extra_i]; extra_i += 1; const clobber = self.code.nullTerminatedString(str_index); - try stream.print("{}, ", .{std.zig.fmtId(clobber)}); + try stream.print("{}", .{std.zig.fmtId(clobber)}); + if (i + 1 < clobbers_len) { + try stream.writeAll(", "); + } } } - try self.writeInstRef(stream, extra.data.asm_source); try stream.writeAll(") "); - try self.writeSrc(stream, inst_data.src()); + try self.writeSrc(stream, src); } fn writePlNodeOverflowArithmetic(self: *Writer, stream: anytype, inst: Inst.Index) !void { @@ -3467,6 +3529,40 @@ const Writer = struct { ); } + fn writeFuncExtended(self: *Writer, stream: anytype, extended: Inst.Extended.InstData) !void { + const extra = self.code.extraData(Inst.ExtendedFunc, extended.operand); + const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; + const small = @bitCast(Inst.ExtendedFunc.Small, extended.small); + + var extra_index: usize = extra.end; + if (small.has_lib_name) { + const lib_name = self.code.nullTerminatedString(self.code.extra[extra_index]); + extra_index += 1; + try stream.print("lib_name=\"{}\", ", .{std.zig.fmtEscapes(lib_name)}); + } + const cc: Inst.Ref = if (!small.has_cc) .none else blk: { + const cc = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]); + extra_index += 1; + break :blk cc; + }; + + const param_types = self.code.refSlice(extra_index, extra.data.param_types_len); + extra_index += param_types.len; + + const body = self.code.extra[extra_index..][0..extra.data.body_len]; + + return self.writeFuncCommon( + stream, + param_types, + extra.data.return_type, + small.is_inferred_error, + small.is_var_args, + cc, + body, + src, + ); + } + fn writeBoolBr(self: *Writer, stream: anytype, inst: Inst.Index) !void { const inst_data = self.code.instructions.items(.data)[inst].bool_br; const extra = self.code.extraData(Inst.Block, inst_data.payload_index); diff --git a/src/type.zig b/src/type.zig index 5bcf06cb5d..18dd453814 100644 --- a/src/type.zig +++ b/src/type.zig @@ -95,6 +95,8 @@ pub const Type = extern union { .anyerror_void_error_union, .error_union => return .ErrorUnion, + .anyframe_T, .@"anyframe" => return .AnyFrame, + .empty_struct, .empty_struct_literal, .@"struct", @@ -620,6 +622,7 @@ pub const Type = extern union { .call_options, .export_options, .extern_options, + .@"anyframe", => unreachable, .array_u8, @@ -637,6 +640,7 @@ pub const Type = extern union { .optional, .optional_single_mut_pointer, .optional_single_const_pointer, + .anyframe_T, => return self.copyPayloadShallow(allocator, Payload.ElemType), .int_signed, @@ -754,6 +758,7 @@ pub const Type = extern union { .void, .type, .anyerror, + .@"anyframe", .comptime_int, .comptime_float, .noreturn, @@ -820,6 +825,12 @@ pub const Type = extern union { continue; }, + .anyframe_T => { + const return_type = ty.castTag(.anyframe_T).?.data; + try writer.print("anyframe->", .{}); + ty = return_type; + continue; + }, .array_u8 => { const len = ty.castTag(.array_u8).?.data; return writer.print("[{d}]u8", .{len}); @@ -994,6 +1005,7 @@ pub const Type = extern union { .void => return Value.initTag(.void_type), .type => return Value.initTag(.type_type), .anyerror => return Value.initTag(.anyerror_type), + .@"anyframe" => return Value.initTag(.anyframe_type), .comptime_int => return Value.initTag(.comptime_int_type), .comptime_float => return Value.initTag(.comptime_float_type), .noreturn => return Value.initTag(.noreturn_type), @@ -1075,6 +1087,8 @@ pub const Type = extern union { .call_options, .export_options, .extern_options, + .@"anyframe", + .anyframe_T, => true, .@"struct" => { @@ -1223,6 +1237,8 @@ pub const Type = extern union { .pointer, .manyptr_u8, .manyptr_const_u8, + .@"anyframe", + .anyframe_T, => return @divExact(target.cpu.arch.ptrBitWidth(), 8), .c_short => return @divExact(CType.short.sizeInBits(target), 8), @@ -1388,7 +1404,11 @@ pub const Type = extern union { .i64, .u64 => return 8, .u128, .i128 => return 16, - .isize, .usize => return @divExact(target.cpu.arch.ptrBitWidth(), 8), + .isize, + .usize, + .@"anyframe", + .anyframe_T, + => return @divExact(target.cpu.arch.ptrBitWidth(), 8), .const_slice, .mut_slice, @@ -1536,7 +1556,11 @@ pub const Type = extern union { .i64, .u64, .f64 => 64, .u128, .i128, .f128 => 128, - .isize, .usize => target.cpu.arch.ptrBitWidth(), + .isize, + .usize, + .@"anyframe", + .anyframe_T, + => target.cpu.arch.ptrBitWidth(), .const_slice, .mut_slice, @@ -2256,6 +2280,8 @@ pub const Type = extern union { .call_options, .export_options, .extern_options, + .@"anyframe", + .anyframe_T, => return null, .@"struct" => { @@ -2666,9 +2692,10 @@ pub const Type = extern union { comptime_int, comptime_float, noreturn, + @"anyframe", + @"null", + @"undefined", enum_literal, - manyptr_u8, - manyptr_const_u8, atomic_ordering, atomic_rmw_op, calling_convention, @@ -2677,15 +2704,15 @@ pub const Type = extern union { call_options, export_options, extern_options, - @"null", - @"undefined", + manyptr_u8, + manyptr_const_u8, fn_noreturn_no_args, fn_void_no_args, fn_naked_noreturn_no_args, fn_ccc_void_no_args, single_const_pointer_to_comptime_int, - anyerror_void_error_union, const_slice_u8, + anyerror_void_error_union, /// This is a special type for variadic parameters of a function call. /// Casts to it will validate that the type can be passed to a c calling convetion function. var_args_param, @@ -2719,6 +2746,7 @@ pub const Type = extern union { optional_single_mut_pointer, optional_single_const_pointer, error_union, + anyframe_T, error_set, error_set_single, empty_struct, @@ -2790,6 +2818,7 @@ pub const Type = extern union { .call_options, .export_options, .extern_options, + .@"anyframe", => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), .array_u8, @@ -2807,6 +2836,7 @@ pub const Type = extern union { .optional, .optional_single_mut_pointer, .optional_single_const_pointer, + .anyframe_T, => Payload.ElemType, .int_signed, diff --git a/src/value.zig b/src/value.zig index e1ca79332c..d2d7be3007 100644 --- a/src/value.zig +++ b/src/value.zig @@ -55,17 +55,10 @@ pub const Value = extern union { comptime_int_type, comptime_float_type, noreturn_type, + anyframe_type, null_type, undefined_type, - fn_noreturn_no_args_type, - fn_void_no_args_type, - fn_naked_noreturn_no_args_type, - fn_ccc_void_no_args_type, - single_const_pointer_to_comptime_int_type, - const_slice_u8_type, enum_literal_type, - manyptr_u8_type, - manyptr_const_u8_type, atomic_ordering_type, atomic_rmw_op_type, calling_convention_type, @@ -74,6 +67,14 @@ pub const Value = extern union { call_options_type, export_options_type, extern_options_type, + manyptr_u8_type, + manyptr_const_u8_type, + fn_noreturn_no_args_type, + fn_void_no_args_type, + fn_naked_noreturn_no_args_type, + fn_ccc_void_no_args_type, + single_const_pointer_to_comptime_int_type, + const_slice_u8_type, undef, zero, @@ -166,6 +167,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type, .fn_ccc_void_no_args_type, .single_const_pointer_to_comptime_int_type, + .anyframe_type, .const_slice_u8_type, .enum_literal_type, .undef, @@ -334,6 +336,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type, .fn_ccc_void_no_args_type, .single_const_pointer_to_comptime_int_type, + .anyframe_type, .const_slice_u8_type, .enum_literal_type, .undef, @@ -502,6 +505,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"), .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"), .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), + .anyframe_type => return out_stream.writeAll("anyframe"), .const_slice_u8_type => return out_stream.writeAll("[]const u8"), .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), .manyptr_u8_type => return out_stream.writeAll("[*]u8"), @@ -633,6 +637,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args), .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args), .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), + .anyframe_type => Type.initTag(.@"anyframe"), .const_slice_u8_type => Type.initTag(.const_slice_u8), .enum_literal_type => Type.initTag(.enum_literal), .manyptr_u8_type => Type.initTag(.manyptr_u8), @@ -1070,6 +1075,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type, .fn_ccc_void_no_args_type, .single_const_pointer_to_comptime_int_type, + .anyframe_type, .const_slice_u8_type, .enum_literal_type, .ty, @@ -1338,6 +1344,7 @@ pub const Value = extern union { .fn_naked_noreturn_no_args_type, .fn_ccc_void_no_args_type, .single_const_pointer_to_comptime_int_type, + .anyframe_type, .const_slice_u8_type, .enum_literal_type, .manyptr_u8_type, |
