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