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_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, // Should be the Int target
49            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        // Initialize the allocated space
64        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}