Skip to content

Commit bed4733

Browse files
authored
Merge pull request #83 from czgdp1807/ptr_01
Added support for pointer in LC by porting ``integration_tests/associate_02.f90`` from LFortran
2 parents f7fac14 + 8bee7cd commit bed4733

File tree

7 files changed

+119
-26
lines changed

7 files changed

+119
-26
lines changed

integration_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,6 @@ RUN(NAME struct_02.cpp LABELS gcc llvm NOFAST)
213213
RUN(NAME struct_03.cpp LABELS gcc llvm NOFAST)
214214
RUN(NAME struct_04.cpp LABELS gcc llvm NOFAST)
215215

216+
RUN(NAME pointer_01.cpp LABELS gcc llvm NOFAST)
217+
216218
RUN(NAME function_01.cpp LABELS gcc llvm NOFAST)

integration_tests/pointer_01.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <iostream>
2+
#include <complex>
3+
4+
using namespace std::complex_literals;
5+
6+
#define check(p, t, v) if( *p != v ) { \
7+
exit(2); \
8+
} \
9+
if( t != v ) { \
10+
exit(2); \
11+
} \
12+
13+
int main() {
14+
15+
int* p1;
16+
double* p2;
17+
int t1 = 2;
18+
double t2 = 2.0;
19+
std::complex<double>* p3;
20+
std::complex<double> t3 = 2.0 + 1i*3.0;
21+
22+
p1 = &t1;
23+
p2 = &t2;
24+
p3 = &t3;
25+
*p1 = 1;
26+
*p2 = 4.0;
27+
28+
std::cout << *p1 << std::endl;
29+
std::cout << t1 << std::endl;
30+
check(p1, t1, 1)
31+
32+
t1 = *p2 + *p1;
33+
34+
std::cout << *p1 << std::endl;
35+
std::cout << t1 << std::endl;
36+
check(p1, t1, 5);
37+
38+
t1 = 8;
39+
40+
std::cout << *p1 << std::endl;
41+
std::cout << t1 << std::endl;
42+
check(p1, t1, 8);
43+
44+
*p3 = 2.0 * (*p3);
45+
std::cout << *p3 << std::endl;
46+
std::cout << t3 << std::endl;
47+
check(p3, t3, 4.0 + 1i*6.0);
48+
49+
}

src/lc/clang_ast_to_asr.cpp

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
210210
return dummy_variable_sym;
211211
}
212212

213+
ASR::asr_t* make_Assignment_t_util(Allocator &al, const Location &a_loc,
214+
ASR::expr_t* a_target, ASR::expr_t* a_value, ASR::stmt_t* a_overloaded) {
215+
if( ASR::is_a<ASR::AddressOf_t>(*a_value) ) {
216+
a_value = ASRUtils::EXPR(ASR::make_Var_t(al, a_value->base.loc,
217+
ASR::down_cast<ASR::AddressOf_t>(a_value)->m_v));
218+
return ASR::make_Associate_t(al, a_loc, a_target, a_value);
219+
}
220+
221+
return ASR::make_Assignment_t(al, a_loc, a_target, a_value, a_overloaded);
222+
}
223+
213224
void construct_program() {
214225
// Convert the main function into a program
215226
ASR::TranslationUnit_t* tu = (ASR::TranslationUnit_t*)this->tu;
@@ -236,7 +247,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
236247

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

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

@@ -726,7 +737,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
726737
ASR::expr_t* value = ASRUtils::EXPR(tmp.get());
727738
cast_helper(obj, value, true);
728739
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), obj, value);
729-
tmp = ASR::make_Assignment_t(al, Lloc(x), obj, value, nullptr);
740+
tmp = make_Assignment_t_util(al, Lloc(x), obj, value, nullptr);
730741
is_stmt_created = true;
731742
}
732743
assignment_target = nullptr;
@@ -737,7 +748,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
737748
if( !is_stmt_created ) {
738749
ASR::expr_t* value = ASRUtils::EXPR(tmp.get());
739750
cast_helper(obj, value, true);
740-
tmp = ASR::make_Assignment_t(al, Lloc(x), obj, value, nullptr);
751+
tmp = make_Assignment_t_util(al, Lloc(x), obj, value, nullptr);
741752
is_stmt_created = true;
742753
}
743754
assignment_target = nullptr;
@@ -962,7 +973,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
962973
ASR::abiType::Source, false, target_physical_type, override_physical_type, false);
963974
ASR::expr_t* new_shape = ASRUtils::cast_to_descriptor(al, args.p[0]);
964975
tmp = ASR::make_ArrayReshape_t(al, Lloc(x), callee, new_shape, target_type, nullptr);
965-
tmp = ASR::make_Assignment_t(al, Lloc(x), callee, ASRUtils::EXPR(tmp.get()), nullptr);
976+
tmp = make_Assignment_t_util(al, Lloc(x), callee, ASRUtils::EXPR(tmp.get()), nullptr);
966977
is_stmt_created = true;
967978
} else if (sf == SpecialFunc::Size) {
968979
if( args.size() != 0 ) {
@@ -982,7 +993,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
982993

983994
ASR::expr_t* arg = args.p[0];
984995
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), callee, arg);
985-
tmp = ASR::make_Assignment_t(al, Lloc(x), callee, arg, nullptr);
996+
tmp = make_Assignment_t_util(al, Lloc(x), callee, arg, nullptr);
986997
is_stmt_created = true;
987998
} else if( sf == SpecialFunc::All ) {
988999
// Handles xt::all() - no arguments
@@ -1331,7 +1342,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
13311342
if( tmp != nullptr && !is_stmt_created ) {
13321343
ASR::expr_t* init_val = ASRUtils::EXPR(tmp.get());
13331344
add_reshape_if_needed(init_val, var);
1334-
tmp = ASR::make_Assignment_t(al, Lloc(x), var, init_val, nullptr);
1345+
tmp = make_Assignment_t_util(al, Lloc(x), var, init_val, nullptr);
13351346
is_stmt_created = true;
13361347
}
13371348
}
@@ -1545,7 +1556,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
15451556
if( op == clang::BO_Assign ) {
15461557
cast_helper(x_lhs, x_rhs, true);
15471558
ASRUtils::make_ArrayBroadcast_t_util(al, Lloc(x), x_lhs, x_rhs);
1548-
tmp = ASR::make_Assignment_t(al, Lloc(x), x_lhs, x_rhs, nullptr);
1559+
tmp = make_Assignment_t_util(al, Lloc(x), x_lhs, x_rhs, nullptr);
15491560
is_stmt_created = true;
15501561
} else {
15511562
bool is_binop = false, is_cmpop = false;
@@ -1689,22 +1700,10 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
16891700
}
16901701

