From 5b9996992354b5b5ae04e437372969af4637afcb Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 5 Mar 2024 15:35:38 +0530 Subject: [PATCH 1/5] TEST: Ported integration_tests/union_01.py from LPython --- integration_tests/union_01.cpp | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 integration_tests/union_01.cpp diff --git a/integration_tests/union_01.cpp b/integration_tests/union_01.cpp new file mode 100644 index 0000000..c9cf8d0 --- /dev/null +++ b/integration_tests/union_01.cpp @@ -0,0 +1,37 @@ +#include + +union u_type { + int32_t integer32; + float real32; + double real64; + int64_t integer64; +}; + +#define assert(cond) if( !(cond) ) { \ + exit(2); \ +} \ + +void test_union() { + union u_type unionobj; + unionobj.integer32 = 1; + std::cout << unionobj.integer32 << std::endl; + assert( unionobj.integer32 == 1 ); + + unionobj.real32 = 2.0; + std::cout << unionobj.real32 << std::endl; + assert( abs(unionobj.real32 - 2.0) <= 1e-6 ); + + unionobj.real64 = 3.5; + std::cout << unionobj.real64 << std::endl; + assert( abs(unionobj.real64 - 3.5) <= 1e-12 ); + + unionobj.integer64 = 4; + std::cout << unionobj.integer64 << std::endl; + assert( unionobj.integer64 == 4 ); +} + +int main() { + +test_union(); + +} From 938df50ff7addb3da3bd099fcc8f7e33e227b548 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 5 Mar 2024 15:36:01 +0530 Subject: [PATCH 2/5] DEV: Added support for UnionType --- src/lc/clang_ast_to_asr.cpp | 48 +++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/lc/clang_ast_to_asr.cpp b/src/lc/clang_ast_to_asr.cpp index 72b47a7..5de7753 100644 --- a/src/lc/clang_ast_to_asr.cpp +++ b/src/lc/clang_ast_to_asr.cpp @@ -472,12 +472,16 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitorgetTypeClass() == clang::Type::TypeClass::Record ) { const clang::CXXRecordDecl* record_type = clang_type->getAsCXXRecordDecl(); - std::string struct_name = record_type->getNameAsString(); - ASR::symbol_t* struct_t = current_scope->resolve_symbol(struct_name); - if( !struct_t ) { - throw std::runtime_error(struct_name + " not defined."); + std::string name = record_type->getNameAsString(); + ASR::symbol_t* type_t = current_scope->resolve_symbol(name); + if( !type_t ) { + throw std::runtime_error(name + " not defined."); + } + if( clang_type->isUnionType() ) { + type = ASRUtils::TYPE(ASR::make_Union_t(al, l, type_t)); + } else { + type = ASRUtils::TYPE(ASR::make_Struct_t(al, l, type_t)); } - type = ASRUtils::TYPE(ASR::make_Struct_t(al, l, struct_t)); } else { throw std::runtime_error("clang::QualType not yet supported " + std::string(clang_type->getTypeClassName())); @@ -518,17 +522,24 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor(parent_scope); - std::string struct_name = x->getNameAsString(); + std::string name = x->getNameAsString(); Vec field_names; field_names.reserve(al, 1); for( auto field = x->field_begin(); field != x->field_end(); field++ ) { clang::FieldDecl* field_decl = *field; TraverseFieldDecl(field_decl); field_names.push_back(al, s2c(al, field_decl->getNameAsString())); } - ASR::symbol_t* struct_t = ASR::down_cast(ASR::make_StructType_t(al, Lloc(x), current_scope, - s2c(al, struct_name), nullptr, 0, field_names.p, field_names.size(), ASR::abiType::Source, - ASR::accessType::Public, false, x->isAbstract(), nullptr, 0, nullptr, nullptr)); - parent_scope->add_symbol(struct_name, struct_t); + if( x->isUnion() ) { + ASR::symbol_t* union_t = ASR::down_cast(ASR::make_UnionType_t(al, Lloc(x), current_scope, + s2c(al, name), nullptr, 0, field_names.p, field_names.size(), ASR::abiType::Source, + ASR::accessType::Public, nullptr, 0, nullptr)); + parent_scope->add_symbol(name, union_t); + } else { + ASR::symbol_t* struct_t = ASR::down_cast(ASR::make_StructType_t(al, Lloc(x), current_scope, + s2c(al, name), nullptr, 0, field_names.p, field_names.size(), ASR::abiType::Source, + ASR::accessType::Public, false, x->isAbstract(), nullptr, 0, nullptr, nullptr)); + parent_scope->add_symbol(name, struct_t); + } current_scope = parent_scope; return true; } @@ -734,6 +745,23 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitoradd_symbol(mangled_name, member); tmp = ASR::make_StructInstanceMember_t(al, Lloc(x), base, member, ASRUtils::symbol_type(member), evaluate_compile_time_value_for_StructInstanceMember(base, member_name)); + } else if( ASR::is_a(*base_type) ) { + ASR::Union_t* union_t = ASR::down_cast(base_type); + ASR::UnionType_t* union_type_t = ASR::down_cast( + ASRUtils::symbol_get_past_external(union_t->m_union_type)); + ASR::symbol_t* member = union_type_t->m_symtab->resolve_symbol(member_name); + if( !member ) { + throw std::runtime_error(member_name + " not found in the scope of " + union_type_t->m_name); + } + std::string mangled_name = current_scope->get_unique_name( + member_name + "@" + union_type_t->m_name); + member = ASR::down_cast(ASR::make_ExternalSymbol_t( + al, Lloc(x), current_scope, s2c(al, mangled_name), member, + union_type_t->m_name, nullptr, 0, s2c(al, member_name), + ASR::accessType::Public)); + current_scope->add_symbol(mangled_name, member); + tmp = ASR::make_UnionInstanceMember_t(al, Lloc(x), + base, member, ASRUtils::symbol_type(member), nullptr); } else if( special_function_map.find(member_name) != special_function_map.end() ) { member_name_obj.set(member_name); return clang::RecursiveASTVisitor::TraverseMemberExpr(x); From 4787337df804ead4c53eb1eec5de763c03c7ad29 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 5 Mar 2024 15:36:59 +0530 Subject: [PATCH 3/5] DEV: Fix ExternalSymbol for UnionInstanceMember --- src/libasr/asr_verify.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index f56658a..9bea5dc 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -703,6 +703,7 @@ class VerifyVisitor : public BaseWalkVisitor ASR::Module_t *m = ASRUtils::get_sym_module(x.m_external); ASR::StructType_t* sm = nullptr; ASR::EnumType_t* em = nullptr; + ASR::UnionType_t* um = nullptr; ASR::Function_t* fm = nullptr; bool is_valid_owner = false; is_valid_owner = m != nullptr && ((ASR::symbol_t*) m == ASRUtils::get_asr_owner(x.m_external)); @@ -711,13 +712,17 @@ class VerifyVisitor : public BaseWalkVisitor ASR::symbol_t* asr_owner_sym = ASRUtils::get_asr_owner(x.m_external); is_valid_owner = (ASR::is_a(*asr_owner_sym) || ASR::is_a(*asr_owner_sym) || - ASR::is_a(*asr_owner_sym)); + ASR::is_a(*asr_owner_sym) || + ASR::is_a(*asr_owner_sym)); if( ASR::is_a(*asr_owner_sym) ) { sm = ASR::down_cast(asr_owner_sym); asr_owner_name = sm->m_name; } else if( ASR::is_a(*asr_owner_sym) ) { em = ASR::down_cast(asr_owner_sym); asr_owner_name = em->m_name; + } else if( ASR::is_a(*asr_owner_sym) ) { + um = ASR::down_cast(asr_owner_sym); + asr_owner_name = um->m_name; } else if( ASR::is_a(*asr_owner_sym) ) { fm = ASR::down_cast(asr_owner_sym); asr_owner_name = fm->m_name; @@ -746,6 +751,8 @@ class VerifyVisitor : public BaseWalkVisitor s = em->m_symtab->resolve_symbol(std::string(x.m_original_name)); } else if( fm ) { s = fm->m_symtab->resolve_symbol(std::string(x.m_original_name)); + } else if( um ) { + s = um->m_symtab->resolve_symbol(std::string(x.m_original_name)); } require(s != nullptr, "ExternalSymbol::m_original_name ('" From ed732061044d48f206a3983516490a17b8e82177 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 5 Mar 2024 15:37:26 +0530 Subject: [PATCH 4/5] DEV: Get past external symbol for UnionInstanceMember::m_m --- src/libasr/codegen/asr_to_llvm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index d472b33..004afde 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -1500,7 +1500,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor this->visit_expr(*x.m_v); ptr_loads = ptr_loads_copy; llvm::Value* union_llvm = tmp; - ASR::Variable_t* member_var = ASR::down_cast(x.m_m); + ASR::Variable_t* member_var = ASR::down_cast( + ASRUtils::symbol_get_past_external(x.m_m)); ASR::ttype_t* member_type_asr = ASRUtils::get_contained_type(member_var->m_type); if( ASR::is_a(*member_type_asr) ) { ASR::Struct_t* d = ASR::down_cast(member_type_asr); From bf23900564d097f3ff6f6068757fb9922a49452d Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 5 Mar 2024 15:37:37 +0530 Subject: [PATCH 5/5] TEST: Register union_01.cpp --- integration_tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 0824228..9fa42f1 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -229,3 +229,5 @@ RUN(NAME enum_01.cpp LABELS gcc llvm NOFAST) RUN(NAME enum_02.cpp LABELS gcc llvm NOFAST) RUN(NAME enum_03.cpp LABELS gcc llvm NOFAST) RUN(NAME enum_04.cpp LABELS gcc llvm NOFAST) + +RUN(NAME union_01.cpp LABELS gcc llvm NOFAST)