@@ -554,13 +554,62 @@ def _add_to_adjacency_list(self, src_node_ptr, tgt_node_ptr):
554554 adj_cap_ptr = self .builder .gep (src_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 5 )])
555555
556556 current_count = self .builder .load (adj_count_ptr )
557- current_capacity = self .builder .load (adj_cap_ptr )
557+ tgt_node_name_ptr = self .builder .gep (tgt_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 1 )])
558+ tgt_node_name = self .builder .load (tgt_node_name_ptr )
559+ tgt_node_name_len_ptr = self .builder .gep (tgt_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 2 )])
560+ tgt_node_name_len = self .builder .load (tgt_node_name_len_ptr )
558561
559- needs_resize = self .builder .icmp_signed ('>=' , current_count , current_capacity )
562+ adj_list_void = self .builder .load (adj_list_ptr )
563+ adj_list_exists = self .builder .icmp_signed ('!=' , adj_list_void , ir .Constant (self .void_ptr , None ))
564+
565+ check_duplicates_block = self .builder .block .parent .append_basic_block (name = "check_duplicates" )
566+ proceed_add_block = self .builder .block .parent .append_basic_block (name = "proceed_add" )
567+ self .builder .cbranch (adj_list_exists , check_duplicates_block , proceed_add_block )
568+
569+ self .builder .position_at_end (check_duplicates_block )
570+ adj_list_typed = self .builder .bitcast (adj_list_void , self .node_type .as_pointer ().as_pointer ())
571+ dup_i = self .builder .alloca (self .int_type , name = "dup_check_i" )
572+ self .builder .store (ir .Constant (self .int_type , 0 ), dup_i )
573+
574+ dup_loop_block = self .builder .block .parent .append_basic_block (name = "dup_check_loop" )
575+ dup_check_block = self .builder .block .parent .append_basic_block (name = "dup_check_node" )
576+ dup_next_block = self .builder .block .parent .append_basic_block (name = "dup_next" )
577+ self .builder .branch (dup_loop_block )
578+
579+ self .builder .position_at_end (dup_loop_block )
580+ dup_i_val = self .builder .load (dup_i )
581+ current_count_loop = self .builder .load (adj_count_ptr )
582+ dup_loop_condition = self .builder .icmp_signed ('<' , dup_i_val , current_count_loop )
583+ self .builder .cbranch (dup_loop_condition , dup_check_block , proceed_add_block )
584+
585+ self .builder .position_at_end (dup_check_block )
586+ existing_node_ptr = self .builder .gep (adj_list_typed , [dup_i_val ])
587+ existing_node = self .builder .load (existing_node_ptr )
588+ existing_name_ptr = self .builder .gep (existing_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 1 )])
589+ existing_name = self .builder .load (existing_name_ptr )
590+ existing_name_len_ptr = self .builder .gep (existing_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 2 )])
591+ existing_name_len = self .builder .load (existing_name_len_ptr )
592+
593+ len_match = self .builder .icmp_signed ('==' , existing_name_len , tgt_node_name_len )
594+ dup_content_check_block = self .builder .block .parent .append_basic_block (name = "dup_content_check" )
595+ self .builder .cbranch (len_match , dup_content_check_block , dup_next_block )
596+
597+ self .builder .position_at_end (dup_content_check_block )
598+ names_match = self ._compare_strings (existing_name , tgt_node_name , tgt_node_name_len )
599+ self .builder .cbranch (names_match , proceed_add_block , dup_next_block )
600+
601+ self .builder .position_at_end (dup_next_block )
602+ next_dup_i = self .builder .add (dup_i_val , ir .Constant (self .int_type , 1 ))
603+ self .builder .store (next_dup_i , dup_i )
604+ self .builder .branch (dup_loop_block )
605+
606+ self .builder .position_at_end (proceed_add_block )
607+ current_capacity = self .builder .load (adj_cap_ptr )
608+ current_count_final = self .builder .load (adj_count_ptr )
609+ needs_resize = self .builder .icmp_signed ('>=' , current_count_final , current_capacity )
560610
561611 resize_adj_block = self .builder .block .parent .append_basic_block (name = "resize_adj" )
562612 add_adj_block = self .builder .block .parent .append_basic_block (name = "add_adj" )
563-
564613 self .builder .cbranch (needs_resize , resize_adj_block , add_adj_block )
565614
566615 self .builder .position_at_end (resize_adj_block )
@@ -569,24 +618,18 @@ def _add_to_adjacency_list(self, src_node_ptr, tgt_node_ptr):
569618 ir .Constant (self .int_type , 1 ),
570619 self .builder .mul (current_capacity , ir .Constant (self .int_type , 2 ))
571620 )
572-
573- target_data = self ._get_target_data ()
574- ptr_type = self .node_type .as_pointer ()
575621 ptr_size = ir .Constant (self .int64_type , self ._get_pointer_size ())
576-
577622 new_size_bytes = self .builder .mul (self .builder .zext (new_capacity , self .int64_type ), ptr_size )
578623 new_array_mem = self .builder .call (self .malloc_func , [new_size_bytes ])
579624
580625 old_adj_list = self .builder .load (adj_list_ptr )
581- copy_needed = self .builder .icmp_signed ('>' , current_count , ir .Constant (self .int_type , 0 ))
582-
626+ copy_needed = self .builder .icmp_signed ('>' , current_count_final , ir .Constant (self .int_type , 0 ))
583627 copy_block = self .builder .block .parent .append_basic_block (name = "copy_existing" )
584628 store_block = self .builder .block .parent .append_basic_block (name = "store_new_array" )
585-
586629 self .builder .cbranch (copy_needed , copy_block , store_block )
587630
588631 self .builder .position_at_end (copy_block )
589- old_size_bytes = self .builder .mul (self .builder .zext (current_count , self .int64_type ), ptr_size )
632+ old_size_bytes = self .builder .mul (self .builder .zext (current_count_final , self .int64_type ), ptr_size )
590633 self .builder .call (self .memcpy_func , [new_array_mem , old_adj_list , old_size_bytes ])
591634 self .builder .call (self .free_func , [old_adj_list ])
592635 self .builder .branch (store_block )
@@ -599,11 +642,8 @@ def _add_to_adjacency_list(self, src_node_ptr, tgt_node_ptr):
599642 self .builder .position_at_end (add_adj_block )
600643 adj_array = self .builder .load (adj_list_ptr )
601644 adj_array_typed = self .builder .bitcast (adj_array , self .node_type .as_pointer ().as_pointer ())
602-
603- current_count_final = self .builder .load (adj_count_ptr )
604645 target_addr = self .builder .gep (adj_array_typed , [current_count_final ])
605646 self .builder .store (tgt_node_ptr , target_addr )
606-
607647 new_count = self .builder .add (current_count_final , ir .Constant (self .int_type , 1 ))
608648 self .builder .store (new_count , adj_count_ptr )
609649
@@ -640,29 +680,32 @@ def _create_hash_insert(self):
640680 self .builder .ret (ir .Constant (self .int_type , 0 ))
641681
642682 def _create_is_adjacent (self ):
643- is_adj_type = ir .FunctionType (self .bool_type ,
644- [self .graph_type .as_pointer (), self .char_ptr , self .int_type , self .char_ptr , self .int_type ])
683+ is_adj_type = ir .FunctionType (
684+ self .bool_type ,
685+ [self .graph_type .as_pointer (), self .char_ptr , self .int_type ,
686+ self .char_ptr , self .int_type ]
687+ )
645688 self .is_adjacent = ir .Function (self .module , is_adj_type , name = "is_adjacent" )
646689
647- entry_block = self .is_adjacent .append_basic_block (name = "entry" )
648- node1_found_block = self .is_adjacent .append_basic_block (name = "node1_found" )
649- check_adjacency_block = self .is_adjacent .append_basic_block (name = "check_adjacency" )
650- search_adj_block = self .is_adjacent .append_basic_block (name = "search_adjacency" )
651- adj_loop_block = self .is_adjacent .append_basic_block (name = "adj_search_loop" )
652- adj_check_block = self .is_adjacent .append_basic_block (name = "adj_check_node" )
653- adj_next_block = self .is_adjacent .append_basic_block (name = "adj_next" )
654- adj_loop_end_block = self .is_adjacent .append_basic_block (name = "adj_loop_end" )
655- true_block = self .is_adjacent .append_basic_block (name = "return_true" )
656- false_block = self .is_adjacent .append_basic_block (name = "return_false" )
690+ entry_block = self .is_adjacent .append_basic_block ("entry" )
691+ node1_found_block = self .is_adjacent .append_basic_block ("node1_found" )
692+ check_adjacency_block = self .is_adjacent .append_basic_block ("check_adjacency" )
693+ search_adj_block = self .is_adjacent .append_basic_block ("search_adj" )
694+ adj_loop_block = self .is_adjacent .append_basic_block ("adj_loop" )
695+ adj_check_block = self .is_adjacent .append_basic_block ("adj_check" )
696+ adj_next_block = self .is_adjacent .append_basic_block ("adj_next" )
697+ content_check_block = self .is_adjacent .append_basic_block ("content_check" )
698+ adj_loop_end_block = self .is_adjacent .append_basic_block ("adj_loop_end" )
699+ true_block = self .is_adjacent .append_basic_block ("return_true" )
700+ false_block = self .is_adjacent .append_basic_block ("return_false" )
657701
658702 self .builder .position_at_end (entry_block )
659-
660703 graph_ptr , node1_name , node1_name_len , node2_name , node2_name_len = self .is_adjacent .args
661704
662705 node_map_ptr = self .builder .gep (graph_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 3 )])
663706 node_map = self .builder .load (node_map_ptr )
664- node1_void = self .builder .call (self .hash_lookup , [node_map , node1_name , node1_name_len ])
665707
708+ node1_void = self .builder .call (self .hash_lookup , [node_map , node1_name , node1_name_len ])
666709 node1_exists = self .builder .icmp_signed ('!=' , node1_void , ir .Constant (self .void_ptr , None ))
667710 self .builder .cbranch (node1_exists , node1_found_block , false_block )
668711
@@ -684,40 +727,50 @@ def _create_is_adjacent(self):
684727 adj_exists = self .builder .icmp_signed ('!=' , adj_list_void , ir .Constant (self .void_ptr , None ))
685728 count_positive = self .builder .icmp_signed ('>' , adj_count , ir .Constant (self .int_type , 0 ))
686729 should_search = self .builder .and_ (adj_exists , count_positive )
687-
688730 self .builder .cbranch (should_search , search_adj_block , false_block )
689731
690732 self .builder .position_at_end (search_adj_block )
691733 adj_array_typed = self .builder .bitcast (adj_list_void , self .node_type .as_pointer ().as_pointer ())
692- i = self .builder .alloca (self .int_type , name = "adj_search_i " )
734+ i = self .builder .alloca (self .int_type , name = "i " )
693735 self .builder .store (ir .Constant (self .int_type , 0 ), i )
694736 self .builder .branch (adj_loop_block )
695737
696738 self .builder .position_at_end (adj_loop_block )
697739 i_val = self .builder .load (i )
698- loop_condition = self .builder .icmp_signed ('<' , i_val , adj_count )
699- self .builder .cbranch (loop_condition , adj_check_block , adj_loop_end_block )
740+ loop_cond = self .builder .icmp_signed ('<' , i_val , adj_count )
741+ self .builder .cbranch (loop_cond , adj_check_block , adj_loop_end_block )
700742
701743 self .builder .position_at_end (adj_check_block )
702744 entry_ptr = self .builder .gep (adj_array_typed , [i_val ])
703745 adj_node = self .builder .load (entry_ptr )
704- nodes_match = self .builder .icmp_signed ('==' , adj_node , node2_ptr )
705- self .builder .cbranch (nodes_match , true_block , adj_next_block )
746+
747+ adj_node_name_ptr = self .builder .gep (adj_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 1 )])
748+ adj_node_name = self .builder .load (adj_node_name_ptr )
749+ adj_node_name_len_ptr = self .builder .gep (adj_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 2 )])
750+ adj_node_name_len = self .builder .load (adj_node_name_len_ptr )
751+
752+ len_match = self .builder .icmp_signed ('==' , adj_node_name_len , node2_name_len )
753+ self .builder .cbranch (len_match , content_check_block , adj_next_block )
754+
755+ self .builder .position_at_end (content_check_block )
756+ names_match = self ._compare_strings (adj_node_name , node2_name , node2_name_len )
757+ self .builder .cbranch (names_match , true_block , adj_next_block )
706758
707759 self .builder .position_at_end (adj_next_block )
708760 next_i = self .builder .add (i_val , ir .Constant (self .int_type , 1 ))
709761 self .builder .store (next_i , i )
710762 self .builder .branch (adj_loop_block )
711763
712- self .builder .position_at_end (true_block )
713- self .builder .ret (ir .Constant (self .bool_type , 1 ))
714-
715764 self .builder .position_at_end (adj_loop_end_block )
716765 self .builder .ret (ir .Constant (self .bool_type , 0 ))
717766
767+ self .builder .position_at_end (true_block )
768+ self .builder .ret (ir .Constant (self .bool_type , 1 ))
769+
718770 self .builder .position_at_end (false_block )
719771 self .builder .ret (ir .Constant (self .bool_type , 0 ))
720772
773+
721774 def _create_remove_vertex (self ):
722775
723776 remove_vertex_type = ir .FunctionType (self .int_type ,
@@ -964,6 +1017,11 @@ def _remove_from_all_adjacency_lists(self, graph_ptr, vertex_name, vertex_name_l
9641017 self .builder .position_at_end (done_adj_cleanup )
9651018
9661019 def _remove_from_adjacency_list (self , src_node_ptr , tgt_node_ptr ):
1020+ tgt_node_name_ptr = self .builder .gep (tgt_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 1 )])
1021+ tgt_node_name = self .builder .load (tgt_node_name_ptr )
1022+ tgt_node_name_len_ptr = self .builder .gep (tgt_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 2 )])
1023+ tgt_node_name_len = self .builder .load (tgt_node_name_len_ptr )
1024+
9671025 adj_list_ptr = self .builder .gep (src_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 3 )])
9681026 adj_count_ptr = self .builder .gep (src_node_ptr , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 4 )])
9691027
@@ -993,8 +1051,20 @@ def _remove_from_adjacency_list(self, src_node_ptr, tgt_node_ptr):
9931051 adj_entry_ptr = self .builder .gep (adj_list_typed , [i_val ])
9941052 adj_node = self .builder .load (adj_entry_ptr )
9951053
996- is_target = self .builder .icmp_signed ('==' , adj_node , tgt_node_ptr )
997- self .builder .cbranch (is_target , adj_found_block , adj_next_block )
1054+ adj_node_name_ptr = self .builder .gep (adj_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 1 )])
1055+ adj_node_name = self .builder .load (adj_node_name_ptr )
1056+ adj_node_name_len_ptr = self .builder .gep (adj_node , [ir .Constant (self .int_type , 0 ), ir .Constant (self .int_type , 2 )])
1057+ adj_node_name_len = self .builder .load (adj_node_name_len_ptr )
1058+
1059+ len_match = self .builder .icmp_signed ('==' , adj_node_name_len , tgt_node_name_len )
1060+
1061+ content_check_block = self .builder .block .parent .append_basic_block (name = "adj_content_check" )
1062+
1063+ self .builder .cbranch (len_match , content_check_block , adj_next_block )
1064+
1065+ self .builder .position_at_end (content_check_block )
1066+ names_match = self ._compare_strings (adj_node_name , tgt_node_name , tgt_node_name_len )
1067+ self .builder .cbranch (names_match , adj_found_block , adj_next_block )
9981068
9991069 self .builder .position_at_end (adj_found_block )
10001070 shift_i = self .builder .alloca (self .int_type , name = "adj_shift_i" )
0 commit comments