16911702
void cast_helper(ASR::expr_t*& left, ASR::expr_t*& right, bool is_assign) {
1692-
bool no_cast = ((ASR::is_a<ASR::Pointer_t>(*ASRUtils::expr_type(left)) &&
1693-
ASR::is_a<ASR::Var_t>(*left)) ||
1694-
(ASR::is_a<ASR::Pointer_t>(*ASRUtils::expr_type(right)) &&
1695-
ASR::is_a<ASR::Var_t>(*right)));
16961703
ASR::ttype_t *right_type = ASRUtils::expr_type(right);
16971704
ASR::ttype_t *left_type = ASRUtils::expr_type(left);
16981705
left_type = ASRUtils::extract_type(left_type);
16991706
right_type = ASRUtils::extract_type(right_type);
1700-
if( no_cast ) {
1701-
int lkind = ASRUtils::extract_kind_from_ttype_t(left_type);
1702-
int rkind = ASRUtils::extract_kind_from_ttype_t(right_type);
1703-
if( left_type->type != right_type->type || lkind != rkind ) {
1704-
throw SemanticError("Casting for mismatching pointer types not supported yet.",
1705-
right_type->base.loc);
1706-
}
1707-
}
17081707

17091708
// Handle presence of logical types in binary operations
17101709
// by converting them into 32-bit integers.
@@ -1886,7 +1885,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
18861885
ASR::symbol_t* return_sym = current_scope->resolve_symbol("__return_var");
18871886
ASR::expr_t* return_var = ASRUtils::EXPR(ASR::make_Var_t(al, Lloc(x), return_sym));
18881887
TraverseStmt(x->getRetValue());
1889-
tmp = ASR::make_Assignment_t(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr);
1888+
tmp = make_Assignment_t_util(al, Lloc(x), return_var, ASRUtils::EXPR(tmp.get()), nullptr);
18901889
current_body->push_back(al, ASRUtils::STMT(tmp.get()));
18911890
tmp = ASR::make_Return_t(al, Lloc(x));
18921891
is_stmt_created = true;
@@ -1939,7 +1938,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
19391938
ASR::expr_t* x_rhs = ASRUtils::EXPR(tmp.get());
19401939
CreateBinOp(x_lhs, x_rhs, ASR::binopType::Add, Lloc(x));
19411940
ASR::expr_t* sum_expr = ASRUtils::EXPR(tmp.get());
1942-
tmp = ASR::make_Assignment_t(al, Lloc(x), x_lhs, sum_expr, nullptr);
1941+
tmp = make_Assignment_t_util(al, Lloc(x), x_lhs, sum_expr, nullptr);
19431942
is_stmt_created = true;
19441943
return true;
19451944
}
@@ -1956,7 +1955,7 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
19561955
ASRUtils::EXPR(ASR::make_IntegerConstant_t(
19571956
al, Lloc(x), 1, ASRUtils::expr_type(var))),
19581957
ASRUtils::expr_type(var), nullptr));
1959-
tmp = ASR::make_Assignment_t(al, Lloc(x), var, incbyone, nullptr);
1958+
tmp = make_Assignment_t_util(al, Lloc(x), var, incbyone, nullptr);
19601959
is_stmt_created = true;
19611960
break;
19621961
}
@@ -1968,8 +1967,31 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
19681967
CreateLogicalNot(var, Lloc(x));
19691968
break;
19701969
}
1970+
case clang::UnaryOperatorKind::UO_AddrOf: {
1971+
if( !ASR::is_a<ASR::Var_t>(*var) ) {
1972+
throw std::runtime_error("Address of operator is only supported for symbols.");
1973+
}
1974+
1975+
ASR::Var_t* var_t = ASR::down_cast<ASR::Var_t>(var);
1976+
tmp = ASR::make_AddressOf_t(al, Lloc(x), var_t->m_v, ASRUtils::TYPE(
1977+
ASR::make_Pointer_t(al, Lloc(x), ASRUtils::expr_type(var))));
1978+
is_stmt_created = false;
1979+
break;
1980+
}
1981+
case clang::UnaryOperatorKind::UO_Deref: {
1982+
if( !ASR::is_a<ASR::Var_t>(*var) ) {
1983+
throw std::runtime_error("Dereference operator is only supported for symbols.");
1984+
}
1985+
1986+
ASR::Var_t* var_t = ASR::down_cast<ASR::Var_t>(var);
1987+
tmp = ASR::make_DereferencePointer_t(al, Lloc(x), var_t->m_v,
1988+
ASRUtils::type_get_past_pointer(ASRUtils::expr_type(var)));
1989+
is_stmt_created = false;
1990+
break;
1991+
}
19711992
default: {
1972-
throw std::runtime_error("Only postfix increment and minus are supported so far.");
1993+
throw std::runtime_error("Only postfix increment, minus and "
1994+
"address of operators are supported so far.");
19731995
}
19741996
}
19751997
return true;

