Skip to content

Commit

Permalink
Merge pull request #83 from czgdp1807/ptr_01
Browse files Browse the repository at this point in the history
Added support for pointer in LC by porting ``integration_tests/associate_02.f90`` from LFortran
  • Loading branch information
czgdp1807 authored Feb 2, 2024
2 parents f7fac14 + 8bee7cd commit bed4733
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 26 deletions.
2 changes: 2 additions & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,6 @@ RUN(NAME struct_02.cpp LABELS gcc llvm NOFAST)
RUN(NAME struct_03.cpp LABELS gcc llvm NOFAST)
RUN(NAME struct_04.cpp LABELS gcc llvm NOFAST)

RUN(NAME pointer_01.cpp LABELS gcc llvm NOFAST)

RUN(NAME function_01.cpp LABELS gcc llvm NOFAST)
49 changes: 49 additions & 0 deletions integration_tests/pointer_01.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <iostream>
#include <complex>

using namespace std::complex_literals;

#define check(p, t, v) if( *p != v ) { \
exit(2); \
} \
if( t != v ) { \
exit(2); \
} \

int main() {

int* p1;
double* p2;
int t1 = 2;
double t2 = 2.0;
std::complex<double>* p3;
std::complex<double> t3 = 2.0 + 1i*3.0;

p1 = &t1;
p2 = &t2;
p3 = &t3;
*p1 = 1;
*p2 = 4.0;

std::cout << *p1 << std::endl;
std::cout << t1 << std::endl;
check(p1, t1, 1)

t1 = *p2 + *p1;

std::cout << *p1 << std::endl;
std::cout << t1 << std::endl;
check(p1, t1, 5);

t1 = 8;

std::cout << *p1 << std::endl;
std::cout << t1 << std::endl;
check(p1, t1, 8);

*p3 = 2.0 * (*p3);
std::cout << *p3 << std::endl;
std::cout << t3 << std::endl;
check(p3, t3, 4.0 + 1i*6.0);

}
68 changes: 45 additions & 23 deletions src/lc/clang_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,17 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
return dummy_variable_sym;
}

ASR::asr_t* make_Assignment_t_util(Allocator &al, const Location &a_loc,
ASR::expr_t* a_target, ASR::expr_t* a_value, ASR::stmt_t* a_overloaded) {
if( ASR::is_a<ASR::AddressOf_t>(*a_value) ) {
a_value = ASRUtils::EXPR(ASR::make_Var_t(al, a_value->base.loc,
ASR::down_cast<ASR::AddressOf_t>(a_value)->m_v));
return ASR::make_Associate_t(al, a_loc, a_target, a_value);
}

return ASR::make_Assignment_t(al, a_loc, a_target, a_value, a_overloaded);
}

