@@ -5828,6 +5828,189 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
5828
5828
strings_to_be_deallocated.p = strings_to_be_deallocated_copy;
5829
5829
}
5830
5830
5831
+ void visit_ForEach (const ASR::ForEach_t &x) {
5832
+ llvm::Value **strings_to_be_deallocated_copy = strings_to_be_deallocated.p ;
5833
+ size_t n = strings_to_be_deallocated.n ;
5834
+ strings_to_be_deallocated.reserve (al, 1 );
5835
+
5836
+ int64_t ptr_loads_copy = ptr_loads;
5837
+ ptr_loads = 0 ;
5838
+ this ->visit_expr (*x.m_container );
5839
+ llvm::Value *pcontainer = tmp;
5840
+ ptr_loads = 0 ;
5841
+ this ->visit_expr (*x.m_var );
5842
+ llvm::Value *pvar = tmp;
5843
+ ptr_loads = ptr_loads_copy;
5844
+
5845
+ if (ASR::is_a<ASR::Dict_t>(*ASRUtils::expr_type (x.m_container ))) {
5846
+ ASR::Dict_t *dict_type = ASR::down_cast<ASR::Dict_t>(
5847
+ ASRUtils::expr_type (x.m_container ));
5848
+ ASR::ttype_t *key_type = dict_type->m_key_type ;
5849
+ llvm::Value *capacity = LLVM::CreateLoad (*builder,
5850
+ llvm_utils->dict_api ->get_pointer_to_capacity (pcontainer));
5851
+ llvm::Value *key_mask = LLVM::CreateLoad (*builder,
5852
+ llvm_utils->dict_api ->get_pointer_to_keymask (pcontainer));
5853
+ llvm::Value *key_list = llvm_utils->dict_api ->get_key_list (pcontainer);
5854
+ llvm::AllocaInst *idx_ptr = builder->CreateAlloca (
5855
+ llvm::Type::getInt32Ty (context), nullptr );
5856
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (
5857
+ llvm::Type::getInt32Ty (context), llvm::APInt (32 , 0 )), idx_ptr);
5858
+
5859
+ if (llvm_utils->dict_api == llvm_utils->dict_api_sc ) {
5860
+ llvm::Value *key_value_pairs = LLVM::CreateLoad (*builder,
5861
+ llvm_utils->dict_api ->get_pointer_to_key_value_pairs (pcontainer));
5862
+ llvm::Type* kv_pair_type =
5863
+ llvm_utils->dict_api ->get_key_value_pair_type (key_type, dict_type->m_value_type );
5864
+ llvm::AllocaInst *chain_itr = builder->CreateAlloca (
5865
+ llvm::Type::getInt8PtrTy (context), nullptr );
5866
+
5867
+ create_loop (nullptr , [=](){
5868
+ call_lcompilers_free_strings ();
5869
+ return builder->CreateICmpSGT (capacity, LLVM::CreateLoad (*builder, idx_ptr));
5870
+ }, [&](){
5871
+ llvm::Value* idx = LLVM::CreateLoad (*builder, idx_ptr);
5872
+ llvm::Value* key_mask_value = LLVM::CreateLoad (*builder,
5873
+ llvm_utils->create_ptr_gep (key_mask, idx));
5874
+ llvm::Value* is_key_set = builder->CreateICmpEQ (key_mask_value,
5875
+ llvm::ConstantInt::get (llvm::Type::getInt8Ty (context), llvm::APInt (8 , 1 )));
5876
+
5877
+ llvm_utils->create_if_else (is_key_set, [&]() {
5878
+ llvm::Value* dict_i = llvm_utils->create_ptr_gep (key_value_pairs, idx);
5879
+ llvm::Value* kv_ll_i8 = builder->CreateBitCast (dict_i, llvm::Type::getInt8PtrTy (context));
5880
+ LLVM::CreateStore (*builder, kv_ll_i8, chain_itr);
5881
+
5882
+ llvm::BasicBlock *loop2head = llvm::BasicBlock::Create (context, " loop2.head" );
5883
+ llvm::BasicBlock *loop2body = llvm::BasicBlock::Create (context, " loop2.body" );
5884
+ llvm::BasicBlock *loop2end = llvm::BasicBlock::Create (context, " loop2.end" );
5885
+
5886
+ // head
5887
+ llvm_utils->start_new_block (loop2head);
5888
+ {
5889
+ llvm::Value *cond = builder->CreateICmpNE (
5890
+ LLVM::CreateLoad (*builder, chain_itr),
5891
+ llvm::ConstantPointerNull::get (llvm::Type::getInt8PtrTy (context))
5892
+ );
5893
+ builder->CreateCondBr (cond, loop2body, loop2end);
5894
+ }
5895
+
5896
+ // body
5897
+ llvm_utils->start_new_block (loop2body);
5898
+ {
5899
+ llvm::Value* kv_struct_i8 = LLVM::CreateLoad (*builder, chain_itr);
5900
+ llvm::Value* kv_struct = builder->CreateBitCast (kv_struct_i8, kv_pair_type->getPointerTo ());
5901
+ llvm::Value* kv_el = llvm_utils->create_gep (kv_struct, 0 );
5902
+ if ( !LLVM::is_llvm_struct (key_type) ) {
5903
+ kv_el = LLVM::CreateLoad (*builder, kv_el);
5904
+ }
5905
+ LLVM::CreateStore (*builder, kv_el, pvar);
5906
+ for (size_t i=0 ; i<x.n_body ; i++) {
5907
+ this ->visit_stmt (*x.m_body [i]);
5908
+ }
5909
+ call_lcompilers_free_strings ();
5910
+ llvm::Value* next_kv_struct = LLVM::CreateLoad (*builder, llvm_utils->create_gep (kv_struct, 2 ));
5911
+ LLVM::CreateStore (*builder, next_kv_struct, chain_itr);
5912
+ }
5913
+
5914
+ builder->CreateBr (loop2head);
5915
+
5916
+ // end
5917
+ llvm_utils->start_new_block (loop2end);
5918
+ }, [=]() {
5919
+ });
5920
+ llvm::Value* tmp = builder->CreateAdd (idx,
5921
+ llvm::ConstantInt::get (context, llvm::APInt (32 , 1 )));
5922
+ LLVM::CreateStore (*builder, tmp, idx_ptr);
5923
+
5924
+ });
5925
+
5926
+ } else {
5927
+ create_loop (nullptr , [=](){
5928
+ call_lcompilers_free_strings ();
5929
+ return builder->CreateICmpSGT (capacity, LLVM::CreateLoad (*builder, idx_ptr));
5930
+ }, [&](){
5931
+ llvm::Value *idx = LLVM::CreateLoad (*builder, idx_ptr);
5932
+ llvm::Value *key_mask_value = LLVM::CreateLoad (*builder,
5933
+ llvm_utils->create_ptr_gep (key_mask, idx));
5934
+ llvm::Value *is_key_skip = builder->CreateICmpEQ (key_mask_value,
5935
+ llvm::ConstantInt::get (llvm::Type::getInt8Ty (context),
5936
+ llvm::APInt (8 , 3 )));
5937
+ llvm::Value *is_key_set = builder->CreateICmpNE (key_mask_value,
5938
+ llvm::ConstantInt::get (llvm::Type::getInt8Ty (context),
5939
+ llvm::APInt (8 , 0 )));
5940
+
5941
+ llvm::Value *el_exists = builder->CreateAnd (is_key_set,
5942
+ builder->CreateNot (is_key_skip));
5943
+
5944
+ llvm_utils->create_if_else (el_exists, [&]() {
5945
+ LLVM::CreateStore (*builder, llvm_utils->list_api ->read_item (key_list, idx,
5946
+ false , *module , LLVM::is_llvm_struct (key_type)), pvar);
5947
+
5948
+ for (size_t i=0 ; i<x.n_body ; i++) {
5949
+ this ->visit_stmt (*x.m_body [i]);
5950
+ }
5951
+ call_lcompilers_free_strings ();
5952
+ }, [=](){});
5953
+
5954
+ idx = builder->CreateAdd (idx,
5955
+ llvm::ConstantInt::get (context, llvm::APInt (32 , 1 )));
5956
+ LLVM::CreateStore (*builder, idx, idx_ptr);
5957
+ });
5958
+ }
5959
+ } else if (ASR::is_a<ASR::Set_t>(*ASRUtils::expr_type (x.m_container ))) {
5960
+ ASR::Set_t *set_type = ASR::down_cast<ASR::Set_t>(
5961
+ ASRUtils::expr_type (x.m_container ));
5962
+ ASR::ttype_t *el_type = set_type->m_type ;
5963
+
5964
+ llvm::AllocaInst *idx_ptr = builder->CreateAlloca (
5965
+ llvm::Type::getInt32Ty (context), nullptr );
5966
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (
5967
+ llvm::Type::getInt32Ty (context), llvm::APInt (32 , 0 )), idx_ptr);
5968
+
5969
+ llvm::Value *capacity = LLVM::CreateLoad (*builder,
5970
+ llvm_utils->set_api ->get_pointer_to_capacity (pcontainer));
5971
+ llvm::Value *el_list = llvm_utils->set_api ->get_el_list (pcontainer);
5972
+ llvm::Value *el_mask = LLVM::CreateLoad (*builder,
5973
+ llvm_utils->set_api ->get_pointer_to_mask (pcontainer));
5974
+
5975
+ create_loop (nullptr , [=](){
5976
+ call_lcompilers_free_strings ();
5977
+ return builder->CreateICmpSGT (capacity, LLVM::CreateLoad (*builder, idx_ptr));
5978
+ }, [&](){
5979
+ llvm::Value *idx = LLVM::CreateLoad (*builder, idx_ptr);
5980
+ llvm::Value *el_mask_value = LLVM::CreateLoad (*builder,
5981
+ llvm_utils->create_ptr_gep (el_mask, idx));
5982
+ llvm::Value *is_el_skip = builder->CreateICmpEQ (el_mask_value,
5983
+ llvm::ConstantInt::get (llvm::Type::getInt8Ty (context),
5984
+ llvm::APInt (8 , 3 )));
5985
+ llvm::Value *is_el_set = builder->CreateICmpNE (el_mask_value,
5986
+ llvm::ConstantInt::get (llvm::Type::getInt8Ty (context),
5987
+ llvm::APInt (8 , 0 )));
5988
+
5989
+ llvm::Value *el_exists = builder->CreateAnd (is_el_set,
5990
+ builder->CreateNot (is_el_skip));
5991
+
5992
+ llvm_utils->create_if_else (el_exists, [&]() {
5993
+ LLVM::CreateStore (*builder, llvm_utils->list_api ->read_item (el_list, idx,
5994
+ false , *module , LLVM::is_llvm_struct (el_type)), pvar);
5995
+
5996
+ for (size_t i=0 ; i<x.n_body ; i++) {
5997
+ this ->visit_stmt (*x.m_body [i]);
5998
+ }
5999
+ call_lcompilers_free_strings ();
6000
+ }, [=](){});
6001
+
6002
+ idx = builder->CreateAdd (idx,
6003
+ llvm::ConstantInt::get (context, llvm::APInt (32 , 1 )));
6004
+ LLVM::CreateStore (*builder, idx, idx_ptr);
6005
+ });
6006
+ } else {
6007
+ throw CodeGenError (" Only sets and dictionaries are supported with this loop for now." );
6008
+ }
6009
+ strings_to_be_deallocated.reserve (al, n);
6010
+ strings_to_be_deallocated.n = n;
6011
+ strings_to_be_deallocated.p = strings_to_be_deallocated_copy;
6012
+ }
6013
+
5831
6014
bool case_insensitive_string_compare (const std::string& str1, const std::string& str2) {
5832
6015
if (str1.size () != str2.size ()) {
5833
6016
return false ;
0 commit comments