| author | |
| committer | |
| log | dea437edfb124b8a4cf4f2e09330ef4282991cc9 |
| tree | cff1a5c5f9b89c4f8f94def8006f7d07f9757dbc |
| parent | 903bed931dddc8b3f7ad1fa87e57eca13375dd32 |
| signature |
7 files changed, 47 insertions(+), 7 deletions(-)
src/AstGen.zig+13-5| ... | @@ -1274,6 +1274,7 @@ fn fnProtoExpr( | ... | @@ -1274,6 +1274,7 @@ fn fnProtoExpr( |
| 1274 | .is_inferred_error = false, | 1274 | .is_inferred_error = false, |
| 1275 | .is_test = false, | 1275 | .is_test = false, |
| 1276 | .is_extern = false, | 1276 | .is_extern = false, |
| 1277 | .is_noinline = false, | ||
| 1277 | .noalias_bits = noalias_bits, | 1278 | .noalias_bits = noalias_bits, |
| 1278 | }); | 1279 | }); |
| 1279 | 1280 | ||
| ... | @@ -3389,7 +3390,6 @@ fn fnDecl( | ... | @@ -3389,7 +3390,6 @@ fn fnDecl( |
| 3389 | }; | 3390 | }; |
| 3390 | defer fn_gz.unstack(); | 3391 | defer fn_gz.unstack(); |
| 3391 | 3392 | ||
| 3392 | // TODO: support noinline | ||
| 3393 | const is_pub = fn_proto.visib_token != null; | 3393 | const is_pub = fn_proto.visib_token != null; |
| 3394 | const is_export = blk: { | 3394 | const is_export = blk: { |
| 3395 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; | 3395 | const maybe_export_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| ... | @@ -3403,6 +3403,10 @@ fn fnDecl( | ... | @@ -3403,6 +3403,10 @@ fn fnDecl( |
| 3403 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; | 3403 | const maybe_inline_token = fn_proto.extern_export_inline_token orelse break :blk false; |
| 3404 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | 3404 | break :blk token_tags[maybe_inline_token] == .keyword_inline; |
| 3405 | }; | 3405 | }; |
| 3406 | const is_noinline = blk: { | ||
| 3407 | const maybe_noinline_token = fn_proto.extern_export_inline_token orelse break :blk false; | ||
| 3408 | break :blk token_tags[maybe_noinline_token] == .keyword_noinline; | ||
| 3409 | }; | ||
| 3406 | 3410 | ||
| 3407 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); | 3411 | const doc_comment_index = try astgen.docCommentAsString(fn_proto.firstToken()); |
| 3408 | 3412 | ||
| ... | @@ -3610,6 +3614,7 @@ fn fnDecl( | ... | @@ -3610,6 +3614,7 @@ fn fnDecl( |
| 3610 | .is_inferred_error = false, | 3614 | .is_inferred_error = false, |
| 3611 | .is_test = false, | 3615 | .is_test = false, |
| 3612 | .is_extern = true, | 3616 | .is_extern = true, |
| 3617 | .is_noinline = is_noinline, | ||
| 3613 | .noalias_bits = noalias_bits, | 3618 | .noalias_bits = noalias_bits, |
| 3614 | }); | 3619 | }); |
| 3615 | } else func: { | 3620 | } else func: { |
| ... | @@ -3658,6 +3663,7 @@ fn fnDecl( | ... | @@ -3658,6 +3663,7 @@ fn fnDecl( |
| 3658 | .is_inferred_error = is_inferred_error, | 3663 | .is_inferred_error = is_inferred_error, |
| 3659 | .is_test = false, | 3664 | .is_test = false, |
| 3660 | .is_extern = false, | 3665 | .is_extern = false, |
| 3666 | .is_noinline = is_noinline, | ||
| 3661 | .noalias_bits = noalias_bits, | 3667 | .noalias_bits = noalias_bits, |
| 3662 | }); | 3668 | }); |
| 3663 | }; | 3669 | }; |
| ... | @@ -4093,6 +4099,7 @@ fn testDecl( | ... | @@ -4093,6 +4099,7 @@ fn testDecl( |
| 4093 | .is_inferred_error = true, | 4099 | .is_inferred_error = true, |
| 4094 | .is_test = true, | 4100 | .is_test = true, |
| 4095 | .is_extern = false, | 4101 | .is_extern = false, |
| 4102 | .is_noinline = false, | ||
| 4096 | .noalias_bits = 0, | 4103 | .noalias_bits = 0, |
| 4097 | }); | 4104 | }); |
| 4098 | 4105 | ||
| ... | @@ -10175,6 +10182,7 @@ const GenZir = struct { | ... | @@ -10175,6 +10182,7 @@ const GenZir = struct { |
| 10175 | is_inferred_error: bool, | 10182 | is_inferred_error: bool, |
| 10176 | is_test: bool, | 10183 | is_test: bool, |
| 10177 | is_extern: bool, | 10184 | is_extern: bool, |
| 10185 | is_noinline: bool, | ||
| 10178 | }) !Zir.Inst.Ref { | 10186 | }) !Zir.Inst.Ref { |
| 10179 | assert(args.src_node != 0); | 10187 | assert(args.src_node != 0); |
| 10180 | const astgen = gz.astgen; | 10188 | const astgen = gz.astgen; |
| ... | @@ -10216,10 +10224,9 @@ const GenZir = struct { | ... | @@ -10216,10 +10224,9 @@ const GenZir = struct { |
| 10216 | } | 10224 | } |
| 10217 | const body_len = astgen.countBodyLenAfterFixups(body); | 10225 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10218 | 10226 | ||
| 10219 | if (args.cc_ref != .none or args.lib_name != 0 or | 10227 | if (args.cc_ref != .none or args.lib_name != 0 or args.is_var_args or args.is_test or |
| 10220 | args.is_var_args or args.is_test or args.is_extern or | 10228 | args.is_extern or args.align_ref != .none or args.section_ref != .none or |
| 10221 | args.align_ref != .none or args.section_ref != .none or | 10229 | args.addrspace_ref != .none or args.noalias_bits != 0 or args.is_noinline) |
| 10222 | args.addrspace_ref != .none or args.noalias_bits != 0) | ||
| 10223 | { | 10230 | { |
| 10224 | var align_body: []Zir.Inst.Index = &.{}; | 10231 | var align_body: []Zir.Inst.Index = &.{}; |
| 10225 | var addrspace_body: []Zir.Inst.Index = &.{}; | 10232 | var addrspace_body: []Zir.Inst.Index = &.{}; |
| ... | @@ -10252,6 +10259,7 @@ const GenZir = struct { | ... | @@ -10252,6 +10259,7 @@ const GenZir = struct { |
| 10252 | .is_inferred_error = args.is_inferred_error, | 10259 | .is_inferred_error = args.is_inferred_error, |
| 10253 | .is_test = args.is_test, | 10260 | .is_test = args.is_test, |
| 10254 | .is_extern = args.is_extern, | 10261 | .is_extern = args.is_extern, |
| 10262 | .is_noinline = args.is_noinline, | ||
| 10255 | .has_lib_name = args.lib_name != 0, | 10263 | .has_lib_name = args.lib_name != 0, |
| 10256 | .has_any_noalias = args.noalias_bits != 0, | 10264 | .has_any_noalias = args.noalias_bits != 0, |
| 10257 | 10265 |
src/Module.zig+1-1| ... | @@ -1488,7 +1488,7 @@ pub const Fn = struct { | ... | @@ -1488,7 +1488,7 @@ pub const Fn = struct { |
| 1488 | branch_quota: u32, | 1488 | branch_quota: u32, |
| 1489 | state: Analysis, | 1489 | state: Analysis, |
| 1490 | is_cold: bool = false, | 1490 | is_cold: bool = false, |
| 1491 | is_noinline: bool = false, | 1491 | is_noinline: bool, |
| 1492 | calls_or_awaits_errorable_fn: bool = false, | 1492 | calls_or_awaits_errorable_fn: bool = false, |
| 1493 | 1493 | ||
| 1494 | /// Any inferred error sets that this function owns, both its own inferred error set and | 1494 | /// Any inferred error sets that this function owns, both its own inferred error set and |
src/Sema.zig+9| ... | @@ -7252,6 +7252,7 @@ fn zirFunc( | ... | @@ -7252,6 +7252,7 @@ fn zirFunc( |
| 7252 | src_locs, | 7252 | src_locs, |
| 7253 | null, | 7253 | null, |
| 7254 | 0, | 7254 | 0, |
| 7255 | false, | ||
| 7255 | ); | 7256 | ); |
| 7256 | } | 7257 | } |
| 7257 | 7258 | ||
| ... | @@ -7382,6 +7383,7 @@ fn funcCommon( | ... | @@ -7382,6 +7383,7 @@ fn funcCommon( |
| 7382 | src_locs: Zir.Inst.Func.SrcLocs, | 7383 | src_locs: Zir.Inst.Func.SrcLocs, |
| 7383 | opt_lib_name: ?[]const u8, | 7384 | opt_lib_name: ?[]const u8, |
| 7384 | noalias_bits: u32, | 7385 | noalias_bits: u32, |
| 7386 | is_noinline: bool, | ||
| 7385 | ) CompileError!Air.Inst.Ref { | 7387 | ) CompileError!Air.Inst.Ref { |
| 7386 | const fn_src = LazySrcLoc.nodeOffset(src_node_offset); | 7388 | const fn_src = LazySrcLoc.nodeOffset(src_node_offset); |
| 7387 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 7389 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| ... | @@ -7577,6 +7579,10 @@ fn funcCommon( | ... | @@ -7577,6 +7579,10 @@ fn funcCommon( |
| 7577 | }); | 7579 | }); |
| 7578 | } | 7580 | } |
| 7579 | 7581 | ||
| 7582 | if (cc_workaround == .Inline and is_noinline) { | ||
| 7583 | return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{}); | ||
| 7584 | } | ||
| 7585 | |||
| 7580 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ | 7586 | break :fn_ty try Type.Tag.function.create(sema.arena, .{ |
| 7581 | .param_types = param_types, | 7587 | .param_types = param_types, |
| 7582 | .comptime_params = comptime_params.ptr, | 7588 | .comptime_params = comptime_params.ptr, |
| ... | @@ -7657,6 +7663,7 @@ fn funcCommon( | ... | @@ -7657,6 +7663,7 @@ fn funcCommon( |
| 7657 | .rbrace_column = @truncate(u16, src_locs.columns >> 16), | 7663 | .rbrace_column = @truncate(u16, src_locs.columns >> 16), |
| 7658 | .param_names = param_names, | 7664 | .param_names = param_names, |
| 7659 | .branch_quota = default_branch_quota, | 7665 | .branch_quota = default_branch_quota, |
| 7666 | .is_noinline = is_noinline, | ||
| 7660 | }; | 7667 | }; |
| 7661 | if (maybe_inferred_error_set_node) |node| { | 7668 | if (maybe_inferred_error_set_node) |node| { |
| 7662 | new_func.inferred_error_sets.prepend(node); | 7669 | new_func.inferred_error_sets.prepend(node); |
| ... | @@ -18443,6 +18450,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -18443,6 +18450,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 18443 | const is_var_args = extra.data.bits.is_var_args; | 18450 | const is_var_args = extra.data.bits.is_var_args; |
| 18444 | const is_inferred_error = extra.data.bits.is_inferred_error; | 18451 | const is_inferred_error = extra.data.bits.is_inferred_error; |
| 18445 | const is_extern = extra.data.bits.is_extern; | 18452 | const is_extern = extra.data.bits.is_extern; |
| 18453 | const is_noinline = extra.data.bits.is_noinline; | ||
| 18446 | 18454 | ||
| 18447 | return sema.funcCommon( | 18455 | return sema.funcCommon( |
| 18448 | block, | 18456 | block, |
| ... | @@ -18460,6 +18468,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -18460,6 +18468,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 18460 | src_locs, | 18468 | src_locs, |
| 18461 | lib_name, | 18469 | lib_name, |
| 18462 | noalias_bits, | 18470 | noalias_bits, |
| 18471 | is_noinline, | ||
| 18463 | ); | 18472 | ); |
| 18464 | } | 18473 | } |
| 18465 | 18474 |
src/Zir.zig+2-1| ... | @@ -2736,6 +2736,7 @@ pub const Inst = struct { | ... | @@ -2736,6 +2736,7 @@ pub const Inst = struct { |
| 2736 | is_inferred_error: bool, | 2736 | is_inferred_error: bool, |
| 2737 | is_test: bool, | 2737 | is_test: bool, |
| 2738 | is_extern: bool, | 2738 | is_extern: bool, |
| 2739 | is_noinline: bool, | ||
| 2739 | has_align_ref: bool, | 2740 | has_align_ref: bool, |
| 2740 | has_align_body: bool, | 2741 | has_align_body: bool, |
| 2741 | has_addrspace_ref: bool, | 2742 | has_addrspace_ref: bool, |
| ... | @@ -2748,7 +2749,7 @@ pub const Inst = struct { | ... | @@ -2748,7 +2749,7 @@ pub const Inst = struct { |
| 2748 | has_ret_ty_body: bool, | 2749 | has_ret_ty_body: bool, |
| 2749 | has_lib_name: bool, | 2750 | has_lib_name: bool, |
| 2750 | has_any_noalias: bool, | 2751 | has_any_noalias: bool, |
| 2751 | _: u16 = undefined, | 2752 | _: u15 = undefined, |
| 2752 | }; | 2753 | }; |
| 2753 | }; | 2754 | }; |
| 2754 | 2755 |
src/codegen/llvm.zig+6| ... | @@ -699,6 +699,12 @@ pub const Object = struct { | ... | @@ -699,6 +699,12 @@ pub const Object = struct { |
| 699 | DeclGen.removeFnAttr(llvm_func, "cold"); | 699 | DeclGen.removeFnAttr(llvm_func, "cold"); |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | if (func.is_noinline) { | ||
| 703 | dg.addFnAttr(llvm_func, "noinline"); | ||
| 704 | } else { | ||
| 705 | DeclGen.removeFnAttr(llvm_func, "noinline"); | ||
| 706 | } | ||
| 707 | |||
| 702 | // Remove all the basic blocks of a function in order to start over, generating | 708 | // Remove all the basic blocks of a function in order to start over, generating |
| 703 | // LLVM IR from an empty function body. | 709 | // LLVM IR from an empty function body. |
| 704 | while (llvm_func.getFirstBasicBlock()) |bb| { | 710 | while (llvm_func.getFirstBasicBlock()) |bb| { |
src/print_zir.zig+4| ... | @@ -1984,6 +1984,7 @@ const Writer = struct { | ... | @@ -1984,6 +1984,7 @@ const Writer = struct { |
| 1984 | inferred_error_set, | 1984 | inferred_error_set, |
| 1985 | false, | 1985 | false, |
| 1986 | false, | 1986 | false, |
| 1987 | false, | ||
| 1987 | 1988 | ||
| 1988 | .none, | 1989 | .none, |
| 1989 | &.{}, | 1990 | &.{}, |
| ... | @@ -2091,6 +2092,7 @@ const Writer = struct { | ... | @@ -2091,6 +2092,7 @@ const Writer = struct { |
| 2091 | extra.data.bits.is_inferred_error, | 2092 | extra.data.bits.is_inferred_error, |
| 2092 | extra.data.bits.is_var_args, | 2093 | extra.data.bits.is_var_args, |
| 2093 | extra.data.bits.is_extern, | 2094 | extra.data.bits.is_extern, |
| 2095 | extra.data.bits.is_noinline, | ||
| 2094 | align_ref, | 2096 | align_ref, |
| 2095 | align_body, | 2097 | align_body, |
| 2096 | addrspace_ref, | 2098 | addrspace_ref, |
| ... | @@ -2250,6 +2252,7 @@ const Writer = struct { | ... | @@ -2250,6 +2252,7 @@ const Writer = struct { |
| 2250 | inferred_error_set: bool, | 2252 | inferred_error_set: bool, |
| 2251 | var_args: bool, | 2253 | var_args: bool, |
| 2252 | is_extern: bool, | 2254 | is_extern: bool, |
| 2255 | is_noinline: bool, | ||
| 2253 | align_ref: Zir.Inst.Ref, | 2256 | align_ref: Zir.Inst.Ref, |
| 2254 | align_body: []const Zir.Inst.Index, | 2257 | align_body: []const Zir.Inst.Index, |
| 2255 | addrspace_ref: Zir.Inst.Ref, | 2258 | addrspace_ref: Zir.Inst.Ref, |
| ... | @@ -2273,6 +2276,7 @@ const Writer = struct { | ... | @@ -2273,6 +2276,7 @@ const Writer = struct { |
| 2273 | try self.writeFlag(stream, "vargs, ", var_args); | 2276 | try self.writeFlag(stream, "vargs, ", var_args); |
| 2274 | try self.writeFlag(stream, "extern, ", is_extern); | 2277 | try self.writeFlag(stream, "extern, ", is_extern); |
| 2275 | try self.writeFlag(stream, "inferror, ", inferred_error_set); | 2278 | try self.writeFlag(stream, "inferror, ", inferred_error_set); |
| 2279 | try self.writeFlag(stream, "noinline, ", is_noinline); | ||
| 2276 | 2280 | ||
| 2277 | if (noalias_bits != 0) { | 2281 | if (noalias_bits != 0) { |
| 2278 | try stream.print("noalias=0b{b}, ", .{noalias_bits}); | 2282 | try stream.print("noalias=0b{b}, ", .{noalias_bits}); |
test/cases/compile_errors/noinline_fn_cc_inline.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const cc = .Inline; | ||
| 2 | noinline fn foo() callconv(cc) void {} | ||
| 3 | |||
| 4 | comptime { | ||
| 5 | _ = foo; | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage2 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // :2:28: error: 'noinline' function cannot have callconv 'Inline' | ||