| ... | @@ -666,15 +666,36 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { | ... | @@ -666,15 +666,36 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 666 | | 666 | |
| 667 | LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type); | 667 | LLVMValueRef target_ref = gen_lvalue(g, node, lhs_node, &op1_type); |
| 668 | | 668 | |
| | 669 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); |
| | 670 | |
| 669 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); | 671 | LLVMValueRef value = gen_expr(g, node->data.bin_op_expr.op2); |
| 670 | | 672 | |
| 671 | if (node->data.bin_op_expr.bin_op == BinOpTypeAssign) { | 673 | if (op1_type->id == TypeTableEntryIdStruct) { |
| 672 | // value is ready as is | 674 | assert(op2_type->id == TypeTableEntryIdStruct); |
| 673 | } else { | 675 | assert(op1_type == op2_type); |
| | 676 | assert(node->data.bin_op_expr.bin_op == BinOpTypeAssign); |
| | 677 | |
| | 678 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| | 679 | |
| | 680 | add_debug_source_node(g, node); |
| | 681 | LLVMValueRef src_ptr = LLVMBuildBitCast(g->builder, value, ptr_u8, ""); |
| | 682 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, target_ref, ptr_u8, ""); |
| | 683 | |
| | 684 | LLVMValueRef params[] = { |
| | 685 | dest_ptr, // dest pointer |
| | 686 | src_ptr, // source pointer |
| | 687 | LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), op1_type->size_in_bits / 8, false), // byte count |
| | 688 | LLVMConstInt(LLVMInt32Type(), op1_type->align_in_bits / 8, false), // align in bits |
| | 689 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| | 690 | }; |
| | 691 | |
| | 692 | return LLVMBuildCall(g->builder, g->memcpy_fn_val, params, 5, ""); |
| | 693 | } |
| | 694 | |
| | 695 | if (node->data.bin_op_expr.bin_op != BinOpTypeAssign) { |
| 674 | add_debug_source_node(g, node->data.bin_op_expr.op1); | 696 | add_debug_source_node(g, node->data.bin_op_expr.op1); |
| 675 | LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); | 697 | LLVMValueRef left_value = LLVMBuildLoad(g->builder, target_ref, ""); |
| 676 | | 698 | |
| 677 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); | | |
| 678 | value = gen_arithmetic_bin_op(g, left_value, value, op1_type, op2_type, node); | 699 | value = gen_arithmetic_bin_op(g, left_value, value, op1_type, op2_type, node); |
| 679 | } | 700 | } |
| 680 | | 701 | |
| ... | @@ -1158,6 +1179,20 @@ static LLVMAttribute to_llvm_fn_attr(FnAttrId attr_id) { | ... | @@ -1158,6 +1179,20 @@ static LLVMAttribute to_llvm_fn_attr(FnAttrId attr_id) { |
| 1158 | static void do_code_gen(CodeGen *g) { | 1179 | static void do_code_gen(CodeGen *g) { |
| 1159 | assert(!g->errors.length); | 1180 | assert(!g->errors.length); |
| 1160 | | 1181 | |
| | 1182 | { |
| | 1183 | LLVMTypeRef param_types[] = { |
| | 1184 | LLVMPointerType(LLVMInt8Type(), 0), |
| | 1185 | LLVMPointerType(LLVMInt8Type(), 0), |
| | 1186 | LLVMIntType(g->pointer_size_bytes * 8), |
| | 1187 | LLVMInt32Type(), |
| | 1188 | LLVMInt1Type(), |
| | 1189 | }; |
| | 1190 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false); |
| | 1191 | Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8); |
| | 1192 | g->memcpy_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); |
| | 1193 | assert(LLVMGetIntrinsicID(g->memcpy_fn_val)); |
| | 1194 | } |
| | 1195 | |
| 1161 | // Generate module level variables | 1196 | // Generate module level variables |
| 1162 | for (int i = 0; i < g->global_vars.length; i += 1) { | 1197 | for (int i = 0; i < g->global_vars.length; i += 1) { |
| 1163 | VariableTableEntry *var = g->global_vars.at(i); | 1198 | VariableTableEntry *var = g->global_vars.at(i); |
| ... | @@ -1379,7 +1414,7 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -1379,7 +1414,7 @@ static void define_builtin_types(CodeGen *g) { |
| 1379 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool); | 1414 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool); |
| 1380 | entry->type_ref = LLVMInt1Type(); | 1415 | entry->type_ref = LLVMInt1Type(); |
| 1381 | buf_init_from_str(&entry->name, "bool"); | 1416 | buf_init_from_str(&entry->name, "bool"); |
| 1382 | entry->size_in_bits = 1; | 1417 | entry->size_in_bits = 8; |
| 1383 | entry->align_in_bits = 8; | 1418 | entry->align_in_bits = 8; |
| 1384 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | 1419 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), |
| 1385 | entry->size_in_bits, entry->align_in_bits, | 1420 | entry->size_in_bits, entry->align_in_bits, |