swamp_code_gen/
vec.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::{Place, VmType};
11use swamp_vm_types::{MemoryLocation, PointerLocation};
12
13impl CodeBuilder<'_> {
14    pub(crate) fn grid_subscript_helper(
15        &mut self,
16        grid_header_location: &Place,
17        analyzed_element_type: &TypeRef,
18        x_expr: &Expression,
19        y_expr: &Expression,
20        ctx: &Context,
21    ) -> Place {
22        let pointer_location = self.grid_subscript_helper_helper(
23            grid_header_location,
24            analyzed_element_type,
25            x_expr,
26            y_expr,
27            ctx,
28        );
29        // Fix: Dereference the pointer like map subscript does, instead of returning pointer to pointer
30        Place::Memory(MemoryLocation::new_copy_over_whole_type_with_zero_offset(
31            pointer_location.ptr_reg,
32        ))
33    }
34
35    /// Emits Swamp VM opcodes to calculate the memory address of an element within an array.
36    ///
37    /// The function targets a vec-like structured with a `u16` length prefix followed by
38    /// contiguous element data in memory. It uses the provided `int_expression` as the
39    /// index for the lookup. Calls the `subscript_helper_from_location_to_location` to
40    /// emit the bounds checking.
41    pub fn vec_subscript_helper(
42        &mut self,
43        vec_header_location: &Place,
44        analyzed_element_type: &TypeRef,
45        int_expr: &Expression,
46        ctx: &Context,
47    ) -> Place {
48        let pointer_location = self.vec_subscript_helper_helper(
49            vec_header_location,
50            analyzed_element_type,
51            int_expr,
52            ctx,
53        );
54        Place::Memory(pointer_location.memory_location())
55    }
56
57    pub fn emit_vec_subscript_range_helper(
58        &mut self,
59        destination_memory_location: &Place,
60        source_memory_location: &Place,
61        range_expr: &Expression,
62        node: &Node,
63        comment: &str,
64        ctx: &Context,
65    ) {
66        let destination_pointer = self.emit_compute_effective_address_to_register(
67            destination_memory_location,
68            node,
69            "get the destination vec",
70        );
71        let destination_pointer_loc = PointerLocation::new(destination_pointer);
72        let source_pointer = self.emit_compute_effective_address_to_register(
73            source_memory_location,
74            node,
75            "get vector source address to take range from",
76        );
77        let source_pointer_loc = PointerLocation::new(source_pointer);
78
79        let range_header_register = self.emit_scalar_rvalue(range_expr, ctx);
80
81        self.builder.add_vec_copy_range(
82            &destination_pointer_loc,
83            &source_pointer_loc,
84            &range_header_register,
85            node,
86            "copy range, but leave the capacity on the destination",
87        );
88    }
89
90    pub fn grid_subscript_helper_helper(
91        &mut self,
92        grid_header_location: &Place,
93        analyzed_element_type: &TypeRef,
94        x_int_expr: &Expression,
95        y_int_expr: &Expression,
96        ctx: &Context,
97    ) -> PointerLocation {
98        let gen_element_type = self.state.layout_cache.layout(analyzed_element_type);
99        let x_int_reg = self.emit_scalar_rvalue(x_int_expr, ctx);
100        let y_int_reg = self.emit_scalar_rvalue(y_int_expr, ctx);
101        let node = &x_int_expr.node;
102
103        let grid_header_ptr_reg = self.emit_compute_effective_address_to_register(
104            grid_header_location,
105            node,
106            "get grid header absolute pointer",
107        );
108
109        let grid_header_ptr_location = PointerLocation {
110            ptr_reg: grid_header_ptr_reg,
111        };
112
113        let absolute_pointer_to_element = self.temp_registers.allocate(
114            VmType::new_contained_in_register(gen_element_type.clone()),
115            "temporary target",
116        );
117        self.builder.add_grid_get_entry_addr(
118            absolute_pointer_to_element.register(),
119            &grid_header_ptr_location,
120            &x_int_reg,
121            &y_int_reg,
122            gen_element_type.total_size,
123            node,
124            "lookup grid subscript",
125        );
126
127        PointerLocation {
128            ptr_reg: absolute_pointer_to_element.register,
129        }
130    }
131
132    pub fn vec_subscript_helper_helper(
133        &mut self,
134        vec_header_location: &Place,
135        analyzed_element_type: &TypeRef,
136        int_expr: &Expression,
137        ctx: &Context,
138    ) -> PointerLocation {
139        let gen_element_type = self.state.layout_cache.layout(analyzed_element_type);
140        let index_int_reg = self.emit_scalar_rvalue(int_expr, ctx);
141        let node = &int_expr.node;
142
143        let vec_header_ptr_reg = self.emit_compute_effective_address_to_register(
144            vec_header_location,
145            node,
146            "get vec header absolute pointer",
147        );
148
149        let absolute_pointer_to_element = self.temp_registers.allocate(
150            VmType::new_contained_in_register(gen_element_type.clone()),
151            "temporary target",
152        );
153        self.builder.add_vec_subscript(
154            absolute_pointer_to_element.register(),
155            &vec_header_ptr_reg,
156            &index_int_reg,
157            node,
158            "lookup veclike subscript",
159        );
160
161        PointerLocation {
162            ptr_reg: absolute_pointer_to_element.register,
163        }
164    }
165}