authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-16 02:19:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-16 02:19:01-04:00
logac6d1674e3384bacd6893191feaf814a23d24b08
tree644fc69b51f3800aa3f1a693bf04ef1f8fdb9afd
parentce3c52471dd8a86e429ea037f4344b243723eb74

IR working for if statements


7 files changed, 1017 insertions(+), 487 deletions(-)

src/all_types.hpp+26
...@@ -1411,6 +1411,8 @@ struct IrBasicBlock {...@@ -1411,6 +1411,8 @@ struct IrBasicBlock {
1411 IrBasicBlock *other;1411 IrBasicBlock *other;
1412 const char *name_hint;1412 const char *name_hint;
1413 size_t debug_id;1413 size_t debug_id;
1414 size_t ref_count;
1415 LLVMBasicBlockRef llvm_block;
1414};1416};
14151417
1416enum IrInstructionId {1418enum IrInstructionId {
...@@ -1428,6 +1430,9 @@ enum IrInstructionId {...@@ -1428,6 +1430,9 @@ enum IrInstructionId {
1428 IrInstructionIdConst,1430 IrInstructionIdConst,
1429 IrInstructionIdReturn,1431 IrInstructionIdReturn,
1430 IrInstructionIdCast,1432 IrInstructionIdCast,
1433 IrInstructionIdContainerInitList,
1434 IrInstructionIdContainerInitFields,
1435 IrInstructionIdUnreachable,
1431};1436};
14321437
1433struct IrInstruction {1438struct IrInstruction {
...@@ -1586,4 +1591,25 @@ struct IrInstructionCast {...@@ -1586,4 +1591,25 @@ struct IrInstructionCast {
1586 LLVMValueRef tmp_ptr;1591 LLVMValueRef tmp_ptr;
1587};1592};
15881593
1594struct IrInstructionContainerInitList {
1595 IrInstruction base;
1596
1597 IrInstruction *container_type;
1598 size_t item_count;
1599 IrInstruction **items;
1600};
1601
1602struct IrInstructionContainerInitFields {
1603 IrInstruction base;
1604
1605 IrInstruction *container_type;
1606 size_t field_count;
1607 Buf **field_names;
1608 IrInstruction **field_values;
1609};
1610
1611struct IrInstructionUnreachable {
1612 IrInstruction base;
1613};
1614
1589#endif1615#endif
src/analyze.cpp+1-189
...@@ -29,7 +29,6 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *...@@ -29,7 +29,6 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
29 BlockContext *context, AstNode *node, Buf *err_name);29 BlockContext *context, AstNode *node, Buf *err_name);
30static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,30static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
31 TypeTableEntry *expected_type, AstNode *node);31 TypeTableEntry *expected_type, AstNode *node);
32static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
33static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,32static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
34 bool depends_on_compile_var);33 bool depends_on_compile_var);
35static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,34static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
...@@ -2386,187 +2385,6 @@ static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *...@@ -2386,187 +2385,6 @@ static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *
2386 return nullptr;2385 return nullptr;
2387}2386}
23882387
2389static const char *err_container_init_syntax_name(ContainerInitKind kind) {
2390 switch (kind) {
2391 case ContainerInitKindStruct:
2392 return "struct";
2393 case ContainerInitKindArray:
2394 return "array";
2395 }
2396 zig_unreachable();
2397}
2398
2399static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
2400 BlockContext *context, AstNode *node)
2401{
2402 assert(node->type == NodeTypeContainerInitExpr);
2403
2404 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
2405
2406 ContainerInitKind kind = container_init_expr->kind;
2407
2408 if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
2409 container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
2410 }
2411
2412 TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
2413 container_init_expr->type);
2414
2415 if (container_meta_type->id == TypeTableEntryIdInvalid) {
2416 return g->builtin_types.entry_invalid;
2417 }
2418
2419 if (node->data.container_init_expr.enum_type) {
2420 get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
2421 return node->data.container_init_expr.enum_type;
2422 }
2423
2424 TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
2425
2426 if (container_type->id == TypeTableEntryIdInvalid) {
2427 return container_type;
2428 } else if (container_type->id == TypeTableEntryIdStruct &&
2429 !container_type->data.structure.is_slice &&
2430 (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
2431 container_init_expr->entries.length == 0)))
2432 {
2433 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2434 codegen->type_entry = container_type;
2435 codegen->source_node = node;
2436
2437
2438 size_t expr_field_count = container_init_expr->entries.length;
2439 size_t actual_field_count = container_type->data.structure.src_field_count;
2440
2441 AstNode *non_const_expr_culprit = nullptr;
2442
2443 size_t *field_use_counts = allocate<size_t>(actual_field_count);
2444 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2445 const_val->ok = true;
2446 const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
2447 for (size_t i = 0; i < expr_field_count; i += 1) {
2448 AstNode *val_field_node = container_init_expr->entries.at(i);
2449 assert(val_field_node->type == NodeTypeStructValueField);
2450
2451 val_field_node->block_context = context;
2452
2453 TypeStructField *type_field = find_struct_type_field(container_type,
2454 val_field_node->data.struct_val_field.name);
2455
2456 if (!type_field) {
2457 add_node_error(g, val_field_node,
2458 buf_sprintf("no member named '%s' in '%s'",
2459 buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
2460 continue;
2461 }
2462
2463 if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
2464 return g->builtin_types.entry_invalid;
2465 }
2466
2467 size_t field_index = type_field->src_index;
2468 field_use_counts[field_index] += 1;
2469 if (field_use_counts[field_index] > 1) {
2470 add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
2471 continue;
2472 }
2473
2474 val_field_node->data.struct_val_field.type_struct_field = type_field;
2475
2476 analyze_expression(g, import, context, type_field->type_entry,
2477 val_field_node->data.struct_val_field.expr);
2478
2479 if (const_val->ok) {
2480 ConstExprValue *field_val =
2481 &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
2482 if (field_val->ok) {
2483 const_val->data.x_struct.fields[field_index] = field_val;
2484 const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
2485 } else {
2486 const_val->ok = false;
2487 non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
2488 }
2489 }
2490 }
2491 if (!const_val->ok) {
2492 assert(non_const_expr_culprit);
2493 if (context->fn_entry) {
2494 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2495 } else {
2496 add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
2497 }
2498 }
2499
2500 for (size_t i = 0; i < actual_field_count; i += 1) {
2501 if (field_use_counts[i] == 0) {
2502 add_node_error(g, node,
2503 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
2504 }
2505 }
2506 return container_type;
2507 } else if (container_type->id == TypeTableEntryIdStruct &&
2508 container_type->data.structure.is_slice &&
2509 kind == ContainerInitKindArray)
2510 {
2511 size_t elem_count = container_init_expr->entries.length;
2512
2513 TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
2514 assert(pointer_type->id == TypeTableEntryIdPointer);
2515 TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
2516
2517 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2518 const_val->ok = true;
2519 const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
2520
2521 for (size_t i = 0; i < elem_count; i += 1) {
2522 AstNode **elem_node = &container_init_expr->entries.at(i);
2523 analyze_expression(g, import, context, child_type, *elem_node);
2524
2525 if (const_val->ok) {
2526 ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
2527 if (elem_const_val->ok) {
2528 const_val->data.x_array.fields[i] = elem_const_val;
2529 const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
2530 elem_const_val->depends_on_compile_var;
2531 } else {
2532 const_val->ok = false;
2533 }
2534 }
2535 }
2536
2537 TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
2538
2539 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2540 codegen->type_entry = fixed_size_array_type;
2541 codegen->source_node = node;
2542 if (!const_val->ok) {
2543 if (!context->fn_entry) {
2544 add_node_error(g, node,
2545 buf_sprintf("unable to evaluate constant expression"));
2546 } else {
2547 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2548 }
2549 }
2550
2551 return fixed_size_array_type;
2552 } else if (container_type->id == TypeTableEntryIdArray) {
2553 zig_panic("TODO array container init");
2554 return container_type;
2555 } else if (container_type->id == TypeTableEntryIdVoid) {
2556 if (container_init_expr->entries.length != 0) {
2557 add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
2558 return g->builtin_types.entry_invalid;
2559 } else {
2560 return resolve_expr_const_val_as_void(g, node);
2561 }
2562 } else {
2563 add_node_error(g, node,
2564 buf_sprintf("type '%s' does not support %s initialization syntax",
2565 buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
2566 return g->builtin_types.entry_invalid;
2567 }
2568}
2569
2570static bool is_container(TypeTableEntry *type_entry) {2388static bool is_container(TypeTableEntry *type_entry) {
2571 switch (type_entry->id) {2389 switch (type_entry->id) {
2572 case TypeTableEntryIdInvalid:2390 case TypeTableEntryIdInvalid:
...@@ -2928,12 +2746,6 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2928,12 +2746,6 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
2928 return return_type;2746 return return_type;
2929}2747}
29302748
2931static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node) {
2932 Expr *expr = get_resolved_expr(node);
2933 expr->const_val.ok = true;
2934 return g->builtin_types.entry_void;
2935}
2936
2937static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,2749static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
2938 bool depends_on_compile_var)2750 bool depends_on_compile_var)
2939{2751{
...@@ -5331,7 +5143,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -5331,7 +5143,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
5331 return_type = analyze_field_access_expr(g, import, context, expected_type, node);5143 return_type = analyze_field_access_expr(g, import, context, expected_type, node);
5332 break;5144 break;
5333 case NodeTypeContainerInitExpr:5145 case NodeTypeContainerInitExpr:
5334 return_type = analyze_container_init_expr(g, import, context, node);5146 zig_panic("analyze container init moved to ir.cpp");
5335 break;5147 break;
5336 case NodeTypeNumberLiteral:5148 case NodeTypeNumberLiteral:
5337 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);5149 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
src/codegen.cpp+215-182
...@@ -12,6 +12,7 @@...@@ -12,6 +12,7 @@
12#include "errmsg.hpp"12#include "errmsg.hpp"
13#include "error.hpp"13#include "error.hpp"
14#include "hash_map.hpp"14#include "hash_map.hpp"
15#include "ir.hpp"
15#include "link.hpp"16#include "link.hpp"
16#include "os.hpp"17#include "os.hpp"
17#include "parseh.hpp"18#include "parseh.hpp"
...@@ -513,18 +514,6 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {...@@ -513,18 +514,6 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
513 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");514 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
514}515}
515516
516static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) {
517 assert(node->type == NodeTypeFnCallExpr);
518
519 if (want_debug_safety(g, node) || g->is_test_build) {
520 gen_debug_safety_crash(g);
521 } else {
522 LLVMBuildUnreachable(g->builder);
523 }
524
525 return nullptr;
526}
527
528static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {517static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
529 assert(node->type == NodeTypeFnCallExpr);518 assert(node->type == NodeTypeFnCallExpr);
530519
...@@ -711,7 +700,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -711,7 +700,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
711 case BuiltinFnIdTruncate:700 case BuiltinFnIdTruncate:
712 return gen_truncate(g, node);701 return gen_truncate(g, node);
713 case BuiltinFnIdUnreachable:702 case BuiltinFnIdUnreachable:
714 return gen_unreachable(g, node);703 zig_panic("moved to ir render");
715 case BuiltinFnIdSetFnTest:704 case BuiltinFnIdSetFnTest:
716 case BuiltinFnIdSetFnVisible:705 case BuiltinFnIdSetFnVisible:
717 case BuiltinFnIdSetFnStaticEval:706 case BuiltinFnIdSetFnStaticEval:
...@@ -1334,154 +1323,6 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,...@@ -1334,154 +1323,6 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
1334 return result;1323 return result;
1335}1324}
13361325
1337static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1338 assert(node->type == NodeTypePrefixOpExpr);
1339 assert(node->data.prefix_op_expr.primary_expr);
1340
1341 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
1342 TypeTableEntry *expr_type = get_expr_type(expr_node);
1343
1344 PrefixOp op = node->data.prefix_op_expr.prefix_op;
1345
1346 switch (op) {
1347 case PrefixOpInvalid:
1348 zig_unreachable();
1349 case PrefixOpNegation:
1350 case PrefixOpNegationWrap:
1351 {
1352 LLVMValueRef expr = gen_expr(g, expr_node);
1353 if (expr_type->id == TypeTableEntryIdFloat) {
1354 return LLVMBuildFNeg(g->builder, expr, "");
1355 } else if (expr_type->id == TypeTableEntryIdInt) {
1356 if (op == PrefixOpNegationWrap) {
1357 return LLVMBuildNeg(g->builder, expr, "");
1358 } else if (want_debug_safety(g, expr_node)) {
1359 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1360 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
1361 } else if (expr_type->data.integral.is_signed) {
1362 return LLVMBuildNSWNeg(g->builder, expr, "");
1363 } else {
1364 return LLVMBuildNUWNeg(g->builder, expr, "");
1365 }
1366 } else {
1367 zig_unreachable();
1368 }
1369 }
1370 case PrefixOpBoolNot:
1371 {
1372 LLVMValueRef expr = gen_expr(g, expr_node);
1373 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1374 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
1375 }
1376 case PrefixOpBinNot:
1377 {
1378 LLVMValueRef expr = gen_expr(g, expr_node);
1379 return LLVMBuildNot(g->builder, expr, "");
1380 }
1381 case PrefixOpAddressOf:
1382 case PrefixOpConstAddressOf:
1383 {
1384 TypeTableEntry *lvalue_type;
1385 return gen_lvalue(g, node, expr_node, &lvalue_type);
1386 }
1387
1388 case PrefixOpDereference:
1389 {
1390 LLVMValueRef expr = gen_expr(g, expr_node);
1391 assert(expr_type->id == TypeTableEntryIdPointer);
1392 if (!type_has_bits(expr_type)) {
1393 return nullptr;
1394 } else {
1395 TypeTableEntry *child_type = expr_type->data.pointer.child_type;
1396 return get_handle_value(g, expr, child_type);
1397 }
1398 }
1399 case PrefixOpMaybe:
1400 {
1401 zig_panic("TODO codegen PrefixOpMaybe");
1402 }
1403 case PrefixOpError:
1404 {
1405 zig_panic("TODO codegen PrefixOpError");
1406 }
1407 case PrefixOpUnwrapError:
1408 {
1409 LLVMValueRef expr_val = gen_expr(g, expr_node);
1410 TypeTableEntry *expr_type = get_expr_type(expr_node);
1411 assert(expr_type->id == TypeTableEntryIdErrorUnion);
1412 TypeTableEntry *child_type = expr_type->data.error.child_type;
1413
1414 if (want_debug_safety(g, node)) {
1415 LLVMValueRef err_val;
1416 if (type_has_bits(child_type)) {
1417 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1418 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
1419 } else {
1420 err_val = expr_val;
1421 }
1422 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
1423 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
1424 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
1425 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
1426 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
1427
1428 LLVMPositionBuilderAtEnd(g->builder, err_block);
1429 gen_debug_safety_crash(g);
1430
1431 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1432 }
1433
1434 if (type_has_bits(child_type)) {
1435 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1436 return get_handle_value(g, child_val_ptr, child_type);
1437 } else {
1438 return nullptr;
1439 }
1440 }
1441 case PrefixOpUnwrapMaybe:
1442 {
1443 LLVMValueRef expr_val = gen_expr(g, expr_node);
1444
1445 TypeTableEntry *expr_type = get_expr_type(expr_node);
1446 assert(expr_type->id == TypeTableEntryIdMaybe);
1447 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
1448
1449 if (want_debug_safety(g, node)) {
1450 LLVMValueRef cond_val;
1451 if (child_type->id == TypeTableEntryIdPointer ||
1452 child_type->id == TypeTableEntryIdFn)
1453 {
1454 cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr_val,
1455 LLVMConstNull(child_type->type_ref), "");
1456 } else {
1457 LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1458 cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
1459 }
1460
1461 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk");
1462 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeNull");
1463 LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
1464
1465 LLVMPositionBuilderAtEnd(g->builder, null_block);
1466 gen_debug_safety_crash(g);
1467
1468 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1469 }
1470
1471
1472 if (child_type->id == TypeTableEntryIdPointer ||
1473 child_type->id == TypeTableEntryIdFn)
1474 {
1475 return expr_val;
1476 } else {
1477 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1478 return get_handle_value(g, maybe_field_ptr, child_type);
1479 }
1480 }
1481 }
1482 zig_unreachable();
1483}
1484
1485static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,1326static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
1486 TypeTableEntry *type_entry, bool exact)1327 TypeTableEntry *type_entry, bool exact)
1487{1328{
...@@ -2468,8 +2309,20 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -2468,8 +2309,20 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
2468 return nullptr;2309 return nullptr;
2469}2310}
24702311
2312static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
2313 if (!type_has_bits(instruction->type_entry))
2314 return nullptr;
2315 if (!instruction->llvm_value) {
2316 assert(instruction->static_value.ok);
2317 assert(instruction->type_entry);
2318 instruction->llvm_value = gen_const_val(g, instruction->type_entry, &instruction->static_value);
2319 assert(instruction->llvm_value);
2320 }
2321 return instruction->llvm_value;
2322}
2323
2471static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {2324static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2472 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);2325 LLVMBuildRet(g->builder, ir_llvm_value(g, return_instruction->value));
2473 return nullptr;2326 return nullptr;
2474}2327}
24752328
...@@ -2488,8 +2341,8 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,...@@ -2488,8 +2341,8 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
2488 IrInstructionBinOp *bin_op_instruction)2341 IrInstructionBinOp *bin_op_instruction)
2489{2342{
2490 IrBinOp op_id = bin_op_instruction->op_id;2343 IrBinOp op_id = bin_op_instruction->op_id;
2491 LLVMValueRef op1 = bin_op_instruction->op1->llvm_value;2344 LLVMValueRef op1 = ir_llvm_value(g, bin_op_instruction->op1);
2492 LLVMValueRef op2 = bin_op_instruction->op2->llvm_value;2345 LLVMValueRef op2 = ir_llvm_value(g, bin_op_instruction->op2);
2493 if (op_id == IrBinOpBoolOr) {2346 if (op_id == IrBinOpBoolOr) {
2494 return LLVMBuildOr(g->builder, op1, op2, "");2347 return LLVMBuildOr(g->builder, op1, op2, "");
2495 } else if (op_id == IrBinOpBoolAnd) {2348 } else if (op_id == IrBinOpBoolAnd) {
...@@ -2508,18 +2361,21 @@ static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,...@@ -2508,18 +2361,21 @@ static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
25082361
2509 assert(op1->type_entry == op2->type_entry);2362 assert(op1->type_entry == op2->type_entry);
25102363
2364 LLVMValueRef op1_value = ir_llvm_value(g, op1);
2365 LLVMValueRef op2_value = ir_llvm_value(g, op2);
2366
2511 if (op1->type_entry->id == TypeTableEntryIdFloat) {2367 if (op1->type_entry->id == TypeTableEntryIdFloat) {
2512 return LLVMBuildFAdd(g->builder, op1->llvm_value, op2->llvm_value, "");2368 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
2513 } else if (op1->type_entry->id == TypeTableEntryIdInt) {2369 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
2514 bool is_wrapping = (op_id == IrBinOpAddWrap);2370 bool is_wrapping = (op_id == IrBinOpAddWrap);
2515 if (is_wrapping) {2371 if (is_wrapping) {
2516 return LLVMBuildAdd(g->builder, op1->llvm_value, op2->llvm_value, "");2372 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
2517 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {2373 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
2518 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1->llvm_value, op2->llvm_value);2374 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);
2519 } else if (op1->type_entry->data.integral.is_signed) {2375 } else if (op1->type_entry->data.integral.is_signed) {
2520 return LLVMBuildNSWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");2376 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
2521 } else {2377 } else {
2522 return LLVMBuildNUWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");2378 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
2523 }2379 }
2524 } else {2380 } else {
2525 zig_unreachable();2381 zig_unreachable();
...@@ -2570,7 +2426,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2570,7 +2426,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2570{2426{
2571 TypeTableEntry *actual_type = cast_instruction->value->type_entry;2427 TypeTableEntry *actual_type = cast_instruction->value->type_entry;
2572 TypeTableEntry *wanted_type = cast_instruction->base.type_entry;2428 TypeTableEntry *wanted_type = cast_instruction->base.type_entry;
2573 LLVMValueRef expr_val = cast_instruction->value->llvm_value;2429 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
2574 assert(expr_val);2430 assert(expr_val);
25752431
2576 switch (cast_instruction->cast_op) {2432 switch (cast_instruction->cast_op) {
...@@ -2792,13 +2648,176 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2792,13 +2648,176 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2792 zig_unreachable();2648 zig_unreachable();
2793}2649}
27942650
2651static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
2652 IrInstructionUnreachable *unreachable_instruction)
2653{
2654 if (ir_want_debug_safety(g, &unreachable_instruction->base) || g->is_test_build) {
2655 gen_debug_safety_crash(g);
2656 } else {
2657 LLVMBuildUnreachable(g->builder);
2658 }
2659 return nullptr;
2660}
2661
2662static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutable *executable,
2663 IrInstructionCondBr *cond_br_instruction)
2664{
2665 LLVMBuildCondBr(g->builder,
2666 ir_llvm_value(g, cond_br_instruction->condition),
2667 cond_br_instruction->then_block->llvm_block,
2668 cond_br_instruction->else_block->llvm_block);
2669 return nullptr;
2670}
2671
2672static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstructionBr *br_instruction) {
2673 LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block);
2674 return nullptr;
2675}
2676
2677static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
2678 IrUnOp op_id = un_op_instruction->op_id;
2679 LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value);
2680 TypeTableEntry *expr_type = un_op_instruction->value->type_entry;
2681
2682 switch (op_id) {
2683 case IrUnOpInvalid:
2684 zig_unreachable();
2685 case IrUnOpNegation:
2686 case IrUnOpNegationWrap:
2687 {
2688 if (expr_type->id == TypeTableEntryIdFloat) {
2689 return LLVMBuildFNeg(g->builder, expr, "");
2690 } else if (expr_type->id == TypeTableEntryIdInt) {
2691 if (op_id == IrUnOpNegationWrap) {
2692 return LLVMBuildNeg(g->builder, expr, "");
2693 } else if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2694 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
2695 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
2696 } else if (expr_type->data.integral.is_signed) {
2697 return LLVMBuildNSWNeg(g->builder, expr, "");
2698 } else {
2699 return LLVMBuildNUWNeg(g->builder, expr, "");
2700 }
2701 } else {
2702 zig_unreachable();
2703 }
2704 }
2705 case IrUnOpBoolNot:
2706 {
2707 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
2708 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
2709 }
2710 case IrUnOpBinNot:
2711 return LLVMBuildNot(g->builder, expr, "");
2712 case IrUnOpAddressOf:
2713 case IrUnOpConstAddressOf:
2714 zig_panic("TODO address of codegen");
2715 //{
2716 // TypeTableEntry *lvalue_type;
2717 // return gen_lvalue(g, node, expr_node, &lvalue_type);
2718 //}
2719 case IrUnOpDereference:
2720 {
2721 assert(expr_type->id == TypeTableEntryIdPointer);
2722 if (!type_has_bits(expr_type)) {
2723 return nullptr;
2724 } else {
2725 TypeTableEntry *child_type = expr_type->data.pointer.child_type;
2726 return get_handle_value(g, expr, child_type);
2727 }
2728 }
2729 case IrUnOpError:
2730 {
2731 zig_panic("TODO codegen PrefixOpError");
2732 }
2733 case IrUnOpMaybe:
2734 {
2735 zig_panic("TODO codegen PrefixOpMaybe");
2736 }
2737 case IrUnOpUnwrapError:
2738 {
2739 assert(expr_type->id == TypeTableEntryIdErrorUnion);
2740 TypeTableEntry *child_type = expr_type->data.error.child_type;
2741
2742 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2743 LLVMValueRef err_val;
2744 if (type_has_bits(child_type)) {
2745 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
2746 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
2747 } else {
2748 err_val = expr;
2749 }
2750 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
2751 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
2752 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
2753 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
2754 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
2755
2756 LLVMPositionBuilderAtEnd(g->builder, err_block);
2757 gen_debug_safety_crash(g);
2758
2759 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2760 }
2761
2762 if (type_has_bits(child_type)) {
2763 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
2764 return get_handle_value(g, child_val_ptr, child_type);
2765 } else {
2766 return nullptr;
2767 }
2768 }
2769 case IrUnOpUnwrapMaybe:
2770 {
2771 assert(expr_type->id == TypeTableEntryIdMaybe);
2772 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
2773
2774 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2775 LLVMValueRef cond_val;
2776 if (child_type->id == TypeTableEntryIdPointer ||
2777 child_type->id == TypeTableEntryIdFn)
2778 {
2779 cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr,
2780 LLVMConstNull(child_type->type_ref), "");
2781 } else {
2782 LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
2783 cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
2784 }
2785
2786 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk");
2787 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeNull");
2788 LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
2789
2790 LLVMPositionBuilderAtEnd(g->builder, null_block);
2791 gen_debug_safety_crash(g);
2792
2793 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2794 }
2795
2796
2797 if (child_type->id == TypeTableEntryIdPointer ||
2798 child_type->id == TypeTableEntryIdFn)
2799 {
2800 return expr;
2801 } else {
2802 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
2803 return get_handle_value(g, maybe_field_ptr, child_type);
2804 }
2805 }
2806 case IrUnOpErrorReturn:
2807 case IrUnOpMaybeReturn:
2808 zig_panic("TODO codegen more un ops");
2809 }
2810
2811 zig_unreachable();
2812}
2813
2795static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {2814static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2796 set_debug_source_node(g, instruction->source_node);2815 set_debug_source_node(g, instruction->source_node);
2816
2797 switch (instruction->id) {2817 switch (instruction->id) {
2798 case IrInstructionIdInvalid:2818 case IrInstructionIdInvalid:
2799 zig_unreachable();
2800 case IrInstructionIdConst:2819 case IrInstructionIdConst:
2801 return gen_const_val(g, instruction->type_entry, &instruction->static_value);2820 zig_unreachable();
2802 case IrInstructionIdReturn:2821 case IrInstructionIdReturn:
2803 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2822 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
2804 case IrInstructionIdLoadVar:2823 case IrInstructionIdLoadVar:
...@@ -2807,14 +2826,21 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2807,14 +2826,21 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2807 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);2826 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
2808 case IrInstructionIdCast:2827 case IrInstructionIdCast:
2809 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);2828 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);
2829 case IrInstructionIdUnreachable:
2830 return ir_render_unreachable(g, executable, (IrInstructionUnreachable *)instruction);
2810 case IrInstructionIdCondBr:2831 case IrInstructionIdCondBr:
2832 return ir_render_cond_br(g, executable, (IrInstructionCondBr *)instruction);
2811 case IrInstructionIdBr:2833 case IrInstructionIdBr:
2834 return ir_render_br(g, executable, (IrInstructionBr *)instruction);
2835 case IrInstructionIdUnOp:
2836 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
2812 case IrInstructionIdSwitchBr:2837 case IrInstructionIdSwitchBr:
2813 case IrInstructionIdPhi:2838 case IrInstructionIdPhi:
2814 case IrInstructionIdStoreVar:2839 case IrInstructionIdStoreVar:
2815 case IrInstructionIdCall:2840 case IrInstructionIdCall:
2816 case IrInstructionIdBuiltinCall:2841 case IrInstructionIdBuiltinCall:
2817 case IrInstructionIdUnOp:2842 case IrInstructionIdContainerInitList:
2843 case IrInstructionIdContainerInitFields:
2818 zig_panic("TODO render more IR instructions to LLVM");2844 zig_panic("TODO render more IR instructions to LLVM");
2819 }2845 }
2820 zig_unreachable();2846 zig_unreachable();
...@@ -2826,8 +2852,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {...@@ -2826,8 +2852,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
2826 assert(executable->basic_block_list.length > 0);2852 assert(executable->basic_block_list.length > 0);
2827 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {2853 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
2828 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);2854 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
2855 if (current_block->ref_count == 0)
2856 continue;
2857 assert(current_block->llvm_block);
2858 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
2829 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {2859 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
2830 IrInstruction *instruction = current_block->instruction_list.at(instr_i);2860 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
2861 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
2862 continue;
2831 instruction->llvm_value = ir_render_instruction(g, executable, instruction);2863 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
2832 }2864 }
2833 }2865 }
...@@ -3622,7 +3654,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -3622,7 +3654,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
3622 case NodeTypeVariableDeclaration:3654 case NodeTypeVariableDeclaration:
3623 return gen_var_decl_expr(g, node);3655 return gen_var_decl_expr(g, node);
3624 case NodeTypePrefixOpExpr:3656 case NodeTypePrefixOpExpr:
3625 return gen_prefix_op_expr(g, node);3657 zig_panic("moved to ir render");
3626 case NodeTypeFnCallExpr:3658 case NodeTypeFnCallExpr:
3627 return gen_fn_call_expr(g, node);3659 return gen_fn_call_expr(g, node);
3628 case NodeTypeArrayAccessExpr:3660 case NodeTypeArrayAccessExpr:
...@@ -4018,14 +4050,15 @@ static void generate_error_name_table(CodeGen *g) {...@@ -4018,14 +4050,15 @@ static void generate_error_name_table(CodeGen *g) {
4018 LLVMSetUnnamedAddr(g->err_name_table, true);4050 LLVMSetUnnamedAddr(g->err_name_table, true);
4019}4051}
40204052
4021static void build_label_blocks(CodeGen *g, FnTableEntry *fn) {4053static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {
4022 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn->fn_value, "entry");4054 IrExecutable *executable = &fn->analyzed_executable;
4023 for (size_t i = 0; i < fn->all_labels.length; i += 1) {4055 assert(executable->basic_block_list.length > 0);
4024 LabelTableEntry *label = fn->all_labels.at(i);4056 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
4025 Buf *name = label->decl_node->data.label.name;4057 IrBasicBlock *bb = executable->basic_block_list.at(block_i);
4026 label->basic_block = LLVMAppendBasicBlock(fn->fn_value, buf_ptr(name));4058 bb->llvm_block = LLVMAppendBasicBlock(fn->fn_value, bb->name_hint);
4027 }4059 }
4028 LLVMPositionBuilderAtEnd(g->builder, entry_block);4060 IrBasicBlock *entry_bb = executable->basic_block_list.at(0);
4061 LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block);
4029}4062}
40304063
4031static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,4064static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,
...@@ -4252,7 +4285,7 @@ static void do_code_gen(CodeGen *g) {...@@ -4252,7 +4285,7 @@ static void do_code_gen(CodeGen *g) {
4252 assert(proto_node->type == NodeTypeFnProto);4285 assert(proto_node->type == NodeTypeFnProto);
4253 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;4286 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
42544287
4255 build_label_blocks(g, fn_table_entry);4288 build_all_basic_blocks(g, fn_table_entry);
42564289
42574290
4258 // Set up debug info for blocks4291 // Set up debug info for blocks
src/ir.cpp+659-50
...@@ -40,6 +40,29 @@ static size_t exec_next_debug_id(IrExecutable *exec) {...@@ -40,6 +40,29 @@ static size_t exec_next_debug_id(IrExecutable *exec) {
40 return result;40 return result;
41}41}
4242
43static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) {
44 new_instruction->other = old_instruction;
45 old_instruction->other = new_instruction;
46}
47
48static void ir_link_new_bb(IrBasicBlock *new_bb, IrBasicBlock *old_bb) {
49 new_bb->other = old_bb;
50 old_bb->other = new_bb;
51}
52
53static void ir_ref_bb(IrBasicBlock *bb) {
54 bb->ref_count += 1;
55}
56
57static void ir_unref_bb(IrBasicBlock *bb) {
58 bb->ref_count -= 1;
59 assert(bb->ref_count != SIZE_MAX);
60}
61
62static void ir_ref_instruction(IrInstruction *instruction) {
63 instruction->ref_count += 1;
64}
65
43static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {66static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {
44 IrBasicBlock *result = allocate<IrBasicBlock>(1);67 IrBasicBlock *result = allocate<IrBasicBlock>(1);
45 result->name_hint = name_hint;68 result->name_hint = name_hint;
...@@ -48,10 +71,20 @@ static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint)...@@ -48,10 +71,20 @@ static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint)
48 return result;71 return result;
49}72}
5073
74static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
75 IrBasicBlock *new_bb = ir_build_basic_block(irb, other_bb->name_hint);
76 ir_link_new_bb(new_bb, other_bb);
77 return new_bb;
78}
79
51static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {80static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
52 return IrInstructionIdCondBr;81 return IrInstructionIdCondBr;
53}82}
5483
84static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) {
85 return IrInstructionIdBr;
86}
87
55static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchBr *) {88static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchBr *) {
56 return IrInstructionIdSwitchBr;89 return IrInstructionIdSwitchBr;
57}90}
...@@ -96,8 +129,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {...@@ -96,8 +129,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
96 return IrInstructionIdCast;129 return IrInstructionIdCast;
97}130}
98131
99static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) {132static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {
100 return IrInstructionIdBr;133 return IrInstructionIdContainerInitList;
134}
135
136static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitFields *) {
137 return IrInstructionIdContainerInitFields;
138}
139
140static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) {
141 return IrInstructionIdUnreachable;
101}142}
102143
103template<typename T>144template<typename T>
...@@ -123,6 +164,10 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst...@@ -123,6 +164,10 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst
123 cast_instruction->dest_type = dest_type;164 cast_instruction->dest_type = dest_type;
124 cast_instruction->value = value;165 cast_instruction->value = value;
125 cast_instruction->cast_op = cast_op;166 cast_instruction->cast_op = cast_op;
167
168 ir_ref_instruction(dest_type);
169 ir_ref_instruction(value);
170
126 return &cast_instruction->base;171 return &cast_instruction->base;
127}172}
128173
...@@ -135,19 +180,44 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI...@@ -135,19 +180,44 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
135 cond_br_instruction->condition = condition;180 cond_br_instruction->condition = condition;
136 cond_br_instruction->then_block = then_block;181 cond_br_instruction->then_block = then_block;
137 cond_br_instruction->else_block = else_block;182 cond_br_instruction->else_block = else_block;
183
184 ir_ref_instruction(condition);
185 ir_ref_bb(then_block);
186 ir_ref_bb(else_block);
187
138 return &cond_br_instruction->base;188 return &cond_br_instruction->base;
139}189}
140190
191static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,
192 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block)
193{
194 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->source_node,
195 condition, then_block, else_block);
196 ir_link_new_instruction(new_instruction, old_instruction);
197 return new_instruction;
198}
199
141static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {200static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
142 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);201 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
143 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;202 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
144 return_instruction->base.static_value.ok = true;203 return_instruction->base.static_value.ok = true;
145 return_instruction->value = return_value;204 return_instruction->value = return_value;
205
206 ir_ref_instruction(return_value);
207
146 return &return_instruction->base;208 return &return_instruction->base;
147}209}
148210
149static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {211static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_instruction,
150 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);212 IrInstruction *return_value)
213{
214 IrInstruction *new_instruction = ir_build_return(irb, old_instruction->source_node, return_value);
215 ir_link_new_instruction(new_instruction, old_instruction);
216 return new_instruction;
217}
218
219static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
220 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
151 const_instruction->base.type_entry = type_entry;221 const_instruction->base.type_entry = type_entry;
152 const_instruction->base.static_value.ok = true;222 const_instruction->base.static_value.ok = true;
153 return &const_instruction->base;223 return &const_instruction->base;
...@@ -206,9 +276,21 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBi...@@ -206,9 +276,21 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBi
206 bin_op_instruction->op_id = op_id;276 bin_op_instruction->op_id = op_id;
207 bin_op_instruction->op1 = op1;277 bin_op_instruction->op1 = op1;
208 bin_op_instruction->op2 = op2;278 bin_op_instruction->op2 = op2;
279
280 ir_ref_instruction(op1);
281 ir_ref_instruction(op2);
282
209 return &bin_op_instruction->base;283 return &bin_op_instruction->base;
210}284}
211285
286static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_instruction, IrBinOp op_id,
287 IrInstruction *op1, IrInstruction *op2)
288{
289 IrInstruction *new_instruction = ir_build_bin_op(irb, old_instruction->source_node, op_id, op1, op2);
290 ir_link_new_instruction(new_instruction, old_instruction);
291 return new_instruction;
292}
293
212static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {294static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
213 IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node);295 IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node);
214 load_var_instruction->base.type_entry = var->type;296 load_var_instruction->base.type_entry = var->type;
...@@ -216,6 +298,15 @@ static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, Va...@@ -216,6 +298,15 @@ static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, Va
216 return &load_var_instruction->base;298 return &load_var_instruction->base;
217}299}
218300
301static IrInstruction *ir_build_load_var_from(IrBuilder *irb, IrInstruction *old_instruction,
302 VariableTableEntry *var)
303{
304 IrInstruction *new_instruction = ir_build_load_var(irb, old_instruction->source_node, var);
305 ir_link_new_instruction(new_instruction, old_instruction);
306 return new_instruction;
307
308}
309
219static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,310static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
220 IrInstruction *fn, size_t arg_count, IrInstruction **args)311 IrInstruction *fn, size_t arg_count, IrInstruction **args)
221{312{
...@@ -223,6 +314,12 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,...@@ -223,6 +314,12 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
223 call_instruction->fn = fn;314 call_instruction->fn = fn;
224 call_instruction->arg_count = arg_count;315 call_instruction->arg_count = arg_count;
225 call_instruction->args = args;316 call_instruction->args = args;
317
318 ir_ref_instruction(fn);
319 for (size_t i = 0; i < arg_count; i += 1) {
320 ir_ref_instruction(args[i]);
321 }
322
226 return &call_instruction->base;323 return &call_instruction->base;
227}324}
228325
...@@ -232,6 +329,11 @@ static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node...@@ -232,6 +329,11 @@ static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node
232 IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node);329 IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node);
233 call_instruction->fn = fn;330 call_instruction->fn = fn;
234 call_instruction->args = args;331 call_instruction->args = args;
332
333 for (size_t i = 0; i < fn->param_count; i += 1) {
334 ir_ref_instruction(args[i]);
335 }
336
235 return &call_instruction->base;337 return &call_instruction->base;
236}338}
237339
...@@ -242,22 +344,105 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,...@@ -242,22 +344,105 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
242 phi_instruction->incoming_count = incoming_count;344 phi_instruction->incoming_count = incoming_count;
243 phi_instruction->incoming_blocks = incoming_blocks;345 phi_instruction->incoming_blocks = incoming_blocks;
244 phi_instruction->incoming_values = incoming_values;346 phi_instruction->incoming_values = incoming_values;
347
348 for (size_t i = 0; i < incoming_count; i += 1) {
349 ir_ref_instruction(incoming_values[i]);
350 }
351
245 return &phi_instruction->base;352 return &phi_instruction->base;
246}353}
247354
355static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instruction,
356 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
357{
358 IrInstruction *new_instruction = ir_build_phi(irb, old_instruction->source_node,
359 incoming_count, incoming_blocks, incoming_values);
360 ir_link_new_instruction(new_instruction, old_instruction);
361 return new_instruction;
362}
363
248static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {364static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {
249 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);365 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
250 br_instruction->dest_block = dest_block;366 br_instruction->dest_block = dest_block;
367
368 ir_ref_bb(dest_block);
369
251 return &br_instruction->base;370 return &br_instruction->base;
252}371}
253372
373static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
374 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block);
375 ir_link_new_instruction(new_instruction, old_instruction);
376 return new_instruction;
377}
378
254static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {379static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
255 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);380 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);
256 br_instruction->op_id = op_id;381 br_instruction->op_id = op_id;
257 br_instruction->value = value;382 br_instruction->value = value;
383
384 ir_ref_instruction(value);
385
258 return &br_instruction->base;386 return &br_instruction->base;
259}387}
260388
389static IrInstruction *ir_build_un_op_from(IrBuilder *irb, IrInstruction *old_instruction,
390 IrUnOp op_id, IrInstruction *value)
391{
392 IrInstruction *new_instruction = ir_build_un_op(irb, old_instruction->source_node, op_id, value);
393 ir_link_new_instruction(new_instruction, old_instruction);
394 return new_instruction;
395}
396
397static IrInstruction *ir_build_container_init_list(IrBuilder *irb, AstNode *source_node,
398 IrInstruction *container_type, size_t item_count, IrInstruction **items)
399{
400 IrInstructionContainerInitList *container_init_list_instruction =
401 ir_build_instruction<IrInstructionContainerInitList>(irb, source_node);
402 container_init_list_instruction->container_type = container_type;
403 container_init_list_instruction->item_count = item_count;
404 container_init_list_instruction->items = items;
405
406 ir_ref_instruction(container_type);
407 for (size_t i = 0; i < item_count; i += 1) {
408 ir_ref_instruction(items[i]);
409 }
410
411 return &container_init_list_instruction->base;
412}
413
414static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *source_node,
415 IrInstruction *container_type, size_t field_count, Buf **field_names, IrInstruction **field_values)
416{
417 IrInstructionContainerInitFields *container_init_fields_instruction =
418 ir_build_instruction<IrInstructionContainerInitFields>(irb, source_node);
419 container_init_fields_instruction->container_type = container_type;
420 container_init_fields_instruction->field_count = field_count;
421 container_init_fields_instruction->field_names = field_names;
422 container_init_fields_instruction->field_values = field_values;
423
424 ir_ref_instruction(container_type);
425 for (size_t i = 0; i < field_count; i += 1) {
426 ir_ref_instruction(field_values[i]);
427 }
428
429 return &container_init_fields_instruction->base;
430}
431
432static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {
433 IrInstructionUnreachable *unreachable_instruction =
434 ir_build_instruction<IrInstructionUnreachable>(irb, source_node);
435 unreachable_instruction->base.static_value.ok = true;
436 unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
437 return &unreachable_instruction->base;
438}
439
440static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *old_instruction) {
441 IrInstruction *new_instruction = ir_build_unreachable(irb, old_instruction->source_node);
442 ir_link_new_instruction(new_instruction, old_instruction);
443 return new_instruction;
444}
445
261446
262//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {447//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
263// size_t result = 0;448// size_t result = 0;
...@@ -524,6 +709,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {...@@ -524,6 +709,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
524709
525 builtin_fn->ref_count += 1;710 builtin_fn->ref_count += 1;
526711
712 if (builtin_fn->id == BuiltinFnIdUnreachable) {
713 return ir_build_unreachable(irb, node);
714 }
715
527 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);716 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);
528 for (size_t i = 0; i < actual_param_count; i += 1) {717 for (size_t i = 0; i < actual_param_count; i += 1) {
529 AstNode *arg_node = node->data.fn_call_expr.params.at(i);718 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
...@@ -649,6 +838,51 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {...@@ -649,6 +838,51 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {
649 zig_unreachable();838 zig_unreachable();
650}839}
651840
841static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) {
842 assert(node->type == NodeTypeContainerInitExpr);
843
844 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
845 ContainerInitKind kind = container_init_expr->kind;
846
847 IrInstruction *container_type = ir_gen_node(irb, container_init_expr->type, node->block_context);
848 if (container_type == irb->codegen->invalid_instruction)
849 return container_type;
850
851 if (kind == ContainerInitKindStruct) {
852 size_t field_count = container_init_expr->entries.length;
853 IrInstruction **values = allocate<IrInstruction *>(field_count);
854 Buf **names = allocate<Buf *>(field_count);
855 for (size_t i = 0; i < field_count; i += 1) {
856 AstNode *entry_node = container_init_expr->entries.at(i);
857 assert(entry_node->type == NodeTypeStructValueField);
858
859 Buf *name = entry_node->data.struct_val_field.name;
860 AstNode *expr_node = entry_node->data.struct_val_field.expr;
861 IrInstruction *expr_value = ir_gen_node(irb, expr_node, node->block_context);
862 if (expr_value == irb->codegen->invalid_instruction)
863 return expr_value;
864
865 names[i] = name;
866 values[i] = expr_value;
867 }
868 return ir_build_container_init_fields(irb, node, container_type, field_count, names, values);
869 } else if (kind == ContainerInitKindArray) {
870 size_t item_count = container_init_expr->entries.length;
871 IrInstruction **values = allocate<IrInstruction *>(item_count);
872 for (size_t i = 0; i < item_count; i += 1) {
873 AstNode *expr_node = container_init_expr->entries.at(i);
874 IrInstruction *expr_value = ir_gen_node(irb, expr_node, node->block_context);
875 if (expr_value == irb->codegen->invalid_instruction)
876 return expr_value;
877
878 values[i] = expr_value;
879 }
880 return ir_build_container_init_list(irb, node, container_type, item_count, values);
881 } else {
882 zig_unreachable();
883 }
884}
885
652static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,886static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
653 bool pointer_only)887 bool pointer_only)
654{888{
...@@ -670,6 +904,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -670,6 +904,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
670 return ir_gen_if_bool_expr(irb, node);904 return ir_gen_if_bool_expr(irb, node);
671 case NodeTypePrefixOpExpr:905 case NodeTypePrefixOpExpr:
672 return ir_gen_prefix_op_expr(irb, node);906 return ir_gen_prefix_op_expr(irb, node);
907 case NodeTypeContainerInitExpr:
908 return ir_gen_container_init_expr(irb, node);
673 case NodeTypeUnwrapErrorExpr:909 case NodeTypeUnwrapErrorExpr:
674 case NodeTypeReturnExpr:910 case NodeTypeReturnExpr:
675 case NodeTypeDefer:911 case NodeTypeDefer:
...@@ -685,7 +921,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -685,7 +921,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
685 case NodeTypeBreak:921 case NodeTypeBreak:
686 case NodeTypeContinue:922 case NodeTypeContinue:
687 case NodeTypeLabel:923 case NodeTypeLabel:
688 case NodeTypeContainerInitExpr:
689 case NodeTypeSwitchExpr:924 case NodeTypeSwitchExpr:
690 case NodeTypeBoolLiteral:925 case NodeTypeBoolLiteral:
691 case NodeTypeStringLiteral:926 case NodeTypeStringLiteral:
...@@ -733,6 +968,8 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext...@@ -733,6 +968,8 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext
733 irb->exec = ir_executable;968 irb->exec = ir_executable;
734969
735 irb->current_basic_block = ir_build_basic_block(irb, "Entry");970 irb->current_basic_block = ir_build_basic_block(irb, "Entry");
971 // Entry block gets a reference because we enter it to begin.
972 ir_ref_bb(irb->current_basic_block);
736973
737 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);974 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);
738 assert(result);975 assert(result);
...@@ -767,11 +1004,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {...@@ -767,11 +1004,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
767 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no);1004 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no);
768}1005}
7691006
770static void ir_link_new(IrInstruction *new_instruction, IrInstruction *old_instruction) {
771 new_instruction->other = old_instruction;
772 old_instruction->other = new_instruction;
773}
774
775/*1007/*
776static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) {1008static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) {
777 assert(node->type == NodeTypeGoto);1009 assert(node->type == NodeTypeGoto);
...@@ -1033,7 +1265,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -1033,7 +1265,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
1033 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;1265 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
10341266
1035 if (value->static_value.ok) {1267 if (value->static_value.ok) {
1036 IrInstruction *result = ir_build_const(&ira->new_irb, source_instr->source_node, wanted_type);1268 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);
1037 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,1269 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
1038 &result->static_value, wanted_type);1270 &result->static_value, wanted_type);
1039 return result;1271 return result;
...@@ -1058,6 +1290,12 @@ static bool is_u8(TypeTableEntry *type) {...@@ -1058,6 +1290,12 @@ static bool is_u8(TypeTableEntry *type) {
1058 !type->data.integral.is_signed && type->data.integral.bit_count == 8;1290 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
1059}1291}
10601292
1293static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
1294 if (old_bb->other)
1295 return old_bb->other;
1296 return ir_build_bb_from(&ira->new_irb, old_bb);
1297}
1298
1061static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,1299static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1062 IrInstruction *dest_type, IrInstruction *value)1300 IrInstruction *dest_type, IrInstruction *value)
1063{1301{
...@@ -1365,10 +1603,7 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi...@@ -1365,10 +1603,7 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi
1365 return ira->codegen->builtin_types.entry_invalid;1603 return ira->codegen->builtin_types.entry_invalid;
1366 }1604 }
13671605
1368 ir_link_new(ir_build_return(&ira->new_irb, return_instruction->base.source_node, value),1606 return ir_build_return_from(&ira->new_irb, &return_instruction->base, value)->type_entry;
1369 &return_instruction->base);
1370
1371 return ira->codegen->builtin_types.entry_unreachable;
1372}1607}
13731608
1374static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {1609static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
...@@ -1411,8 +1646,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -1411,8 +1646,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1411 return bool_type;1646 return bool_type;
1412 }1647 }
14131648
1414 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1649 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other);
1415 bin_op_instruction->op_id, op1->other, op2->other), &bin_op_instruction->base);
14161650
1417 return bool_type;1651 return bool_type;
1418}1652}
...@@ -1481,8 +1715,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -1481,8 +1715,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
14811715
1482 zig_panic("TODO interpret bin_op_cmp");1716 zig_panic("TODO interpret bin_op_cmp");
14831717
1484 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1718 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
1485 op_id, op1->other, op2->other), &bin_op_instruction->base);
14861719
1487 return ira->codegen->builtin_types.entry_bool;1720 return ira->codegen->builtin_types.entry_bool;
1488}1721}
...@@ -1639,8 +1872,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -1639,8 +1872,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
16391872
1640 }1873 }
16411874
1642 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,1875 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
1643 op_id, op1->other, op2->other), &bin_op_instruction->base);
16441876
1645 return resolved_type;1877 return resolved_type;
1646}1878}
...@@ -1684,8 +1916,7 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi...@@ -1684,8 +1916,7 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi
1684}1916}
16851917
1686static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {1918static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {
1687 ir_link_new(ir_build_load_var(&ira->new_irb, load_var_instruction->base.source_node,1919 ir_build_load_var_from(&ira->new_irb, &load_var_instruction->base, load_var_instruction->var);
1688 load_var_instruction->var), &load_var_instruction->base);
1689 return load_var_instruction->var->type;1920 return load_var_instruction->var->type;
1690}1921}
16911922
...@@ -1709,15 +1940,14 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -1709,15 +1940,14 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
1709 if (cast_instruction == ira->codegen->invalid_instruction)1940 if (cast_instruction == ira->codegen->invalid_instruction)
1710 return ira->codegen->builtin_types.entry_invalid;1941 return ira->codegen->builtin_types.entry_invalid;
17111942
1712 ir_link_new(cast_instruction, &call_instruction->base);1943 ir_link_new_instruction(cast_instruction, &call_instruction->base);
1713 return cast_instruction->type_entry;1944 return cast_instruction->type_entry;
1714 } else {1945 } else {
1715 zig_panic("TODO analyze more fn call types");1946 zig_panic("TODO analyze more fn call types");
1716 }1947 }
1717 } else {1948 } else {
1718 //ir_link_new(ir_build_call(&ira->new_irb, call_instruction->base.source_node,1949 //ir_build_call_from(&ira->new_irb, &call_instruction->base,
1719 // call_instruction->fn, call_instruction->arg_count, call_instruction->args),1950 // call_instruction->fn, call_instruction->arg_count, call_instruction->args);
1720 // &call_instruction->base);
17211951
1722 zig_panic("TODO analyze fn call");1952 zig_panic("TODO analyze fn call");
1723 }1953 }
...@@ -1726,7 +1956,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -1726,7 +1956,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
1726static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {1956static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
1727 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;1957 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
17281958
1729 IrInstruction *casted_value = ir_get_casted_value(ira, un_op_instruction->value, bool_type);1959 IrInstruction *casted_value = ir_get_casted_value(ira, un_op_instruction->value->other, bool_type);
1730 if (casted_value == ira->codegen->invalid_instruction)1960 if (casted_value == ira->codegen->invalid_instruction)
1731 return ira->codegen->builtin_types.entry_invalid;1961 return ira->codegen->builtin_types.entry_invalid;
17321962
...@@ -1739,9 +1969,7 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn...@@ -1739,9 +1969,7 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
1739 return bool_type;1969 return bool_type;
1740 }1970 }
17411971
1742 IrInstruction *new_instruction = ir_build_un_op(&ira->new_irb, un_op_instruction->base.source_node,1972 ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpBoolNot, casted_value);
1743 IrUnOpBoolNot, casted_value);
1744 ir_link_new(new_instruction, &un_op_instruction->base);
17451973
1746 return bool_type;1974 return bool_type;
1747}1975}
...@@ -2924,8 +3152,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -2924,8 +3152,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
2924// return analyze_compile_err(g, import, context, node);3152// return analyze_compile_err(g, import, context, node);
2925// case BuiltinFnIdIntType:3153// case BuiltinFnIdIntType:
2926// return analyze_int_type(g, import, context, node);3154// return analyze_int_type(g, import, context, node);
2927// case BuiltinFnIdUnreachable:
2928// return g->builtin_types.entry_unreachable;
2929// case BuiltinFnIdSetFnTest:3155// case BuiltinFnIdSetFnTest:
2930// return analyze_set_fn_test(g, import, context, node);3156// return analyze_set_fn_test(g, import, context, node);
2931// case BuiltinFnIdSetFnNoInline:3157// case BuiltinFnIdSetFnNoInline:
...@@ -2940,6 +3166,300 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -2940,6 +3166,300 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
2940// zig_unreachable();3166// zig_unreachable();
2941//}3167//}
29423168
3169//static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
3170// BlockContext *context, AstNode *node)
3171//{
3172// assert(node->type == NodeTypeContainerInitExpr);
3173//
3174// AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
3175//
3176// ContainerInitKind kind = container_init_expr->kind;
3177//
3178// if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
3179// container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
3180// }
3181//
3182// TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
3183// container_init_expr->type);
3184//
3185// if (container_meta_type->id == TypeTableEntryIdInvalid) {
3186// return g->builtin_types.entry_invalid;
3187// }
3188//
3189// if (node->data.container_init_expr.enum_type) {
3190// get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
3191// return node->data.container_init_expr.enum_type;
3192// }
3193//
3194// TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
3195//
3196// if (container_type->id == TypeTableEntryIdInvalid) {
3197// return container_type;
3198// } else if (container_type->id == TypeTableEntryIdStruct &&
3199// !container_type->data.structure.is_slice &&
3200// (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
3201// container_init_expr->entries.length == 0)))
3202// {
3203// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
3204// codegen->type_entry = container_type;
3205// codegen->source_node = node;
3206//
3207//
3208// size_t expr_field_count = container_init_expr->entries.length;
3209// size_t actual_field_count = container_type->data.structure.src_field_count;
3210//
3211// AstNode *non_const_expr_culprit = nullptr;
3212//
3213// size_t *field_use_counts = allocate<size_t>(actual_field_count);
3214// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3215// const_val->ok = true;
3216// const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
3217// for (size_t i = 0; i < expr_field_count; i += 1) {
3218// AstNode *val_field_node = container_init_expr->entries.at(i);
3219// assert(val_field_node->type == NodeTypeStructValueField);
3220//
3221// val_field_node->block_context = context;
3222//
3223// TypeStructField *type_field = find_struct_type_field(container_type,
3224// val_field_node->data.struct_val_field.name);
3225//
3226// if (!type_field) {
3227// add_node_error(g, val_field_node,
3228// buf_sprintf("no member named '%s' in '%s'",
3229// buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
3230// continue;
3231// }
3232//
3233// if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
3234// return g->builtin_types.entry_invalid;
3235// }
3236//
3237// size_t field_index = type_field->src_index;
3238// field_use_counts[field_index] += 1;
3239// if (field_use_counts[field_index] > 1) {
3240// add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
3241// continue;
3242// }
3243//
3244// val_field_node->data.struct_val_field.type_struct_field = type_field;
3245//
3246// analyze_expression(g, import, context, type_field->type_entry,
3247// val_field_node->data.struct_val_field.expr);
3248//
3249// if (const_val->ok) {
3250// ConstExprValue *field_val =
3251// &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
3252// if (field_val->ok) {
3253// const_val->data.x_struct.fields[field_index] = field_val;
3254// const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
3255// } else {
3256// const_val->ok = false;
3257// non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
3258// }
3259// }
3260// }
3261// if (!const_val->ok) {
3262// assert(non_const_expr_culprit);
3263// if (context->fn_entry) {
3264// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
3265// } else {
3266// add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
3267// }
3268// }
3269//
3270// for (size_t i = 0; i < actual_field_count; i += 1) {
3271// if (field_use_counts[i] == 0) {
3272// add_node_error(g, node,
3273// buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
3274// }
3275// }
3276// return container_type;
3277// } else if (container_type->id == TypeTableEntryIdStruct &&
3278// container_type->data.structure.is_slice &&
3279// kind == ContainerInitKindArray)
3280// {
3281// size_t elem_count = container_init_expr->entries.length;
3282//
3283// TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
3284// assert(pointer_type->id == TypeTableEntryIdPointer);
3285// TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
3286//
3287// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3288// const_val->ok = true;
3289// const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
3290//
3291// for (size_t i = 0; i < elem_count; i += 1) {
3292// AstNode **elem_node = &container_init_expr->entries.at(i);
3293// analyze_expression(g, import, context, child_type, *elem_node);
3294//
3295// if (const_val->ok) {
3296// ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
3297// if (elem_const_val->ok) {
3298// const_val->data.x_array.fields[i] = elem_const_val;
3299// const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
3300// elem_const_val->depends_on_compile_var;
3301// } else {
3302// const_val->ok = false;
3303// }
3304// }
3305// }
3306//
3307// TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
3308//
3309// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
3310// codegen->type_entry = fixed_size_array_type;
3311// codegen->source_node = node;
3312// if (!const_val->ok) {
3313// if (!context->fn_entry) {
3314// add_node_error(g, node,
3315// buf_sprintf("unable to evaluate constant expression"));
3316// } else {
3317// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
3318// }
3319// }
3320//
3321// return fixed_size_array_type;
3322// } else if (container_type->id == TypeTableEntryIdArray) {
3323// zig_panic("TODO array container init");
3324// return container_type;
3325// } else if (container_type->id == TypeTableEntryIdVoid) {
3326// if (container_init_expr->entries.length != 0) {
3327// add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
3328// return g->builtin_types.entry_invalid;
3329// } else {
3330// return resolve_expr_const_val_as_void(g, node);
3331// }
3332// } else {
3333// add_node_error(g, node,
3334// buf_sprintf("type '%s' does not support %s initialization syntax",
3335// buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
3336// return g->builtin_types.entry_invalid;
3337// }
3338//}
3339
3340static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
3341 IrBasicBlock *old_dest_block = br_instruction->dest_block;
3342 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3343 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
3344 return ira->codegen->builtin_types.entry_unreachable;
3345}
3346
3347static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
3348 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
3349 IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type);
3350 if (condition == ira->codegen->invalid_instruction)
3351 return ira->codegen->builtin_types.entry_invalid;
3352
3353 if (condition->static_value.ok) {
3354 IrBasicBlock *old_dest_block;
3355 IrBasicBlock *old_ignored_block;
3356 if (condition->static_value.data.x_bool) {
3357 old_dest_block = cond_br_instruction->then_block;
3358 old_ignored_block = cond_br_instruction->else_block;
3359 } else {
3360 old_dest_block = cond_br_instruction->else_block;
3361 old_ignored_block = cond_br_instruction->then_block;
3362 }
3363 ir_unref_bb(old_ignored_block);
3364 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3365 ir_build_br_from(&ira->new_irb, &cond_br_instruction->base, new_bb);
3366 return ira->codegen->builtin_types.entry_unreachable;
3367 }
3368
3369 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
3370 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
3371 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block);
3372 return ira->codegen->builtin_types.entry_unreachable;
3373}
3374
3375static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
3376 IrInstructionBuiltinCall *builtin_call_instruction)
3377{
3378 switch (builtin_call_instruction->fn->id) {
3379 case BuiltinFnIdInvalid:
3380 case BuiltinFnIdUnreachable:
3381 zig_unreachable();
3382 case BuiltinFnIdMemcpy:
3383 case BuiltinFnIdMemset:
3384 case BuiltinFnIdSizeof:
3385 case BuiltinFnIdAlignof:
3386 case BuiltinFnIdMaxValue:
3387 case BuiltinFnIdMinValue:
3388 case BuiltinFnIdMemberCount:
3389 case BuiltinFnIdTypeof:
3390 case BuiltinFnIdAddWithOverflow:
3391 case BuiltinFnIdSubWithOverflow:
3392 case BuiltinFnIdMulWithOverflow:
3393 case BuiltinFnIdShlWithOverflow:
3394 case BuiltinFnIdCInclude:
3395 case BuiltinFnIdCDefine:
3396 case BuiltinFnIdCUndef:
3397 case BuiltinFnIdCompileVar:
3398 case BuiltinFnIdCompileErr:
3399 case BuiltinFnIdConstEval:
3400 case BuiltinFnIdCtz:
3401 case BuiltinFnIdClz:
3402 case BuiltinFnIdImport:
3403 case BuiltinFnIdCImport:
3404 case BuiltinFnIdErrName:
3405 case BuiltinFnIdBreakpoint:
3406 case BuiltinFnIdReturnAddress:
3407 case BuiltinFnIdFrameAddress:
3408 case BuiltinFnIdEmbedFile:
3409 case BuiltinFnIdCmpExchange:
3410 case BuiltinFnIdFence:
3411 case BuiltinFnIdDivExact:
3412 case BuiltinFnIdTruncate:
3413 case BuiltinFnIdIntType:
3414 case BuiltinFnIdSetFnTest:
3415 case BuiltinFnIdSetFnVisible:
3416 case BuiltinFnIdSetFnStaticEval:
3417 case BuiltinFnIdSetFnNoInline:
3418 case BuiltinFnIdSetDebugSafety:
3419 zig_panic("TODO analyze more builtin functions");
3420 }
3421 zig_unreachable();
3422}
3423
3424static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
3425 IrInstructionUnreachable *unreachable_instruction)
3426{
3427 return ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base)->type_entry;
3428}
3429
3430static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
3431 ZigList<IrBasicBlock*> new_incoming_blocks = {0};
3432 ZigList<IrInstruction*> new_incoming_values = {0};
3433
3434 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
3435 IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
3436 if (predecessor->ref_count == 0)
3437 continue;
3438
3439 assert(predecessor->other);
3440 new_incoming_blocks.append(predecessor->other);
3441
3442 IrInstruction *old_value = phi_instruction->incoming_values[i];
3443 assert(old_value);
3444 new_incoming_values.append(old_value->other);
3445 }
3446 assert(new_incoming_blocks.length != 0);
3447
3448 if (new_incoming_blocks.length == 1) {
3449 IrInstruction *first_value = new_incoming_values.at(0);
3450 phi_instruction->base.other = first_value;
3451 return first_value->type_entry;
3452 }
3453
3454 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &phi_instruction->base,
3455 new_incoming_values.items, new_incoming_values.length);
3456 if (resolved_type->id == TypeTableEntryIdInvalid)
3457 return resolved_type;
3458
3459 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
3460 new_incoming_blocks.items, new_incoming_values.items);
3461 return resolved_type;
3462}
29433463
2944static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {3464static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
2945 switch (instruction->id) {3465 switch (instruction->id) {
...@@ -2957,13 +3477,21 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -2957,13 +3477,21 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
2957 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);3477 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
2958 case IrInstructionIdCall:3478 case IrInstructionIdCall:
2959 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);3479 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
2960 case IrInstructionIdCondBr:
2961 case IrInstructionIdBr:3480 case IrInstructionIdBr:
2962 case IrInstructionIdSwitchBr:3481 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
3482 case IrInstructionIdCondBr:
3483 return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction);
3484 case IrInstructionIdBuiltinCall:
3485 return ir_analyze_instruction_builtin_call(ira, (IrInstructionBuiltinCall *)instruction);
3486 case IrInstructionIdUnreachable:
3487 return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction);
2963 case IrInstructionIdPhi:3488 case IrInstructionIdPhi:
3489 return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
3490 case IrInstructionIdSwitchBr:
2964 case IrInstructionIdStoreVar:3491 case IrInstructionIdStoreVar:
2965 case IrInstructionIdBuiltinCall:
2966 case IrInstructionIdCast:3492 case IrInstructionIdCast:
3493 case IrInstructionIdContainerInitList:
3494 case IrInstructionIdContainerInitFields:
2967 zig_panic("TODO analyze more instructions");3495 zig_panic("TODO analyze more instructions");
2968 }3496 }
2969 zig_unreachable();3497 zig_unreachable();
...@@ -3000,25 +3528,106 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -3000,25 +3528,106 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
3000 ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count);3528 ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count);
30013529
3002 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;3530 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
3531 for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) {
3532 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(bb_i);
3533 if (ira->old_irb.current_basic_block->ref_count == 0)
3534 continue;
30033535
3004 ira->new_irb.current_basic_block = ir_build_basic_block(&ira->new_irb, "Entry");3536 ira->new_irb.current_basic_block = ir_get_new_bb(ira, ira->old_irb.current_basic_block);
3005 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0);
3006
3007 ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block;
3008 ira->old_irb.current_basic_block->other = ira->new_irb.current_basic_block;
30093537
3538 return_type = ira->codegen->builtin_types.entry_void;
30103539
3011 for (size_t i = 0; i < ira->old_irb.current_basic_block->instruction_list.length; i += 1) {3540 for (size_t instr_i = 0; instr_i < ira->old_irb.current_basic_block->instruction_list.length; instr_i += 1) {
3012 IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(i);3541 IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(instr_i);
3013 if (return_type->id == TypeTableEntryIdUnreachable) {3542 if (return_type->id == TypeTableEntryIdUnreachable) {
3014 add_node_error(ira->codegen, first_executing_node(instruction->source_node),3543 // TODO
3015 buf_sprintf("unreachable code"));3544 //add_node_error(ira->codegen, first_executing_node(instruction->source_node),
3016 break;3545 // buf_sprintf("unreachable code"));
3546 break;
3547 }
3548 bool is_last = (instr_i == ira->old_irb.current_basic_block->instruction_list.length - 1);
3549 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3550 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
3017 }3551 }
3018 bool is_last = (i == ira->old_irb.current_basic_block->instruction_list.length - 1);
3019 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3020 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
3021 }3552 }
30223553
3554 // Give entry block a ref
3555 ir_ref_bb(ira->new_irb.exec->basic_block_list.at(0));
3556
3023 return return_type;3557 return return_type;
3024}3558}
3559
3560static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) {
3561 switch (call_instruction->fn->id) {
3562 case BuiltinFnIdInvalid:
3563 zig_unreachable();
3564 case BuiltinFnIdMemcpy:
3565 case BuiltinFnIdMemset:
3566 case BuiltinFnIdAddWithOverflow:
3567 case BuiltinFnIdSubWithOverflow:
3568 case BuiltinFnIdMulWithOverflow:
3569 case BuiltinFnIdShlWithOverflow:
3570 case BuiltinFnIdCInclude:
3571 case BuiltinFnIdCDefine:
3572 case BuiltinFnIdCUndef:
3573 case BuiltinFnIdImport:
3574 case BuiltinFnIdCImport:
3575 case BuiltinFnIdBreakpoint:
3576 case BuiltinFnIdEmbedFile:
3577 case BuiltinFnIdCmpExchange:
3578 case BuiltinFnIdFence:
3579 case BuiltinFnIdUnreachable:
3580 case BuiltinFnIdSetFnTest:
3581 case BuiltinFnIdSetFnVisible:
3582 case BuiltinFnIdSetFnStaticEval:
3583 case BuiltinFnIdSetFnNoInline:
3584 case BuiltinFnIdSetDebugSafety:
3585 return true;
3586 case BuiltinFnIdSizeof:
3587 case BuiltinFnIdAlignof:
3588 case BuiltinFnIdMaxValue:
3589 case BuiltinFnIdMinValue:
3590 case BuiltinFnIdMemberCount:
3591 case BuiltinFnIdTypeof:
3592 case BuiltinFnIdCompileVar:
3593 case BuiltinFnIdCompileErr:
3594 case BuiltinFnIdConstEval:
3595 case BuiltinFnIdCtz:
3596 case BuiltinFnIdClz:
3597 case BuiltinFnIdErrName:
3598 case BuiltinFnIdReturnAddress:
3599 case BuiltinFnIdFrameAddress:
3600 case BuiltinFnIdDivExact:
3601 case BuiltinFnIdTruncate:
3602 case BuiltinFnIdIntType:
3603 return false;
3604 }
3605 zig_unreachable();
3606}
3607
3608bool ir_has_side_effects(IrInstruction *instruction) {
3609 switch (instruction->id) {
3610 case IrInstructionIdInvalid:
3611 zig_unreachable();
3612 case IrInstructionIdBr:
3613 case IrInstructionIdCondBr:
3614 case IrInstructionIdSwitchBr:
3615 case IrInstructionIdStoreVar:
3616 case IrInstructionIdCall:
3617 case IrInstructionIdReturn:
3618 case IrInstructionIdUnreachable:
3619 return true;
3620 case IrInstructionIdPhi:
3621 case IrInstructionIdUnOp:
3622 case IrInstructionIdBinOp:
3623 case IrInstructionIdLoadVar:
3624 case IrInstructionIdConst:
3625 case IrInstructionIdCast:
3626 case IrInstructionIdContainerInitList:
3627 case IrInstructionIdContainerInitFields:
3628 return false;
3629 case IrInstructionIdBuiltinCall:
3630 return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction);
3631 }
3632 zig_unreachable();
3633}
src/ir.hpp+2
...@@ -16,4 +16,6 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);...@@ -16,4 +16,6 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
17 TypeTableEntry *expected_type);17 TypeTableEntry *expected_type);
1818
19bool ir_has_side_effects(IrInstruction *instruction);
20
19#endif21#endif
src/ir_print.cpp+105-55
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1#include "ir.hpp"
1#include "ir_print.hpp"2#include "ir_print.hpp"
23
3struct IrPrint {4struct IrPrint {
...@@ -14,49 +15,46 @@ static void ir_print_indent(IrPrint *irp) {...@@ -14,49 +15,46 @@ static void ir_print_indent(IrPrint *irp) {
1415
15static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {16static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
16 ir_print_indent(irp);17 ir_print_indent(irp);
17 fprintf(irp->f, "#%-3zu| ", instruction->debug_id);18 const char *type_name = instruction->type_entry ? buf_ptr(&instruction->type_entry->name) : "(unknown)";
19 const char *ref_count = ir_has_side_effects(instruction) ?
20 "-" : buf_ptr(buf_sprintf("%zu", instruction->ref_count));
21 fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);
18}22}
1923
20static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {24static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
21 ir_print_prefix(irp, &return_instruction->base);25 TypeTableEntry *type_entry = instruction->type_entry;
22 assert(return_instruction->value);
23 fprintf(irp->f, "return #%zu\n", return_instruction->value->debug_id);
24}
25
26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
27 ir_print_prefix(irp, &const_instruction->base);
28 TypeTableEntry *type_entry = const_instruction->base.type_entry;
29 fprintf(irp->f, "%s ", buf_ptr(&type_entry->name));
30 switch (type_entry->id) {26 switch (type_entry->id) {
31 case TypeTableEntryIdInvalid:27 case TypeTableEntryIdInvalid:
32 zig_unreachable();28 zig_unreachable();
33 case TypeTableEntryIdVoid:29 case TypeTableEntryIdVoid:
34 fprintf(irp->f, "%s\n", "void");30 fprintf(irp->f, "{}");
35 break;31 break;
36 case TypeTableEntryIdNumLitFloat:32 case TypeTableEntryIdNumLitFloat:
37 fprintf(irp->f, "%f\n", const_instruction->base.static_value.data.x_bignum.data.x_float);33 fprintf(irp->f, "%f", instruction->static_value.data.x_bignum.data.x_float);
38 break;34 break;
39 case TypeTableEntryIdNumLitInt:35 case TypeTableEntryIdNumLitInt:
40 {36 {
41 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;37 BigNum *bignum = &instruction->static_value.data.x_bignum;
42 const char *negative_str = bignum->is_negative ? "-" : "";38 const char *negative_str = bignum->is_negative ? "-" : "";
43 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);39 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
44 break;40 break;
45 }41 }
46 case TypeTableEntryIdMetaType:42 case TypeTableEntryIdMetaType:
47 fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));43 fprintf(irp->f, "%s", buf_ptr(&instruction->static_value.data.x_type->name));
48 break;44 break;
49 case TypeTableEntryIdInt:45 case TypeTableEntryIdInt:
50 {46 {
51 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;47 BigNum *bignum = &instruction->static_value.data.x_bignum;
52 assert(bignum->kind == BigNumKindInt);48 assert(bignum->kind == BigNumKindInt);
53 const char *negative_str = bignum->is_negative ? "-" : "";49 const char *negative_str = bignum->is_negative ? "-" : "";
54 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);50 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
55 }51 }
56 break;52 break;
53 case TypeTableEntryIdUnreachable:
54 fprintf(irp->f, "@unreachable()");
55 break;
57 case TypeTableEntryIdVar:56 case TypeTableEntryIdVar:
58 case TypeTableEntryIdBool:57 case TypeTableEntryIdBool:
59 case TypeTableEntryIdUnreachable:
60 case TypeTableEntryIdFloat:58 case TypeTableEntryIdFloat:
61 case TypeTableEntryIdPointer:59 case TypeTableEntryIdPointer:
62 case TypeTableEntryIdArray:60 case TypeTableEntryIdArray:
...@@ -77,6 +75,27 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)...@@ -77,6 +75,27 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
77 }75 }
78}76}
7977
78static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
79 if (instruction->static_value.ok) {
80 ir_print_const_instruction(irp, instruction);
81 } else {
82 fprintf(irp->f, "#%zu", instruction->debug_id);
83 }
84}
85
86static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
87 fprintf(irp->f, "$%s_%zu", bb->name_hint, bb->debug_id);
88}
89
90static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
91 assert(return_instruction->value);
92 fprintf(irp->f, "return ");
93 ir_print_other_instruction(irp, return_instruction->value);
94}
95
96static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
97 ir_print_const_instruction(irp, &const_instruction->base);
98}
8099
81static const char *ir_bin_op_id_str(IrBinOp op_id) {100static const char *ir_bin_op_id_str(IrBinOp op_id) {
82 switch (op_id) {101 switch (op_id) {
...@@ -169,87 +188,108 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {...@@ -169,87 +188,108 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
169}188}
170189
171static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {190static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
172 ir_print_prefix(irp, &un_op_instruction->base);191 fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
173 fprintf(irp->f, "%s #%zu\n",192 ir_print_other_instruction(irp, un_op_instruction->value);
174 ir_un_op_id_str(un_op_instruction->op_id),
175 un_op_instruction->value->debug_id);
176}193}
177194
178static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {195static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
179 ir_print_prefix(irp, &bin_op_instruction->base);196 ir_print_other_instruction(irp, bin_op_instruction->op1);
180 fprintf(irp->f, "#%zu %s #%zu\n",197 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
181 bin_op_instruction->op1->debug_id,198 ir_print_other_instruction(irp, bin_op_instruction->op2);
182 ir_bin_op_id_str(bin_op_instruction->op_id),
183 bin_op_instruction->op2->debug_id);
184}199}
185200
186static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {201static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
187 ir_print_prefix(irp, &load_var_instruction->base);202 fprintf(irp->f, "%s", buf_ptr(&load_var_instruction->var->name));
188 fprintf(irp->f, "%s\n",
189 buf_ptr(&load_var_instruction->var->name));
190}203}
191204
192static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {205static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
193 ir_print_prefix(irp, &cast_instruction->base);206 fprintf(irp->f, "cast ");
194 fprintf(irp->f, "cast #%zu to #%zu\n",207 ir_print_other_instruction(irp, cast_instruction->value);
195 cast_instruction->value->debug_id,208 fprintf(irp->f, " to ");
196 cast_instruction->dest_type->debug_id);209 ir_print_other_instruction(irp, cast_instruction->dest_type);
197}210}
198211
199static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {212static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
200 ir_print_prefix(irp, &call_instruction->base);213 ir_print_other_instruction(irp, call_instruction->fn);
201 fprintf(irp->f, "#%zu(", call_instruction->fn->debug_id);214 fprintf(irp->f, "(");
202 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {215 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
203 IrInstruction *arg = call_instruction->args[i];216 IrInstruction *arg = call_instruction->args[i];
204 if (i != 0)217 if (i != 0)
205 fprintf(irp->f, ", ");218 fprintf(irp->f, ", ");
206 fprintf(irp->f, "#%zu", arg->debug_id);219 ir_print_other_instruction(irp, arg);
207 }220 }
208 fprintf(irp->f, ")\n");221 fprintf(irp->f, ")");
209}222}
210223
211static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {224static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {
212 ir_print_prefix(irp, &call_instruction->base);
213 fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));225 fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));
214 for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {226 for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {
215 IrInstruction *arg = call_instruction->args[i];227 IrInstruction *arg = call_instruction->args[i];
216 if (i != 0)228 if (i != 0)
217 fprintf(irp->f, ", ");229 fprintf(irp->f, ", ");
218 fprintf(irp->f, "#%zu", arg->debug_id);230 ir_print_other_instruction(irp, arg);
219 }231 }
220 fprintf(irp->f, ")\n");232 fprintf(irp->f, ")");
221}233}
222234
223235
224static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {236static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
225 ir_print_prefix(irp, &cond_br_instruction->base);237 fprintf(irp->f, "if (");
226 fprintf(irp->f, "if #%zu then $%s_%zu else $%s_%zu\n",238 ir_print_other_instruction(irp, cond_br_instruction->condition);
227 cond_br_instruction->condition->debug_id,239 fprintf(irp->f, ") ");
228 cond_br_instruction->then_block->name_hint, cond_br_instruction->then_block->debug_id,240 ir_print_other_block(irp, cond_br_instruction->then_block);
229 cond_br_instruction->else_block->name_hint, cond_br_instruction->else_block->debug_id);241 fprintf(irp->f, " else ");
242 ir_print_other_block(irp, cond_br_instruction->else_block);
230}243}
231244
232static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {245static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
233 ir_print_prefix(irp, &br_instruction->base);246 fprintf(irp->f, "goto ");
234 fprintf(irp->f, "goto $%s_%zu\n",247 ir_print_other_block(irp, br_instruction->dest_block);
235 br_instruction->dest_block->name_hint, br_instruction->dest_block->debug_id);
236}248}
237249
238static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {250static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
239 ir_print_prefix(irp, &phi_instruction->base);
240 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {251 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
241 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];252 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
242 IrInstruction *incoming_value = phi_instruction->incoming_values[i];253 IrInstruction *incoming_value = phi_instruction->incoming_values[i];
243 if (i != 0)254 if (i != 0)
244 fprintf(irp->f, " ");255 fprintf(irp->f, " ");
245 fprintf(irp->f, "$%s_%zu:#%zu",256 ir_print_other_block(irp, incoming_block);
246 incoming_block->name_hint, incoming_block->debug_id,257 fprintf(irp->f, ":");
247 incoming_value->debug_id);258 ir_print_other_instruction(irp, incoming_value);
248 }259 }
249 fprintf(irp->f, "\n");260}
261
262static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
263 ir_print_other_instruction(irp, instruction->container_type);
264 fprintf(irp->f, "{");
265 for (size_t i = 0; i < instruction->item_count; i += 1) {
266 IrInstruction *item = instruction->items[i];
267 if (i != 0)
268 fprintf(irp->f, ", ");
269 ir_print_other_instruction(irp, item);
270 }
271 fprintf(irp->f, "}");
272}
273
274static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
275 ir_print_other_instruction(irp, instruction->container_type);
276 fprintf(irp->f, "{");
277 for (size_t i = 0; i < instruction->field_count; i += 1) {
278 Buf *name = instruction->field_names[i];
279 IrInstruction *field_value = instruction->field_values[i];
280 const char *comma = (i == 0) ? "" : ", ";
281 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(name));
282 ir_print_other_instruction(irp, field_value);
283 }
284 fprintf(irp->f, "}");
285}
286
287static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
288 fprintf(irp->f, "unreachable");
250}289}
251290
252static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {291static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
292 ir_print_prefix(irp, instruction);
253 switch (instruction->id) {293 switch (instruction->id) {
254 case IrInstructionIdInvalid:294 case IrInstructionIdInvalid:
255 zig_unreachable();295 zig_unreachable();
...@@ -286,10 +326,20 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -286,10 +326,20 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
286 case IrInstructionIdPhi:326 case IrInstructionIdPhi:
287 ir_print_phi(irp, (IrInstructionPhi *)instruction);327 ir_print_phi(irp, (IrInstructionPhi *)instruction);
288 break;328 break;
329 case IrInstructionIdContainerInitList:
330 ir_print_container_init_list(irp, (IrInstructionContainerInitList *)instruction);
331 break;
332 case IrInstructionIdContainerInitFields:
333 ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
334 break;
335 case IrInstructionIdUnreachable:
336 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
337 break;
289 case IrInstructionIdSwitchBr:338 case IrInstructionIdSwitchBr:
290 case IrInstructionIdStoreVar:339 case IrInstructionIdStoreVar:
291 zig_panic("TODO print more IR instructions");340 zig_panic("TODO print more IR instructions");
292 }341 }
342 fprintf(irp->f, "\n");
293}343}
294344
295void ir_print(FILE *f, IrExecutable *executable, int indent_size) {345void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
src/parser.cpp+9-11
...@@ -1912,14 +1912,11 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand...@@ -1912,14 +1912,11 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand
1912 return node;1912 return node;
1913}1913}
19141914
1915//static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {1915static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
1916// AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token);1916 AstNode *node = ast_create_node(pc, NodeTypeBlock, token);
1917// node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token);1917 normalize_parent_ptrs(node);
1918// node->data.container_init_expr.kind = ContainerInitKindArray;1918 return node;
1919// node->data.container_init_expr.type->data.symbol_expr.symbol = pc->void_buf;1919}
1920// normalize_parent_ptrs(node);
1921// return node;
1922//}
19231920
1924/*1921/*
1925Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)1922Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
...@@ -1961,12 +1958,13 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -1961,12 +1958,13 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
1961 semicolon_expected = !statement_node;1958 semicolon_expected = !statement_node;
1962 if (!statement_node) {1959 if (!statement_node) {
1963 statement_node = ast_parse_non_block_expr(pc, token_index, false);1960 statement_node = ast_parse_non_block_expr(pc, token_index, false);
1961 if (!statement_node) {
1962 statement_node = ast_create_void_expr(pc, last_token);
1963 }
1964 }1964 }
1965 }1965 }
1966 }1966 }
1967 if (statement_node) {1967 node->data.block.statements.append(statement_node);
1968 node->data.block.statements.append(statement_node);
1969 }
19701968
1971 last_token = &pc->tokens->at(*token_index);1969 last_token = &pc->tokens->at(*token_index);
1972 if (last_token->id == TokenIdRBrace) {1970 if (last_token->id == TokenIdRBrace) {