1use crate::code_bld::CodeBuilder;
6use crate::ctx::Context;
7use source_map_node::Node;
8use swamp_semantic::Expression;
9use swamp_types::TypeRef;
10use swamp_vm_types::types::{Destination, TypedRegister, VmType, pointer_type};
11use swamp_vm_types::{AggregateMemoryLocation, MemoryLocation, MemoryOffset, PointerLocation};
12
13impl CodeBuilder<'_> {
14 pub fn sparse_subscript_helper(
15 &mut self,
16 vec_header_location: &Destination,
17 analyzed_element_type: &TypeRef,
18 int_expr: &Expression,
19 ctx: &Context,
20 ) -> Destination {
21 let pointer_location = self.sparse_subscript_helper_helper(
22 vec_header_location,
23 analyzed_element_type,
24 int_expr,
25 ctx,
26 );
27 Destination::Memory(pointer_location.memory_location())
28 }
29
30 pub(crate) fn emit_sparse_add(
31 &mut self,
32 target: &TypedRegister,
33 self_addr: &PointerLocation,
34 element_expr: &Expression,
35 node: &Node,
36 ctx: &Context,
37 ) {
38 let element_gen_type = self.state.layout_cache.layout(&element_expr.ty);
39
40 let temp_element_ptr = self.temp_registers.allocate(
41 VmType::new_contained_in_register(pointer_type()),
42 "pointer to new element",
43 );
44
45 self.builder.add_sparse_add_give_entry_address(
46 temp_element_ptr.register(),
47 target, self_addr,
49 element_gen_type.total_size,
50 node,
51 "add space and get pointer to new element",
52 );
53
54 let location = AggregateMemoryLocation {
55 location: MemoryLocation {
56 base_ptr_reg: temp_element_ptr.register,
57 offset: MemoryOffset(0),
58 ty: VmType::new_unknown_placement(element_gen_type.clone()),
59 },
60 };
61
62 if element_gen_type.is_aggregate() {
64 self.emit_initialize_memory_for_any_type(
65 &location.location,
66 node,
67 "initialize sparse set element memory",
68 );
69 }
70
71 self.emit_expression_into_target_memory(
72 &location.location,
73 element_expr,
74 "sparse add, put expression into entry memory location",
75 ctx,
76 );
77 }
78
79 pub(crate) fn emit_sparse_remove(
80 &mut self,
81 self_addr: &PointerLocation,
82 element_expr: &Expression,
83 node: &Node,
84 ctx: &Context,
85 ) {
86 let int_reg = self.emit_scalar_rvalue(element_expr, ctx);
87 self.builder
88 .add_sparse_remove(self_addr, &int_reg, node, "");
89 }
90
91 pub(crate) fn emit_sparse_is_alive(
92 &mut self,
93 dest_bool_reg: &TypedRegister,
94 self_addr: &PointerLocation,
95 element_expr: &Expression,
96 node: &Node,
97 ctx: &Context,
98 ) {
99 let int_reg = self.emit_scalar_rvalue(element_expr, ctx);
100 self.builder
101 .add_sparse_is_alive(dest_bool_reg, self_addr, &int_reg, node, "");
102 }
103 pub fn sparse_subscript_helper_helper(
104 &mut self,
105 sparse_header_location: &Destination,
106 analyzed_element_type: &TypeRef,
107 int_expr: &Expression,
108 ctx: &Context,
109 ) -> PointerLocation {
110 let gen_element_type = self.state.layout_cache.layout(analyzed_element_type);
111 let index_int_reg = self.emit_scalar_rvalue(int_expr, ctx);
112 let node = &int_expr.node;
113
114 let sparse_header_ptr_reg = self.emit_compute_effective_address_to_register(
115 sparse_header_location,
116 node,
117 "get sparse header absolute pointer",
118 );
119
120 let absolute_pointer_to_element = self.temp_registers.allocate(
121 VmType::new_contained_in_register(gen_element_type.clone()),
122 "temporary target",
123 );
124
125 let pointer_location = PointerLocation {
126 ptr_reg: sparse_header_ptr_reg,
127 };
128
129 self.builder.add_sparse_get_entry_addr(
130 absolute_pointer_to_element.register(),
131 &pointer_location,
132 &index_int_reg,
133 gen_element_type.total_size,
134 node,
135 "lookup sparse subscript",
136 );
137
138 PointerLocation {
139 ptr_reg: absolute_pointer_to_element.register,
140 }
141 }
142}