authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-09 23:21:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-09 23:21:02-05:00
log9d19b8d66e5eb26ec739ce74b0635270cebf6343
treeee856044ffbc4adc199f94a0cceda4b5894d5051
parentb8379b4c5b702badf15f668ad30369f4370e4490

IR: move unused codegen code to commented out in bottom of ir.cpp


2 files changed, 2080 insertions(+), 2247 deletions(-)

src/codegen.cpp+89-2246
......@@ -22,7 +22,6 @@
2222#include <stdio.h>
2323#include <errno.h>
2424
25
2625static void init_darwin_native(CodeGen *g) {
2726 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");
2827 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");
......@@ -227,27 +226,8 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) {
227226 g->linker_rdynamic = rdynamic;
228227}
229228
230static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
231static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node, TypeTableEntry **out_type_entry);
232static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue);
233static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
234 bool unwrap_maybe, LLVMValueRef *init_val, TypeTableEntry **init_val_type, bool var_is_ptr);
235static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
236 LLVMValueRef target_ref, LLVMValueRef value,
237 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
238static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
239static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
240 TypeTableEntry *type_entry, bool exact);
241229static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
242230
243static TypeTableEntry *get_type_for_type_node(AstNode *node) {
244 Expr *expr = get_resolved_expr(node);
245 assert(expr->type_entry->id == TypeTableEntryIdMetaType);
246 ConstExprValue *const_val = &expr->const_val;
247 assert(const_val->ok);
248 return const_val->data.x_type;
249}
250
251231static void set_debug_source_node(CodeGen *g, AstNode *node) {
252232 assert(node->block_context);
253233 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
......@@ -257,10 +237,6 @@ static void clear_debug_source_node(CodeGen *g) {
257237 ZigLLVMClearCurrentDebugLocation(g->builder);
258238}
259239
260static TypeTableEntry *get_expr_type(AstNode *node) {
261 return get_resolved_expr(node)->type_entry;
262}
263
264240enum AddSubMul {
265241 AddSubMulAdd = 0,
266242 AddSubMulSub = 1,
......@@ -329,24 +305,6 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, TypeTableEntry *type_entry,
329305 return *fn;
330306}
331307
332static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
333 // [0-ctz,1-clz][0-8,1-16,2-32,3-64]
334 size_t index0 = (fn_id == BuiltinFnIdCtz) ? 0 : 1;
335 size_t index1 = bits_index(int_type->data.integral.bit_count);
336 LLVMValueRef *fn = &g->int_builtin_fns[index0][index1];
337 if (!*fn) {
338 const char *fn_name = (fn_id == BuiltinFnIdCtz) ? "cttz" : "ctlz";
339 Buf *llvm_name = buf_sprintf("llvm.%s.i%zu", fn_name, int_type->data.integral.bit_count);
340 LLVMTypeRef param_types[] = {
341 int_type->type_ref,
342 LLVMInt1Type(),
343 };
344 LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, 2, false);
345 *fn = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
346 }
347 return *fn;
348}
349
350308static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntry *type) {
351309 if (handle_is_ptr(type)) {
352310 return ptr;
......@@ -413,349 +371,6 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
413371 LLVMPositionBuilderAtEnd(g->builder, ok_block);
414372}
415373
416static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {
417 assert(node->type == NodeTypeFnCallExpr);
418 assert(g->generate_error_name_table);
419
420 if (g->error_decls.length == 1) {
421 LLVMBuildUnreachable(g->builder);
422 return nullptr;
423 }
424
425
426 AstNode *err_val_node = node->data.fn_call_expr.params.at(0);
427 LLVMValueRef err_val = gen_expr(g, err_val_node);
428
429 if (want_debug_safety(g, node)) {
430 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
431 LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
432 add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
433 }
434
435 LLVMValueRef indices[] = {
436 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
437 err_val,
438 };
439 return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, "");
440}
441
442static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
443 switch (atomic_order) {
444 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
445 case AtomicOrderMonotonic: return LLVMAtomicOrderingMonotonic;
446 case AtomicOrderAcquire: return LLVMAtomicOrderingAcquire;
447 case AtomicOrderRelease: return LLVMAtomicOrderingRelease;
448 case AtomicOrderAcqRel: return LLVMAtomicOrderingAcquireRelease;
449 case AtomicOrderSeqCst: return LLVMAtomicOrderingSequentiallyConsistent;
450 }
451 zig_unreachable();
452}
453
454static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {
455 assert(node->type == NodeTypeFnCallExpr);
456
457 AstNode *ptr_arg = node->data.fn_call_expr.params.at(0);
458 AstNode *cmp_arg = node->data.fn_call_expr.params.at(1);
459 AstNode *new_arg = node->data.fn_call_expr.params.at(2);
460 AstNode *success_order_arg = node->data.fn_call_expr.params.at(3);
461 AstNode *failure_order_arg = node->data.fn_call_expr.params.at(4);
462
463 LLVMValueRef ptr_val = gen_expr(g, ptr_arg);
464 LLVMValueRef cmp_val = gen_expr(g, cmp_arg);
465 LLVMValueRef new_val = gen_expr(g, new_arg);
466
467 ConstExprValue *success_order_val = &get_resolved_expr(success_order_arg)->const_val;
468 ConstExprValue *failure_order_val = &get_resolved_expr(failure_order_arg)->const_val;
469
470 assert(success_order_val->ok);
471 assert(failure_order_val->ok);
472
473 LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering((AtomicOrder)success_order_val->data.x_enum.tag);
474 LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering((AtomicOrder)failure_order_val->data.x_enum.tag);
475
476 LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
477 success_order, failure_order);
478
479 return LLVMBuildExtractValue(g->builder, result_val, 1, "");
480}
481
482static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {
483 assert(node->type == NodeTypeFnCallExpr);
484
485 AstNode *atomic_order_arg = node->data.fn_call_expr.params.at(0);
486 ConstExprValue *atomic_order_val = &get_resolved_expr(atomic_order_arg)->const_val;
487
488 assert(atomic_order_val->ok);
489
490 LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering((AtomicOrder)atomic_order_val->data.x_enum.tag);
491
492 LLVMBuildFence(g->builder, atomic_order, false, "");
493 return nullptr;
494}
495
496static LLVMValueRef gen_div_exact(CodeGen *g, AstNode *node) {
497 assert(node->type == NodeTypeFnCallExpr);
498
499 AstNode *op1_node = node->data.fn_call_expr.params.at(0);
500 AstNode *op2_node = node->data.fn_call_expr.params.at(1);
501
502 LLVMValueRef op1_val = gen_expr(g, op1_node);
503 LLVMValueRef op2_val = gen_expr(g, op2_node);
504
505 return gen_div(g, node, op1_val, op2_val, get_expr_type(op1_node), true);
506}
507
508static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
509 assert(node->type == NodeTypeFnCallExpr);
510
511 TypeTableEntry *dest_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
512 AstNode *src_node = node->data.fn_call_expr.params.at(1);
513
514 LLVMValueRef src_val = gen_expr(g, src_node);
515
516 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
517}
518
519static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
520 assert(node->type == NodeTypeFnCallExpr);
521
522 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
523 assert(fn_call_param_count == 4);
524
525 TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
526 assert(int_type->id == TypeTableEntryIdInt);
527
528 LLVMValueRef val1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
529 LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
530 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
531
532 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
533 LLVMValueRef orig_val;
534 if (int_type->data.integral.is_signed) {
535 orig_val = LLVMBuildAShr(g->builder, result, val2, "");
536 } else {
537 orig_val = LLVMBuildLShr(g->builder, result, val2, "");
538 }
539 LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, val1, orig_val, "");
540
541 LLVMBuildStore(g->builder, result, ptr_result);
542
543 return overflow_bit;
544}
545
546static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
547 assert(node->type == NodeTypeFnCallExpr);
548 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
549 assert(fn_ref_expr->type == NodeTypeSymbol);
550 BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
551
552 switch (builtin_fn->id) {
553 case BuiltinFnIdInvalid:
554 case BuiltinFnIdTypeof:
555 case BuiltinFnIdCInclude:
556 case BuiltinFnIdCDefine:
557 case BuiltinFnIdCUndef:
558 case BuiltinFnIdImport:
559 case BuiltinFnIdCImport:
560 case BuiltinFnIdCompileErr:
561 case BuiltinFnIdIntType:
562 zig_unreachable();
563 case BuiltinFnIdCtz:
564 case BuiltinFnIdClz:
565 {
566 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
567 assert(fn_call_param_count == 2);
568 TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
569 assert(int_type->id == TypeTableEntryIdInt);
570 LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, builtin_fn->id);
571 LLVMValueRef operand = gen_expr(g, node->data.fn_call_expr.params.at(1));
572 LLVMValueRef params[] {
573 operand,
574 LLVMConstNull(LLVMInt1Type()),
575 };
576 return LLVMBuildCall(g->builder, fn_val, params, 2, "");
577 }
578 case BuiltinFnIdAddWithOverflow:
579 case BuiltinFnIdSubWithOverflow:
580 case BuiltinFnIdMulWithOverflow:
581 {
582 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
583 assert(fn_call_param_count == 4);
584
585 TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
586 AddSubMul add_sub_mul;
587 if (builtin_fn->id == BuiltinFnIdAddWithOverflow) {
588 add_sub_mul = AddSubMulAdd;
589 } else if (builtin_fn->id == BuiltinFnIdSubWithOverflow) {
590 add_sub_mul = AddSubMulSub;
591 } else if (builtin_fn->id == BuiltinFnIdMulWithOverflow) {
592 add_sub_mul = AddSubMulMul;
593 } else {
594 zig_unreachable();
595 }
596 LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
597
598 LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
599 LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
600 LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
601
602 LLVMValueRef params[] = {
603 op1,
604 op2,
605 };
606
607 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
608 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
609 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
610 LLVMBuildStore(g->builder, result, ptr_result);
611
612 return overflow_bit;
613 }
614 case BuiltinFnIdShlWithOverflow:
615 return gen_shl_with_overflow(g, node);
616 case BuiltinFnIdMemcpy:
617 {
618 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
619 assert(fn_call_param_count == 3);
620
621 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
622 TypeTableEntry *dest_type = get_expr_type(dest_node);
623
624 LLVMValueRef dest_ptr = gen_expr(g, dest_node);
625 LLVMValueRef src_ptr = gen_expr(g, node->data.fn_call_expr.params.at(1));
626 LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
627
628 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
629
630 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
631 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
632
633 uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
634
635 LLVMValueRef params[] = {
636 dest_ptr_casted, // dest pointer
637 src_ptr_casted, // source pointer
638 len_val, // byte count
639 LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
640 LLVMConstNull(LLVMInt1Type()), // is volatile
641 };
642
643 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
644 return nullptr;
645 }
646 case BuiltinFnIdMemset:
647 {
648 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
649 assert(fn_call_param_count == 3);
650
651 AstNode *dest_node = node->data.fn_call_expr.params.at(0);
652 TypeTableEntry *dest_type = get_expr_type(dest_node);
653
654 LLVMValueRef dest_ptr = gen_expr(g, dest_node);
655 LLVMValueRef char_val = gen_expr(g, node->data.fn_call_expr.params.at(1));
656 LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
657
658 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
659
660 LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
661
662 uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
663
664 LLVMValueRef params[] = {
665 dest_ptr_casted, // dest pointer
666 char_val, // source pointer
667 len_val, // byte count
668 LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
669 LLVMConstNull(LLVMInt1Type()), // is volatile
670 };
671
672 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
673 return nullptr;
674 }
675 case BuiltinFnIdSizeof:
676 case BuiltinFnIdAlignof:
677 case BuiltinFnIdMinValue:
678 case BuiltinFnIdMaxValue:
679 case BuiltinFnIdMemberCount:
680 case BuiltinFnIdConstEval:
681 case BuiltinFnIdEmbedFile:
682 // caught by constant expression eval codegen
683 zig_unreachable();
684 case BuiltinFnIdCompileVar:
685 return nullptr;
686 case BuiltinFnIdErrName:
687 return gen_err_name(g, node);
688 case BuiltinFnIdBreakpoint:
689 return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
690 case BuiltinFnIdFrameAddress:
691 case BuiltinFnIdReturnAddress:
692 {
693 LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
694 return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
695 }
696 case BuiltinFnIdCmpExchange:
697 return gen_cmp_exchange(g, node);
698 case BuiltinFnIdFence:
699 return gen_fence(g, node);
700 case BuiltinFnIdDivExact:
701 return gen_div_exact(g, node);
702 case BuiltinFnIdTruncate:
703 return gen_truncate(g, node);
704 case BuiltinFnIdUnreachable:
705 zig_panic("moved to ir render");
706 case BuiltinFnIdSetFnTest:
707 case BuiltinFnIdSetFnVisible:
708 case BuiltinFnIdSetFnStaticEval:
709 case BuiltinFnIdSetFnNoInline:
710 case BuiltinFnIdSetDebugSafety:
711 // do nothing
712 return nullptr;
713 }
714 zig_unreachable();
715}
716
717static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
718 AstNode *arg_node)
719{
720 assert(node->type == NodeTypeFieldAccessExpr);
721
722 uint64_t value = node->data.field_access_expr.type_enum_field->value;
723 LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
724 LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
725
726 if (enum_type->data.enumeration.gen_field_count == 0) {
727 return tag_value;
728 } else {
729 TypeTableEntry *arg_node_type = nullptr;
730 LLVMValueRef new_union_val = gen_expr(g, arg_node);
731 if (arg_node) {
732 arg_node_type = get_expr_type(arg_node);
733 } else {
734 arg_node_type = g->builtin_types.entry_void;
735 }
736
737 LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
738
739 // populate the new tag value
740 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
741 LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
742
743 if (arg_node_type->id != TypeTableEntryIdVoid) {
744 // populate the union value
745 TypeTableEntry *union_val_type = get_expr_type(arg_node);
746 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
747 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
748 LLVMPointerType(union_val_type->type_ref, 0), "");
749
750 gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val,
751 union_val_type, union_val_type);
752
753 }
754
755 return tmp_struct_ptr;
756 }
757}
758
759374static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeTableEntry *actual_type_non_canon,
760375 TypeTableEntry *wanted_type_non_canon, LLVMValueRef expr_val)
761376{
......@@ -839,111 +454,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
839454 }
840455}
841456
842static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
843 assert(node->type == NodeTypeFnCallExpr);
844
845 if (node->data.fn_call_expr.is_builtin) {
846 return gen_builtin_fn_call_expr(g, node);
847 }
848
849 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
850 TypeTableEntry *struct_type = nullptr;
851 AstNode *first_param_expr = nullptr;
852
853 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
854 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
855 fn_ref_expr->data.field_access_expr.is_member_fn)
856 {
857 first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
858 struct_type = get_expr_type(first_param_expr);
859 }
860
861 TypeTableEntry *fn_type;
862 LLVMValueRef fn_val;
863 AstNode *generic_proto_node;
864 if (fn_table_entry) {
865 fn_val = fn_table_entry->fn_value;
866 fn_type = fn_table_entry->type_entry;
867 generic_proto_node = fn_table_entry->proto_node->data.fn_proto.generic_proto_node;
868 } else {
869 fn_val = gen_expr(g, fn_ref_expr);
870 fn_type = get_expr_type(fn_ref_expr);
871 generic_proto_node = nullptr;
872 }
873
874 TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
875
876 bool ret_has_bits = type_has_bits(src_return_type);
877
878 size_t fn_call_param_count = node->data.fn_call_expr.params.length;
879 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
880 size_t actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);
881 bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
882
883 // don't really include void values
884 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
885
886 size_t gen_param_index = 0;
887 if (first_arg_ret) {
888 gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr;
889 gen_param_index += 1;
890 }
891 if (struct_type && type_has_bits(struct_type)) {
892 gen_param_values[gen_param_index] = gen_expr(g, first_param_expr);
893 assert(gen_param_values[gen_param_index]);
894 gen_param_index += 1;
895 }
896
897 for (size_t call_i = 0; call_i < fn_call_param_count; call_i += 1) {
898 size_t proto_i = call_i + (struct_type ? 1 : 0);
899 if (generic_proto_node &&
900 generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
901 {
902 continue;
903 }
904 AstNode *expr_node = node->data.fn_call_expr.params.at(call_i);
905 LLVMValueRef param_value = gen_expr(g, expr_node);
906 assert(param_value);
907 TypeTableEntry *param_type = get_expr_type(expr_node);
908 if (is_var_args || type_has_bits(param_type)) {
909 gen_param_values[gen_param_index] = param_value;
910 gen_param_index += 1;
911 }
912 }
913
914 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
915 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
916
917 if (src_return_type->id == TypeTableEntryIdUnreachable) {
918 return LLVMBuildUnreachable(g->builder);
919 } else if (!ret_has_bits) {
920 return nullptr;
921 } else if (first_arg_ret) {
922 return node->data.fn_call_expr.tmp_ptr;
923 } else {
924 return result;
925 }
926}
927
928static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
929 TypeTableEntry *type_entry = get_expr_type(node);
930
931 LLVMValueRef array_ptr;
932 if (node->type == NodeTypeFieldAccessExpr) {
933 array_ptr = gen_field_access_expr(g, node, true);
934 if (type_entry->id == TypeTableEntryIdPointer) {
935 // we have a double pointer so we must dereference it once
936 array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
937 }
938 } else {
939 array_ptr = gen_expr(g, node);
940 }
941
942 assert(!array_ptr || LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
943
944 return array_ptr;
945}
946
947457static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMValueRef array_ptr,
948458 TypeTableEntry *array_type, LLVMValueRef subscript_value)
949459{
......@@ -993,358 +503,78 @@ static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMVal
993503 }
994504}
995505
996static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
997 assert(node->type == NodeTypeArrayAccessExpr);
998
999 AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
1000 TypeTableEntry *array_type = get_expr_type(array_expr_node);
506static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
507 LLVMValueRef val1, LLVMValueRef val2)
508{
509 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
510 LLVMValueRef params[] = {
511 val1,
512 val2,
513 };
514 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
515 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
516 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
517 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
518 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
519 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
1001520
1002 LLVMValueRef array_ptr = gen_array_base_ptr(g, array_expr_node);
521 LLVMPositionBuilderAtEnd(g->builder, fail_block);
522 gen_debug_safety_crash(g);
1003523
1004 LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);
1005 return gen_array_elem_ptr(g, node, array_ptr, array_type, subscript_value);
524 LLVMPositionBuilderAtEnd(g->builder, ok_block);
525 return result;
1006526}
1007527
1008static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) {
1009 assert(node->type == NodeTypeFieldAccessExpr);
1010
1011 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
1012
1013 *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
1014 if (!type_has_bits(*out_type_entry)) {
1015 return nullptr;
1016 }
528static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
529 LLVMValueRef val1, LLVMValueRef val2)
530{
531 // for unsigned left shifting, we do the wrapping shift, then logically shift
532 // right the same number of bits
533 // if the values don't match, we have an overflow
534 // for signed left shifting we do the same except arithmetic shift right
1017535
1018 LLVMValueRef struct_ptr;
1019 if (struct_expr_node->type == NodeTypeSymbol) {
1020 VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable;
1021 assert(var);
536 assert(type_entry->id == TypeTableEntryIdInt);
1022537
1023 if (var->type->id == TypeTableEntryIdPointer) {
1024 struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");
1025 } else {
1026 struct_ptr = var->value_ref;
1027 }
1028 } else if (struct_expr_node->type == NodeTypeFieldAccessExpr) {
1029 struct_ptr = gen_field_access_expr(g, struct_expr_node, true);
1030 TypeTableEntry *field_type = get_expr_type(struct_expr_node);
1031 if (field_type->id == TypeTableEntryIdPointer) {
1032 // we have a double pointer so we must dereference it once
1033 struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
1034 }
538 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
539 LLVMValueRef orig_val;
540 if (type_entry->data.integral.is_signed) {
541 orig_val = LLVMBuildAShr(g->builder, result, val2, "");
1035542 } else {
1036 struct_ptr = gen_expr(g, struct_expr_node);
543 orig_val = LLVMBuildLShr(g->builder, result, val2, "");
1037544 }
545 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
1038546
1039 assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
1040 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);
547 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
548 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
549 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1041550
1042 size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
1043 assert(gen_field_index != SIZE_MAX);
551 LLVMPositionBuilderAtEnd(g->builder, fail_block);
552 gen_debug_safety_crash(g);
1044553
1045 return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
554 LLVMPositionBuilderAtEnd(g->builder, ok_block);
555 return result;
1046556}
1047557
1048static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
1049 assert(node->type == NodeTypeSliceExpr);
1050
1051 AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
1052 TypeTableEntry *array_type = get_expr_type(array_ref_node);
1053
1054 LLVMValueRef tmp_struct_ptr = node->data.slice_expr.resolved_struct_val_expr.ptr;
1055 LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
558static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
559 TypeTableEntry *type_entry, bool exact)
560{
1056561
1057 if (array_type->id == TypeTableEntryIdArray) {
1058 LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
1059 LLVMValueRef end_val;
1060 if (node->data.slice_expr.end) {
1061 end_val = gen_expr(g, node->data.slice_expr.end);
562 if (want_debug_safety(g, source_node)) {
563 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
564 LLVMValueRef is_zero_bit;
565 if (type_entry->id == TypeTableEntryIdInt) {
566 is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
567 } else if (type_entry->id == TypeTableEntryIdFloat) {
568 is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
1062569 } else {
1063 end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false);
570 zig_unreachable();
1064571 }
572 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk");
573 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail");
574 LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);
1065575
1066 if (want_debug_safety(g, node)) {
1067 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1068 if (node->data.slice_expr.end) {
1069 LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1070 array_type->data.array.len, false);
1071 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
1072 }
1073 }
1074
1075 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
1076 LLVMValueRef indices[] = {
1077 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
1078 start_val,
1079 };
1080 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
1081 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
1082
1083 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
1084 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1085 LLVMBuildStore(g->builder, len_value, len_field_ptr);
1086
1087 return tmp_struct_ptr;
1088 } else if (array_type->id == TypeTableEntryIdPointer) {
1089 LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
1090 LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);
1091
1092 if (want_debug_safety(g, node)) {
1093 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1094 }
1095
1096 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
1097 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
1098 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
1099
1100 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
1101 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1102 LLVMBuildStore(g->builder, len_value, len_field_ptr);
1103
1104 return tmp_struct_ptr;
1105 } else if (array_type->id == TypeTableEntryIdStruct) {
1106 assert(array_type->data.structure.is_slice);
1107 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
1108 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
1109
1110 size_t ptr_index = array_type->data.structure.fields[0].gen_index;
1111 assert(ptr_index != SIZE_MAX);
1112 size_t len_index = array_type->data.structure.fields[1].gen_index;
1113 assert(len_index != SIZE_MAX);
1114
1115 LLVMValueRef prev_end = nullptr;
1116 if (!node->data.slice_expr.end || want_debug_safety(g, node)) {
1117 LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
1118 prev_end = LLVMBuildLoad(g->builder, src_len_ptr, "");
1119 }
1120
1121 LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
1122 LLVMValueRef end_val;
1123 if (node->data.slice_expr.end) {
1124 end_val = gen_expr(g, node->data.slice_expr.end);
1125 } else {
1126 end_val = prev_end;
1127 }
1128
1129 if (want_debug_safety(g, node)) {
1130 assert(prev_end);
1131 add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
1132 if (node->data.slice_expr.end) {
1133 add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);
1134 }
1135 }
1136
1137 LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
1138 LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
1139 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");
1140 LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, len_index, "");
1141 LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
1142
1143 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, len_index, "");
1144 LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
1145 LLVMBuildStore(g->builder, len_value, len_field_ptr);
1146
1147 return tmp_struct_ptr;
1148 } else {
1149 zig_unreachable();
1150 }
1151}
1152
1153
1154static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
1155 assert(node->type == NodeTypeArrayAccessExpr);
1156
1157 LLVMValueRef ptr = gen_array_ptr(g, node);
1158 TypeTableEntry *child_type;
1159 TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
1160 if (array_type->id == TypeTableEntryIdPointer) {
1161 child_type = array_type->data.pointer.child_type;
1162 } else if (array_type->id == TypeTableEntryIdStruct) {
1163 assert(array_type->data.structure.is_slice);
1164 TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
1165 assert(child_ptr_type->id == TypeTableEntryIdPointer);
1166 child_type = child_ptr_type->data.pointer.child_type;
1167 } else if (array_type->id == TypeTableEntryIdArray) {
1168 child_type = array_type->data.array.child_type;
1169 } else {
1170 zig_unreachable();
1171 }
1172
1173 if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
1174 return ptr;
1175 } else {
1176 return LLVMBuildLoad(g->builder, ptr, "");
1177 }
1178}
1179
1180static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTableEntry *variable) {
1181 if (!type_has_bits(variable->type)) {
1182 return nullptr;
1183 } else {
1184 assert(variable->value_ref);
1185 return get_handle_value(g, variable->value_ref, variable->type);
1186 }
1187}
1188
1189static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
1190 assert(node->type == NodeTypeFieldAccessExpr);
1191
1192 AstNode *struct_expr = node->data.field_access_expr.struct_expr;
1193 TypeTableEntry *struct_type = get_expr_type(struct_expr);
1194
1195 if (struct_type->id == TypeTableEntryIdArray) {
1196 Buf *name = node->data.field_access_expr.field_name;
1197 assert(buf_eql_str(name, "len"));
1198 return LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1199 struct_type->data.array.len, false);
1200 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
1201 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
1202 {
1203 TypeTableEntry *type_entry;
1204 LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
1205 if (is_lvalue || handle_is_ptr(type_entry)) {
1206 return ptr;
1207 } else {
1208 return LLVMBuildLoad(g->builder, ptr, "");
1209 }
1210 } else if (struct_type->id == TypeTableEntryIdMetaType) {
1211 assert(!is_lvalue);
1212 TypeTableEntry *child_type = get_type_for_type_node(struct_expr);
1213 if (child_type->id == TypeTableEntryIdEnum) {
1214 return gen_enum_value_expr(g, node, child_type, nullptr);
1215 } else {
1216 zig_unreachable();
1217 }
1218 } else if (struct_type->id == TypeTableEntryIdNamespace) {
1219 VariableTableEntry *variable = get_resolved_expr(node)->variable;
1220 assert(variable);
1221 return gen_variable(g, node, variable);
1222 } else {
1223 zig_unreachable();
1224 }
1225}
1226
1227static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
1228 TypeTableEntry **out_type_entry)
1229{
1230 LLVMValueRef target_ref;
1231
1232 if (node->type == NodeTypeSymbol) {
1233 VariableTableEntry *var = get_resolved_expr(node)->variable;
1234 assert(var);
1235
1236 *out_type_entry = var->type;
1237 target_ref = var->value_ref;
1238 } else if (node->type == NodeTypeArrayAccessExpr) {
1239 TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
1240 if (array_type->id == TypeTableEntryIdArray) {
1241 *out_type_entry = array_type->data.array.child_type;
1242 target_ref = gen_array_ptr(g, node);
1243 } else if (array_type->id == TypeTableEntryIdPointer) {
1244 *out_type_entry = array_type->data.pointer.child_type;
1245 target_ref = gen_array_ptr(g, node);
1246 } else if (array_type->id == TypeTableEntryIdStruct) {
1247 assert(array_type->data.structure.is_slice);
1248 *out_type_entry = array_type->data.structure.fields[0].type_entry->data.pointer.child_type;
1249 target_ref = gen_array_ptr(g, node);
1250 } else {
1251 zig_unreachable();
1252 }
1253 } else if (node->type == NodeTypeFieldAccessExpr) {
1254 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
1255 TypeTableEntry *struct_type = get_expr_type(struct_expr_node);
1256 if (struct_type->id == TypeTableEntryIdNamespace) {
1257 target_ref = gen_field_access_expr(g, node, true);
1258 *out_type_entry = get_expr_type(node);
1259 } else {
1260 target_ref = gen_field_ptr(g, node, out_type_entry);
1261 }
1262 } else if (node->type == NodeTypePrefixOpExpr) {
1263 assert(node->data.prefix_op_expr.prefix_op == PrefixOpDereference);
1264 AstNode *target_expr = node->data.prefix_op_expr.primary_expr;
1265 TypeTableEntry *type_entry = get_expr_type(target_expr);
1266 assert(type_entry->id == TypeTableEntryIdPointer);
1267 *out_type_entry = type_entry->data.pointer.child_type;
1268 return gen_expr(g, target_expr);
1269 } else {
1270 zig_panic("bad assign target");
1271 }
1272
1273 return target_ref;
1274}
1275
1276static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
1277 LLVMValueRef val1, LLVMValueRef val2)
1278{
1279 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
1280 LLVMValueRef params[] = {
1281 val1,
1282 val2,
1283 };
1284 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
1285 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1286 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1287 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
1288 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
1289 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
1290
1291 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1292 gen_debug_safety_crash(g);
1293
1294 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1295 return result;
1296}
1297
1298static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
1299 LLVMValueRef val1, LLVMValueRef val2)
1300{
1301 // for unsigned left shifting, we do the wrapping shift, then logically shift
1302 // right the same number of bits
1303 // if the values don't match, we have an overflow
1304 // for signed left shifting we do the same except arithmetic shift right
1305
1306 assert(type_entry->id == TypeTableEntryIdInt);
1307
1308 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
1309 LLVMValueRef orig_val;
1310 if (type_entry->data.integral.is_signed) {
1311 orig_val = LLVMBuildAShr(g->builder, result, val2, "");
1312 } else {
1313 orig_val = LLVMBuildLShr(g->builder, result, val2, "");
1314 }
1315 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
1316
1317 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
1318 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
1319 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1320
1321 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1322 gen_debug_safety_crash(g);
1323
1324 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1325 return result;
1326}
1327
1328static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
1329 TypeTableEntry *type_entry, bool exact)
1330{
1331
1332 if (want_debug_safety(g, source_node)) {
1333 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
1334 LLVMValueRef is_zero_bit;
1335 if (type_entry->id == TypeTableEntryIdInt) {
1336 is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
1337 } else if (type_entry->id == TypeTableEntryIdFloat) {
1338 is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
1339 } else {
1340 zig_unreachable();
1341 }
1342 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk");
1343 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail");
1344 LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);
1345
1346 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1347 gen_debug_safety_crash(g);
576 LLVMPositionBuilderAtEnd(g->builder, fail_block);
577 gen_debug_safety_crash(g);
1348578
1349579 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1350580 }
......@@ -1529,18 +759,6 @@ static LLVMValueRef gen_arithmetic_bin_op(CodeGen *g, AstNode *source_node,
1529759 }
1530760 zig_unreachable();
1531761}
1532static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
1533 assert(node->type == NodeTypeBinOpExpr);
1534
1535 LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
1536 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
1537
1538 TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
1539 TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
1540 return gen_arithmetic_bin_op(g, node, val1, val2, op1_type, op2_type, node->data.bin_op_expr.bin_op);
1541
1542}
1543
1544762static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) {
1545763 switch (cmp_op) {
1546764 case IrBinOpCmpEq:
......@@ -1579,63 +797,6 @@ static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) {
1579797 }
1580798}
1581799
1582static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
1583 assert(node->type == NodeTypeBinOpExpr);
1584
1585 LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
1586 LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
1587
1588 // block for when val1 == true
1589 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue");
1590 // block for when val1 == false (don't even evaluate the second part)
1591 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
1592
1593 LLVMBuildCondBr(g->builder, val1, true_block, false_block);
1594
1595 LLVMPositionBuilderAtEnd(g->builder, true_block);
1596 LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
1597 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
1598
1599 LLVMBuildBr(g->builder, false_block);
1600
1601 LLVMPositionBuilderAtEnd(g->builder, false_block);
1602 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
1603 LLVMValueRef incoming_values[2] = {val1, val2};
1604 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
1605 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
1606
1607 return phi;
1608}
1609
1610static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
1611 assert(expr_node->type == NodeTypeBinOpExpr);
1612
1613 LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1);
1614 LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
1615
1616 // block for when val1 == false
1617 LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse");
1618 // block for when val1 == true (don't even evaluate the second part)
1619 LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
1620
1621 LLVMBuildCondBr(g->builder, val1, true_block, false_block);
1622
1623 LLVMPositionBuilderAtEnd(g->builder, false_block);
1624 LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);
1625
1626 LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
1627
1628 LLVMBuildBr(g->builder, true_block);
1629
1630 LLVMPositionBuilderAtEnd(g->builder, true_block);
1631 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
1632 LLVMValueRef incoming_values[2] = {val1, val2};
1633 LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
1634 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
1635
1636 return phi;
1637}
1638
1639800static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef dest,
1640801 TypeTableEntry *type_entry)
1641802{
......@@ -1650,632 +811,53 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, LLVMValueRef src, LLVMValueRef
1650811 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
1651812 uint64_t align_bytes = get_memcpy_align(g, type_entry);
1652813 assert(size_bytes > 0);
1653 assert(align_bytes > 0);
1654
1655 LLVMValueRef params[] = {
1656 dest_ptr, // dest pointer
1657 src_ptr, // source pointer
1658 LLVMConstInt(usize->type_ref, size_bytes, false),
1659 LLVMConstInt(LLVMInt32Type(), align_bytes, false),
1660 LLVMConstNull(LLVMInt1Type()), // is volatile
1661 };
1662
1663 return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");
1664}
1665
1666static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
1667 LLVMValueRef target_ref, LLVMValueRef value,
1668 TypeTableEntry *op1_type, TypeTableEntry *op2_type)
1669{
1670 if (!type_has_bits(op1_type)) {
1671 return nullptr;
1672 }
1673 if (handle_is_ptr(op1_type)) {
1674 assert(op1_type == op2_type);
1675 assert(bin_op == BinOpTypeAssign);
1676
1677 return gen_struct_memcpy(g, value, target_ref, op1_type);
1678 }
1679
1680 if (bin_op != BinOpTypeAssign) {
1681 assert(source_node->type == NodeTypeBinOpExpr);
1682 LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");
1683
1684 value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);
1685 }
1686
1687 LLVMBuildStore(g->builder, value, target_ref);
1688 return nullptr;
1689}
1690
1691static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
1692 assert(node->type == NodeTypeBinOpExpr);
1693
1694 AstNode *lhs_node = node->data.bin_op_expr.op1;
1695
1696 TypeTableEntry *op1_type;
1697
1698 LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type);
1699
1700 TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
1701
1702 LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);
1703
1704 gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type);
1705 return nullptr;
1706}
1707
1708static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref) {
1709 TypeTableEntry *type_entry = get_expr_type(node);
1710 assert(type_entry->id == TypeTableEntryIdMaybe);
1711 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1712 if (child_type->id == TypeTableEntryIdPointer ||
1713 child_type->id == TypeTableEntryIdFn)
1714 {
1715 return maybe_struct_ref;
1716 } else {
1717 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");
1718 return get_handle_value(g, maybe_field_ptr, child_type);
1719 }
1720}
1721
1722static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
1723 assert(node->type == NodeTypeBinOpExpr);
1724 assert(node->data.bin_op_expr.bin_op == BinOpTypeUnwrapMaybe);
1725
1726 AstNode *op1_node = node->data.bin_op_expr.op1;
1727 AstNode *op2_node = node->data.bin_op_expr.op2;
1728
1729 LLVMValueRef maybe_struct_ref = gen_expr(g, op1_node);
1730
1731 TypeTableEntry *maybe_type = get_expr_type(op1_node);
1732 assert(maybe_type->id == TypeTableEntryIdMaybe);
1733 TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
1734
1735 LLVMValueRef cond_value;
1736 if (child_type->id == TypeTableEntryIdPointer ||
1737 child_type->id == TypeTableEntryIdFn)
1738 {
1739 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
1740 LLVMConstNull(child_type->type_ref), "");
1741 } else {
1742 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");
1743 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
1744 }
1745
1746 LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNonNull");
1747 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNull");
1748 LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEnd");
1749
1750 bool null_reachable = get_expr_type(op2_node)->id != TypeTableEntryIdUnreachable;
1751
1752 LLVMBuildCondBr(g->builder, cond_value, non_null_block, null_block);
1753
1754 LLVMPositionBuilderAtEnd(g->builder, non_null_block);
1755 LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);
1756 LLVMBuildBr(g->builder, end_block);
1757 LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
1758
1759 LLVMPositionBuilderAtEnd(g->builder, null_block);
1760 LLVMValueRef null_result = gen_expr(g, op2_node);
1761 if (null_reachable) {
1762 LLVMBuildBr(g->builder, end_block);
1763 }
1764 LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
1765
1766 LLVMPositionBuilderAtEnd(g->builder, end_block);
1767 if (null_reachable) {
1768 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
1769 LLVMValueRef incoming_values[2] = {non_null_result, null_result};
1770 LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
1771 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
1772 return phi;
1773 } else {
1774 return non_null_result;
1775 }
1776
1777 return nullptr;
1778}
1779
1780static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) {
1781 switch (node->data.bin_op_expr.bin_op) {
1782 case BinOpTypeInvalid:
1783 case BinOpTypeArrayCat:
1784 case BinOpTypeArrayMult:
1785 zig_unreachable();
1786 case BinOpTypeAssign:
1787 case BinOpTypeAssignTimes:
1788 case BinOpTypeAssignTimesWrap:
1789 case BinOpTypeAssignDiv:
1790 case BinOpTypeAssignMod:
1791 case BinOpTypeAssignPlus:
1792 case BinOpTypeAssignPlusWrap:
1793 case BinOpTypeAssignMinus:
1794 case BinOpTypeAssignMinusWrap:
1795 case BinOpTypeAssignBitShiftLeft:
1796 case BinOpTypeAssignBitShiftLeftWrap:
1797 case BinOpTypeAssignBitShiftRight:
1798 case BinOpTypeAssignBitAnd:
1799 case BinOpTypeAssignBitXor:
1800 case BinOpTypeAssignBitOr:
1801 case BinOpTypeAssignBoolAnd:
1802 case BinOpTypeAssignBoolOr:
1803 return gen_assign_expr(g, node);
1804 case BinOpTypeBoolOr:
1805 return gen_bool_or_expr(g, node);
1806 case BinOpTypeBoolAnd:
1807 return gen_bool_and_expr(g, node);
1808 case BinOpTypeCmpEq:
1809 case BinOpTypeCmpNotEq:
1810 case BinOpTypeCmpLessThan:
1811 case BinOpTypeCmpGreaterThan:
1812 case BinOpTypeCmpLessOrEq:
1813 case BinOpTypeCmpGreaterOrEq:
1814 zig_panic("moved to ir_render");
1815 case BinOpTypeUnwrapMaybe:
1816 return gen_unwrap_maybe_expr(g, node);
1817 case BinOpTypeBinOr:
1818 case BinOpTypeBinXor:
1819 case BinOpTypeBinAnd:
1820 case BinOpTypeBitShiftLeft:
1821 case BinOpTypeBitShiftLeftWrap:
1822 case BinOpTypeBitShiftRight:
1823 case BinOpTypeAdd:
1824 case BinOpTypeAddWrap:
1825 case BinOpTypeSub:
1826 case BinOpTypeSubWrap:
1827 case BinOpTypeMult:
1828 case BinOpTypeMultWrap:
1829 case BinOpTypeDiv:
1830 case BinOpTypeMod:
1831 return gen_arithmetic_bin_op_expr(g, node);
1832 }
1833 zig_unreachable();
1834}
1835
1836static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
1837 assert(node->type == NodeTypeUnwrapErrorExpr);
1838
1839 AstNode *op1 = node->data.unwrap_err_expr.op1;
1840 AstNode *op2 = node->data.unwrap_err_expr.op2;
1841 VariableTableEntry *var = node->data.unwrap_err_expr.var;
1842
1843 LLVMValueRef expr_val = gen_expr(g, op1);
1844 TypeTableEntry *expr_type = get_expr_type(op1);
1845 TypeTableEntry *op2_type = get_expr_type(op2);
1846 assert(expr_type->id == TypeTableEntryIdErrorUnion);
1847 TypeTableEntry *child_type = expr_type->data.error.child_type;
1848 LLVMValueRef err_val;
1849 if (handle_is_ptr(expr_type)) {
1850 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1851 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
1852 } else {
1853 err_val = expr_val;
1854 }
1855 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
1856 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
1857
1858 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
1859 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
1860 LLVMBasicBlockRef end_block;
1861 bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable;
1862 bool have_end_block = err_reachable && type_has_bits(child_type);
1863 if (have_end_block) {
1864 end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd");
1865 }
1866
1867 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
1868
1869 LLVMPositionBuilderAtEnd(g->builder, err_block);
1870 if (var) {
1871 LLVMBuildStore(g->builder, err_val, var->value_ref);
1872 }
1873 LLVMValueRef err_result = gen_expr(g, op2);
1874 if (have_end_block) {
1875 LLVMBuildBr(g->builder, end_block);
1876 } else if (err_reachable) {
1877 LLVMBuildBr(g->builder, ok_block);
1878 }
1879
1880 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1881 if (!type_has_bits(child_type)) {
1882 return nullptr;
1883 }
1884 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1885 LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type);
1886
1887 if (!have_end_block) {
1888 return child_val;
1889 }
1890
1891 LLVMBuildBr(g->builder, end_block);
1892
1893 LLVMPositionBuilderAtEnd(g->builder, end_block);
1894 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(err_result), "");
1895 LLVMValueRef incoming_values[2] = {child_val, err_result};
1896 LLVMBasicBlockRef incoming_blocks[2] = {ok_block, err_block};
1897 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
1898 return phi;
1899}
1900
1901static void gen_defers_for_block(CodeGen *g, BlockContext *inner_block, BlockContext *outer_block,
1902 bool gen_error_defers, bool gen_maybe_defers)
1903{
1904 while (inner_block != outer_block) {
1905 if (inner_block->node->type == NodeTypeDefer &&
1906 ((inner_block->node->data.defer.kind == ReturnKindUnconditional) ||
1907 (gen_error_defers && inner_block->node->data.defer.kind == ReturnKindError) ||
1908 (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe)))
1909 {
1910 gen_expr(g, inner_block->node->data.defer.expr);
1911 }
1912 inner_block = inner_block->parent;
1913 }
1914}
1915
1916static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
1917 size_t result = 0;
1918 while (inner_block != outer_block) {
1919 if (inner_block->node->type == NodeTypeDefer &&
1920 (inner_block->node->data.defer.kind == ReturnKindError ||
1921 inner_block->node->data.defer.kind == ReturnKindMaybe))
1922 {
1923 result += 1;
1924 }
1925 inner_block = inner_block->parent;
1926 }
1927 return result;
1928}
1929
1930static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) {
1931 BlockContext *defer_inner_block = source_node->block_context;
1932 BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context;
1933 if (rk == ReturnKnowledgeUnknown) {
1934 if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
1935 // generate branching code that checks the return value and generates defers
1936 // if the return value is error
1937 zig_panic("TODO");
1938 }
1939 } else if (rk != ReturnKnowledgeSkipDefers) {
1940 gen_defers_for_block(g, defer_inner_block, defer_outer_block,
1941 rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
1942 }
1943
1944 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
1945 bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
1946 if (handle_is_ptr(return_type)) {
1947 if (is_extern) {
1948 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
1949 LLVMBuildRet(g->builder, by_val_value);
1950 } else {
1951 assert(g->cur_ret_ptr);
1952 gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
1953 LLVMBuildRetVoid(g->builder);
1954 }
1955 } else {
1956 LLVMBuildRet(g->builder, value);
1957 }
1958 return nullptr;
1959}
1960
1961static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
1962 assert(node->type == NodeTypeReturnExpr);
1963 AstNode *param_node = node->data.return_expr.expr;
1964 assert(param_node);
1965 LLVMValueRef value = gen_expr(g, param_node);
1966 TypeTableEntry *value_type = get_expr_type(param_node);
1967
1968 switch (node->data.return_expr.kind) {
1969 case ReturnKindUnconditional:
1970 {
1971 Expr *expr = get_resolved_expr(param_node);
1972 if (expr->const_val.ok) {
1973 if (value_type->id == TypeTableEntryIdErrorUnion) {
1974 if (expr->const_val.data.x_err.err) {
1975 expr->return_knowledge = ReturnKnowledgeKnownError;
1976 } else {
1977 expr->return_knowledge = ReturnKnowledgeKnownNonError;
1978 }
1979 } else if (value_type->id == TypeTableEntryIdMaybe) {
1980 if (expr->const_val.data.x_maybe) {
1981 expr->return_knowledge = ReturnKnowledgeKnownNonNull;
1982 } else {
1983 expr->return_knowledge = ReturnKnowledgeKnownNull;
1984 }
1985 }
1986 }
1987 return gen_return(g, node, value, expr->return_knowledge);
1988 }
1989 case ReturnKindError:
1990 {
1991 assert(value_type->id == TypeTableEntryIdErrorUnion);
1992 TypeTableEntry *child_type = value_type->data.error.child_type;
1993
1994 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
1995 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
1996
1997 LLVMValueRef err_val;
1998 if (type_has_bits(child_type)) {
1999 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
2000 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
2001 } else {
2002 err_val = value;
2003 }
2004 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
2005 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
2006 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
2007
2008 LLVMPositionBuilderAtEnd(g->builder, return_block);
2009 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2010 if (return_type->id == TypeTableEntryIdPureError) {
2011 gen_return(g, node, err_val, ReturnKnowledgeKnownError);
2012 } else if (return_type->id == TypeTableEntryIdErrorUnion) {
2013 if (type_has_bits(return_type->data.error.child_type)) {
2014 assert(g->cur_ret_ptr);
2015
2016 LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
2017 LLVMBuildStore(g->builder, err_val, tag_ptr);
2018 LLVMBuildRetVoid(g->builder);
2019 } else {
2020 gen_return(g, node, err_val, ReturnKnowledgeKnownError);
2021 }
2022 } else {
2023 zig_unreachable();
2024 }
2025
2026 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2027 if (type_has_bits(child_type)) {
2028 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
2029 return get_handle_value(g, val_ptr, child_type);
2030 } else {
2031 return nullptr;
2032 }
2033 }
2034 case ReturnKindMaybe:
2035 {
2036 assert(value_type->id == TypeTableEntryIdMaybe);
2037 TypeTableEntry *child_type = value_type->data.maybe.child_type;
2038
2039 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");
2040 LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");
2041
2042 LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
2043 LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");
2044
2045 LLVMValueRef zero = LLVMConstNull(LLVMInt1Type());
2046 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, is_non_null, zero, "");
2047 LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
2048
2049 LLVMPositionBuilderAtEnd(g->builder, return_block);
2050 TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2051 assert(return_type->id == TypeTableEntryIdMaybe);
2052 if (handle_is_ptr(return_type)) {
2053 assert(g->cur_ret_ptr);
2054
2055 LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");
2056 LLVMBuildStore(g->builder, zero, maybe_bit_ptr);
2057 LLVMBuildRetVoid(g->builder);
2058 } else {
2059 LLVMValueRef ret_zero_value = LLVMConstNull(return_type->type_ref);
2060 gen_return(g, node, ret_zero_value, ReturnKnowledgeKnownNull);
2061 }
2062
2063 LLVMPositionBuilderAtEnd(g->builder, continue_block);
2064 if (type_has_bits(child_type)) {
2065 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
2066 return get_handle_value(g, val_ptr, child_type);
2067 } else {
2068 return nullptr;
2069 }
2070 }
2071 }
2072 zig_unreachable();
2073}
2074
2075static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,
2076 AstNode *then_node, AstNode *else_node)
2077{
2078 assert(then_node);
2079 assert(else_node);
2080
2081 TypeTableEntry *then_type = get_expr_type(then_node);
2082 TypeTableEntry *else_type = get_expr_type(else_node);
2083
2084 bool use_then_value = type_has_bits(then_type);
2085 bool use_else_value = type_has_bits(else_type);
2086
2087 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
2088 LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else");
2089
2090 LLVMBasicBlockRef endif_block = nullptr;
2091 bool then_endif_reachable = then_type->id != TypeTableEntryIdUnreachable;
2092 bool else_endif_reachable = else_type->id != TypeTableEntryIdUnreachable;
2093 if (then_endif_reachable || else_endif_reachable) {
2094 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
2095 }
2096
2097 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
2098
2099 LLVMPositionBuilderAtEnd(g->builder, then_block);
2100 LLVMValueRef then_expr_result = gen_expr(g, then_node);
2101 if (then_endif_reachable) {
2102 clear_debug_source_node(g);
2103 LLVMBuildBr(g->builder, endif_block);
2104 }
2105 LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
2106
2107 LLVMPositionBuilderAtEnd(g->builder, else_block);
2108 LLVMValueRef else_expr_result = gen_expr(g, else_node);
2109 if (else_endif_reachable) {
2110 clear_debug_source_node(g);
2111 LLVMBuildBr(g->builder, endif_block);
2112 }
2113 LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
2114
2115 if (then_endif_reachable || else_endif_reachable) {
2116 LLVMPositionBuilderAtEnd(g->builder, endif_block);
2117 if (use_then_value && use_else_value) {
2118 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
2119 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
2120 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
2121 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
2122 return phi;
2123 } else if (use_then_value) {
2124 return then_expr_result;
2125 } else if (use_else_value) {
2126 return else_expr_result;
2127 }
2128 }
2129
2130 return nullptr;
2131}
2132
2133static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {
2134 assert(node->type == NodeTypeIfBoolExpr);
2135 assert(node->data.if_bool_expr.condition);
2136 assert(node->data.if_bool_expr.then_block);
2137
2138 ConstExprValue *const_val = &get_resolved_expr(node->data.if_bool_expr.condition)->const_val;
2139 if (const_val->ok) {
2140 if (const_val->data.x_bool) {
2141 return gen_expr(g, node->data.if_bool_expr.then_block);
2142 } else if (node->data.if_bool_expr.else_node) {
2143 return gen_expr(g, node->data.if_bool_expr.else_node);
2144 } else {
2145 return nullptr;
2146 }
2147 } else {
2148 LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition);
2149
2150 return gen_if_bool_expr_raw(g, node, cond_value,
2151 node->data.if_bool_expr.then_block,
2152 node->data.if_bool_expr.else_node);
2153 }
2154}
2155
2156static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) {
2157 BlockContext *block_context = var->block_context;
2158 AstNode *source_node = var->decl_node;
2159 ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(source_node->line + 1, source_node->column + 1,
2160 block_context->di_scope);
2161 ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc,
2162 LLVMGetInsertBlock(g->builder));
2163}
2164
2165static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTableEntry *variable, bool maybe_is_ptr,
2166 LLVMValueRef init_val, TypeTableEntry *child_type, AstNode *then_node)
2167{
2168 if (node->data.if_var_expr.var_is_ptr) {
2169 LLVMValueRef payload_ptr;
2170 if (maybe_is_ptr) {
2171 zig_panic("TODO");
2172 } else {
2173 payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
2174 }
2175 LLVMBuildStore(g->builder, payload_ptr, variable->value_ref);
2176 } else {
2177 LLVMValueRef payload_val;
2178 if (maybe_is_ptr) {
2179 payload_val = init_val;
2180 } else {
2181 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
2182 payload_val = get_handle_value(g, payload_ptr, child_type);
2183 }
2184 gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val,
2185 variable->type, child_type);
2186 }
2187 gen_var_debug_decl(g, variable);
2188
2189 return gen_expr(g, then_node);
2190}
2191
2192static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
2193 assert(node->type == NodeTypeIfVarExpr);
2194 assert(node->data.if_var_expr.var_decl.expr);
2195
2196 AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;
2197 VariableTableEntry *variable = var_decl->variable;
2198
2199 // test if value is the maybe state
2200 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
2201 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
2202
2203 LLVMValueRef init_val = gen_expr(g, var_decl->expr);
2204
2205
2206 AstNode *then_node = node->data.if_var_expr.then_block;
2207 AstNode *else_node = node->data.if_var_expr.else_node;
2208 bool maybe_is_ptr = child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
2209
2210 ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
2211 if (const_val->ok) {
2212 if (const_val->data.x_maybe) {
2213 return gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node);
2214 } else {
2215 return gen_expr(g, else_node);
2216 }
2217 }
2218
2219 LLVMValueRef cond_value;
2220 if (maybe_is_ptr) {
2221 cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
2222 } else {
2223 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
2224 cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
2225 }
2226
2227 TypeTableEntry *then_type = get_expr_type(then_node);
2228 TypeTableEntry *else_type = get_expr_type(else_node);
814 assert(align_bytes > 0);
2229815
2230 bool use_then_value = type_has_bits(then_type);
2231 bool use_else_value = type_has_bits(else_type);
816 LLVMValueRef params[] = {
817 dest_ptr, // dest pointer
818 src_ptr, // source pointer
819 LLVMConstInt(usize->type_ref, size_bytes, false),
820 LLVMConstInt(LLVMInt32Type(), align_bytes, false),
821 LLVMConstNull(LLVMInt1Type()), // is volatile
822 };
2232823
2233 LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeThen");
2234 LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeElse");
824 return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, "");
825}
2235826
2236 LLVMBasicBlockRef endif_block;
2237 bool then_endif_reachable = then_type->id != TypeTableEntryIdUnreachable;
2238 bool else_endif_reachable = else_type->id != TypeTableEntryIdUnreachable;
2239 if (then_endif_reachable || else_endif_reachable) {
2240 endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf");
827static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType bin_op,
828 LLVMValueRef target_ref, LLVMValueRef value,
829 TypeTableEntry *op1_type, TypeTableEntry *op2_type)
830{
831 if (!type_has_bits(op1_type)) {
832 return nullptr;
2241833 }
834 if (handle_is_ptr(op1_type)) {
835 assert(op1_type == op2_type);
836 assert(bin_op == BinOpTypeAssign);
2242837
2243 LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
2244
2245 LLVMPositionBuilderAtEnd(g->builder, then_block);
2246 LLVMValueRef then_expr_result = gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node);
2247
2248 if (then_endif_reachable) {
2249 LLVMBuildBr(g->builder, endif_block);
838 return gen_struct_memcpy(g, value, target_ref, op1_type);
2250839 }
2251 LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
2252840
841 if (bin_op != BinOpTypeAssign) {
842 assert(source_node->type == NodeTypeBinOpExpr);
843 LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, "");
2253844
2254 LLVMPositionBuilderAtEnd(g->builder, else_block);
2255 LLVMValueRef else_expr_result = gen_expr(g, else_node);
2256 if (else_endif_reachable) {
2257 LLVMBuildBr(g->builder, endif_block);
2258 }
2259 LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
2260
2261 if (then_endif_reachable || else_endif_reachable) {
2262 LLVMPositionBuilderAtEnd(g->builder, endif_block);
2263 if (use_then_value && use_else_value) {
2264 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
2265 LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
2266 LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
2267 LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
2268 return phi;
2269 } else if (use_then_value) {
2270 return then_expr_result;
2271 } else if (use_else_value) {
2272 return else_expr_result;
2273 }
845 value = gen_arithmetic_bin_op(g, source_node, left_value, value, op1_type, op2_type, bin_op);
2274846 }
2275847
848 LLVMBuildStore(g->builder, value, target_ref);
2276849 return nullptr;
2277850}
2278851
852static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) {
853 BlockContext *block_context = var->block_context;
854 AstNode *source_node = var->decl_node;
855 ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(source_node->line + 1, source_node->column + 1,
856 block_context->di_scope);
857 ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc,
858 LLVMGetInsertBlock(g->builder));
859}
860
2279861static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
2280862 if (!type_has_bits(instruction->type_entry))
2281863 return nullptr;
......@@ -3025,745 +1607,6 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
30251607 }
30261608}
30271609
3028static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
3029 assert(block_node->type == NodeTypeBlock);
3030
3031 LLVMValueRef return_value = nullptr;
3032 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
3033 AstNode *statement_node = block_node->data.block.statements.at(i);
3034 return_value = gen_expr(g, statement_node);
3035 }
3036
3037 bool end_unreachable = implicit_return_type && implicit_return_type->id == TypeTableEntryIdUnreachable;
3038 if (end_unreachable) {
3039 return nullptr;
3040 }
3041
3042 gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block,
3043 false, false);
3044
3045 if (implicit_return_type) {
3046 return gen_return(g, block_node, return_value, ReturnKnowledgeSkipDefers);
3047 } else {
3048 return return_value;
3049 }
3050}
3051
3052static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) {
3053 const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2;
3054 size_t len = tok->end - tok->start - 2;
3055 size_t result = 0;
3056 for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {
3057 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
3058 if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) {
3059 return result;
3060 }
3061 }
3062 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {
3063 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
3064 if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) {
3065 return result;
3066 }
3067 }
3068 return SIZE_MAX;
3069}
3070
3071static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
3072 assert(node->type == NodeTypeAsmExpr);
3073
3074 AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
3075
3076 Buf *src_template = asm_expr->asm_template;
3077
3078 Buf llvm_template = BUF_INIT;
3079 buf_resize(&llvm_template, 0);
3080
3081 for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
3082 AsmToken *asm_token = &asm_expr->token_list.at(token_i);
3083 switch (asm_token->id) {
3084 case AsmTokenIdTemplate:
3085 for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) {
3086 uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));
3087 if (c == '$') {
3088 buf_append_str(&llvm_template, "$$");
3089 } else {
3090 buf_append_char(&llvm_template, c);
3091 }
3092 }
3093 break;
3094 case AsmTokenIdPercent:
3095 buf_append_char(&llvm_template, '%');
3096 break;
3097 case AsmTokenIdVar:
3098 size_t index = find_asm_index(g, node, asm_token);
3099 assert(index < SIZE_MAX);
3100 buf_appendf(&llvm_template, "$%zu", index);
3101 break;
3102 }
3103 }
3104
3105 Buf constraint_buf = BUF_INIT;
3106 buf_resize(&constraint_buf, 0);
3107
3108 assert(asm_expr->return_count == 0 || asm_expr->return_count == 1);
3109
3110 size_t total_constraint_count = asm_expr->output_list.length +
3111 asm_expr->input_list.length +
3112 asm_expr->clobber_list.length;
3113 size_t input_and_output_count = asm_expr->output_list.length +
3114 asm_expr->input_list.length -
3115 asm_expr->return_count;
3116 size_t total_index = 0;
3117 size_t param_index = 0;
3118 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count);
3119 LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count);
3120 for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {
3121 AsmOutput *asm_output = asm_expr->output_list.at(i);
3122 bool is_return = (asm_output->return_type != nullptr);
3123 assert(*buf_ptr(asm_output->constraint) == '=');
3124 if (is_return) {
3125 buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
3126 } else {
3127 buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1);
3128 }
3129 if (total_index + 1 < total_constraint_count) {
3130 buf_append_char(&constraint_buf, ',');
3131 }
3132
3133 if (!is_return) {
3134 VariableTableEntry *variable = asm_output->variable;
3135 assert(variable);
3136 param_types[param_index] = LLVMTypeOf(variable->value_ref);
3137 param_values[param_index] = variable->value_ref;
3138 param_index += 1;
3139 }
3140 }
3141 for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
3142 AsmInput *asm_input = asm_expr->input_list.at(i);
3143 buf_append_buf(&constraint_buf, asm_input->constraint);
3144 if (total_index + 1 < total_constraint_count) {
3145 buf_append_char(&constraint_buf, ',');
3146 }
3147
3148 TypeTableEntry *expr_type = get_expr_type(asm_input->expr);
3149 param_types[param_index] = expr_type->type_ref;
3150 param_values[param_index] = gen_expr(g, asm_input->expr);
3151 }
3152 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
3153 Buf *clobber_buf = asm_expr->clobber_list.at(i);
3154 buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf));
3155 if (total_index + 1 < total_constraint_count) {
3156 buf_append_char(&constraint_buf, ',');
3157 }
3158 }
3159
3160 LLVMTypeRef ret_type;
3161 if (asm_expr->return_count == 0) {
3162 ret_type = LLVMVoidType();
3163 } else {
3164 ret_type = get_expr_type(node)->type_ref;
3165 }
3166 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false);
3167
3168 bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
3169 LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
3170 buf_ptr(&constraint_buf), is_volatile, false);
3171
3172 set_debug_source_node(g, node);
3173 return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
3174}
3175
3176static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
3177 assert(node->type == NodeTypeContainerInitExpr);
3178
3179 TypeTableEntry *type_entry = get_expr_type(node);
3180
3181
3182 if (node->data.container_init_expr.enum_type) {
3183 size_t param_count = node->data.container_init_expr.entries.length;
3184 AstNode *arg1_node;
3185 if (param_count == 1) {
3186 arg1_node = node->data.container_init_expr.entries.at(0);
3187 } else {
3188 assert(param_count == 0);
3189 arg1_node = nullptr;
3190 }
3191 return gen_enum_value_expr(g, node->data.container_init_expr.type,
3192 node->data.container_init_expr.enum_type, arg1_node);
3193 }
3194
3195
3196 if (type_entry->id == TypeTableEntryIdStruct) {
3197 assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
3198
3199 size_t src_field_count = type_entry->data.structure.src_field_count;
3200 assert(src_field_count == node->data.container_init_expr.entries.length);
3201
3202 StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
3203 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
3204
3205 for (size_t i = 0; i < src_field_count; i += 1) {
3206 AstNode *field_node = node->data.container_init_expr.entries.at(i);
3207 assert(field_node->type == NodeTypeStructValueField);
3208 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
3209 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
3210 continue;
3211 }
3212 assert(buf_eql_buf(type_struct_field->name, field_node->data.struct_val_field.name));
3213
3214 set_debug_source_node(g, field_node);
3215 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
3216 AstNode *expr_node = field_node->data.struct_val_field.expr;
3217 LLVMValueRef value = gen_expr(g, expr_node);
3218 gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value,
3219 type_struct_field->type_entry, get_expr_type(expr_node));
3220 }
3221
3222 return tmp_struct_ptr;
3223 } else if (type_entry->id == TypeTableEntryIdVoid) {
3224 assert(node->data.container_init_expr.entries.length == 0);
3225 return nullptr;
3226 } else if (type_entry->id == TypeTableEntryIdArray) {
3227 StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
3228 LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr;
3229
3230 size_t field_count = type_entry->data.array.len;
3231 assert(field_count == node->data.container_init_expr.entries.length);
3232
3233 TypeTableEntry *child_type = type_entry->data.array.child_type;
3234
3235 for (size_t i = 0; i < field_count; i += 1) {
3236 AstNode *field_node = node->data.container_init_expr.entries.at(i);
3237 LLVMValueRef elem_val = gen_expr(g, field_node);
3238
3239 LLVMValueRef indices[] = {
3240 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
3241 LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false),
3242 };
3243 set_debug_source_node(g, field_node);
3244 LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
3245 gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
3246 child_type, get_expr_type(field_node));
3247 }
3248
3249 return tmp_array_ptr;
3250 } else {
3251 zig_unreachable();
3252 }
3253}
3254
3255static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
3256 assert(node->type == NodeTypeWhileExpr);
3257 assert(node->data.while_expr.condition);
3258 assert(node->data.while_expr.body);
3259
3260 //AstNode *continue_expr_node = node->data.while_expr.continue_expr;
3261
3262 bool condition_always_true = node->data.while_expr.condition_always_true;
3263 //bool contains_break = node->data.while_expr.contains_break;
3264 if (condition_always_true) {
3265 // generate a forever loop
3266 zig_panic("TODO IR");
3267
3268 //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
3269 //LLVMBasicBlockRef continue_block = continue_expr_node ?
3270 // LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
3271 //LLVMBasicBlockRef end_block = nullptr;
3272 //if (contains_break) {
3273 // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
3274 //}
3275
3276 //set_debug_source_node(g, node);
3277 //LLVMBuildBr(g->builder, body_block);
3278
3279 //if (continue_expr_node) {
3280 // LLVMPositionBuilderAtEnd(g->builder, continue_block);
3281
3282 // gen_expr(g, continue_expr_node);
3283
3284 // set_debug_source_node(g, node);
3285 // LLVMBuildBr(g->builder, body_block);
3286 //}
3287
3288 //LLVMPositionBuilderAtEnd(g->builder, body_block);
3289 //g->break_block_stack.append(end_block);
3290 //g->continue_block_stack.append(continue_block);
3291 //gen_expr(g, node->data.while_expr.body);
3292 //g->break_block_stack.pop();
3293 //g->continue_block_stack.pop();
3294
3295 //if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
3296 // set_debug_source_node(g, node);
3297 // LLVMBuildBr(g->builder, continue_block);
3298 //}
3299
3300 //if (contains_break) {
3301 // LLVMPositionBuilderAtEnd(g->builder, end_block);
3302 //}
3303 } else {
3304 zig_panic("moved to ir.cpp");
3305 }
3306
3307 return nullptr;
3308}
3309
3310//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
3311// assert(node->type == NodeTypeBreak);
3312// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
3313//
3314// set_debug_source_node(g, node);
3315// return LLVMBuildBr(g->builder, dest_block);
3316//}
3317
3318//static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
3319// assert(node->type == NodeTypeContinue);
3320// LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
3321//
3322// set_debug_source_node(g, node);
3323// return LLVMBuildBr(g->builder, dest_block);
3324//}
3325
3326static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
3327 bool unwrap_maybe, LLVMValueRef *init_value, TypeTableEntry **expr_type, bool var_is_ptr)
3328{
3329 VariableTableEntry *variable = var_decl->variable;
3330
3331 assert(variable);
3332
3333 if (var_decl->expr) {
3334 *init_value = gen_expr(g, var_decl->expr);
3335 *expr_type = get_expr_type(var_decl->expr);
3336 }
3337 if (!type_has_bits(variable->type)) {
3338 return nullptr;
3339 }
3340
3341 bool have_init_expr = false;
3342 bool want_zeroes = false;
3343 if (var_decl->expr) {
3344 ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
3345 if (!const_val->ok || const_val->special == ConstValSpecialOther) {
3346 have_init_expr = true;
3347 }
3348 if (const_val->ok && const_val->special == ConstValSpecialZeroes) {
3349 want_zeroes = true;
3350 }
3351 }
3352 if (have_init_expr) {
3353 TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
3354 LLVMValueRef value;
3355 if (unwrap_maybe) {
3356 assert(var_decl->expr);
3357 assert(expr_type->id == TypeTableEntryIdMaybe);
3358 value = gen_unwrap_maybe(g, var_decl->expr, *init_value);
3359 expr_type = expr_type->data.maybe.child_type;
3360 } else {
3361 value = *init_value;
3362 }
3363 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
3364 value, variable->type, expr_type);
3365 } else {
3366 bool ignore_uninit = false;
3367 // handle runtime stack allocation
3368 if (var_decl->type) {
3369 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
3370 if (var_type->id == TypeTableEntryIdStruct &&
3371 var_type->data.structure.is_slice)
3372 {
3373 assert(var_decl->type->type == NodeTypeArrayType);
3374 AstNode *size_node = var_decl->type->data.array_type.size;
3375 if (size_node) {
3376 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
3377 if (!const_val->ok) {
3378 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
3379 assert(ptr_type->id == TypeTableEntryIdPointer);
3380 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
3381
3382 LLVMValueRef size_val = gen_expr(g, size_node);
3383
3384 set_debug_source_node(g, source_node);
3385 LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
3386 size_val, "");
3387
3388 size_t ptr_index = var_type->data.structure.fields[0].gen_index;
3389 assert(ptr_index != SIZE_MAX);
3390 size_t len_index = var_type->data.structure.fields[1].gen_index;
3391 assert(len_index != SIZE_MAX);
3392
3393 // store the freshly allocated pointer in the unknown size array struct
3394 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
3395 variable->value_ref, ptr_index, "");
3396 LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
3397
3398 // store the size in the len field
3399 LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
3400 variable->value_ref, len_index, "");
3401 LLVMBuildStore(g->builder, size_val, len_field_ptr);
3402
3403 // don't clobber what we just did with debug initialization
3404 ignore_uninit = true;
3405 }
3406 }
3407 }
3408 }
3409 bool want_safe = want_debug_safety(g, source_node);
3410 if (!ignore_uninit && (want_safe || want_zeroes)) {
3411 TypeTableEntry *usize = g->builtin_types.entry_usize;
3412 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, variable->type->type_ref);
3413 uint64_t align_bytes = get_memcpy_align(g, variable->type);
3414
3415 // memset uninitialized memory to 0xa
3416 set_debug_source_node(g, source_node);
3417 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3418 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), want_zeroes ? 0x00 : 0xaa, false);
3419 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
3420 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3421 LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false);
3422 LLVMValueRef params[] = {
3423 dest_ptr,
3424 fill_char,
3425 byte_count,
3426 align_in_bytes,
3427 LLVMConstNull(LLVMInt1Type()), // is volatile
3428 };
3429
3430 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
3431 }
3432 }
3433
3434 gen_var_debug_decl(g, variable);
3435 return nullptr;
3436}
3437
3438static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
3439 AstNode *init_expr = node->data.variable_declaration.expr;
3440 if (node->data.variable_declaration.is_const && init_expr) {
3441 TypeTableEntry *init_expr_type = get_expr_type(init_expr);
3442 if (init_expr_type->id == TypeTableEntryIdNumLitFloat ||
3443 init_expr_type->id == TypeTableEntryIdNumLitInt)
3444 {
3445 return nullptr;
3446 }
3447 }
3448
3449 LLVMValueRef init_val = nullptr;
3450 TypeTableEntry *init_val_type;
3451 return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type, false);
3452}
3453
3454static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
3455 assert(node->type == NodeTypeSymbol);
3456 VariableTableEntry *variable = get_resolved_expr(node)->variable;
3457 if (variable) {
3458 return gen_variable(g, node, variable);
3459 }
3460
3461 zig_unreachable();
3462}
3463
3464static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
3465 assert(node->type == NodeTypeSwitchExpr);
3466
3467 if (node->data.switch_expr.const_chosen_prong_index != SIZE_MAX) {
3468 AstNode *prong_node = node->data.switch_expr.prongs.at(node->data.switch_expr.const_chosen_prong_index);
3469 assert(prong_node->type == NodeTypeSwitchProng);
3470 AstNode *prong_expr = prong_node->data.switch_prong.expr;
3471 return gen_expr(g, prong_expr);
3472 }
3473
3474 TypeTableEntry *target_type = get_expr_type(node->data.switch_expr.expr);
3475 LLVMValueRef target_value_handle = gen_expr(g, node->data.switch_expr.expr);
3476 LLVMValueRef target_value;
3477 if (handle_is_ptr(target_type)) {
3478 if (target_type->id == TypeTableEntryIdEnum) {
3479 set_debug_source_node(g, node);
3480 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
3481 target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
3482 } else if (target_type->id == TypeTableEntryIdErrorUnion) {
3483 set_debug_source_node(g, node);
3484 LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
3485 target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
3486 } else {
3487 zig_unreachable();
3488 }
3489 } else {
3490 target_value = target_value_handle;
3491 }
3492
3493
3494 TypeTableEntry *switch_type = get_expr_type(node);
3495 bool result_has_bits = type_has_bits(switch_type);
3496 bool end_unreachable = (switch_type->id == TypeTableEntryIdUnreachable);
3497
3498 LLVMBasicBlockRef end_block = end_unreachable ?
3499 nullptr : LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchEnd");
3500 LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchElse");
3501 size_t prong_count = node->data.switch_expr.prongs.length;
3502
3503 set_debug_source_node(g, node);
3504 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, prong_count);
3505
3506 ZigList<LLVMValueRef> incoming_values = {0};
3507 ZigList<LLVMBasicBlockRef> incoming_blocks = {0};
3508
3509 AstNode *else_prong = nullptr;
3510 for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
3511 AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
3512 VariableTableEntry *prong_var = prong_node->data.switch_prong.var;
3513
3514 LLVMBasicBlockRef prong_block;
3515 if (prong_node->data.switch_prong.items.length == 0) {
3516 assert(!else_prong);
3517 else_prong = prong_node;
3518 prong_block = else_block;
3519 } else {
3520 prong_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchProng");
3521 size_t prong_item_count = prong_node->data.switch_prong.items.length;
3522 bool make_item_blocks = prong_var && prong_item_count > 1;
3523
3524 for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
3525 AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
3526
3527 assert(item_node->type != NodeTypeSwitchRange);
3528 LLVMValueRef val;
3529 if (target_type->id == TypeTableEntryIdEnum ||
3530 target_type->id == TypeTableEntryIdErrorUnion)
3531 {
3532 assert(item_node->type == NodeTypeSymbol);
3533 TypeEnumField *enum_field = nullptr;
3534 uint32_t err_value = 0;
3535 if (target_type->id == TypeTableEntryIdEnum) {
3536 enum_field = item_node->data.symbol_expr.enum_field;
3537 assert(enum_field);
3538 val = LLVMConstInt(target_type->data.enumeration.tag_type->type_ref,
3539 enum_field->value, false);
3540 } else if (target_type->id == TypeTableEntryIdErrorUnion) {
3541 err_value = item_node->data.symbol_expr.err_value;
3542 val = LLVMConstInt(g->err_tag_type->type_ref, err_value, false);
3543 } else {
3544 zig_unreachable();
3545 }
3546
3547 if (prong_var && type_has_bits(prong_var->type)) {
3548 LLVMBasicBlockRef item_block;
3549
3550 if (make_item_blocks) {
3551 item_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchProngItem");
3552 LLVMAddCase(switch_instr, val, item_block);
3553 LLVMPositionBuilderAtEnd(g->builder, item_block);
3554 } else {
3555 LLVMAddCase(switch_instr, val, prong_block);
3556 LLVMPositionBuilderAtEnd(g->builder, prong_block);
3557 }
3558
3559 AstNode *var_node = prong_node->data.switch_prong.var_symbol;
3560 set_debug_source_node(g, var_node);
3561 if (prong_node->data.switch_prong.var_is_target_expr) {
3562 gen_assign_raw(g, var_node, BinOpTypeAssign,
3563 prong_var->value_ref, target_value, prong_var->type, target_type);
3564 } else if (target_type->id == TypeTableEntryIdEnum) {
3565 assert(enum_field);
3566 assert(type_has_bits(enum_field->type_entry));
3567 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle,
3568 1, "");
3569 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
3570 LLVMPointerType(enum_field->type_entry->type_ref, 0), "");
3571 LLVMValueRef handle_val = get_handle_value(g, bitcasted_union_field_ptr,
3572 enum_field->type_entry);
3573
3574 gen_assign_raw(g, var_node, BinOpTypeAssign,
3575 prong_var->value_ref, handle_val, prong_var->type, enum_field->type_entry);
3576 } else if (target_type->id == TypeTableEntryIdErrorUnion) {
3577 if (err_value == 0) {
3578 // variable is the payload
3579 LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,
3580 target_value_handle, 1, "");
3581 LLVMValueRef handle_val = get_handle_value(g, err_payload_ptr, prong_var->type);
3582 gen_assign_raw(g, var_node, BinOpTypeAssign,
3583 prong_var->value_ref, handle_val, prong_var->type, prong_var->type);
3584 } else {
3585 // variable is the pure error value
3586 LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder,
3587 target_value_handle, 0, "");
3588 LLVMValueRef handle_val = LLVMBuildLoad(g->builder, err_tag_ptr, "");
3589 gen_assign_raw(g, var_node, BinOpTypeAssign,
3590 prong_var->value_ref, handle_val, prong_var->type, g->err_tag_type);
3591 }
3592 } else {
3593 zig_unreachable();
3594 }
3595 if (make_item_blocks) {
3596 set_debug_source_node(g, var_node);
3597 LLVMBuildBr(g->builder, prong_block);
3598 }
3599 } else {
3600 LLVMAddCase(switch_instr, val, prong_block);
3601 }
3602 } else {
3603 assert(get_resolved_expr(item_node)->const_val.ok);
3604 val = gen_expr(g, item_node);
3605 LLVMAddCase(switch_instr, val, prong_block);
3606 }
3607 }
3608 }
3609
3610 LLVMPositionBuilderAtEnd(g->builder, prong_block);
3611 AstNode *prong_expr = prong_node->data.switch_prong.expr;
3612 LLVMValueRef prong_val = gen_expr(g, prong_expr);
3613
3614 if (get_expr_type(prong_expr)->id != TypeTableEntryIdUnreachable) {
3615 set_debug_source_node(g, prong_expr);
3616 LLVMBuildBr(g->builder, end_block);
3617 incoming_values.append(prong_val);
3618 incoming_blocks.append(LLVMGetInsertBlock(g->builder));
3619 }
3620 }
3621
3622 if (!else_prong) {
3623 LLVMPositionBuilderAtEnd(g->builder, else_block);
3624 set_debug_source_node(g, node);
3625 if (want_debug_safety(g, node)) {
3626 gen_debug_safety_crash(g);
3627 } else {
3628 LLVMBuildUnreachable(g->builder);
3629 }
3630 }
3631
3632 if (end_unreachable) {
3633 return nullptr;
3634 }
3635
3636 LLVMPositionBuilderAtEnd(g->builder, end_block);
3637
3638 if (result_has_bits) {
3639 set_debug_source_node(g, node);
3640 LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(incoming_values.at(0)), "");
3641 LLVMAddIncoming(phi, incoming_values.items, incoming_blocks.items, incoming_values.length);
3642 return phi;
3643 } else {
3644 return nullptr;
3645 }
3646}
3647
3648static LLVMValueRef gen_goto(CodeGen *g, AstNode *node) {
3649 assert(node->type == NodeTypeGoto);
3650
3651 // generate defers for blocks that we exit
3652 LabelTableEntry *label = node->data.goto_expr.label_entry;
3653 BlockContext *this_context = node->block_context;
3654 BlockContext *target_context = label->decl_node->block_context;
3655 gen_defers_for_block(g, this_context, target_context, false, false);
3656
3657 set_debug_source_node(g, node);
3658 LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
3659 return nullptr;
3660}
3661
3662static LLVMValueRef gen_label(CodeGen *g, AstNode *node) {
3663 assert(node->type == NodeTypeLabel);
3664
3665 LabelTableEntry *label = node->data.label.label_entry;
3666 assert(label);
3667
3668 LLVMBasicBlockRef basic_block = label->basic_block;
3669 if (label->entered_from_fallthrough) {
3670 set_debug_source_node(g, node);
3671 LLVMBuildBr(g->builder, basic_block);
3672 }
3673 LLVMPositionBuilderAtEnd(g->builder, basic_block);
3674 return nullptr;
3675}
3676
3677static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
3678 Expr *expr = get_resolved_expr(node);
3679 if (expr->const_val.ok) {
3680 if (!type_has_bits(expr->type_entry)) {
3681 return nullptr;
3682 } else {
3683 assert(expr->const_llvm_val);
3684 return expr->const_llvm_val;
3685 }
3686 }
3687 switch (node->type) {
3688 case NodeTypeBinOpExpr:
3689 return gen_bin_op_expr(g, node);
3690 case NodeTypeUnwrapErrorExpr:
3691 return gen_unwrap_err_expr(g, node);
3692 case NodeTypeReturnExpr:
3693 return gen_return_expr(g, node);
3694 case NodeTypeDefer:
3695 // nothing to do
3696 return nullptr;
3697 case NodeTypeVariableDeclaration:
3698 return gen_var_decl_expr(g, node);
3699 case NodeTypePrefixOpExpr:
3700 zig_panic("moved to ir render");
3701 case NodeTypeFnCallExpr:
3702 return gen_fn_call_expr(g, node);
3703 case NodeTypeArrayAccessExpr:
3704 return gen_array_access_expr(g, node, false);
3705 case NodeTypeSliceExpr:
3706 return gen_slice_expr(g, node);
3707 case NodeTypeFieldAccessExpr:
3708 return gen_field_access_expr(g, node, false);
3709 case NodeTypeIfBoolExpr:
3710 return gen_if_bool_expr(g, node);
3711 case NodeTypeIfVarExpr:
3712 return gen_if_var_expr(g, node);
3713 case NodeTypeWhileExpr:
3714 return gen_while_expr(g, node);
3715 case NodeTypeForExpr:
3716 zig_panic("moved to ir render");
3717 case NodeTypeAsmExpr:
3718 return gen_asm_expr(g, node);
3719 case NodeTypeSymbol:
3720 return gen_symbol(g, node);
3721 case NodeTypeBlock:
3722 return gen_block(g, node, nullptr);
3723 case NodeTypeGoto:
3724 return gen_goto(g, node);
3725 case NodeTypeBreak:
3726 zig_panic("TODO IR");
3727 case NodeTypeContinue:
3728 zig_panic("TODO IR");
3729 case NodeTypeLabel:
3730 return gen_label(g, node);
3731 case NodeTypeContainerInitExpr:
3732 return gen_container_init_expr(g, node);
3733 case NodeTypeSwitchExpr:
3734 return gen_switch_expr(g, node);
3735 case NodeTypeNumberLiteral:
3736 case NodeTypeBoolLiteral:
3737 case NodeTypeStringLiteral:
3738 case NodeTypeCharLiteral:
3739 case NodeTypeNullLiteral:
3740 case NodeTypeUndefinedLiteral:
3741 case NodeTypeZeroesLiteral:
3742 case NodeTypeThisLiteral:
3743 case NodeTypeErrorType:
3744 case NodeTypeTypeLiteral:
3745 case NodeTypeArrayType:
3746 case NodeTypeVarLiteral:
3747 // caught by constant expression eval codegen
3748 zig_unreachable();
3749 case NodeTypeRoot:
3750 case NodeTypeFnProto:
3751 case NodeTypeFnDef:
3752 case NodeTypeFnDecl:
3753 case NodeTypeParamDecl:
3754 case NodeTypeUse:
3755 case NodeTypeContainerDecl:
3756 case NodeTypeStructField:
3757 case NodeTypeStructValueField:
3758 case NodeTypeSwitchProng:
3759 case NodeTypeSwitchRange:
3760 case NodeTypeErrorValueDecl:
3761 case NodeTypeTypeDecl:
3762 zig_unreachable();
3763 }
3764 zig_unreachable();
3765}
3766
37671610static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val) {
37681611 assert(const_val->ok);
37691612
src/ir.cpp+1991-1
......@@ -1693,7 +1693,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
16931693 case NodeTypeSwitchRange:
16941694 case NodeTypeErrorValueDecl:
16951695 case NodeTypeTypeDecl:
1696 zig_panic("TODO more IR gen");
1696 zig_panic("TODO more IR gen for node types");
16971697 }
16981698 zig_unreachable();
16991699}
......@@ -3966,6 +3966,8 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) {
39663966 return value;
39673967}
39683968
3969// TODO port over all this commented out code into new IR way of doing things
3970
39693971//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
39703972// AstNode *node, const char *err_format, bool is_max)
39713973//{
......@@ -7401,3 +7403,1991 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
74017403// return nullptr;
74027404//}
74037405
7406//
7407//static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) {
7408// assert(node->type == NodeTypeFnCallExpr);
7409// assert(g->generate_error_name_table);
7410//
7411// if (g->error_decls.length == 1) {
7412// LLVMBuildUnreachable(g->builder);
7413// return nullptr;
7414// }
7415//
7416//
7417// AstNode *err_val_node = node->data.fn_call_expr.params.at(0);
7418// LLVMValueRef err_val = gen_expr(g, err_val_node);
7419//
7420// if (want_debug_safety(g, node)) {
7421// LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val));
7422// LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false);
7423// add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val);
7424// }
7425//
7426// LLVMValueRef indices[] = {
7427// LLVMConstNull(g->builtin_types.entry_usize->type_ref),
7428// err_val,
7429// };
7430// return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, "");
7431//}
7432//
7433//static LLVMValueRef gen_cmp_exchange(CodeGen *g, AstNode *node) {
7434// assert(node->type == NodeTypeFnCallExpr);
7435//
7436// AstNode *ptr_arg = node->data.fn_call_expr.params.at(0);
7437// AstNode *cmp_arg = node->data.fn_call_expr.params.at(1);
7438// AstNode *new_arg = node->data.fn_call_expr.params.at(2);
7439// AstNode *success_order_arg = node->data.fn_call_expr.params.at(3);
7440// AstNode *failure_order_arg = node->data.fn_call_expr.params.at(4);
7441//
7442// LLVMValueRef ptr_val = gen_expr(g, ptr_arg);
7443// LLVMValueRef cmp_val = gen_expr(g, cmp_arg);
7444// LLVMValueRef new_val = gen_expr(g, new_arg);
7445//
7446// ConstExprValue *success_order_val = &get_resolved_expr(success_order_arg)->const_val;
7447// ConstExprValue *failure_order_val = &get_resolved_expr(failure_order_arg)->const_val;
7448//
7449// assert(success_order_val->ok);
7450// assert(failure_order_val->ok);
7451//
7452// LLVMAtomicOrdering success_order = to_LLVMAtomicOrdering((AtomicOrder)success_order_val->data.x_enum.tag);
7453// LLVMAtomicOrdering failure_order = to_LLVMAtomicOrdering((AtomicOrder)failure_order_val->data.x_enum.tag);
7454//
7455// LLVMValueRef result_val = ZigLLVMBuildCmpXchg(g->builder, ptr_val, cmp_val, new_val,
7456// success_order, failure_order);
7457//
7458// return LLVMBuildExtractValue(g->builder, result_val, 1, "");
7459//}
7460//
7461//static LLVMValueRef gen_div_exact(CodeGen *g, AstNode *node) {
7462// assert(node->type == NodeTypeFnCallExpr);
7463//
7464// AstNode *op1_node = node->data.fn_call_expr.params.at(0);
7465// AstNode *op2_node = node->data.fn_call_expr.params.at(1);
7466//
7467// LLVMValueRef op1_val = gen_expr(g, op1_node);
7468// LLVMValueRef op2_val = gen_expr(g, op2_node);
7469//
7470// return gen_div(g, node, op1_val, op2_val, get_expr_type(op1_node), true);
7471//}
7472//
7473//static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
7474// assert(node->type == NodeTypeFnCallExpr);
7475//
7476// TypeTableEntry *dest_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
7477// AstNode *src_node = node->data.fn_call_expr.params.at(1);
7478//
7479// LLVMValueRef src_val = gen_expr(g, src_node);
7480//
7481// return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
7482//}
7483//
7484//static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
7485// assert(node->type == NodeTypeFnCallExpr);
7486//
7487// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7488// assert(fn_call_param_count == 4);
7489//
7490// TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
7491// assert(int_type->id == TypeTableEntryIdInt);
7492//
7493// LLVMValueRef val1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
7494// LLVMValueRef val2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
7495// LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
7496//
7497// LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
7498// LLVMValueRef orig_val;
7499// if (int_type->data.integral.is_signed) {
7500// orig_val = LLVMBuildAShr(g->builder, result, val2, "");
7501// } else {
7502// orig_val = LLVMBuildLShr(g->builder, result, val2, "");
7503// }
7504// LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, val1, orig_val, "");
7505//
7506// LLVMBuildStore(g->builder, result, ptr_result);
7507//
7508// return overflow_bit;
7509//}
7510//
7511//static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
7512// assert(node->type == NodeTypeFnCallExpr);
7513// AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
7514// assert(fn_ref_expr->type == NodeTypeSymbol);
7515// BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
7516//
7517// switch (builtin_fn->id) {
7518// case BuiltinFnIdInvalid:
7519// case BuiltinFnIdTypeof:
7520// case BuiltinFnIdCInclude:
7521// case BuiltinFnIdCDefine:
7522// case BuiltinFnIdCUndef:
7523// case BuiltinFnIdImport:
7524// case BuiltinFnIdCImport:
7525// case BuiltinFnIdCompileErr:
7526// case BuiltinFnIdIntType:
7527// zig_unreachable();
7528// case BuiltinFnIdCtz:
7529// case BuiltinFnIdClz:
7530// {
7531// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7532// assert(fn_call_param_count == 2);
7533// TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
7534// assert(int_type->id == TypeTableEntryIdInt);
7535// LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, builtin_fn->id);
7536// LLVMValueRef operand = gen_expr(g, node->data.fn_call_expr.params.at(1));
7537// LLVMValueRef params[] {
7538// operand,
7539// LLVMConstNull(LLVMInt1Type()),
7540// };
7541// return LLVMBuildCall(g->builder, fn_val, params, 2, "");
7542// }
7543// case BuiltinFnIdAddWithOverflow:
7544// case BuiltinFnIdSubWithOverflow:
7545// case BuiltinFnIdMulWithOverflow:
7546// {
7547// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7548// assert(fn_call_param_count == 4);
7549//
7550// TypeTableEntry *int_type = get_type_for_type_node(node->data.fn_call_expr.params.at(0));
7551// AddSubMul add_sub_mul;
7552// if (builtin_fn->id == BuiltinFnIdAddWithOverflow) {
7553// add_sub_mul = AddSubMulAdd;
7554// } else if (builtin_fn->id == BuiltinFnIdSubWithOverflow) {
7555// add_sub_mul = AddSubMulSub;
7556// } else if (builtin_fn->id == BuiltinFnIdMulWithOverflow) {
7557// add_sub_mul = AddSubMulMul;
7558// } else {
7559// zig_unreachable();
7560// }
7561// LLVMValueRef fn_val = get_int_overflow_fn(g, int_type, add_sub_mul);
7562//
7563// LLVMValueRef op1 = gen_expr(g, node->data.fn_call_expr.params.at(1));
7564// LLVMValueRef op2 = gen_expr(g, node->data.fn_call_expr.params.at(2));
7565// LLVMValueRef ptr_result = gen_expr(g, node->data.fn_call_expr.params.at(3));
7566//
7567// LLVMValueRef params[] = {
7568// op1,
7569// op2,
7570// };
7571//
7572// LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
7573// LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
7574// LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
7575// LLVMBuildStore(g->builder, result, ptr_result);
7576//
7577// return overflow_bit;
7578// }
7579// case BuiltinFnIdShlWithOverflow:
7580// return gen_shl_with_overflow(g, node);
7581// case BuiltinFnIdMemcpy:
7582// {
7583// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7584// assert(fn_call_param_count == 3);
7585//
7586// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
7587// TypeTableEntry *dest_type = get_expr_type(dest_node);
7588//
7589// LLVMValueRef dest_ptr = gen_expr(g, dest_node);
7590// LLVMValueRef src_ptr = gen_expr(g, node->data.fn_call_expr.params.at(1));
7591// LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
7592//
7593// LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
7594//
7595// LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
7596// LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, ptr_u8, "");
7597//
7598// uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
7599//
7600// LLVMValueRef params[] = {
7601// dest_ptr_casted, // dest pointer
7602// src_ptr_casted, // source pointer
7603// len_val, // byte count
7604// LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
7605// LLVMConstNull(LLVMInt1Type()), // is volatile
7606// };
7607//
7608// LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
7609// return nullptr;
7610// }
7611// case BuiltinFnIdMemset:
7612// {
7613// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7614// assert(fn_call_param_count == 3);
7615//
7616// AstNode *dest_node = node->data.fn_call_expr.params.at(0);
7617// TypeTableEntry *dest_type = get_expr_type(dest_node);
7618//
7619// LLVMValueRef dest_ptr = gen_expr(g, dest_node);
7620// LLVMValueRef char_val = gen_expr(g, node->data.fn_call_expr.params.at(1));
7621// LLVMValueRef len_val = gen_expr(g, node->data.fn_call_expr.params.at(2));
7622//
7623// LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
7624//
7625// LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, dest_ptr, ptr_u8, "");
7626//
7627// uint64_t align_in_bytes = get_memcpy_align(g, dest_type->data.pointer.child_type);
7628//
7629// LLVMValueRef params[] = {
7630// dest_ptr_casted, // dest pointer
7631// char_val, // source pointer
7632// len_val, // byte count
7633// LLVMConstInt(LLVMInt32Type(), align_in_bytes, false), // align in bytes
7634// LLVMConstNull(LLVMInt1Type()), // is volatile
7635// };
7636//
7637// LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
7638// return nullptr;
7639// }
7640// case BuiltinFnIdSizeof:
7641// case BuiltinFnIdAlignof:
7642// case BuiltinFnIdMinValue:
7643// case BuiltinFnIdMaxValue:
7644// case BuiltinFnIdMemberCount:
7645// case BuiltinFnIdConstEval:
7646// case BuiltinFnIdEmbedFile:
7647// // caught by constant expression eval codegen
7648// zig_unreachable();
7649// case BuiltinFnIdCompileVar:
7650// return nullptr;
7651// case BuiltinFnIdErrName:
7652// return gen_err_name(g, node);
7653// case BuiltinFnIdBreakpoint:
7654// return LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
7655// case BuiltinFnIdFrameAddress:
7656// case BuiltinFnIdReturnAddress:
7657// {
7658// LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref);
7659// return LLVMBuildCall(g->builder, builtin_fn->fn_val, &zero, 1, "");
7660// }
7661// case BuiltinFnIdCmpExchange:
7662// return gen_cmp_exchange(g, node);
7663// case BuiltinFnIdFence:
7664// return gen_fence(g, node);
7665// case BuiltinFnIdDivExact:
7666// return gen_div_exact(g, node);
7667// case BuiltinFnIdTruncate:
7668// return gen_truncate(g, node);
7669// case BuiltinFnIdUnreachable:
7670// zig_panic("moved to ir render");
7671// case BuiltinFnIdSetFnTest:
7672// case BuiltinFnIdSetFnVisible:
7673// case BuiltinFnIdSetFnStaticEval:
7674// case BuiltinFnIdSetFnNoInline:
7675// case BuiltinFnIdSetDebugSafety:
7676// // do nothing
7677// return nullptr;
7678// }
7679// zig_unreachable();
7680//}
7681//
7682//static LLVMValueRef gen_enum_value_expr(CodeGen *g, AstNode *node, TypeTableEntry *enum_type,
7683// AstNode *arg_node)
7684//{
7685// assert(node->type == NodeTypeFieldAccessExpr);
7686//
7687// uint64_t value = node->data.field_access_expr.type_enum_field->value;
7688// LLVMTypeRef tag_type_ref = enum_type->data.enumeration.tag_type->type_ref;
7689// LLVMValueRef tag_value = LLVMConstInt(tag_type_ref, value, false);
7690//
7691// if (enum_type->data.enumeration.gen_field_count == 0) {
7692// return tag_value;
7693// } else {
7694// TypeTableEntry *arg_node_type = nullptr;
7695// LLVMValueRef new_union_val = gen_expr(g, arg_node);
7696// if (arg_node) {
7697// arg_node_type = get_expr_type(arg_node);
7698// } else {
7699// arg_node_type = g->builtin_types.entry_void;
7700// }
7701//
7702// LLVMValueRef tmp_struct_ptr = node->data.field_access_expr.resolved_struct_val_expr.ptr;
7703//
7704// // populate the new tag value
7705// LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
7706// LLVMBuildStore(g->builder, tag_value, tag_field_ptr);
7707//
7708// if (arg_node_type->id != TypeTableEntryIdVoid) {
7709// // populate the union value
7710// TypeTableEntry *union_val_type = get_expr_type(arg_node);
7711// LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
7712// LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
7713// LLVMPointerType(union_val_type->type_ref, 0), "");
7714//
7715// gen_assign_raw(g, arg_node, BinOpTypeAssign, bitcasted_union_field_ptr, new_union_val,
7716// union_val_type, union_val_type);
7717//
7718// }
7719//
7720// return tmp_struct_ptr;
7721// }
7722//}
7723//
7724//static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
7725// assert(node->type == NodeTypeFnCallExpr);
7726//
7727// if (node->data.fn_call_expr.is_builtin) {
7728// return gen_builtin_fn_call_expr(g, node);
7729// }
7730//
7731// FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
7732// TypeTableEntry *struct_type = nullptr;
7733// AstNode *first_param_expr = nullptr;
7734//
7735// AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
7736// if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
7737// fn_ref_expr->data.field_access_expr.is_member_fn)
7738// {
7739// first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr;
7740// struct_type = get_expr_type(first_param_expr);
7741// }
7742//
7743// TypeTableEntry *fn_type;
7744// LLVMValueRef fn_val;
7745// AstNode *generic_proto_node;
7746// if (fn_table_entry) {
7747// fn_val = fn_table_entry->fn_value;
7748// fn_type = fn_table_entry->type_entry;
7749// generic_proto_node = fn_table_entry->proto_node->data.fn_proto.generic_proto_node;
7750// } else {
7751// fn_val = gen_expr(g, fn_ref_expr);
7752// fn_type = get_expr_type(fn_ref_expr);
7753// generic_proto_node = nullptr;
7754// }
7755//
7756// TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
7757//
7758// bool ret_has_bits = type_has_bits(src_return_type);
7759//
7760// size_t fn_call_param_count = node->data.fn_call_expr.params.length;
7761// bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
7762// size_t actual_param_count = fn_call_param_count + (struct_type ? 1 : 0) + (first_arg_ret ? 1 : 0);
7763// bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
7764//
7765// // don't really include void values
7766// LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
7767//
7768// size_t gen_param_index = 0;
7769// if (first_arg_ret) {
7770// gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr;
7771// gen_param_index += 1;
7772// }
7773// if (struct_type && type_has_bits(struct_type)) {
7774// gen_param_values[gen_param_index] = gen_expr(g, first_param_expr);
7775// assert(gen_param_values[gen_param_index]);
7776// gen_param_index += 1;
7777// }
7778//
7779// for (size_t call_i = 0; call_i < fn_call_param_count; call_i += 1) {
7780// size_t proto_i = call_i + (struct_type ? 1 : 0);
7781// if (generic_proto_node &&
7782// generic_proto_node->data.fn_proto.params.at(proto_i)->data.param_decl.is_inline)
7783// {
7784// continue;
7785// }
7786// AstNode *expr_node = node->data.fn_call_expr.params.at(call_i);
7787// LLVMValueRef param_value = gen_expr(g, expr_node);
7788// assert(param_value);
7789// TypeTableEntry *param_type = get_expr_type(expr_node);
7790// if (is_var_args || type_has_bits(param_type)) {
7791// gen_param_values[gen_param_index] = param_value;
7792// gen_param_index += 1;
7793// }
7794// }
7795//
7796// LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
7797// gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
7798//
7799// if (src_return_type->id == TypeTableEntryIdUnreachable) {
7800// return LLVMBuildUnreachable(g->builder);
7801// } else if (!ret_has_bits) {
7802// return nullptr;
7803// } else if (first_arg_ret) {
7804// return node->data.fn_call_expr.tmp_ptr;
7805// } else {
7806// return result;
7807// }
7808//}
7809//
7810//static LLVMValueRef gen_array_base_ptr(CodeGen *g, AstNode *node) {
7811// TypeTableEntry *type_entry = get_expr_type(node);
7812//
7813// LLVMValueRef array_ptr;
7814// if (node->type == NodeTypeFieldAccessExpr) {
7815// array_ptr = gen_field_access_expr(g, node, true);
7816// if (type_entry->id == TypeTableEntryIdPointer) {
7817// // we have a double pointer so we must dereference it once
7818// array_ptr = LLVMBuildLoad(g->builder, array_ptr, "");
7819// }
7820// } else {
7821// array_ptr = gen_expr(g, node);
7822// }
7823//
7824// assert(!array_ptr || LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
7825//
7826// return array_ptr;
7827//}
7828//
7829//static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) {
7830// assert(node->type == NodeTypeArrayAccessExpr);
7831//
7832// AstNode *array_expr_node = node->data.array_access_expr.array_ref_expr;
7833// TypeTableEntry *array_type = get_expr_type(array_expr_node);
7834//
7835// LLVMValueRef array_ptr = gen_array_base_ptr(g, array_expr_node);
7836//
7837// LLVMValueRef subscript_value = gen_expr(g, node->data.array_access_expr.subscript);
7838// return gen_array_elem_ptr(g, node, array_ptr, array_type, subscript_value);
7839//}
7840//
7841//static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **out_type_entry) {
7842// assert(node->type == NodeTypeFieldAccessExpr);
7843//
7844// AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
7845//
7846// *out_type_entry = node->data.field_access_expr.type_struct_field->type_entry;
7847// if (!type_has_bits(*out_type_entry)) {
7848// return nullptr;
7849// }
7850//
7851// LLVMValueRef struct_ptr;
7852// if (struct_expr_node->type == NodeTypeSymbol) {
7853// VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable;
7854// assert(var);
7855//
7856// if (var->type->id == TypeTableEntryIdPointer) {
7857// struct_ptr = LLVMBuildLoad(g->builder, var->value_ref, "");
7858// } else {
7859// struct_ptr = var->value_ref;
7860// }
7861// } else if (struct_expr_node->type == NodeTypeFieldAccessExpr) {
7862// struct_ptr = gen_field_access_expr(g, struct_expr_node, true);
7863// TypeTableEntry *field_type = get_expr_type(struct_expr_node);
7864// if (field_type->id == TypeTableEntryIdPointer) {
7865// // we have a double pointer so we must dereference it once
7866// struct_ptr = LLVMBuildLoad(g->builder, struct_ptr, "");
7867// }
7868// } else {
7869// struct_ptr = gen_expr(g, struct_expr_node);
7870// }
7871//
7872// assert(LLVMGetTypeKind(LLVMTypeOf(struct_ptr)) == LLVMPointerTypeKind);
7873// assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(struct_ptr))) == LLVMStructTypeKind);
7874//
7875// size_t gen_field_index = node->data.field_access_expr.type_struct_field->gen_index;
7876// assert(gen_field_index != SIZE_MAX);
7877//
7878// return LLVMBuildStructGEP(g->builder, struct_ptr, gen_field_index, "");
7879//}
7880//
7881//static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
7882// assert(node->type == NodeTypeSliceExpr);
7883//
7884// AstNode *array_ref_node = node->data.slice_expr.array_ref_expr;
7885// TypeTableEntry *array_type = get_expr_type(array_ref_node);
7886//
7887// LLVMValueRef tmp_struct_ptr = node->data.slice_expr.resolved_struct_val_expr.ptr;
7888// LLVMValueRef array_ptr = gen_array_base_ptr(g, array_ref_node);
7889//
7890// if (array_type->id == TypeTableEntryIdArray) {
7891// LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
7892// LLVMValueRef end_val;
7893// if (node->data.slice_expr.end) {
7894// end_val = gen_expr(g, node->data.slice_expr.end);
7895// } else {
7896// end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false);
7897// }
7898//
7899// if (want_debug_safety(g, node)) {
7900// add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
7901// if (node->data.slice_expr.end) {
7902// LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
7903// array_type->data.array.len, false);
7904// add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end);
7905// }
7906// }
7907//
7908// LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
7909// LLVMValueRef indices[] = {
7910// LLVMConstNull(g->builtin_types.entry_usize->type_ref),
7911// start_val,
7912// };
7913// LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
7914// LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
7915//
7916// LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
7917// LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
7918// LLVMBuildStore(g->builder, len_value, len_field_ptr);
7919//
7920// return tmp_struct_ptr;
7921// } else if (array_type->id == TypeTableEntryIdPointer) {
7922// LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
7923// LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end);
7924//
7925// if (want_debug_safety(g, node)) {
7926// add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
7927// }
7928//
7929// LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, "");
7930// LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
7931// LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
7932//
7933// LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, "");
7934// LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
7935// LLVMBuildStore(g->builder, len_value, len_field_ptr);
7936//
7937// return tmp_struct_ptr;
7938// } else if (array_type->id == TypeTableEntryIdStruct) {
7939// assert(array_type->data.structure.is_slice);
7940// assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
7941// assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
7942//
7943// size_t ptr_index = array_type->data.structure.fields[0].gen_index;
7944// assert(ptr_index != SIZE_MAX);
7945// size_t len_index = array_type->data.structure.fields[1].gen_index;
7946// assert(len_index != SIZE_MAX);
7947//
7948// LLVMValueRef prev_end = nullptr;
7949// if (!node->data.slice_expr.end || want_debug_safety(g, node)) {
7950// LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
7951// prev_end = LLVMBuildLoad(g->builder, src_len_ptr, "");
7952// }
7953//
7954// LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start);
7955// LLVMValueRef end_val;
7956// if (node->data.slice_expr.end) {
7957// end_val = gen_expr(g, node->data.slice_expr.end);
7958// } else {
7959// end_val = prev_end;
7960// }
7961//
7962// if (want_debug_safety(g, node)) {
7963// assert(prev_end);
7964// add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val);
7965// if (node->data.slice_expr.end) {
7966// add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, prev_end);
7967// }
7968// }
7969//
7970// LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
7971// LLVMValueRef src_ptr = LLVMBuildLoad(g->builder, src_ptr_ptr, "");
7972// LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, ptr_index, "");
7973// LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, len_index, "");
7974// LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr);
7975//
7976// LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, len_index, "");
7977// LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
7978// LLVMBuildStore(g->builder, len_value, len_field_ptr);
7979//
7980// return tmp_struct_ptr;
7981// } else {
7982// zig_unreachable();
7983// }
7984//}
7985//
7986//
7987//static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
7988// TypeTableEntry **out_type_entry)
7989//{
7990// LLVMValueRef target_ref;
7991//
7992// if (node->type == NodeTypeSymbol) {
7993// VariableTableEntry *var = get_resolved_expr(node)->variable;
7994// assert(var);
7995//
7996// *out_type_entry = var->type;
7997// target_ref = var->value_ref;
7998// } else if (node->type == NodeTypeArrayAccessExpr) {
7999// TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
8000// if (array_type->id == TypeTableEntryIdArray) {
8001// *out_type_entry = array_type->data.array.child_type;
8002// target_ref = gen_array_ptr(g, node);
8003// } else if (array_type->id == TypeTableEntryIdPointer) {
8004// *out_type_entry = array_type->data.pointer.child_type;
8005// target_ref = gen_array_ptr(g, node);
8006// } else if (array_type->id == TypeTableEntryIdStruct) {
8007// assert(array_type->data.structure.is_slice);
8008// *out_type_entry = array_type->data.structure.fields[0].type_entry->data.pointer.child_type;
8009// target_ref = gen_array_ptr(g, node);
8010// } else {
8011// zig_unreachable();
8012// }
8013// } else if (node->type == NodeTypeFieldAccessExpr) {
8014// AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
8015// TypeTableEntry *struct_type = get_expr_type(struct_expr_node);
8016// if (struct_type->id == TypeTableEntryIdNamespace) {
8017// target_ref = gen_field_access_expr(g, node, true);
8018// *out_type_entry = get_expr_type(node);
8019// } else {
8020// target_ref = gen_field_ptr(g, node, out_type_entry);
8021// }
8022// } else if (node->type == NodeTypePrefixOpExpr) {
8023// assert(node->data.prefix_op_expr.prefix_op == PrefixOpDereference);
8024// AstNode *target_expr = node->data.prefix_op_expr.primary_expr;
8025// TypeTableEntry *type_entry = get_expr_type(target_expr);
8026// assert(type_entry->id == TypeTableEntryIdPointer);
8027// *out_type_entry = type_entry->data.pointer.child_type;
8028// return gen_expr(g, target_expr);
8029// } else {
8030// zig_panic("bad assign target");
8031// }
8032//
8033// return target_ref;
8034//}
8035//
8036//static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
8037// assert(node->type == NodeTypeBinOpExpr);
8038//
8039// LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
8040// LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
8041//
8042// TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
8043// TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
8044// return gen_arithmetic_bin_op(g, node, val1, val2, op1_type, op2_type, node->data.bin_op_expr.bin_op);
8045//
8046//}
8047//
8048//static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
8049// assert(node->type == NodeTypeBinOpExpr);
8050//
8051// LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
8052// LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
8053//
8054// // block for when val1 == true
8055// LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue");
8056// // block for when val1 == false (don't even evaluate the second part)
8057// LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse");
8058//
8059// LLVMBuildCondBr(g->builder, val1, true_block, false_block);
8060//
8061// LLVMPositionBuilderAtEnd(g->builder, true_block);
8062// LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
8063// LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
8064//
8065// LLVMBuildBr(g->builder, false_block);
8066//
8067// LLVMPositionBuilderAtEnd(g->builder, false_block);
8068// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
8069// LLVMValueRef incoming_values[2] = {val1, val2};
8070// LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
8071// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8072//
8073// return phi;
8074//}
8075//
8076//static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) {
8077// assert(expr_node->type == NodeTypeBinOpExpr);
8078//
8079// LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1);
8080// LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder);
8081//
8082// // block for when val1 == false
8083// LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse");
8084// // block for when val1 == true (don't even evaluate the second part)
8085// LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue");
8086//
8087// LLVMBuildCondBr(g->builder, val1, true_block, false_block);
8088//
8089// LLVMPositionBuilderAtEnd(g->builder, false_block);
8090// LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2);
8091//
8092// LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder);
8093//
8094// LLVMBuildBr(g->builder, true_block);
8095//
8096// LLVMPositionBuilderAtEnd(g->builder, true_block);
8097// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), "");
8098// LLVMValueRef incoming_values[2] = {val1, val2};
8099// LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block};
8100// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8101//
8102// return phi;
8103//}
8104//
8105//static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) {
8106// assert(node->type == NodeTypeBinOpExpr);
8107//
8108// AstNode *lhs_node = node->data.bin_op_expr.op1;
8109//
8110// TypeTableEntry *op1_type;
8111//
8112// LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type);
8113//
8114// TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
8115//
8116// LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2);
8117//
8118// gen_assign_raw(g, node, node->data.bin_op_expr.bin_op, target_ref, value, op1_type, op2_type);
8119// return nullptr;
8120//}
8121//
8122//static LLVMValueRef gen_unwrap_maybe_expr(CodeGen *g, AstNode *node) {
8123// assert(node->type == NodeTypeBinOpExpr);
8124// assert(node->data.bin_op_expr.bin_op == BinOpTypeUnwrapMaybe);
8125//
8126// AstNode *op1_node = node->data.bin_op_expr.op1;
8127// AstNode *op2_node = node->data.bin_op_expr.op2;
8128//
8129// LLVMValueRef maybe_struct_ref = gen_expr(g, op1_node);
8130//
8131// TypeTableEntry *maybe_type = get_expr_type(op1_node);
8132// assert(maybe_type->id == TypeTableEntryIdMaybe);
8133// TypeTableEntry *child_type = maybe_type->data.maybe.child_type;
8134//
8135// LLVMValueRef cond_value;
8136// if (child_type->id == TypeTableEntryIdPointer ||
8137// child_type->id == TypeTableEntryIdFn)
8138// {
8139// cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref,
8140// LLVMConstNull(child_type->type_ref), "");
8141// } else {
8142// LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 1, "");
8143// cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
8144// }
8145//
8146// LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNonNull");
8147// LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeNull");
8148// LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEnd");
8149//
8150// bool null_reachable = get_expr_type(op2_node)->id != TypeTableEntryIdUnreachable;
8151//
8152// LLVMBuildCondBr(g->builder, cond_value, non_null_block, null_block);
8153//
8154// LLVMPositionBuilderAtEnd(g->builder, non_null_block);
8155// LLVMValueRef non_null_result = gen_unwrap_maybe(g, op1_node, maybe_struct_ref);
8156// LLVMBuildBr(g->builder, end_block);
8157// LLVMBasicBlockRef post_non_null_result_block = LLVMGetInsertBlock(g->builder);
8158//
8159// LLVMPositionBuilderAtEnd(g->builder, null_block);
8160// LLVMValueRef null_result = gen_expr(g, op2_node);
8161// if (null_reachable) {
8162// LLVMBuildBr(g->builder, end_block);
8163// }
8164// LLVMBasicBlockRef post_null_result_block = LLVMGetInsertBlock(g->builder);
8165//
8166// LLVMPositionBuilderAtEnd(g->builder, end_block);
8167// if (null_reachable) {
8168// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(non_null_result), "");
8169// LLVMValueRef incoming_values[2] = {non_null_result, null_result};
8170// LLVMBasicBlockRef incoming_blocks[2] = {post_non_null_result_block, post_null_result_block};
8171// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8172// return phi;
8173// } else {
8174// return non_null_result;
8175// }
8176//
8177// return nullptr;
8178//}
8179//
8180//static LLVMValueRef gen_unwrap_err_expr(CodeGen *g, AstNode *node) {
8181// assert(node->type == NodeTypeUnwrapErrorExpr);
8182//
8183// AstNode *op1 = node->data.unwrap_err_expr.op1;
8184// AstNode *op2 = node->data.unwrap_err_expr.op2;
8185// VariableTableEntry *var = node->data.unwrap_err_expr.var;
8186//
8187// LLVMValueRef expr_val = gen_expr(g, op1);
8188// TypeTableEntry *expr_type = get_expr_type(op1);
8189// TypeTableEntry *op2_type = get_expr_type(op2);
8190// assert(expr_type->id == TypeTableEntryIdErrorUnion);
8191// TypeTableEntry *child_type = expr_type->data.error.child_type;
8192// LLVMValueRef err_val;
8193// if (handle_is_ptr(expr_type)) {
8194// LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
8195// err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
8196// } else {
8197// err_val = expr_val;
8198// }
8199// LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
8200// LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
8201//
8202// LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
8203// LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
8204// LLVMBasicBlockRef end_block;
8205// bool err_reachable = op2_type->id != TypeTableEntryIdUnreachable;
8206// bool have_end_block = err_reachable && type_has_bits(child_type);
8207// if (have_end_block) {
8208// end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrEnd");
8209// }
8210//
8211// LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
8212//
8213// LLVMPositionBuilderAtEnd(g->builder, err_block);
8214// if (var) {
8215// LLVMBuildStore(g->builder, err_val, var->value_ref);
8216// }
8217// LLVMValueRef err_result = gen_expr(g, op2);
8218// if (have_end_block) {
8219// LLVMBuildBr(g->builder, end_block);
8220// } else if (err_reachable) {
8221// LLVMBuildBr(g->builder, ok_block);
8222// }
8223//
8224// LLVMPositionBuilderAtEnd(g->builder, ok_block);
8225// if (!type_has_bits(child_type)) {
8226// return nullptr;
8227// }
8228// LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
8229// LLVMValueRef child_val = get_handle_value(g, child_val_ptr, child_type);
8230//
8231// if (!have_end_block) {
8232// return child_val;
8233// }
8234//
8235// LLVMBuildBr(g->builder, end_block);
8236//
8237// LLVMPositionBuilderAtEnd(g->builder, end_block);
8238// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(err_result), "");
8239// LLVMValueRef incoming_values[2] = {child_val, err_result};
8240// LLVMBasicBlockRef incoming_blocks[2] = {ok_block, err_block};
8241// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8242// return phi;
8243//}
8244//
8245//static void gen_defers_for_block(CodeGen *g, BlockContext *inner_block, BlockContext *outer_block,
8246// bool gen_error_defers, bool gen_maybe_defers)
8247//{
8248// while (inner_block != outer_block) {
8249// if (inner_block->node->type == NodeTypeDefer &&
8250// ((inner_block->node->data.defer.kind == ReturnKindUnconditional) ||
8251// (gen_error_defers && inner_block->node->data.defer.kind == ReturnKindError) ||
8252// (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe)))
8253// {
8254// gen_expr(g, inner_block->node->data.defer.expr);
8255// }
8256// inner_block = inner_block->parent;
8257// }
8258//}
8259//
8260//static LLVMValueRef gen_return_expr(CodeGen *g, AstNode *node) {
8261// assert(node->type == NodeTypeReturnExpr);
8262// AstNode *param_node = node->data.return_expr.expr;
8263// assert(param_node);
8264// LLVMValueRef value = gen_expr(g, param_node);
8265// TypeTableEntry *value_type = get_expr_type(param_node);
8266//
8267// switch (node->data.return_expr.kind) {
8268// case ReturnKindUnconditional:
8269// {
8270// Expr *expr = get_resolved_expr(param_node);
8271// if (expr->const_val.ok) {
8272// if (value_type->id == TypeTableEntryIdErrorUnion) {
8273// if (expr->const_val.data.x_err.err) {
8274// expr->return_knowledge = ReturnKnowledgeKnownError;
8275// } else {
8276// expr->return_knowledge = ReturnKnowledgeKnownNonError;
8277// }
8278// } else if (value_type->id == TypeTableEntryIdMaybe) {
8279// if (expr->const_val.data.x_maybe) {
8280// expr->return_knowledge = ReturnKnowledgeKnownNonNull;
8281// } else {
8282// expr->return_knowledge = ReturnKnowledgeKnownNull;
8283// }
8284// }
8285// }
8286// return gen_return(g, node, value, expr->return_knowledge);
8287// }
8288// case ReturnKindError:
8289// {
8290// assert(value_type->id == TypeTableEntryIdErrorUnion);
8291// TypeTableEntry *child_type = value_type->data.error.child_type;
8292//
8293// LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetReturn");
8294// LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ErrRetContinue");
8295//
8296// LLVMValueRef err_val;
8297// if (type_has_bits(child_type)) {
8298// LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
8299// err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
8300// } else {
8301// err_val = value;
8302// }
8303// LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
8304// LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
8305// LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
8306//
8307// LLVMPositionBuilderAtEnd(g->builder, return_block);
8308// TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
8309// if (return_type->id == TypeTableEntryIdPureError) {
8310// gen_return(g, node, err_val, ReturnKnowledgeKnownError);
8311// } else if (return_type->id == TypeTableEntryIdErrorUnion) {
8312// if (type_has_bits(return_type->data.error.child_type)) {
8313// assert(g->cur_ret_ptr);
8314//
8315// LLVMValueRef tag_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 0, "");
8316// LLVMBuildStore(g->builder, err_val, tag_ptr);
8317// LLVMBuildRetVoid(g->builder);
8318// } else {
8319// gen_return(g, node, err_val, ReturnKnowledgeKnownError);
8320// }
8321// } else {
8322// zig_unreachable();
8323// }
8324//
8325// LLVMPositionBuilderAtEnd(g->builder, continue_block);
8326// if (type_has_bits(child_type)) {
8327// LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
8328// return get_handle_value(g, val_ptr, child_type);
8329// } else {
8330// return nullptr;
8331// }
8332// }
8333// case ReturnKindMaybe:
8334// {
8335// assert(value_type->id == TypeTableEntryIdMaybe);
8336// TypeTableEntry *child_type = value_type->data.maybe.child_type;
8337//
8338// LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetReturn");
8339// LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeRetContinue");
8340//
8341// LLVMValueRef maybe_val_ptr = LLVMBuildStructGEP(g->builder, value, 1, "");
8342// LLVMValueRef is_non_null = LLVMBuildLoad(g->builder, maybe_val_ptr, "");
8343//
8344// LLVMValueRef zero = LLVMConstNull(LLVMInt1Type());
8345// LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, is_non_null, zero, "");
8346// LLVMBuildCondBr(g->builder, cond_val, continue_block, return_block);
8347//
8348// LLVMPositionBuilderAtEnd(g->builder, return_block);
8349// TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
8350// assert(return_type->id == TypeTableEntryIdMaybe);
8351// if (handle_is_ptr(return_type)) {
8352// assert(g->cur_ret_ptr);
8353//
8354// LLVMValueRef maybe_bit_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, 1, "");
8355// LLVMBuildStore(g->builder, zero, maybe_bit_ptr);
8356// LLVMBuildRetVoid(g->builder);
8357// } else {
8358// LLVMValueRef ret_zero_value = LLVMConstNull(return_type->type_ref);
8359// gen_return(g, node, ret_zero_value, ReturnKnowledgeKnownNull);
8360// }
8361//
8362// LLVMPositionBuilderAtEnd(g->builder, continue_block);
8363// if (type_has_bits(child_type)) {
8364// LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, value, 0, "");
8365// return get_handle_value(g, val_ptr, child_type);
8366// } else {
8367// return nullptr;
8368// }
8369// }
8370// }
8371// zig_unreachable();
8372//}
8373//
8374//static LLVMValueRef gen_if_bool_expr_raw(CodeGen *g, AstNode *source_node, LLVMValueRef cond_value,
8375// AstNode *then_node, AstNode *else_node)
8376//{
8377// assert(then_node);
8378// assert(else_node);
8379//
8380// TypeTableEntry *then_type = get_expr_type(then_node);
8381// TypeTableEntry *else_type = get_expr_type(else_node);
8382//
8383// bool use_then_value = type_has_bits(then_type);
8384// bool use_else_value = type_has_bits(else_type);
8385//
8386// LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Then");
8387// LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "Else");
8388//
8389// LLVMBasicBlockRef endif_block = nullptr;
8390// bool then_endif_reachable = then_type->id != TypeTableEntryIdUnreachable;
8391// bool else_endif_reachable = else_type->id != TypeTableEntryIdUnreachable;
8392// if (then_endif_reachable || else_endif_reachable) {
8393// endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "EndIf");
8394// }
8395//
8396// LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
8397//
8398// LLVMPositionBuilderAtEnd(g->builder, then_block);
8399// LLVMValueRef then_expr_result = gen_expr(g, then_node);
8400// if (then_endif_reachable) {
8401// clear_debug_source_node(g);
8402// LLVMBuildBr(g->builder, endif_block);
8403// }
8404// LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
8405//
8406// LLVMPositionBuilderAtEnd(g->builder, else_block);
8407// LLVMValueRef else_expr_result = gen_expr(g, else_node);
8408// if (else_endif_reachable) {
8409// clear_debug_source_node(g);
8410// LLVMBuildBr(g->builder, endif_block);
8411// }
8412// LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
8413//
8414// if (then_endif_reachable || else_endif_reachable) {
8415// LLVMPositionBuilderAtEnd(g->builder, endif_block);
8416// if (use_then_value && use_else_value) {
8417// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
8418// LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
8419// LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
8420// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8421// return phi;
8422// } else if (use_then_value) {
8423// return then_expr_result;
8424// } else if (use_else_value) {
8425// return else_expr_result;
8426// }
8427// }
8428//
8429// return nullptr;
8430//}
8431//
8432//static LLVMValueRef gen_if_bool_expr(CodeGen *g, AstNode *node) {
8433// assert(node->type == NodeTypeIfBoolExpr);
8434// assert(node->data.if_bool_expr.condition);
8435// assert(node->data.if_bool_expr.then_block);
8436//
8437// ConstExprValue *const_val = &get_resolved_expr(node->data.if_bool_expr.condition)->const_val;
8438// if (const_val->ok) {
8439// if (const_val->data.x_bool) {
8440// return gen_expr(g, node->data.if_bool_expr.then_block);
8441// } else if (node->data.if_bool_expr.else_node) {
8442// return gen_expr(g, node->data.if_bool_expr.else_node);
8443// } else {
8444// return nullptr;
8445// }
8446// } else {
8447// LLVMValueRef cond_value = gen_expr(g, node->data.if_bool_expr.condition);
8448//
8449// return gen_if_bool_expr_raw(g, node, cond_value,
8450// node->data.if_bool_expr.then_block,
8451// node->data.if_bool_expr.else_node);
8452// }
8453//}
8454//
8455//static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTableEntry *variable, bool maybe_is_ptr,
8456// LLVMValueRef init_val, TypeTableEntry *child_type, AstNode *then_node)
8457//{
8458// if (node->data.if_var_expr.var_is_ptr) {
8459// LLVMValueRef payload_ptr;
8460// if (maybe_is_ptr) {
8461// zig_panic("TODO");
8462// } else {
8463// payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
8464// }
8465// LLVMBuildStore(g->builder, payload_ptr, variable->value_ref);
8466// } else {
8467// LLVMValueRef payload_val;
8468// if (maybe_is_ptr) {
8469// payload_val = init_val;
8470// } else {
8471// LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, "");
8472// payload_val = get_handle_value(g, payload_ptr, child_type);
8473// }
8474// gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val,
8475// variable->type, child_type);
8476// }
8477// gen_var_debug_decl(g, variable);
8478//
8479// return gen_expr(g, then_node);
8480//}
8481//
8482//static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
8483// assert(node->type == NodeTypeIfVarExpr);
8484// assert(node->data.if_var_expr.var_decl.expr);
8485//
8486// AstNodeVariableDeclaration *var_decl = &node->data.if_var_expr.var_decl;
8487// VariableTableEntry *variable = var_decl->variable;
8488//
8489// // test if value is the maybe state
8490// TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
8491// TypeTableEntry *child_type = expr_type->data.maybe.child_type;
8492//
8493// LLVMValueRef init_val = gen_expr(g, var_decl->expr);
8494//
8495//
8496// AstNode *then_node = node->data.if_var_expr.then_block;
8497// AstNode *else_node = node->data.if_var_expr.else_node;
8498// bool maybe_is_ptr = child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
8499//
8500// ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
8501// if (const_val->ok) {
8502// if (const_val->data.x_maybe) {
8503// return gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node);
8504// } else {
8505// return gen_expr(g, else_node);
8506// }
8507// }
8508//
8509// LLVMValueRef cond_value;
8510// if (maybe_is_ptr) {
8511// cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), "");
8512// } else {
8513// LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, init_val, 1, "");
8514// cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, "");
8515// }
8516//
8517// TypeTableEntry *then_type = get_expr_type(then_node);
8518// TypeTableEntry *else_type = get_expr_type(else_node);
8519//
8520// bool use_then_value = type_has_bits(then_type);
8521// bool use_else_value = type_has_bits(else_type);
8522//
8523// LLVMBasicBlockRef then_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeThen");
8524// LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeElse");
8525//
8526// LLVMBasicBlockRef endif_block;
8527// bool then_endif_reachable = then_type->id != TypeTableEntryIdUnreachable;
8528// bool else_endif_reachable = else_type->id != TypeTableEntryIdUnreachable;
8529// if (then_endif_reachable || else_endif_reachable) {
8530// endif_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "MaybeEndIf");
8531// }
8532//
8533// LLVMBuildCondBr(g->builder, cond_value, then_block, else_block);
8534//
8535// LLVMPositionBuilderAtEnd(g->builder, then_block);
8536// LLVMValueRef then_expr_result = gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node);
8537//
8538// if (then_endif_reachable) {
8539// LLVMBuildBr(g->builder, endif_block);
8540// }
8541// LLVMBasicBlockRef after_then_block = LLVMGetInsertBlock(g->builder);
8542//
8543//
8544// LLVMPositionBuilderAtEnd(g->builder, else_block);
8545// LLVMValueRef else_expr_result = gen_expr(g, else_node);
8546// if (else_endif_reachable) {
8547// LLVMBuildBr(g->builder, endif_block);
8548// }
8549// LLVMBasicBlockRef after_else_block = LLVMGetInsertBlock(g->builder);
8550//
8551// if (then_endif_reachable || else_endif_reachable) {
8552// LLVMPositionBuilderAtEnd(g->builder, endif_block);
8553// if (use_then_value && use_else_value) {
8554// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(then_expr_result), "");
8555// LLVMValueRef incoming_values[2] = {then_expr_result, else_expr_result};
8556// LLVMBasicBlockRef incoming_blocks[2] = {after_then_block, after_else_block};
8557// LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2);
8558// return phi;
8559// } else if (use_then_value) {
8560// return then_expr_result;
8561// } else if (use_else_value) {
8562// return else_expr_result;
8563// }
8564// }
8565//
8566// return nullptr;
8567//}
8568//
8569//static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
8570// assert(block_node->type == NodeTypeBlock);
8571//
8572// LLVMValueRef return_value = nullptr;
8573// for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
8574// AstNode *statement_node = block_node->data.block.statements.at(i);
8575// return_value = gen_expr(g, statement_node);
8576// }
8577//
8578// bool end_unreachable = implicit_return_type && implicit_return_type->id == TypeTableEntryIdUnreachable;
8579// if (end_unreachable) {
8580// return nullptr;
8581// }
8582//
8583// gen_defers_for_block(g, block_node->data.block.nested_block, block_node->data.block.child_block,
8584// false, false);
8585//
8586// if (implicit_return_type) {
8587// return gen_return(g, block_node, return_value, ReturnKnowledgeSkipDefers);
8588// } else {
8589// return return_value;
8590// }
8591//}
8592//
8593//static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {
8594// assert(node->type == NodeTypeAsmExpr);
8595//
8596// AstNodeAsmExpr *asm_expr = &node->data.asm_expr;
8597//
8598// Buf *src_template = asm_expr->asm_template;
8599//
8600// Buf llvm_template = BUF_INIT;
8601// buf_resize(&llvm_template, 0);
8602//
8603// for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
8604// AsmToken *asm_token = &asm_expr->token_list.at(token_i);
8605// switch (asm_token->id) {
8606// case AsmTokenIdTemplate:
8607// for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) {
8608// uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));
8609// if (c == '$') {
8610// buf_append_str(&llvm_template, "$$");
8611// } else {
8612// buf_append_char(&llvm_template, c);
8613// }
8614// }
8615// break;
8616// case AsmTokenIdPercent:
8617// buf_append_char(&llvm_template, '%');
8618// break;
8619// case AsmTokenIdVar:
8620// size_t index = find_asm_index(g, node, asm_token);
8621// assert(index < SIZE_MAX);
8622// buf_appendf(&llvm_template, "$%zu", index);
8623// break;
8624// }
8625// }
8626//
8627// Buf constraint_buf = BUF_INIT;
8628// buf_resize(&constraint_buf, 0);
8629//
8630// assert(asm_expr->return_count == 0 || asm_expr->return_count == 1);
8631//
8632// size_t total_constraint_count = asm_expr->output_list.length +
8633// asm_expr->input_list.length +
8634// asm_expr->clobber_list.length;
8635// size_t input_and_output_count = asm_expr->output_list.length +
8636// asm_expr->input_list.length -
8637// asm_expr->return_count;
8638// size_t total_index = 0;
8639// size_t param_index = 0;
8640// LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count);
8641// LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count);
8642// for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {
8643// AsmOutput *asm_output = asm_expr->output_list.at(i);
8644// bool is_return = (asm_output->return_type != nullptr);
8645// assert(*buf_ptr(asm_output->constraint) == '=');
8646// if (is_return) {
8647// buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
8648// } else {
8649// buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1);
8650// }
8651// if (total_index + 1 < total_constraint_count) {
8652// buf_append_char(&constraint_buf, ',');
8653// }
8654//
8655// if (!is_return) {
8656// VariableTableEntry *variable = asm_output->variable;
8657// assert(variable);
8658// param_types[param_index] = LLVMTypeOf(variable->value_ref);
8659// param_values[param_index] = variable->value_ref;
8660// param_index += 1;
8661// }
8662// }
8663// for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
8664// AsmInput *asm_input = asm_expr->input_list.at(i);
8665// buf_append_buf(&constraint_buf, asm_input->constraint);
8666// if (total_index + 1 < total_constraint_count) {
8667// buf_append_char(&constraint_buf, ',');
8668// }
8669//
8670// TypeTableEntry *expr_type = get_expr_type(asm_input->expr);
8671// param_types[param_index] = expr_type->type_ref;
8672// param_values[param_index] = gen_expr(g, asm_input->expr);
8673// }
8674// for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
8675// Buf *clobber_buf = asm_expr->clobber_list.at(i);
8676// buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf));
8677// if (total_index + 1 < total_constraint_count) {
8678// buf_append_char(&constraint_buf, ',');
8679// }
8680// }
8681//
8682// LLVMTypeRef ret_type;
8683// if (asm_expr->return_count == 0) {
8684// ret_type = LLVMVoidType();
8685// } else {
8686// ret_type = get_expr_type(node)->type_ref;
8687// }
8688// LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false);
8689//
8690// bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
8691// LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
8692// buf_ptr(&constraint_buf), is_volatile, false);
8693//
8694// set_debug_source_node(g, node);
8695// return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
8696//}
8697//
8698//static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
8699// assert(node->type == NodeTypeContainerInitExpr);
8700//
8701// TypeTableEntry *type_entry = get_expr_type(node);
8702//
8703//
8704// if (node->data.container_init_expr.enum_type) {
8705// size_t param_count = node->data.container_init_expr.entries.length;
8706// AstNode *arg1_node;
8707// if (param_count == 1) {
8708// arg1_node = node->data.container_init_expr.entries.at(0);
8709// } else {
8710// assert(param_count == 0);
8711// arg1_node = nullptr;
8712// }
8713// return gen_enum_value_expr(g, node->data.container_init_expr.type,
8714// node->data.container_init_expr.enum_type, arg1_node);
8715// }
8716//
8717//
8718// if (type_entry->id == TypeTableEntryIdStruct) {
8719// assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
8720//
8721// size_t src_field_count = type_entry->data.structure.src_field_count;
8722// assert(src_field_count == node->data.container_init_expr.entries.length);
8723//
8724// StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
8725// LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
8726//
8727// for (size_t i = 0; i < src_field_count; i += 1) {
8728// AstNode *field_node = node->data.container_init_expr.entries.at(i);
8729// assert(field_node->type == NodeTypeStructValueField);
8730// TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
8731// if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
8732// continue;
8733// }
8734// assert(buf_eql_buf(type_struct_field->name, field_node->data.struct_val_field.name));
8735//
8736// set_debug_source_node(g, field_node);
8737// LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
8738// AstNode *expr_node = field_node->data.struct_val_field.expr;
8739// LLVMValueRef value = gen_expr(g, expr_node);
8740// gen_assign_raw(g, field_node, BinOpTypeAssign, field_ptr, value,
8741// type_struct_field->type_entry, get_expr_type(expr_node));
8742// }
8743//
8744// return tmp_struct_ptr;
8745// } else if (type_entry->id == TypeTableEntryIdVoid) {
8746// assert(node->data.container_init_expr.entries.length == 0);
8747// return nullptr;
8748// } else if (type_entry->id == TypeTableEntryIdArray) {
8749// StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
8750// LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr;
8751//
8752// size_t field_count = type_entry->data.array.len;
8753// assert(field_count == node->data.container_init_expr.entries.length);
8754//
8755// TypeTableEntry *child_type = type_entry->data.array.child_type;
8756//
8757// for (size_t i = 0; i < field_count; i += 1) {
8758// AstNode *field_node = node->data.container_init_expr.entries.at(i);
8759// LLVMValueRef elem_val = gen_expr(g, field_node);
8760//
8761// LLVMValueRef indices[] = {
8762// LLVMConstNull(g->builtin_types.entry_usize->type_ref),
8763// LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false),
8764// };
8765// set_debug_source_node(g, field_node);
8766// LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
8767// gen_assign_raw(g, field_node, BinOpTypeAssign, elem_ptr, elem_val,
8768// child_type, get_expr_type(field_node));
8769// }
8770//
8771// return tmp_array_ptr;
8772// } else {
8773// zig_unreachable();
8774// }
8775//}
8776//
8777//static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
8778// assert(node->type == NodeTypeWhileExpr);
8779// assert(node->data.while_expr.condition);
8780// assert(node->data.while_expr.body);
8781//
8782// //AstNode *continue_expr_node = node->data.while_expr.continue_expr;
8783//
8784// bool condition_always_true = node->data.while_expr.condition_always_true;
8785// //bool contains_break = node->data.while_expr.contains_break;
8786// if (condition_always_true) {
8787// // generate a forever loop
8788// zig_panic("TODO IR");
8789//
8790// //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileBody");
8791// //LLVMBasicBlockRef continue_block = continue_expr_node ?
8792// // LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileContinue") : body_block;
8793// //LLVMBasicBlockRef end_block = nullptr;
8794// //if (contains_break) {
8795// // end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "WhileEnd");
8796// //}
8797//
8798// //set_debug_source_node(g, node);
8799// //LLVMBuildBr(g->builder, body_block);
8800//
8801// //if (continue_expr_node) {
8802// // LLVMPositionBuilderAtEnd(g->builder, continue_block);
8803//
8804// // gen_expr(g, continue_expr_node);
8805//
8806// // set_debug_source_node(g, node);
8807// // LLVMBuildBr(g->builder, body_block);
8808// //}
8809//
8810// //LLVMPositionBuilderAtEnd(g->builder, body_block);
8811// //g->break_block_stack.append(end_block);
8812// //g->continue_block_stack.append(continue_block);
8813// //gen_expr(g, node->data.while_expr.body);
8814// //g->break_block_stack.pop();
8815// //g->continue_block_stack.pop();
8816//
8817// //if (get_expr_type(node->data.while_expr.body)->id != TypeTableEntryIdUnreachable) {
8818// // set_debug_source_node(g, node);
8819// // LLVMBuildBr(g->builder, continue_block);
8820// //}
8821//
8822// //if (contains_break) {
8823// // LLVMPositionBuilderAtEnd(g->builder, end_block);
8824// //}
8825// } else {
8826// zig_panic("moved to ir.cpp");
8827// }
8828//
8829// return nullptr;
8830//}
8831
8832//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
8833// assert(node->type == NodeTypeBreak);
8834// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
8835//
8836// set_debug_source_node(g, node);
8837// return LLVMBuildBr(g->builder, dest_block);
8838//}
8839
8840//static LLVMValueRef gen_continue(CodeGen *g, AstNode *node) {
8841// assert(node->type == NodeTypeContinue);
8842// LLVMBasicBlockRef dest_block = g->continue_block_stack.last();
8843//
8844// set_debug_source_node(g, node);
8845// return LLVMBuildBr(g->builder, dest_block);
8846//}
8847//
8848//static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVariableDeclaration *var_decl,
8849// bool unwrap_maybe, LLVMValueRef *init_value, TypeTableEntry **expr_type, bool var_is_ptr)
8850//{
8851// VariableTableEntry *variable = var_decl->variable;
8852//
8853// assert(variable);
8854//
8855// if (var_decl->expr) {
8856// *init_value = gen_expr(g, var_decl->expr);
8857// *expr_type = get_expr_type(var_decl->expr);
8858// }
8859// if (!type_has_bits(variable->type)) {
8860// return nullptr;
8861// }
8862//
8863// bool have_init_expr = false;
8864// bool want_zeroes = false;
8865// if (var_decl->expr) {
8866// ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val;
8867// if (!const_val->ok || const_val->special == ConstValSpecialOther) {
8868// have_init_expr = true;
8869// }
8870// if (const_val->ok && const_val->special == ConstValSpecialZeroes) {
8871// want_zeroes = true;
8872// }
8873// }
8874// if (have_init_expr) {
8875// TypeTableEntry *expr_type = get_expr_type(var_decl->expr);
8876// LLVMValueRef value;
8877// if (unwrap_maybe) {
8878// assert(var_decl->expr);
8879// assert(expr_type->id == TypeTableEntryIdMaybe);
8880// value = gen_unwrap_maybe(g, var_decl->expr, *init_value);
8881// expr_type = expr_type->data.maybe.child_type;
8882// } else {
8883// value = *init_value;
8884// }
8885// gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
8886// value, variable->type, expr_type);
8887// } else {
8888// bool ignore_uninit = false;
8889// // handle runtime stack allocation
8890// if (var_decl->type) {
8891// TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
8892// if (var_type->id == TypeTableEntryIdStruct &&
8893// var_type->data.structure.is_slice)
8894// {
8895// assert(var_decl->type->type == NodeTypeArrayType);
8896// AstNode *size_node = var_decl->type->data.array_type.size;
8897// if (size_node) {
8898// ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
8899// if (!const_val->ok) {
8900// TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
8901// assert(ptr_type->id == TypeTableEntryIdPointer);
8902// TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
8903//
8904// LLVMValueRef size_val = gen_expr(g, size_node);
8905//
8906// set_debug_source_node(g, source_node);
8907// LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref,
8908// size_val, "");
8909//
8910// size_t ptr_index = var_type->data.structure.fields[0].gen_index;
8911// assert(ptr_index != SIZE_MAX);
8912// size_t len_index = var_type->data.structure.fields[1].gen_index;
8913// assert(len_index != SIZE_MAX);
8914//
8915// // store the freshly allocated pointer in the unknown size array struct
8916// LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder,
8917// variable->value_ref, ptr_index, "");
8918// LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr);
8919//
8920// // store the size in the len field
8921// LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder,
8922// variable->value_ref, len_index, "");
8923// LLVMBuildStore(g->builder, size_val, len_field_ptr);
8924//
8925// // don't clobber what we just did with debug initialization
8926// ignore_uninit = true;
8927// }
8928// }
8929// }
8930// }
8931// bool want_safe = want_debug_safety(g, source_node);
8932// if (!ignore_uninit && (want_safe || want_zeroes)) {
8933// TypeTableEntry *usize = g->builtin_types.entry_usize;
8934// uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, variable->type->type_ref);
8935// uint64_t align_bytes = get_memcpy_align(g, variable->type);
8936//
8937// // memset uninitialized memory to 0xa
8938// set_debug_source_node(g, source_node);
8939// LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
8940// LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), want_zeroes ? 0x00 : 0xaa, false);
8941// LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");
8942// LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
8943// LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), align_bytes, false);
8944// LLVMValueRef params[] = {
8945// dest_ptr,
8946// fill_char,
8947// byte_count,
8948// align_in_bytes,
8949// LLVMConstNull(LLVMInt1Type()), // is volatile
8950// };
8951//
8952// LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
8953// }
8954// }
8955//
8956// gen_var_debug_decl(g, variable);
8957// return nullptr;
8958//}
8959//
8960//static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
8961// assert(node->type == NodeTypeSwitchExpr);
8962//
8963// if (node->data.switch_expr.const_chosen_prong_index != SIZE_MAX) {
8964// AstNode *prong_node = node->data.switch_expr.prongs.at(node->data.switch_expr.const_chosen_prong_index);
8965// assert(prong_node->type == NodeTypeSwitchProng);
8966// AstNode *prong_expr = prong_node->data.switch_prong.expr;
8967// return gen_expr(g, prong_expr);
8968// }
8969//
8970// TypeTableEntry *target_type = get_expr_type(node->data.switch_expr.expr);
8971// LLVMValueRef target_value_handle = gen_expr(g, node->data.switch_expr.expr);
8972// LLVMValueRef target_value;
8973// if (handle_is_ptr(target_type)) {
8974// if (target_type->id == TypeTableEntryIdEnum) {
8975// set_debug_source_node(g, node);
8976// LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
8977// target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
8978// } else if (target_type->id == TypeTableEntryIdErrorUnion) {
8979// set_debug_source_node(g, node);
8980// LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle, 0, "");
8981// target_value = LLVMBuildLoad(g->builder, tag_field_ptr, "");
8982// } else {
8983// zig_unreachable();
8984// }
8985// } else {
8986// target_value = target_value_handle;
8987// }
8988//
8989//
8990// TypeTableEntry *switch_type = get_expr_type(node);
8991// bool result_has_bits = type_has_bits(switch_type);
8992// bool end_unreachable = (switch_type->id == TypeTableEntryIdUnreachable);
8993//
8994// LLVMBasicBlockRef end_block = end_unreachable ?
8995// nullptr : LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchEnd");
8996// LLVMBasicBlockRef else_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchElse");
8997// size_t prong_count = node->data.switch_expr.prongs.length;
8998//
8999// set_debug_source_node(g, node);
9000// LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_value, else_block, prong_count);
9001//
9002// ZigList<LLVMValueRef> incoming_values = {0};
9003// ZigList<LLVMBasicBlockRef> incoming_blocks = {0};
9004//
9005// AstNode *else_prong = nullptr;
9006// for (size_t prong_i = 0; prong_i < prong_count; prong_i += 1) {
9007// AstNode *prong_node = node->data.switch_expr.prongs.at(prong_i);
9008// VariableTableEntry *prong_var = prong_node->data.switch_prong.var;
9009//
9010// LLVMBasicBlockRef prong_block;
9011// if (prong_node->data.switch_prong.items.length == 0) {
9012// assert(!else_prong);
9013// else_prong = prong_node;
9014// prong_block = else_block;
9015// } else {
9016// prong_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchProng");
9017// size_t prong_item_count = prong_node->data.switch_prong.items.length;
9018// bool make_item_blocks = prong_var && prong_item_count > 1;
9019//
9020// for (size_t item_i = 0; item_i < prong_item_count; item_i += 1) {
9021// AstNode *item_node = prong_node->data.switch_prong.items.at(item_i);
9022//
9023// assert(item_node->type != NodeTypeSwitchRange);
9024// LLVMValueRef val;
9025// if (target_type->id == TypeTableEntryIdEnum ||
9026// target_type->id == TypeTableEntryIdErrorUnion)
9027// {
9028// assert(item_node->type == NodeTypeSymbol);
9029// TypeEnumField *enum_field = nullptr;
9030// uint32_t err_value = 0;
9031// if (target_type->id == TypeTableEntryIdEnum) {
9032// enum_field = item_node->data.symbol_expr.enum_field;
9033// assert(enum_field);
9034// val = LLVMConstInt(target_type->data.enumeration.tag_type->type_ref,
9035// enum_field->value, false);
9036// } else if (target_type->id == TypeTableEntryIdErrorUnion) {
9037// err_value = item_node->data.symbol_expr.err_value;
9038// val = LLVMConstInt(g->err_tag_type->type_ref, err_value, false);
9039// } else {
9040// zig_unreachable();
9041// }
9042//
9043// if (prong_var && type_has_bits(prong_var->type)) {
9044// LLVMBasicBlockRef item_block;
9045//
9046// if (make_item_blocks) {
9047// item_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "SwitchProngItem");
9048// LLVMAddCase(switch_instr, val, item_block);
9049// LLVMPositionBuilderAtEnd(g->builder, item_block);
9050// } else {
9051// LLVMAddCase(switch_instr, val, prong_block);
9052// LLVMPositionBuilderAtEnd(g->builder, prong_block);
9053// }
9054//
9055// AstNode *var_node = prong_node->data.switch_prong.var_symbol;
9056// set_debug_source_node(g, var_node);
9057// if (prong_node->data.switch_prong.var_is_target_expr) {
9058// gen_assign_raw(g, var_node, BinOpTypeAssign,
9059// prong_var->value_ref, target_value, prong_var->type, target_type);
9060// } else if (target_type->id == TypeTableEntryIdEnum) {
9061// assert(enum_field);
9062// assert(type_has_bits(enum_field->type_entry));
9063// LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, target_value_handle,
9064// 1, "");
9065// LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr,
9066// LLVMPointerType(enum_field->type_entry->type_ref, 0), "");
9067// LLVMValueRef handle_val = get_handle_value(g, bitcasted_union_field_ptr,
9068// enum_field->type_entry);
9069//
9070// gen_assign_raw(g, var_node, BinOpTypeAssign,
9071// prong_var->value_ref, handle_val, prong_var->type, enum_field->type_entry);
9072// } else if (target_type->id == TypeTableEntryIdErrorUnion) {
9073// if (err_value == 0) {
9074// // variable is the payload
9075// LLVMValueRef err_payload_ptr = LLVMBuildStructGEP(g->builder,
9076// target_value_handle, 1, "");
9077// LLVMValueRef handle_val = get_handle_value(g, err_payload_ptr, prong_var->type);
9078// gen_assign_raw(g, var_node, BinOpTypeAssign,
9079// prong_var->value_ref, handle_val, prong_var->type, prong_var->type);
9080// } else {
9081// // variable is the pure error value
9082// LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder,
9083// target_value_handle, 0, "");
9084// LLVMValueRef handle_val = LLVMBuildLoad(g->builder, err_tag_ptr, "");
9085// gen_assign_raw(g, var_node, BinOpTypeAssign,
9086// prong_var->value_ref, handle_val, prong_var->type, g->err_tag_type);
9087// }
9088// } else {
9089// zig_unreachable();
9090// }
9091// if (make_item_blocks) {
9092// set_debug_source_node(g, var_node);
9093// LLVMBuildBr(g->builder, prong_block);
9094// }
9095// } else {
9096// LLVMAddCase(switch_instr, val, prong_block);
9097// }
9098// } else {
9099// assert(get_resolved_expr(item_node)->const_val.ok);
9100// val = gen_expr(g, item_node);
9101// LLVMAddCase(switch_instr, val, prong_block);
9102// }
9103// }
9104// }
9105//
9106// LLVMPositionBuilderAtEnd(g->builder, prong_block);
9107// AstNode *prong_expr = prong_node->data.switch_prong.expr;
9108// LLVMValueRef prong_val = gen_expr(g, prong_expr);
9109//
9110// if (get_expr_type(prong_expr)->id != TypeTableEntryIdUnreachable) {
9111// set_debug_source_node(g, prong_expr);
9112// LLVMBuildBr(g->builder, end_block);
9113// incoming_values.append(prong_val);
9114// incoming_blocks.append(LLVMGetInsertBlock(g->builder));
9115// }
9116// }
9117//
9118// if (!else_prong) {
9119// LLVMPositionBuilderAtEnd(g->builder, else_block);
9120// set_debug_source_node(g, node);
9121// if (want_debug_safety(g, node)) {
9122// gen_debug_safety_crash(g);
9123// } else {
9124// LLVMBuildUnreachable(g->builder);
9125// }
9126// }
9127//
9128// if (end_unreachable) {
9129// return nullptr;
9130// }
9131//
9132// LLVMPositionBuilderAtEnd(g->builder, end_block);
9133//
9134// if (result_has_bits) {
9135// set_debug_source_node(g, node);
9136// LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMTypeOf(incoming_values.at(0)), "");
9137// LLVMAddIncoming(phi, incoming_values.items, incoming_blocks.items, incoming_values.length);
9138// return phi;
9139// } else {
9140// return nullptr;
9141// }
9142//}
9143//
9144//static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
9145// assert(node->type == NodeTypeArrayAccessExpr);
9146//
9147// LLVMValueRef ptr = gen_array_ptr(g, node);
9148// TypeTableEntry *child_type;
9149// TypeTableEntry *array_type = get_expr_type(node->data.array_access_expr.array_ref_expr);
9150// if (array_type->id == TypeTableEntryIdPointer) {
9151// child_type = array_type->data.pointer.child_type;
9152// } else if (array_type->id == TypeTableEntryIdStruct) {
9153// assert(array_type->data.structure.is_slice);
9154// TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
9155// assert(child_ptr_type->id == TypeTableEntryIdPointer);
9156// child_type = child_ptr_type->data.pointer.child_type;
9157// } else if (array_type->id == TypeTableEntryIdArray) {
9158// child_type = array_type->data.array.child_type;
9159// } else {
9160// zig_unreachable();
9161// }
9162//
9163// if (is_lvalue || !ptr || handle_is_ptr(child_type)) {
9164// return ptr;
9165// } else {
9166// return LLVMBuildLoad(g->builder, ptr, "");
9167// }
9168//}
9169//
9170//static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
9171// assert(node->type == NodeTypeFieldAccessExpr);
9172//
9173// AstNode *struct_expr = node->data.field_access_expr.struct_expr;
9174// TypeTableEntry *struct_type = get_expr_type(struct_expr);
9175//
9176// if (struct_type->id == TypeTableEntryIdArray) {
9177// Buf *name = node->data.field_access_expr.field_name;
9178// assert(buf_eql_str(name, "len"));
9179// return LLVMConstInt(g->builtin_types.entry_usize->type_ref,
9180// struct_type->data.array.len, false);
9181// } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
9182// struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
9183// {
9184// TypeTableEntry *type_entry;
9185// LLVMValueRef ptr = gen_field_ptr(g, node, &type_entry);
9186// if (is_lvalue || handle_is_ptr(type_entry)) {
9187// return ptr;
9188// } else {
9189// return LLVMBuildLoad(g->builder, ptr, "");
9190// }
9191// } else if (struct_type->id == TypeTableEntryIdMetaType) {
9192// assert(!is_lvalue);
9193// TypeTableEntry *child_type = get_type_for_type_node(struct_expr);
9194// if (child_type->id == TypeTableEntryIdEnum) {
9195// return gen_enum_value_expr(g, node, child_type, nullptr);
9196// } else {
9197// zig_unreachable();
9198// }
9199// } else if (struct_type->id == TypeTableEntryIdNamespace) {
9200// VariableTableEntry *variable = get_resolved_expr(node)->variable;
9201// assert(variable);
9202// return gen_variable(g, node, variable);
9203// } else {
9204// zig_unreachable();
9205// }
9206//}
9207//
9208//static LLVMValueRef gen_return(CodeGen *g, AstNode *source_node, LLVMValueRef value, ReturnKnowledge rk) {
9209// BlockContext *defer_inner_block = source_node->block_context;
9210// BlockContext *defer_outer_block = source_node->block_context->fn_entry->fn_def_node->block_context;
9211// if (rk == ReturnKnowledgeUnknown) {
9212// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
9213// // generate branching code that checks the return value and generates defers
9214// // if the return value is error
9215// zig_panic("TODO");
9216// }
9217// } else if (rk != ReturnKnowledgeSkipDefers) {
9218// gen_defers_for_block(g, defer_inner_block, defer_outer_block,
9219// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
9220// }
9221//
9222// TypeTableEntry *return_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
9223// bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
9224// if (handle_is_ptr(return_type)) {
9225// if (is_extern) {
9226// LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
9227// LLVMBuildRet(g->builder, by_val_value);
9228// } else {
9229// assert(g->cur_ret_ptr);
9230// gen_assign_raw(g, source_node, BinOpTypeAssign, g->cur_ret_ptr, value, return_type, return_type);
9231// LLVMBuildRetVoid(g->builder);
9232// }
9233// } else {
9234// LLVMBuildRet(g->builder, value);
9235// }
9236// return nullptr;
9237//}
9238//
9239//static LLVMValueRef gen_goto(CodeGen *g, AstNode *node) {
9240// assert(node->type == NodeTypeGoto);
9241//
9242// // generate defers for blocks that we exit
9243// LabelTableEntry *label = node->data.goto_expr.label_entry;
9244// BlockContext *this_context = node->block_context;
9245// BlockContext *target_context = label->decl_node->block_context;
9246// gen_defers_for_block(g, this_context, target_context, false, false);
9247//
9248// set_debug_source_node(g, node);
9249// LLVMBuildBr(g->builder, node->data.goto_expr.label_entry->basic_block);
9250// return nullptr;
9251//}
9252//
9253//static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
9254// AstNode *init_expr = node->data.variable_declaration.expr;
9255// if (node->data.variable_declaration.is_const && init_expr) {
9256// TypeTableEntry *init_expr_type = get_expr_type(init_expr);
9257// if (init_expr_type->id == TypeTableEntryIdNumLitFloat ||
9258// init_expr_type->id == TypeTableEntryIdNumLitInt)
9259// {
9260// return nullptr;
9261// }
9262// }
9263//
9264// LLVMValueRef init_val = nullptr;
9265// TypeTableEntry *init_val_type;
9266// return gen_var_decl_raw(g, node, &node->data.variable_declaration, false, &init_val, &init_val_type, false);
9267//}
9268//
9269//static LLVMValueRef get_int_builtin_fn(CodeGen *g, TypeTableEntry *int_type, BuiltinFnId fn_id) {
9270// // [0-ctz,1-clz][0-8,1-16,2-32,3-64]
9271// size_t index0 = (fn_id == BuiltinFnIdCtz) ? 0 : 1;
9272// size_t index1 = bits_index(int_type->data.integral.bit_count);
9273// LLVMValueRef *fn = &g->int_builtin_fns[index0][index1];
9274// if (!*fn) {
9275// const char *fn_name = (fn_id == BuiltinFnIdCtz) ? "cttz" : "ctlz";
9276// Buf *llvm_name = buf_sprintf("llvm.%s.i%zu", fn_name, int_type->data.integral.bit_count);
9277// LLVMTypeRef param_types[] = {
9278// int_type->type_ref,
9279// LLVMInt1Type(),
9280// };
9281// LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, 2, false);
9282// *fn = LLVMAddFunction(g->module, buf_ptr(llvm_name), fn_type);
9283// }
9284// return *fn;
9285//}
9286//
9287//static LLVMValueRef gen_fence(CodeGen *g, AstNode *node) {
9288// assert(node->type == NodeTypeFnCallExpr);
9289//
9290// AstNode *atomic_order_arg = node->data.fn_call_expr.params.at(0);
9291// ConstExprValue *atomic_order_val = &get_resolved_expr(atomic_order_arg)->const_val;
9292//
9293// assert(atomic_order_val->ok);
9294//
9295// LLVMAtomicOrdering atomic_order = to_LLVMAtomicOrdering((AtomicOrder)atomic_order_val->data.x_enum.tag);
9296//
9297// LLVMBuildFence(g->builder, atomic_order, false, "");
9298// return nullptr;
9299//}
9300//
9301//static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
9302// switch (atomic_order) {
9303// case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
9304// case AtomicOrderMonotonic: return LLVMAtomicOrderingMonotonic;
9305// case AtomicOrderAcquire: return LLVMAtomicOrderingAcquire;
9306// case AtomicOrderRelease: return LLVMAtomicOrderingRelease;
9307// case AtomicOrderAcqRel: return LLVMAtomicOrderingAcquireRelease;
9308// case AtomicOrderSeqCst: return LLVMAtomicOrderingSequentiallyConsistent;
9309// }
9310// zig_unreachable();
9311//}
9312//
9313//static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref) {
9314// TypeTableEntry *type_entry = get_expr_type(node);
9315// assert(type_entry->id == TypeTableEntryIdMaybe);
9316// TypeTableEntry *child_type = type_entry->data.maybe.child_type;
9317// if (child_type->id == TypeTableEntryIdPointer ||
9318// child_type->id == TypeTableEntryIdFn)
9319// {
9320// return maybe_struct_ref;
9321// } else {
9322// LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, 0, "");
9323// return get_handle_value(g, maybe_field_ptr, child_type);
9324// }
9325//}
9326//
9327//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
9328// size_t result = 0;
9329// while (inner_block != outer_block) {
9330// if (inner_block->node->type == NodeTypeDefer &&
9331// (inner_block->node->data.defer.kind == ReturnKindError ||
9332// inner_block->node->data.defer.kind == ReturnKindMaybe))
9333// {
9334// result += 1;
9335// }
9336// inner_block = inner_block->parent;
9337// }
9338// return result;
9339//}
9340//
9341//static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) {
9342// const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2;
9343// size_t len = tok->end - tok->start - 2;
9344// size_t result = 0;
9345// for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {
9346// AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
9347// if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) {
9348// return result;
9349// }
9350// }
9351// for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {
9352// AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
9353// if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) {
9354// return result;
9355// }
9356// }
9357// return SIZE_MAX;
9358//}
9359//
9360//static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
9361// assert(node->type == NodeTypeSymbol);
9362// VariableTableEntry *variable = get_resolved_expr(node)->variable;
9363// if (variable) {
9364// return gen_variable(g, node, variable);
9365// }
9366//
9367// zig_unreachable();
9368//}
9369//
9370//static LLVMValueRef gen_label(CodeGen *g, AstNode *node) {
9371// assert(node->type == NodeTypeLabel);
9372//
9373// LabelTableEntry *label = node->data.label.label_entry;
9374// assert(label);
9375//
9376// LLVMBasicBlockRef basic_block = label->basic_block;
9377// if (label->entered_from_fallthrough) {
9378// set_debug_source_node(g, node);
9379// LLVMBuildBr(g->builder, basic_block);
9380// }
9381// LLVMPositionBuilderAtEnd(g->builder, basic_block);
9382// return nullptr;
9383//}
9384//
9385//static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTableEntry *variable) {
9386// if (!type_has_bits(variable->type)) {
9387// return nullptr;
9388// } else {
9389// assert(variable->value_ref);
9390// return get_handle_value(g, variable->value_ref, variable->type);
9391// }
9392//}
9393//