Skip to main content

luaur_code_gen/functions/
translate_builtin_math_log.rs

1use crate::enums::builtin_impl_type::BuiltinImplType;
2use crate::enums::ir_cmd::IrCmd;
3use crate::functions::builtin_check_double::builtin_check_double;
4use crate::functions::builtin_load_double::builtin_load_double;
5use crate::records::builtin_impl_result::BuiltinImplResult;
6use crate::records::ir_builder::IrBuilder;
7use crate::records::ir_op::IrOp;
8
9pub fn translate_builtin_math_log(
10    build: &mut IrBuilder,
11    nparams: i32,
12    ra: i32,
13    arg: i32,
14    args: IrOp,
15    nresults: i32,
16    pcpos: i32,
17) -> BuiltinImplResult {
18    if nparams < 1 || nresults > 1 {
19        return BuiltinImplResult {
20            r#type: BuiltinImplType::None,
21            actual_result_count: -1,
22        };
23    }
24
25    let mut libm_id = 12; // LBF_MATH_LOG
26    let mut denom: Option<f64> = None;
27
28    if nparams != 1 {
29        let y = build.function.as_double_op(args);
30
31        if y.is_none() {
32            return BuiltinImplResult {
33                r#type: BuiltinImplType::None,
34                actual_result_count: -1,
35            };
36        }
37
38        let y_val = y.unwrap();
39        if y_val == 2.0 {
40            libm_id = 256; // LBF_IR_MATH_LOG2
41        } else if y_val == 10.0 {
42            libm_id = 13; // LBF_MATH_LOG10
43        } else {
44            denom = Some(y_val.ln());
45        }
46    }
47
48    let arg_op = build.vm_reg(arg as u8);
49    builtin_check_double(build, arg_op, pcpos);
50
51    let va = builtin_load_double(build, arg_op);
52
53    let const_libm_id = build.const_uint(libm_id as u32);
54    let mut res = build.inst_ir_cmd_ir_op_ir_op(IrCmd::INVOKE_LIBM, const_libm_id, va);
55
56    if let Some(d) = denom {
57        let const_d = build.const_double(d);
58        res = build.inst_ir_cmd_ir_op_ir_op(IrCmd::DIV_NUM, res, const_d);
59    }
60
61    let ra_op = build.vm_reg(ra as u8);
62    build.inst_ir_cmd_ir_op_ir_op(IrCmd::STORE_DOUBLE, ra_op, res);
63
64    if ra != arg {
65        let const_tag = build.const_tag(0); // LUA_TNUMBER
66        build.inst_ir_cmd_ir_op_ir_op(IrCmd::STORE_TAG, ra_op, const_tag);
67    }
68
69    BuiltinImplResult {
70        r#type: BuiltinImplType::Full,
71        actual_result_count: 1,
72    }
73}