| ... | @@ -41,6 +41,8 @@ fn_block: ?*GenZir = null, | ... | @@ -41,6 +41,8 @@ fn_block: ?*GenZir = null, |
| 41 | /// Maps string table indexes to the first `@import` ZIR instruction | 41 | /// Maps string table indexes to the first `@import` ZIR instruction |
| 42 | /// that uses this string as the operand. | 42 | /// that uses this string as the operand. |
| 43 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, | 43 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, |
| | 44 | /// Used for temporary storage when building payloads. |
| | 45 | scratch: std.ArrayListUnmanaged(u32) = .{}, |
| 44 | | 46 | |
| 45 | const InnerError = error{ OutOfMemory, AnalysisFail }; | 47 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 46 | | 48 | |
| ... | @@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { | ... | @@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { |
| 53 | fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { | 55 | fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 54 | const fields = std.meta.fields(@TypeOf(extra)); | 56 | const fields = std.meta.fields(@TypeOf(extra)); |
| 55 | const result = @intCast(u32, astgen.extra.items.len); | 57 | const result = @intCast(u32, astgen.extra.items.len); |
| | 58 | astgen.extra.items.len += fields.len; |
| | 59 | setExtra(astgen, result, extra); |
| | 60 | return result; |
| | 61 | } |
| | 62 | |
| | 63 | fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| | 64 | const fields = std.meta.fields(@TypeOf(extra)); |
| | 65 | var i = index; |
| 56 | inline for (fields) |field| { | 66 | inline for (fields) |field| { |
| 57 | astgen.extra.appendAssumeCapacity(switch (field.field_type) { | 67 | astgen.extra.items[i] = switch (field.field_type) { |
| 58 | u32 => @field(extra, field.name), | 68 | u32 => @field(extra, field.name), |
| 59 | Zir.Inst.Ref => @enumToInt(@field(extra, field.name)), | 69 | Zir.Inst.Ref => @enumToInt(@field(extra, field.name)), |
| 60 | i32 => @bitCast(u32, @field(extra, field.name)), | 70 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 61 | Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)), | 71 | Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)), |
| 62 | Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)), | 72 | Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)), |
| 63 | else => @compileError("bad field type"), | 73 | else => @compileError("bad field type"), |
| 64 | }); | 74 | }; |
| | 75 | i += 1; |
| 65 | } | 76 | } |
| | 77 | } |
| | 78 | |
| | 79 | fn reserveExtra(astgen: *AstGen, size: usize) Allocator.Error!u32 { |
| | 80 | const result = @intCast(u32, astgen.extra.items.len); |
| | 81 | try astgen.extra.resize(astgen.gpa, result + size); |
| 66 | return result; | 82 | return result; |
| 67 | } | 83 | } |
| 68 | | 84 | |
| ... | @@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { | ... | @@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 101 | | 117 | |
| 102 | var top_scope: Scope.Top = .{}; | 118 | var top_scope: Scope.Top = .{}; |
| 103 | | 119 | |
| | 120 | var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; |
| 104 | var gen_scope: GenZir = .{ | 121 | var gen_scope: GenZir = .{ |
| 105 | .force_comptime = true, | 122 | .force_comptime = true, |
| 106 | .in_defer = false, | 123 | .in_defer = false, |
| ... | @@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { | ... | @@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 109 | .decl_node_index = 0, | 126 | .decl_node_index = 0, |
| 110 | .decl_line = 0, | 127 | .decl_line = 0, |
| 111 | .astgen = &astgen, | 128 | .astgen = &astgen, |
| | 129 | .instructions = &gz_instructions, |
| | 130 | .instructions_top = 0, |
| 112 | }; | 131 | }; |
| 113 | defer gen_scope.instructions.deinit(gpa); | 132 | defer gz_instructions.deinit(gpa); |
| 114 | | 133 | |
| 115 | const container_decl: Ast.full.ContainerDecl = .{ | 134 | const container_decl: Ast.full.ContainerDecl = .{ |
| 116 | .layout_token = null, | 135 | .layout_token = null, |
| ... | @@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void { | ... | @@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void { |
| 184 | astgen.string_bytes.deinit(gpa); | 203 | astgen.string_bytes.deinit(gpa); |
| 185 | astgen.compile_errors.deinit(gpa); | 204 | astgen.compile_errors.deinit(gpa); |
| 186 | astgen.imports.deinit(gpa); | 205 | astgen.imports.deinit(gpa); |
| | 206 | astgen.scratch.deinit(gpa); |
| 187 | } | 207 | } |
| 188 | | 208 | |
| 189 | pub const ResultLoc = union(enum) { | 209 | pub const ResultLoc = union(enum) { |
| ... | @@ -1024,12 +1044,12 @@ fn suspendExpr( | ... | @@ -1024,12 +1044,12 @@ fn suspendExpr( |
| 1024 | } | 1044 | } |
| 1025 | assert(body_node != 0); | 1045 | assert(body_node != 0); |
| 1026 | | 1046 | |
| 1027 | const suspend_inst = try gz.addBlock(.suspend_block, node); | 1047 | const suspend_inst = try gz.makeBlockInst(.suspend_block, node); |
| 1028 | try gz.instructions.append(gpa, suspend_inst); | 1048 | try gz.instructions.append(gpa, suspend_inst); |
| 1029 | | 1049 | |
| 1030 | var suspend_scope = gz.makeSubBlock(scope); | 1050 | var suspend_scope = gz.makeSubBlock(scope); |
| 1031 | suspend_scope.suspend_node = node; | 1051 | suspend_scope.suspend_node = node; |
| 1032 | defer suspend_scope.instructions.deinit(gpa); | 1052 | defer suspend_scope.unstack(); |
| 1033 | | 1053 | |
| 1034 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); | 1054 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); |
| 1035 | if (!gz.refIsNoReturn(body_result)) { | 1055 | if (!gz.refIsNoReturn(body_result)) { |
| ... | @@ -1084,7 +1104,6 @@ fn fnProtoExpr( | ... | @@ -1084,7 +1104,6 @@ fn fnProtoExpr( |
| 1084 | fn_proto: Ast.full.FnProto, | 1104 | fn_proto: Ast.full.FnProto, |
| 1085 | ) InnerError!Zir.Inst.Ref { | 1105 | ) InnerError!Zir.Inst.Ref { |
| 1086 | const astgen = gz.astgen; | 1106 | const astgen = gz.astgen; |
| 1087 | const gpa = astgen.gpa; | | |
| 1088 | const tree = astgen.tree; | 1107 | const tree = astgen.tree; |
| 1089 | const token_tags = tree.tokens.items(.tag); | 1108 | const token_tags = tree.tokens.items(.tag); |
| 1090 | | 1109 | |
| ... | @@ -1130,14 +1149,14 @@ fn fnProtoExpr( | ... | @@ -1130,14 +1149,14 @@ fn fnProtoExpr( |
| 1130 | const param_type_node = param.type_expr; | 1149 | const param_type_node = param.type_expr; |
| 1131 | assert(param_type_node != 0); | 1150 | assert(param_type_node != 0); |
| 1132 | var param_gz = gz.makeSubBlock(scope); | 1151 | var param_gz = gz.makeSubBlock(scope); |
| 1133 | defer param_gz.instructions.deinit(gpa); | 1152 | defer param_gz.unstack(); |
| 1134 | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); | 1153 | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); |
| 1135 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); | 1154 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 1136 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); | 1155 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| 1137 | const main_tokens = tree.nodes.items(.main_token); | 1156 | const main_tokens = tree.nodes.items(.main_token); |
| 1138 | const name_token = param.name_token orelse main_tokens[param_type_node]; | 1157 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 1139 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; | 1158 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 1140 | const param_inst = try gz.addParam(tag, name_token, param_name, param_gz.instructions.items); | 1159 | const param_inst = try gz.addParam(&param_gz, tag, name_token, param_name); |
| 1141 | assert(param_inst_expected == param_inst); | 1160 | assert(param_inst_expected == param_inst); |
| 1142 | } | 1161 | } |
| 1143 | } | 1162 | } |
| ... | @@ -1172,16 +1191,16 @@ fn fnProtoExpr( | ... | @@ -1172,16 +1191,16 @@ fn fnProtoExpr( |
| 1172 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); | 1191 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 1173 | } | 1192 | } |
| 1174 | var ret_gz = gz.makeSubBlock(scope); | 1193 | var ret_gz = gz.makeSubBlock(scope); |
| 1175 | defer ret_gz.instructions.deinit(gpa); | 1194 | defer ret_gz.unstack(); |
| 1176 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); | 1195 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); |
| 1177 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | 1196 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 1178 | | 1197 | |
| 1179 | const result = try gz.addFunc(.{ | 1198 | const result = try gz.addFunc(.{ |
| 1180 | .src_node = fn_proto.ast.proto_node, | 1199 | .src_node = fn_proto.ast.proto_node, |
| 1181 | .param_block = 0, | 1200 | .param_block = 0, |
| 1182 | .ret_ty = ret_gz.instructions.items, | 1201 | .ret_gz = &ret_gz, |
| 1183 | .ret_br = ret_br, | 1202 | .ret_br = ret_br, |
| 1184 | .body = &[0]Zir.Inst.Index{}, | 1203 | .body_gz = null, |
| 1185 | .cc = cc, | 1204 | .cc = cc, |
| 1186 | .align_inst = align_inst, | 1205 | .align_inst = align_inst, |
| 1187 | .lib_name = 0, | 1206 | .lib_name = 0, |
| ... | @@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone( | ... | @@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone( |
| 1307 | tag: Zir.Inst.Tag, | 1326 | tag: Zir.Inst.Tag, |
| 1308 | ) InnerError!Zir.Inst.Ref { | 1327 | ) InnerError!Zir.Inst.Ref { |
| 1309 | const astgen = gz.astgen; | 1328 | const astgen = gz.astgen; |
| 1310 | const gpa = astgen.gpa; | | |
| 1311 | const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len); | | |
| 1312 | defer gpa.free(elem_list); | | |
| 1313 | | 1329 | |
| 1314 | for (elements) |elem_init, i| { | 1330 | const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{ |
| 1315 | elem_list[i] = try expr(gz, scope, .none, elem_init); | 1331 | .operands_len = @intCast(u32, elements.len), |
| 1316 | } | | |
| 1317 | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{ | | |
| 1318 | .operands_len = @intCast(u32, elem_list.len), | | |
| 1319 | }); | 1332 | }); |
| 1320 | try astgen.appendRefs(elem_list); | 1333 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1321 | return init_inst; | 1334 | |
| | 1335 | for (elements) |elem_init| { |
| | 1336 | const elem_ref = try expr(gz, scope, .none, elem_init); |
| | 1337 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| | 1338 | extra_index += 1; |
| | 1339 | } |
| | 1340 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1322 | } | 1341 | } |
| 1323 | | 1342 | |
| 1324 | fn arrayInitExprRlTy( | 1343 | fn arrayInitExprRlTy( |
| ... | @@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy( | ... | @@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy( |
| 1330 | tag: Zir.Inst.Tag, | 1349 | tag: Zir.Inst.Tag, |
| 1331 | ) InnerError!Zir.Inst.Ref { | 1350 | ) InnerError!Zir.Inst.Ref { |
| 1332 | const astgen = gz.astgen; | 1351 | const astgen = gz.astgen; |
| 1333 | const gpa = astgen.gpa; | | |
| 1334 | | 1352 | |
| 1335 | const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len); | 1353 | const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{ |
| 1336 | defer gpa.free(elem_list); | 1354 | .operands_len = @intCast(u32, elements.len), |
| | 1355 | }); |
| | 1356 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1337 | | 1357 | |
| 1338 | const elem_rl: ResultLoc = .{ .ty = elem_ty_inst }; | 1358 | const elem_rl: ResultLoc = .{ .ty = elem_ty_inst }; |
| 1339 | | 1359 | for (elements) |elem_init| { |
| 1340 | for (elements) |elem_init, i| { | 1360 | const elem_ref = try expr(gz, scope, elem_rl, elem_init); |
| 1341 | elem_list[i] = try expr(gz, scope, elem_rl, elem_init); | 1361 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| | 1362 | extra_index += 1; |
| 1342 | } | 1363 | } |
| 1343 | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{ | 1364 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1344 | .operands_len = @intCast(u32, elem_list.len), | | |
| 1345 | }); | | |
| 1346 | try astgen.appendRefs(elem_list); | | |
| 1347 | return init_inst; | | |
| 1348 | } | 1365 | } |
| 1349 | | 1366 | |
| 1350 | fn arrayInitExprRlPtr( | 1367 | fn arrayInitExprRlPtr( |
| ... | @@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr( | ... | @@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr( |
| 1361 | } | 1378 | } |
| 1362 | | 1379 | |
| 1363 | var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr); | 1380 | var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr); |
| 1364 | defer as_scope.instructions.deinit(gz.astgen.gpa); | 1381 | defer as_scope.unstack(); |
| 1365 | | 1382 | |
| 1366 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); | 1383 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); |
| 1367 | return as_scope.finishCoercion(gz, rl, node, result, array_ty); | 1384 | return as_scope.finishCoercion(gz, rl, node, result, array_ty); |
| ... | @@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner( | ... | @@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner( |
| 1375 | elements: []const Ast.Node.Index, | 1392 | elements: []const Ast.Node.Index, |
| 1376 | ) InnerError!Zir.Inst.Ref { | 1393 | ) InnerError!Zir.Inst.Ref { |
| 1377 | const astgen = gz.astgen; | 1394 | const astgen = gz.astgen; |
| 1378 | const gpa = astgen.gpa; | | |
| 1379 | | 1395 | |
| 1380 | const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len); | 1396 | const payload_index = try addExtra(astgen, Zir.Inst.Block{ |
| 1381 | defer gpa.free(elem_ptr_list); | 1397 | .body_len = @intCast(u32, elements.len), |
| | 1398 | }); |
| | 1399 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1382 | | 1400 | |
| 1383 | for (elements) |elem_init, i| { | 1401 | for (elements) |elem_init, i| { |
| 1384 | const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{ | 1402 | const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{ |
| 1385 | .ptr = result_ptr, | 1403 | .ptr = result_ptr, |
| 1386 | .index = @intCast(u32, i), | 1404 | .index = @intCast(u32, i), |
| 1387 | }); | 1405 | }); |
| 1388 | elem_ptr_list[i] = refToIndex(elem_ptr).?; | 1406 | astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; |
| | 1407 | extra_index += 1; |
| 1389 | _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init); | 1408 | _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init); |
| 1390 | } | 1409 | } |
| 1391 | _ = try gz.addPlNode(.validate_array_init, node, Zir.Inst.Block{ | 1410 | _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index); |
| 1392 | .body_len = @intCast(u32, elem_ptr_list.len), | | |
| 1393 | }); | | |
| 1394 | try astgen.extra.appendSlice(gpa, elem_ptr_list); | | |
| 1395 | return .void_value; | 1411 | return .void_value; |
| 1396 | } | 1412 | } |
| 1397 | | 1413 | |
| ... | @@ -1505,30 +1521,25 @@ fn structInitExprRlNone( | ... | @@ -1505,30 +1521,25 @@ fn structInitExprRlNone( |
| 1505 | tag: Zir.Inst.Tag, | 1521 | tag: Zir.Inst.Tag, |
| 1506 | ) InnerError!Zir.Inst.Ref { | 1522 | ) InnerError!Zir.Inst.Ref { |
| 1507 | const astgen = gz.astgen; | 1523 | const astgen = gz.astgen; |
| 1508 | const gpa = astgen.gpa; | | |
| 1509 | const tree = astgen.tree; | 1524 | const tree = astgen.tree; |
| 1510 | | 1525 | |
| 1511 | const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); | 1526 | const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{ |
| 1512 | defer gpa.free(fields_list); | 1527 | .fields_len = @intCast(u32, struct_init.ast.fields.len), |
| | 1528 | }); |
| | 1529 | const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len; |
| | 1530 | var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size); |
| 1513 | | 1531 | |
| 1514 | for (struct_init.ast.fields) |field_init, i| { | 1532 | for (struct_init.ast.fields) |field_init| { |
| 1515 | const name_token = tree.firstToken(field_init) - 2; | 1533 | const name_token = tree.firstToken(field_init) - 2; |
| 1516 | const str_index = try astgen.identAsString(name_token); | 1534 | const str_index = try astgen.identAsString(name_token); |
| 1517 | | 1535 | setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{ |
| 1518 | fields_list[i] = .{ | | |
| 1519 | .field_name = str_index, | 1536 | .field_name = str_index, |
| 1520 | .init = try expr(gz, scope, .none, field_init), | 1537 | .init = try expr(gz, scope, .none, field_init), |
| 1521 | }; | 1538 | }); |
| 1522 | } | 1539 | extra_index += field_size; |
| 1523 | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{ | | |
| 1524 | .fields_len = @intCast(u32, fields_list.len), | | |
| 1525 | }); | | |
| 1526 | try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len * | | |
| 1527 | @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len); | | |
| 1528 | for (fields_list) |field| { | | |
| 1529 | _ = gz.astgen.addExtraAssumeCapacity(field); | | |
| 1530 | } | 1540 | } |
| 1531 | return init_inst; | 1541 | |
| | 1542 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1532 | } | 1543 | } |
| 1533 | | 1544 | |
| 1534 | fn structInitExprRlPtr( | 1545 | fn structInitExprRlPtr( |
| ... | @@ -1545,7 +1556,7 @@ fn structInitExprRlPtr( | ... | @@ -1545,7 +1556,7 @@ fn structInitExprRlPtr( |
| 1545 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); | 1556 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1546 | | 1557 | |
| 1547 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); | 1558 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); |
| 1548 | defer as_scope.instructions.deinit(gz.astgen.gpa); | 1559 | defer as_scope.unstack(); |
| 1549 | | 1560 | |
| 1550 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); | 1561 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); |
| 1551 | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); | 1562 | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); |
| ... | @@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner( | ... | @@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner( |
| 1559 | result_ptr: Zir.Inst.Ref, | 1570 | result_ptr: Zir.Inst.Ref, |
| 1560 | ) InnerError!Zir.Inst.Ref { | 1571 | ) InnerError!Zir.Inst.Ref { |
| 1561 | const astgen = gz.astgen; | 1572 | const astgen = gz.astgen; |
| 1562 | const gpa = astgen.gpa; | | |
| 1563 | const tree = astgen.tree; | 1573 | const tree = astgen.tree; |
| 1564 | | 1574 | |
| 1565 | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); | 1575 | const payload_index = try addExtra(astgen, Zir.Inst.Block{ |
| 1566 | defer gpa.free(field_ptr_list); | 1576 | .body_len = @intCast(u32, struct_init.ast.fields.len), |
| | 1577 | }); |
| | 1578 | var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len); |
| 1567 | | 1579 | |
| 1568 | for (struct_init.ast.fields) |field_init, i| { | 1580 | for (struct_init.ast.fields) |field_init| { |
| 1569 | const name_token = tree.firstToken(field_init) - 2; | 1581 | const name_token = tree.firstToken(field_init) - 2; |
| 1570 | const str_index = try astgen.identAsString(name_token); | 1582 | const str_index = try astgen.identAsString(name_token); |
| 1571 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ | 1583 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ |
| 1572 | .lhs = result_ptr, | 1584 | .lhs = result_ptr, |
| 1573 | .field_name_start = str_index, | 1585 | .field_name_start = str_index, |
| 1574 | }); | 1586 | }); |
| 1575 | field_ptr_list[i] = refToIndex(field_ptr).?; | 1587 | astgen.extra.items[extra_index] = refToIndex(field_ptr).?; |
| | 1588 | extra_index += 1; |
| 1576 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); | 1589 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); |
| 1577 | } | 1590 | } |
| 1578 | _ = try gz.addPlNode(.validate_struct_init, node, Zir.Inst.Block{ | 1591 | |
| 1579 | .body_len = @intCast(u32, field_ptr_list.len), | 1592 | _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index); |
| 1580 | }); | | |
| 1581 | try astgen.extra.appendSlice(gpa, field_ptr_list); | | |
| 1582 | return Zir.Inst.Ref.void_value; | 1593 | return Zir.Inst.Ref.void_value; |
| 1583 | } | 1594 | } |
| 1584 | | 1595 | |
| ... | @@ -1591,34 +1602,29 @@ fn structInitExprRlTy( | ... | @@ -1591,34 +1602,29 @@ fn structInitExprRlTy( |
| 1591 | tag: Zir.Inst.Tag, | 1602 | tag: Zir.Inst.Tag, |
| 1592 | ) InnerError!Zir.Inst.Ref { | 1603 | ) InnerError!Zir.Inst.Ref { |
| 1593 | const astgen = gz.astgen; | 1604 | const astgen = gz.astgen; |
| 1594 | const gpa = astgen.gpa; | | |
| 1595 | const tree = astgen.tree; | 1605 | const tree = astgen.tree; |
| 1596 | | 1606 | |
| 1597 | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); | 1607 | const payload_index = try addExtra(astgen, Zir.Inst.StructInit{ |
| 1598 | defer gpa.free(fields_list); | 1608 | .fields_len = @intCast(u32, struct_init.ast.fields.len), |
| | 1609 | }); |
| | 1610 | const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len; |
| | 1611 | var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size); |
| 1599 | | 1612 | |
| 1600 | for (struct_init.ast.fields) |field_init, i| { | 1613 | for (struct_init.ast.fields) |field_init| { |
| 1601 | const name_token = tree.firstToken(field_init) - 2; | 1614 | const name_token = tree.firstToken(field_init) - 2; |
| 1602 | const str_index = try astgen.identAsString(name_token); | 1615 | const str_index = try astgen.identAsString(name_token); |
| 1603 | | | |
| 1604 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ | 1616 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ |
| 1605 | .container_type = ty_inst, | 1617 | .container_type = ty_inst, |
| 1606 | .name_start = str_index, | 1618 | .name_start = str_index, |
| 1607 | }); | 1619 | }); |
| 1608 | fields_list[i] = .{ | 1620 | setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{ |
| 1609 | .field_type = refToIndex(field_ty_inst).?, | 1621 | .field_type = refToIndex(field_ty_inst).?, |
| 1610 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), | 1622 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), |
| 1611 | }; | 1623 | }); |
| 1612 | } | 1624 | extra_index += field_size; |
| 1613 | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{ | | |
| 1614 | .fields_len = @intCast(u32, fields_list.len), | | |
| 1615 | }); | | |
| 1616 | try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len * | | |
| 1617 | @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len); | | |
| 1618 | for (fields_list) |field| { | | |
| 1619 | _ = gz.astgen.addExtraAssumeCapacity(field); | | |
| 1620 | } | 1625 | } |
| 1621 | return init_inst; | 1626 | |
| | 1627 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1622 | } | 1628 | } |
| 1623 | | 1629 | |
| 1624 | /// This calls expr in a comptime scope, and is intended to be called as a helper function. | 1630 | /// This calls expr in a comptime scope, and is intended to be called as a helper function. |
| ... | @@ -1871,7 +1877,7 @@ fn labeledBlockExpr( | ... | @@ -1871,7 +1877,7 @@ fn labeledBlockExpr( |
| 1871 | | 1877 | |
| 1872 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct | 1878 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct |
| 1873 | // so that break statements can reference it. | 1879 | // so that break statements can reference it. |
| 1874 | const block_inst = try gz.addBlock(zir_tag, block_node); | 1880 | const block_inst = try gz.makeBlockInst(zir_tag, block_node); |
| 1875 | try gz.instructions.append(astgen.gpa, block_inst); | 1881 | try gz.instructions.append(astgen.gpa, block_inst); |
| 1876 | | 1882 | |
| 1877 | var block_scope = gz.makeSubBlock(parent_scope); | 1883 | var block_scope = gz.makeSubBlock(parent_scope); |
| ... | @@ -1880,7 +1886,7 @@ fn labeledBlockExpr( | ... | @@ -1880,7 +1886,7 @@ fn labeledBlockExpr( |
| 1880 | .block_inst = block_inst, | 1886 | .block_inst = block_inst, |
| 1881 | }; | 1887 | }; |
| 1882 | block_scope.setBreakResultLoc(rl); | 1888 | block_scope.setBreakResultLoc(rl); |
| 1883 | defer block_scope.instructions.deinit(astgen.gpa); | 1889 | defer block_scope.unstack(); |
| 1884 | defer block_scope.labeled_breaks.deinit(astgen.gpa); | 1890 | defer block_scope.labeled_breaks.deinit(astgen.gpa); |
| 1885 | defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 1891 | defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 1886 | | 1892 | |
| ... | @@ -2485,7 +2491,6 @@ fn varDecl( | ... | @@ -2485,7 +2491,6 @@ fn varDecl( |
| 2485 | ) InnerError!*Scope { | 2491 | ) InnerError!*Scope { |
| 2486 | try emitDbgNode(gz, node); | 2492 | try emitDbgNode(gz, node); |
| 2487 | const astgen = gz.astgen; | 2493 | const astgen = gz.astgen; |
| 2488 | const gpa = astgen.gpa; | | |
| 2489 | const tree = astgen.tree; | 2494 | const tree = astgen.tree; |
| 2490 | const token_tags = tree.tokens.items(.tag); | 2495 | const token_tags = tree.tokens.items(.tag); |
| 2491 | const main_tokens = tree.nodes.items(.main_token); | 2496 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -2546,7 +2551,9 @@ fn varDecl( | ... | @@ -2546,7 +2551,9 @@ fn varDecl( |
| 2546 | // Detect whether the initialization expression actually uses the | 2551 | // Detect whether the initialization expression actually uses the |
| 2547 | // result location pointer. | 2552 | // result location pointer. |
| 2548 | var init_scope = gz.makeSubBlock(scope); | 2553 | var init_scope = gz.makeSubBlock(scope); |
| 2549 | defer init_scope.instructions.deinit(gpa); | 2554 | // we may add more instructions to gz before stacking init_scope |
| | 2555 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2556 | defer init_scope.unstack(); |
| 2550 | | 2557 | |
| 2551 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; | 2558 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| 2552 | var opt_type_inst: Zir.Inst.Ref = .none; | 2559 | var opt_type_inst: Zir.Inst.Ref = .none; |
| ... | @@ -2554,6 +2561,7 @@ fn varDecl( | ... | @@ -2554,6 +2561,7 @@ fn varDecl( |
| 2554 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); | 2561 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); |
| 2555 | opt_type_inst = type_inst; | 2562 | opt_type_inst = type_inst; |
| 2556 | if (align_inst == .none) { | 2563 | if (align_inst == .none) { |
| | 2564 | init_scope.instructions_top = gz.instructions.items.len; |
| 2557 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); | 2565 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); |
| 2558 | } else { | 2566 | } else { |
| 2559 | init_scope.rl_ptr = try gz.addAllocExtended(.{ | 2567 | init_scope.rl_ptr = try gz.addAllocExtended(.{ |
| ... | @@ -2563,19 +2571,24 @@ fn varDecl( | ... | @@ -2563,19 +2571,24 @@ fn varDecl( |
| 2563 | .is_const = true, | 2571 | .is_const = true, |
| 2564 | .is_comptime = false, | 2572 | .is_comptime = false, |
| 2565 | }); | 2573 | }); |
| | 2574 | init_scope.instructions_top = gz.instructions.items.len; |
| 2566 | } | 2575 | } |
| 2567 | init_scope.rl_ty_inst = type_inst; | 2576 | init_scope.rl_ty_inst = type_inst; |
| 2568 | } else { | 2577 | } else { |
| 2569 | const alloc = if (align_inst == .none) | 2578 | const alloc = if (align_inst == .none) alloc: { |
| 2570 | try init_scope.addNode(.alloc_inferred, node) | 2579 | init_scope.instructions_top = gz.instructions.items.len; |
| 2571 | else | 2580 | break :alloc try init_scope.addNode(.alloc_inferred, node); |
| 2572 | try gz.addAllocExtended(.{ | 2581 | } else alloc: { |
| | 2582 | const ref = try gz.addAllocExtended(.{ |
| 2573 | .node = node, | 2583 | .node = node, |
| 2574 | .type_inst = .none, | 2584 | .type_inst = .none, |
| 2575 | .align_inst = align_inst, | 2585 | .align_inst = align_inst, |
| 2576 | .is_const = true, | 2586 | .is_const = true, |
| 2577 | .is_comptime = false, | 2587 | .is_comptime = false, |
| 2578 | }); | 2588 | }); |
| | 2589 | init_scope.instructions_top = gz.instructions.items.len; |
| | 2590 | break :alloc ref; |
| | 2591 | }; |
| 2579 | resolve_inferred_alloc = alloc; | 2592 | resolve_inferred_alloc = alloc; |
| 2580 | init_scope.rl_ptr = alloc; | 2593 | init_scope.rl_ptr = alloc; |
| 2581 | } | 2594 | } |
| ... | @@ -2585,20 +2598,24 @@ fn varDecl( | ... | @@ -2585,20 +2598,24 @@ fn varDecl( |
| 2585 | const zir_tags = astgen.instructions.items(.tag); | 2598 | const zir_tags = astgen.instructions.items(.tag); |
| 2586 | const zir_datas = astgen.instructions.items(.data); | 2599 | const zir_datas = astgen.instructions.items(.data); |
| 2587 | | 2600 | |
| 2588 | const parent_zir = &gz.instructions; | | |
| 2589 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { | 2601 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { |
| 2590 | // Result location pointer not used. We don't need an alloc for this | 2602 | // Result location pointer not used. We don't need an alloc for this |
| 2591 | // const local, and type inference becomes trivial. | 2603 | // const local, and type inference becomes trivial. |
| 2592 | // Move the init_scope instructions into the parent scope, eliding | 2604 | // Implicitly move the init_scope instructions into the parent scope, |
| 2593 | // the alloc instruction and the store_to_block_ptr instruction. | 2605 | // then elide the alloc instruction and the store_to_block_ptr instruction. |
| 2594 | try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len); | 2606 | var src = init_scope.instructions_top; |
| 2595 | for (init_scope.instructions.items) |src_inst| { | 2607 | var dst = src; |
| | 2608 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2609 | while (src < gz.instructions.items.len) : (src += 1) { |
| | 2610 | const src_inst = gz.instructions.items[src]; |
| 2596 | if (indexToRef(src_inst) == init_scope.rl_ptr) continue; | 2611 | if (indexToRef(src_inst) == init_scope.rl_ptr) continue; |
| 2597 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 2612 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2598 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; | 2613 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; |
| 2599 | } | 2614 | } |
| 2600 | parent_zir.appendAssumeCapacity(src_inst); | 2615 | gz.instructions.items[dst] = src_inst; |
| | 2616 | dst += 1; |
| 2601 | } | 2617 | } |
| | 2618 | gz.instructions.items.len = dst; |
| 2602 | | 2619 | |
| 2603 | const sub_scope = try block_arena.create(Scope.LocalVal); | 2620 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2604 | sub_scope.* = .{ | 2621 | sub_scope.* = .{ |
| ... | @@ -2613,11 +2630,13 @@ fn varDecl( | ... | @@ -2613,11 +2630,13 @@ fn varDecl( |
| 2613 | } | 2630 | } |
| 2614 | // The initialization expression took advantage of the result location | 2631 | // The initialization expression took advantage of the result location |
| 2615 | // of the const local. In this case we will create an alloc and a LocalPtr for it. | 2632 | // of the const local. In this case we will create an alloc and a LocalPtr for it. |
| 2616 | // Move the init_scope instructions into the parent scope, swapping | 2633 | // Implicitly move the init_scope instructions into the parent scope, then swap |
| 2617 | // store_to_block_ptr for store_to_inferred_ptr. | 2634 | // store_to_block_ptr for store_to_inferred_ptr. |
| 2618 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len; | 2635 | |
| 2619 | try parent_zir.ensureTotalCapacity(gpa, expected_len); | 2636 | var src = init_scope.instructions_top; |
| 2620 | for (init_scope.instructions.items) |src_inst| { | 2637 | init_scope.instructions_top = GenZir.unstacked_top; |
| | 2638 | while (src < gz.instructions.items.len) : (src += 1) { |
| | 2639 | const src_inst = gz.instructions.items[src]; |
| 2621 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 2640 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2622 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) { | 2641 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) { |
| 2623 | if (var_decl.ast.type_node != 0) { | 2642 | if (var_decl.ast.type_node != 0) { |
| ... | @@ -2627,9 +2646,7 @@ fn varDecl( | ... | @@ -2627,9 +2646,7 @@ fn varDecl( |
| 2627 | } | 2646 | } |
| 2628 | } | 2647 | } |
| 2629 | } | 2648 | } |
| 2630 | parent_zir.appendAssumeCapacity(src_inst); | | |
| 2631 | } | 2649 | } |
| 2632 | assert(parent_zir.items.len == expected_len); | | |
| 2633 | if (resolve_inferred_alloc != .none) { | 2650 | if (resolve_inferred_alloc != .none) { |
| 2634 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); | 2651 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2635 | } | 2652 | } |
| ... | @@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I | ... | @@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I |
| 2994 | return rvalue(gz, rl, result, node); | 3011 | return rvalue(gz, rl, result, node); |
| 2995 | } | 3012 | } |
| 2996 | | 3013 | |
| 2997 | const WipDecls = struct { | 3014 | const WipMembers = struct { |
| 2998 | decl_index: usize = 0, | 3015 | payload: *ArrayListUnmanaged(u32), |
| 2999 | cur_bit_bag: u32 = 0, | 3016 | payload_top: usize, |
| 3000 | bit_bag: ArrayListUnmanaged(u32) = .{}, | 3017 | decls_start: u32, |
| 3001 | payload: ArrayListUnmanaged(u32) = .{}, | 3018 | decls_end: u32, |
| | 3019 | field_bits_start: u32, |
| | 3020 | fields_start: u32, |
| | 3021 | fields_end: u32, |
| | 3022 | decl_index: u32 = 0, |
| | 3023 | field_index: u32 = 0, |
| | 3024 | |
| | 3025 | const Self = @This(); |
| | 3026 | /// struct, union, enum, and opaque decls all use same 4 bits per decl |
| | 3027 | const bits_per_decl = 4; |
| | 3028 | const decls_per_u32 = 32 / bits_per_decl; |
| | 3029 | /// struct, union, enum, and opaque decls all have maximum size of 10 u32 slots |
| | 3030 | /// (4 for src_hash + line + name + value + align + link_section + address_space) |
| | 3031 | const max_decl_size = 10; |
| | 3032 | |
| | 3033 | pub fn init(gpa: *Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { |
| | 3034 | const payload_top = @intCast(u32, payload.items.len); |
| | 3035 | const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32; |
| | 3036 | const field_bits_start = decls_start + decl_count * max_decl_size; |
| | 3037 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { |
| | 3038 | const fields_per_u32 = 32 / bits_per_field; |
| | 3039 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; |
| | 3040 | } else 0; |
| | 3041 | const payload_end = fields_start + field_count * max_field_size; |
| | 3042 | try payload.resize(gpa, payload_end); |
| | 3043 | return Self{ |
| | 3044 | .payload = payload, |
| | 3045 | .payload_top = payload_top, |
| | 3046 | .decls_start = decls_start, |
| | 3047 | .field_bits_start = field_bits_start, |
| | 3048 | .fields_start = fields_start, |
| | 3049 | .decls_end = decls_start, |
| | 3050 | .fields_end = fields_start, |
| | 3051 | }; |
| | 3052 | } |
| 3002 | | 3053 | |
| 3003 | const bits_per_field = 4; | 3054 | pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void { |
| 3004 | const fields_per_u32 = 32 / bits_per_field; | 3055 | const index = self.payload_top + self.decl_index / decls_per_u32; |
| 3005 | | 3056 | assert(index < self.decls_start); |
| 3006 | fn next( | 3057 | const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index]; |
| 3007 | wip_decls: *WipDecls, | 3058 | self.payload.items[index] = (bit_bag >> bits_per_decl) | |
| 3008 | gpa: *Allocator, | | |
| 3009 | is_pub: bool, | | |
| 3010 | is_export: bool, | | |
| 3011 | has_align: bool, | | |
| 3012 | has_section_or_addrspace: bool, | | |
| 3013 | ) Allocator.Error!void { | | |
| 3014 | if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) { | | |
| 3015 | try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); | | |
| 3016 | wip_decls.cur_bit_bag = 0; | | |
| 3017 | } | | |
| 3018 | wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) | | | |
| 3019 | (@as(u32, @boolToInt(is_pub)) << 28) | | 3059 | (@as(u32, @boolToInt(is_pub)) << 28) | |
| 3020 | (@as(u32, @boolToInt(is_export)) << 29) | | 3060 | (@as(u32, @boolToInt(is_export)) << 29) | |
| 3021 | (@as(u32, @boolToInt(has_align)) << 30) | | 3061 | (@as(u32, @boolToInt(has_align)) << 30) | |
| 3022 | (@as(u32, @boolToInt(has_section_or_addrspace)) << 31); | 3062 | (@as(u32, @boolToInt(has_section_or_addrspace)) << 31); |
| 3023 | wip_decls.decl_index += 1; | 3063 | self.decl_index += 1; |
| | 3064 | } |
| | 3065 | |
| | 3066 | pub fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { |
| | 3067 | const fields_per_u32 = 32 / bits_per_field; |
| | 3068 | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| | 3069 | assert(index < self.fields_start); |
| | 3070 | var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index]; |
| | 3071 | bit_bag >>= bits_per_field; |
| | 3072 | comptime var i = 0; |
| | 3073 | inline while (i < bits_per_field) : (i += 1) { |
| | 3074 | bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i); |
| | 3075 | } |
| | 3076 | self.payload.items[index] = bit_bag; |
| | 3077 | self.field_index += 1; |
| | 3078 | } |
| | 3079 | |
| | 3080 | pub fn appendToDecl(self: *Self, data: u32) void { |
| | 3081 | assert(self.decls_end < self.field_bits_start); |
| | 3082 | self.payload.items[self.decls_end] = data; |
| | 3083 | self.decls_end += 1; |
| | 3084 | } |
| | 3085 | |
| | 3086 | pub fn appendToDeclSlice(self: *Self, data: []const u32) void { |
| | 3087 | assert(self.decls_end + data.len <= self.field_bits_start); |
| | 3088 | mem.copy(u32, self.payload.items[self.decls_end..], data); |
| | 3089 | self.decls_end += @intCast(u32, data.len); |
| | 3090 | } |
| | 3091 | |
| | 3092 | pub fn appendToField(self: *Self, data: u32) void { |
| | 3093 | assert(self.fields_end < self.payload.items.len); |
| | 3094 | self.payload.items[self.fields_end] = data; |
| | 3095 | self.fields_end += 1; |
| | 3096 | } |
| | 3097 | |
| | 3098 | pub fn finishBits(self: *Self, comptime bits_per_field: u32) void { |
| | 3099 | const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32); |
| | 3100 | if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) { |
| | 3101 | const index = self.payload_top + self.decl_index / decls_per_u32; |
| | 3102 | self.payload.items[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl); |
| | 3103 | } |
| | 3104 | if (bits_per_field > 0) { |
| | 3105 | const fields_per_u32 = 32 / bits_per_field; |
| | 3106 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); |
| | 3107 | if (self.field_index > 0 and empty_field_slots < fields_per_u32) { |
| | 3108 | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| | 3109 | self.payload.items[index] >>= @intCast(u5, empty_field_slots * bits_per_field); |
| | 3110 | } |
| | 3111 | } |
| | 3112 | } |
| | 3113 | |
| | 3114 | pub fn declsSlice(self: *Self) []u32 { |
| | 3115 | return self.payload.items[self.payload_top..self.decls_end]; |
| | 3116 | } |
| | 3117 | |
| | 3118 | pub fn fieldsSlice(self: *Self) []u32 { |
| | 3119 | return self.payload.items[self.field_bits_start..self.fields_end]; |
| 3024 | } | 3120 | } |
| 3025 | | 3121 | |
| 3026 | fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void { | 3122 | pub fn deinit(self: *Self) void { |
| 3027 | wip_decls.bit_bag.deinit(gpa); | 3123 | self.payload.items.len = self.payload_top; |
| 3028 | wip_decls.payload.deinit(gpa); | | |
| 3029 | } | 3124 | } |
| 3030 | }; | 3125 | }; |
| 3031 | | 3126 | |
| ... | @@ -3033,12 +3128,11 @@ fn fnDecl( | ... | @@ -3033,12 +3128,11 @@ fn fnDecl( |
| 3033 | astgen: *AstGen, | 3128 | astgen: *AstGen, |
| 3034 | gz: *GenZir, | 3129 | gz: *GenZir, |
| 3035 | scope: *Scope, | 3130 | scope: *Scope, |
| 3036 | wip_decls: *WipDecls, | 3131 | wip_members: *WipMembers, |
| 3037 | decl_node: Ast.Node.Index, | 3132 | decl_node: Ast.Node.Index, |
| 3038 | body_node: Ast.Node.Index, | 3133 | body_node: Ast.Node.Index, |
| 3039 | fn_proto: Ast.full.FnProto, | 3134 | fn_proto: Ast.full.FnProto, |
| 3040 | ) InnerError!void { | 3135 | ) InnerError!void { |
| 3041 | const gpa = astgen.gpa; | | |
| 3042 | const tree = astgen.tree; | 3136 | const tree = astgen.tree; |
| 3043 | const token_tags = tree.tokens.items(.tag); | 3137 | const token_tags = tree.tokens.items(.tag); |
| 3044 | | 3138 | |
| ... | @@ -3048,7 +3142,7 @@ fn fnDecl( | ... | @@ -3048,7 +3142,7 @@ fn fnDecl( |
| 3048 | | 3142 | |
| 3049 | // We insert this at the beginning so that its instruction index marks the | 3143 | // We insert this at the beginning so that its instruction index marks the |
| 3050 | // start of the top level declaration. | 3144 | // start of the top level declaration. |
| 3051 | const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node); | 3145 | const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node); |
| 3052 | | 3146 | |
| 3053 | var decl_gz: GenZir = .{ | 3147 | var decl_gz: GenZir = .{ |
| 3054 | .force_comptime = true, | 3148 | .force_comptime = true, |
| ... | @@ -3057,8 +3151,10 @@ fn fnDecl( | ... | @@ -3057,8 +3151,10 @@ fn fnDecl( |
| 3057 | .decl_line = gz.calcLine(decl_node), | 3151 | .decl_line = gz.calcLine(decl_node), |
| 3058 | .parent = scope, | 3152 | .parent = scope, |
| 3059 | .astgen = astgen, | 3153 | .astgen = astgen, |
| | 3154 | .instructions = gz.instructions, |
| | 3155 | .instructions_top = gz.instructions.items.len, |
| 3060 | }; | 3156 | }; |
| 3061 | defer decl_gz.instructions.deinit(gpa); | 3157 | defer decl_gz.unstack(); |
| 3062 | | 3158 | |
| 3063 | var fn_gz: GenZir = .{ | 3159 | var fn_gz: GenZir = .{ |
| 3064 | .force_comptime = false, | 3160 | .force_comptime = false, |
| ... | @@ -3067,8 +3163,10 @@ fn fnDecl( | ... | @@ -3067,8 +3163,10 @@ fn fnDecl( |
| 3067 | .decl_line = decl_gz.decl_line, | 3163 | .decl_line = decl_gz.decl_line, |
| 3068 | .parent = &decl_gz.base, | 3164 | .parent = &decl_gz.base, |
| 3069 | .astgen = astgen, | 3165 | .astgen = astgen, |
| | 3166 | .instructions = gz.instructions, |
| | 3167 | .instructions_top = GenZir.unstacked_top, |
| 3070 | }; | 3168 | }; |
| 3071 | defer fn_gz.instructions.deinit(gpa); | 3169 | defer fn_gz.unstack(); |
| 3072 | | 3170 | |
| 3073 | // TODO: support noinline | 3171 | // TODO: support noinline |
| 3074 | const is_pub = fn_proto.visib_token != null; | 3172 | const is_pub = fn_proto.visib_token != null; |
| ... | @@ -3085,7 +3183,7 @@ fn fnDecl( | ... | @@ -3085,7 +3183,7 @@ fn fnDecl( |
| 3085 | break :blk token_tags[maybe_inline_token] == .keyword_inline; | 3183 | break :blk token_tags[maybe_inline_token] == .keyword_inline; |
| 3086 | }; | 3184 | }; |
| 3087 | const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0; | 3185 | const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0; |
| 3088 | try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace); | 3186 | wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace); |
| 3089 | | 3187 | |
| 3090 | var params_scope = &fn_gz.base; | 3188 | var params_scope = &fn_gz.base; |
| 3091 | const is_var_args = is_var_args: { | 3189 | const is_var_args = is_var_args: { |
| ... | @@ -3134,7 +3232,7 @@ fn fnDecl( | ... | @@ -3134,7 +3232,7 @@ fn fnDecl( |
| 3134 | const param_type_node = param.type_expr; | 3232 | const param_type_node = param.type_expr; |
| 3135 | assert(param_type_node != 0); | 3233 | assert(param_type_node != 0); |
| 3136 | var param_gz = decl_gz.makeSubBlock(scope); | 3234 | var param_gz = decl_gz.makeSubBlock(scope); |
| 3137 | defer param_gz.instructions.deinit(gpa); | 3235 | defer param_gz.unstack(); |
| 3138 | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); | 3236 | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); |
| 3139 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); | 3237 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 3140 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); | 3238 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| ... | @@ -3142,7 +3240,7 @@ fn fnDecl( | ... | @@ -3142,7 +3240,7 @@ fn fnDecl( |
| 3142 | const main_tokens = tree.nodes.items(.main_token); | 3240 | const main_tokens = tree.nodes.items(.main_token); |
| 3143 | const name_token = param.name_token orelse main_tokens[param_type_node]; | 3241 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 3144 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; | 3242 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 3145 | const param_inst = try decl_gz.addParam(tag, name_token, param_name, param_gz.instructions.items); | 3243 | const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name); |
| 3146 | assert(param_inst_expected == param_inst); | 3244 | assert(param_inst_expected == param_inst); |
| 3147 | break :param indexToRef(param_inst); | 3245 | break :param indexToRef(param_inst); |
| 3148 | }; | 3246 | }; |
| ... | @@ -3207,7 +3305,7 @@ fn fnDecl( | ... | @@ -3207,7 +3305,7 @@ fn fnDecl( |
| 3207 | }; | 3305 | }; |
| 3208 | | 3306 | |
| 3209 | var ret_gz = decl_gz.makeSubBlock(params_scope); | 3307 | var ret_gz = decl_gz.makeSubBlock(params_scope); |
| 3210 | defer ret_gz.instructions.deinit(gpa); | 3308 | defer ret_gz.unstack(); |
| 3211 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); | 3309 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); |
| 3212 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); | 3310 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 3213 | | 3311 | |
| ... | @@ -3220,10 +3318,10 @@ fn fnDecl( | ... | @@ -3220,10 +3318,10 @@ fn fnDecl( |
| 3220 | } | 3318 | } |
| 3221 | break :func try decl_gz.addFunc(.{ | 3319 | break :func try decl_gz.addFunc(.{ |
| 3222 | .src_node = decl_node, | 3320 | .src_node = decl_node, |
| 3223 | .ret_ty = ret_gz.instructions.items, | 3321 | .ret_gz = &ret_gz, |
| 3224 | .ret_br = ret_br, | 3322 | .ret_br = ret_br, |
| 3225 | .param_block = block_inst, | 3323 | .param_block = block_inst, |
| 3226 | .body = &[0]Zir.Inst.Index{}, | 3324 | .body_gz = null, |
| 3227 | .cc = cc, | 3325 | .cc = cc, |
| 3228 | .align_inst = .none, // passed in the per-decl data | 3326 | .align_inst = .none, // passed in the per-decl data |
| 3229 | .lib_name = lib_name, | 3327 | .lib_name = lib_name, |
| ... | @@ -3237,6 +3335,9 @@ fn fnDecl( | ... | @@ -3237,6 +3335,9 @@ fn fnDecl( |
| 3237 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); | 3335 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); |
| 3238 | } | 3336 | } |
| 3239 | | 3337 | |
| | 3338 | // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz |
| | 3339 | fn_gz.instructions_top = ret_gz.instructions.items.len; |
| | 3340 | |
| 3240 | const prev_fn_block = astgen.fn_block; | 3341 | const prev_fn_block = astgen.fn_block; |
| 3241 | astgen.fn_block = &fn_gz; | 3342 | astgen.fn_block = &fn_gz; |
| 3242 | defer astgen.fn_block = prev_fn_block; | 3343 | defer astgen.fn_block = prev_fn_block; |
| ... | @@ -3250,14 +3351,7 @@ fn fnDecl( | ... | @@ -3250,14 +3351,7 @@ fn fnDecl( |
| 3250 | _ = try expr(&fn_gz, params_scope, .none, body_node); | 3351 | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 3251 | try checkUsed(gz, &fn_gz.base, params_scope); | 3352 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 3252 | | 3353 | |
| 3253 | const need_implicit_ret = blk: { | 3354 | if (!fn_gz.endsWithNoReturn()) { |
| 3254 | if (fn_gz.instructions.items.len == 0) | | |
| 3255 | break :blk true; | | |
| 3256 | const last = fn_gz.instructions.items[fn_gz.instructions.items.len - 1]; | | |
| 3257 | const zir_tags = astgen.instructions.items(.tag); | | |
| 3258 | break :blk !zir_tags[last].isNoReturn(); | | |
| 3259 | }; | | |
| 3260 | if (need_implicit_ret) { | | |
| 3261 | // Since we are adding the return instruction here, we must handle the coercion. | 3355 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3262 | // We do this by using the `ret_coerce` instruction. | 3356 | // We do this by using the `ret_coerce` instruction. |
| 3263 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); | 3357 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | @@ -3268,9 +3362,9 @@ fn fnDecl( | ... | @@ -3268,9 +3362,9 @@ fn fnDecl( |
| 3268 | .lbrace_line = lbrace_line, | 3362 | .lbrace_line = lbrace_line, |
| 3269 | .lbrace_column = lbrace_column, | 3363 | .lbrace_column = lbrace_column, |
| 3270 | .param_block = block_inst, | 3364 | .param_block = block_inst, |
| 3271 | .ret_ty = ret_gz.instructions.items, | 3365 | .ret_gz = &ret_gz, |
| 3272 | .ret_br = ret_br, | 3366 | .ret_br = ret_br, |
| 3273 | .body = fn_gz.instructions.items, | 3367 | .body_gz = &fn_gz, |
| 3274 | .cc = cc, | 3368 | .cc = cc, |
| 3275 | .align_inst = .none, // passed in the per-decl data | 3369 | .align_inst = .none, // passed in the per-decl data |
| 3276 | .lib_name = lib_name, | 3370 | .lib_name = lib_name, |
| ... | @@ -3282,29 +3376,27 @@ fn fnDecl( | ... | @@ -3282,29 +3376,27 @@ fn fnDecl( |
| 3282 | }; | 3376 | }; |
| 3283 | | 3377 | |
| 3284 | // We add this at the end so that its instruction index marks the end range | 3378 | // We add this at the end so that its instruction index marks the end range |
| 3285 | // of the top level declaration. | 3379 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. |
| 3286 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); | 3380 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); |
| 3287 | try decl_gz.setBlockBody(block_inst); | 3381 | try decl_gz.setBlockBody(block_inst); |
| 3288 | | 3382 | |
| 3289 | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); | | |
| 3290 | { | 3383 | { |
| 3291 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); | 3384 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3292 | const casted = @bitCast([4]u32, contents_hash); | 3385 | const casted = @bitCast([4]u32, contents_hash); |
| 3293 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3386 | wip_members.appendToDeclSlice(&casted); |
| 3294 | } | 3387 | } |
| 3295 | { | 3388 | { |
| 3296 | const line_delta = decl_gz.decl_line - gz.decl_line; | 3389 | const line_delta = decl_gz.decl_line - gz.decl_line; |
| 3297 | wip_decls.payload.appendAssumeCapacity(line_delta); | 3390 | wip_members.appendToDecl(line_delta); |
| 3298 | } | 3391 | } |
| 3299 | wip_decls.payload.appendAssumeCapacity(fn_name_str_index); | 3392 | wip_members.appendToDecl(fn_name_str_index); |
| 3300 | wip_decls.payload.appendAssumeCapacity(block_inst); | 3393 | wip_members.appendToDecl(block_inst); |
| 3301 | if (align_inst != .none) { | 3394 | if (align_inst != .none) { |
| 3302 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); | 3395 | wip_members.appendToDecl(@enumToInt(align_inst)); |
| 3303 | } | 3396 | } |
| 3304 | | | |
| 3305 | if (has_section_or_addrspace) { | 3397 | if (has_section_or_addrspace) { |
| 3306 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); | 3398 | wip_members.appendToDecl(@enumToInt(section_inst)); |
| 3307 | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); | 3399 | wip_members.appendToDecl(@enumToInt(addrspace_inst)); |
| 3308 | } | 3400 | } |
| 3309 | } | 3401 | } |
| 3310 | | 3402 | |
| ... | @@ -3312,18 +3404,17 @@ fn globalVarDecl( | ... | @@ -3312,18 +3404,17 @@ fn globalVarDecl( |
| 3312 | astgen: *AstGen, | 3404 | astgen: *AstGen, |
| 3313 | gz: *GenZir, | 3405 | gz: *GenZir, |
| 3314 | scope: *Scope, | 3406 | scope: *Scope, |
| 3315 | wip_decls: *WipDecls, | 3407 | wip_members: *WipMembers, |
| 3316 | node: Ast.Node.Index, | 3408 | node: Ast.Node.Index, |
| 3317 | var_decl: Ast.full.VarDecl, | 3409 | var_decl: Ast.full.VarDecl, |
| 3318 | ) InnerError!void { | 3410 | ) InnerError!void { |
| 3319 | const gpa = astgen.gpa; | | |
| 3320 | const tree = astgen.tree; | 3411 | const tree = astgen.tree; |
| 3321 | const token_tags = tree.tokens.items(.tag); | 3412 | const token_tags = tree.tokens.items(.tag); |
| 3322 | | 3413 | |
| 3323 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; | 3414 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 3324 | // We do this at the beginning so that the instruction index marks the range start | 3415 | // We do this at the beginning so that the instruction index marks the range start |
| 3325 | // of the top level declaration. | 3416 | // of the top level declaration. |
| 3326 | const block_inst = try gz.addBlock(.block_inline, node); | 3417 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3327 | | 3418 | |
| 3328 | const name_token = var_decl.ast.mut_token + 1; | 3419 | const name_token = var_decl.ast.mut_token + 1; |
| 3329 | const name_str_index = try astgen.identAsString(name_token); | 3420 | const name_str_index = try astgen.identAsString(name_token); |
| ... | @@ -3336,8 +3427,10 @@ fn globalVarDecl( | ... | @@ -3336,8 +3427,10 @@ fn globalVarDecl( |
| 3336 | .force_comptime = true, | 3427 | .force_comptime = true, |
| 3337 | .in_defer = false, | 3428 | .in_defer = false, |
| 3338 | .anon_name_strategy = .parent, | 3429 | .anon_name_strategy = .parent, |
| | 3430 | .instructions = gz.instructions, |
| | 3431 | .instructions_top = gz.instructions.items.len, |
| 3339 | }; | 3432 | }; |
| 3340 | defer block_scope.instructions.deinit(gpa); | 3433 | defer block_scope.unstack(); |
| 3341 | | 3434 | |
| 3342 | const is_pub = var_decl.visib_token != null; | 3435 | const is_pub = var_decl.visib_token != null; |
| 3343 | const is_export = blk: { | 3436 | const is_export = blk: { |
| ... | @@ -3358,7 +3451,7 @@ fn globalVarDecl( | ... | @@ -3358,7 +3451,7 @@ fn globalVarDecl( |
| 3358 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); | 3451 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); |
| 3359 | }; | 3452 | }; |
| 3360 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; | 3453 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; |
| 3361 | try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, has_section_or_addrspace); | 3454 | wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace); |
| 3362 | | 3455 | |
| 3363 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { | 3456 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 3364 | if (!is_mutable) { | 3457 | if (!is_mutable) { |
| ... | @@ -3436,24 +3529,23 @@ fn globalVarDecl( | ... | @@ -3436,24 +3529,23 @@ fn globalVarDecl( |
| 3436 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); | 3529 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); |
| 3437 | try block_scope.setBlockBody(block_inst); | 3530 | try block_scope.setBlockBody(block_inst); |
| 3438 | | 3531 | |
| 3439 | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); | | |
| 3440 | { | 3532 | { |
| 3441 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); | 3533 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3442 | const casted = @bitCast([4]u32, contents_hash); | 3534 | const casted = @bitCast([4]u32, contents_hash); |
| 3443 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3535 | wip_members.appendToDeclSlice(&casted); |
| 3444 | } | 3536 | } |
| 3445 | { | 3537 | { |
| 3446 | const line_delta = block_scope.decl_line - gz.decl_line; | 3538 | const line_delta = block_scope.decl_line - gz.decl_line; |
| 3447 | wip_decls.payload.appendAssumeCapacity(line_delta); | 3539 | wip_members.appendToDecl(line_delta); |
| 3448 | } | 3540 | } |
| 3449 | wip_decls.payload.appendAssumeCapacity(name_str_index); | 3541 | wip_members.appendToDecl(name_str_index); |
| 3450 | wip_decls.payload.appendAssumeCapacity(block_inst); | 3542 | wip_members.appendToDecl(block_inst); |
| 3451 | if (align_inst != .none) { | 3543 | if (align_inst != .none) { |
| 3452 | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); | 3544 | wip_members.appendToDecl(@enumToInt(align_inst)); |
| 3453 | } | 3545 | } |
| 3454 | if (has_section_or_addrspace) { | 3546 | if (has_section_or_addrspace) { |
| 3455 | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); | 3547 | wip_members.appendToDecl(@enumToInt(section_inst)); |
| 3456 | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); | 3548 | wip_members.appendToDecl(@enumToInt(addrspace_inst)); |
| 3457 | } | 3549 | } |
| 3458 | } | 3550 | } |
| 3459 | | 3551 | |
| ... | @@ -3461,18 +3553,17 @@ fn comptimeDecl( | ... | @@ -3461,18 +3553,17 @@ fn comptimeDecl( |
| 3461 | astgen: *AstGen, | 3553 | astgen: *AstGen, |
| 3462 | gz: *GenZir, | 3554 | gz: *GenZir, |
| 3463 | scope: *Scope, | 3555 | scope: *Scope, |
| 3464 | wip_decls: *WipDecls, | 3556 | wip_members: *WipMembers, |
| 3465 | node: Ast.Node.Index, | 3557 | node: Ast.Node.Index, |
| 3466 | ) InnerError!void { | 3558 | ) InnerError!void { |
| 3467 | const gpa = astgen.gpa; | | |
| 3468 | const tree = astgen.tree; | 3559 | const tree = astgen.tree; |
| 3469 | const node_datas = tree.nodes.items(.data); | 3560 | const node_datas = tree.nodes.items(.data); |
| 3470 | const body_node = node_datas[node].lhs; | 3561 | const body_node = node_datas[node].lhs; |
| 3471 | | 3562 | |
| 3472 | // Up top so the ZIR instruction index marks the start range of this | 3563 | // Up top so the ZIR instruction index marks the start range of this |
| 3473 | // top-level declaration. | 3564 | // top-level declaration. |
| 3474 | const block_inst = try gz.addBlock(.block_inline, node); | 3565 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3475 | try wip_decls.next(gpa, false, false, false, false); | 3566 | wip_members.nextDecl(false, false, false, false); |
| 3476 | | 3567 | |
| 3477 | var decl_block: GenZir = .{ | 3568 | var decl_block: GenZir = .{ |
| 3478 | .force_comptime = true, | 3569 | .force_comptime = true, |
| ... | @@ -3481,37 +3572,37 @@ fn comptimeDecl( | ... | @@ -3481,37 +3572,37 @@ fn comptimeDecl( |
| 3481 | .decl_line = gz.calcLine(node), | 3572 | .decl_line = gz.calcLine(node), |
| 3482 | .parent = scope, | 3573 | .parent = scope, |
| 3483 | .astgen = astgen, | 3574 | .astgen = astgen, |
| | 3575 | .instructions = gz.instructions, |
| | 3576 | .instructions_top = gz.instructions.items.len, |
| 3484 | }; | 3577 | }; |
| 3485 | defer decl_block.instructions.deinit(gpa); | 3578 | defer decl_block.unstack(); |
| 3486 | | 3579 | |
| 3487 | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); | 3580 | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); |
| 3488 | if (decl_block.instructions.items.len == 0 or !decl_block.refIsNoReturn(block_result)) { | 3581 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { |
| 3489 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); | 3582 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); |
| 3490 | } | 3583 | } |
| 3491 | try decl_block.setBlockBody(block_inst); | 3584 | try decl_block.setBlockBody(block_inst); |
| 3492 | | 3585 | |
| 3493 | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); | | |
| 3494 | { | 3586 | { |
| 3495 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); | 3587 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3496 | const casted = @bitCast([4]u32, contents_hash); | 3588 | const casted = @bitCast([4]u32, contents_hash); |
| 3497 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3589 | wip_members.appendToDeclSlice(&casted); |
| 3498 | } | 3590 | } |
| 3499 | { | 3591 | { |
| 3500 | const line_delta = decl_block.decl_line - gz.decl_line; | 3592 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3501 | wip_decls.payload.appendAssumeCapacity(line_delta); | 3593 | wip_members.appendToDecl(line_delta); |
| 3502 | } | 3594 | } |
| 3503 | wip_decls.payload.appendAssumeCapacity(0); | 3595 | wip_members.appendToDecl(0); |
| 3504 | wip_decls.payload.appendAssumeCapacity(block_inst); | 3596 | wip_members.appendToDecl(block_inst); |
| 3505 | } | 3597 | } |
| 3506 | | 3598 | |
| 3507 | fn usingnamespaceDecl( | 3599 | fn usingnamespaceDecl( |
| 3508 | astgen: *AstGen, | 3600 | astgen: *AstGen, |
| 3509 | gz: *GenZir, | 3601 | gz: *GenZir, |
| 3510 | scope: *Scope, | 3602 | scope: *Scope, |
| 3511 | wip_decls: *WipDecls, | 3603 | wip_members: *WipMembers, |
| 3512 | node: Ast.Node.Index, | 3604 | node: Ast.Node.Index, |
| 3513 | ) InnerError!void { | 3605 | ) InnerError!void { |
| 3514 | const gpa = astgen.gpa; | | |
| 3515 | const tree = astgen.tree; | 3606 | const tree = astgen.tree; |
| 3516 | const node_datas = tree.nodes.items(.data); | 3607 | const node_datas = tree.nodes.items(.data); |
| 3517 | | 3608 | |
| ... | @@ -3524,8 +3615,8 @@ fn usingnamespaceDecl( | ... | @@ -3524,8 +3615,8 @@ fn usingnamespaceDecl( |
| 3524 | }; | 3615 | }; |
| 3525 | // Up top so the ZIR instruction index marks the start range of this | 3616 | // Up top so the ZIR instruction index marks the start range of this |
| 3526 | // top-level declaration. | 3617 | // top-level declaration. |
| 3527 | const block_inst = try gz.addBlock(.block_inline, node); | 3618 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3528 | try wip_decls.next(gpa, is_pub, true, false, false); | 3619 | wip_members.nextDecl(is_pub, true, false, false); |
| 3529 | | 3620 | |
| 3530 | var decl_block: GenZir = .{ | 3621 | var decl_block: GenZir = .{ |
| 3531 | .force_comptime = true, | 3622 | .force_comptime = true, |
| ... | @@ -3534,44 +3625,44 @@ fn usingnamespaceDecl( | ... | @@ -3534,44 +3625,44 @@ fn usingnamespaceDecl( |
| 3534 | .decl_line = gz.calcLine(node), | 3625 | .decl_line = gz.calcLine(node), |
| 3535 | .parent = scope, | 3626 | .parent = scope, |
| 3536 | .astgen = astgen, | 3627 | .astgen = astgen, |
| | 3628 | .instructions = gz.instructions, |
| | 3629 | .instructions_top = gz.instructions.items.len, |
| 3537 | }; | 3630 | }; |
| 3538 | defer decl_block.instructions.deinit(gpa); | 3631 | defer decl_block.unstack(); |
| 3539 | | 3632 | |
| 3540 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); | 3633 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 3541 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); | 3634 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); |
| 3542 | try decl_block.setBlockBody(block_inst); | 3635 | try decl_block.setBlockBody(block_inst); |
| 3543 | | 3636 | |
| 3544 | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); | | |
| 3545 | { | 3637 | { |
| 3546 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); | 3638 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3547 | const casted = @bitCast([4]u32, contents_hash); | 3639 | const casted = @bitCast([4]u32, contents_hash); |
| 3548 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3640 | wip_members.appendToDeclSlice(&casted); |
| 3549 | } | 3641 | } |
| 3550 | { | 3642 | { |
| 3551 | const line_delta = decl_block.decl_line - gz.decl_line; | 3643 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3552 | wip_decls.payload.appendAssumeCapacity(line_delta); | 3644 | wip_members.appendToDecl(line_delta); |
| 3553 | } | 3645 | } |
| 3554 | wip_decls.payload.appendAssumeCapacity(0); | 3646 | wip_members.appendToDecl(0); |
| 3555 | wip_decls.payload.appendAssumeCapacity(block_inst); | 3647 | wip_members.appendToDecl(block_inst); |
| 3556 | } | 3648 | } |
| 3557 | | 3649 | |
| 3558 | fn testDecl( | 3650 | fn testDecl( |
| 3559 | astgen: *AstGen, | 3651 | astgen: *AstGen, |
| 3560 | gz: *GenZir, | 3652 | gz: *GenZir, |
| 3561 | scope: *Scope, | 3653 | scope: *Scope, |
| 3562 | wip_decls: *WipDecls, | 3654 | wip_members: *WipMembers, |
| 3563 | node: Ast.Node.Index, | 3655 | node: Ast.Node.Index, |
| 3564 | ) InnerError!void { | 3656 | ) InnerError!void { |
| 3565 | const gpa = astgen.gpa; | | |
| 3566 | const tree = astgen.tree; | 3657 | const tree = astgen.tree; |
| 3567 | const node_datas = tree.nodes.items(.data); | 3658 | const node_datas = tree.nodes.items(.data); |
| 3568 | const body_node = node_datas[node].rhs; | 3659 | const body_node = node_datas[node].rhs; |
| 3569 | | 3660 | |
| 3570 | // Up top so the ZIR instruction index marks the start range of this | 3661 | // Up top so the ZIR instruction index marks the start range of this |
| 3571 | // top-level declaration. | 3662 | // top-level declaration. |
| 3572 | const block_inst = try gz.addBlock(.block_inline, node); | 3663 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3573 | | 3664 | |
| 3574 | try wip_decls.next(gpa, false, false, false, false); | 3665 | wip_members.nextDecl(false, false, false, false); |
| 3575 | | 3666 | |
| 3576 | var decl_block: GenZir = .{ | 3667 | var decl_block: GenZir = .{ |
| 3577 | .force_comptime = true, | 3668 | .force_comptime = true, |
| ... | @@ -3580,8 +3671,10 @@ fn testDecl( | ... | @@ -3580,8 +3671,10 @@ fn testDecl( |
| 3580 | .decl_line = gz.calcLine(node), | 3671 | .decl_line = gz.calcLine(node), |
| 3581 | .parent = scope, | 3672 | .parent = scope, |
| 3582 | .astgen = astgen, | 3673 | .astgen = astgen, |
| | 3674 | .instructions = gz.instructions, |
| | 3675 | .instructions_top = gz.instructions.items.len, |
| 3583 | }; | 3676 | }; |
| 3584 | defer decl_block.instructions.deinit(gpa); | 3677 | defer decl_block.unstack(); |
| 3585 | | 3678 | |
| 3586 | const test_name: u32 = blk: { | 3679 | const test_name: u32 = blk: { |
| 3587 | const main_tokens = tree.nodes.items(.main_token); | 3680 | const main_tokens = tree.nodes.items(.main_token); |
| ... | @@ -3602,8 +3695,10 @@ fn testDecl( | ... | @@ -3602,8 +3695,10 @@ fn testDecl( |
| 3602 | .decl_line = decl_block.decl_line, | 3695 | .decl_line = decl_block.decl_line, |
| 3603 | .parent = &decl_block.base, | 3696 | .parent = &decl_block.base, |
| 3604 | .astgen = astgen, | 3697 | .astgen = astgen, |
| | 3698 | .instructions = decl_block.instructions, |
| | 3699 | .instructions_top = decl_block.instructions.items.len, |
| 3605 | }; | 3700 | }; |
| 3606 | defer fn_block.instructions.deinit(gpa); | 3701 | defer fn_block.unstack(); |
| 3607 | | 3702 | |
| 3608 | const prev_fn_block = astgen.fn_block; | 3703 | const prev_fn_block = astgen.fn_block; |
| 3609 | astgen.fn_block = &fn_block; | 3704 | astgen.fn_block = &fn_block; |
| ... | @@ -3616,7 +3711,7 @@ fn testDecl( | ... | @@ -3616,7 +3711,7 @@ fn testDecl( |
| 3616 | const lbrace_column = @intCast(u32, astgen.source_column); | 3711 | const lbrace_column = @intCast(u32, astgen.source_column); |
| 3617 | | 3712 | |
| 3618 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); | 3713 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); |
| 3619 | if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) { | 3714 | if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) { |
| 3620 | // Since we are adding the return instruction here, we must handle the coercion. | 3715 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3621 | // We do this by using the `ret_coerce` instruction. | 3716 | // We do this by using the `ret_coerce` instruction. |
| 3622 | _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); | 3717 | _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | @@ -3627,9 +3722,9 @@ fn testDecl( | ... | @@ -3627,9 +3722,9 @@ fn testDecl( |
| 3627 | .lbrace_line = lbrace_line, | 3722 | .lbrace_line = lbrace_line, |
| 3628 | .lbrace_column = lbrace_column, | 3723 | .lbrace_column = lbrace_column, |
| 3629 | .param_block = block_inst, | 3724 | .param_block = block_inst, |
| 3630 | .ret_ty = &.{}, | 3725 | .ret_gz = null, |
| 3631 | .ret_br = 0, | 3726 | .ret_br = 0, |
| 3632 | .body = fn_block.instructions.items, | 3727 | .body_gz = &fn_block, |
| 3633 | .cc = .none, | 3728 | .cc = .none, |
| 3634 | .align_inst = .none, | 3729 | .align_inst = .none, |
| 3635 | .lib_name = 0, | 3730 | .lib_name = 0, |
| ... | @@ -3642,18 +3737,17 @@ fn testDecl( | ... | @@ -3642,18 +3737,17 @@ fn testDecl( |
| 3642 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); | 3737 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); |
| 3643 | try decl_block.setBlockBody(block_inst); | 3738 | try decl_block.setBlockBody(block_inst); |
| 3644 | | 3739 | |
| 3645 | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); | | |
| 3646 | { | 3740 | { |
| 3647 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); | 3741 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3648 | const casted = @bitCast([4]u32, contents_hash); | 3742 | const casted = @bitCast([4]u32, contents_hash); |
| 3649 | wip_decls.payload.appendSliceAssumeCapacity(&casted); | 3743 | wip_members.appendToDeclSlice(&casted); |
| 3650 | } | 3744 | } |
| 3651 | { | 3745 | { |
| 3652 | const line_delta = decl_block.decl_line - gz.decl_line; | 3746 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3653 | wip_decls.payload.appendAssumeCapacity(line_delta); | 3747 | wip_members.appendToDecl(line_delta); |
| 3654 | } | 3748 | } |
| 3655 | wip_decls.payload.appendAssumeCapacity(test_name); | 3749 | wip_members.appendToDecl(test_name); |
| 3656 | wip_decls.payload.appendAssumeCapacity(block_inst); | 3750 | wip_members.appendToDecl(block_inst); |
| 3657 | } | 3751 | } |
| 3658 | | 3752 | |
| 3659 | fn structDeclInner( | 3753 | fn structDeclInner( |
| ... | @@ -3681,7 +3775,6 @@ fn structDeclInner( | ... | @@ -3681,7 +3775,6 @@ fn structDeclInner( |
| 3681 | const gpa = astgen.gpa; | 3775 | const gpa = astgen.gpa; |
| 3682 | const tree = astgen.tree; | 3776 | const tree = astgen.tree; |
| 3683 | const node_tags = tree.nodes.items(.tag); | 3777 | const node_tags = tree.nodes.items(.tag); |
| 3684 | const node_datas = tree.nodes.items(.data); | | |
| 3685 | | 3778 | |
| 3686 | var namespace: Scope.Namespace = .{ | 3779 | var namespace: Scope.Namespace = .{ |
| 3687 | .parent = scope, | 3780 | .parent = scope, |
| ... | @@ -3701,162 +3794,28 @@ fn structDeclInner( | ... | @@ -3701,162 +3794,28 @@ fn structDeclInner( |
| 3701 | .astgen = astgen, | 3794 | .astgen = astgen, |
| 3702 | .force_comptime = true, | 3795 | .force_comptime = true, |
| 3703 | .in_defer = false, | 3796 | .in_defer = false, |
| | 3797 | .instructions = gz.instructions, |
| | 3798 | .instructions_top = gz.instructions.items.len, |
| 3704 | }; | 3799 | }; |
| 3705 | defer block_scope.instructions.deinit(gpa); | 3800 | defer block_scope.unstack(); |
| 3706 | | | |
| 3707 | try astgen.scanDecls(&namespace, container_decl.ast.members); | | |
| 3708 | | | |
| 3709 | var wip_decls: WipDecls = .{}; | | |
| 3710 | defer wip_decls.deinit(gpa); | | |
| 3711 | | 3801 | |
| 3712 | // We don't know which members are fields until we iterate, so cannot do | 3802 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3713 | // an accurate ensureTotalCapacity yet. | 3803 | const field_count = @intCast(u32, container_decl.ast.members.len - decl_count); |
| 3714 | var fields_data = ArrayListUnmanaged(u32){}; | | |
| 3715 | defer fields_data.deinit(gpa); | | |
| 3716 | | 3804 | |
| 3717 | const bits_per_field = 4; | 3805 | const bits_per_field = 4; |
| 3718 | const fields_per_u32 = 32 / bits_per_field; | 3806 | const max_field_size = 4; |
| 3719 | // We only need this if there are greater than fields_per_u32 fields. | 3807 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 3720 | var bit_bag = ArrayListUnmanaged(u32){}; | 3808 | defer wip_members.deinit(); |
| 3721 | defer bit_bag.deinit(gpa); | | |
| 3722 | | 3809 | |
| 3723 | var known_has_bits = false; | 3810 | var known_has_bits = false; |
| 3724 | var cur_bit_bag: u32 = 0; | | |
| 3725 | var field_index: usize = 0; | | |
| 3726 | for (container_decl.ast.members) |member_node| { | 3811 | for (container_decl.ast.members) |member_node| { |
| 3727 | const member = switch (node_tags[member_node]) { | 3812 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 3728 | .container_field_init => tree.containerFieldInit(member_node), | 3813 | .decl => continue, |
| 3729 | .container_field_align => tree.containerFieldAlign(member_node), | 3814 | .field => |field| field, |
| 3730 | .container_field => tree.containerField(member_node), | | |
| 3731 | | | |
| 3732 | .fn_decl => { | | |
| 3733 | const fn_proto = node_datas[member_node].lhs; | | |
| 3734 | const body = node_datas[member_node].rhs; | | |
| 3735 | switch (node_tags[fn_proto]) { | | |
| 3736 | .fn_proto_simple => { | | |
| 3737 | var params: [1]Ast.Node.Index = undefined; | | |
| 3738 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { | | |
| 3739 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3740 | error.AnalysisFail => {}, | | |
| 3741 | }; | | |
| 3742 | continue; | | |
| 3743 | }, | | |
| 3744 | .fn_proto_multi => { | | |
| 3745 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { | | |
| 3746 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3747 | error.AnalysisFail => {}, | | |
| 3748 | }; | | |
| 3749 | continue; | | |
| 3750 | }, | | |
| 3751 | .fn_proto_one => { | | |
| 3752 | var params: [1]Ast.Node.Index = undefined; | | |
| 3753 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { | | |
| 3754 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3755 | error.AnalysisFail => {}, | | |
| 3756 | }; | | |
| 3757 | continue; | | |
| 3758 | }, | | |
| 3759 | .fn_proto => { | | |
| 3760 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { | | |
| 3761 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3762 | error.AnalysisFail => {}, | | |
| 3763 | }; | | |
| 3764 | continue; | | |
| 3765 | }, | | |
| 3766 | else => unreachable, | | |
| 3767 | } | | |
| 3768 | }, | | |
| 3769 | .fn_proto_simple => { | | |
| 3770 | var params: [1]Ast.Node.Index = undefined; | | |
| 3771 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { | | |
| 3772 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3773 | error.AnalysisFail => {}, | | |
| 3774 | }; | | |
| 3775 | continue; | | |
| 3776 | }, | | |
| 3777 | .fn_proto_multi => { | | |
| 3778 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { | | |
| 3779 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3780 | error.AnalysisFail => {}, | | |
| 3781 | }; | | |
| 3782 | continue; | | |
| 3783 | }, | | |
| 3784 | .fn_proto_one => { | | |
| 3785 | var params: [1]Ast.Node.Index = undefined; | | |
| 3786 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { | | |
| 3787 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3788 | error.AnalysisFail => {}, | | |
| 3789 | }; | | |
| 3790 | continue; | | |
| 3791 | }, | | |
| 3792 | .fn_proto => { | | |
| 3793 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { | | |
| 3794 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3795 | error.AnalysisFail => {}, | | |
| 3796 | }; | | |
| 3797 | continue; | | |
| 3798 | }, | | |
| 3799 | | | |
| 3800 | .global_var_decl => { | | |
| 3801 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { | | |
| 3802 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3803 | error.AnalysisFail => {}, | | |
| 3804 | }; | | |
| 3805 | continue; | | |
| 3806 | }, | | |
| 3807 | .local_var_decl => { | | |
| 3808 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { | | |
| 3809 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3810 | error.AnalysisFail => {}, | | |
| 3811 | }; | | |
| 3812 | continue; | | |
| 3813 | }, | | |
| 3814 | .simple_var_decl => { | | |
| 3815 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { | | |
| 3816 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3817 | error.AnalysisFail => {}, | | |
| 3818 | }; | | |
| 3819 | continue; | | |
| 3820 | }, | | |
| 3821 | .aligned_var_decl => { | | |
| 3822 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { | | |
| 3823 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3824 | error.AnalysisFail => {}, | | |
| 3825 | }; | | |
| 3826 | continue; | | |
| 3827 | }, | | |
| 3828 | | | |
| 3829 | .@"comptime" => { | | |
| 3830 | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 3831 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3832 | error.AnalysisFail => {}, | | |
| 3833 | }; | | |
| 3834 | continue; | | |
| 3835 | }, | | |
| 3836 | .@"usingnamespace" => { | | |
| 3837 | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 3838 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3839 | error.AnalysisFail => {}, | | |
| 3840 | }; | | |
| 3841 | continue; | | |
| 3842 | }, | | |
| 3843 | .test_decl => { | | |
| 3844 | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 3845 | error.OutOfMemory => return error.OutOfMemory, | | |
| 3846 | error.AnalysisFail => {}, | | |
| 3847 | }; | | |
| 3848 | continue; | | |
| 3849 | }, | | |
| 3850 | else => unreachable, | | |
| 3851 | }; | 3815 | }; |
| 3852 | if (field_index % fields_per_u32 == 0 and field_index != 0) { | | |
| 3853 | try bit_bag.append(gpa, cur_bit_bag); | | |
| 3854 | cur_bit_bag = 0; | | |
| 3855 | } | | |
| 3856 | try fields_data.ensureUnusedCapacity(gpa, 4); | | |
| 3857 | | 3816 | |
| 3858 | const field_name = try astgen.identAsString(member.ast.name_token); | 3817 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 3859 | fields_data.appendAssumeCapacity(field_name); | 3818 | wip_members.appendToField(field_name); |
| 3860 | | 3819 | |
| 3861 | if (member.ast.type_expr == 0) { | 3820 | if (member.ast.type_expr == 0) { |
| 3862 | return astgen.failTok(member.ast.name_token, "struct field missing type", .{}); | 3821 | return astgen.failTok(member.ast.name_token, "struct field missing type", .{}); |
| ... | @@ -3866,7 +3825,7 @@ fn structDeclInner( | ... | @@ -3866,7 +3825,7 @@ fn structDeclInner( |
| 3866 | .none | 3825 | .none |
| 3867 | else | 3826 | else |
| 3868 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | 3827 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| 3869 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); | 3828 | wip_members.appendToField(@enumToInt(field_type)); |
| 3870 | | 3829 | |
| 3871 | known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); | 3830 | known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); |
| 3872 | | 3831 | |
| ... | @@ -3874,79 +3833,47 @@ fn structDeclInner( | ... | @@ -3874,79 +3833,47 @@ fn structDeclInner( |
| 3874 | const have_value = member.ast.value_expr != 0; | 3833 | const have_value = member.ast.value_expr != 0; |
| 3875 | const is_comptime = member.comptime_token != null; | 3834 | const is_comptime = member.comptime_token != null; |
| 3876 | const unused = false; | 3835 | const unused = false; |
| 3877 | cur_bit_bag = (cur_bit_bag >> bits_per_field) | | 3836 | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused }); |
| 3878 | (@as(u32, @boolToInt(have_align)) << 28) | | | |
| 3879 | (@as(u32, @boolToInt(have_value)) << 29) | | | |
| 3880 | (@as(u32, @boolToInt(is_comptime)) << 30) | | | |
| 3881 | (@as(u32, @boolToInt(unused)) << 31); | | |
| 3882 | | 3837 | |
| 3883 | if (have_align) { | 3838 | if (have_align) { |
| 3884 | const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr); | 3839 | const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr); |
| 3885 | fields_data.appendAssumeCapacity(@enumToInt(align_inst)); | 3840 | wip_members.appendToField(@enumToInt(align_inst)); |
| 3886 | } | 3841 | } |
| 3887 | if (have_value) { | 3842 | if (have_value) { |
| 3888 | const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type }; | 3843 | const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type }; |
| 3889 | | 3844 | |
| 3890 | const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr); | 3845 | const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr); |
| 3891 | fields_data.appendAssumeCapacity(@enumToInt(default_inst)); | 3846 | wip_members.appendToField(@enumToInt(default_inst)); |
| 3892 | } else if (member.comptime_token) |comptime_token| { | 3847 | } else if (member.comptime_token) |comptime_token| { |
| 3893 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); | 3848 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); |
| 3894 | } | 3849 | } |
| 3895 | | | |
| 3896 | field_index += 1; | | |
| 3897 | } | | |
| 3898 | { | | |
| 3899 | const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32); | | |
| 3900 | if (empty_slot_count < fields_per_u32) { | | |
| 3901 | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field); | | |
| 3902 | } | | |
| 3903 | } | | |
| 3904 | { | | |
| 3905 | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); | | |
| 3906 | if (empty_slot_count < WipDecls.fields_per_u32) { | | |
| 3907 | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); | | |
| 3908 | } | | |
| 3909 | } | 3850 | } |
| 3910 | | 3851 | |
| 3911 | if (block_scope.instructions.items.len != 0) { | 3852 | if (!block_scope.isEmpty()) { |
| 3912 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 3853 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 3913 | } | 3854 | } |
| 3914 | | 3855 | |
| | 3856 | const body = block_scope.instructionsSlice(); |
| | 3857 | |
| 3915 | try gz.setStruct(decl_inst, .{ | 3858 | try gz.setStruct(decl_inst, .{ |
| 3916 | .src_node = node, | 3859 | .src_node = node, |
| 3917 | .layout = layout, | 3860 | .layout = layout, |
| 3918 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 3861 | .body_len = @intCast(u32, body.len), |
| 3919 | .fields_len = @intCast(u32, field_index), | 3862 | .fields_len = field_count, |
| 3920 | .decls_len = @intCast(u32, wip_decls.decl_index), | 3863 | .decls_len = decl_count, |
| 3921 | .known_has_bits = known_has_bits, | 3864 | .known_has_bits = known_has_bits, |
| 3922 | }); | 3865 | }); |
| 3923 | | 3866 | |
| 3924 | // zig fmt: off | 3867 | wip_members.finishBits(bits_per_field); |
| 3925 | try astgen.extra.ensureUnusedCapacity(gpa, | 3868 | const decls_slice = wip_members.declsSlice(); |
| 3926 | bit_bag.items.len + | 3869 | const fields_slice = wip_members.fieldsSlice(); |
| 3927 | @boolToInt(wip_decls.decl_index != 0) + | 3870 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 3928 | wip_decls.payload.items.len + | 3871 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 3929 | block_scope.instructions.items.len + | 3872 | astgen.extra.appendSliceAssumeCapacity(body); |
| 3930 | wip_decls.bit_bag.items.len + | 3873 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 3931 | @boolToInt(field_index != 0) + | | |
| 3932 | fields_data.items.len | | |
| 3933 | ); | | |
| 3934 | // zig fmt: on | | |
| 3935 | | | |
| 3936 | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. | | |
| 3937 | if (wip_decls.decl_index != 0) { | | |
| 3938 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | | |
| 3939 | } | | |
| 3940 | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); | | |
| 3941 | | | |
| 3942 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | | |
| 3943 | | | |
| 3944 | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. | | |
| 3945 | if (field_index != 0) { | | |
| 3946 | astgen.extra.appendAssumeCapacity(cur_bit_bag); | | |
| 3947 | } | | |
| 3948 | astgen.extra.appendSliceAssumeCapacity(fields_data.items); | | |
| 3949 | | 3874 | |
| | 3875 | block_scope.unstack(); |
| | 3876 | try gz.addNamespaceCaptures(&namespace); |
| 3950 | return indexToRef(decl_inst); | 3877 | return indexToRef(decl_inst); |
| 3951 | } | 3878 | } |
| 3952 | | 3879 | |
| ... | @@ -3965,7 +3892,6 @@ fn unionDeclInner( | ... | @@ -3965,7 +3892,6 @@ fn unionDeclInner( |
| 3965 | const gpa = astgen.gpa; | 3892 | const gpa = astgen.gpa; |
| 3966 | const tree = astgen.tree; | 3893 | const tree = astgen.tree; |
| 3967 | const node_tags = tree.nodes.items(.tag); | 3894 | const node_tags = tree.nodes.items(.tag); |
| 3968 | const node_datas = tree.nodes.items(.data); | | |
| 3969 | | 3895 | |
| 3970 | var namespace: Scope.Namespace = .{ | 3896 | var namespace: Scope.Namespace = .{ |
| 3971 | .parent = scope, | 3897 | .parent = scope, |
| ... | @@ -3985,192 +3911,54 @@ fn unionDeclInner( | ... | @@ -3985,192 +3911,54 @@ fn unionDeclInner( |
| 3985 | .astgen = astgen, | 3911 | .astgen = astgen, |
| 3986 | .force_comptime = true, | 3912 | .force_comptime = true, |
| 3987 | .in_defer = false, | 3913 | .in_defer = false, |
| | 3914 | .instructions = gz.instructions, |
| | 3915 | .instructions_top = gz.instructions.items.len, |
| 3988 | }; | 3916 | }; |
| 3989 | defer block_scope.instructions.deinit(gpa); | 3917 | defer block_scope.unstack(); |
| 3990 | | 3918 | |
| 3991 | try astgen.scanDecls(&namespace, members); | 3919 | const decl_count = try astgen.scanDecls(&namespace, members); |
| | 3920 | const field_count = @intCast(u32, members.len - decl_count); |
| 3992 | | 3921 | |
| 3993 | const arg_inst: Zir.Inst.Ref = if (arg_node != 0) | 3922 | const arg_inst: Zir.Inst.Ref = if (arg_node != 0) |
| 3994 | try typeExpr(&block_scope, &namespace.base, arg_node) | 3923 | try typeExpr(&block_scope, &namespace.base, arg_node) |
| 3995 | else | 3924 | else |
| 3996 | .none; | 3925 | .none; |
| 3997 | | 3926 | |
| 3998 | var wip_decls: WipDecls = .{}; | | |
| 3999 | defer wip_decls.deinit(gpa); | | |
| 4000 | | | |
| 4001 | // We don't know which members are fields until we iterate, so cannot do | | |
| 4002 | // an accurate ensureTotalCapacity yet. | | |
| 4003 | var fields_data = ArrayListUnmanaged(u32){}; | | |
| 4004 | defer fields_data.deinit(gpa); | | |
| 4005 | | | |
| 4006 | const bits_per_field = 4; | 3927 | const bits_per_field = 4; |
| 4007 | const fields_per_u32 = 32 / bits_per_field; | 3928 | const max_field_size = 4; |
| 4008 | // We only need this if there are greater than fields_per_u32 fields. | 3929 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 4009 | var bit_bag = ArrayListUnmanaged(u32){}; | 3930 | defer wip_members.deinit(); |
| 4010 | defer bit_bag.deinit(gpa); | | |
| 4011 | | 3931 | |
| 4012 | var cur_bit_bag: u32 = 0; | | |
| 4013 | var field_index: usize = 0; | | |
| 4014 | for (members) |member_node| { | 3932 | for (members) |member_node| { |
| 4015 | const member = switch (node_tags[member_node]) { | 3933 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 4016 | .container_field_init => tree.containerFieldInit(member_node), | 3934 | .decl => continue, |
| 4017 | .container_field_align => tree.containerFieldAlign(member_node), | 3935 | .field => |field| field, |
| 4018 | .container_field => tree.containerField(member_node), | | |
| 4019 | | | |
| 4020 | .fn_decl => { | | |
| 4021 | const fn_proto = node_datas[member_node].lhs; | | |
| 4022 | const body = node_datas[member_node].rhs; | | |
| 4023 | switch (node_tags[fn_proto]) { | | |
| 4024 | .fn_proto_simple => { | | |
| 4025 | var params: [1]Ast.Node.Index = undefined; | | |
| 4026 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { | | |
| 4027 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4028 | error.AnalysisFail => {}, | | |
| 4029 | }; | | |
| 4030 | continue; | | |
| 4031 | }, | | |
| 4032 | .fn_proto_multi => { | | |
| 4033 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { | | |
| 4034 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4035 | error.AnalysisFail => {}, | | |
| 4036 | }; | | |
| 4037 | continue; | | |
| 4038 | }, | | |
| 4039 | .fn_proto_one => { | | |
| 4040 | var params: [1]Ast.Node.Index = undefined; | | |
| 4041 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { | | |
| 4042 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4043 | error.AnalysisFail => {}, | | |
| 4044 | }; | | |
| 4045 | continue; | | |
| 4046 | }, | | |
| 4047 | .fn_proto => { | | |
| 4048 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { | | |
| 4049 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4050 | error.AnalysisFail => {}, | | |
| 4051 | }; | | |
| 4052 | continue; | | |
| 4053 | }, | | |
| 4054 | else => unreachable, | | |
| 4055 | } | | |
| 4056 | }, | | |
| 4057 | .fn_proto_simple => { | | |
| 4058 | var params: [1]Ast.Node.Index = undefined; | | |
| 4059 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { | | |
| 4060 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4061 | error.AnalysisFail => {}, | | |
| 4062 | }; | | |
| 4063 | continue; | | |
| 4064 | }, | | |
| 4065 | .fn_proto_multi => { | | |
| 4066 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { | | |
| 4067 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4068 | error.AnalysisFail => {}, | | |
| 4069 | }; | | |
| 4070 | continue; | | |
| 4071 | }, | | |
| 4072 | .fn_proto_one => { | | |
| 4073 | var params: [1]Ast.Node.Index = undefined; | | |
| 4074 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { | | |
| 4075 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4076 | error.AnalysisFail => {}, | | |
| 4077 | }; | | |
| 4078 | continue; | | |
| 4079 | }, | | |
| 4080 | .fn_proto => { | | |
| 4081 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { | | |
| 4082 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4083 | error.AnalysisFail => {}, | | |
| 4084 | }; | | |
| 4085 | continue; | | |
| 4086 | }, | | |
| 4087 | | | |
| 4088 | .global_var_decl => { | | |
| 4089 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { | | |
| 4090 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4091 | error.AnalysisFail => {}, | | |
| 4092 | }; | | |
| 4093 | continue; | | |
| 4094 | }, | | |
| 4095 | .local_var_decl => { | | |
| 4096 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { | | |
| 4097 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4098 | error.AnalysisFail => {}, | | |
| 4099 | }; | | |
| 4100 | continue; | | |
| 4101 | }, | | |
| 4102 | .simple_var_decl => { | | |
| 4103 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { | | |
| 4104 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4105 | error.AnalysisFail => {}, | | |
| 4106 | }; | | |
| 4107 | continue; | | |
| 4108 | }, | | |
| 4109 | .aligned_var_decl => { | | |
| 4110 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { | | |
| 4111 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4112 | error.AnalysisFail => {}, | | |
| 4113 | }; | | |
| 4114 | continue; | | |
| 4115 | }, | | |
| 4116 | | | |
| 4117 | .@"comptime" => { | | |
| 4118 | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4119 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4120 | error.AnalysisFail => {}, | | |
| 4121 | }; | | |
| 4122 | continue; | | |
| 4123 | }, | | |
| 4124 | .@"usingnamespace" => { | | |
| 4125 | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4126 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4127 | error.AnalysisFail => {}, | | |
| 4128 | }; | | |
| 4129 | continue; | | |
| 4130 | }, | | |
| 4131 | .test_decl => { | | |
| 4132 | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4133 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4134 | error.AnalysisFail => {}, | | |
| 4135 | }; | | |
| 4136 | continue; | | |
| 4137 | }, | | |
| 4138 | else => unreachable, | | |
| 4139 | }; | 3936 | }; |
| 4140 | if (field_index % fields_per_u32 == 0 and field_index != 0) { | | |
| 4141 | try bit_bag.append(gpa, cur_bit_bag); | | |
| 4142 | cur_bit_bag = 0; | | |
| 4143 | } | | |
| 4144 | if (member.comptime_token) |comptime_token| { | 3937 | if (member.comptime_token) |comptime_token| { |
| 4145 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); | 3938 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 4146 | } | 3939 | } |
| 4147 | try fields_data.ensureUnusedCapacity(gpa, 4); | | |
| 4148 | | 3940 | |
| 4149 | const field_name = try astgen.identAsString(member.ast.name_token); | 3941 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4150 | fields_data.appendAssumeCapacity(field_name); | 3942 | wip_members.appendToField(field_name); |
| 4151 | | 3943 | |
| 4152 | const have_type = member.ast.type_expr != 0; | 3944 | const have_type = member.ast.type_expr != 0; |
| 4153 | const have_align = member.ast.align_expr != 0; | 3945 | const have_align = member.ast.align_expr != 0; |
| 4154 | const have_value = member.ast.value_expr != 0; | 3946 | const have_value = member.ast.value_expr != 0; |
| 4155 | const unused = false; | 3947 | const unused = false; |
| 4156 | cur_bit_bag = (cur_bit_bag >> bits_per_field) | | 3948 | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); |
| 4157 | (@as(u32, @boolToInt(have_type)) << 28) | | | |
| 4158 | (@as(u32, @boolToInt(have_align)) << 29) | | | |
| 4159 | (@as(u32, @boolToInt(have_value)) << 30) | | | |
| 4160 | (@as(u32, @boolToInt(unused)) << 31); | | |
| 4161 | | 3949 | |
| 4162 | if (have_type) { | 3950 | if (have_type) { |
| 4163 | const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") | 3951 | const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") |
| 4164 | .none | 3952 | .none |
| 4165 | else | 3953 | else |
| 4166 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); | 3954 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| 4167 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); | 3955 | wip_members.appendToField(@enumToInt(field_type)); |
| 4168 | } else if (arg_inst == .none and !have_auto_enum) { | 3956 | } else if (arg_inst == .none and !have_auto_enum) { |
| 4169 | return astgen.failNode(member_node, "union field missing type", .{}); | 3957 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 4170 | } | 3958 | } |
| 4171 | if (have_align) { | 3959 | if (have_align) { |
| 4172 | const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); | 3960 | const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); |
| 4173 | fields_data.appendAssumeCapacity(@enumToInt(align_inst)); | 3961 | wip_members.appendToField(@enumToInt(align_inst)); |
| 4174 | } | 3962 | } |
| 4175 | if (have_value) { | 3963 | if (have_value) { |
| 4176 | if (arg_inst == .none) { | 3964 | if (arg_inst == .none) { |
| ... | @@ -4202,65 +3990,39 @@ fn unionDeclInner( | ... | @@ -4202,65 +3990,39 @@ fn unionDeclInner( |
| 4202 | ); | 3990 | ); |
| 4203 | } | 3991 | } |
| 4204 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); | 3992 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4205 | fields_data.appendAssumeCapacity(@enumToInt(tag_value)); | 3993 | wip_members.appendToField(@enumToInt(tag_value)); |
| 4206 | } | 3994 | } |
| 4207 | | | |
| 4208 | field_index += 1; | | |
| 4209 | } | 3995 | } |
| 4210 | if (field_index == 0) { | 3996 | if (field_count == 0) { |
| 4211 | return astgen.failNode(node, "union declarations must have at least one tag", .{}); | 3997 | return astgen.failNode(node, "union declarations must have at least one tag", .{}); |
| 4212 | } | 3998 | } |
| 4213 | { | | |
| 4214 | const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32); | | |
| 4215 | if (empty_slot_count < fields_per_u32) { | | |
| 4216 | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field); | | |
| 4217 | } | | |
| 4218 | } | | |
| 4219 | { | | |
| 4220 | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); | | |
| 4221 | if (empty_slot_count < WipDecls.fields_per_u32) { | | |
| 4222 | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); | | |
| 4223 | } | | |
| 4224 | } | | |
| 4225 | | 3999 | |
| 4226 | if (block_scope.instructions.items.len != 0) { | 4000 | if (!block_scope.isEmpty()) { |
| 4227 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 4001 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 4228 | } | 4002 | } |
| 4229 | | 4003 | |
| | 4004 | const body = block_scope.instructionsSlice(); |
| | 4005 | |
| 4230 | try gz.setUnion(decl_inst, .{ | 4006 | try gz.setUnion(decl_inst, .{ |
| 4231 | .src_node = node, | 4007 | .src_node = node, |
| 4232 | .layout = layout, | 4008 | .layout = layout, |
| 4233 | .tag_type = arg_inst, | 4009 | .tag_type = arg_inst, |
| 4234 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 4010 | .body_len = @intCast(u32, body.len), |
| 4235 | .fields_len = @intCast(u32, field_index), | 4011 | .fields_len = field_count, |
| 4236 | .decls_len = @intCast(u32, wip_decls.decl_index), | 4012 | .decls_len = decl_count, |
| 4237 | .auto_enum_tag = have_auto_enum, | 4013 | .auto_enum_tag = have_auto_enum, |
| 4238 | }); | 4014 | }); |
| 4239 | | 4015 | |
| 4240 | // zig fmt: off | 4016 | wip_members.finishBits(bits_per_field); |
| 4241 | try astgen.extra.ensureUnusedCapacity(gpa, | 4017 | const decls_slice = wip_members.declsSlice(); |
| 4242 | bit_bag.items.len + | 4018 | const fields_slice = wip_members.fieldsSlice(); |
| 4243 | @boolToInt(wip_decls.decl_index != 0) + | 4019 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4244 | wip_decls.payload.items.len + | 4020 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4245 | block_scope.instructions.items.len + | 4021 | astgen.extra.appendSliceAssumeCapacity(body); |
| 4246 | wip_decls.bit_bag.items.len + | 4022 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4247 | 1 + // cur_bit_bag | | |
| 4248 | fields_data.items.len | | |
| 4249 | ); | | |
| 4250 | // zig fmt: on | | |
| 4251 | | | |
| 4252 | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. | | |
| 4253 | if (wip_decls.decl_index != 0) { | | |
| 4254 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | | |
| 4255 | } | | |
| 4256 | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); | | |
| 4257 | | | |
| 4258 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | | |
| 4259 | | | |
| 4260 | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. | | |
| 4261 | astgen.extra.appendAssumeCapacity(cur_bit_bag); | | |
| 4262 | astgen.extra.appendSliceAssumeCapacity(fields_data.items); | | |
| 4263 | | 4023 | |
| | 4024 | block_scope.unstack(); |
| | 4025 | try gz.addNamespaceCaptures(&namespace); |
| 4264 | return indexToRef(decl_inst); | 4026 | return indexToRef(decl_inst); |
| 4265 | } | 4027 | } |
| 4266 | | 4028 | |
| ... | @@ -4276,7 +4038,6 @@ fn containerDecl( | ... | @@ -4276,7 +4038,6 @@ fn containerDecl( |
| 4276 | const tree = astgen.tree; | 4038 | const tree = astgen.tree; |
| 4277 | const token_tags = tree.tokens.items(.tag); | 4039 | const token_tags = tree.tokens.items(.tag); |
| 4278 | const node_tags = tree.nodes.items(.tag); | 4040 | const node_tags = tree.nodes.items(.tag); |
| 4279 | const node_datas = tree.nodes.items(.data); | | |
| 4280 | | 4041 | |
| 4281 | const prev_fn_block = astgen.fn_block; | 4042 | const prev_fn_block = astgen.fn_block; |
| 4282 | astgen.fn_block = null; | 4043 | astgen.fn_block = null; |
| ... | @@ -4430,172 +4191,39 @@ fn containerDecl( | ... | @@ -4430,172 +4191,39 @@ fn containerDecl( |
| 4430 | .astgen = astgen, | 4191 | .astgen = astgen, |
| 4431 | .force_comptime = true, | 4192 | .force_comptime = true, |
| 4432 | .in_defer = false, | 4193 | .in_defer = false, |
| | 4194 | .instructions = gz.instructions, |
| | 4195 | .instructions_top = gz.instructions.items.len, |
| 4433 | }; | 4196 | }; |
| 4434 | defer block_scope.instructions.deinit(gpa); | 4197 | defer block_scope.unstack(); |
| 4435 | | 4198 | |
| 4436 | try astgen.scanDecls(&namespace, container_decl.ast.members); | 4199 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4437 | | 4200 | |
| 4438 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) | 4201 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) |
| 4439 | try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg) | 4202 | try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg) |
| 4440 | else | 4203 | else |
| 4441 | .none; | 4204 | .none; |
| 4442 | | 4205 | |
| 4443 | var wip_decls: WipDecls = .{}; | 4206 | const bits_per_field = 1; |
| 4444 | defer wip_decls.deinit(gpa); | 4207 | const max_field_size = 2; |
| 4445 | | 4208 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size); |
| 4446 | var fields_data = ArrayListUnmanaged(u32){}; | 4209 | defer wip_members.deinit(); |
| 4447 | defer fields_data.deinit(gpa); | | |
| 4448 | | | |
| 4449 | try fields_data.ensureTotalCapacity(gpa, counts.total_fields + counts.values); | | |
| 4450 | | | |
| 4451 | // We only need this if there are greater than 32 fields. | | |
| 4452 | var bit_bag = ArrayListUnmanaged(u32){}; | | |
| 4453 | defer bit_bag.deinit(gpa); | | |
| 4454 | | 4210 | |
| 4455 | var cur_bit_bag: u32 = 0; | | |
| 4456 | var field_index: usize = 0; | | |
| 4457 | for (container_decl.ast.members) |member_node| { | 4211 | for (container_decl.ast.members) |member_node| { |
| 4458 | if (member_node == counts.nonexhaustive_node) | 4212 | if (member_node == counts.nonexhaustive_node) |
| 4459 | continue; | 4213 | continue; |
| 4460 | const member = switch (node_tags[member_node]) { | 4214 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 4461 | .container_field_init => tree.containerFieldInit(member_node), | 4215 | .decl => continue, |
| 4462 | .container_field_align => tree.containerFieldAlign(member_node), | 4216 | .field => |field| field, |
| 4463 | .container_field => tree.containerField(member_node), | | |
| 4464 | | | |
| 4465 | .fn_decl => { | | |
| 4466 | const fn_proto = node_datas[member_node].lhs; | | |
| 4467 | const body = node_datas[member_node].rhs; | | |
| 4468 | switch (node_tags[fn_proto]) { | | |
| 4469 | .fn_proto_simple => { | | |
| 4470 | var params: [1]Ast.Node.Index = undefined; | | |
| 4471 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { | | |
| 4472 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4473 | error.AnalysisFail => {}, | | |
| 4474 | }; | | |
| 4475 | continue; | | |
| 4476 | }, | | |
| 4477 | .fn_proto_multi => { | | |
| 4478 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { | | |
| 4479 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4480 | error.AnalysisFail => {}, | | |
| 4481 | }; | | |
| 4482 | continue; | | |
| 4483 | }, | | |
| 4484 | .fn_proto_one => { | | |
| 4485 | var params: [1]Ast.Node.Index = undefined; | | |
| 4486 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { | | |
| 4487 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4488 | error.AnalysisFail => {}, | | |
| 4489 | }; | | |
| 4490 | continue; | | |
| 4491 | }, | | |
| 4492 | .fn_proto => { | | |
| 4493 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { | | |
| 4494 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4495 | error.AnalysisFail => {}, | | |
| 4496 | }; | | |
| 4497 | continue; | | |
| 4498 | }, | | |
| 4499 | else => unreachable, | | |
| 4500 | } | | |
| 4501 | }, | | |
| 4502 | .fn_proto_simple => { | | |
| 4503 | var params: [1]Ast.Node.Index = undefined; | | |
| 4504 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { | | |
| 4505 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4506 | error.AnalysisFail => {}, | | |
| 4507 | }; | | |
| 4508 | continue; | | |
| 4509 | }, | | |
| 4510 | .fn_proto_multi => { | | |
| 4511 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { | | |
| 4512 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4513 | error.AnalysisFail => {}, | | |
| 4514 | }; | | |
| 4515 | continue; | | |
| 4516 | }, | | |
| 4517 | .fn_proto_one => { | | |
| 4518 | var params: [1]Ast.Node.Index = undefined; | | |
| 4519 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { | | |
| 4520 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4521 | error.AnalysisFail => {}, | | |
| 4522 | }; | | |
| 4523 | continue; | | |
| 4524 | }, | | |
| 4525 | .fn_proto => { | | |
| 4526 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { | | |
| 4527 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4528 | error.AnalysisFail => {}, | | |
| 4529 | }; | | |
| 4530 | continue; | | |
| 4531 | }, | | |
| 4532 | | | |
| 4533 | .global_var_decl => { | | |
| 4534 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { | | |
| 4535 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4536 | error.AnalysisFail => {}, | | |
| 4537 | }; | | |
| 4538 | continue; | | |
| 4539 | }, | | |
| 4540 | .local_var_decl => { | | |
| 4541 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { | | |
| 4542 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4543 | error.AnalysisFail => {}, | | |
| 4544 | }; | | |
| 4545 | continue; | | |
| 4546 | }, | | |
| 4547 | .simple_var_decl => { | | |
| 4548 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { | | |
| 4549 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4550 | error.AnalysisFail => {}, | | |
| 4551 | }; | | |
| 4552 | continue; | | |
| 4553 | }, | | |
| 4554 | .aligned_var_decl => { | | |
| 4555 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { | | |
| 4556 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4557 | error.AnalysisFail => {}, | | |
| 4558 | }; | | |
| 4559 | continue; | | |
| 4560 | }, | | |
| 4561 | | | |
| 4562 | .@"comptime" => { | | |
| 4563 | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4564 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4565 | error.AnalysisFail => {}, | | |
| 4566 | }; | | |
| 4567 | continue; | | |
| 4568 | }, | | |
| 4569 | .@"usingnamespace" => { | | |
| 4570 | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4571 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4572 | error.AnalysisFail => {}, | | |
| 4573 | }; | | |
| 4574 | continue; | | |
| 4575 | }, | | |
| 4576 | .test_decl => { | | |
| 4577 | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4578 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4579 | error.AnalysisFail => {}, | | |
| 4580 | }; | | |
| 4581 | continue; | | |
| 4582 | }, | | |
| 4583 | else => unreachable, | | |
| 4584 | }; | 4217 | }; |
| 4585 | if (field_index % 32 == 0 and field_index != 0) { | | |
| 4586 | try bit_bag.append(gpa, cur_bit_bag); | | |
| 4587 | cur_bit_bag = 0; | | |
| 4588 | } | | |
| 4589 | assert(member.comptime_token == null); | 4218 | assert(member.comptime_token == null); |
| 4590 | assert(member.ast.type_expr == 0); | 4219 | assert(member.ast.type_expr == 0); |
| 4591 | assert(member.ast.align_expr == 0); | 4220 | assert(member.ast.align_expr == 0); |
| 4592 | | 4221 | |
| 4593 | const field_name = try astgen.identAsString(member.ast.name_token); | 4222 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4594 | fields_data.appendAssumeCapacity(field_name); | 4223 | wip_members.appendToField(field_name); |
| 4595 | | 4224 | |
| 4596 | const have_value = member.ast.value_expr != 0; | 4225 | const have_value = member.ast.value_expr != 0; |
| 4597 | cur_bit_bag = (cur_bit_bag >> 1) | | 4226 | wip_members.nextField(bits_per_field, .{have_value}); |
| 4598 | (@as(u32, @boolToInt(have_value)) << 31); | | |
| 4599 | | 4227 | |
| 4600 | if (have_value) { | 4228 | if (have_value) { |
| 4601 | if (arg_inst == .none) { | 4229 | if (arg_inst == .none) { |
| ... | @@ -4613,60 +4241,35 @@ fn containerDecl( | ... | @@ -4613,60 +4241,35 @@ fn containerDecl( |
| 4613 | ); | 4241 | ); |
| 4614 | } | 4242 | } |
| 4615 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr); | 4243 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4616 | fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst)); | 4244 | wip_members.appendToField(@enumToInt(tag_value_inst)); |
| 4617 | } | | |
| 4618 | | | |
| 4619 | field_index += 1; | | |
| 4620 | } | | |
| 4621 | { | | |
| 4622 | const empty_slot_count = 32 - (field_index % 32); | | |
| 4623 | if (empty_slot_count < 32) { | | |
| 4624 | cur_bit_bag >>= @intCast(u5, empty_slot_count); | | |
| 4625 | } | | |
| 4626 | } | | |
| 4627 | { | | |
| 4628 | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); | | |
| 4629 | if (empty_slot_count < WipDecls.fields_per_u32) { | | |
| 4630 | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); | | |
| 4631 | } | 4245 | } |
| 4632 | } | 4246 | } |
| 4633 | | 4247 | |
| 4634 | if (block_scope.instructions.items.len != 0) { | 4248 | if (!block_scope.isEmpty()) { |
| 4635 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); | 4249 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 4636 | } | 4250 | } |
| 4637 | | 4251 | |
| | 4252 | const body = block_scope.instructionsSlice(); |
| | 4253 | |
| 4638 | try gz.setEnum(decl_inst, .{ | 4254 | try gz.setEnum(decl_inst, .{ |
| 4639 | .src_node = node, | 4255 | .src_node = node, |
| 4640 | .nonexhaustive = nonexhaustive, | 4256 | .nonexhaustive = nonexhaustive, |
| 4641 | .tag_type = arg_inst, | 4257 | .tag_type = arg_inst, |
| 4642 | .body_len = @intCast(u32, block_scope.instructions.items.len), | 4258 | .body_len = @intCast(u32, body.len), |
| 4643 | .fields_len = @intCast(u32, field_index), | 4259 | .fields_len = @intCast(u32, counts.total_fields), |
| 4644 | .decls_len = @intCast(u32, wip_decls.decl_index), | 4260 | .decls_len = @intCast(u32, counts.decls), |
| 4645 | }); | 4261 | }); |
| 4646 | | 4262 | |
| 4647 | // zig fmt: off | 4263 | wip_members.finishBits(bits_per_field); |
| 4648 | try astgen.extra.ensureUnusedCapacity(gpa, | 4264 | const decls_slice = wip_members.declsSlice(); |
| 4649 | bit_bag.items.len + | 4265 | const fields_slice = wip_members.fieldsSlice(); |
| 4650 | @boolToInt(wip_decls.decl_index != 0) + | 4266 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4651 | wip_decls.payload.items.len + | 4267 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4652 | block_scope.instructions.items.len + | 4268 | astgen.extra.appendSliceAssumeCapacity(body); |
| 4653 | wip_decls.bit_bag.items.len + | 4269 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4654 | 1 + // cur_bit_bag | | |
| 4655 | fields_data.items.len | | |
| 4656 | ); | | |
| 4657 | // zig fmt: on | | |
| 4658 | | | |
| 4659 | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. | | |
| 4660 | if (wip_decls.decl_index != 0) { | | |
| 4661 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | | |
| 4662 | } | | |
| 4663 | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); | | |
| 4664 | | | |
| 4665 | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); | | |
| 4666 | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. | | |
| 4667 | astgen.extra.appendAssumeCapacity(cur_bit_bag); | | |
| 4668 | astgen.extra.appendSliceAssumeCapacity(fields_data.items); | | |
| 4669 | | 4270 | |
| | 4271 | block_scope.unstack(); |
| | 4272 | try gz.addNamespaceCaptures(&namespace); |
| 4670 | return rvalue(gz, rl, indexToRef(decl_inst), node); | 4273 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4671 | }, | 4274 | }, |
| 4672 | .keyword_opaque => { | 4275 | .keyword_opaque => { |
| ... | @@ -4682,166 +4285,155 @@ fn containerDecl( | ... | @@ -4682,166 +4285,155 @@ fn containerDecl( |
| 4682 | }; | 4285 | }; |
| 4683 | defer namespace.deinit(gpa); | 4286 | defer namespace.deinit(gpa); |
| 4684 | | 4287 | |
| 4685 | try astgen.scanDecls(&namespace, container_decl.ast.members); | 4288 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4686 | | 4289 | |
| 4687 | var wip_decls: WipDecls = .{}; | 4290 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); |
| 4688 | defer wip_decls.deinit(gpa); | 4291 | defer wip_members.deinit(); |
| 4689 | | 4292 | |
| 4690 | for (container_decl.ast.members) |member_node| { | 4293 | for (container_decl.ast.members) |member_node| { |
| 4691 | switch (node_tags[member_node]) { | 4294 | _ = try containerMember(gz, &namespace.base, &wip_members, member_node); |
| 4692 | .container_field_init, .container_field_align, .container_field => {}, | | |
| 4693 | | | |
| 4694 | .fn_decl => { | | |
| 4695 | const fn_proto = node_datas[member_node].lhs; | | |
| 4696 | const body = node_datas[member_node].rhs; | | |
| 4697 | switch (node_tags[fn_proto]) { | | |
| 4698 | .fn_proto_simple => { | | |
| 4699 | var params: [1]Ast.Node.Index = undefined; | | |
| 4700 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { | | |
| 4701 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4702 | error.AnalysisFail => {}, | | |
| 4703 | }; | | |
| 4704 | continue; | | |
| 4705 | }, | | |
| 4706 | .fn_proto_multi => { | | |
| 4707 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { | | |
| 4708 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4709 | error.AnalysisFail => {}, | | |
| 4710 | }; | | |
| 4711 | continue; | | |
| 4712 | }, | | |
| 4713 | .fn_proto_one => { | | |
| 4714 | var params: [1]Ast.Node.Index = undefined; | | |
| 4715 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { | | |
| 4716 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4717 | error.AnalysisFail => {}, | | |
| 4718 | }; | | |
| 4719 | continue; | | |
| 4720 | }, | | |
| 4721 | .fn_proto => { | | |
| 4722 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { | | |
| 4723 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4724 | error.AnalysisFail => {}, | | |
| 4725 | }; | | |
| 4726 | continue; | | |
| 4727 | }, | | |
| 4728 | else => unreachable, | | |
| 4729 | } | | |
| 4730 | }, | | |
| 4731 | .fn_proto_simple => { | | |
| 4732 | var params: [1]Ast.Node.Index = undefined; | | |
| 4733 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { | | |
| 4734 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4735 | error.AnalysisFail => {}, | | |
| 4736 | }; | | |
| 4737 | continue; | | |
| 4738 | }, | | |
| 4739 | .fn_proto_multi => { | | |
| 4740 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { | | |
| 4741 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4742 | error.AnalysisFail => {}, | | |
| 4743 | }; | | |
| 4744 | continue; | | |
| 4745 | }, | | |
| 4746 | .fn_proto_one => { | | |
| 4747 | var params: [1]Ast.Node.Index = undefined; | | |
| 4748 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { | | |
| 4749 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4750 | error.AnalysisFail => {}, | | |
| 4751 | }; | | |
| 4752 | continue; | | |
| 4753 | }, | | |
| 4754 | .fn_proto => { | | |
| 4755 | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { | | |
| 4756 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4757 | error.AnalysisFail => {}, | | |
| 4758 | }; | | |
| 4759 | continue; | | |
| 4760 | }, | | |
| 4761 | | | |
| 4762 | .global_var_decl => { | | |
| 4763 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { | | |
| 4764 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4765 | error.AnalysisFail => {}, | | |
| 4766 | }; | | |
| 4767 | continue; | | |
| 4768 | }, | | |
| 4769 | .local_var_decl => { | | |
| 4770 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { | | |
| 4771 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4772 | error.AnalysisFail => {}, | | |
| 4773 | }; | | |
| 4774 | continue; | | |
| 4775 | }, | | |
| 4776 | .simple_var_decl => { | | |
| 4777 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { | | |
| 4778 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4779 | error.AnalysisFail => {}, | | |
| 4780 | }; | | |
| 4781 | continue; | | |
| 4782 | }, | | |
| 4783 | .aligned_var_decl => { | | |
| 4784 | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { | | |
| 4785 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4786 | error.AnalysisFail => {}, | | |
| 4787 | }; | | |
| 4788 | continue; | | |
| 4789 | }, | | |
| 4790 | | | |
| 4791 | .@"comptime" => { | | |
| 4792 | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4793 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4794 | error.AnalysisFail => {}, | | |
| 4795 | }; | | |
| 4796 | continue; | | |
| 4797 | }, | | |
| 4798 | .@"usingnamespace" => { | | |
| 4799 | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4800 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4801 | error.AnalysisFail => {}, | | |
| 4802 | }; | | |
| 4803 | continue; | | |
| 4804 | }, | | |
| 4805 | .test_decl => { | | |
| 4806 | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { | | |
| 4807 | error.OutOfMemory => return error.OutOfMemory, | | |
| 4808 | error.AnalysisFail => {}, | | |
| 4809 | }; | | |
| 4810 | continue; | | |
| 4811 | }, | | |
| 4812 | else => unreachable, | | |
| 4813 | } | | |
| 4814 | } | | |
| 4815 | { | | |
| 4816 | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); | | |
| 4817 | if (empty_slot_count < WipDecls.fields_per_u32) { | | |
| 4818 | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); | | |
| 4819 | } | | |
| 4820 | } | 4295 | } |
| 4821 | | 4296 | |
| 4822 | try gz.setOpaque(decl_inst, .{ | 4297 | try gz.setOpaque(decl_inst, .{ |
| 4823 | .src_node = node, | 4298 | .src_node = node, |
| 4824 | .decls_len = @intCast(u32, wip_decls.decl_index), | 4299 | .decls_len = decl_count, |
| 4825 | }); | 4300 | }); |
| 4826 | | 4301 | |
| 4827 | // zig fmt: off | 4302 | wip_members.finishBits(0); |
| 4828 | try astgen.extra.ensureUnusedCapacity(gpa, | 4303 | const decls_slice = wip_members.declsSlice(); |
| 4829 | wip_decls.bit_bag.items.len + | 4304 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len); |
| 4830 | @boolToInt(wip_decls.decl_index != 0) + | 4305 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4831 | wip_decls.payload.items.len | | |
| 4832 | ); | | |
| 4833 | // zig fmt: on | | |
| 4834 | | 4306 | |
| 4835 | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. | 4307 | try gz.addNamespaceCaptures(&namespace); |
| 4836 | if (wip_decls.decl_index != 0) { | 4308 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4837 | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); | 4309 | }, |
| | 4310 | else => unreachable, |
| | 4311 | } |
| | 4312 | } |
| | 4313 | |
| | 4314 | const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField }; |
| | 4315 | |
| | 4316 | fn containerMember( |
| | 4317 | gz: *GenZir, |
| | 4318 | scope: *Scope, |
| | 4319 | wip_members: *WipMembers, |
| | 4320 | member_node: Ast.Node.Index, |
| | 4321 | ) InnerError!ContainerMemberResult { |
| | 4322 | const astgen = gz.astgen; |
| | 4323 | const tree = astgen.tree; |
| | 4324 | const node_tags = tree.nodes.items(.tag); |
| | 4325 | const node_datas = tree.nodes.items(.data); |
| | 4326 | switch (node_tags[member_node]) { |
| | 4327 | .container_field_init => return ContainerMemberResult{ .field = tree.containerFieldInit(member_node) }, |
| | 4328 | .container_field_align => return ContainerMemberResult{ .field = tree.containerFieldAlign(member_node) }, |
| | 4329 | .container_field => return ContainerMemberResult{ .field = tree.containerField(member_node) }, |
| | 4330 | |
| | 4331 | .fn_decl => { |
| | 4332 | const fn_proto = node_datas[member_node].lhs; |
| | 4333 | const body = node_datas[member_node].rhs; |
| | 4334 | switch (node_tags[fn_proto]) { |
| | 4335 | .fn_proto_simple => { |
| | 4336 | var params: [1]Ast.Node.Index = undefined; |
| | 4337 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| | 4338 | error.OutOfMemory => return error.OutOfMemory, |
| | 4339 | error.AnalysisFail => {}, |
| | 4340 | }; |
| | 4341 | }, |
| | 4342 | .fn_proto_multi => { |
| | 4343 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| | 4344 | error.OutOfMemory => return error.OutOfMemory, |
| | 4345 | error.AnalysisFail => {}, |
| | 4346 | }; |
| | 4347 | }, |
| | 4348 | .fn_proto_one => { |
| | 4349 | var params: [1]Ast.Node.Index = undefined; |
| | 4350 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| | 4351 | error.OutOfMemory => return error.OutOfMemory, |
| | 4352 | error.AnalysisFail => {}, |
| | 4353 | }; |
| | 4354 | }, |
| | 4355 | .fn_proto => { |
| | 4356 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| | 4357 | error.OutOfMemory => return error.OutOfMemory, |
| | 4358 | error.AnalysisFail => {}, |
| | 4359 | }; |
| | 4360 | }, |
| | 4361 | else => unreachable, |
| 4838 | } | 4362 | } |
| 4839 | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); | 4363 | }, |
| | 4364 | .fn_proto_simple => { |
| | 4365 | var params: [1]Ast.Node.Index = undefined; |
| | 4366 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| | 4367 | error.OutOfMemory => return error.OutOfMemory, |
| | 4368 | error.AnalysisFail => {}, |
| | 4369 | }; |
| | 4370 | }, |
| | 4371 | .fn_proto_multi => { |
| | 4372 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| | 4373 | error.OutOfMemory => return error.OutOfMemory, |
| | 4374 | error.AnalysisFail => {}, |
| | 4375 | }; |
| | 4376 | }, |
| | 4377 | .fn_proto_one => { |
| | 4378 | var params: [1]Ast.Node.Index = undefined; |
| | 4379 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| | 4380 | error.OutOfMemory => return error.OutOfMemory, |
| | 4381 | error.AnalysisFail => {}, |
| | 4382 | }; |
| | 4383 | }, |
| | 4384 | .fn_proto => { |
| | 4385 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| | 4386 | error.OutOfMemory => return error.OutOfMemory, |
| | 4387 | error.AnalysisFail => {}, |
| | 4388 | }; |
| | 4389 | }, |
| 4840 | | 4390 | |
| 4841 | return rvalue(gz, rl, indexToRef(decl_inst), node); | 4391 | .global_var_decl => { |
| | 4392 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| | 4393 | error.OutOfMemory => return error.OutOfMemory, |
| | 4394 | error.AnalysisFail => {}, |
| | 4395 | }; |
| | 4396 | }, |
| | 4397 | .local_var_decl => { |
| | 4398 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| | 4399 | error.OutOfMemory => return error.OutOfMemory, |
| | 4400 | error.AnalysisFail => {}, |
| | 4401 | }; |
| | 4402 | }, |
| | 4403 | .simple_var_decl => { |
| | 4404 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| | 4405 | error.OutOfMemory => return error.OutOfMemory, |
| | 4406 | error.AnalysisFail => {}, |
| | 4407 | }; |
| | 4408 | }, |
| | 4409 | .aligned_var_decl => { |
| | 4410 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| | 4411 | error.OutOfMemory => return error.OutOfMemory, |
| | 4412 | error.AnalysisFail => {}, |
| | 4413 | }; |
| | 4414 | }, |
| | 4415 | |
| | 4416 | .@"comptime" => { |
| | 4417 | astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| | 4418 | error.OutOfMemory => return error.OutOfMemory, |
| | 4419 | error.AnalysisFail => {}, |
| | 4420 | }; |
| | 4421 | }, |
| | 4422 | .@"usingnamespace" => { |
| | 4423 | astgen.usingnamespaceDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| | 4424 | error.OutOfMemory => return error.OutOfMemory, |
| | 4425 | error.AnalysisFail => {}, |
| | 4426 | }; |
| | 4427 | }, |
| | 4428 | .test_decl => { |
| | 4429 | astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| | 4430 | error.OutOfMemory => return error.OutOfMemory, |
| | 4431 | error.AnalysisFail => {}, |
| | 4432 | }; |
| 4842 | }, | 4433 | }, |
| 4843 | else => unreachable, | 4434 | else => unreachable, |
| 4844 | } | 4435 | } |
| | 4436 | return .decl; |
| 4845 | } | 4437 | } |
| 4846 | | 4438 | |
| 4847 | fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { | 4439 | fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| ... | @@ -4851,20 +4443,18 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir | ... | @@ -4851,20 +4443,18 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir |
| 4851 | const main_tokens = tree.nodes.items(.main_token); | 4443 | const main_tokens = tree.nodes.items(.main_token); |
| 4852 | const token_tags = tree.tokens.items(.tag); | 4444 | const token_tags = tree.tokens.items(.tag); |
| 4853 | | 4445 | |
| 4854 | var field_names: std.ArrayListUnmanaged(u32) = .{}; | 4446 | const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len); |
| 4855 | defer field_names.deinit(gpa); | 4447 | var fields_len: usize = 0; |
| 4856 | | | |
| 4857 | { | 4448 | { |
| 4858 | const error_token = main_tokens[node]; | 4449 | const error_token = main_tokens[node]; |
| 4859 | var tok_i = error_token + 2; | 4450 | var tok_i = error_token + 2; |
| 4860 | var field_i: usize = 0; | | |
| 4861 | while (true) : (tok_i += 1) { | 4451 | while (true) : (tok_i += 1) { |
| 4862 | switch (token_tags[tok_i]) { | 4452 | switch (token_tags[tok_i]) { |
| 4863 | .doc_comment, .comma => {}, | 4453 | .doc_comment, .comma => {}, |
| 4864 | .identifier => { | 4454 | .identifier => { |
| 4865 | const str_index = try astgen.identAsString(tok_i); | 4455 | const str_index = try astgen.identAsString(tok_i); |
| 4866 | try field_names.append(gpa, str_index); | 4456 | try astgen.extra.append(gpa, str_index); |
| 4867 | field_i += 1; | 4457 | fields_len += 1; |
| 4868 | }, | 4458 | }, |
| 4869 | .r_brace => break, | 4459 | .r_brace => break, |
| 4870 | else => unreachable, | 4460 | else => unreachable, |
| ... | @@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir | ... | @@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir |
| 4872 | } | 4462 | } |
| 4873 | } | 4463 | } |
| 4874 | | 4464 | |
| 4875 | const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{ | 4465 | setExtra(astgen, payload_index, Zir.Inst.ErrorSetDecl{ |
| 4876 | .fields_len = @intCast(u32, field_names.items.len), | 4466 | .fields_len = @intCast(u32, fields_len), |
| 4877 | }); | 4467 | }); |
| 4878 | try astgen.extra.appendSlice(gpa, field_names.items); | 4468 | const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index); |
| 4879 | return rvalue(gz, rl, result, node); | 4469 | return rvalue(gz, rl, result, node); |
| 4880 | } | 4470 | } |
| 4881 | | 4471 | |
| ... | @@ -4896,7 +4486,7 @@ fn tryExpr( | ... | @@ -4896,7 +4486,7 @@ fn tryExpr( |
| 4896 | | 4486 | |
| 4897 | var block_scope = parent_gz.makeSubBlock(scope); | 4487 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4898 | block_scope.setBreakResultLoc(rl); | 4488 | block_scope.setBreakResultLoc(rl); |
| 4899 | defer block_scope.instructions.deinit(astgen.gpa); | 4489 | defer block_scope.unstack(); |
| 4900 | | 4490 | |
| 4901 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 4491 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4902 | .ref => .ref, | 4492 | .ref => .ref, |
| ... | @@ -4916,12 +4506,13 @@ fn tryExpr( | ... | @@ -4916,12 +4506,13 @@ fn tryExpr( |
| 4916 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); | 4506 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); |
| 4917 | const condbr = try block_scope.addCondBr(.condbr, node); | 4507 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4918 | | 4508 | |
| 4919 | const block = try parent_gz.addBlock(.block, node); | 4509 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4920 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 4921 | try block_scope.setBlockBody(block); | 4510 | try block_scope.setBlockBody(block); |
| | 4511 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4512 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4922 | | 4513 | |
| 4923 | var then_scope = parent_gz.makeSubBlock(scope); | 4514 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4924 | defer then_scope.instructions.deinit(astgen.gpa); | 4515 | defer then_scope.unstack(); |
| 4925 | | 4516 | |
| 4926 | block_scope.break_count += 1; | 4517 | block_scope.break_count += 1; |
| 4927 | // This could be a pointer or value depending on `err_ops[2]`. | 4518 | // This could be a pointer or value depending on `err_ops[2]`. |
| ... | @@ -4931,8 +4522,9 @@ fn tryExpr( | ... | @@ -4931,8 +4522,9 @@ fn tryExpr( |
| 4931 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), | 4522 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), |
| 4932 | }; | 4523 | }; |
| 4933 | | 4524 | |
| | 4525 | // else_scope will be stacked on then_scope as both are stacked on parent_gz |
| 4934 | var else_scope = parent_gz.makeSubBlock(scope); | 4526 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4935 | defer else_scope.instructions.deinit(astgen.gpa); | 4527 | defer else_scope.unstack(); |
| 4936 | | 4528 | |
| 4937 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); | 4529 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); |
| 4938 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); | 4530 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); |
| ... | @@ -4972,7 +4564,7 @@ fn orelseCatchExpr( | ... | @@ -4972,7 +4564,7 @@ fn orelseCatchExpr( |
| 4972 | | 4564 | |
| 4973 | var block_scope = parent_gz.makeSubBlock(scope); | 4565 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4974 | block_scope.setBreakResultLoc(rl); | 4566 | block_scope.setBreakResultLoc(rl); |
| 4975 | defer block_scope.instructions.deinit(astgen.gpa); | 4567 | defer block_scope.unstack(); |
| 4976 | | 4568 | |
| 4977 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { | 4569 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4978 | .ref => .ref, | 4570 | .ref => .ref, |
| ... | @@ -4987,12 +4579,13 @@ fn orelseCatchExpr( | ... | @@ -4987,12 +4579,13 @@ fn orelseCatchExpr( |
| 4987 | const cond = try block_scope.addUnNode(cond_op, operand, node); | 4579 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 4988 | const condbr = try block_scope.addCondBr(.condbr, node); | 4580 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4989 | | 4581 | |
| 4990 | const block = try parent_gz.addBlock(.block, node); | 4582 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4991 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 4992 | try block_scope.setBlockBody(block); | 4583 | try block_scope.setBlockBody(block); |
| | 4584 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4585 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4993 | | 4586 | |
| 4994 | var then_scope = parent_gz.makeSubBlock(scope); | 4587 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4995 | defer then_scope.instructions.deinit(astgen.gpa); | 4588 | defer then_scope.unstack(); |
| 4996 | | 4589 | |
| 4997 | // This could be a pointer or value depending on `unwrap_op`. | 4590 | // This could be a pointer or value depending on `unwrap_op`. |
| 4998 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); | 4591 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); |
| ... | @@ -5002,7 +4595,7 @@ fn orelseCatchExpr( | ... | @@ -5002,7 +4595,7 @@ fn orelseCatchExpr( |
| 5002 | }; | 4595 | }; |
| 5003 | | 4596 | |
| 5004 | var else_scope = parent_gz.makeSubBlock(scope); | 4597 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5005 | defer else_scope.instructions.deinit(astgen.gpa); | 4598 | defer else_scope.unstack(); |
| 5006 | | 4599 | |
| 5007 | var err_val_scope: Scope.LocalVal = undefined; | 4600 | var err_val_scope: Scope.LocalVal = undefined; |
| 5008 | const else_sub_scope = blk: { | 4601 | const else_sub_scope = blk: { |
| ... | @@ -5049,6 +4642,7 @@ fn orelseCatchExpr( | ... | @@ -5049,6 +4642,7 @@ fn orelseCatchExpr( |
| 5049 | ); | 4642 | ); |
| 5050 | } | 4643 | } |
| 5051 | | 4644 | |
| | 4645 | /// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`. |
| 5052 | fn finishThenElseBlock( | 4646 | fn finishThenElseBlock( |
| 5053 | parent_gz: *GenZir, | 4647 | parent_gz: *GenZir, |
| 5054 | rl: ResultLoc, | 4648 | rl: ResultLoc, |
| ... | @@ -5067,33 +4661,33 @@ fn finishThenElseBlock( | ... | @@ -5067,33 +4661,33 @@ fn finishThenElseBlock( |
| 5067 | // We now have enough information to decide whether the result instruction should | 4661 | // We now have enough information to decide whether the result instruction should |
| 5068 | // be communicated via result location pointer or break instructions. | 4662 | // be communicated via result location pointer or break instructions. |
| 5069 | const strat = rl.strategy(block_scope); | 4663 | const strat = rl.strategy(block_scope); |
| | 4664 | // else_scope may be stacked on then_scope, so check for no-return on then_scope manually |
| | 4665 | const tags = parent_gz.astgen.instructions.items(.tag); |
| | 4666 | const then_slice = then_scope.instructionsSliceUpto(else_scope); |
| | 4667 | const then_no_return = then_slice.len > 0 and tags[then_slice[then_slice.len - 1]].isNoReturn(); |
| | 4668 | const else_no_return = else_scope.endsWithNoReturn(); |
| | 4669 | |
| 5070 | switch (strat.tag) { | 4670 | switch (strat.tag) { |
| 5071 | .break_void => { | 4671 | .break_void => { |
| 5072 | if (!then_scope.endsWithNoReturn()) { | 4672 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, .void_value) else 0; |
| 5073 | _ = try then_scope.addBreak(break_tag, then_break_block, .void_value); | 4673 | const else_break = if (!else_no_return) try else_scope.makeBreak(break_tag, main_block, .void_value) else 0; |
| 5074 | } | | |
| 5075 | if (!else_scope.endsWithNoReturn()) { | | |
| 5076 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); | | |
| 5077 | } | | |
| 5078 | assert(!strat.elide_store_to_block_ptr_instructions); | 4674 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 5079 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 4675 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 5080 | return indexToRef(main_block); | 4676 | return indexToRef(main_block); |
| 5081 | }, | 4677 | }, |
| 5082 | .break_operand => { | 4678 | .break_operand => { |
| 5083 | if (!then_scope.endsWithNoReturn()) { | 4679 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0; |
| 5084 | _ = try then_scope.addBreak(break_tag, then_break_block, then_result); | 4680 | const else_break = if (else_result == .none) |
| 5085 | } | 4681 | try else_scope.makeBreak(break_tag, main_block, .void_value) |
| 5086 | if (else_result != .none) { | 4682 | else if (!else_no_return) |
| 5087 | if (!else_scope.endsWithNoReturn()) { | 4683 | try else_scope.makeBreak(break_tag, main_block, else_result) |
| 5088 | _ = try else_scope.addBreak(break_tag, main_block, else_result); | 4684 | else |
| 5089 | } | 4685 | 0; |
| 5090 | } else { | 4686 | |
| 5091 | _ = try else_scope.addBreak(break_tag, main_block, .void_value); | | |
| 5092 | } | | |
| 5093 | if (strat.elide_store_to_block_ptr_instructions) { | 4687 | if (strat.elide_store_to_block_ptr_instructions) { |
| 5094 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_scope.rl_ptr); | 4688 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, then_break, else_scope, else_break, block_scope.rl_ptr); |
| 5095 | } else { | 4689 | } else { |
| 5096 | try setCondBrPayload(condbr, cond, then_scope, else_scope); | 4690 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 5097 | } | 4691 | } |
| 5098 | const block_ref = indexToRef(main_block); | 4692 | const block_ref = indexToRef(main_block); |
| 5099 | switch (rl) { | 4693 | switch (rl) { |
| ... | @@ -5221,7 +4815,7 @@ fn boolBinOp( | ... | @@ -5221,7 +4815,7 @@ fn boolBinOp( |
| 5221 | const bool_br = try gz.addBoolBr(zir_tag, lhs); | 4815 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 5222 | | 4816 | |
| 5223 | var rhs_scope = gz.makeSubBlock(scope); | 4817 | var rhs_scope = gz.makeSubBlock(scope); |
| 5224 | defer rhs_scope.instructions.deinit(gz.astgen.gpa); | 4818 | defer rhs_scope.unstack(); |
| 5225 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); | 4819 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); |
| 5226 | if (!gz.refIsNoReturn(rhs)) { | 4820 | if (!gz.refIsNoReturn(rhs)) { |
| 5227 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); | 4821 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); |
| ... | @@ -5245,7 +4839,7 @@ fn ifExpr( | ... | @@ -5245,7 +4839,7 @@ fn ifExpr( |
| 5245 | | 4839 | |
| 5246 | var block_scope = parent_gz.makeSubBlock(scope); | 4840 | var block_scope = parent_gz.makeSubBlock(scope); |
| 5247 | block_scope.setBreakResultLoc(rl); | 4841 | block_scope.setBreakResultLoc(rl); |
| 5248 | defer block_scope.instructions.deinit(astgen.gpa); | 4842 | defer block_scope.unstack(); |
| 5249 | | 4843 | |
| 5250 | const payload_is_ref = if (if_full.payload_token) |payload_token| | 4844 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 5251 | token_tags[payload_token] == .asterisk | 4845 | token_tags[payload_token] == .asterisk |
| ... | @@ -5283,12 +4877,13 @@ fn ifExpr( | ... | @@ -5283,12 +4877,13 @@ fn ifExpr( |
| 5283 | | 4877 | |
| 5284 | const condbr = try block_scope.addCondBr(.condbr, node); | 4878 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 5285 | | 4879 | |
| 5286 | const block = try parent_gz.addBlock(.block, node); | 4880 | const block = try parent_gz.makeBlockInst(.block, node); |
| 5287 | try parent_gz.instructions.append(astgen.gpa, block); | | |
| 5288 | try block_scope.setBlockBody(block); | 4881 | try block_scope.setBlockBody(block); |
| | 4882 | // block_scope unstacked now, can add new instructions to parent_gz |
| | 4883 | try parent_gz.instructions.append(astgen.gpa, block); |
| 5289 | | 4884 | |
| 5290 | var then_scope = parent_gz.makeSubBlock(scope); | 4885 | var then_scope = parent_gz.makeSubBlock(scope); |
| 5291 | defer then_scope.instructions.deinit(astgen.gpa); | 4886 | defer then_scope.unstack(); |
| 5292 | | 4887 | |
| 5293 | var payload_val_scope: Scope.LocalVal = undefined; | 4888 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5294 | | 4889 | |
| ... | @@ -5354,7 +4949,7 @@ fn ifExpr( | ... | @@ -5354,7 +4949,7 @@ fn ifExpr( |
| 5354 | // instructions or not. | 4949 | // instructions or not. |
| 5355 | | 4950 | |
| 5356 | var else_scope = parent_gz.makeSubBlock(scope); | 4951 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5357 | defer else_scope.instructions.deinit(astgen.gpa); | 4952 | defer else_scope.unstack(); |
| 5358 | | 4953 | |
| 5359 | const else_node = if_full.ast.else_expr; | 4954 | const else_node = if_full.ast.else_expr; |
| 5360 | const else_info: struct { | 4955 | const else_info: struct { |
| ... | @@ -5417,52 +5012,70 @@ fn ifExpr( | ... | @@ -5417,52 +5012,70 @@ fn ifExpr( |
| 5417 | ); | 5012 | ); |
| 5418 | } | 5013 | } |
| 5419 | | 5014 | |
| | 5015 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 5420 | fn setCondBrPayload( | 5016 | fn setCondBrPayload( |
| 5421 | condbr: Zir.Inst.Index, | 5017 | condbr: Zir.Inst.Index, |
| 5422 | cond: Zir.Inst.Ref, | 5018 | cond: Zir.Inst.Ref, |
| 5423 | then_scope: *GenZir, | 5019 | then_scope: *GenZir, |
| | 5020 | then_break: Zir.Inst.Index, |
| 5424 | else_scope: *GenZir, | 5021 | else_scope: *GenZir, |
| | 5022 | else_break: Zir.Inst.Index, |
| 5425 | ) !void { | 5023 | ) !void { |
| | 5024 | defer then_scope.unstack(); |
| | 5025 | defer else_scope.unstack(); |
| 5426 | const astgen = then_scope.astgen; | 5026 | const astgen = then_scope.astgen; |
| 5427 | | 5027 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| | 5028 | const else_body = else_scope.instructionsSlice(); |
| | 5029 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| | 5030 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5428 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5031 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5429 | then_scope.instructions.items.len + else_scope.instructions.items.len); | 5032 | then_body_len + else_body_len); |
| 5430 | | 5033 | |
| 5431 | const zir_datas = astgen.instructions.items(.data); | 5034 | const zir_datas = astgen.instructions.items(.data); |
| 5432 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ | 5035 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 5433 | .condition = cond, | 5036 | .condition = cond, |
| 5434 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), | 5037 | .then_body_len = then_body_len, |
| 5435 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), | 5038 | .else_body_len = else_body_len, |
| 5436 | }); | 5039 | }); |
| 5437 | astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items); | 5040 | astgen.extra.appendSliceAssumeCapacity(then_body); |
| 5438 | astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items); | 5041 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| | 5042 | astgen.extra.appendSliceAssumeCapacity(else_body); |
| | 5043 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5439 | } | 5044 | } |
| 5440 | | 5045 | |
| | 5046 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 5441 | fn setCondBrPayloadElideBlockStorePtr( | 5047 | fn setCondBrPayloadElideBlockStorePtr( |
| 5442 | condbr: Zir.Inst.Index, | 5048 | condbr: Zir.Inst.Index, |
| 5443 | cond: Zir.Inst.Ref, | 5049 | cond: Zir.Inst.Ref, |
| 5444 | then_scope: *GenZir, | 5050 | then_scope: *GenZir, |
| | 5051 | then_break: Zir.Inst.Index, |
| 5445 | else_scope: *GenZir, | 5052 | else_scope: *GenZir, |
| | 5053 | else_break: Zir.Inst.Index, |
| 5446 | block_ptr: Zir.Inst.Ref, | 5054 | block_ptr: Zir.Inst.Ref, |
| 5447 | ) !void { | 5055 | ) !void { |
| | 5056 | defer then_scope.unstack(); |
| | 5057 | defer else_scope.unstack(); |
| 5448 | const astgen = then_scope.astgen; | 5058 | const astgen = then_scope.astgen; |
| 5449 | | 5059 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| | 5060 | const else_body = else_scope.instructionsSlice(); |
| | 5061 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| | 5062 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5450 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5063 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5451 | then_scope.instructions.items.len + else_scope.instructions.items.len); | 5064 | then_body_len + else_body_len); |
| 5452 | | 5065 | |
| 5453 | const zir_tags = astgen.instructions.items(.tag); | 5066 | const zir_tags = astgen.instructions.items(.tag); |
| 5454 | const zir_datas = astgen.instructions.items(.data); | 5067 | const zir_datas = astgen.instructions.items(.data); |
| 5455 | | 5068 | |
| 5456 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ | 5069 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 5457 | .condition = cond, | 5070 | .condition = cond, |
| 5458 | .then_body_len = @intCast(u32, then_scope.instructions.items.len), | 5071 | .then_body_len = then_body_len, |
| 5459 | .else_body_len = @intCast(u32, else_scope.instructions.items.len), | 5072 | .else_body_len = else_body_len, |
| 5460 | }); | 5073 | }); |
| 5461 | zir_datas[condbr].pl_node.payload_index = condbr_pl; | 5074 | zir_datas[condbr].pl_node.payload_index = condbr_pl; |
| 5462 | const then_body_len_index = condbr_pl + 1; | 5075 | const then_body_len_index = condbr_pl + 1; |
| 5463 | const else_body_len_index = condbr_pl + 2; | 5076 | const else_body_len_index = condbr_pl + 2; |
| 5464 | | 5077 | |
| 5465 | for (then_scope.instructions.items) |src_inst| { | 5078 | for (then_body) |src_inst| { |
| 5466 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 5079 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5467 | if (zir_datas[src_inst].bin.lhs == block_ptr) { | 5080 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5468 | astgen.extra.items[then_body_len_index] -= 1; | 5081 | astgen.extra.items[then_body_len_index] -= 1; |
| ... | @@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5471 | } | 5084 | } |
| 5472 | astgen.extra.appendAssumeCapacity(src_inst); | 5085 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5473 | } | 5086 | } |
| 5474 | for (else_scope.instructions.items) |src_inst| { | 5087 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| | 5088 | for (else_body) |src_inst| { |
| 5475 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 5089 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5476 | if (zir_datas[src_inst].bin.lhs == block_ptr) { | 5090 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5477 | astgen.extra.items[else_body_len_index] -= 1; | 5091 | astgen.extra.items[else_body_len_index] -= 1; |
| ... | @@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5480 | } | 5094 | } |
| 5481 | astgen.extra.appendAssumeCapacity(src_inst); | 5095 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5482 | } | 5096 | } |
| | 5097 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5483 | } | 5098 | } |
| 5484 | | 5099 | |
| 5485 | fn whileExpr( | 5100 | fn whileExpr( |
| ... | @@ -5499,17 +5114,17 @@ fn whileExpr( | ... | @@ -5499,17 +5114,17 @@ fn whileExpr( |
| 5499 | | 5114 | |
| 5500 | const is_inline = parent_gz.force_comptime or while_full.inline_token != null; | 5115 | const is_inline = parent_gz.force_comptime or while_full.inline_token != null; |
| 5501 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; | 5116 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5502 | const loop_block = try parent_gz.addBlock(loop_tag, node); | 5117 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5503 | try parent_gz.instructions.append(astgen.gpa, loop_block); | 5118 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5504 | | 5119 | |
| 5505 | var loop_scope = parent_gz.makeSubBlock(scope); | 5120 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5506 | loop_scope.setBreakResultLoc(rl); | 5121 | loop_scope.setBreakResultLoc(rl); |
| 5507 | defer loop_scope.instructions.deinit(astgen.gpa); | 5122 | defer loop_scope.unstack(); |
| 5508 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); | 5123 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5509 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 5124 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5510 | | 5125 | |
| 5511 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); | 5126 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5512 | defer continue_scope.instructions.deinit(astgen.gpa); | 5127 | defer continue_scope.unstack(); |
| 5513 | | 5128 | |
| 5514 | const payload_is_ref = if (while_full.payload_token) |payload_token| | 5129 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 5515 | token_tags[payload_token] == .asterisk | 5130 | token_tags[payload_token] == .asterisk |
| ... | @@ -5548,15 +5163,19 @@ fn whileExpr( | ... | @@ -5548,15 +5163,19 @@ fn whileExpr( |
| 5548 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; | 5163 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5549 | const condbr = try continue_scope.addCondBr(condbr_tag, node); | 5164 | const condbr = try continue_scope.addCondBr(condbr_tag, node); |
| 5550 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; | 5165 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5551 | const cond_block = try loop_scope.addBlock(block_tag, node); | 5166 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5552 | try loop_scope.instructions.append(astgen.gpa, cond_block); | | |
| 5553 | try continue_scope.setBlockBody(cond_block); | 5167 | try continue_scope.setBlockBody(cond_block); |
| | 5168 | // continue_scope unstacked now, can add new instructions to loop_scope |
| | 5169 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5554 | | 5170 | |
| | 5171 | // make scope now but don't stack on parent_gz until loop_scope |
| | 5172 | // gets unstacked after cont_expr is emitted and added below |
| 5555 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); | 5173 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5556 | defer then_scope.instructions.deinit(astgen.gpa); | 5174 | then_scope.instructions_top = GenZir.unstacked_top; |
| | 5175 | defer then_scope.unstack(); |
| 5557 | | 5176 | |
| | 5177 | var payload_inst: Zir.Inst.Index = 0; |
| 5558 | var payload_val_scope: Scope.LocalVal = undefined; | 5178 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5559 | | | |
| 5560 | const then_sub_scope = s: { | 5179 | const then_sub_scope = s: { |
| 5561 | if (while_full.error_token != null) { | 5180 | if (while_full.error_token != null) { |
| 5562 | if (while_full.payload_token) |payload_token| { | 5181 | if (while_full.payload_token) |payload_token| { |
| ... | @@ -5564,7 +5183,8 @@ fn whileExpr( | ... | @@ -5564,7 +5183,8 @@ fn whileExpr( |
| 5564 | .err_union_payload_unsafe_ptr | 5183 | .err_union_payload_unsafe_ptr |
| 5565 | else | 5184 | else |
| 5566 | .err_union_payload_unsafe; | 5185 | .err_union_payload_unsafe; |
| 5567 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); | 5186 | // will add this instruction to then_scope.instructions below |
| | 5187 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5568 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; | 5188 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 5569 | const ident_bytes = tree.tokenSlice(ident_token); | 5189 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5570 | if (mem.eql(u8, "_", ident_bytes)) | 5190 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | @@ -5576,7 +5196,7 @@ fn whileExpr( | ... | @@ -5576,7 +5196,7 @@ fn whileExpr( |
| 5576 | .parent = &then_scope.base, | 5196 | .parent = &then_scope.base, |
| 5577 | .gen_zir = &then_scope, | 5197 | .gen_zir = &then_scope, |
| 5578 | .name = ident_name, | 5198 | .name = ident_name, |
| 5579 | .inst = payload_inst, | 5199 | .inst = indexToRef(payload_inst), |
| 5580 | .token_src = payload_token, | 5200 | .token_src = payload_token, |
| 5581 | .id_cat = .@"capture", | 5201 | .id_cat = .@"capture", |
| 5582 | }; | 5202 | }; |
| ... | @@ -5590,7 +5210,8 @@ fn whileExpr( | ... | @@ -5590,7 +5210,8 @@ fn whileExpr( |
| 5590 | .optional_payload_unsafe_ptr | 5210 | .optional_payload_unsafe_ptr |
| 5591 | else | 5211 | else |
| 5592 | .optional_payload_unsafe; | 5212 | .optional_payload_unsafe; |
| 5593 | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); | 5213 | // will add this instruction to then_scope.instructions below |
| | 5214 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5594 | const ident_name = try astgen.identAsString(ident_token); | 5215 | const ident_name = try astgen.identAsString(ident_token); |
| 5595 | const ident_bytes = tree.tokenSlice(ident_token); | 5216 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5596 | if (mem.eql(u8, "_", ident_bytes)) | 5217 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | @@ -5600,7 +5221,7 @@ fn whileExpr( | ... | @@ -5600,7 +5221,7 @@ fn whileExpr( |
| 5600 | .parent = &then_scope.base, | 5221 | .parent = &then_scope.base, |
| 5601 | .gen_zir = &then_scope, | 5222 | .gen_zir = &then_scope, |
| 5602 | .name = ident_name, | 5223 | .name = ident_name, |
| 5603 | .inst = payload_inst, | 5224 | .inst = indexToRef(payload_inst), |
| 5604 | .token_src = ident_token, | 5225 | .token_src = ident_token, |
| 5605 | .id_cat = .@"capture", | 5226 | .id_cat = .@"capture", |
| 5606 | }; | 5227 | }; |
| ... | @@ -5630,6 +5251,9 @@ fn whileExpr( | ... | @@ -5630,6 +5251,9 @@ fn whileExpr( |
| 5630 | }); | 5251 | }); |
| 5631 | } | 5252 | } |
| 5632 | | 5253 | |
| | 5254 | // done adding instructions to loop_scope, can now stack then_scope |
| | 5255 | then_scope.instructions_top = then_scope.instructions.items.len; |
| | 5256 | if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); |
| 5633 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); | 5257 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| 5634 | if (!then_scope.endsWithNoReturn()) { | 5258 | if (!then_scope.endsWithNoReturn()) { |
| 5635 | loop_scope.break_count += 1; | 5259 | loop_scope.break_count += 1; |
| ... | @@ -5637,7 +5261,7 @@ fn whileExpr( | ... | @@ -5637,7 +5261,7 @@ fn whileExpr( |
| 5637 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 5261 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5638 | | 5262 | |
| 5639 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); | 5263 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5640 | defer else_scope.instructions.deinit(astgen.gpa); | 5264 | defer else_scope.unstack(); |
| 5641 | | 5265 | |
| 5642 | const else_node = while_full.ast.else_expr; | 5266 | const else_node = while_full.ast.else_expr; |
| 5643 | const else_info: struct { | 5267 | const else_info: struct { |
| ... | @@ -5650,7 +5274,7 @@ fn whileExpr( | ... | @@ -5650,7 +5274,7 @@ fn whileExpr( |
| 5650 | .err_union_code_ptr | 5274 | .err_union_code_ptr |
| 5651 | else | 5275 | else |
| 5652 | .err_union_code; | 5276 | .err_union_code; |
| 5653 | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); | 5277 | const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 5654 | const ident_name = try astgen.identAsString(error_token); | 5278 | const ident_name = try astgen.identAsString(error_token); |
| 5655 | const ident_bytes = tree.tokenSlice(error_token); | 5279 | const ident_bytes = tree.tokenSlice(error_token); |
| 5656 | if (mem.eql(u8, ident_bytes, "_")) | 5280 | if (mem.eql(u8, ident_bytes, "_")) |
| ... | @@ -5660,7 +5284,7 @@ fn whileExpr( | ... | @@ -5660,7 +5284,7 @@ fn whileExpr( |
| 5660 | .parent = &else_scope.base, | 5284 | .parent = &else_scope.base, |
| 5661 | .gen_zir = &else_scope, | 5285 | .gen_zir = &else_scope, |
| 5662 | .name = ident_name, | 5286 | .name = ident_name, |
| 5663 | .inst = payload_inst, | 5287 | .inst = else_payload_inst, |
| 5664 | .token_src = error_token, | 5288 | .token_src = error_token, |
| 5665 | .id_cat = .@"capture", | 5289 | .id_cat = .@"capture", |
| 5666 | }; | 5290 | }; |
| ... | @@ -5742,17 +5366,17 @@ fn forExpr( | ... | @@ -5742,17 +5366,17 @@ fn forExpr( |
| 5742 | }; | 5366 | }; |
| 5743 | | 5367 | |
| 5744 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; | 5368 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5745 | const loop_block = try parent_gz.addBlock(loop_tag, node); | 5369 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5746 | try parent_gz.instructions.append(astgen.gpa, loop_block); | 5370 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5747 | | 5371 | |
| 5748 | var loop_scope = parent_gz.makeSubBlock(scope); | 5372 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5749 | loop_scope.setBreakResultLoc(rl); | 5373 | loop_scope.setBreakResultLoc(rl); |
| 5750 | defer loop_scope.instructions.deinit(astgen.gpa); | 5374 | defer loop_scope.unstack(); |
| 5751 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); | 5375 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5752 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); | 5376 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5753 | | 5377 | |
| 5754 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); | 5378 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5755 | defer cond_scope.instructions.deinit(astgen.gpa); | 5379 | defer cond_scope.unstack(); |
| 5756 | | 5380 | |
| 5757 | // check condition i < array_expr.len | 5381 | // check condition i < array_expr.len |
| 5758 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | 5382 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | @@ -5764,9 +5388,10 @@ fn forExpr( | ... | @@ -5764,9 +5388,10 @@ fn forExpr( |
| 5764 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; | 5388 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5765 | const condbr = try cond_scope.addCondBr(condbr_tag, node); | 5389 | const condbr = try cond_scope.addCondBr(condbr_tag, node); |
| 5766 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; | 5390 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5767 | const cond_block = try loop_scope.addBlock(block_tag, node); | 5391 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5768 | try loop_scope.instructions.append(astgen.gpa, cond_block); | | |
| 5769 | try cond_scope.setBlockBody(cond_block); | 5392 | try cond_scope.setBlockBody(cond_block); |
| | 5393 | // cond_block unstacked now, can add new instructions to loop_scope |
| | 5394 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5770 | | 5395 | |
| 5771 | // Increment the index variable. | 5396 | // Increment the index variable. |
| 5772 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); | 5397 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | @@ -5789,7 +5414,7 @@ fn forExpr( | ... | @@ -5789,7 +5414,7 @@ fn forExpr( |
| 5789 | } | 5414 | } |
| 5790 | | 5415 | |
| 5791 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); | 5416 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5792 | defer then_scope.instructions.deinit(astgen.gpa); | 5417 | defer then_scope.unstack(); |
| 5793 | | 5418 | |
| 5794 | var payload_val_scope: Scope.LocalVal = undefined; | 5419 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5795 | var index_scope: Scope.LocalPtr = undefined; | 5420 | var index_scope: Scope.LocalPtr = undefined; |
| ... | @@ -5851,7 +5476,7 @@ fn forExpr( | ... | @@ -5851,7 +5476,7 @@ fn forExpr( |
| 5851 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); | 5476 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5852 | | 5477 | |
| 5853 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); | 5478 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5854 | defer else_scope.instructions.deinit(astgen.gpa); | 5479 | defer else_scope.unstack(); |
| 5855 | | 5480 | |
| 5856 | const else_node = for_full.ast.else_expr; | 5481 | const else_node = for_full.ast.else_expr; |
| 5857 | const else_info: struct { | 5482 | const else_info: struct { |
| ... | @@ -6030,27 +5655,29 @@ fn switchExpr( | ... | @@ -6030,27 +5655,29 @@ fn switchExpr( |
| 6030 | const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node); | 5655 | const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node); |
| 6031 | const item_rl: ResultLoc = .{ .ty = cond_ty_inst }; | 5656 | const item_rl: ResultLoc = .{ .ty = cond_ty_inst }; |
| 6032 | | 5657 | |
| 6033 | // These contain the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti. | 5658 | // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti, |
| 6034 | // This is the optional else prong body. | 5659 | // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with |
| 6035 | var special_case_payload = ArrayListUnmanaged(u32){}; | 5660 | // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes |
| 6036 | defer special_case_payload.deinit(gpa); | 5661 | const payloads = &astgen.scratch; |
| 6037 | // This is all the scalar cases. | 5662 | const scratch_top = astgen.scratch.items.len; |
| 6038 | var scalar_cases_payload = ArrayListUnmanaged(u32){}; | 5663 | const case_table_start = scratch_top; |
| 6039 | defer scalar_cases_payload.deinit(gpa); | 5664 | const scalar_case_table = case_table_start + @boolToInt(special_prong != .none); |
| 6040 | // Same deal, but this is only the `extra` data for the multi cases. | 5665 | const multi_case_table = scalar_case_table + scalar_cases_len; |
| 6041 | var multi_cases_payload = ArrayListUnmanaged(u32){}; | 5666 | const case_table_end = multi_case_table + multi_cases_len; |
| 6042 | defer multi_cases_payload.deinit(gpa); | 5667 | try astgen.scratch.resize(gpa, case_table_end); |
| | 5668 | defer astgen.scratch.items.len = scratch_top; |
| 6043 | | 5669 | |
| 6044 | var block_scope = parent_gz.makeSubBlock(scope); | 5670 | var block_scope = parent_gz.makeSubBlock(scope); |
| | 5671 | // block_scope not used for collecting instructions |
| | 5672 | block_scope.instructions_top = GenZir.unstacked_top; |
| 6045 | block_scope.setBreakResultLoc(rl); | 5673 | block_scope.setBreakResultLoc(rl); |
| 6046 | defer block_scope.instructions.deinit(gpa); | | |
| 6047 | | 5674 | |
| 6048 | // This gets added to the parent block later, after the item expressions. | 5675 | // This gets added to the parent block later, after the item expressions. |
| 6049 | const switch_block = try parent_gz.addBlock(.switch_block, switch_node); | 5676 | const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); |
| 6050 | | 5677 | |
| 6051 | // We re-use this same scope for all cases, including the special prong, if any. | 5678 | // We re-use this same scope for all cases, including the special prong, if any. |
| 6052 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); | 5679 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); |
| 6053 | defer case_scope.instructions.deinit(gpa); | 5680 | case_scope.instructions_top = GenZir.unstacked_top; |
| 6054 | | 5681 | |
| 6055 | // In this pass we generate all the item and prong expressions. | 5682 | // In this pass we generate all the item and prong expressions. |
| 6056 | var multi_case_index: u32 = 0; | 5683 | var multi_case_index: u32 = 0; |
| ... | @@ -6062,21 +5689,12 @@ fn switchExpr( | ... | @@ -6062,21 +5689,12 @@ fn switchExpr( |
| 6062 | else => unreachable, | 5689 | else => unreachable, |
| 6063 | }; | 5690 | }; |
| 6064 | | 5691 | |
| 6065 | // Reset the scope. | | |
| 6066 | case_scope.instructions.shrinkRetainingCapacity(0); | | |
| 6067 | | | |
| 6068 | const is_multi_case = case.ast.values.len > 1 or | 5692 | const is_multi_case = case.ast.values.len > 1 or |
| 6069 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); | 5693 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); |
| 6070 | | 5694 | |
| | 5695 | var capture_inst: Zir.Inst.Index = 0; |
| 6071 | var capture_val_scope: Scope.LocalVal = undefined; | 5696 | var capture_val_scope: Scope.LocalVal = undefined; |
| 6072 | const sub_scope = blk: { | 5697 | const sub_scope = blk: { |
| 6073 | const capture_index = if (is_multi_case) ci: { | | |
| 6074 | multi_case_index += 1; | | |
| 6075 | break :ci multi_case_index - 1; | | |
| 6076 | } else ci: { | | |
| 6077 | scalar_case_index += 1; | | |
| 6078 | break :ci scalar_case_index - 1; | | |
| 6079 | }; | | |
| 6080 | const payload_token = case.payload_token orelse break :blk &case_scope.base; | 5698 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 6081 | const ident = if (token_tags[payload_token] == .asterisk) | 5699 | const ident = if (token_tags[payload_token] == .asterisk) |
| 6082 | payload_token + 1 | 5700 | payload_token + 1 |
| ... | @@ -6089,19 +5707,20 @@ fn switchExpr( | ... | @@ -6089,19 +5707,20 @@ fn switchExpr( |
| 6089 | } | 5707 | } |
| 6090 | break :blk &case_scope.base; | 5708 | break :blk &case_scope.base; |
| 6091 | } | 5709 | } |
| 6092 | const capture = if (case_node == special_node) capture: { | 5710 | if (case_node == special_node) { |
| 6093 | const capture_tag: Zir.Inst.Tag = if (is_ptr) | 5711 | const capture_tag: Zir.Inst.Tag = if (is_ptr) |
| 6094 | .switch_capture_else_ref | 5712 | .switch_capture_else_ref |
| 6095 | else | 5713 | else |
| 6096 | .switch_capture_else; | 5714 | .switch_capture_else; |
| 6097 | break :capture try case_scope.add(.{ | 5715 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| | 5716 | try astgen.instructions.append(gpa, .{ |
| 6098 | .tag = capture_tag, | 5717 | .tag = capture_tag, |
| 6099 | .data = .{ .switch_capture = .{ | 5718 | .data = .{ .switch_capture = .{ |
| 6100 | .switch_inst = switch_block, | 5719 | .switch_inst = switch_block, |
| 6101 | .prong_index = undefined, | 5720 | .prong_index = undefined, |
| 6102 | } }, | 5721 | } }, |
| 6103 | }); | 5722 | }); |
| 6104 | } else capture: { | 5723 | } else { |
| 6105 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); | 5724 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); |
| 6106 | const is_ptr_bits: u2 = @boolToInt(is_ptr); | 5725 | const is_ptr_bits: u2 = @boolToInt(is_ptr); |
| 6107 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { | 5726 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { |
| ... | @@ -6110,30 +5729,33 @@ fn switchExpr( | ... | @@ -6110,30 +5729,33 @@ fn switchExpr( |
| 6110 | 0b10 => .switch_capture_multi, | 5729 | 0b10 => .switch_capture_multi, |
| 6111 | 0b11 => .switch_capture_multi_ref, | 5730 | 0b11 => .switch_capture_multi_ref, |
| 6112 | }; | 5731 | }; |
| 6113 | break :capture try case_scope.add(.{ | 5732 | const capture_index = if (is_multi_case) multi_case_index else scalar_case_index; |
| | 5733 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| | 5734 | try astgen.instructions.append(gpa, .{ |
| 6114 | .tag = capture_tag, | 5735 | .tag = capture_tag, |
| 6115 | .data = .{ .switch_capture = .{ | 5736 | .data = .{ .switch_capture = .{ |
| 6116 | .switch_inst = switch_block, | 5737 | .switch_inst = switch_block, |
| 6117 | .prong_index = capture_index, | 5738 | .prong_index = capture_index, |
| 6118 | } }, | 5739 | } }, |
| 6119 | }); | 5740 | }); |
| 6120 | }; | 5741 | } |
| 6121 | const capture_name = try astgen.identAsString(ident); | 5742 | const capture_name = try astgen.identAsString(ident); |
| 6122 | capture_val_scope = .{ | 5743 | capture_val_scope = .{ |
| 6123 | .parent = &case_scope.base, | 5744 | .parent = &case_scope.base, |
| 6124 | .gen_zir = &case_scope, | 5745 | .gen_zir = &case_scope, |
| 6125 | .name = capture_name, | 5746 | .name = capture_name, |
| 6126 | .inst = capture, | 5747 | .inst = indexToRef(capture_inst), |
| 6127 | .token_src = payload_token, | 5748 | .token_src = payload_token, |
| 6128 | .id_cat = .@"capture", | 5749 | .id_cat = .@"capture", |
| 6129 | }; | 5750 | }; |
| 6130 | break :blk &capture_val_scope.base; | 5751 | break :blk &capture_val_scope.base; |
| 6131 | }; | 5752 | }; |
| 6132 | | 5753 | |
| 6133 | if (is_multi_case) { | 5754 | const header_index = @intCast(u32, payloads.items.len); |
| 6134 | // items_len, ranges_len, body_len | 5755 | const body_len_index = if (is_multi_case) blk: { |
| 6135 | const header_index = multi_cases_payload.items.len; | 5756 | payloads.items[multi_case_table + multi_case_index] = header_index; |
| 6136 | try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3); | 5757 | multi_case_index += 1; |
| | 5758 | try payloads.resize(gpa, header_index + 3); // items_len, ranges_len, body_len |
| 6137 | | 5759 | |
| 6138 | // items | 5760 | // items |
| 6139 | var items_len: u32 = 0; | 5761 | var items_len: u32 = 0; |
| ... | @@ -6142,7 +5764,7 @@ fn switchExpr( | ... | @@ -6142,7 +5764,7 @@ fn switchExpr( |
| 6142 | items_len += 1; | 5764 | items_len += 1; |
| 6143 | | 5765 | |
| 6144 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); | 5766 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 6145 | try multi_cases_payload.append(gpa, @enumToInt(item_inst)); | 5767 | try payloads.append(gpa, @enumToInt(item_inst)); |
| 6146 | } | 5768 | } |
| 6147 | | 5769 | |
| 6148 | // ranges | 5770 | // ranges |
| ... | @@ -6153,47 +5775,44 @@ fn switchExpr( | ... | @@ -6153,47 +5775,44 @@ fn switchExpr( |
| 6153 | | 5775 | |
| 6154 | const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); | 5776 | const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); |
| 6155 | const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs); | 5777 | const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs); |
| 6156 | try multi_cases_payload.appendSlice(gpa, &[_]u32{ | 5778 | try payloads.appendSlice(gpa, &[_]u32{ |
| 6157 | @enumToInt(first), @enumToInt(last), | 5779 | @enumToInt(first), @enumToInt(last), |
| 6158 | }); | 5780 | }); |
| 6159 | } | 5781 | } |
| 6160 | | 5782 | |
| 6161 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 5783 | payloads.items[header_index] = items_len; |
| 6162 | try checkUsed(parent_gz, &case_scope.base, sub_scope); | 5784 | payloads.items[header_index + 1] = ranges_len; |
| 6163 | if (!parent_gz.refIsNoReturn(case_result)) { | 5785 | break :blk header_index + 2; |
| 6164 | block_scope.break_count += 1; | 5786 | } else if (case_node == special_node) blk: { |
| 6165 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 5787 | payloads.items[case_table_start] = header_index; |
| 6166 | } | 5788 | try payloads.resize(gpa, header_index + 1); // body_len |
| 6167 | | 5789 | break :blk header_index; |
| 6168 | multi_cases_payload.items[header_index + 0] = items_len; | 5790 | } else blk: { |
| 6169 | multi_cases_payload.items[header_index + 1] = ranges_len; | 5791 | payloads.items[scalar_case_table + scalar_case_index] = header_index; |
| 6170 | multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len); | 5792 | scalar_case_index += 1; |
| 6171 | try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items); | 5793 | try payloads.resize(gpa, header_index + 2); // item, body_len |
| 6172 | } else if (case_node == special_node) { | | |
| 6173 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | | |
| 6174 | try checkUsed(parent_gz, &case_scope.base, sub_scope); | | |
| 6175 | if (!parent_gz.refIsNoReturn(case_result)) { | | |
| 6176 | block_scope.break_count += 1; | | |
| 6177 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | | |
| 6178 | } | | |
| 6179 | try special_case_payload.ensureUnusedCapacity(gpa, 1 + // body_len | | |
| 6180 | case_scope.instructions.items.len); | | |
| 6181 | special_case_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); | | |
| 6182 | special_case_payload.appendSliceAssumeCapacity(case_scope.instructions.items); | | |
| 6183 | } else { | | |
| 6184 | const item_node = case.ast.values[0]; | 5794 | const item_node = case.ast.values[0]; |
| 6185 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); | 5795 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| | 5796 | payloads.items[header_index] = @enumToInt(item_inst); |
| | 5797 | break :blk header_index + 1; |
| | 5798 | }; |
| | 5799 | |
| | 5800 | { |
| | 5801 | // temporarily stack case_scope on parent_gz |
| | 5802 | case_scope.instructions_top = parent_gz.instructions.items.len; |
| | 5803 | defer case_scope.unstack(); |
| | 5804 | |
| | 5805 | if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst); |
| 6186 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); | 5806 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6187 | try checkUsed(parent_gz, &case_scope.base, sub_scope); | 5807 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6188 | if (!parent_gz.refIsNoReturn(case_result)) { | 5808 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6189 | block_scope.break_count += 1; | 5809 | block_scope.break_count += 1; |
| 6190 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); | 5810 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6191 | } | 5811 | } |
| 6192 | try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + // item + body_len | 5812 | |
| 6193 | case_scope.instructions.items.len); | 5813 | const case_slice = case_scope.instructionsSlice(); |
| 6194 | scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst)); | 5814 | payloads.items[body_len_index] = @intCast(u32, case_slice.len); |
| 6195 | scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); | 5815 | try payloads.appendSlice(gpa, case_slice); |
| 6196 | scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items); | | |
| 6197 | } | 5816 | } |
| 6198 | } | 5817 | } |
| 6199 | // Now that the item expressions are generated we can add this. | 5818 | // Now that the item expressions are generated we can add this. |
| ... | @@ -6201,9 +5820,7 @@ fn switchExpr( | ... | @@ -6201,9 +5820,7 @@ fn switchExpr( |
| 6201 | | 5820 | |
| 6202 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len + | 5821 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len + |
| 6203 | @boolToInt(multi_cases_len != 0) + | 5822 | @boolToInt(multi_cases_len != 0) + |
| 6204 | special_case_payload.items.len + | 5823 | payloads.items.len - case_table_end); |
| 6205 | scalar_cases_payload.items.len + | | |
| 6206 | multi_cases_payload.items.len); | | |
| 6207 | | 5824 | |
| 6208 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{ | 5825 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{ |
| 6209 | .operand = cond, | 5826 | .operand = cond, |
| ... | @@ -6216,105 +5833,59 @@ fn switchExpr( | ... | @@ -6216,105 +5833,59 @@ fn switchExpr( |
| 6216 | }, | 5833 | }, |
| 6217 | }); | 5834 | }); |
| 6218 | | 5835 | |
| 6219 | const zir_datas = astgen.instructions.items(.data); | | |
| 6220 | const zir_tags = astgen.instructions.items(.tag); | | |
| 6221 | | | |
| 6222 | zir_datas[switch_block].pl_node.payload_index = payload_index; | | |
| 6223 | | | |
| 6224 | if (multi_cases_len != 0) { | 5836 | if (multi_cases_len != 0) { |
| 6225 | astgen.extra.appendAssumeCapacity(multi_cases_len); | 5837 | astgen.extra.appendAssumeCapacity(multi_cases_len); |
| 6226 | } | 5838 | } |
| 6227 | | 5839 | |
| 6228 | const strat = rl.strategy(&block_scope); | 5840 | const zir_datas = astgen.instructions.items(.data); |
| 6229 | switch (strat.tag) { | 5841 | const zir_tags = astgen.instructions.items(.tag); |
| 6230 | .break_operand => { | | |
| 6231 | // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus | | |
| 6232 | // `elide_store_to_block_ptr_instructions` will either be true, | | |
| 6233 | // or all prongs are noreturn. | | |
| 6234 | if (!strat.elide_store_to_block_ptr_instructions) { | | |
| 6235 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); | | |
| 6236 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); | | |
| 6237 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); | | |
| 6238 | return indexToRef(switch_block); | | |
| 6239 | } | | |
| 6240 | | 5842 | |
| 6241 | // There will necessarily be a store_to_block_ptr for | 5843 | zir_datas[switch_block].pl_node.payload_index = payload_index; |
| 6242 | // all prongs, except for prongs that ended with a noreturn instruction. | | |
| 6243 | // Elide all the `store_to_block_ptr` instructions. | | |
| 6244 | | 5844 | |
| 6245 | // The break instructions need to have their operands coerced if the | 5845 | const strat = rl.strategy(&block_scope); |
| 6246 | // switch's result location is a `ty`. In this case we overwrite the | 5846 | for (payloads.items[case_table_start..case_table_end]) |start_index, i| { |
| 6247 | // `store_to_block_ptr` instruction with an `as` instruction and repurpose | 5847 | var body_len_index = start_index; |
| 6248 | // it as the break operand. | 5848 | var end_index = start_index; |
| | 5849 | const table_index = case_table_start + i; |
| | 5850 | if (table_index < scalar_case_table) { |
| | 5851 | end_index += 1; |
| | 5852 | } else if (table_index < multi_case_table) { |
| | 5853 | body_len_index += 1; |
| | 5854 | end_index += 2; |
| | 5855 | } else { |
| | 5856 | body_len_index += 2; |
| | 5857 | const items_len = payloads.items[start_index]; |
| | 5858 | const ranges_len = payloads.items[start_index + 1]; |
| | 5859 | end_index += 3 + items_len + 2 * ranges_len; |
| | 5860 | } |
| 6249 | | 5861 | |
| 6250 | var extra_index: usize = 0; | 5862 | const body_len = payloads.items[body_len_index]; |
| 6251 | if (special_prong != .none) special_prong: { | 5863 | end_index += body_len; |
| 6252 | const body_len_index = extra_index; | 5864 | |
| 6253 | const body_len = special_case_payload.items[extra_index]; | 5865 | switch (strat.tag) { |
| 6254 | extra_index += 1; | 5866 | .break_operand => blk: { |
| 6255 | if (body_len < 2) { | 5867 | // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus |
| 6256 | extra_index += body_len; | 5868 | // `elide_store_to_block_ptr_instructions` will either be true, |
| 6257 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); | 5869 | // or all prongs are noreturn. |
| 6258 | break :special_prong; | 5870 | if (!strat.elide_store_to_block_ptr_instructions) |
| 6259 | } | 5871 | break :blk; |
| 6260 | extra_index += body_len - 2; | 5872 | |
| 6261 | const store_inst = special_case_payload.items[extra_index]; | 5873 | // There will necessarily be a store_to_block_ptr for |
| 6262 | if (zir_tags[store_inst] != .store_to_block_ptr or | 5874 | // all prongs, except for prongs that ended with a noreturn instruction. |
| 6263 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) | 5875 | // Elide all the `store_to_block_ptr` instructions. |
| 6264 | { | 5876 | |
| 6265 | extra_index += 2; | 5877 | // The break instructions need to have their operands coerced if the |
| 6266 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); | 5878 | // switch's result location is a `ty`. In this case we overwrite the |
| 6267 | break :special_prong; | 5879 | // `store_to_block_ptr` instruction with an `as` instruction and repurpose |
| 6268 | } | 5880 | // it as the break operand. |
| 6269 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); | 5881 | if (body_len < 2) |
| 6270 | if (block_scope.rl_ty_inst != .none) { | 5882 | break :blk; |
| 6271 | extra_index += 1; | 5883 | const store_inst = payloads.items[end_index - 2]; |
| 6272 | const break_inst = special_case_payload.items[extra_index]; | | |
| 6273 | extra_index += 1; | | |
| 6274 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); | | |
| 6275 | zir_tags[store_inst] = .as; | | |
| 6276 | zir_datas[store_inst].bin = .{ | | |
| 6277 | .lhs = block_scope.rl_ty_inst, | | |
| 6278 | .rhs = zir_datas[break_inst].@"break".operand, | | |
| 6279 | }; | | |
| 6280 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); | | |
| 6281 | } else { | | |
| 6282 | special_case_payload.items[body_len_index] -= 1; | | |
| 6283 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); | | |
| 6284 | extra_index += 1; | | |
| 6285 | astgen.extra.appendAssumeCapacity(special_case_payload.items[extra_index]); | | |
| 6286 | extra_index += 1; | | |
| 6287 | } | | |
| 6288 | } else { | | |
| 6289 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); | | |
| 6290 | } | | |
| 6291 | extra_index = 0; | | |
| 6292 | var scalar_i: u32 = 0; | | |
| 6293 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | | |
| 6294 | const start_index = extra_index; | | |
| 6295 | extra_index += 1; | | |
| 6296 | const body_len_index = extra_index; | | |
| 6297 | const body_len = scalar_cases_payload.items[extra_index]; | | |
| 6298 | extra_index += 1; | | |
| 6299 | if (body_len < 2) { | | |
| 6300 | extra_index += body_len; | | |
| 6301 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); | | |
| 6302 | continue; | | |
| 6303 | } | | |
| 6304 | extra_index += body_len - 2; | | |
| 6305 | const store_inst = scalar_cases_payload.items[extra_index]; | | |
| 6306 | if (zir_tags[store_inst] != .store_to_block_ptr or | 5884 | if (zir_tags[store_inst] != .store_to_block_ptr or |
| 6307 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) | 5885 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) |
| 6308 | { | 5886 | break :blk; |
| 6309 | extra_index += 2; | 5887 | const break_inst = payloads.items[end_index - 1]; |
| 6310 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); | | |
| 6311 | continue; | | |
| 6312 | } | | |
| 6313 | if (block_scope.rl_ty_inst != .none) { | 5888 | if (block_scope.rl_ty_inst != .none) { |
| 6314 | extra_index += 1; | | |
| 6315 | const break_inst = scalar_cases_payload.items[extra_index]; | | |
| 6316 | extra_index += 1; | | |
| 6317 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); | | |
| 6318 | zir_tags[store_inst] = .as; | 5889 | zir_tags[store_inst] = .as; |
| 6319 | zir_datas[store_inst].bin = .{ | 5890 | zir_datas[store_inst].bin = .{ |
| 6320 | .lhs = block_scope.rl_ty_inst, | 5891 | .lhs = block_scope.rl_ty_inst, |
| ... | @@ -6322,125 +5893,30 @@ fn switchExpr( | ... | @@ -6322,125 +5893,30 @@ fn switchExpr( |
| 6322 | }; | 5893 | }; |
| 6323 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); | 5894 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); |
| 6324 | } else { | 5895 | } else { |
| 6325 | scalar_cases_payload.items[body_len_index] -= 1; | 5896 | payloads.items[body_len_index] -= 1; |
| 6326 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); | 5897 | astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index .. end_index - 2]); |
| 6327 | extra_index += 1; | 5898 | astgen.extra.appendAssumeCapacity(break_inst); |
| 6328 | astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]); | | |
| 6329 | extra_index += 1; | | |
| 6330 | } | | |
| 6331 | } | | |
| 6332 | extra_index = 0; | | |
| 6333 | var multi_i: u32 = 0; | | |
| 6334 | while (multi_i < multi_cases_len) : (multi_i += 1) { | | |
| 6335 | const start_index = extra_index; | | |
| 6336 | const items_len = multi_cases_payload.items[extra_index]; | | |
| 6337 | extra_index += 1; | | |
| 6338 | const ranges_len = multi_cases_payload.items[extra_index]; | | |
| 6339 | extra_index += 1; | | |
| 6340 | const body_len_index = extra_index; | | |
| 6341 | const body_len = multi_cases_payload.items[extra_index]; | | |
| 6342 | extra_index += 1; | | |
| 6343 | extra_index += items_len; | | |
| 6344 | extra_index += 2 * ranges_len; | | |
| 6345 | if (body_len < 2) { | | |
| 6346 | extra_index += body_len; | | |
| 6347 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); | | |
| 6348 | continue; | | |
| 6349 | } | | |
| 6350 | extra_index += body_len - 2; | | |
| 6351 | const store_inst = multi_cases_payload.items[extra_index]; | | |
| 6352 | if (zir_tags[store_inst] != .store_to_block_ptr or | | |
| 6353 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) | | |
| 6354 | { | | |
| 6355 | extra_index += 2; | | |
| 6356 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); | | |
| 6357 | continue; | 5899 | continue; |
| 6358 | } | 5900 | } |
| 6359 | if (block_scope.rl_ty_inst != .none) { | 5901 | }, |
| 6360 | extra_index += 1; | 5902 | .break_void => { |
| 6361 | const break_inst = multi_cases_payload.items[extra_index]; | 5903 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 6362 | extra_index += 1; | 5904 | const last_inst = payloads.items[end_index - 1]; |
| 6363 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); | 5905 | if (zir_tags[last_inst] == .@"break" and |
| 6364 | zir_tags[store_inst] = .as; | 5906 | zir_datas[last_inst].@"break".block_inst == switch_block) |
| 6365 | zir_datas[store_inst].bin = .{ | | |
| 6366 | .lhs = block_scope.rl_ty_inst, | | |
| 6367 | .rhs = zir_datas[break_inst].@"break".operand, | | |
| 6368 | }; | | |
| 6369 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); | | |
| 6370 | } else { | | |
| 6371 | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); | | |
| 6372 | multi_cases_payload.items[body_len_index] -= 1; | | |
| 6373 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); | | |
| 6374 | extra_index += 1; | | |
| 6375 | astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]); | | |
| 6376 | extra_index += 1; | | |
| 6377 | } | | |
| 6378 | } | | |
| 6379 | | | |
| 6380 | const block_ref = indexToRef(switch_block); | | |
| 6381 | switch (rl) { | | |
| 6382 | .ref => return block_ref, | | |
| 6383 | else => return rvalue(parent_gz, rl, block_ref, switch_node), | | |
| 6384 | } | | |
| 6385 | }, | | |
| 6386 | .break_void => { | | |
| 6387 | assert(!strat.elide_store_to_block_ptr_instructions); | | |
| 6388 | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); | | |
| 6389 | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); | | |
| 6390 | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); | | |
| 6391 | // Modify all the terminating instruction tags to become `break` variants. | | |
| 6392 | var extra_index: usize = payload_index; | | |
| 6393 | extra_index += 2; | | |
| 6394 | extra_index += @boolToInt(multi_cases_len != 0); | | |
| 6395 | if (special_prong != .none) { | | |
| 6396 | const body_len = astgen.extra.items[extra_index]; | | |
| 6397 | extra_index += 1; | | |
| 6398 | const body = astgen.extra.items[extra_index..][0..body_len]; | | |
| 6399 | extra_index += body_len; | | |
| 6400 | const last = body[body.len - 1]; | | |
| 6401 | if (zir_tags[last] == .@"break" and | | |
| 6402 | zir_datas[last].@"break".block_inst == switch_block) | | |
| 6403 | { | | |
| 6404 | zir_datas[last].@"break".operand = .void_value; | | |
| 6405 | } | | |
| 6406 | } | | |
| 6407 | var scalar_i: u32 = 0; | | |
| 6408 | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { | | |
| 6409 | extra_index += 1; | | |
| 6410 | const body_len = astgen.extra.items[extra_index]; | | |
| 6411 | extra_index += 1; | | |
| 6412 | const body = astgen.extra.items[extra_index..][0..body_len]; | | |
| 6413 | extra_index += body_len; | | |
| 6414 | const last = body[body.len - 1]; | | |
| 6415 | if (zir_tags[last] == .@"break" and | | |
| 6416 | zir_datas[last].@"break".block_inst == switch_block) | | |
| 6417 | { | | |
| 6418 | zir_datas[last].@"break".operand = .void_value; | | |
| 6419 | } | | |
| 6420 | } | | |
| 6421 | var multi_i: u32 = 0; | | |
| 6422 | while (multi_i < multi_cases_len) : (multi_i += 1) { | | |
| 6423 | const items_len = astgen.extra.items[extra_index]; | | |
| 6424 | extra_index += 1; | | |
| 6425 | const ranges_len = astgen.extra.items[extra_index]; | | |
| 6426 | extra_index += 1; | | |
| 6427 | const body_len = astgen.extra.items[extra_index]; | | |
| 6428 | extra_index += 1; | | |
| 6429 | extra_index += items_len; | | |
| 6430 | extra_index += 2 * ranges_len; | | |
| 6431 | const body = astgen.extra.items[extra_index..][0..body_len]; | | |
| 6432 | extra_index += body_len; | | |
| 6433 | const last = body[body.len - 1]; | | |
| 6434 | if (zir_tags[last] == .@"break" and | | |
| 6435 | zir_datas[last].@"break".block_inst == switch_block) | | |
| 6436 | { | 5907 | { |
| 6437 | zir_datas[last].@"break".operand = .void_value; | 5908 | zir_datas[last_inst].@"break".operand = .void_value; |
| 6438 | } | 5909 | } |
| 6439 | } | 5910 | }, |
| | 5911 | } |
| 6440 | | 5912 | |
| 6441 | return indexToRef(switch_block); | 5913 | astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index..end_index]); |
| 6442 | }, | | |
| 6443 | } | 5914 | } |
| | 5915 | |
| | 5916 | const block_ref = indexToRef(switch_block); |
| | 5917 | if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref) |
| | 5918 | return rvalue(parent_gz, rl, block_ref, switch_node); |
| | 5919 | return block_ref; |
| 6444 | } | 5920 | } |
| 6445 | | 5921 | |
| 6446 | fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { | 5922 | fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| ... | @@ -6519,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -6519,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6519 | const condbr = try gz.addCondBr(.condbr, node); | 5995 | const condbr = try gz.addCondBr(.condbr, node); |
| 6520 | | 5996 | |
| 6521 | var then_scope = gz.makeSubBlock(scope); | 5997 | var then_scope = gz.makeSubBlock(scope); |
| 6522 | defer then_scope.instructions.deinit(astgen.gpa); | 5998 | defer then_scope.unstack(); |
| 6523 | | 5999 | |
| 6524 | try genDefers(&then_scope, defer_outer, scope, .normal_only); | 6000 | try genDefers(&then_scope, defer_outer, scope, .normal_only); |
| 6525 | try then_scope.addRet(rl, operand, node); | 6001 | try then_scope.addRet(rl, operand, node); |
| 6526 | | 6002 | |
| 6527 | var else_scope = gz.makeSubBlock(scope); | 6003 | var else_scope = gz.makeSubBlock(scope); |
| 6528 | defer else_scope.instructions.deinit(astgen.gpa); | 6004 | defer else_scope.unstack(); |
| 6529 | | 6005 | |
| 6530 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ | 6006 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ |
| 6531 | .both = try else_scope.addUnNode(.err_union_code, result, node), | 6007 | .both = try else_scope.addUnNode(.err_union_code, result, node), |
| ... | @@ -6533,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref | ... | @@ -6533,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6533 | try genDefers(&else_scope, defer_outer, scope, which_ones); | 6009 | try genDefers(&else_scope, defer_outer, scope, which_ones); |
| 6534 | try else_scope.addRet(rl, operand, node); | 6010 | try else_scope.addRet(rl, operand, node); |
| 6535 | | 6011 | |
| 6536 | try setCondBrPayload(condbr, is_non_err, &then_scope, &else_scope); | 6012 | try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0); |
| 6537 | | 6013 | |
| 6538 | return Zir.Inst.Ref.unreachable_value; | 6014 | return Zir.Inst.Ref.unreachable_value; |
| 6539 | }, | 6015 | }, |
| ... | @@ -6559,25 +6035,25 @@ fn identifier( | ... | @@ -6559,25 +6035,25 @@ fn identifier( |
| 6559 | if (mem.eql(u8, ident_name_raw, "_")) { | 6035 | if (mem.eql(u8, ident_name_raw, "_")) { |
| 6560 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); | 6036 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); |
| 6561 | } | 6037 | } |
| 6562 | const ident_name = try astgen.identifierTokenString(ident_token); | | |
| 6563 | | 6038 | |
| | 6039 | // if not @"" syntax, just use raw token slice |
| 6564 | if (ident_name_raw[0] != '@') { | 6040 | if (ident_name_raw[0] != '@') { |
| 6565 | if (primitives.get(ident_name)) |zir_const_ref| { | 6041 | if (primitives.get(ident_name_raw)) |zir_const_ref| { |
| 6566 | return rvalue(gz, rl, zir_const_ref, ident); | 6042 | return rvalue(gz, rl, zir_const_ref, ident); |
| 6567 | } | 6043 | } |
| 6568 | | 6044 | |
| 6569 | if (ident_name.len >= 2) integer: { | 6045 | if (ident_name_raw.len >= 2) integer: { |
| 6570 | const first_c = ident_name[0]; | 6046 | const first_c = ident_name_raw[0]; |
| 6571 | if (first_c == 'i' or first_c == 'u') { | 6047 | if (first_c == 'i' or first_c == 'u') { |
| 6572 | const signedness: std.builtin.Signedness = switch (first_c == 'i') { | 6048 | const signedness: std.builtin.Signedness = switch (first_c == 'i') { |
| 6573 | true => .signed, | 6049 | true => .signed, |
| 6574 | false => .unsigned, | 6050 | false => .unsigned, |
| 6575 | }; | 6051 | }; |
| 6576 | const bit_count = std.fmt.parseInt(u16, ident_name[1..], 10) catch |err| switch (err) { | 6052 | const bit_count = std.fmt.parseInt(u16, ident_name_raw[1..], 10) catch |err| switch (err) { |
| 6577 | error.Overflow => return astgen.failNode( | 6053 | error.Overflow => return astgen.failNode( |
| 6578 | ident, | 6054 | ident, |
| 6579 | "primitive integer type '{s}' exceeds maximum bit width of 65535", | 6055 | "primitive integer type '{s}' exceeds maximum bit width of 65535", |
| 6580 | .{ident_name}, | 6056 | .{ident_name_raw}, |
| 6581 | ), | 6057 | ), |
| 6582 | error.InvalidCharacter => break :integer, | 6058 | error.InvalidCharacter => break :integer, |
| 6583 | }; | 6059 | }; |
| ... | @@ -6630,6 +6106,7 @@ fn identifier( | ... | @@ -6630,6 +6106,7 @@ fn identifier( |
| 6630 | | 6106 | |
| 6631 | // Can't close over a runtime variable | 6107 | // Can't close over a runtime variable |
| 6632 | if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) { | 6108 | if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) { |
| | 6109 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 6633 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ | 6110 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ |
| 6634 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), | 6111 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), |
| 6635 | try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}), | 6112 | try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}), |
| ... | @@ -6677,6 +6154,7 @@ fn identifier( | ... | @@ -6677,6 +6154,7 @@ fn identifier( |
| 6677 | .top => break, | 6154 | .top => break, |
| 6678 | }; | 6155 | }; |
| 6679 | if (found_already == null) { | 6156 | if (found_already == null) { |
| | 6157 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 6680 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); | 6158 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); |
| 6681 | } | 6159 | } |
| 6682 | | 6160 | |
| ... | @@ -6712,9 +6190,15 @@ fn tunnelThroughClosure( | ... | @@ -6712,9 +6190,15 @@ fn tunnelThroughClosure( |
| 6712 | // already has one for this value. | 6190 | // already has one for this value. |
| 6713 | const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?); | 6191 | const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?); |
| 6714 | if (!gop.found_existing) { | 6192 | if (!gop.found_existing) { |
| 6715 | // Make a new capture for this value | 6193 | // Make a new capture for this value but don't add it to the declaring_gz yet |
| 6716 | const capture_ref = try ns.?.declaring_gz.?.addUnTok(.closure_capture, value, token); | 6194 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| 6717 | gop.value_ptr.* = refToIndex(capture_ref).?; | 6195 | .tag = .closure_capture, |
| | 6196 | .data = .{ .un_tok = .{ |
| | 6197 | .operand = value, |
| | 6198 | .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token), |
| | 6199 | } }, |
| | 6200 | }); |
| | 6201 | gop.value_ptr.* = @intCast(Zir.Inst.Index, gz.astgen.instructions.len - 1); |
| 6718 | } | 6202 | } |
| 6719 | | 6203 | |
| 6720 | // Add an instruction to get the value from the closure into | 6204 | // Add an instruction to get the value from the closure into |
| ... | @@ -7155,10 +6639,8 @@ fn asRlPtr( | ... | @@ -7155,10 +6639,8 @@ fn asRlPtr( |
| 7155 | operand_node: Ast.Node.Index, | 6639 | operand_node: Ast.Node.Index, |
| 7156 | dest_type: Zir.Inst.Ref, | 6640 | dest_type: Zir.Inst.Ref, |
| 7157 | ) InnerError!Zir.Inst.Ref { | 6641 | ) InnerError!Zir.Inst.Ref { |
| 7158 | const astgen = parent_gz.astgen; | | |
| 7159 | | | |
| 7160 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr); | 6642 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr); |
| 7161 | defer as_scope.instructions.deinit(astgen.gpa); | 6643 | defer as_scope.unstack(); |
| 7162 | | 6644 | |
| 7163 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); | 6645 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); |
| 7164 | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); | 6646 | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); |
| ... | @@ -7196,13 +6678,18 @@ fn typeOf( | ... | @@ -7196,13 +6678,18 @@ fn typeOf( |
| 7196 | const result = try gz.addUnNode(.typeof, expr_result, node); | 6678 | const result = try gz.addUnNode(.typeof, expr_result, node); |
| 7197 | return rvalue(gz, rl, result, node); | 6679 | return rvalue(gz, rl, result, node); |
| 7198 | } | 6680 | } |
| 7199 | const arena = gz.astgen.arena; | 6681 | |
| 7200 | var items = try arena.alloc(Zir.Inst.Ref, params.len); | 6682 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ |
| 7201 | for (params) |param, param_i| { | 6683 | .src_node = gz.nodeIndexToRelative(node), |
| 7202 | items[param_i] = try reachableExpr(gz, scope, .none, param, node); | 6684 | }); |
| | 6685 | var extra_index = try reserveExtra(gz.astgen, params.len); |
| | 6686 | for (params) |param| { |
| | 6687 | const param_ref = try reachableExpr(gz, scope, .none, param, node); |
| | 6688 | gz.astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| | 6689 | extra_index += 1; |
| 7203 | } | 6690 | } |
| 7204 | | 6691 | |
| 7205 | const result = try gz.addExtendedMultiOp(.typeof_peer, node, items); | 6692 | const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len); |
| 7206 | return rvalue(gz, rl, result, node); | 6693 | return rvalue(gz, rl, result, node); |
| 7207 | } | 6694 | } |
| 7208 | | 6695 | |
| ... | @@ -7259,12 +6746,16 @@ fn builtinCall( | ... | @@ -7259,12 +6746,16 @@ fn builtinCall( |
| 7259 | return rvalue(gz, rl, result, node); | 6746 | return rvalue(gz, rl, result, node); |
| 7260 | }, | 6747 | }, |
| 7261 | .compile_log => { | 6748 | .compile_log => { |
| 7262 | const arg_refs = try astgen.gpa.alloc(Zir.Inst.Ref, params.len); | 6749 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ |
| 7263 | defer astgen.gpa.free(arg_refs); | 6750 | .src_node = gz.nodeIndexToRelative(node), |
| 7264 | | 6751 | }); |
| 7265 | for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param); | 6752 | var extra_index = try reserveExtra(gz.astgen, params.len); |
| 7266 | | 6753 | for (params) |param| { |
| 7267 | const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs); | 6754 | const param_ref = try expr(gz, scope, .none, param); |
| | 6755 | astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| | 6756 | extra_index += 1; |
| | 6757 | } |
| | 6758 | const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log,payload_index, params.len); |
| 7268 | return rvalue(gz, rl, result, node); | 6759 | return rvalue(gz, rl, result, node); |
| 7269 | }, | 6760 | }, |
| 7270 | .field => { | 6761 | .field => { |
| ... | @@ -7921,14 +7412,15 @@ fn cImport( | ... | @@ -7921,14 +7412,15 @@ fn cImport( |
| 7921 | var block_scope = gz.makeSubBlock(scope); | 7412 | var block_scope = gz.makeSubBlock(scope); |
| 7922 | block_scope.force_comptime = true; | 7413 | block_scope.force_comptime = true; |
| 7923 | block_scope.c_import = true; | 7414 | block_scope.c_import = true; |
| 7924 | defer block_scope.instructions.deinit(gpa); | 7415 | defer block_scope.unstack(); |
| 7925 | | 7416 | |
| 7926 | const block_inst = try gz.addBlock(.c_import, node); | 7417 | const block_inst = try gz.makeBlockInst(.c_import, node); |
| 7927 | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); | 7418 | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); |
| 7928 | if (!gz.refIsNoReturn(block_result)) { | 7419 | if (!gz.refIsNoReturn(block_result)) { |
| 7929 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); | 7420 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); |
| 7930 | } | 7421 | } |
| 7931 | try block_scope.setBlockBody(block_inst); | 7422 | try block_scope.setBlockBody(block_inst); |
| | 7423 | // block_scope unstacked now, can add new instructions to gz |
| 7932 | try gz.instructions.append(gpa, block_inst); | 7424 | try gz.instructions.append(gpa, block_inst); |
| 7933 | | 7425 | |
| 7934 | return indexToRef(block_inst); | 7426 | return indexToRef(block_inst); |
| ... | @@ -7974,22 +7466,6 @@ fn callExpr( | ... | @@ -7974,22 +7466,6 @@ fn callExpr( |
| 7974 | const astgen = gz.astgen; | 7466 | const astgen = gz.astgen; |
| 7975 | | 7467 | |
| 7976 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); | 7468 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); |
| 7977 | | | |
| 7978 | // A large proportion of calls have 5 or less arguments, due to this preventing allocations | | |
| 7979 | // for calls with few arguments has a sizeable effect on the aggregated runtime of this function | | |
| 7980 | var arg_buffer: [5]Zir.Inst.Ref = undefined; | | |
| 7981 | const args: []Zir.Inst.Ref = if (call.ast.params.len <= arg_buffer.len) | | |
| 7982 | arg_buffer[0..call.ast.params.len] | | |
| 7983 | else | | |
| 7984 | try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len); | | |
| 7985 | defer if (call.ast.params.len > arg_buffer.len) astgen.gpa.free(args); | | |
| 7986 | | | |
| 7987 | for (call.ast.params) |param_node, i| { | | |
| 7988 | // Parameters are always temporary values, they have no | | |
| 7989 | // meaningful result location. Sema will coerce them. | | |
| 7990 | args[i] = try expr(gz, scope, .none, param_node); | | |
| 7991 | } | | |
| 7992 | | | |
| 7993 | const modifier: std.builtin.CallOptions.Modifier = blk: { | 7469 | const modifier: std.builtin.CallOptions.Modifier = blk: { |
| 7994 | if (gz.force_comptime) { | 7470 | if (gz.force_comptime) { |
| 7995 | break :blk .compile_time; | 7471 | break :blk .compile_time; |
| ... | @@ -8002,7 +7478,28 @@ fn callExpr( | ... | @@ -8002,7 +7478,28 @@ fn callExpr( |
| 8002 | } | 7478 | } |
| 8003 | break :blk .auto; | 7479 | break :blk .auto; |
| 8004 | }; | 7480 | }; |
| 8005 | const call_inst = try gz.addCall(modifier, callee, args, node); | 7481 | |
| | 7482 | assert(callee != .none); |
| | 7483 | assert(node != 0); |
| | 7484 | |
| | 7485 | const payload_index = try addExtra(astgen, Zir.Inst.Call{ |
| | 7486 | .callee = callee, |
| | 7487 | .flags = .{ |
| | 7488 | .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)), |
| | 7489 | .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len), |
| | 7490 | }, |
| | 7491 | }); |
| | 7492 | var extra_index = try reserveExtra(astgen, call.ast.params.len); |
| | 7493 | |
| | 7494 | for (call.ast.params) |param_node| { |
| | 7495 | // Parameters are always temporary values, they have no |
| | 7496 | // meaningful result location. Sema will coerce them. |
| | 7497 | const arg_ref = try expr(gz, scope, .none, param_node); |
| | 7498 | astgen.extra.items[extra_index] = @enumToInt(arg_ref); |
| | 7499 | extra_index += 1; |
| | 7500 | } |
| | 7501 | |
| | 7502 | const call_inst = try gz.addPlNodePayloadIndex(.call, node, payload_index); |
| 8006 | return rvalue(gz, rl, call_inst, node); // TODO function call with result location | 7503 | return rvalue(gz, rl, call_inst, node); // TODO function call with result location |
| 8007 | } | 7504 | } |
| 8008 | | 7505 | |
| ... | @@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { | ... | @@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 8747 | /// result locations must call this function on their result. | 8244 | /// result locations must call this function on their result. |
| 8748 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. | 8245 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. |
| 8749 | /// If the `ResultLoc` is `ty`, it will coerce the result to the type. | 8246 | /// If the `ResultLoc` is `ty`, it will coerce the result to the type. |
| | 8247 | /// Assumes nothing stacked on `gz`. |
| 8750 | fn rvalue( | 8248 | fn rvalue( |
| 8751 | gz: *GenZir, | 8249 | gz: *GenZir, |
| 8752 | rl: ResultLoc, | 8250 | rl: ResultLoc, |
| ... | @@ -9326,7 +8824,7 @@ const Scope = struct { | ... | @@ -9326,7 +8824,7 @@ const Scope = struct { |
| 9326 | | 8824 | |
| 9327 | /// Map from the raw captured value to the instruction | 8825 | /// Map from the raw captured value to the instruction |
| 9328 | /// ref of the capture for decls in this namespace | 8826 | /// ref of the capture for decls in this namespace |
| 9329 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | 8827 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 9330 | | 8828 | |
| 9331 | pub fn deinit(self: *Namespace, gpa: *Allocator) void { | 8829 | pub fn deinit(self: *Namespace, gpa: *Allocator) void { |
| 9332 | self.decls.deinit(gpa); | 8830 | self.decls.deinit(gpa); |
| ... | @@ -9359,9 +8857,12 @@ const GenZir = struct { | ... | @@ -9359,9 +8857,12 @@ const GenZir = struct { |
| 9359 | parent: *Scope, | 8857 | parent: *Scope, |
| 9360 | /// All `GenZir` scopes for the same ZIR share this. | 8858 | /// All `GenZir` scopes for the same ZIR share this. |
| 9361 | astgen: *AstGen, | 8859 | astgen: *AstGen, |
| 9362 | /// Keeps track of the list of instructions in this scope only. Indexes | 8860 | /// Keeps track of the list of instructions in this scope. Possibly shared. |
| 9363 | /// to instructions in `astgen`. | 8861 | /// Indexes to instructions in `astgen`. |
| 9364 | instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{}, | 8862 | instructions: *ArrayListUnmanaged(Zir.Inst.Index), |
| | 8863 | /// A sub-block may share its instructions ArrayList with containing GenZir, |
| | 8864 | /// if use is strictly nested. This saves prior size of list for unstacking. |
| | 8865 | instructions_top: usize, |
| 9365 | label: ?Label = null, | 8866 | label: ?Label = null, |
| 9366 | break_block: Zir.Inst.Index = 0, | 8867 | break_block: Zir.Inst.Index = 0, |
| 9367 | continue_block: Zir.Inst.Index = 0, | 8868 | continue_block: Zir.Inst.Index = 0, |
| ... | @@ -9397,6 +8898,36 @@ const GenZir = struct { | ... | @@ -9397,6 +8898,36 @@ const GenZir = struct { |
| 9397 | /// Keys are the raw instruction index, values are the closure_capture instruction. | 8898 | /// Keys are the raw instruction index, values are the closure_capture instruction. |
| 9398 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, | 8899 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 9399 | | 8900 | |
| | 8901 | const unstacked_top = std.math.maxInt(usize); |
| | 8902 | /// Call unstack before adding any new instructions to containing GenZir. |
| | 8903 | fn unstack(self: *GenZir) void { |
| | 8904 | if (self.instructions_top != unstacked_top) { |
| | 8905 | self.instructions.items.len = self.instructions_top; |
| | 8906 | self.instructions_top = unstacked_top; |
| | 8907 | } |
| | 8908 | } |
| | 8909 | |
| | 8910 | fn isEmpty(self: *const GenZir) bool { |
| | 8911 | return (self.instructions_top == unstacked_top) or |
| | 8912 | (self.instructions.items.len == self.instructions_top); |
| | 8913 | } |
| | 8914 | |
| | 8915 | fn instructionsSlice(self: *const GenZir) []Zir.Inst.Index { |
| | 8916 | return if (self.instructions_top == unstacked_top) |
| | 8917 | &[0]Zir.Inst.Index{} |
| | 8918 | else |
| | 8919 | self.instructions.items[self.instructions_top..]; |
| | 8920 | } |
| | 8921 | |
| | 8922 | fn instructionsSliceUpto(self: *const GenZir, stacked_gz: *GenZir) []Zir.Inst.Index { |
| | 8923 | return if (self.instructions_top == unstacked_top) |
| | 8924 | &[0]Zir.Inst.Index{} |
| | 8925 | else if (self.instructions == stacked_gz.instructions and stacked_gz.instructions_top != unstacked_top) |
| | 8926 | self.instructions.items[self.instructions_top..stacked_gz.instructions_top] |
| | 8927 | else |
| | 8928 | self.instructions.items[self.instructions_top..]; |
| | 8929 | } |
| | 8930 | |
| 9400 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { | 8931 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { |
| 9401 | return .{ | 8932 | return .{ |
| 9402 | .force_comptime = gz.force_comptime, | 8933 | .force_comptime = gz.force_comptime, |
| ... | @@ -9408,6 +8939,8 @@ const GenZir = struct { | ... | @@ -9408,6 +8939,8 @@ const GenZir = struct { |
| 9408 | .astgen = gz.astgen, | 8939 | .astgen = gz.astgen, |
| 9409 | .suspend_node = gz.suspend_node, | 8940 | .suspend_node = gz.suspend_node, |
| 9410 | .nosuspend_node = gz.nosuspend_node, | 8941 | .nosuspend_node = gz.nosuspend_node, |
| | 8942 | .instructions = gz.instructions, |
| | 8943 | .instructions_top = gz.instructions.items.len, |
| 9411 | }; | 8944 | }; |
| 9412 | } | 8945 | } |
| 9413 | | 8946 | |
| ... | @@ -9421,12 +8954,13 @@ const GenZir = struct { | ... | @@ -9421,12 +8954,13 @@ const GenZir = struct { |
| 9421 | // result location. If it does, elide the coerce_result_ptr instruction | 8954 | // result location. If it does, elide the coerce_result_ptr instruction |
| 9422 | // as well as the store instruction, instead passing the result as an rvalue. | 8955 | // as well as the store instruction, instead passing the result as an rvalue. |
| 9423 | var as_scope = parent_gz.makeSubBlock(scope); | 8956 | var as_scope = parent_gz.makeSubBlock(scope); |
| 9424 | errdefer as_scope.instructions.deinit(parent_gz.astgen.gpa); | 8957 | errdefer as_scope.unstack(); |
| 9425 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); | 8958 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); |
| 9426 | | 8959 | |
| 9427 | return as_scope; | 8960 | return as_scope; |
| 9428 | } | 8961 | } |
| 9429 | | 8962 | |
| | 8963 | /// Assumes `as_scope` is stacked immediately on top of `parent_gz`. Unstacks `as_scope`. |
| 9430 | fn finishCoercion( | 8964 | fn finishCoercion( |
| 9431 | as_scope: *GenZir, | 8965 | as_scope: *GenZir, |
| 9432 | parent_gz: *GenZir, | 8966 | parent_gz: *GenZir, |
| ... | @@ -9434,25 +8968,32 @@ const GenZir = struct { | ... | @@ -9434,25 +8968,32 @@ const GenZir = struct { |
| 9434 | src_node: Ast.Node.Index, | 8968 | src_node: Ast.Node.Index, |
| 9435 | result: Zir.Inst.Ref, | 8969 | result: Zir.Inst.Ref, |
| 9436 | dest_type: Zir.Inst.Ref, | 8970 | dest_type: Zir.Inst.Ref, |
| 9437 | ) !Zir.Inst.Ref { | 8971 | ) InnerError!Zir.Inst.Ref { |
| | 8972 | assert(as_scope.instructions == parent_gz.instructions); |
| 9438 | const astgen = as_scope.astgen; | 8973 | const astgen = as_scope.astgen; |
| 9439 | const parent_zir = &parent_gz.instructions; | | |
| 9440 | if (as_scope.rvalue_rl_count == 1) { | 8974 | if (as_scope.rvalue_rl_count == 1) { |
| 9441 | // Busted! This expression didn't actually need a pointer. | 8975 | // Busted! This expression didn't actually need a pointer. |
| 9442 | const zir_tags = astgen.instructions.items(.tag); | 8976 | const zir_tags = astgen.instructions.items(.tag); |
| 9443 | const zir_datas = astgen.instructions.items(.data); | 8977 | const zir_datas = astgen.instructions.items(.data); |
| 9444 | try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len); | 8978 | var src: usize = as_scope.instructions_top; |
| 9445 | for (as_scope.instructions.items) |src_inst| { | 8979 | var dst: usize = src; |
| | 8980 | while (src < as_scope.instructions.items.len) : (src += 1) { |
| | 8981 | const src_inst = as_scope.instructions.items[src]; |
| 9446 | if (indexToRef(src_inst) == as_scope.rl_ptr) continue; | 8982 | if (indexToRef(src_inst) == as_scope.rl_ptr) continue; |
| 9447 | if (zir_tags[src_inst] == .store_to_block_ptr) { | 8983 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 9448 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; | 8984 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; |
| 9449 | } | 8985 | } |
| 9450 | parent_zir.appendAssumeCapacity(src_inst); | 8986 | as_scope.instructions.items[dst] = src_inst; |
| | 8987 | dst += 1; |
| 9451 | } | 8988 | } |
| | 8989 | parent_gz.instructions.items.len -= src - dst; |
| | 8990 | as_scope.instructions_top = GenZir.unstacked_top; |
| | 8991 | // as_scope now unstacked, can add new instructions to parent_gz |
| 9452 | const casted_result = try parent_gz.addBin(.as, dest_type, result); | 8992 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 9453 | return rvalue(parent_gz, rl, casted_result, src_node); | 8993 | return rvalue(parent_gz, rl, casted_result, src_node); |
| 9454 | } else { | 8994 | } else { |
| 9455 | try parent_zir.appendSlice(astgen.gpa, as_scope.instructions.items); | 8995 | // implicitly move all as_scope instructions to parent_gz |
| | 8996 | as_scope.instructions_top = GenZir.unstacked_top; |
| 9456 | return result; | 8997 | return result; |
| 9457 | } | 8998 | } |
| 9458 | } | 8999 | } |
| ... | @@ -9463,9 +9004,10 @@ const GenZir = struct { | ... | @@ -9463,9 +9004,10 @@ const GenZir = struct { |
| 9463 | used: bool = false, | 9004 | used: bool = false, |
| 9464 | }; | 9005 | }; |
| 9465 | | 9006 | |
| | 9007 | /// Assumes nothing stacked on `gz`. |
| 9466 | fn endsWithNoReturn(gz: GenZir) bool { | 9008 | fn endsWithNoReturn(gz: GenZir) bool { |
| | 9009 | if (gz.isEmpty()) return false; |
| 9467 | const tags = gz.astgen.instructions.items(.tag); | 9010 | const tags = gz.astgen.instructions.items(.tag); |
| 9468 | if (gz.instructions.items.len == 0) return false; | | |
| 9469 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; | 9011 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; |
| 9470 | return tags[last_inst].isNoReturn(); | 9012 | return tags[last_inst].isNoReturn(); |
| 9471 | } | 9013 | } |
| ... | @@ -9535,41 +9077,46 @@ const GenZir = struct { | ... | @@ -9535,41 +9077,46 @@ const GenZir = struct { |
| 9535 | } | 9077 | } |
| 9536 | } | 9078 | } |
| 9537 | | 9079 | |
| 9538 | fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void { | 9080 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9081 | fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9539 | const gpa = gz.astgen.gpa; | 9082 | const gpa = gz.astgen.gpa; |
| 9540 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9083 | const body = gz.instructionsSlice(); |
| 9541 | gz.instructions.items.len); | 9084 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9542 | const zir_datas = gz.astgen.instructions.items(.data); | 9085 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9543 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( | 9086 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9544 | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, | 9087 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 9545 | ); | 9088 | ); |
| 9546 | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); | 9089 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| | 9090 | gz.unstack(); |
| 9547 | } | 9091 | } |
| 9548 | | 9092 | |
| 9549 | fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void { | 9093 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9094 | fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9550 | const gpa = gz.astgen.gpa; | 9095 | const gpa = gz.astgen.gpa; |
| 9551 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9096 | const body = gz.instructionsSlice(); |
| 9552 | gz.instructions.items.len); | 9097 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9553 | const zir_datas = gz.astgen.instructions.items(.data); | 9098 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9554 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( | 9099 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9555 | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, | 9100 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 9556 | ); | 9101 | ); |
| 9557 | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); | 9102 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| | 9103 | gz.unstack(); |
| 9558 | } | 9104 | } |
| 9559 | | 9105 | |
| 9560 | /// Same as `setBlockBody` except we don't copy instructions which are | 9106 | /// Same as `setBlockBody` except we don't copy instructions which are |
| 9561 | /// `store_to_block_ptr` instructions with lhs set to .none. | 9107 | /// `store_to_block_ptr` instructions with lhs set to .none. |
| 9562 | fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void { | 9108 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| | 9109 | fn setBlockBodyEliding(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9563 | const gpa = gz.astgen.gpa; | 9110 | const gpa = gz.astgen.gpa; |
| 9564 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + | 9111 | const body = gz.instructionsSlice(); |
| 9565 | gz.instructions.items.len); | 9112 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9566 | const zir_datas = gz.astgen.instructions.items(.data); | 9113 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9567 | const zir_tags = gz.astgen.instructions.items(.tag); | 9114 | const zir_tags = gz.astgen.instructions.items(.tag); |
| 9568 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ | 9115 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ |
| 9569 | .body_len = @intCast(u32, gz.instructions.items.len), | 9116 | .body_len = @intCast(u32, body.len), |
| 9570 | }); | 9117 | }); |
| 9571 | zir_datas[inst].pl_node.payload_index = block_pl_index; | 9118 | zir_datas[inst].pl_node.payload_index = block_pl_index; |
| 9572 | for (gz.instructions.items) |sub_inst| { | 9119 | for (body) |sub_inst| { |
| 9573 | if (zir_tags[sub_inst] == .store_to_block_ptr and | 9120 | if (zir_tags[sub_inst] == .store_to_block_ptr and |
| 9574 | zir_datas[sub_inst].bin.lhs == .none) | 9121 | zir_datas[sub_inst].bin.lhs == .none) |
| 9575 | { | 9122 | { |
| ... | @@ -9579,15 +9126,17 @@ const GenZir = struct { | ... | @@ -9579,15 +9126,17 @@ const GenZir = struct { |
| 9579 | } | 9126 | } |
| 9580 | gz.astgen.extra.appendAssumeCapacity(sub_inst); | 9127 | gz.astgen.extra.appendAssumeCapacity(sub_inst); |
| 9581 | } | 9128 | } |
| | 9129 | gz.unstack(); |
| 9582 | } | 9130 | } |
| 9583 | | 9131 | |
| | 9132 | /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`. |
| 9584 | fn addFunc(gz: *GenZir, args: struct { | 9133 | fn addFunc(gz: *GenZir, args: struct { |
| 9585 | src_node: Ast.Node.Index, | 9134 | src_node: Ast.Node.Index, |
| 9586 | lbrace_line: u32 = 0, | 9135 | lbrace_line: u32 = 0, |
| 9587 | lbrace_column: u32 = 0, | 9136 | lbrace_column: u32 = 0, |
| 9588 | body: []const Zir.Inst.Index, | 9137 | body_gz: ?*GenZir, |
| 9589 | param_block: Zir.Inst.Index, | 9138 | param_block: Zir.Inst.Index, |
| 9590 | ret_ty: []const Zir.Inst.Index, | 9139 | ret_gz: ?*GenZir, |
| 9591 | ret_br: Zir.Inst.Index, | 9140 | ret_br: Zir.Inst.Index, |
| 9592 | cc: Zir.Inst.Ref, | 9141 | cc: Zir.Inst.Ref, |
| 9593 | align_inst: Zir.Inst.Ref, | 9142 | align_inst: Zir.Inst.Ref, |
| ... | @@ -9601,12 +9150,13 @@ const GenZir = struct { | ... | @@ -9601,12 +9150,13 @@ const GenZir = struct { |
| 9601 | const astgen = gz.astgen; | 9150 | const astgen = gz.astgen; |
| 9602 | const gpa = astgen.gpa; | 9151 | const gpa = astgen.gpa; |
| 9603 | | 9152 | |
| 9604 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | | |
| 9605 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); | 9153 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9606 | | 9154 | |
| | 9155 | var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| | 9156 | var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 9607 | var src_locs_buffer: [3]u32 = undefined; | 9157 | var src_locs_buffer: [3]u32 = undefined; |
| 9608 | var src_locs: []u32 = src_locs_buffer[0..0]; | 9158 | var src_locs: []u32 = src_locs_buffer[0..0]; |
| 9609 | if (args.body.len != 0) { | 9159 | if (args.body_gz) |body_gz| { |
| 9610 | const tree = astgen.tree; | 9160 | const tree = astgen.tree; |
| 9611 | const node_tags = tree.nodes.items(.tag); | 9161 | const node_tags = tree.nodes.items(.tag); |
| 9612 | const node_datas = tree.nodes.items(.data); | 9162 | const node_datas = tree.nodes.items(.data); |
| ... | @@ -9624,6 +9174,13 @@ const GenZir = struct { | ... | @@ -9624,6 +9174,13 @@ const GenZir = struct { |
| 9624 | src_locs_buffer[1] = rbrace_line; | 9174 | src_locs_buffer[1] = rbrace_line; |
| 9625 | src_locs_buffer[2] = columns; | 9175 | src_locs_buffer[2] = columns; |
| 9626 | src_locs = &src_locs_buffer; | 9176 | src_locs = &src_locs_buffer; |
| | 9177 | |
| | 9178 | body = body_gz.instructionsSlice(); |
| | 9179 | if (args.ret_gz) |ret_gz| |
| | 9180 | ret_ty = ret_gz.instructionsSliceUpto(body_gz); |
| | 9181 | } else { |
| | 9182 | if (args.ret_gz) |ret_gz| |
| | 9183 | ret_ty = ret_gz.instructionsSlice(); |
| 9627 | } | 9184 | } |
| 9628 | | 9185 | |
| 9629 | if (args.cc != .none or args.lib_name != 0 or | 9186 | if (args.cc != .none or args.lib_name != 0 or |
| ... | @@ -9633,7 +9190,7 @@ const GenZir = struct { | ... | @@ -9633,7 +9190,7 @@ const GenZir = struct { |
| 9633 | try astgen.extra.ensureUnusedCapacity( | 9190 | try astgen.extra.ensureUnusedCapacity( |
| 9634 | gpa, | 9191 | gpa, |
| 9635 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + | 9192 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + |
| 9636 | args.ret_ty.len + args.body.len + src_locs.len + | 9193 | ret_ty.len + body.len + src_locs.len + |
| 9637 | @boolToInt(args.lib_name != 0) + | 9194 | @boolToInt(args.lib_name != 0) + |
| 9638 | @boolToInt(args.align_inst != .none) + | 9195 | @boolToInt(args.align_inst != .none) + |
| 9639 | @boolToInt(args.cc != .none), | 9196 | @boolToInt(args.cc != .none), |
| ... | @@ -9641,8 +9198,8 @@ const GenZir = struct { | ... | @@ -9641,8 +9198,8 @@ const GenZir = struct { |
| 9641 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ | 9198 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ |
| 9642 | .src_node = gz.nodeIndexToRelative(args.src_node), | 9199 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 9643 | .param_block = args.param_block, | 9200 | .param_block = args.param_block, |
| 9644 | .ret_body_len = @intCast(u32, args.ret_ty.len), | 9201 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9645 | .body_len = @intCast(u32, args.body.len), | 9202 | .body_len = @intCast(u32, body.len), |
| 9646 | }); | 9203 | }); |
| 9647 | if (args.lib_name != 0) { | 9204 | if (args.lib_name != 0) { |
| 9648 | astgen.extra.appendAssumeCapacity(args.lib_name); | 9205 | astgen.extra.appendAssumeCapacity(args.lib_name); |
| ... | @@ -9653,9 +9210,13 @@ const GenZir = struct { | ... | @@ -9653,9 +9210,13 @@ const GenZir = struct { |
| 9653 | if (args.align_inst != .none) { | 9210 | if (args.align_inst != .none) { |
| 9654 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); | 9211 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); |
| 9655 | } | 9212 | } |
| 9656 | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); | 9213 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9657 | astgen.extra.appendSliceAssumeCapacity(args.body); | 9214 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9658 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 9215 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| | 9216 | // order is important when unstacking |
| | 9217 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| | 9218 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| | 9219 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9659 | | 9220 | |
| 9660 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | 9221 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 9661 | if (args.ret_br != 0) { | 9222 | if (args.ret_br != 0) { |
| ... | @@ -9683,17 +9244,21 @@ const GenZir = struct { | ... | @@ -9683,17 +9244,21 @@ const GenZir = struct { |
| 9683 | try astgen.extra.ensureUnusedCapacity( | 9244 | try astgen.extra.ensureUnusedCapacity( |
| 9684 | gpa, | 9245 | gpa, |
| 9685 | @typeInfo(Zir.Inst.Func).Struct.fields.len + | 9246 | @typeInfo(Zir.Inst.Func).Struct.fields.len + |
| 9686 | args.ret_ty.len + args.body.len + src_locs.len, | 9247 | ret_ty.len + body.len + src_locs.len, |
| 9687 | ); | 9248 | ); |
| 9688 | | 9249 | |
| 9689 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | 9250 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 9690 | .param_block = args.param_block, | 9251 | .param_block = args.param_block, |
| 9691 | .ret_body_len = @intCast(u32, args.ret_ty.len), | 9252 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9692 | .body_len = @intCast(u32, args.body.len), | 9253 | .body_len = @intCast(u32, body.len), |
| 9693 | }); | 9254 | }); |
| 9694 | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); | 9255 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9695 | astgen.extra.appendSliceAssumeCapacity(args.body); | 9256 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9696 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 9257 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| | 9258 | // order is important when unstacking |
| | 9259 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| | 9260 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| | 9261 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9697 | | 9262 | |
| 9698 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; | 9263 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; |
| 9699 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | 9264 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| ... | @@ -9765,44 +9330,6 @@ const GenZir = struct { | ... | @@ -9765,44 +9330,6 @@ const GenZir = struct { |
| 9765 | return indexToRef(new_index); | 9330 | return indexToRef(new_index); |
| 9766 | } | 9331 | } |
| 9767 | | 9332 | |
| 9768 | fn addCall( | | |
| 9769 | gz: *GenZir, | | |
| 9770 | modifier: std.builtin.CallOptions.Modifier, | | |
| 9771 | callee: Zir.Inst.Ref, | | |
| 9772 | args: []const Zir.Inst.Ref, | | |
| 9773 | /// Absolute node index. This function does the conversion to offset from Decl. | | |
| 9774 | src_node: Ast.Node.Index, | | |
| 9775 | ) !Zir.Inst.Ref { | | |
| 9776 | assert(callee != .none); | | |
| 9777 | assert(src_node != 0); | | |
| 9778 | const gpa = gz.astgen.gpa; | | |
| 9779 | const Call = Zir.Inst.Call; | | |
| 9780 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | | |
| 9781 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); | | |
| 9782 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Call).Struct.fields.len + | | |
| 9783 | args.len); | | |
| 9784 | | | |
| 9785 | const payload_index = gz.astgen.addExtraAssumeCapacity(Call{ | | |
| 9786 | .callee = callee, | | |
| 9787 | .flags = .{ | | |
| 9788 | .packed_modifier = @intCast(Call.Flags.PackedModifier, @enumToInt(modifier)), | | |
| 9789 | .args_len = @intCast(Call.Flags.PackedArgsLen, args.len), | | |
| 9790 | }, | | |
| 9791 | }); | | |
| 9792 | gz.astgen.appendRefsAssumeCapacity(args); | | |
| 9793 | | | |
| 9794 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | | |
| 9795 | gz.astgen.instructions.appendAssumeCapacity(.{ | | |
| 9796 | .tag = .call, | | |
| 9797 | .data = .{ .pl_node = .{ | | |
| 9798 | .src_node = gz.nodeIndexToRelative(src_node), | | |
| 9799 | .payload_index = payload_index, | | |
| 9800 | } }, | | |
| 9801 | }); | | |
| 9802 | gz.instructions.appendAssumeCapacity(new_index); | | |
| 9803 | return indexToRef(new_index); | | |
| 9804 | } | | |
| 9805 | | | |
| 9806 | /// Note that this returns a `Zir.Inst.Index` not a ref. | 9333 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 9807 | /// Leaves the `payload_index` field undefined. | 9334 | /// Leaves the `payload_index` field undefined. |
| 9808 | fn addBoolBr( | 9335 | fn addBoolBr( |
| ... | @@ -9878,6 +9405,25 @@ const GenZir = struct { | ... | @@ -9878,6 +9405,25 @@ const GenZir = struct { |
| 9878 | }); | 9405 | }); |
| 9879 | } | 9406 | } |
| 9880 | | 9407 | |
| | 9408 | fn makeUnNode( |
| | 9409 | gz: *GenZir, |
| | 9410 | tag: Zir.Inst.Tag, |
| | 9411 | operand: Zir.Inst.Ref, |
| | 9412 | /// Absolute node index. This function does the conversion to offset from Decl. |
| | 9413 | src_node: Ast.Node.Index, |
| | 9414 | ) !Zir.Inst.Index { |
| | 9415 | assert(operand != .none); |
| | 9416 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| | 9417 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| | 9418 | .tag = tag, |
| | 9419 | .data = .{ .un_node = .{ |
| | 9420 | .operand = operand, |
| | 9421 | .src_node = gz.nodeIndexToRelative(src_node), |
| | 9422 | } }, |
| | 9423 | }); |
| | 9424 | return new_index; |
| | 9425 | } |
| | 9426 | |
| 9881 | fn addPlNode( | 9427 | fn addPlNode( |
| 9882 | gz: *GenZir, | 9428 | gz: *GenZir, |
| 9883 | tag: Zir.Inst.Tag, | 9429 | tag: Zir.Inst.Tag, |
| ... | @@ -9902,25 +9448,43 @@ const GenZir = struct { | ... | @@ -9902,25 +9448,43 @@ const GenZir = struct { |
| 9902 | return indexToRef(new_index); | 9448 | return indexToRef(new_index); |
| 9903 | } | 9449 | } |
| 9904 | | 9450 | |
| | 9451 | fn addPlNodePayloadIndex( |
| | 9452 | gz: *GenZir, |
| | 9453 | tag: Zir.Inst.Tag, |
| | 9454 | /// Absolute node index. This function does the conversion to offset from Decl. |
| | 9455 | src_node: Ast.Node.Index, |
| | 9456 | payload_index: u32, |
| | 9457 | ) !Zir.Inst.Ref { |
| | 9458 | return try gz.add(.{ |
| | 9459 | .tag = tag, |
| | 9460 | .data = .{ .pl_node = .{ |
| | 9461 | .src_node = gz.nodeIndexToRelative(src_node), |
| | 9462 | .payload_index = payload_index, |
| | 9463 | } }, |
| | 9464 | }); |
| | 9465 | } |
| | 9466 | |
| | 9467 | /// Supports `param_gz` stacked on `gz`. Assumes nothing stacked on `param_gz`. Unstacks `param_gz`. |
| 9905 | fn addParam( | 9468 | fn addParam( |
| 9906 | gz: *GenZir, | 9469 | gz: *GenZir, |
| | 9470 | param_gz: *GenZir, |
| 9907 | tag: Zir.Inst.Tag, | 9471 | tag: Zir.Inst.Tag, |
| 9908 | /// Absolute token index. This function does the conversion to Decl offset. | 9472 | /// Absolute token index. This function does the conversion to Decl offset. |
| 9909 | abs_tok_index: Ast.TokenIndex, | 9473 | abs_tok_index: Ast.TokenIndex, |
| 9910 | name: u32, | 9474 | name: u32, |
| 9911 | body: []const u32, | | |
| 9912 | ) !Zir.Inst.Index { | 9475 | ) !Zir.Inst.Index { |
| 9913 | const gpa = gz.astgen.gpa; | 9476 | const gpa = gz.astgen.gpa; |
| 9914 | try gz.instructions.ensureUnusedCapacity(gpa, 1); | 9477 | const param_body = param_gz.instructionsSlice(); |
| 9915 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); | 9478 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9916 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len + | 9479 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len + |
| 9917 | body.len); | 9480 | param_body.len); |
| 9918 | | 9481 | |
| 9919 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{ | 9482 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{ |
| 9920 | .name = name, | 9483 | .name = name, |
| 9921 | .body_len = @intCast(u32, body.len), | 9484 | .body_len = @intCast(u32, param_body.len), |
| 9922 | }); | 9485 | }); |
| 9923 | gz.astgen.extra.appendSliceAssumeCapacity(body); | 9486 | gz.astgen.extra.appendSliceAssumeCapacity(param_body); |
| | 9487 | param_gz.unstack(); |
| 9924 | | 9488 | |
| 9925 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | 9489 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9926 | gz.astgen.instructions.appendAssumeCapacity(.{ | 9490 | gz.astgen.instructions.appendAssumeCapacity(.{ |
| ... | @@ -9991,6 +9555,30 @@ const GenZir = struct { | ... | @@ -9991,6 +9555,30 @@ const GenZir = struct { |
| 9991 | return indexToRef(new_index); | 9555 | return indexToRef(new_index); |
| 9992 | } | 9556 | } |
| 9993 | | 9557 | |
| | 9558 | fn addExtendedMultiOpPayloadIndex( |
| | 9559 | gz: *GenZir, |
| | 9560 | opcode: Zir.Inst.Extended, |
| | 9561 | payload_index: u32, |
| | 9562 | trailing_len: usize, |
| | 9563 | ) !Zir.Inst.Ref { |
| | 9564 | const astgen = gz.astgen; |
| | 9565 | const gpa = astgen.gpa; |
| | 9566 | |
| | 9567 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| | 9568 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| | 9569 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| | 9570 | astgen.instructions.appendAssumeCapacity(.{ |
| | 9571 | .tag = .extended, |
| | 9572 | .data = .{ .extended = .{ |
| | 9573 | .opcode = opcode, |
| | 9574 | .small = @intCast(u16, trailing_len), |
| | 9575 | .operand = payload_index, |
| | 9576 | } }, |
| | 9577 | }); |
| | 9578 | gz.instructions.appendAssumeCapacity(new_index); |
| | 9579 | return indexToRef(new_index); |
| | 9580 | } |
| | 9581 | |
| 9994 | fn addUnTok( | 9582 | fn addUnTok( |
| 9995 | gz: *GenZir, | 9583 | gz: *GenZir, |
| 9996 | tag: Zir.Inst.Tag, | 9584 | tag: Zir.Inst.Tag, |
| ... | @@ -10039,6 +9627,23 @@ const GenZir = struct { | ... | @@ -10039,6 +9627,23 @@ const GenZir = struct { |
| 10039 | }); | 9627 | }); |
| 10040 | } | 9628 | } |
| 10041 | | 9629 | |
| | 9630 | fn makeBreak( |
| | 9631 | gz: *GenZir, |
| | 9632 | tag: Zir.Inst.Tag, |
| | 9633 | break_block: Zir.Inst.Index, |
| | 9634 | operand: Zir.Inst.Ref, |
| | 9635 | ) !Zir.Inst.Index { |
| | 9636 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| | 9637 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| | 9638 | .tag = tag, |
| | 9639 | .data = .{ .@"break" = .{ |
| | 9640 | .block_inst = break_block, |
| | 9641 | .operand = operand, |
| | 9642 | } }, |
| | 9643 | }); |
| | 9644 | return new_index; |
| | 9645 | } |
| | 9646 | |
| 10042 | fn addBin( | 9647 | fn addBin( |
| 10043 | gz: *GenZir, | 9648 | gz: *GenZir, |
| 10044 | tag: Zir.Inst.Tag, | 9649 | tag: Zir.Inst.Tag, |
| ... | @@ -10227,7 +9832,7 @@ const GenZir = struct { | ... | @@ -10227,7 +9832,7 @@ const GenZir = struct { |
| 10227 | /// Note that this returns a `Zir.Inst.Index` not a ref. | 9832 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 10228 | /// Does *not* append the block instruction to the scope. | 9833 | /// Does *not* append the block instruction to the scope. |
| 10229 | /// Leaves the `payload_index` field undefined. | 9834 | /// Leaves the `payload_index` field undefined. |
| 10230 | fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { | 9835 | fn makeBlockInst(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { |
| 10231 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); | 9836 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 10232 | const gpa = gz.astgen.gpa; | 9837 | const gpa = gz.astgen.gpa; |
| 10233 | try gz.astgen.instructions.append(gpa, .{ | 9838 | try gz.astgen.instructions.append(gpa, .{ |
| ... | @@ -10464,6 +10069,15 @@ const GenZir = struct { | ... | @@ -10464,6 +10069,15 @@ const GenZir = struct { |
| 10464 | else => unreachable, | 10069 | else => unreachable, |
| 10465 | } | 10070 | } |
| 10466 | } | 10071 | } |
| | 10072 | |
| | 10073 | fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void { |
| | 10074 | if (namespace.captures.count() > 0) { |
| | 10075 | try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count()); |
| | 10076 | for (namespace.captures.values()) |capture| { |
| | 10077 | gz.instructions.appendAssumeCapacity(capture); |
| | 10078 | } |
| | 10079 | } |
| | 10080 | } |
| 10467 | }; | 10081 | }; |
| 10468 | | 10082 | |
| 10469 | /// This can only be for short-lived references; the memory becomes invalidated | 10083 | /// This can only be for short-lived references; the memory becomes invalidated |
| ... | @@ -10581,12 +10195,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { | ... | @@ -10581,12 +10195,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 10581 | astgen.source_column = column; | 10195 | astgen.source_column = column; |
| 10582 | } | 10196 | } |
| 10583 | | 10197 | |
| 10584 | fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !void { | 10198 | fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !u32 { |
| 10585 | const gpa = astgen.gpa; | 10199 | const gpa = astgen.gpa; |
| 10586 | const tree = astgen.tree; | 10200 | const tree = astgen.tree; |
| 10587 | const node_tags = tree.nodes.items(.tag); | 10201 | const node_tags = tree.nodes.items(.tag); |
| 10588 | const main_tokens = tree.nodes.items(.main_token); | 10202 | const main_tokens = tree.nodes.items(.main_token); |
| 10589 | const token_tags = tree.tokens.items(.tag); | 10203 | const token_tags = tree.tokens.items(.tag); |
| | 10204 | var decl_count: u32 = 0; |
| 10590 | for (members) |member_node| { | 10205 | for (members) |member_node| { |
| 10591 | const name_token = switch (node_tags[member_node]) { | 10206 | const name_token = switch (node_tags[member_node]) { |
| 10592 | .fn_proto_simple, | 10207 | .fn_proto_simple, |
| ... | @@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10597 | .local_var_decl, | 10212 | .local_var_decl, |
| 10598 | .simple_var_decl, | 10213 | .simple_var_decl, |
| 10599 | .aligned_var_decl, | 10214 | .aligned_var_decl, |
| 10600 | => main_tokens[member_node] + 1, | 10215 | => blk: { |
| | 10216 | decl_count += 1; |
| | 10217 | break :blk main_tokens[member_node] + 1; |
| | 10218 | }, |
| 10601 | | 10219 | |
| 10602 | .fn_decl => blk: { | 10220 | .fn_decl => blk: { |
| | 10221 | decl_count += 1; |
| 10603 | const ident = main_tokens[member_node] + 1; | 10222 | const ident = main_tokens[member_node] + 1; |
| 10604 | if (token_tags[ident] != .identifier) { | 10223 | if (token_tags[ident] != .identifier) { |
| 10605 | switch (astgen.failNode(member_node, "missing function name", .{})) { | 10224 | switch (astgen.failNode(member_node, "missing function name", .{})) { |
| ... | @@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10610 | break :blk ident; | 10229 | break :blk ident; |
| 10611 | }, | 10230 | }, |
| 10612 | | 10231 | |
| | 10232 | .@"comptime", .@"usingnamespace", .test_decl => { |
| | 10233 | decl_count += 1; |
| | 10234 | continue; |
| | 10235 | }, |
| | 10236 | |
| 10613 | else => continue, | 10237 | else => continue, |
| 10614 | }; | 10238 | }; |
| 10615 | | 10239 | |
| ... | @@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. | ... | @@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10643 | } | 10267 | } |
| 10644 | gop.value_ptr.* = member_node; | 10268 | gop.value_ptr.* = member_node; |
| 10645 | } | 10269 | } |
| | 10270 | return decl_count; |
| 10646 | } | 10271 | } |