void construct_program() {
// Convert the main function into a program
ASR::TranslationUnit_t* tu = (ASR::TranslationUnit_t*)this->tu;
Expand All @@ -236,7 +247,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit

ASR::symbol_t* exit_variable_sym = declare_dummy_variable("exit_code", program_scope, loc, int32_type);
ASR::expr_t* variable_var = ASRUtils::EXPR(ASR::make_Var_t(al, loc, exit_variable_sym));
ASR::asr_t* assign_stmt = ASR::make_Assignment_t(al, loc, variable_var, ASRUtils::EXPR(func_call_main), nullptr);
ASR::asr_t* assign_stmt = make_Assignment_t_util(al, loc, variable_var, ASRUtils::EXPR(func_call_main), nullptr);

prog_body.push_back(al, ASRUtils::STMT(assign_stmt));

Expand Down Expand Up @@ -726,7 +737,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
ASR::expr_t* value = ASRUtils::EXPR(tmp.get());
cast_helper(obj, value, true);
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), obj, value);
tmp = ASR::make_Assignment_t(al, Lloc(x), obj, value, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), obj, value, nullptr);
is_stmt_created = true;
}
assignment_target = nullptr;
Expand All @@ -737,7 +748,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
if( !is_stmt_created ) {
ASR::expr_t* value = ASRUtils::EXPR(tmp.get());
cast_helper(obj, value, true);
tmp = ASR::make_Assignment_t(al, Lloc(x), obj, value, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), obj, value, nullptr);
is_stmt_created = true;
}
assignment_target = nullptr;
Expand Down Expand Up @@ -962,7 +973,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
ASR::abiType::Source, false, target_physical_type, override_physical_type, false);
ASR::expr_t* new_shape = ASRUtils::cast_to_descriptor(al, args.p[0]);
tmp = ASR::make_ArrayReshape_t(al, Lloc(x), callee, new_shape, target_type, nullptr);
tmp = ASR::make_Assignment_t(al, Lloc(x), callee, ASRUtils::EXPR(tmp.get()), nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), callee, ASRUtils::EXPR(tmp.get()), nullptr);
is_stmt_created = true;
} else if (sf == SpecialFunc::Size) {
if( args.size() != 0 ) {
Expand All @@ -982,7 +993,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit

ASR::expr_t* arg = args.p[0];
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), callee, arg);
tmp = ASR::make_Assignment_t(al, Lloc(x), callee, arg, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), callee, arg, nullptr);
is_stmt_created = true;
} else if( sf == SpecialFunc::All ) {
// Handles xt::all() - no arguments
Expand Down Expand Up @@ -1331,7 +1342,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
if( tmp != nullptr && !is_stmt_created ) {
ASR::expr_t* init_val = ASRUtils::EXPR(tmp.get());
add_reshape_if_needed(init_val, var);
tmp = ASR::make_Assignment_t(al, Lloc(x), var, init_val, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), var, init_val, nullptr);
is_stmt_created = true;
}
}
Expand Down Expand Up @@ -1545,7 +1556,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
if( op == clang::BO_Assign ) {
cast_helper(x_lhs, x_rhs, true);
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), x_lhs, x_rhs);
tmp = ASR::make_Assignment_t(al, Lloc(x), x_lhs, x_rhs, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), x_lhs, x_rhs, nullptr);
is_stmt_created = true;
} else {
bool is_binop = false, is_cmpop = false;
Expand Down Expand Up @@ -1689,22 +1700,10 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
}

void cast_helper(ASR::expr_t*& left, ASR::expr_t*& right, bool is_assign) {
bool no_cast = ((ASR::is_a<ASR::Pointer_t>(*ASRUtils::expr_type(left)) &&
ASR::is_a<ASR::Var_t>(*left)) ||
(ASR::is_a<ASR::Pointer_t>(*ASRUtils::expr_type(right)) &&
ASR::is_a<ASR::Var_t>(*right)));
ASR::ttype_t *right_type = ASRUtils::expr_type(right);
ASR::ttype_t *left_type = ASRUtils::expr_type(left);
left_type = ASRUtils::extract_type(left_type);
right_type = ASRUtils::extract_type(right_type);
if( no_cast ) {
int lkind = ASRUtils::extract_kind_from_ttype_t(left_type);
int rkind = ASRUtils::extract_kind_from_ttype_t(right_type);
if( left_type->type != right_type->type || lkind != rkind ) {
throw SemanticError("Casting for mismatching pointer types not supported yet.",
right_type->base.loc);
}
}

// Handle presence of logical types in binary operations
// by converting them into 32-bit integers.
Expand Down Expand Up @@ -1886,7 +1885,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
ASR::symbol_t* return_sym = current_scope->resolve_symbol("__return_var");
ASR::expr_t* return_var = ASRUtils::EXPR(ASR::make_Var_t(al, Lloc(x), return_sym));
TraverseStmt(x->getRetValue());
tmp = ASR::make_Assignment_t(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr);
current_body->push_back(al, ASRUtils::STMT(tmp.get()));
tmp = ASR::make_Return_t(al, Lloc(x));
is_stmt_created = true;
Expand Down Expand Up @@ -1939,7 +1938,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
ASR::expr_t* x_rhs = ASRUtils::EXPR(tmp.get());
CreateBinOp(x_lhs, x_rhs, ASR::binopType::Add, Lloc(x));
ASR::expr_t* sum_expr = ASRUtils::EXPR(tmp.get());
tmp = ASR::make_Assignment_t(al, Lloc(x), x_lhs, sum_expr, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), x_lhs, sum_expr, nullptr);
is_stmt_created = true;
return true;
}
Expand All @@ -1956,7 +1955,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
ASRUtils::EXPR(ASR::make_IntegerConstant_t(
al, Lloc(x), 1, ASRUtils::expr_type(var))),
ASRUtils::expr_type(var), nullptr));
tmp = ASR::make_Assignment_t(al, Lloc(x), var, incbyone, nullptr);
tmp = make_Assignment_t_util(al, Lloc(x), var, incbyone, nullptr);
is_stmt_created = true;
break;
}
Expand All @@ -1968,8 +1967,31 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
CreateLogicalNot(var, Lloc(x));
break;
}
case clang::UnaryOperatorKind::UO_AddrOf: {
if( !ASR::is_a<ASR::Var_t>(*var) ) {
throw std::runtime_error("Address of operator is only supported for symbols.");
}

ASR::Var_t* var_t = ASR::down_cast<ASR::Var_t>(var);
tmp = ASR::make_AddressOf_t(al, Lloc(x), var_t->m_v, ASRUtils::TYPE(
ASR::make_Pointer_t(al, Lloc(x), ASRUtils::expr_type(var))));
is_stmt_created = false;
break;
}
case clang::UnaryOperatorKind::UO_Deref: {
if( !ASR::is_a<ASR::Var_t>(*var) ) {
throw std::runtime_error("Dereference operator is only supported for symbols.");
}

ASR::Var_t* var_t = ASR::down_cast<ASR::Var_t>(var);
tmp = ASR::make_DereferencePointer_t(al, Lloc(x), var_t->m_v,
ASRUtils::type_get_past_pointer(ASRUtils::expr_type(var)));
is_stmt_created = false;
break;
}
default: {
throw std::runtime_error("Only postfix increment and minus are supported so far.");
throw std::runtime_error("Only postfix increment, minus and "
"address of operators are supported so far.");
}
}
return true;
Expand Down
2 changes: 2 additions & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ expr
| DictLen(expr arg, ttype type, expr? value)

