| ... | @@ -163,36 +163,36 @@ pub fn analyzeBody( | ... | @@ -163,36 +163,36 @@ pub fn analyzeBody( |
| 163 | const air_inst: Air.Inst.Ref = switch (tags[inst]) { | 163 | const air_inst: Air.Inst.Ref = switch (tags[inst]) { |
| 164 | // zig fmt: off | 164 | // zig fmt: off |
| 165 | .arg => try sema.zirArg(block, inst), | 165 | .arg => try sema.zirArg(block, inst), |
| 166 | //.alloc => try sema.zirAlloc(block, inst), | 166 | .alloc => try sema.zirAlloc(block, inst), |
| 167 | //.alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)), | 167 | .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)), |
| 168 | //.alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)), | 168 | .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)), |
| 169 | //.alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst), | 169 | .alloc_inferred_comptime => try sema.zirAllocInferredComptime(block, inst), |
| 170 | //.alloc_mut => try sema.zirAllocMut(block, inst), | 170 | .alloc_mut => try sema.zirAllocMut(block, inst), |
| 171 | //.alloc_comptime => try sema.zirAllocComptime(block, inst), | 171 | .alloc_comptime => try sema.zirAllocComptime(block, inst), |
| 172 | //.anyframe_type => try sema.zirAnyframeType(block, inst), | 172 | .anyframe_type => try sema.zirAnyframeType(block, inst), |
| 173 | //.array_cat => try sema.zirArrayCat(block, inst), | 173 | .array_cat => try sema.zirArrayCat(block, inst), |
| 174 | //.array_mul => try sema.zirArrayMul(block, inst), | 174 | .array_mul => try sema.zirArrayMul(block, inst), |
| 175 | //.array_type => try sema.zirArrayType(block, inst), | 175 | .array_type => try sema.zirArrayType(block, inst), |
| 176 | //.array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), | 176 | .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), |
| 177 | //.vector_type => try sema.zirVectorType(block, inst), | 177 | .vector_type => try sema.zirVectorType(block, inst), |
| 178 | //.as => try sema.zirAs(block, inst), | 178 | .as => try sema.zirAs(block, inst), |
| 179 | //.as_node => try sema.zirAsNode(block, inst), | 179 | .as_node => try sema.zirAsNode(block, inst), |
| 180 | //.bit_and => try sema.zirBitwise(block, inst, .bit_and), | 180 | .bit_and => try sema.zirBitwise(block, inst, .bit_and), |
| 181 | //.bit_not => try sema.zirBitNot(block, inst), | 181 | .bit_not => try sema.zirBitNot(block, inst), |
| 182 | //.bit_or => try sema.zirBitwise(block, inst, .bit_or), | 182 | .bit_or => try sema.zirBitwise(block, inst, .bit_or), |
| 183 | //.bitcast => try sema.zirBitcast(block, inst), | 183 | .bitcast => try sema.zirBitcast(block, inst), |
| 184 | //.bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst), | 184 | .bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst), |
| 185 | //.block => try sema.zirBlock(block, inst), | 185 | .block => try sema.zirBlock(block, inst), |
| 186 | //.suspend_block => try sema.zirSuspendBlock(block, inst), | 186 | .suspend_block => try sema.zirSuspendBlock(block, inst), |
| 187 | //.bool_not => try sema.zirBoolNot(block, inst), | 187 | .bool_not => try sema.zirBoolNot(block, inst), |
| 188 | //.bool_br_and => try sema.zirBoolBr(block, inst, false), | 188 | .bool_br_and => try sema.zirBoolBr(block, inst, false), |
| 189 | //.bool_br_or => try sema.zirBoolBr(block, inst, true), | 189 | .bool_br_or => try sema.zirBoolBr(block, inst, true), |
| 190 | //.c_import => try sema.zirCImport(block, inst), | 190 | .c_import => try sema.zirCImport(block, inst), |
| 191 | //.call => try sema.zirCall(block, inst, .auto, false), | 191 | .call => try sema.zirCall(block, inst, .auto, false), |
| 192 | //.call_chkused => try sema.zirCall(block, inst, .auto, true), | 192 | .call_chkused => try sema.zirCall(block, inst, .auto, true), |
| 193 | //.call_compile_time => try sema.zirCall(block, inst, .compile_time, false), | 193 | .call_compile_time => try sema.zirCall(block, inst, .compile_time, false), |
| 194 | //.call_nosuspend => try sema.zirCall(block, inst, .no_async, false), | 194 | .call_nosuspend => try sema.zirCall(block, inst, .no_async, false), |
| 195 | //.call_async => try sema.zirCall(block, inst, .async_kw, false), | 195 | .call_async => try sema.zirCall(block, inst, .async_kw, false), |
| 196 | .cmp_eq => try sema.zirCmp(block, inst, .eq), | 196 | .cmp_eq => try sema.zirCmp(block, inst, .eq), |
| 197 | .cmp_gt => try sema.zirCmp(block, inst, .gt), | 197 | .cmp_gt => try sema.zirCmp(block, inst, .gt), |
| 198 | .cmp_gte => try sema.zirCmp(block, inst, .gte), | 198 | .cmp_gte => try sema.zirCmp(block, inst, .gte), |
| ... | @@ -1957,24 +1957,23 @@ fn analyzeBlockBody( | ... | @@ -1957,24 +1957,23 @@ fn analyzeBlockBody( |
| 1957 | | 1957 | |
| 1958 | // Blocks must terminate with noreturn instruction. | 1958 | // Blocks must terminate with noreturn instruction. |
| 1959 | assert(child_block.instructions.items.len != 0); | 1959 | assert(child_block.instructions.items.len != 0); |
| 1960 | assert(child_block.instructions.items[child_block.instructions.items.len - 1].ty.isNoReturn()); | 1960 | assert(sema.getTypeOf(indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1])).isNoReturn()); |
| 1961 | | 1961 | |
| 1962 | if (merges.results.items.len == 0) { | 1962 | if (merges.results.items.len == 0) { |
| 1963 | // No need for a block instruction. We can put the new instructions | 1963 | // No need for a block instruction. We can put the new instructions |
| 1964 | // directly into the parent block. | 1964 | // directly into the parent block. |
| 1965 | const copied_instructions = try sema.arena.dupe(Air.Inst.Index, child_block.instructions.items); | 1965 | try parent_block.instructions.appendSlice(gpa, child_block.instructions.items); |
| 1966 | try parent_block.instructions.appendSlice(gpa, copied_instructions); | 1966 | return indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1]); |
| 1967 | return copied_instructions[copied_instructions.len - 1]; | | |
| 1968 | } | 1967 | } |
| 1969 | if (merges.results.items.len == 1) { | 1968 | if (merges.results.items.len == 1) { |
| 1970 | const last_inst_index = child_block.instructions.items.len - 1; | 1969 | const last_inst_index = child_block.instructions.items.len - 1; |
| 1971 | const last_inst = child_block.instructions.items[last_inst_index]; | 1970 | const last_inst = child_block.instructions.items[last_inst_index]; |
| 1972 | if (last_inst.breakBlock()) |br_block| { | 1971 | if (sema.getBreakBlock(last_inst)) |br_block| { |
| 1973 | if (br_block == merges.block_inst) { | 1972 | if (br_block == merges.block_inst) { |
| 1974 | // No need for a block instruction. We can put the new instructions directly | 1973 | // No need for a block instruction. We can put the new instructions directly |
| 1975 | // into the parent block. Here we omit the break instruction. | 1974 | // into the parent block. Here we omit the break instruction. |
| 1976 | const copied_instructions = try sema.arena.dupe(Air.Inst.Index, child_block.instructions.items[0..last_inst_index]); | 1975 | const without_break = child_block.instructions.items[0..last_inst_index]; |
| 1977 | try parent_block.instructions.appendSlice(gpa, copied_instructions); | 1976 | try parent_block.instructions.appendSlice(gpa, without_break); |
| 1978 | return merges.results.items[0]; | 1977 | return merges.results.items[0]; |
| 1979 | } | 1978 | } |
| 1980 | } | 1979 | } |
| ... | @@ -1998,36 +1997,50 @@ fn analyzeBlockBody( | ... | @@ -1998,36 +1997,50 @@ fn analyzeBlockBody( |
| 1998 | // Now that the block has its type resolved, we need to go back into all the break | 1997 | // Now that the block has its type resolved, we need to go back into all the break |
| 1999 | // instructions, and insert type coercion on the operands. | 1998 | // instructions, and insert type coercion on the operands. |
| 2000 | for (merges.br_list.items) |br| { | 1999 | for (merges.br_list.items) |br| { |
| 2001 | if (sema.getTypeOf(br.operand).eql(resolved_ty)) { | 2000 | const br_operand = sema.air_instructions.items(.data)[br].br.operand; |
| | 2001 | const br_operand_src = src; |
| | 2002 | const br_operand_ty = sema.getTypeOf(br_operand); |
| | 2003 | if (br_operand_ty.eql(resolved_ty)) { |
| 2002 | // No type coercion needed. | 2004 | // No type coercion needed. |
| 2003 | continue; | 2005 | continue; |
| 2004 | } | 2006 | } |
| 2005 | var coerce_block = parent_block.makeSubBlock(); | 2007 | var coerce_block = parent_block.makeSubBlock(); |
| 2006 | defer coerce_block.instructions.deinit(gpa); | 2008 | defer coerce_block.instructions.deinit(gpa); |
| 2007 | const coerced_operand = try sema.coerce(&coerce_block, resolved_ty, br.operand, br.operand.src); | 2009 | const coerced_operand = try sema.coerce(&coerce_block, resolved_ty, br_operand, br_operand_src); |
| 2008 | // If no instructions were produced, such as in the case of a coercion of a | 2010 | // If no instructions were produced, such as in the case of a coercion of a |
| 2009 | // constant value to a new type, we can simply point the br operand to it. | 2011 | // constant value to a new type, we can simply point the br operand to it. |
| 2010 | if (coerce_block.instructions.items.len == 0) { | 2012 | if (coerce_block.instructions.items.len == 0) { |
| 2011 | br.operand = coerced_operand; | 2013 | sema.air_instructions.items(.data)[br].br.operand = coerced_operand; |
| 2012 | continue; | 2014 | continue; |
| 2013 | } | 2015 | } |
| 2014 | assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] == coerced_operand); | 2016 | assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] == |
| 2015 | // Here we depend on the br instruction having been over-allocated (if necessary) | 2017 | refToIndex(coerced_operand).?); |
| 2016 | // inside zirBreak so that it can be converted into a br_block_flat instruction. | 2018 | |
| 2017 | const br_src = br.base.src; | 2019 | // Convert the br operand to a block. |
| 2018 | const br_ty = br.base.ty; | 2020 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len + |
| 2019 | const br_block_flat = @ptrCast(*Inst.BrBlockFlat, br); | 2021 | coerce_block.instructions.items.len); |
| 2020 | br_block_flat.* = .{ | 2022 | try sema.air_instructions.ensureUnusedCapacity(gpa, 2); |
| 2021 | .base = .{ | 2023 | const sub_block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); |
| 2022 | .src = br_src, | 2024 | const sub_br_inst = sub_block_inst + 1; |
| 2023 | .ty = br_ty, | 2025 | sema.air_instructions.items(.data)[br].br.operand = indexToRef(sub_block_inst); |
| 2024 | .tag = .br_block_flat, | 2026 | sema.air_instructions.appendAssumeCapacity(.{ |
| 2025 | }, | 2027 | .tag = .block, |
| 2026 | .block = merges.block_inst, | 2028 | .data = .{ .ty_pl = .{ |
| 2027 | .body = .{ | 2029 | .ty = try sema.addType(br_operand_ty), |
| 2028 | .instructions = try sema.arena.dupe(Air.Inst.Index, coerce_block.instructions.items), | 2030 | .payload = sema.addExtraAssumeCapacity(Air.Block{ |
| 2029 | }, | 2031 | .body_len = @intCast(u32, coerce_block.instructions.items.len), |
| 2030 | }; | 2032 | }), |
| | 2033 | } }, |
| | 2034 | }); |
| | 2035 | sema.air_extra.appendSliceAssumeCapacity(coerce_block.instructions.items); |
| | 2036 | sema.air_extra.appendAssumeCapacity(sub_br_inst); |
| | 2037 | sema.air_instructions.appendAssumeCapacity(.{ |
| | 2038 | .tag = .br, |
| | 2039 | .data = .{ .br = .{ |
| | 2040 | .block_inst = sub_block_inst, |
| | 2041 | .operand = coerced_operand, |
| | 2042 | } }, |
| | 2043 | }); |
| 2031 | } | 2044 | } |
| 2032 | return indexToRef(merges.block_inst); | 2045 | return indexToRef(merges.block_inst); |
| 2033 | } | 2046 | } |
| ... | @@ -2257,10 +2270,11 @@ fn analyzeCall( | ... | @@ -2257,10 +2270,11 @@ fn analyzeCall( |
| 2257 | ensure_result_used: bool, | 2270 | ensure_result_used: bool, |
| 2258 | args: []const Air.Inst.Ref, | 2271 | args: []const Air.Inst.Ref, |
| 2259 | ) CompileError!Air.Inst.Ref { | 2272 | ) CompileError!Air.Inst.Ref { |
| 2260 | if (func.ty.zigTypeTag() != .Fn) | 2273 | const func_ty = sema.getTypeOf(func); |
| 2261 | return sema.mod.fail(&block.base, func_src, "type '{}' not a function", .{func.ty}); | 2274 | if (func_ty.zigTypeTag() != .Fn) |
| | 2275 | return sema.mod.fail(&block.base, func_src, "type '{}' not a function", .{func_ty}); |
| 2262 | | 2276 | |
| 2263 | const cc = func.ty.fnCallingConvention(); | 2277 | const cc = func_ty.fnCallingConvention(); |
| 2264 | if (cc == .Naked) { | 2278 | if (cc == .Naked) { |
| 2265 | // TODO add error note: declared here | 2279 | // TODO add error note: declared here |
| 2266 | return sema.mod.fail( | 2280 | return sema.mod.fail( |
| ... | @@ -2270,8 +2284,8 @@ fn analyzeCall( | ... | @@ -2270,8 +2284,8 @@ fn analyzeCall( |
| 2270 | .{}, | 2284 | .{}, |
| 2271 | ); | 2285 | ); |
| 2272 | } | 2286 | } |
| 2273 | const fn_params_len = func.ty.fnParamLen(); | 2287 | const fn_params_len = func_ty.fnParamLen(); |
| 2274 | if (func.ty.fnIsVarArgs()) { | 2288 | if (func_ty.fnIsVarArgs()) { |
| 2275 | assert(cc == .C); | 2289 | assert(cc == .C); |
| 2276 | if (args.len < fn_params_len) { | 2290 | if (args.len < fn_params_len) { |
| 2277 | // TODO add error note: declared here | 2291 | // TODO add error note: declared here |
| ... | @@ -2310,11 +2324,9 @@ fn analyzeCall( | ... | @@ -2310,11 +2324,9 @@ fn analyzeCall( |
| 2310 | | 2324 | |
| 2311 | const gpa = sema.gpa; | 2325 | const gpa = sema.gpa; |
| 2312 | | 2326 | |
| 2313 | const ret_type = func.ty.fnReturnType(); | | |
| 2314 | | | |
| 2315 | const is_comptime_call = block.is_comptime or modifier == .compile_time; | 2327 | const is_comptime_call = block.is_comptime or modifier == .compile_time; |
| 2316 | const is_inline_call = is_comptime_call or modifier == .always_inline or | 2328 | const is_inline_call = is_comptime_call or modifier == .always_inline or |
| 2317 | func.ty.fnCallingConvention() == .Inline; | 2329 | func_ty.fnCallingConvention() == .Inline; |
| 2318 | const result: Air.Inst.Ref = if (is_inline_call) res: { | 2330 | const result: Air.Inst.Ref = if (is_inline_call) res: { |
| 2319 | const func_val = try sema.resolveConstValue(block, func_src, func); | 2331 | const func_val = try sema.resolveConstValue(block, func_src, func); |
| 2320 | const module_fn = switch (func_val.tag()) { | 2332 | const module_fn = switch (func_val.tag()) { |
| ... | @@ -2400,7 +2412,19 @@ fn analyzeCall( | ... | @@ -2400,7 +2412,19 @@ fn analyzeCall( |
| 2400 | break :res result; | 2412 | break :res result; |
| 2401 | } else res: { | 2413 | } else res: { |
| 2402 | try sema.requireRuntimeBlock(block, call_src); | 2414 | try sema.requireRuntimeBlock(block, call_src); |
| 2403 | break :res try block.addCall(call_src, ret_type, func, args); | 2415 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len + |
| | 2416 | args.len); |
| | 2417 | const func_inst = try block.addInst(.{ |
| | 2418 | .tag = .call, |
| | 2419 | .data = .{ .pl_op = .{ |
| | 2420 | .operand = func, |
| | 2421 | .payload = sema.addExtraAssumeCapacity(Air.Call{ |
| | 2422 | .args_len = @intCast(u32, args.len), |
| | 2423 | }), |
| | 2424 | } }, |
| | 2425 | }); |
| | 2426 | sema.appendRefsAssumeCapacity(args); |
| | 2427 | break :res func_inst; |
| 2404 | }; | 2428 | }; |
| 2405 | | 2429 | |
| 2406 | if (ensure_result_used) { | 2430 | if (ensure_result_used) { |
| ... | @@ -8140,3 +8164,17 @@ pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 { | ... | @@ -8140,3 +8164,17 @@ pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 { |
| 8140 | } | 8164 | } |
| 8141 | return result; | 8165 | return result; |
| 8142 | } | 8166 | } |
| | 8167 | |
| | 8168 | fn appendRefsAssumeCapacity(sema: *Sema, refs: []const Air.Inst.Ref) void { |
| | 8169 | const coerced = @bitCast([]const u32, refs); |
| | 8170 | sema.air_extra.appendSliceAssumeCapacity(coerced); |
| | 8171 | } |
| | 8172 | |
| | 8173 | fn getBreakBlock(sema: *Sema, inst_index: Air.Inst.Index) ?Air.Inst.Index { |
| | 8174 | const air_datas = sema.air_instructions.items(.data); |
| | 8175 | const air_tags = sema.air_instructions.items(.tag); |
| | 8176 | switch (air_tags[inst_index]) { |
| | 8177 | .br => return air_datas[inst_index].br.block_inst, |
| | 8178 | else => return null, |
| | 8179 | } |
| | 8180 | } |