@@ -48,6 +48,7 @@ enum class IntrinsicScalarFunctions : int64_t {
48
48
FMA,
49
49
FlipSign,
50
50
Mod,
51
+ LShift,
51
52
Trailz,
52
53
FloorDiv,
53
54
ListIndex,
@@ -122,6 +123,7 @@ inline std::string get_intrinsic_name(int x) {
122
123
INTRINSIC_NAME_CASE (FlipSign)
123
124
INTRINSIC_NAME_CASE (FloorDiv)
124
125
INTRINSIC_NAME_CASE (Mod)
126
+ INTRINSIC_NAME_CASE (LShift)
125
127
INTRINSIC_NAME_CASE (Trailz)
126
128
INTRINSIC_NAME_CASE (ListIndex)
127
129
INTRINSIC_NAME_CASE (Partition)
@@ -2382,6 +2384,81 @@ namespace Mod {
2382
2384
2383
2385
} // namespace Mod
2384
2386
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
+
2385
2462
namespace Trailz {
2386
2463
2387
2464
static inline void verify_args (const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) {
@@ -3665,6 +3742,8 @@ namespace IntrinsicScalarFunctionRegistry {
3665
3742
{&FloorDiv::instantiate_FloorDiv, &FloorDiv::verify_args}},
3666
3743
{static_cast <int64_t >(IntrinsicScalarFunctions::Mod),
3667
3744
{&Mod::instantiate_Mod, &Mod::verify_args}},
3745
+ {static_cast <int64_t >(IntrinsicScalarFunctions::LShift),
3746
+ {&LShift::instantiate_LShift, &LShift::verify_args}},
3668
3747
{static_cast <int64_t >(IntrinsicScalarFunctions::Trailz),
3669
3748
{&Trailz::instantiate_Trailz, &Trailz::verify_args}},
3670
3749
{static_cast <int64_t >(IntrinsicScalarFunctions::Abs),
@@ -3793,6 +3872,8 @@ namespace IntrinsicScalarFunctionRegistry {
3793
3872
" floordiv" },
3794
3873
{static_cast <int64_t >(IntrinsicScalarFunctions::Mod),
3795
3874
" mod" },
3875
+ {static_cast <int64_t >(IntrinsicScalarFunctions::LShift),
3876
+ " lshift" },
3796
3877
{static_cast <int64_t >(IntrinsicScalarFunctions::Trailz),
3797
3878
" trailz" },
3798
3879
{static_cast <int64_t >(IntrinsicScalarFunctions::Expm1),
@@ -3901,6 +3982,7 @@ namespace IntrinsicScalarFunctionRegistry {
3901
3982
{" fma" , {&FMA::create_FMA, &FMA::eval_FMA}},
3902
3983
{" floordiv" , {&FloorDiv::create_FloorDiv, &FloorDiv::eval_FloorDiv}},
3903
3984
{" mod" , {&Mod::create_Mod, &Mod::eval_Mod}},
3985
+ {" lshift" , {&LShift::create_LShift, &LShift::eval_LShift}},
3904
3986
{" trailz" , {&Trailz::create_Trailz, &Trailz::eval_Trailz}},
3905
3987
{" list.index" , {&ListIndex::create_ListIndex, &ListIndex::eval_list_index}},
3906
3988
{" list.reverse" , {&ListReverse::create_ListReverse, &ListReverse::eval_list_reverse}},
0 commit comments