| Var(symbol v)
| AddressOf(symbol v, ttype type)
| DereferencePointer(symbol v, ttype type)
| FunctionParam(int param_number, ttype type, expr? value) --- used in types

| ArrayConstant(expr* args, ttype type, arraystorage storage_format)
Expand Down
3 changes: 3 additions & 0 deletions src/libasr/asdl_cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2603,6 +2603,9 @@ def make_visitor(self, name, fields):
elif name.endswith("Constant") or name == "IntegerBOZ":
self.emit("case ASR::exprType::%s: { return f; }"\
% (name), 2, new_line=False)
elif name == "AddressOf" or name == "DereferencePointer":
self.emit("case ASR::exprType::%s: { return nullptr; }"\
% (name), 2, new_line=False)
else:
self.emit("case ASR::exprType::%s: { return ((ASR::%s_t*)f)->m_value; }"\
% (name, name), 2, new_line=False)
Expand Down
10 changes: 8 additions & 2 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,14 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) {

static inline ASR::Variable_t* EXPR2VAR(const ASR::expr_t *f)
{
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
ASR::down_cast<ASR::Var_t>(f)->m_v));
if( ASR::is_a<ASR::Var_t>(*f) ) {
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
ASR::down_cast<ASR::Var_t>(f)->m_v));
} else if( ASR::is_a<ASR::DereferencePointer_t>(*f) ) {
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
ASR::down_cast<ASR::DereferencePointer_t>(f)->m_v));
}
return nullptr;
}

static inline ASR::Function_t* EXPR2FUN(const ASR::expr_t *f)
Expand Down
11 changes: 10 additions & 1 deletion src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6520,12 +6520,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}
}

void visit_Var(const ASR::Var_t &x) {
template <typename T>
void visit_SymbolContainingExpr(const T& x) {
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(
symbol_get_past_external(x.m_v));
fetch_var(v);
}

void visit_Var(const ASR::Var_t& x) {
visit_SymbolContainingExpr(x);
}

void visit_DereferencePointer(const ASR::DereferencePointer_t& x) {
visit_SymbolContainingExpr(x);
}

inline ASR::ttype_t* extract_ttype_t_from_expr(ASR::expr_t* expr) {
return ASRUtils::expr_type(expr);
}
Expand Down

0 comments on commit bed4733

Please sign in to comment.