(&mut self, a: Value, b: Value)
| 1374 | } |
| 1375 | |
| 1376 | fn compile_ipow(&mut self, a: Value, b: Value) -> Value { |
| 1377 | let zero = self.builder.ins().iconst(types::I64, 0); |
| 1378 | let one_i64 = self.builder.ins().iconst(types::I64, 1); |
| 1379 | |
| 1380 | // Create required blocks |
| 1381 | let check_negative = self.builder.create_block(); |
| 1382 | let handle_negative = self.builder.create_block(); |
| 1383 | let loop_block = self.builder.create_block(); |
| 1384 | let continue_block = self.builder.create_block(); |
| 1385 | let exit_block = self.builder.create_block(); |
| 1386 | |
| 1387 | // Set up block parameters |
| 1388 | self.builder.append_block_param(check_negative, types::I64); // exponent |
| 1389 | self.builder.append_block_param(check_negative, types::I64); // base |
| 1390 | |
| 1391 | self.builder.append_block_param(handle_negative, types::I64); // abs(exponent) |
| 1392 | self.builder.append_block_param(handle_negative, types::I64); // base |
| 1393 | |
| 1394 | self.builder.append_block_param(loop_block, types::I64); // exponent |
| 1395 | self.builder.append_block_param(loop_block, types::I64); // result |
| 1396 | self.builder.append_block_param(loop_block, types::I64); // base |
| 1397 | |
| 1398 | self.builder.append_block_param(exit_block, types::I64); // final result |
| 1399 | |
| 1400 | // Set up parameters for continue_block |
| 1401 | self.builder.append_block_param(continue_block, types::I64); // exponent |
| 1402 | self.builder.append_block_param(continue_block, types::I64); // result |
| 1403 | self.builder.append_block_param(continue_block, types::I64); // base |
| 1404 | |
| 1405 | // Initial jump to check if exponent is negative |
| 1406 | self.builder |
| 1407 | .ins() |
| 1408 | .jump(check_negative, &[b.into(), a.into()]); |
| 1409 | |
| 1410 | // Check if exponent is negative |
| 1411 | self.builder.switch_to_block(check_negative); |
| 1412 | let params = self.builder.block_params(check_negative); |
| 1413 | let exp_check = params[0]; |
| 1414 | let base_check = params[1]; |
| 1415 | |
| 1416 | let is_negative = self |
| 1417 | .builder |
| 1418 | .ins() |
| 1419 | .icmp(IntCC::SignedLessThan, exp_check, zero); |
| 1420 | self.builder.ins().brif( |
| 1421 | is_negative, |
| 1422 | handle_negative, |
| 1423 | &[exp_check.into(), base_check.into()], |
| 1424 | loop_block, |
| 1425 | &[exp_check.into(), one_i64.into(), base_check.into()], |
| 1426 | ); |
| 1427 | |
| 1428 | // Handle negative exponent (return 0 for integer exponentiation) |
| 1429 | self.builder.switch_to_block(handle_negative); |
| 1430 | self.builder.ins().jump(exit_block, &[zero.into()]); // Return 0 for negative exponents |
| 1431 | |
| 1432 | // Loop block logic (square-and-multiply algorithm) |
| 1433 | self.builder.switch_to_block(loop_block); |
no test coverage detected