Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 llvm) # lshift
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RUN(NAME intrinsics_03 LABELS llvm) # lshift
RUN(NAME intrinsics_03 LABELS cpython llvm) # lshift

This verifies that the test works with python as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the comment below: #2556 (comment)


# lpython decorator
RUN(NAME lpython_decorator_01 LABELS cpython)
Expand Down
12 changes: 12 additions & 0 deletions integration_tests/intrinsics_03.py
Original file line number Diff line number Diff line change
@@ -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<<b)

print(lshift(5,2))
assert(lshift(5,2) == 5<<2)
82 changes: 82 additions & 0 deletions src/libasr/pass/intrinsic_function_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum class IntrinsicScalarFunctions : int64_t {
FMA,
FlipSign,
Mod,
LShift,
Trailz,
FloorDiv,
ListIndex,
Expand Down Expand Up @@ -122,6 +123,7 @@ inline std::string get_intrinsic_name(int x) {
INTRINSIC_NAME_CASE(FlipSign)
INTRINSIC_NAME_CASE(FloorDiv)
INTRINSIC_NAME_CASE(Mod)
INTRINSIC_NAME_CASE(LShift)
INTRINSIC_NAME_CASE(Trailz)
INTRINSIC_NAME_CASE(ListIndex)
INTRINSIC_NAME_CASE(Partition)
Expand Down Expand Up @@ -2382,6 +2384,81 @@ namespace Mod {

} // namespace Mod

#define i_BitRshift(n, bits, t) EXPR(ASR::make_IntegerBinOp_t(al, loc, \
n, ASR::binopType::BitRShift, bits, t, nullptr))
#define i_BitLshift(n, bits, t) EXPR(ASR::make_IntegerBinOp_t(al, loc, \
n, ASR::binopType::BitLShift, bits, t, nullptr))
Comment thread
Kishan-Ved marked this conversation as resolved.
Outdated

namespace LShift {

static inline void verify_args(const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) {
ASRUtils::require_impl(x.n_args == 2,
"ASR Verify: Call to LShift must have exactly 2 arguments",
x.base.base.loc, diagnostics);
ASR::ttype_t *type1 = ASRUtils::expr_type(x.m_args[0]);
ASR::ttype_t *type2 = ASRUtils::expr_type(x.m_args[1]);
ASRUtils::require_impl((is_integer(*type1) && is_integer(*type2)),
"ASR Verify: Arguments to LShift must be of integer type",
x.base.base.loc, diagnostics);
}

static ASR::expr_t *eval_LShift(Allocator &al, const Location &loc,
ASR::ttype_t* t1, Vec<ASR::expr_t*> &args) {
int64_t a = ASR::down_cast<ASR::IntegerConstant_t>(args[0])->m_n;
int64_t b = ASR::down_cast<ASR::IntegerConstant_t>(args[1])->m_n;
int64_t val = a << b;
return make_ConstantWithType(make_IntegerConstant_t, val, t1, loc);
Comment thread
Kishan-Ved marked this conversation as resolved.
Outdated
}

static inline ASR::asr_t* create_LShift(Allocator& al, const Location& loc,
Vec<ASR::expr_t*>& args,
const std::function<void (const std::string &, const Location &)> 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<ASR::expr_t*> 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<int64_t>(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<ASR::ttype_t*>& arg_types, ASR::ttype_t *return_type,
Vec<ASR::call_arg_t>& 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) {
Expand Down Expand Up @@ -3665,6 +3742,8 @@ namespace IntrinsicScalarFunctionRegistry {
{&FloorDiv::instantiate_FloorDiv, &FloorDiv::verify_args}},
{static_cast<int64_t>(IntrinsicScalarFunctions::Mod),
{&Mod::instantiate_Mod, &Mod::verify_args}},
{static_cast<int64_t>(IntrinsicScalarFunctions::LShift),
{&LShift::instantiate_LShift, &LShift::verify_args}},
{static_cast<int64_t>(IntrinsicScalarFunctions::Trailz),
{&Trailz::instantiate_Trailz, &Trailz::verify_args}},
{static_cast<int64_t>(IntrinsicScalarFunctions::Abs),
Expand Down Expand Up @@ -3793,6 +3872,8 @@ namespace IntrinsicScalarFunctionRegistry {
"floordiv"},
{static_cast<int64_t>(IntrinsicScalarFunctions::Mod),
"mod"},
{static_cast<int64_t>(IntrinsicScalarFunctions::LShift),
"lshift"},
{static_cast<int64_t>(IntrinsicScalarFunctions::Trailz),
"trailz"},
{static_cast<int64_t>(IntrinsicScalarFunctions::Expm1),
Expand Down Expand Up @@ -3901,6 +3982,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}},
Expand Down