| ... | ... | @@ -3237,10 +3237,10 @@ static LLVMValueRef get_soft_f80_bin_op_func(CodeGen *g, const char *name, int p |
| 3237 | 3237 | static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, |
| 3238 | 3238 | Stage1AirInstBinOp *bin_op_instruction) |
| 3239 | 3239 | { |
| 3240 | | // TODO support vectors |
| 3241 | 3240 | IrBinOp op_id = bin_op_instruction->op_id; |
| 3242 | 3241 | Stage1AirInst *op1 = bin_op_instruction->op1; |
| 3243 | 3242 | Stage1AirInst *op2 = bin_op_instruction->op2; |
| 3243 | uint32_t vector_len = op1->value->type->id == ZigTypeIdVector ? op1->value->type->data.vector.len : 0; |
| 3244 | 3244 | |
| 3245 | 3245 | LLVMValueRef op1_value = ir_llvm_value(g, op1); |
| 3246 | 3246 | LLVMValueRef op2_value = ir_llvm_value(g, op2); |
| ... | ... | @@ -3334,21 +3334,63 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, |
| 3334 | 3334 | |
| 3335 | 3335 | LLVMValueRef func_ref = get_soft_f80_bin_op_func(g, func_name, param_count, return_type); |
| 3336 | 3336 | |
| 3337 | | LLVMValueRef params[2] = {op1_value, op2_value}; |
| 3338 | | LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3337 | LLVMValueRef result; |
| 3338 | if (vector_len == 0) { |
| 3339 | LLVMValueRef params[2] = {op1_value, op2_value}; |
| 3340 | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3341 | } else { |
| 3342 | result = build_alloca(g, op1->value->type, "", 0); |
| 3343 | } |
| 3344 | |
| 3345 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; |
| 3346 | for (uint32_t i = 0; i < vector_len; i++) { |
| 3347 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); |
| 3348 | LLVMValueRef params[2] = { |
| 3349 | LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), |
| 3350 | LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), |
| 3351 | }; |
| 3352 | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); |
| 3353 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), |
| 3354 | call_result, index_value, ""); |
| 3355 | } |
| 3339 | 3356 | |
| 3340 | 3357 | if (div_exact_safety_check) { |
| 3341 | 3358 | // Safety check: a / b == floor(a / b) |
| 3342 | | func_ref = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type); |
| 3343 | | LLVMValueRef floored = LLVMBuildCall(g->builder, func_ref, &result, 1, ""); |
| 3359 | LLVMValueRef floor_func = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type); |
| 3360 | LLVMValueRef eq_func = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type); |
| 3361 | |
| 3362 | LLVMValueRef ok_bit; |
| 3363 | if (vector_len == 0) { |
| 3364 | LLVMValueRef floored = LLVMBuildCall(g->builder, floor_func, &result, 1, ""); |
| 3365 | |
| 3366 | LLVMValueRef params[2] = {result, floored}; |
| 3367 | ok_bit = LLVMBuildCall(g->builder, eq_func, params, 2, ""); |
| 3368 | } else { |
| 3369 | ZigType *bool_vec_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool); |
| 3370 | ok_bit = build_alloca(g, bool_vec_ty, "", 0); |
| 3371 | } |
| 3372 | |
| 3373 | for (uint32_t i = 0; i < vector_len; i++) { |
| 3374 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); |
| 3375 | LLVMValueRef div_res = LLVMBuildExtractElement(g->builder, |
| 3376 | LLVMBuildLoad(g->builder, result, ""), index_value, ""); |
| 3344 | 3377 | |
| 3378 | LLVMValueRef params[2] = { |
| 3379 | div_res, |
| 3380 | LLVMBuildCall(g->builder, floor_func, &div_res, 1, ""), |
| 3381 | }; |
| 3382 | LLVMValueRef cmp_res = LLVMBuildCall(g->builder, eq_func, params, 2, ""); |
| 3383 | cmp_res = LLVMBuildTrunc(g->builder, cmp_res, g->builtin_types.entry_bool->llvm_type, ""); |
| 3384 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""), |
| 3385 | cmp_res, index_value, ""); |
| 3386 | } |
| 3387 | |
| 3388 | if (vector_len != 0) { |
| 3389 | ok_bit = ZigLLVMBuildAndReduce(g->builder, LLVMBuildLoad(g->builder, ok_bit, "")); |
| 3390 | } |
| 3345 | 3391 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk"); |
| 3346 | 3392 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail"); |
| 3347 | 3393 | |
| 3348 | | LLVMValueRef params[2] = {result, floored}; |
| 3349 | | func_ref = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type); |
| 3350 | | LLVMValueRef ok_bit = LLVMBuildCall(g->builder, func_ref, params, 2, ""); |
| 3351 | | |
| 3352 | 3394 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 3353 | 3395 | |
| 3354 | 3396 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| ... | ... | @@ -3357,6 +3399,9 @@ static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, |
| 3357 | 3399 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3358 | 3400 | } |
| 3359 | 3401 | |
| 3402 | if (vector_len != 0) { |
| 3403 | result = LLVMBuildLoad(g->builder, result, ""); |
| 3404 | } |
| 3360 | 3405 | return result; |
| 3361 | 3406 | } |
| 3362 | 3407 | |