swamp_code_gen/
sparse.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use 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, // Should be the Int target
48            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        // Initialize the allocated space
63        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}