@@ -48,6 +48,7 @@ enum class IntrinsicScalarFunctions : int64_t {
4848 FMA,
4949 FlipSign,
5050 Mod,
51+ LShift,
5152 Trailz,
5253 FloorDiv,
5354 ListIndex,
@@ -122,6 +123,7 @@ inline std::string get_intrinsic_name(int x) {
122123 INTRINSIC_NAME_CASE (FlipSign)
123124 INTRINSIC_NAME_CASE (FloorDiv)
124125 INTRINSIC_NAME_CASE (Mod)
126+ INTRINSIC_NAME_CASE (LShift)
125127 INTRINSIC_NAME_CASE (Trailz)
126128 INTRINSIC_NAME_CASE (ListIndex)
127129 INTRINSIC_NAME_CASE (Partition)
@@ -2382,6 +2384,81 @@ namespace Mod {
23822384
23832385} // namespace Mod
23842386
2387+ #define i_BitRshift (n, bits, t ) EXPR(ASR::make_IntegerBinOp_t(al, loc, \
2388+ n, ASR::binopType::BitRShift, bits, t, nullptr ))
2389+ #define i_BitLshift (n, bits, t ) EXPR(ASR::make_IntegerBinOp_t(al, loc, \
2390+ n, ASR::binopType::BitLShift, bits, t, nullptr ))
2391+
2392+ namespace LShift {
2393+
2394+ static inline void verify_args (const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) {
2395+ ASRUtils::require_impl (x.n_args == 2 ,
2396+ " ASR Verify: Call to LShift must have exactly 2 arguments" ,
2397+ x.base .base .loc , diagnostics);
2398+ ASR::ttype_t *type1 = ASRUtils::expr_type (x.m_args [0 ]);
2399+ ASR::ttype_t *type2 = ASRUtils::expr_type (x.m_args [1 ]);
2400+ ASRUtils::require_impl ((is_integer (*type1) && is_integer (*type2)),
2401+ " ASR Verify: Arguments to LShift must be of integer type" ,
2402+ x.base .base .loc , diagnostics);
2403+ }
2404+
2405+ static ASR::expr_t *eval_LShift (Allocator &al, const Location &loc,
2406+ ASR::ttype_t * t1, Vec<ASR::expr_t *> &args) {
2407+ int64_t a = ASR::down_cast<ASR::IntegerConstant_t>(args[0 ])->m_n ;
2408+ int64_t b = ASR::down_cast<ASR::IntegerConstant_t>(args[1 ])->m_n ;
2409+ int64_t val = a << b;
2410+ return make_ConstantWithType (make_IntegerConstant_t, val, t1, loc);
2411+ }
2412+
2413+ static inline ASR::asr_t * create_LShift (Allocator& al, const Location& loc,
2414+ Vec<ASR::expr_t *>& args,
2415+ const std::function<void (const std::string &, const Location &)> err) {
2416+ if (args.size () != 2 ) {
2417+ err (" Intrinsic LShift function accepts exactly 2 arguments" , loc);
2418+ }
2419+ ASR::ttype_t *type1 = ASRUtils::expr_type (args[0 ]);
2420+ ASR::ttype_t *type2 = ASRUtils::expr_type (args[1 ]);
2421+ if (!((ASRUtils::is_integer (*type1) && ASRUtils::is_integer (*type2)))) {
2422+ err (" Argument of the LShift function must be Integer" ,
2423+ args[0 ]->base .loc );
2424+ }
2425+ ASR::expr_t *m_value = nullptr ;
2426+ if (all_args_evaluated (args)) {
2427+ Vec<ASR::expr_t *> arg_values; arg_values.reserve (al, 2 );
2428+ arg_values.push_back (al, expr_value (args[0 ]));
2429+ arg_values.push_back (al, expr_value (args[1 ]));
2430+ m_value = eval_LShift (al, loc, expr_type (args[1 ]), arg_values);
2431+ }
2432+ return ASR::make_IntrinsicScalarFunction_t (al, loc,
2433+ static_cast <int64_t >(IntrinsicScalarFunctions::LShift),
2434+ args.p , args.n , 0 , ASRUtils::expr_type (args[0 ]), m_value);
2435+ }
2436+
2437+ static inline ASR::expr_t * instantiate_LShift (Allocator &al, const Location &loc,
2438+ SymbolTable *scope, Vec<ASR::ttype_t *>& arg_types, ASR::ttype_t *return_type,
2439+ Vec<ASR::call_arg_t >& new_args, int64_t /* overload_id*/ ) {
2440+ declare_basic_variables (" _lcompilers_lshift_" + type_to_str_python (arg_types[1 ]));
2441+ fill_func_arg (" a" , arg_types[0 ]);
2442+ fill_func_arg (" p" , arg_types[1 ]);
2443+ auto result = declare (fn_name, return_type, ReturnVar);
2444+ /*
2445+ function LShifti32i32(a, p) result(d)
2446+ integer(int32) :: a
2447+ integer(int32) :: b
2448+ result = a << b
2449+ return result
2450+ end function
2451+ */
2452+ body.push_back (al, b.Assignment (result, i_BitLshift (args[0 ], args[1 ], arg_types[0 ])));
2453+
2454+ ASR::symbol_t *f_sym = make_ASR_Function_t (fn_name, fn_symtab, dep, args,
2455+ body, result, ASR::abiType::Source, ASR::deftypeType::Implementation, nullptr );
2456+ scope->add_symbol (fn_name, f_sym);
2457+ return b.Call (f_sym, new_args, return_type, nullptr );
2458+ }
2459+
2460+ } // namespace LShift
2461+
23852462namespace Trailz {
23862463
23872464 static inline void verify_args (const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) {
@@ -3665,6 +3742,8 @@ namespace IntrinsicScalarFunctionRegistry {
36653742 {&FloorDiv::instantiate_FloorDiv, &FloorDiv::verify_args}},
36663743 {static_cast <int64_t >(IntrinsicScalarFunctions::Mod),
36673744 {&Mod::instantiate_Mod, &Mod::verify_args}},
3745+ {static_cast <int64_t >(IntrinsicScalarFunctions::LShift),
3746+ {&LShift::instantiate_LShift, &LShift::verify_args}},
36683747 {static_cast <int64_t >(IntrinsicScalarFunctions::Trailz),
36693748 {&Trailz::instantiate_Trailz, &Trailz::verify_args}},
36703749 {static_cast <int64_t >(IntrinsicScalarFunctions::Abs),
@@ -3793,6 +3872,8 @@ namespace IntrinsicScalarFunctionRegistry {
37933872 " floordiv" },
37943873 {static_cast <int64_t >(IntrinsicScalarFunctions::Mod),
37953874 " mod" },
3875+ {static_cast <int64_t >(IntrinsicScalarFunctions::LShift),
3876+ " lshift" },
37963877 {static_cast <int64_t >(IntrinsicScalarFunctions::Trailz),
37973878 " trailz" },
37983879 {static_cast <int64_t >(IntrinsicScalarFunctions::Expm1),
@@ -3901,6 +3982,7 @@ namespace IntrinsicScalarFunctionRegistry {
39013982 {" fma" , {&FMA::create_FMA, &FMA::eval_FMA}},
39023983 {" floordiv" , {&FloorDiv::create_FloorDiv, &FloorDiv::eval_FloorDiv}},
39033984 {" mod" , {&Mod::create_Mod, &Mod::eval_Mod}},
3985+ {" lshift" , {&LShift::create_LShift, &LShift::eval_LShift}},
39043986 {" trailz" , {&Trailz::create_Trailz, &Trailz::eval_Trailz}},
39053987 {" list.index" , {&ListIndex::create_ListIndex, &ListIndex::eval_list_index}},
39063988 {" list.reverse" , {&ListReverse::create_ListReverse, &ListReverse::eval_list_reverse}},
0 commit comments