| ... | ... | @@ -324,8 +324,12 @@ static void addLLVMFnAttrInt(LLVMValueRef fn_val, const char *attr_name, uint64_ |
| 324 | 324 | return addLLVMAttrInt(fn_val, -1, attr_name, attr_val); |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | | static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const char *attr_name) { |
| 328 | | return addLLVMAttr(arg_val, param_index + 1, attr_name); |
| 327 | static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char *attr_name) { |
| 328 | return addLLVMAttr(fn_val, param_index + 1, attr_name); |
| 329 | } |
| 330 | |
| 331 | static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) { |
| 332 | return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val); |
| 329 | 333 | } |
| 330 | 334 | |
| 331 | 335 | static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, const char *attr_name) { |
| ... | ... | @@ -912,23 +916,31 @@ static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) { |
| 912 | 916 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr); |
| 913 | 917 | } |
| 914 | 918 | |
| 915 | | static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| 916 | | if (g->memcpy_fn_val) |
| 917 | | return g->memcpy_fn_val; |
| 919 | static LLVMValueRef get_memcpy_fn_val(CodeGen *g, uint32_t dest_align, uint32_t src_align) { |
| 920 | ZigLLVMFnKey key = {}; |
| 921 | key.id = ZigLLVMFnIdMemcpy; |
| 922 | key.data.memcpy.dest_align = dest_align; |
| 923 | key.data.memcpy.src_align = src_align; |
| 924 | |
| 925 | auto existing_entry = g->llvm_fn_table.maybe_get(key); |
| 926 | if (existing_entry) |
| 927 | return existing_entry->value; |
| 918 | 928 | |
| 919 | 929 | LLVMTypeRef param_types[] = { |
| 920 | 930 | LLVMPointerType(LLVMInt8Type(), 0), |
| 921 | 931 | LLVMPointerType(LLVMInt8Type(), 0), |
| 922 | 932 | LLVMIntType(g->pointer_size_bytes * 8), |
| 923 | | LLVMInt32Type(), |
| 924 | 933 | LLVMInt1Type(), |
| 925 | 934 | }; |
| 926 | | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false); |
| 935 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false); |
| 927 | 936 | Buf *name = buf_sprintf("llvm.memcpy.p0i8.p0i8.i%d", g->pointer_size_bytes * 8); |
| 928 | | g->memcpy_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); |
| 929 | | assert(LLVMGetIntrinsicID(g->memcpy_fn_val)); |
| 937 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); |
| 938 | addLLVMArgAttrInt(fn_val, 0, "align", dest_align); |
| 939 | addLLVMArgAttrInt(fn_val, 1, "align", src_align); |
| 940 | assert(LLVMGetIntrinsicID(fn_val)); |
| 930 | 941 | |
| 931 | | return g->memcpy_fn_val; |
| 942 | g->llvm_fn_table.put(key, fn_val); |
| 943 | return fn_val; |
| 932 | 944 | } |
| 933 | 945 | |
| 934 | 946 | static LLVMValueRef get_coro_destroy_fn_val(CodeGen *g) { |
| ... | ... | @@ -1293,15 +1305,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1293 | 1305 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, ""); |
| 1294 | 1306 | LLVMValueRef err_name_len = gen_load_untyped(g, len_field_ptr, 0, false, ""); |
| 1295 | 1307 | |
| 1308 | LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, u8_align_bytes, u8_align_bytes); |
| 1296 | 1309 | LLVMValueRef params[] = { |
| 1297 | 1310 | offset_buf_ptr, // dest pointer |
| 1298 | 1311 | err_name_ptr, // source pointer |
| 1299 | 1312 | err_name_len, // size bytes |
| 1300 | | LLVMConstInt(LLVMInt32Type(), u8_align_bytes, false), // align bytes |
| 1301 | 1313 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| 1302 | 1314 | }; |
| 1303 | 1315 | |
| 1304 | | LLVMBuildCall(g->builder, get_memcpy_fn_val(g), params, 5, ""); |
| 1316 | LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, ""); |
| 1305 | 1317 | |
| 1306 | 1318 | LLVMValueRef const_prefix_len = LLVMConstInt(LLVMTypeOf(err_name_len), strlen(unwrap_err_msg_text), false); |
| 1307 | 1319 | LLVMValueRef full_buf_len = LLVMBuildNUWAdd(g->builder, const_prefix_len, err_name_len, ""); |
| ... | ... | @@ -1535,15 +1547,16 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, TypeTableEntry |
| 1535 | 1547 | LLVMValueRef volatile_bit = ptr_type->data.pointer.is_volatile ? |
| 1536 | 1548 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 1537 | 1549 | |
| 1550 | LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, align_bytes, align_bytes); |
| 1551 | |
| 1538 | 1552 | LLVMValueRef params[] = { |
| 1539 | 1553 | dest_ptr, // dest pointer |
| 1540 | 1554 | src_ptr, // source pointer |
| 1541 | 1555 | LLVMConstInt(usize->type_ref, size_bytes, false), |
| 1542 | | LLVMConstInt(LLVMInt32Type(), align_bytes, false), |
| 1543 | 1556 | volatile_bit, |
| 1544 | 1557 | }; |
| 1545 | 1558 | |
| 1546 | | LLVMBuildCall(g->builder, get_memcpy_fn_val(g), params, 5, ""); |
| 1559 | LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, ""); |
| 1547 | 1560 | return nullptr; |
| 1548 | 1561 | } |
| 1549 | 1562 | |
| ... | ... | @@ -2483,23 +2496,29 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI |
| 2483 | 2496 | return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); |
| 2484 | 2497 | } |
| 2485 | 2498 | |
| 2486 | | static LLVMValueRef get_memset_fn_val(CodeGen *g) { |
| 2487 | | if (g->memset_fn_val) |
| 2488 | | return g->memset_fn_val; |
| 2499 | static LLVMValueRef get_memset_fn_val(CodeGen *g, uint32_t dest_align) { |
| 2500 | ZigLLVMFnKey key = {}; |
| 2501 | key.id = ZigLLVMFnIdMemset; |
| 2502 | key.data.memset.dest_align = dest_align; |
| 2503 | |
| 2504 | auto existing_entry = g->llvm_fn_table.maybe_get(key); |
| 2505 | if (existing_entry) |
| 2506 | return existing_entry->value; |
| 2489 | 2507 | |
| 2490 | 2508 | LLVMTypeRef param_types[] = { |
| 2491 | 2509 | LLVMPointerType(LLVMInt8Type(), 0), |
| 2492 | 2510 | LLVMInt8Type(), |
| 2493 | 2511 | LLVMIntType(g->pointer_size_bytes * 8), |
| 2494 | | LLVMInt32Type(), |
| 2495 | 2512 | LLVMInt1Type(), |
| 2496 | 2513 | }; |
| 2497 | | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 5, false); |
| 2514 | LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false); |
| 2498 | 2515 | Buf *name = buf_sprintf("llvm.memset.p0i8.i%d", g->pointer_size_bytes * 8); |
| 2499 | | g->memset_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); |
| 2500 | | assert(LLVMGetIntrinsicID(g->memset_fn_val)); |
| 2516 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); |
| 2517 | addLLVMArgAttrInt(fn_val, 0, "align", dest_align); |
| 2518 | assert(LLVMGetIntrinsicID(fn_val)); |
| 2501 | 2519 | |
| 2502 | | return g->memset_fn_val; |
| 2520 | g->llvm_fn_table.put(key, fn_val); |
| 2521 | return fn_val; |
| 2503 | 2522 | } |
| 2504 | 2523 | |
| 2505 | 2524 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| ... | ... | @@ -2535,21 +2554,21 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 2535 | 2554 | |
| 2536 | 2555 | assert(var->align_bytes > 0); |
| 2537 | 2556 | |
| 2557 | LLVMValueRef memset_fn_val = get_memset_fn_val(g, var->align_bytes); |
| 2558 | |
| 2538 | 2559 | // memset uninitialized memory to 0xa |
| 2539 | 2560 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); |
| 2540 | 2561 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); |
| 2541 | 2562 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); |
| 2542 | 2563 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); |
| 2543 | | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), var->align_bytes, false); |
| 2544 | 2564 | LLVMValueRef params[] = { |
| 2545 | 2565 | dest_ptr, |
| 2546 | 2566 | fill_char, |
| 2547 | 2567 | byte_count, |
| 2548 | | align_in_bytes, |
| 2549 | 2568 | LLVMConstNull(LLVMInt1Type()), // is volatile |
| 2550 | 2569 | }; |
| 2551 | 2570 | |
| 2552 | | LLVMBuildCall(g->builder, get_memset_fn_val(g), params, 5, ""); |
| 2571 | LLVMBuildCall(g->builder, memset_fn_val, params, 4, ""); |
| 2553 | 2572 | } |
| 2554 | 2573 | } |
| 2555 | 2574 | |
| ... | ... | @@ -3399,17 +3418,16 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns |
| 3399 | 3418 | LLVMValueRef is_volatile = ptr_type->data.pointer.is_volatile ? |
| 3400 | 3419 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 3401 | 3420 | |
| 3402 | | LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.alignment, false); |
| 3421 | LLVMValueRef memset_fn_val = get_memset_fn_val(g, ptr_type->data.pointer.alignment); |
| 3403 | 3422 | |
| 3404 | 3423 | LLVMValueRef params[] = { |
| 3405 | 3424 | dest_ptr_casted, |
| 3406 | 3425 | char_val, |
| 3407 | 3426 | len_val, |
| 3408 | | align_val, |
| 3409 | 3427 | is_volatile, |
| 3410 | 3428 | }; |
| 3411 | 3429 | |
| 3412 | | LLVMBuildCall(g->builder, get_memset_fn_val(g), params, 5, ""); |
| 3430 | LLVMBuildCall(g->builder, memset_fn_val, params, 4, ""); |
| 3413 | 3431 | return nullptr; |
| 3414 | 3432 | } |
| 3415 | 3433 | |
| ... | ... | @@ -3432,18 +3450,17 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns |
| 3432 | 3450 | LLVMValueRef is_volatile = (dest_ptr_type->data.pointer.is_volatile || src_ptr_type->data.pointer.is_volatile) ? |
| 3433 | 3451 | LLVMConstAllOnes(LLVMInt1Type()) : LLVMConstNull(LLVMInt1Type()); |
| 3434 | 3452 | |
| 3435 | | uint32_t min_align_bytes = min(src_ptr_type->data.pointer.alignment, dest_ptr_type->data.pointer.alignment); |
| 3436 | | LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), min_align_bytes, false); |
| 3453 | LLVMValueRef memcpy_fn_val = get_memcpy_fn_val(g, dest_ptr_type->data.pointer.alignment, |
| 3454 | src_ptr_type->data.pointer.alignment); |
| 3437 | 3455 | |
| 3438 | 3456 | LLVMValueRef params[] = { |
| 3439 | 3457 | dest_ptr_casted, |
| 3440 | 3458 | src_ptr_casted, |
| 3441 | 3459 | len_val, |
| 3442 | | align_val, |
| 3443 | 3460 | is_volatile, |
| 3444 | 3461 | }; |
| 3445 | 3462 | |
| 3446 | | LLVMBuildCall(g->builder, get_memcpy_fn_val(g), params, 5, ""); |
| 3463 | LLVMBuildCall(g->builder, memcpy_fn_val, params, 4, ""); |
| 3447 | 3464 | return nullptr; |
| 3448 | 3465 | } |
| 3449 | 3466 | |