src/libasr/ASR.asdl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ expr
311311
| DictLen(expr arg, ttype type, expr? value)
312312

313313
| Var(symbol v)
314+
| AddressOf(symbol v, ttype type)
315+
| DereferencePointer(symbol v, ttype type)
314316
| FunctionParam(int param_number, ttype type, expr? value) --- used in types
315317

316318
| ArrayConstant(expr* args, ttype type, arraystorage storage_format)

src/libasr/asdl_cpp.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,6 +2603,9 @@ def make_visitor(self, name, fields):
26032603
elif name.endswith("Constant") or name == "IntegerBOZ":
26042604
self.emit("case ASR::exprType::%s: { return f; }"\
26052605
% (name), 2, new_line=False)
2606+
elif name == "AddressOf" or name == "DereferencePointer":
2607+
self.emit("case ASR::exprType::%s: { return nullptr; }"\
2608+
% (name), 2, new_line=False)
26062609
else:
26072610
self.emit("case ASR::exprType::%s: { return ((ASR::%s_t*)f)->m_value; }"\
26082611
% (name, name), 2, new_line=False)

src/libasr/asr_utils.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,14 @@ static inline int extract_kind_from_ttype_t(const ASR::ttype_t* type) {
210210

211211
static inline ASR::Variable_t* EXPR2VAR(const ASR::expr_t *f)
212212
{
213-
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
214-
ASR::down_cast<ASR::Var_t>(f)->m_v));
213+
if( ASR::is_a<ASR::Var_t>(*f) ) {
214+
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
215+
ASR::down_cast<ASR::Var_t>(f)->m_v));
216+
} else if( ASR::is_a<ASR::DereferencePointer_t>(*f) ) {
217+
return ASR::down_cast<ASR::Variable_t>(symbol_get_past_external(
218+
ASR::down_cast<ASR::DereferencePointer_t>(f)->m_v));
219+
}
220+
return nullptr;
215221
}
216222

217223
static inline ASR::Function_t* EXPR2FUN(const ASR::expr_t *f)

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6520,12 +6520,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
65206520
}
65216521
}
65226522

6523-
void visit_Var(const ASR::Var_t &x) {
6523+
template <typename T>
6524+
void visit_SymbolContainingExpr(const T& x) {
65246525
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(
65256526
symbol_get_past_external(x.m_v));
65266527
fetch_var(v);
65276528
}
65286529

6530+
void visit_Var(const ASR::Var_t& x) {
6531+
visit_SymbolContainingExpr(x);
6532+
}
6533+
6534+
void visit_DereferencePointer(const ASR::DereferencePointer_t& x) {
6535+
visit_SymbolContainingExpr(x);
6536+
}
6537+
65296538
inline ASR::ttype_t* extract_ttype_t_from_expr(ASR::expr_t* expr) {
65306539
return ASRUtils::expr_type(expr);
65316540
}

0 commit comments

Comments
 (0)