| ... | ... | @@ -3371,14 +3371,12 @@ static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) { |
| 3371 | 3371 | } |
| 3372 | 3372 | |
| 3373 | 3373 | static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { |
| 3374 | | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; |
| 3375 | | |
| 3376 | 3374 | // Handle integers of non-pot bitsize by widening them. |
| 3377 | 3375 | const size_t bitsize = operand_type->data.integral.bit_count; |
| 3378 | 3376 | const bool is_signed = operand_type->data.integral.is_signed; |
| 3379 | 3377 | if (bitsize < 32 || !is_power_of_2(bitsize)) { |
| 3380 | 3378 | const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize); |
| 3381 | | ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize); |
| 3379 | ZigType *wider_type = get_int_type(g, is_signed, wider_bitsize); |
| 3382 | 3380 | value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref); |
| 3383 | 3381 | operand_type = wider_type; |
| 3384 | 3382 | } |
| ... | ... | @@ -3395,35 +3393,22 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, |
| 3395 | 3393 | } |
| 3396 | 3394 | |
| 3397 | 3395 | int param_count = 1; |
| 3398 | | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_type); |
| 3399 | | |
| 3400 | | LLVMValueRef result; |
| 3401 | | if (vector_len == 0) { |
| 3402 | | LLVMValueRef params[1] = {value_ref}; |
| 3403 | | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3396 | LLVMValueRef func_ref; |
| 3397 | if ((operand_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { |
| 3398 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling |
| 3399 | // convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 3400 | LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2); |
| 3401 | value_ref = LLVMBuildBitCast(g->builder, value_ref, v2i64, ""); |
| 3402 | func_ref = get_soft_float_fn(g, fn_name, param_count, v2i64, result_type->llvm_type); |
| 3404 | 3403 | } else { |
| 3405 | | ZigType *alloca_ty = operand_type; |
| 3406 | | result = build_alloca(g, alloca_ty, "", 0); |
| 3407 | | |
| 3408 | | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; |
| 3409 | | for (uint32_t i = 0; i < vector_len; i++) { |
| 3410 | | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); |
| 3411 | | LLVMValueRef params[1] = { |
| 3412 | | LLVMBuildExtractElement(g->builder, value_ref, index_value, ""), |
| 3413 | | }; |
| 3414 | | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3415 | | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), |
| 3416 | | call_result, index_value, ""); |
| 3417 | | } |
| 3418 | | |
| 3419 | | result = LLVMBuildLoad(g->builder, result, ""); |
| 3404 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_type); |
| 3420 | 3405 | } |
| 3421 | | return result; |
| 3406 | |
| 3407 | LLVMValueRef params[1] = {value_ref}; |
| 3408 | return LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3422 | 3409 | } |
| 3423 | 3410 | |
| 3424 | 3411 | static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { |
| 3425 | | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; |
| 3426 | | |
| 3427 | 3412 | // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer |
| 3428 | 3413 | const size_t bitsize = result_type->data.integral.bit_count; |
| 3429 | 3414 | const bool is_signed = result_type->data.integral.is_signed; |
| ... | ... | @@ -3445,46 +3430,41 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, |
| 3445 | 3430 | } |
| 3446 | 3431 | |
| 3447 | 3432 | int param_count = 1; |
| 3448 | | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type); |
| 3449 | | |
| 3450 | | LLVMValueRef result; |
| 3451 | | if (vector_len == 0) { |
| 3452 | | LLVMValueRef params[1] = {value_ref}; |
| 3453 | | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3433 | LLVMValueRef func_ref; |
| 3434 | if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { |
| 3435 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling |
| 3436 | // convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 3437 | LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2); |
| 3438 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, v2i64); |
| 3454 | 3439 | } else { |
| 3455 | | ZigType *alloca_ty = operand_type; |
| 3456 | | result = build_alloca(g, alloca_ty, "", 0); |
| 3440 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type); |
| 3441 | } |
| 3457 | 3442 | |
| 3458 | | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; |
| 3459 | | for (uint32_t i = 0; i < vector_len; i++) { |
| 3460 | | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); |
| 3461 | | LLVMValueRef params[1] = { |
| 3462 | | LLVMBuildExtractElement(g->builder, value_ref, index_value, ""), |
| 3463 | | }; |
| 3464 | | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3465 | | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), |
| 3466 | | call_result, index_value, ""); |
| 3467 | | } |
| 3443 | LLVMValueRef params[1] = {value_ref}; |
| 3444 | LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3468 | 3445 | |
| 3469 | | result = LLVMBuildLoad(g->builder, result, ""); |
| 3446 | if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { |
| 3447 | result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, ""); |
| 3470 | 3448 | } |
| 3471 | 3449 | |
| 3472 | 3450 | // Handle integers of non-pot bitsize by shortening them on the output |
| 3473 | 3451 | if (result_type != wider_type) { |
| 3474 | | return gen_widen_or_shorten(g, false, wider_type, result_type, result); |
| 3452 | result = gen_widen_or_shorten(g, false, wider_type, result_type, result); |
| 3475 | 3453 | } |
| 3454 | |
| 3476 | 3455 | return result; |
| 3477 | 3456 | } |
| 3478 | 3457 | |
| 3479 | 3458 | static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) { |
| 3480 | 3459 | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; |
| 3481 | 3460 | |
| 3482 | | LLVMTypeRef return_type = operand_type->llvm_type; |
| 3483 | 3461 | int param_count = 2; |
| 3484 | 3462 | |
| 3485 | | const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type); |
| 3486 | | const char *math_float_prefix = libc_float_prefix(g, operand_type); |
| 3487 | | const char *math_float_suffix = libc_float_suffix(g, operand_type); |
| 3463 | ZigType *operand_scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| 3464 | LLVMTypeRef return_scalar_type = operand_scalar_type->llvm_type; |
| 3465 | const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_scalar_type); |
| 3466 | const char *math_float_prefix = libc_float_prefix(g, operand_scalar_type); |
| 3467 | const char *math_float_suffix = libc_float_suffix(g, operand_scalar_type); |
| 3488 | 3468 | |
| 3489 | 3469 | char fn_name[64]; |
| 3490 | 3470 | Icmp res_icmp = NONE; |
| ... | ... | @@ -3511,32 +3491,32 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3511 | 3491 | case IrBinOpShlSat: |
| 3512 | 3492 | zig_unreachable(); |
| 3513 | 3493 | case IrBinOpCmpEq: |
| 3514 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3494 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3515 | 3495 | snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev); |
| 3516 | 3496 | res_icmp = EQ_ZERO; |
| 3517 | 3497 | break; |
| 3518 | 3498 | case IrBinOpCmpNotEq: |
| 3519 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3499 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3520 | 3500 | snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev); |
| 3521 | 3501 | res_icmp = NE_ZERO; |
| 3522 | 3502 | break; |
| 3523 | 3503 | case IrBinOpCmpLessOrEq: |
| 3524 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3504 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3525 | 3505 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); |
| 3526 | 3506 | res_icmp = LE_ZERO; |
| 3527 | 3507 | break; |
| 3528 | 3508 | case IrBinOpCmpLessThan: |
| 3529 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3509 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3530 | 3510 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); |
| 3531 | 3511 | res_icmp = EQ_NEG; |
| 3532 | 3512 | break; |
| 3533 | 3513 | case IrBinOpCmpGreaterOrEq: |
| 3534 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3514 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3535 | 3515 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); |
| 3536 | 3516 | res_icmp = GE_ZERO; |
| 3537 | 3517 | break; |
| 3538 | 3518 | case IrBinOpCmpGreaterThan: |
| 3539 | | return_type = g->builtin_types.entry_i32->llvm_type; |
| 3519 | return_scalar_type = g->builtin_types.entry_i32->llvm_type; |
| 3540 | 3520 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); |
| 3541 | 3521 | res_icmp = EQ_ONE; |
| 3542 | 3522 | break; |
| ... | ... | @@ -3569,7 +3549,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3569 | 3549 | zig_unreachable(); |
| 3570 | 3550 | } |
| 3571 | 3551 | |
| 3572 | | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, return_type); |
| 3552 | LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_scalar_type->llvm_type, return_scalar_type); |
| 3573 | 3553 | |
| 3574 | 3554 | LLVMValueRef result; |
| 3575 | 3555 | if (vector_len == 0) { |