authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 15:01:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-21 15:01:21-05:00
log052cd44588a94550a431adc6d1ff5af7e4439c88
tree14ca07924d517b717cfcabd0aa9baf4f75963f0c
parente80e8a80993734f22e9e9c1b8ba078b0b9b946c3

IR: fix codegen for arrays


4 files changed, 253 insertions(+), 229 deletions(-)

src/all_types.hpp+1
......@@ -1626,6 +1626,7 @@ struct IrInstructionElemPtr {
16261626 IrInstruction *array_ptr;
16271627 IrInstruction *elem_index;
16281628 bool is_const;
1629 bool safety_check_on;
16291630};
16301631
16311632struct IrInstructionVarPtr {
src/codegen.cpp+237-117
......@@ -455,55 +455,6 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, AstNode *source_node, TypeT
455455 }
456456}
457457
458static LLVMValueRef gen_array_elem_ptr(CodeGen *g, AstNode *source_node, LLVMValueRef array_ptr,
459 TypeTableEntry *array_type, LLVMValueRef subscript_value)
460{
461 assert(subscript_value);
462
463 if (!type_has_bits(array_type)) {
464 return nullptr;
465 }
466
467 if (array_type->id == TypeTableEntryIdArray) {
468 if (want_debug_safety(g, source_node)) {
469 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
470 array_type->data.array.len, false);
471 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
472 }
473 LLVMValueRef indices[] = {
474 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
475 subscript_value
476 };
477 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
478 } else if (array_type->id == TypeTableEntryIdPointer) {
479 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
480 LLVMValueRef indices[] = {
481 subscript_value
482 };
483 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
484 } else if (array_type->id == TypeTableEntryIdStruct) {
485 assert(array_type->data.structure.is_slice);
486 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
487 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
488
489 if (want_debug_safety(g, source_node)) {
490 size_t len_index = array_type->data.structure.fields[1].gen_index;
491 assert(len_index != SIZE_MAX);
492 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
493 LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, "");
494 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
495 }
496
497 size_t ptr_index = array_type->data.structure.fields[0].gen_index;
498 assert(ptr_index != SIZE_MAX);
499 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
500 LLVMValueRef ptr = LLVMBuildLoad(g->builder, ptr_ptr, "");
501 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
502 } else {
503 zig_unreachable();
504 }
505}
506
507458static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op,
508459 LLVMValueRef val1, LLVMValueRef val2)
509460{
......@@ -640,83 +591,98 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
640591 return nullptr;
641592}
642593
643static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
644 IrInstructionBinOp *bin_op_instruction)
594static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
595 LLVMValueRef val1, LLVMValueRef val2)
645596{
646 IrBinOp op_id = bin_op_instruction->op_id;
647 LLVMValueRef op1 = ir_llvm_value(g, bin_op_instruction->op1);
648 LLVMValueRef op2 = ir_llvm_value(g, bin_op_instruction->op2);
649 if (op_id == IrBinOpBoolOr) {
650 return LLVMBuildOr(g->builder, op1, op2, "");
651 } else if (op_id == IrBinOpBoolAnd) {
652 return LLVMBuildAnd(g->builder, op1, op2, "");
597 // for unsigned left shifting, we do the wrapping shift, then logically shift
598 // right the same number of bits
599 // if the values don't match, we have an overflow
600 // for signed left shifting we do the same except arithmetic shift right
601
602 assert(type_entry->id == TypeTableEntryIdInt);
603
604 LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
605 LLVMValueRef orig_val;
606 if (type_entry->data.integral.is_signed) {
607 orig_val = LLVMBuildAShr(g->builder, result, val2, "");
653608 } else {
654 zig_unreachable();
609 orig_val = LLVMBuildLShr(g->builder, result, val2, "");
655610 }
611 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
612
613 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
614 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
615 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
616
617 LLVMPositionBuilderAtEnd(g->builder, fail_block);
618 gen_debug_safety_crash(g);
619
620 LLVMPositionBuilderAtEnd(g->builder, ok_block);
621 return result;
656622}
657623
658static LLVMValueRef ir_render_bin_op_cmp(CodeGen *g, IrExecutable *executable,
659 IrInstructionBinOp *bin_op_instruction)
624static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
625 TypeTableEntry *type_entry, bool exact)
660626{
661 IrBinOp op_id = bin_op_instruction->op_id;
662 LLVMValueRef val1 = ir_llvm_value(g, bin_op_instruction->op1);
663 LLVMValueRef val2 = ir_llvm_value(g, bin_op_instruction->op2);
664
665 TypeTableEntry *op1_type = bin_op_instruction->op1->type_entry;
666 TypeTableEntry *op2_type = bin_op_instruction->op2->type_entry;
667 assert(op1_type == op2_type);
668
669 if (op1_type->id == TypeTableEntryIdFloat) {
670 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
671 return LLVMBuildFCmp(g->builder, pred, val1, val2, "");
672 } else if (op1_type->id == TypeTableEntryIdInt) {
673 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1_type->data.integral.is_signed);
674 return LLVMBuildICmp(g->builder, pred, val1, val2, "");
675 } else if (op1_type->id == TypeTableEntryIdEnum) {
676 if (op1_type->data.enumeration.gen_field_count == 0) {
677 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
678 return LLVMBuildICmp(g->builder, pred, val1, val2, "");
627
628 if (want_debug_safety(g, source_node)) {
629 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
630 LLVMValueRef is_zero_bit;
631 if (type_entry->id == TypeTableEntryIdInt) {
632 is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
633 } else if (type_entry->id == TypeTableEntryIdFloat) {
634 is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
679635 } else {
680636 zig_unreachable();
681637 }
682 } else if (op1_type->id == TypeTableEntryIdPureError ||
683 op1_type->id == TypeTableEntryIdPointer ||
684 op1_type->id == TypeTableEntryIdBool)
685 {
686 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
687 return LLVMBuildICmp(g->builder, pred, val1, val2, "");
688 } else {
689 zig_unreachable();
638 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk");
639 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail");
640 LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);
641
642 LLVMPositionBuilderAtEnd(g->builder, fail_block);
643 gen_debug_safety_crash(g);
644
645 LLVMPositionBuilderAtEnd(g->builder, ok_block);
690646 }
691}
692647
693static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
694 IrInstructionBinOp *bin_op_instruction)
695{
696 IrBinOp op_id = bin_op_instruction->op_id;
697 IrInstruction *op1 = bin_op_instruction->op1;
698 IrInstruction *op2 = bin_op_instruction->op2;
648 if (type_entry->id == TypeTableEntryIdFloat) {
649 assert(!exact);
650 return LLVMBuildFDiv(g->builder, val1, val2, "");
651 }
699652
700 assert(op1->type_entry == op2->type_entry);
653 assert(type_entry->id == TypeTableEntryIdInt);
701654
702 LLVMValueRef op1_value = ir_llvm_value(g, op1);
703 LLVMValueRef op2_value = ir_llvm_value(g, op2);
655 if (exact) {
656 if (want_debug_safety(g, source_node)) {
657 LLVMValueRef remainder_val;
658 if (type_entry->data.integral.is_signed) {
659 remainder_val = LLVMBuildSRem(g->builder, val1, val2, "");
660 } else {
661 remainder_val = LLVMBuildURem(g->builder, val1, val2, "");
662 }
663 LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
664 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
704665
705 if (op1->type_entry->id == TypeTableEntryIdFloat) {
706 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
707 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
708 bool is_wrapping = (op_id == IrBinOpAddWrap);
709 if (is_wrapping) {
710 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
711 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
712 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);
713 } else if (op1->type_entry->data.integral.is_signed) {
714 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
666 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactOk");
667 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactFail");
668 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
669
670 LLVMPositionBuilderAtEnd(g->builder, fail_block);
671 gen_debug_safety_crash(g);
672
673 LLVMPositionBuilderAtEnd(g->builder, ok_block);
674 }
675 if (type_entry->data.integral.is_signed) {
676 return LLVMBuildExactSDiv(g->builder, val1, val2, "");
715677 } else {
716 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
678 return ZigLLVMBuildExactUDiv(g->builder, val1, val2, "");
717679 }
718680 } else {
719 zig_unreachable();
681 if (type_entry->data.integral.is_signed) {
682 return LLVMBuildSDiv(g->builder, val1, val2, "");
683 } else {
684 return LLVMBuildUDiv(g->builder, val1, val2, "");
685 }
720686 }
721687}
722688
......@@ -724,37 +690,146 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
724690 IrInstructionBinOp *bin_op_instruction)
725691{
726692 IrBinOp op_id = bin_op_instruction->op_id;
693 IrInstruction *op1 = bin_op_instruction->op1;
694 IrInstruction *op2 = bin_op_instruction->op2;
695 AstNode *source_node = bin_op_instruction->base.source_node;
696
697 assert(op1->type_entry == op2->type_entry);
698
699 LLVMValueRef op1_value = ir_llvm_value(g, op1);
700 LLVMValueRef op2_value = ir_llvm_value(g, op2);
727701 switch (op_id) {
728702 case IrBinOpInvalid:
729703 case IrBinOpArrayCat:
730704 case IrBinOpArrayMult:
731705 zig_unreachable();
732706 case IrBinOpBoolOr:
707 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
733708 case IrBinOpBoolAnd:
734 return ir_render_bin_op_bool(g, executable, bin_op_instruction);
709 return LLVMBuildAnd(g->builder, op1_value, op2_value, "");
735710 case IrBinOpCmpEq:
736711 case IrBinOpCmpNotEq:
737712 case IrBinOpCmpLessThan:
738713 case IrBinOpCmpGreaterThan:
739714 case IrBinOpCmpLessOrEq:
740715 case IrBinOpCmpGreaterOrEq:
741 return ir_render_bin_op_cmp(g, executable, bin_op_instruction);
716 if (op1->type_entry->id == TypeTableEntryIdFloat) {
717 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
718 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
719 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
720 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1->type_entry->data.integral.is_signed);
721 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
722 } else if (op1->type_entry->id == TypeTableEntryIdEnum) {
723 if (op1->type_entry->data.enumeration.gen_field_count == 0) {
724 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
725 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
726 } else {
727 zig_unreachable();
728 }
729 } else if (op1->type_entry->id == TypeTableEntryIdPureError ||
730 op1->type_entry->id == TypeTableEntryIdPointer ||
731 op1->type_entry->id == TypeTableEntryIdBool)
732 {
733 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
734 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
735 } else {
736 zig_unreachable();
737 }
742738 case IrBinOpAdd:
743739 case IrBinOpAddWrap:
744 return ir_render_bin_op_add(g, executable, bin_op_instruction);
740 if (op1->type_entry->id == TypeTableEntryIdFloat) {
741 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
742 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
743 bool is_wrapping = (op_id == IrBinOpAddWrap);
744 if (is_wrapping) {
745 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
746 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
747 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);
748 } else if (op1->type_entry->data.integral.is_signed) {
749 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
750 } else {
751 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
752 }
753 } else {
754 zig_unreachable();
755 }
745756 case IrBinOpBinOr:
757 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
746758 case IrBinOpBinXor:
759 return LLVMBuildXor(g->builder, op1_value, op2_value, "");
747760 case IrBinOpBinAnd:
761 return LLVMBuildAnd(g->builder, op1_value, op2_value, "");
748762 case IrBinOpBitShiftLeft:
749763 case IrBinOpBitShiftLeftWrap:
764 {
765 assert(op1->type_entry->id == TypeTableEntryIdInt);
766 bool is_wrapping = (op_id == IrBinOpBitShiftLeftWrap);
767 if (is_wrapping) {
768 return LLVMBuildShl(g->builder, op1_value, op2_value, "");
769 } else if (want_debug_safety(g, source_node)) {
770 return gen_overflow_shl_op(g, op1->type_entry, op1_value, op2_value);
771 } else if (op1->type_entry->data.integral.is_signed) {
772 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");
773 } else {
774 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_value, "");
775 }
776 }
750777 case IrBinOpBitShiftRight:
778 assert(op1->type_entry->id == TypeTableEntryIdInt);
779 if (op1->type_entry->data.integral.is_signed) {
780 return LLVMBuildAShr(g->builder, op1_value, op2_value, "");
781 } else {
782 return LLVMBuildLShr(g->builder, op1_value, op2_value, "");
783 }
751784 case IrBinOpSub:
752785 case IrBinOpSubWrap:
786 if (op1->type_entry->id == TypeTableEntryIdFloat) {
787 return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
788 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
789 bool is_wrapping = (op_id == IrBinOpSubWrap);
790 if (is_wrapping) {
791 return LLVMBuildSub(g->builder, op1_value, op2_value, "");
792 } else if (want_debug_safety(g, source_node)) {
793 return gen_overflow_op(g, op1->type_entry, AddSubMulSub, op1_value, op2_value);
794 } else if (op1->type_entry->data.integral.is_signed) {
795 return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
796 } else {
797 return LLVMBuildNUWSub(g->builder, op1_value, op2_value, "");
798 }
799 } else {
800 zig_unreachable();
801 }
753802 case IrBinOpMult:
754803 case IrBinOpMultWrap:
804 if (op1->type_entry->id == TypeTableEntryIdFloat) {
805 return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
806 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
807 bool is_wrapping = (op_id == IrBinOpMultWrap);
808 if (is_wrapping) {
809 return LLVMBuildMul(g->builder, op1_value, op2_value, "");
810 } else if (want_debug_safety(g, source_node)) {
811 return gen_overflow_op(g, op1->type_entry, AddSubMulMul, op1_value, op2_value);
812 } else if (op1->type_entry->data.integral.is_signed) {
813 return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
814 } else {
815 return LLVMBuildNUWMul(g->builder, op1_value, op2_value, "");
816 }
817 } else {
818 zig_unreachable();
819 }
755820 case IrBinOpDiv:
821 return gen_div(g, source_node, op1_value, op2_value, op1->type_entry, false);
756822 case IrBinOpMod:
757 zig_panic("TODO render more bin ops to LLVM");
823 if (op1->type_entry->id == TypeTableEntryIdFloat) {
824 return LLVMBuildFRem(g->builder, op1_value, op2_value, "");
825 } else {
826 assert(op1->type_entry->id == TypeTableEntryIdInt);
827 if (op1->type_entry->data.integral.is_signed) {
828 return LLVMBuildSRem(g->builder, op1_value, op2_value, "");
829 } else {
830 return LLVMBuildURem(g->builder, op1_value, op2_value, "");
831 }
832 }
758833 }
759834 zig_unreachable();
760835}
......@@ -1242,10 +1317,56 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
12421317
12431318static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrInstructionElemPtr *instruction) {
12441319 LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->array_ptr);
1245 LLVMValueRef array_ptr = LLVMBuildLoad(g->builder, array_ptr_ptr, "");
1320 TypeTableEntry *array_ptr_type = instruction->array_ptr->type_entry;
1321 assert(array_ptr_type->id == TypeTableEntryIdPointer);
1322 TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type;
1323 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type);
12461324 LLVMValueRef subscript_value = ir_llvm_value(g, instruction->elem_index);
1247 TypeTableEntry *array_type = instruction->array_ptr->type_entry;
1248 return gen_array_elem_ptr(g, instruction->base.source_node, array_ptr, array_type, subscript_value);
1325 assert(subscript_value);
1326
1327 if (!type_has_bits(array_type))
1328 return nullptr;
1329
1330 bool safety_check_on = ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on;
1331
1332 if (array_type->id == TypeTableEntryIdArray) {
1333 if (safety_check_on) {
1334 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1335 array_type->data.array.len, false);
1336 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
1337 }
1338 LLVMValueRef indices[] = {
1339 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
1340 subscript_value
1341 };
1342 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
1343 } else if (array_type->id == TypeTableEntryIdPointer) {
1344 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
1345 LLVMValueRef indices[] = {
1346 subscript_value
1347 };
1348 return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, "");
1349 } else if (array_type->id == TypeTableEntryIdStruct) {
1350 assert(array_type->data.structure.is_slice);
1351 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
1352 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
1353
1354 if (safety_check_on) {
1355 size_t len_index = array_type->data.structure.fields[1].gen_index;
1356 assert(len_index != SIZE_MAX);
1357 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, len_index, "");
1358 LLVMValueRef len = LLVMBuildLoad(g->builder, len_ptr, "");
1359 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
1360 }
1361
1362 size_t ptr_index = array_type->data.structure.fields[0].gen_index;
1363 assert(ptr_index != SIZE_MAX);
1364 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, ptr_index, "");
1365 LLVMValueRef ptr = LLVMBuildLoad(g->builder, ptr_ptr, "");
1366 return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, "");
1367 } else {
1368 zig_unreachable();
1369 }
12491370}
12501371
12511372static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
......@@ -1423,7 +1544,6 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
14231544 LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
14241545 buf_ptr(&constraint_buf), is_volatile, false);
14251546
1426 set_debug_source_node(g, asm_node);
14271547 return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
14281548}
14291549
src/ir.cpp+12-112
......@@ -506,11 +506,12 @@ static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_i
506506}
507507
508508static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, AstNode *source_node, IrInstruction *array_ptr,
509 IrInstruction *elem_index)
509 IrInstruction *elem_index, bool safety_check_on)
510510{
511511 IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, source_node);
512512 instruction->array_ptr = array_ptr;
513513 instruction->elem_index = elem_index;
514 instruction->safety_check_on = safety_check_on;
514515
515516 ir_ref_instruction(array_ptr);
516517 ir_ref_instruction(elem_index);
......@@ -519,9 +520,10 @@ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, AstNode *source_node, Ir
519520}
520521
521522static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
522 IrInstruction *array_ptr, IrInstruction *elem_index)
523 IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on)
523524{
524 IrInstruction *new_instruction = ir_build_elem_ptr(irb, old_instruction->source_node, array_ptr, elem_index);
525 IrInstruction *new_instruction = ir_build_elem_ptr(irb, old_instruction->source_node, array_ptr, elem_index,
526 safety_check_on);
525527 ir_link_new_instruction(new_instruction, old_instruction);
526528 return new_instruction;
527529}
......@@ -1353,7 +1355,8 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, AstNode *node, LValPur
13531355 if (subscript_instruction == irb->codegen->invalid_instruction)
13541356 return subscript_instruction;
13551357
1356 IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, node, array_ref_instruction, subscript_instruction);
1358 IrInstruction *ptr_instruction = ir_build_elem_ptr(irb, node, array_ref_instruction,
1359 subscript_instruction, true);
13571360 if (lval != LValPurposeNone)
13581361 return ptr_instruction;
13591362
......@@ -1840,7 +1843,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) {
18401843 ir_build_cond_br(irb, node, cond, body_block, end_block, is_inline);
18411844
18421845 ir_set_cursor_at_end(irb, body_block);
1843 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val);
1846 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val, true);
18441847 IrInstruction *elem_val;
18451848 if (node->data.for_expr.elem_is_ptr) {
18461849 elem_val = elem_ptr;
......@@ -3960,6 +3963,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
39603963 if (casted_elem_index == ira->codegen->invalid_instruction)
39613964 return ira->codegen->builtin_types.entry_invalid;
39623965
3966 bool safety_check_on = true;
39633967 if (casted_elem_index->static_value.special != ConstValSpecialRuntime) {
39643968 uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
39653969 if (array_type->id == TypeTableEntryIdArray) {
......@@ -3970,6 +3974,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
39703974 index, array_len));
39713975 return ira->codegen->builtin_types.entry_invalid;
39723976 }
3977 safety_check_on = false;
39733978 }
39743979
39753980 ConstExprValue *array_ptr_val;
......@@ -4031,7 +4036,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
40314036
40324037 }
40334038
4034 ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr, casted_elem_index);
4039 ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr,
4040 casted_elem_index, safety_check_on);
40354041 return return_type;
40364042}
40374043
......@@ -8668,18 +8674,6 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
86688674// return target_ref;
86698675//}
86708676//
8671//static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) {
8672// assert(node->type == NodeTypeBinOpExpr);
8673//
8674// LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1);
8675// LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2);
8676//
8677// TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1);
8678// TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2);
8679// return gen_arithmetic_bin_op(g, node, val1, val2, op1_type, op2_type, node->data.bin_op_expr.bin_op);
8680//
8681//}
8682//
86838677//static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) {
86848678// assert(node->type == NodeTypeBinOpExpr);
86858679//
......@@ -9678,97 +9672,3 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
96789672// LLVMPositionBuilderAtEnd(g->builder, basic_block);
96799673// return nullptr;
96809674//}
9681//static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
9682// LLVMValueRef val1, LLVMValueRef val2)
9683//{
9684// // for unsigned left shifting, we do the wrapping shift, then logically shift
9685// // right the same number of bits
9686// // if the values don't match, we have an overflow
9687// // for signed left shifting we do the same except arithmetic shift right
9688//
9689// assert(type_entry->id == TypeTableEntryIdInt);
9690//
9691// LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, "");
9692// LLVMValueRef orig_val;
9693// if (type_entry->data.integral.is_signed) {
9694// orig_val = LLVMBuildAShr(g->builder, result, val2, "");
9695// } else {
9696// orig_val = LLVMBuildLShr(g->builder, result, val2, "");
9697// }
9698// LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, "");
9699//
9700// LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk");
9701// LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail");
9702// LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
9703//
9704// LLVMPositionBuilderAtEnd(g->builder, fail_block);
9705// gen_debug_safety_crash(g);
9706//
9707// LLVMPositionBuilderAtEnd(g->builder, ok_block);
9708// return result;
9709//}
9710//
9711//static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
9712// TypeTableEntry *type_entry, bool exact)
9713//{
9714//
9715// if (want_debug_safety(g, source_node)) {
9716// LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
9717// LLVMValueRef is_zero_bit;
9718// if (type_entry->id == TypeTableEntryIdInt) {
9719// is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, "");
9720// } else if (type_entry->id == TypeTableEntryIdFloat) {
9721// is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, "");
9722// } else {
9723// zig_unreachable();
9724// }
9725// LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk");
9726// LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail");
9727// LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);
9728//
9729// LLVMPositionBuilderAtEnd(g->builder, fail_block);
9730// gen_debug_safety_crash(g);
9731//
9732// LLVMPositionBuilderAtEnd(g->builder, ok_block);
9733// }
9734//
9735// if (type_entry->id == TypeTableEntryIdFloat) {
9736// assert(!exact);
9737// return LLVMBuildFDiv(g->builder, val1, val2, "");
9738// }
9739//
9740// assert(type_entry->id == TypeTableEntryIdInt);
9741//
9742// if (exact) {
9743// if (want_debug_safety(g, source_node)) {
9744// LLVMValueRef remainder_val;
9745// if (type_entry->data.integral.is_signed) {
9746// remainder_val = LLVMBuildSRem(g->builder, val1, val2, "");
9747// } else {
9748// remainder_val = LLVMBuildURem(g->builder, val1, val2, "");
9749// }
9750// LLVMValueRef zero = LLVMConstNull(type_entry->type_ref);
9751// LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
9752//
9753// LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactOk");
9754// LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactFail");
9755// LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
9756//
9757// LLVMPositionBuilderAtEnd(g->builder, fail_block);
9758// gen_debug_safety_crash(g);
9759//
9760// LLVMPositionBuilderAtEnd(g->builder, ok_block);
9761// }
9762// if (type_entry->data.integral.is_signed) {
9763// return LLVMBuildExactSDiv(g->builder, val1, val2, "");
9764// } else {
9765// return ZigLLVMBuildExactUDiv(g->builder, val1, val2, "");
9766// }
9767// } else {
9768// if (type_entry->data.integral.is_signed) {
9769// return LLVMBuildSDiv(g->builder, val1, val2, "");
9770// } else {
9771// return LLVMBuildUDiv(g->builder, val1, val2, "");
9772// }
9773// }
9774//}
src/ir_print.cpp+3
......@@ -359,6 +359,9 @@ static void ir_print_elem_ptr(IrPrint *irp, IrInstructionElemPtr *instruction) {
359359 fprintf(irp->f, "[");
360360 ir_print_other_instruction(irp, instruction->elem_index);
361361 fprintf(irp->f, "]");
362 if (!instruction->safety_check_on) {
363 fprintf(irp->f, " // no safety");
364 }
362365}
363366
364367static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {