1use crate::context::{FunctionId, GlobalId, TypeId};
4use crate::function::Function;
5use crate::value::GlobalVariable;
6use std::collections::HashMap;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct DebugLocation {
11 pub line: u32,
13 pub column: u32,
15}
16
17pub struct Module {
19 pub name: String,
21 pub source_filename: Option<String>,
23 pub target_triple: Option<String>,
25 pub data_layout: Option<String>,
27 pub globals: Vec<GlobalVariable>,
29 pub functions: Vec<Function>,
31 pub function_names: HashMap<String, FunctionId>,
33 pub global_names: HashMap<String, GlobalId>,
35 pub named_types: Vec<(String, TypeId)>,
37 pub debug_locations: HashMap<u32, DebugLocation>,
39 pub metadata_nodes: HashMap<u32, String>,
41 pub named_metadata: Vec<(String, String)>,
43}
44
45impl Module {
46 pub fn new(name: impl Into<String>) -> Self {
48 Module {
49 name: name.into(),
50 source_filename: None,
51 target_triple: None,
52 data_layout: None,
53 globals: Vec::new(),
54 functions: Vec::new(),
55 function_names: HashMap::new(),
56 global_names: HashMap::new(),
57 named_types: Vec::new(),
58 debug_locations: HashMap::new(),
59 metadata_nodes: HashMap::new(),
60 named_metadata: Vec::new(),
61 }
62 }
63
64 pub fn add_function(&mut self, f: Function) -> FunctionId {
70 let id = FunctionId(self.functions.len() as u32);
71 self.function_names.insert(f.name.clone(), id);
72 self.functions.push(f);
73 id
74 }
75
76 pub fn function(&self, id: FunctionId) -> &Function {
78 &self.functions[id.0 as usize]
79 }
80
81 pub fn function_mut(&mut self, id: FunctionId) -> &mut Function {
83 &mut self.functions[id.0 as usize]
84 }
85
86 pub fn get_function(&self, name: &str) -> Option<(FunctionId, &Function)> {
88 self.function_names
89 .get(name)
90 .map(|&id| (id, &self.functions[id.0 as usize]))
91 }
92
93 pub fn get_function_id(&self, name: &str) -> Option<FunctionId> {
95 self.function_names.get(name).copied()
96 }
97
98 pub fn num_functions(&self) -> usize {
100 self.functions.len()
101 }
102
103 pub fn add_global(&mut self, gv: GlobalVariable) -> GlobalId {
109 let id = GlobalId(self.globals.len() as u32);
110 self.global_names.insert(gv.name.clone(), id);
111 self.globals.push(gv);
112 id
113 }
114
115 pub fn global(&self, id: GlobalId) -> &GlobalVariable {
117 &self.globals[id.0 as usize]
118 }
119
120 pub fn global_mut(&mut self, id: GlobalId) -> &mut GlobalVariable {
122 &mut self.globals[id.0 as usize]
123 }
124
125 pub fn get_global(&self, name: &str) -> Option<(GlobalId, &GlobalVariable)> {
127 self.global_names
128 .get(name)
129 .map(|&id| (id, &self.globals[id.0 as usize]))
130 }
131
132 pub fn get_global_id(&self, name: &str) -> Option<GlobalId> {
134 self.global_names.get(name).copied()
135 }
136
137 pub fn num_globals(&self) -> usize {
139 self.globals.len()
140 }
141
142 pub fn register_named_type(&mut self, name: impl Into<String>, ty: TypeId) {
149 let name = name.into();
150 if !self.named_types.iter().any(|(n, _)| n == &name) {
151 self.named_types.push((name, ty));
152 }
153 }
154
155 pub fn set_debug_location(&mut self, id: u32, loc: DebugLocation) {
157 self.debug_locations.insert(id, loc);
158 }
159
160 pub fn debug_location(&self, id: u32) -> Option<DebugLocation> {
162 self.debug_locations.get(&id).copied()
163 }
164
165 pub fn set_metadata_node(&mut self, id: u32, value: impl Into<String>) {
167 self.metadata_nodes.insert(id, value.into());
168 }
169
170 pub fn metadata_node(&self, id: u32) -> Option<&str> {
172 self.metadata_nodes.get(&id).map(String::as_str)
173 }
174
175 pub fn set_named_metadata(&mut self, name: impl Into<String>, value: impl Into<String>) {
177 let name = name.into();
178 let value = value.into();
179 if let Some((_, v)) = self.named_metadata.iter_mut().find(|(n, _)| *n == name) {
180 *v = value;
181 } else {
182 self.named_metadata.push((name, value));
183 }
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::context::Context;
191 use crate::value::{GlobalVariable, Linkage};
192
193 #[test]
194 fn module_functions() {
195 let mut ctx = Context::new();
196 let fn_ty = ctx.mk_fn_type(ctx.i32_ty, vec![], false);
197 let f = Function::new("foo", fn_ty, vec![], Linkage::External);
198 let mut m = Module::new("test");
199 let id = m.add_function(f);
200 assert_eq!(id, FunctionId(0));
201 assert_eq!(m.function(id).name, "foo");
202 assert_eq!(m.get_function_id("foo"), Some(FunctionId(0)));
203 }
204
205 #[test]
206 fn module_globals() {
207 let ctx = Context::new();
208 let gv = GlobalVariable {
209 name: "x".to_string(),
210 ty: ctx.i32_ty,
211 initializer: None,
212 is_constant: false,
213 linkage: Linkage::External,
214 };
215 let mut m = Module::new("test");
216 let id = m.add_global(gv);
217 assert_eq!(id, GlobalId(0));
218 assert_eq!(m.global(id).name, "x");
219 }
220}