| author | |
| committer | |
| log | dae4c18aa7999a866b6b145ed3c88cb6c06852be |
| tree | 6aa41102b19c8e0af04bf1dd8af5158c4cc8b3a5 |
| parent | d5f173d28f2991e05dad399ed4d688297e0a5ca7 |
`func_extended` ZIR instructions now have a one of the unused flags used
as a `has_comptime_bits` boolean. When set, it means 1 or more
parameters are `comptime`. In this case, there is a u32 per every 32
parameters (usually just 1 u32) with each bit indicating whether the
corresponding parameter is `comptime`.
Sema uses this information to correctly mark generic functions as
generic. There is now a TODO compile error in place in case a generic
function call happens. A future commit will do the generic function call
implementation.4 files changed, 132 insertions(+), 6 deletions(-)
src/AstGen.zig+65-1| ... | @@ -1064,11 +1064,28 @@ fn fnProtoExpr( | ... | @@ -1064,11 +1064,28 @@ fn fnProtoExpr( |
| 1064 | const param_types = try gpa.alloc(Zir.Inst.Ref, param_count); | 1064 | const param_types = try gpa.alloc(Zir.Inst.Ref, param_count); |
| 1065 | defer gpa.free(param_types); | 1065 | defer gpa.free(param_types); |
| 1066 | 1066 | ||
| 1067 | const bits_per_param = 1; | ||
| 1068 | const params_per_u32 = 32 / bits_per_param; | ||
| 1069 | // We only need this if there are greater than params_per_u32 fields. | ||
| 1070 | var bit_bag = ArrayListUnmanaged(u32){}; | ||
| 1071 | defer bit_bag.deinit(gpa); | ||
| 1072 | var cur_bit_bag: u32 = 0; | ||
| 1067 | var is_var_args = false; | 1073 | var is_var_args = false; |
| 1068 | { | 1074 | { |
| 1069 | var param_type_i: usize = 0; | 1075 | var param_type_i: usize = 0; |
| 1070 | var it = fn_proto.iterate(tree.*); | 1076 | var it = fn_proto.iterate(tree.*); |
| 1071 | while (it.next()) |param| : (param_type_i += 1) { | 1077 | while (it.next()) |param| : (param_type_i += 1) { |
| 1078 | if (param_type_i % params_per_u32 == 0 and param_type_i != 0) { | ||
| 1079 | try bit_bag.append(gpa, cur_bit_bag); | ||
| 1080 | cur_bit_bag = 0; | ||
| 1081 | } | ||
| 1082 | const is_comptime = if (param.comptime_noalias) |token| | ||
| 1083 | token_tags[token] == .keyword_comptime | ||
| 1084 | else | ||
| 1085 | false; | ||
| 1086 | cur_bit_bag = (cur_bit_bag >> bits_per_param) | | ||
| 1087 | (@as(u32, @boolToInt(is_comptime)) << 31); | ||
| 1088 | |||
| 1072 | if (param.anytype_ellipsis3) |token| { | 1089 | if (param.anytype_ellipsis3) |token| { |
| 1073 | switch (token_tags[token]) { | 1090 | switch (token_tags[token]) { |
| 1074 | .keyword_anytype => { | 1091 | .keyword_anytype => { |
| ... | @@ -1088,6 +1105,11 @@ fn fnProtoExpr( | ... | @@ -1088,6 +1105,11 @@ fn fnProtoExpr( |
| 1088 | try expr(gz, scope, .{ .ty = .type_type }, param_type_node); | 1105 | try expr(gz, scope, .{ .ty = .type_type }, param_type_node); |
| 1089 | } | 1106 | } |
| 1090 | assert(param_type_i == param_count); | 1107 | assert(param_type_i == param_count); |
| 1108 | |||
| 1109 | const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32); | ||
| 1110 | if (empty_slot_count < params_per_u32) { | ||
| 1111 | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param); | ||
| 1112 | } | ||
| 1091 | } | 1113 | } |
| 1092 | 1114 | ||
| 1093 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { | 1115 | const align_inst: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { |
| ... | @@ -1131,6 +1153,8 @@ fn fnProtoExpr( | ... | @@ -1131,6 +1153,8 @@ fn fnProtoExpr( |
| 1131 | .is_inferred_error = false, | 1153 | .is_inferred_error = false, |
| 1132 | .is_test = false, | 1154 | .is_test = false, |
| 1133 | .is_extern = false, | 1155 | .is_extern = false, |
| 1156 | .cur_bit_bag = cur_bit_bag, | ||
| 1157 | .bit_bag = bit_bag.items, | ||
| 1134 | }); | 1158 | }); |
| 1135 | return rvalue(gz, rl, result, fn_proto.ast.proto_node); | 1159 | return rvalue(gz, rl, result, fn_proto.ast.proto_node); |
| 1136 | } | 1160 | } |
| ... | @@ -2916,11 +2940,28 @@ fn fnDecl( | ... | @@ -2916,11 +2940,28 @@ fn fnDecl( |
| 2916 | const param_types = try gpa.alloc(Zir.Inst.Ref, param_count); | 2940 | const param_types = try gpa.alloc(Zir.Inst.Ref, param_count); |
| 2917 | defer gpa.free(param_types); | 2941 | defer gpa.free(param_types); |
| 2918 | 2942 | ||
| 2943 | const bits_per_param = 1; | ||
| 2944 | const params_per_u32 = 32 / bits_per_param; | ||
| 2945 | // We only need this if there are greater than params_per_u32 fields. | ||
| 2946 | var bit_bag = ArrayListUnmanaged(u32){}; | ||
| 2947 | defer bit_bag.deinit(gpa); | ||
| 2948 | var cur_bit_bag: u32 = 0; | ||
| 2919 | var is_var_args = false; | 2949 | var is_var_args = false; |
| 2920 | { | 2950 | { |
| 2921 | var param_type_i: usize = 0; | 2951 | var param_type_i: usize = 0; |
| 2922 | var it = fn_proto.iterate(tree.*); | 2952 | var it = fn_proto.iterate(tree.*); |
| 2923 | while (it.next()) |param| : (param_type_i += 1) { | 2953 | while (it.next()) |param| : (param_type_i += 1) { |
| 2954 | if (param_type_i % params_per_u32 == 0 and param_type_i != 0) { | ||
| 2955 | try bit_bag.append(gpa, cur_bit_bag); | ||
| 2956 | cur_bit_bag = 0; | ||
| 2957 | } | ||
| 2958 | const is_comptime = if (param.comptime_noalias) |token| | ||
| 2959 | token_tags[token] == .keyword_comptime | ||
| 2960 | else | ||
| 2961 | false; | ||
| 2962 | cur_bit_bag = (cur_bit_bag >> bits_per_param) | | ||
| 2963 | (@as(u32, @boolToInt(is_comptime)) << 31); | ||
| 2964 | |||
| 2924 | if (param.anytype_ellipsis3) |token| { | 2965 | if (param.anytype_ellipsis3) |token| { |
| 2925 | switch (token_tags[token]) { | 2966 | switch (token_tags[token]) { |
| 2926 | .keyword_anytype => { | 2967 | .keyword_anytype => { |
| ... | @@ -2940,6 +2981,11 @@ fn fnDecl( | ... | @@ -2940,6 +2981,11 @@ fn fnDecl( |
| 2940 | try expr(&decl_gz, &decl_gz.base, .{ .ty = .type_type }, param_type_node); | 2981 | try expr(&decl_gz, &decl_gz.base, .{ .ty = .type_type }, param_type_node); |
| 2941 | } | 2982 | } |
| 2942 | assert(param_type_i == param_count); | 2983 | assert(param_type_i == param_count); |
| 2984 | |||
| 2985 | const empty_slot_count = params_per_u32 - (param_type_i % params_per_u32); | ||
| 2986 | if (empty_slot_count < params_per_u32) { | ||
| 2987 | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_param); | ||
| 2988 | } | ||
| 2943 | } | 2989 | } |
| 2944 | 2990 | ||
| 2945 | const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: { | 2991 | const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: { |
| ... | @@ -3001,6 +3047,8 @@ fn fnDecl( | ... | @@ -3001,6 +3047,8 @@ fn fnDecl( |
| 3001 | .is_inferred_error = false, | 3047 | .is_inferred_error = false, |
| 3002 | .is_test = false, | 3048 | .is_test = false, |
| 3003 | .is_extern = true, | 3049 | .is_extern = true, |
| 3050 | .cur_bit_bag = cur_bit_bag, | ||
| 3051 | .bit_bag = bit_bag.items, | ||
| 3004 | }); | 3052 | }); |
| 3005 | } else func: { | 3053 | } else func: { |
| 3006 | if (is_var_args) { | 3054 | if (is_var_args) { |
| ... | @@ -3094,6 +3142,8 @@ fn fnDecl( | ... | @@ -3094,6 +3142,8 @@ fn fnDecl( |
| 3094 | .is_inferred_error = is_inferred_error, | 3142 | .is_inferred_error = is_inferred_error, |
| 3095 | .is_test = false, | 3143 | .is_test = false, |
| 3096 | .is_extern = false, | 3144 | .is_extern = false, |
| 3145 | .cur_bit_bag = cur_bit_bag, | ||
| 3146 | .bit_bag = bit_bag.items, | ||
| 3097 | }); | 3147 | }); |
| 3098 | }; | 3148 | }; |
| 3099 | 3149 | ||
| ... | @@ -3439,6 +3489,8 @@ fn testDecl( | ... | @@ -3439,6 +3489,8 @@ fn testDecl( |
| 3439 | .is_inferred_error = true, | 3489 | .is_inferred_error = true, |
| 3440 | .is_test = true, | 3490 | .is_test = true, |
| 3441 | .is_extern = false, | 3491 | .is_extern = false, |
| 3492 | .cur_bit_bag = 0, | ||
| 3493 | .bit_bag = &.{}, | ||
| 3442 | }); | 3494 | }); |
| 3443 | 3495 | ||
| 3444 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); | 3496 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); |
| ... | @@ -9135,6 +9187,8 @@ const GenZir = struct { | ... | @@ -9135,6 +9187,8 @@ const GenZir = struct { |
| 9135 | is_inferred_error: bool, | 9187 | is_inferred_error: bool, |
| 9136 | is_test: bool, | 9188 | is_test: bool, |
| 9137 | is_extern: bool, | 9189 | is_extern: bool, |
| 9190 | cur_bit_bag: u32, | ||
| 9191 | bit_bag: []const u32, | ||
| 9138 | }) !Zir.Inst.Ref { | 9192 | }) !Zir.Inst.Ref { |
| 9139 | assert(args.src_node != 0); | 9193 | assert(args.src_node != 0); |
| 9140 | assert(args.ret_ty != .none); | 9194 | assert(args.ret_ty != .none); |
| ... | @@ -9172,13 +9226,18 @@ const GenZir = struct { | ... | @@ -9172,13 +9226,18 @@ const GenZir = struct { |
| 9172 | src_locs = &src_locs_buffer; | 9226 | src_locs = &src_locs_buffer; |
| 9173 | } | 9227 | } |
| 9174 | 9228 | ||
| 9229 | const any_are_comptime = args.cur_bit_bag != 0 or for (args.bit_bag) |x| { | ||
| 9230 | if (x != 0) break true; | ||
| 9231 | } else false; | ||
| 9232 | |||
| 9175 | if (args.cc != .none or args.lib_name != 0 or | 9233 | if (args.cc != .none or args.lib_name != 0 or |
| 9176 | args.is_var_args or args.is_test or args.align_inst != .none or | 9234 | args.is_var_args or args.is_test or args.align_inst != .none or |
| 9177 | args.is_extern) | 9235 | args.is_extern or any_are_comptime) |
| 9178 | { | 9236 | { |
| 9179 | try astgen.extra.ensureUnusedCapacity( | 9237 | try astgen.extra.ensureUnusedCapacity( |
| 9180 | gpa, | 9238 | gpa, |
| 9181 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + | 9239 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + |
| 9240 | @boolToInt(any_are_comptime) + args.bit_bag.len + | ||
| 9182 | args.param_types.len + args.body.len + src_locs.len + | 9241 | args.param_types.len + args.body.len + src_locs.len + |
| 9183 | @boolToInt(args.lib_name != 0) + | 9242 | @boolToInt(args.lib_name != 0) + |
| 9184 | @boolToInt(args.align_inst != .none) + | 9243 | @boolToInt(args.align_inst != .none) + |
| ... | @@ -9199,6 +9258,10 @@ const GenZir = struct { | ... | @@ -9199,6 +9258,10 @@ const GenZir = struct { |
| 9199 | if (args.align_inst != .none) { | 9258 | if (args.align_inst != .none) { |
| 9200 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); | 9259 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); |
| 9201 | } | 9260 | } |
| 9261 | if (any_are_comptime) { | ||
| 9262 | astgen.extra.appendSliceAssumeCapacity(args.bit_bag); // Likely empty. | ||
| 9263 | astgen.extra.appendAssumeCapacity(args.cur_bit_bag); | ||
| 9264 | } | ||
| 9202 | astgen.appendRefsAssumeCapacity(args.param_types); | 9265 | astgen.appendRefsAssumeCapacity(args.param_types); |
| 9203 | astgen.extra.appendSliceAssumeCapacity(args.body); | 9266 | astgen.extra.appendSliceAssumeCapacity(args.body); |
| 9204 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 9267 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| ... | @@ -9216,6 +9279,7 @@ const GenZir = struct { | ... | @@ -9216,6 +9279,7 @@ const GenZir = struct { |
| 9216 | .has_align = args.align_inst != .none, | 9279 | .has_align = args.align_inst != .none, |
| 9217 | .is_test = args.is_test, | 9280 | .is_test = args.is_test, |
| 9218 | .is_extern = args.is_extern, | 9281 | .is_extern = args.is_extern, |
| 9282 | .has_comptime_bits = any_are_comptime, | ||
| 9219 | }), | 9283 | }), |
| 9220 | .operand = payload_index, | 9284 | .operand = payload_index, |
| 9221 | } }, | 9285 | } }, |
src/Sema.zig+28-1| ... | @@ -104,6 +104,9 @@ pub fn analyzeFnBody( | ... | @@ -104,6 +104,9 @@ pub fn analyzeFnBody( |
| 104 | extra_index += @boolToInt(small.has_lib_name); | 104 | extra_index += @boolToInt(small.has_lib_name); |
| 105 | extra_index += @boolToInt(small.has_cc); | 105 | extra_index += @boolToInt(small.has_cc); |
| 106 | extra_index += @boolToInt(small.has_align); | 106 | extra_index += @boolToInt(small.has_align); |
| 107 | if (small.has_comptime_bits) { | ||
| 108 | extra_index += (extra.data.param_types_len + 31) / 32; | ||
| 109 | } | ||
| 107 | extra_index += extra.data.param_types_len; | 110 | extra_index += extra.data.param_types_len; |
| 108 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; | 111 | const body = sema.code.extra[extra_index..][0..extra.data.body_len]; |
| 109 | break :blk body; | 112 | break :blk body; |
| ... | @@ -2533,6 +2536,9 @@ fn analyzeCall( | ... | @@ -2533,6 +2536,9 @@ fn analyzeCall( |
| 2533 | 2536 | ||
| 2534 | break :res result; | 2537 | break :res result; |
| 2535 | } else res: { | 2538 | } else res: { |
| 2539 | if (func_ty.fnIsGeneric()) { | ||
| 2540 | return sema.mod.fail(&block.base, func_src, "TODO implement generic fn call", .{}); | ||
| 2541 | } | ||
| 2536 | try sema.requireRuntimeBlock(block, call_src); | 2542 | try sema.requireRuntimeBlock(block, call_src); |
| 2537 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + | 2543 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 2538 | args.len); | 2544 | args.len); |
| ... | @@ -3208,6 +3214,7 @@ fn zirFunc( | ... | @@ -3208,6 +3214,7 @@ fn zirFunc( |
| 3208 | false, | 3214 | false, |
| 3209 | src_locs, | 3215 | src_locs, |
| 3210 | null, | 3216 | null, |
| 3217 | &.{}, | ||
| 3211 | ); | 3218 | ); |
| 3212 | } | 3219 | } |
| 3213 | 3220 | ||
| ... | @@ -3225,6 +3232,7 @@ fn funcCommon( | ... | @@ -3225,6 +3232,7 @@ fn funcCommon( |
| 3225 | is_extern: bool, | 3232 | is_extern: bool, |
| 3226 | src_locs: Zir.Inst.Func.SrcLocs, | 3233 | src_locs: Zir.Inst.Func.SrcLocs, |
| 3227 | opt_lib_name: ?[]const u8, | 3234 | opt_lib_name: ?[]const u8, |
| 3235 | comptime_bits: []const u32, | ||
| 3228 | ) CompileError!Air.Inst.Ref { | 3236 | ) CompileError!Air.Inst.Ref { |
| 3229 | const src: LazySrcLoc = .{ .node_offset = src_node_offset }; | 3237 | const src: LazySrcLoc = .{ .node_offset = src_node_offset }; |
| 3230 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; | 3238 | const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset }; |
| ... | @@ -3257,13 +3265,23 @@ fn funcCommon( | ... | @@ -3257,13 +3265,23 @@ fn funcCommon( |
| 3257 | } | 3265 | } |
| 3258 | } | 3266 | } |
| 3259 | 3267 | ||
| 3268 | var any_are_comptime = false; | ||
| 3260 | const param_types = try sema.arena.alloc(Type, zir_param_types.len); | 3269 | const param_types = try sema.arena.alloc(Type, zir_param_types.len); |
| 3261 | for (zir_param_types) |param_type, i| { | 3270 | for (zir_param_types) |param_type, i| { |
| 3262 | // TODO make a compile error from `resolveType` report the source location | 3271 | // TODO make a compile error from `resolveType` report the source location |
| 3263 | // of the specific parameter. Will need to take a similar strategy as | 3272 | // of the specific parameter. Will need to take a similar strategy as |
| 3264 | // `resolveSwitchItemVal` to avoid resolving the source location unless | 3273 | // `resolveSwitchItemVal` to avoid resolving the source location unless |
| 3265 | // we actually need to report an error. | 3274 | // we actually need to report an error. |
| 3266 | param_types[i] = try sema.resolveType(block, src, param_type); | 3275 | const param_src = src; |
| 3276 | param_types[i] = try sema.resolveType(block, param_src, param_type); | ||
| 3277 | |||
| 3278 | any_are_comptime = any_are_comptime or blk: { | ||
| 3279 | if (comptime_bits.len == 0) | ||
| 3280 | break :blk false; | ||
| 3281 | const bag = comptime_bits[i / 32]; | ||
| 3282 | const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0; | ||
| 3283 | break :blk is_comptime; | ||
| 3284 | }; | ||
| 3267 | } | 3285 | } |
| 3268 | 3286 | ||
| 3269 | if (align_val.tag() != .null_value) { | 3287 | if (align_val.tag() != .null_value) { |
| ... | @@ -3286,6 +3304,7 @@ fn funcCommon( | ... | @@ -3286,6 +3304,7 @@ fn funcCommon( |
| 3286 | .return_type = return_type, | 3304 | .return_type = return_type, |
| 3287 | .cc = cc, | 3305 | .cc = cc, |
| 3288 | .is_var_args = var_args, | 3306 | .is_var_args = var_args, |
| 3307 | .is_generic = any_are_comptime, | ||
| 3289 | }); | 3308 | }); |
| 3290 | }; | 3309 | }; |
| 3291 | 3310 | ||
| ... | @@ -6526,6 +6545,13 @@ fn zirFuncExtended( | ... | @@ -6526,6 +6545,13 @@ fn zirFuncExtended( |
| 6526 | break :blk align_tv.val; | 6545 | break :blk align_tv.val; |
| 6527 | } else Value.initTag(.null_value); | 6546 | } else Value.initTag(.null_value); |
| 6528 | 6547 | ||
| 6548 | const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: { | ||
| 6549 | const amt = (extra.data.param_types_len + 31) / 32; | ||
| 6550 | const bit_bags = sema.code.extra[extra_index..][0..amt]; | ||
| 6551 | extra_index += amt; | ||
| 6552 | break :blk bit_bags; | ||
| 6553 | }; | ||
| 6554 | |||
| 6529 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); | 6555 | const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len); |
| 6530 | extra_index += param_types.len; | 6556 | extra_index += param_types.len; |
| 6531 | 6557 | ||
| ... | @@ -6554,6 +6580,7 @@ fn zirFuncExtended( | ... | @@ -6554,6 +6580,7 @@ fn zirFuncExtended( |
| 6554 | is_extern, | 6580 | is_extern, |
| 6555 | src_locs, | 6581 | src_locs, |
| 6556 | lib_name, | 6582 | lib_name, |
| 6583 | comptime_bits, | ||
| 6557 | ); | 6584 | ); |
| 6558 | } | 6585 | } |
| 6559 | 6586 |
src/Zir.zig+24-4| ... | @@ -2226,9 +2226,13 @@ pub const Inst = struct { | ... | @@ -2226,9 +2226,13 @@ pub const Inst = struct { |
| 2226 | /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set | 2226 | /// 0. lib_name: u32, // null terminated string index, if has_lib_name is set |
| 2227 | /// 1. cc: Ref, // if has_cc is set | 2227 | /// 1. cc: Ref, // if has_cc is set |
| 2228 | /// 2. align: Ref, // if has_align is set | 2228 | /// 2. align: Ref, // if has_align is set |
| 2229 | /// 3. param_type: Ref // for each param_types_len | 2229 | /// 3. comptime_bits: u32 // for every 32 parameters, if has_comptime_bits is set |
| 2230 | /// 4. body: Index // for each body_len | 2230 | /// - sets of 1 bit: |
| 2231 | /// 5. src_locs: Func.SrcLocs // if body_len != 0 | 2231 | /// 0bX: whether corresponding parameter is comptime |
| 2232 | /// 4. param_type: Ref // for each param_types_len | ||
| 2233 | /// - `none` indicates that the param type is `anytype`. | ||
| 2234 | /// 5. body: Index // for each body_len | ||
| 2235 | /// 6. src_locs: Func.SrcLocs // if body_len != 0 | ||
| 2232 | pub const ExtendedFunc = struct { | 2236 | pub const ExtendedFunc = struct { |
| 2233 | src_node: i32, | 2237 | src_node: i32, |
| 2234 | return_type: Ref, | 2238 | return_type: Ref, |
| ... | @@ -2243,7 +2247,8 @@ pub const Inst = struct { | ... | @@ -2243,7 +2247,8 @@ pub const Inst = struct { |
| 2243 | has_align: bool, | 2247 | has_align: bool, |
| 2244 | is_test: bool, | 2248 | is_test: bool, |
| 2245 | is_extern: bool, | 2249 | is_extern: bool, |
| 2246 | _: u9 = undefined, | 2250 | has_comptime_bits: bool, |
| 2251 | _: u8 = undefined, | ||
| 2247 | }; | 2252 | }; |
| 2248 | }; | 2253 | }; |
| 2249 | 2254 | ||
| ... | @@ -4291,6 +4296,7 @@ const Writer = struct { | ... | @@ -4291,6 +4296,7 @@ const Writer = struct { |
| 4291 | body, | 4296 | body, |
| 4292 | src, | 4297 | src, |
| 4293 | src_locs, | 4298 | src_locs, |
| 4299 | &.{}, | ||
| 4294 | ); | 4300 | ); |
| 4295 | } | 4301 | } |
| 4296 | 4302 | ||
| ... | @@ -4317,6 +4323,13 @@ const Writer = struct { | ... | @@ -4317,6 +4323,13 @@ const Writer = struct { |
| 4317 | break :blk align_inst; | 4323 | break :blk align_inst; |
| 4318 | }; | 4324 | }; |
| 4319 | 4325 | ||
| 4326 | const comptime_bits: []const u32 = if (!small.has_comptime_bits) &.{} else blk: { | ||
| 4327 | const amt = (extra.data.param_types_len + 31) / 32; | ||
| 4328 | const bit_bags = self.code.extra[extra_index..][0..amt]; | ||
| 4329 | extra_index += amt; | ||
| 4330 | break :blk bit_bags; | ||
| 4331 | }; | ||
| 4332 | |||
| 4320 | const param_types = self.code.refSlice(extra_index, extra.data.param_types_len); | 4333 | const param_types = self.code.refSlice(extra_index, extra.data.param_types_len); |
| 4321 | extra_index += param_types.len; | 4334 | extra_index += param_types.len; |
| 4322 | 4335 | ||
| ... | @@ -4339,6 +4352,7 @@ const Writer = struct { | ... | @@ -4339,6 +4352,7 @@ const Writer = struct { |
| 4339 | body, | 4352 | body, |
| 4340 | src, | 4353 | src, |
| 4341 | src_locs, | 4354 | src_locs, |
| 4355 | comptime_bits, | ||
| 4342 | ); | 4356 | ); |
| 4343 | } | 4357 | } |
| 4344 | 4358 | ||
| ... | @@ -4422,10 +4436,16 @@ const Writer = struct { | ... | @@ -4422,10 +4436,16 @@ const Writer = struct { |
| 4422 | body: []const Inst.Index, | 4436 | body: []const Inst.Index, |
| 4423 | src: LazySrcLoc, | 4437 | src: LazySrcLoc, |
| 4424 | src_locs: Zir.Inst.Func.SrcLocs, | 4438 | src_locs: Zir.Inst.Func.SrcLocs, |
| 4439 | comptime_bits: []const u32, | ||
| 4425 | ) !void { | 4440 | ) !void { |
| 4426 | try stream.writeAll("["); | 4441 | try stream.writeAll("["); |
| 4427 | for (param_types) |param_type, i| { | 4442 | for (param_types) |param_type, i| { |
| 4428 | if (i != 0) try stream.writeAll(", "); | 4443 | if (i != 0) try stream.writeAll(", "); |
| 4444 | if (comptime_bits.len != 0) { | ||
| 4445 | const bag = comptime_bits[i / 32]; | ||
| 4446 | const is_comptime = @truncate(u1, bag >> @intCast(u5, i % 32)) != 0; | ||
| 4447 | try self.writeFlag(stream, "comptime ", is_comptime); | ||
| 4448 | } | ||
| 4429 | try self.writeInstRef(stream, param_type); | 4449 | try self.writeInstRef(stream, param_type); |
| 4430 | } | 4450 | } |
| 4431 | try stream.writeAll("], "); | 4451 | try stream.writeAll("], "); |
src/type.zig+15| ... | @@ -764,6 +764,7 @@ pub const Type = extern union { | ... | @@ -764,6 +764,7 @@ pub const Type = extern union { |
| 764 | .param_types = param_types, | 764 | .param_types = param_types, |
| 765 | .cc = payload.cc, | 765 | .cc = payload.cc, |
| 766 | .is_var_args = payload.is_var_args, | 766 | .is_var_args = payload.is_var_args, |
| 767 | .is_generic = payload.is_generic, | ||
| 767 | }); | 768 | }); |
| 768 | }, | 769 | }, |
| 769 | .pointer => { | 770 | .pointer => { |
| ... | @@ -2407,6 +2408,19 @@ pub const Type = extern union { | ... | @@ -2407,6 +2408,19 @@ pub const Type = extern union { |
| 2407 | }; | 2408 | }; |
| 2408 | } | 2409 | } |
| 2409 | 2410 | ||
| 2411 | /// Asserts the type is a function. | ||
| 2412 | pub fn fnIsGeneric(self: Type) bool { | ||
| 2413 | return switch (self.tag()) { | ||
| 2414 | .fn_noreturn_no_args => false, | ||
| 2415 | .fn_void_no_args => false, | ||
| 2416 | .fn_naked_noreturn_no_args => false, | ||
| 2417 | .fn_ccc_void_no_args => false, | ||
| 2418 | .function => self.castTag(.function).?.data.is_generic, | ||
| 2419 | |||
| 2420 | else => unreachable, | ||
| 2421 | }; | ||
| 2422 | } | ||
| 2423 | |||
| 2410 | pub fn isNumeric(self: Type) bool { | 2424 | pub fn isNumeric(self: Type) bool { |
| 2411 | return switch (self.tag()) { | 2425 | return switch (self.tag()) { |
| 2412 | .f16, | 2426 | .f16, |
| ... | @@ -3214,6 +3228,7 @@ pub const Type = extern union { | ... | @@ -3214,6 +3228,7 @@ pub const Type = extern union { |
| 3214 | return_type: Type, | 3228 | return_type: Type, |
| 3215 | cc: std.builtin.CallingConvention, | 3229 | cc: std.builtin.CallingConvention, |
| 3216 | is_var_args: bool, | 3230 | is_var_args: bool, |
| 3231 | is_generic: bool, | ||
| 3217 | }, | 3232 | }, |
| 3218 | }; | 3233 | }; |
| 3219 | 3234 |