| ... | @@ -3371,14 +3371,12 @@ static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) { | ... | @@ -3371,14 +3371,12 @@ static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) { |
| 3371 | } | 3371 | } |
| 3372 | | 3372 | |
| 3373 | static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { | 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 | // Handle integers of non-pot bitsize by widening them. | 3374 | // Handle integers of non-pot bitsize by widening them. |
| 3377 | const size_t bitsize = operand_type->data.integral.bit_count; | 3375 | const size_t bitsize = operand_type->data.integral.bit_count; |
| 3378 | const bool is_signed = operand_type->data.integral.is_signed; | 3376 | const bool is_signed = operand_type->data.integral.is_signed; |
| 3379 | if (bitsize < 32 || !is_power_of_2(bitsize)) { | 3377 | if (bitsize < 32 || !is_power_of_2(bitsize)) { |
| 3380 | const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize); | 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 | value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref); | 3380 | value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref); |
| 3383 | operand_type = wider_type; | 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,35 +3393,22 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, |
| 3395 | } | 3393 | } |
| 3396 | | 3394 | |
| 3397 | int param_count = 1; | 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); | 3396 | LLVMValueRef func_ref; |
| 3399 | | 3397 | if ((operand_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { |
| 3400 | LLVMValueRef result; | 3398 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling |
| 3401 | if (vector_len == 0) { | 3399 | // convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 3402 | LLVMValueRef params[1] = {value_ref}; | 3400 | LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2); |
| 3403 | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); | 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 | } else { | 3403 | } else { |
| 3405 | ZigType *alloca_ty = operand_type; | 3404 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_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, ""); | | |
| 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 | static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { | 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 | // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer | 3412 | // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer |
| 3428 | const size_t bitsize = result_type->data.integral.bit_count; | 3413 | const size_t bitsize = result_type->data.integral.bit_count; |
| 3429 | const bool is_signed = result_type->data.integral.is_signed; | 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,46 +3430,41 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, |
| 3445 | } | 3430 | } |
| 3446 | | 3431 | |
| 3447 | int param_count = 1; | 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); | 3433 | LLVMValueRef func_ref; |
| 3449 | | 3434 | if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { |
| 3450 | LLVMValueRef result; | 3435 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling |
| 3451 | if (vector_len == 0) { | 3436 | // convention to adhere to the ABI that LLVM expects compiler-rt to have. |
| 3452 | LLVMValueRef params[1] = {value_ref}; | 3437 | LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2); |
| 3453 | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); | 3438 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, v2i64); |
| 3454 | } else { | 3439 | } else { |
| 3455 | ZigType *alloca_ty = operand_type; | 3440 | func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type); |
| 3456 | result = build_alloca(g, alloca_ty, "", 0); | 3441 | } |
| 3457 | | 3442 | |
| 3458 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; | 3443 | LLVMValueRef params[1] = {value_ref}; |
| 3459 | for (uint32_t i = 0; i < vector_len; i++) { | 3444 | LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 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 | } | | |
| 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 | // Handle integers of non-pot bitsize by shortening them on the output | 3450 | // Handle integers of non-pot bitsize by shortening them on the output |
| 3473 | if (result_type != wider_type) { | 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 | return result; | 3455 | return result; |
| 3477 | } | 3456 | } |
| 3478 | | 3457 | |
| 3479 | static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) { | 3458 | static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) { |
| 3480 | uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; | 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 | int param_count = 2; | 3461 | int param_count = 2; |
| 3484 | | 3462 | |
| 3485 | const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type); | 3463 | ZigType *operand_scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| 3486 | const char *math_float_prefix = libc_float_prefix(g, operand_type); | 3464 | LLVMTypeRef return_scalar_type = operand_scalar_type->llvm_type; |
| 3487 | const char *math_float_suffix = libc_float_suffix(g, operand_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 | char fn_name[64]; | 3469 | char fn_name[64]; |
| 3490 | Icmp res_icmp = NONE; | 3470 | Icmp res_icmp = NONE; |
| ... | @@ -3511,32 +3491,32 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL | ... | @@ -3511,32 +3491,32 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3511 | case IrBinOpShlSat: | 3491 | case IrBinOpShlSat: |
| 3512 | zig_unreachable(); | 3492 | zig_unreachable(); |
| 3513 | case IrBinOpCmpEq: | 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 | snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev); | 3495 | snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev); |
| 3516 | res_icmp = EQ_ZERO; | 3496 | res_icmp = EQ_ZERO; |
| 3517 | break; | 3497 | break; |
| 3518 | case IrBinOpCmpNotEq: | 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 | snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev); | 3500 | snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev); |
| 3521 | res_icmp = NE_ZERO; | 3501 | res_icmp = NE_ZERO; |
| 3522 | break; | 3502 | break; |
| 3523 | case IrBinOpCmpLessOrEq: | 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 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); | 3505 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); |
| 3526 | res_icmp = LE_ZERO; | 3506 | res_icmp = LE_ZERO; |
| 3527 | break; | 3507 | break; |
| 3528 | case IrBinOpCmpLessThan: | 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 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); | 3510 | snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev); |
| 3531 | res_icmp = EQ_NEG; | 3511 | res_icmp = EQ_NEG; |
| 3532 | break; | 3512 | break; |
| 3533 | case IrBinOpCmpGreaterOrEq: | 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 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); | 3515 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); |
| 3536 | res_icmp = GE_ZERO; | 3516 | res_icmp = GE_ZERO; |
| 3537 | break; | 3517 | break; |
| 3538 | case IrBinOpCmpGreaterThan: | 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 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); | 3520 | snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev); |
| 3541 | res_icmp = EQ_ONE; | 3521 | res_icmp = EQ_ONE; |
| 3542 | break; | 3522 | break; |
| ... | @@ -3569,7 +3549,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL | ... | @@ -3569,7 +3549,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL |
| 3569 | zig_unreachable(); | 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 | LLVMValueRef result; | 3554 | LLVMValueRef result; |
| 3575 | if (vector_len == 0) { | 3555 | if (vector_len == 0) { |