diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 1177bb5266..73d7757fed 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -816,6 +816,7 @@ RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython) # Intrinsic Functions RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any RUN(NAME intrinsics_02 LABELS cpython llvm c) # floordiv +RUN(NAME intrinsics_03 LABELS cpython llvm) # lshift # lpython decorator RUN(NAME lpython_decorator_01 LABELS cpython) diff --git a/integration_tests/intrinsics_03.py b/integration_tests/intrinsics_03.py new file mode 100644 index 0000000000..8d89909843 --- /dev/null +++ b/integration_tests/intrinsics_03.py @@ -0,0 +1,12 @@ +from lpython import i32 + +a : i32 +b : i32 + +a = 5 +b = 2 +print(lshift(a,b)) +assert(lshift(a,b) == a< &args) { + int64_t a = ASR::down_cast(args[0])->m_n; + int64_t b = ASR::down_cast(args[1])->m_n; + int64_t val = a << b; + return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc); + } + + static inline ASR::asr_t* create_LShift(Allocator& al, const Location& loc, + Vec& args, + const std::function err) { + if (args.size() != 2) { + err("Intrinsic LShift function accepts exactly 2 arguments", loc); + } + ASR::ttype_t *type1 = ASRUtils::expr_type(args[0]); + ASR::ttype_t *type2 = ASRUtils::expr_type(args[1]); + if (!((ASRUtils::is_integer(*type1) && ASRUtils::is_integer(*type2)))) { + err("Argument of the LShift function must be Integer", + args[0]->base.loc); + } + ASR::expr_t *m_value = nullptr; + if (all_args_evaluated(args)) { + Vec arg_values; arg_values.reserve(al, 2); + arg_values.push_back(al, expr_value(args[0])); + arg_values.push_back(al, expr_value(args[1])); + m_value = eval_LShift(al, loc, expr_type(args[1]), arg_values); + } + return ASR::make_IntrinsicScalarFunction_t(al, loc, + static_cast(IntrinsicScalarFunctions::LShift), + args.p, args.n, 0, ASRUtils::expr_type(args[0]), m_value); + } + + static inline ASR::expr_t* instantiate_LShift(Allocator &al, const Location &loc, + SymbolTable *scope, Vec& arg_types, ASR::ttype_t *return_type, + Vec& new_args, int64_t /*overload_id*/) { + declare_basic_variables("_lcompilers_lshift_" + type_to_str_python(arg_types[1])); + fill_func_arg("a", arg_types[0]); + fill_func_arg("p", arg_types[1]); + auto result = declare(fn_name, return_type, ReturnVar); + /* + function LShifti32i32(a, p) result(d) + integer(int32) :: a + integer(int32) :: b + result = a << b + return result + end function + */ + body.push_back(al, b.Assignment(result, i_BitLshift(args[0], args[1], arg_types[0]))); + + ASR::symbol_t *f_sym = make_ASR_Function_t(fn_name, fn_symtab, dep, args, + body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr); + scope->add_symbol(fn_name, f_sym); + return b.Call(f_sym, new_args, return_type, nullptr); + } + +} // namespace LShift + namespace Trailz { static inline void verify_args(const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) { @@ -3665,6 +3743,8 @@ namespace IntrinsicScalarFunctionRegistry { {&FloorDiv::instantiate_FloorDiv, &FloorDiv::verify_args}}, {static_cast(IntrinsicScalarFunctions::Mod), {&Mod::instantiate_Mod, &Mod::verify_args}}, + {static_cast(IntrinsicScalarFunctions::LShift), + {&LShift::instantiate_LShift, &LShift::verify_args}}, {static_cast(IntrinsicScalarFunctions::Trailz), {&Trailz::instantiate_Trailz, &Trailz::verify_args}}, {static_cast(IntrinsicScalarFunctions::Abs), @@ -3793,6 +3873,8 @@ namespace IntrinsicScalarFunctionRegistry { "floordiv"}, {static_cast(IntrinsicScalarFunctions::Mod), "mod"}, + {static_cast(IntrinsicScalarFunctions::LShift), + "lshift"}, {static_cast(IntrinsicScalarFunctions::Trailz), "trailz"}, {static_cast(IntrinsicScalarFunctions::Expm1), @@ -3901,6 +3983,7 @@ namespace IntrinsicScalarFunctionRegistry { {"fma", {&FMA::create_FMA, &FMA::eval_FMA}}, {"floordiv", {&FloorDiv::create_FloorDiv, &FloorDiv::eval_FloorDiv}}, {"mod", {&Mod::create_Mod, &Mod::eval_Mod}}, + {"lshift", {&LShift::create_LShift, &LShift::eval_LShift}}, {"trailz", {&Trailz::create_Trailz, &Trailz::eval_Trailz}}, {"list.index", {&ListIndex::create_ListIndex, &ListIndex::eval_list_index}}, {"list.reverse", {&ListReverse::create_ListReverse, &ListReverse::eval_list_reverse}},