1use std::fmt;
5
6use cranelift_codegen::Context;
7use cranelift_codegen::ir::{AbiParam, InstBuilder, Signature, Type, types};
8use cranelift_codegen::isa::OwnedTargetIsa;
9use cranelift_codegen::settings::{self, Configurable};
10use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
11use cranelift_module::{DataDescription, DataId, FuncId, Linkage, Module};
12use nifty_rt::{Slice, symbols};
13
14use crate::CodegenError;
15
16#[derive(Clone, Copy, Debug)]
18pub enum Target {
19 Data(DataId),
20 Function(FuncId),
21}
22
23#[derive(Debug)]
25pub struct Blob {
26 bytes: Vec<u8>,
27 pointers: Vec<(usize, Target)>,
28}
29
30impl Blob {
31 #[must_use]
33 pub fn zeroed(size: usize) -> Self {
34 Self {
35 bytes: vec![0; size],
36 pointers: Vec::new(),
37 }
38 }
39
40 #[must_use]
41 pub fn bytes(bytes: &[u8]) -> Self {
42 Self {
43 bytes: bytes.to_vec(),
44 pointers: Vec::new(),
45 }
46 }
47
48 pub fn put_u8(&mut self, offset: usize, value: u8) {
49 self.put(offset, &[value]);
50 }
51
52 pub fn put_u32(&mut self, offset: usize, value: u32) {
53 self.put(offset, &value.to_ne_bytes());
54 }
55
56 pub fn put_i64(&mut self, offset: usize, value: i64) {
57 self.put(offset, &value.to_ne_bytes());
58 }
59
60 pub fn put_f32(&mut self, offset: usize, value: f32) {
61 self.put(offset, &value.to_ne_bytes());
62 }
63
64 pub fn put_usize(&mut self, offset: usize, value: usize) {
65 self.put(offset, &value.to_ne_bytes());
66 }
67
68 pub fn put_pointer(&mut self, offset: usize, target: Target) {
69 self.pointers.push((offset, target));
70 }
71
72 pub fn put_slice(&mut self, offset: usize, items: Option<Target>, len: usize) {
75 if let Some(items) = items {
76 self.put_pointer(offset + Slice::<u8>::PTR_OFFSET, items);
77 }
78 self.put_usize(offset + Slice::<u8>::LEN_OFFSET, len);
79 }
80
81 fn put(&mut self, offset: usize, value: &[u8]) {
84 self.bytes[offset..offset + value.len()].copy_from_slice(value);
85 }
86}
87
88pub fn host_isa(position_independent: bool) -> Result<OwnedTargetIsa, CodegenError> {
95 let mut flags = settings::builder();
96 flags.set(
97 "is_pic",
98 if position_independent {
99 "true"
100 } else {
101 "false"
102 },
103 )?;
104 flags.set("opt_level", "speed")?;
105 Ok(cranelift_native::builder()
106 .map_err(CodegenError::new)?
107 .finish(settings::Flags::new(flags))?)
108}
109
110pub struct Emitter<M: Module> {
112 module: M,
113 context: Context,
114 builder_context: FunctionBuilderContext,
115}
116
117impl<M: Module> Emitter<M> {
118 pub fn new(module: M) -> Self {
119 Self {
120 module,
121 context: Context::new(),
122 builder_context: FunctionBuilderContext::new(),
123 }
124 }
125
126 pub fn into_module(self) -> M {
127 self.module
128 }
129
130 pub(crate) fn module_mut(&mut self) -> &mut M {
131 &mut self.module
132 }
133
134 #[must_use]
135 pub fn pointer_type(&self) -> Type {
136 self.module.target_config().pointer_type()
137 }
138
139 #[must_use]
141 pub fn signature(&self, params: &[Type], returns: &[Type]) -> Signature {
142 let mut signature = self.module.make_signature();
143 signature
144 .params
145 .extend(params.iter().copied().map(AbiParam::new));
146 signature
147 .returns
148 .extend(returns.iter().copied().map(AbiParam::new));
149 signature
150 }
151
152 pub fn import_function(
157 &mut self,
158 name: &str,
159 signature: &Signature,
160 ) -> Result<FuncId, CodegenError> {
161 Ok(self
162 .module
163 .declare_function(name, Linkage::Import, signature)?)
164 }
165
166 pub fn import_data(&mut self, name: &str) -> Result<DataId, CodegenError> {
171 Ok(self
172 .module
173 .declare_data(name, Linkage::Import, false, false)?)
174 }
175
176 pub fn declare_data(&mut self) -> Result<DataId, CodegenError> {
182 Ok(self.module.declare_anonymous_data(false, false)?)
183 }
184
185 pub fn define_data(&mut self, id: DataId, blob: Blob) -> Result<(), CodegenError> {
188 let mut description = DataDescription::new();
189 description.set_align(8);
190 for (offset, target) in &blob.pointers {
191 let offset = u32::try_from(*offset).map_err(|_| {
192 CodegenError::new(format!("data is too large to point at offset {offset}"))
193 })?;
194 match *target {
195 Target::Data(data) => {
196 let global = self.module.declare_data_in_data(data, &mut description);
197 description.write_data_addr(offset, global, 0);
198 }
199 Target::Function(function) => {
200 let function = self.module.declare_func_in_data(function, &mut description);
201 description.write_function_addr(offset, function);
202 }
203 }
204 }
205 description.define(blob.bytes.into_boxed_slice());
206 self.module.define_data(id, &description)?;
207 Ok(())
208 }
209
210 pub fn data(&mut self, blob: Blob) -> Result<DataId, CodegenError> {
215 let id = self.declare_data()?;
216 self.define_data(id, blob)?;
217 Ok(id)
218 }
219
220 pub fn declare_function(&mut self, signature: &Signature) -> Result<FuncId, CodegenError> {
226 Ok(self.module.declare_anonymous_function(signature)?)
227 }
228
229 pub fn define_function(
236 &mut self,
237 id: FuncId,
238 signature: Signature,
239 build: impl FnOnce(&mut FunctionBuilder<'_>, &mut M) -> Result<(), CodegenError>,
240 ) -> Result<(), CodegenError> {
241 self.context.func.signature = signature;
242 let mut builder = FunctionBuilder::new(&mut self.context.func, &mut self.builder_context);
243 let entry = builder.create_block();
244 builder.append_block_params_for_function_params(entry);
245 builder.switch_to_block(entry);
246 let body = build(&mut builder, &mut self.module);
247 builder.seal_all_blocks();
248 builder.finalize();
249 let defined = body.and_then(|()| Ok(self.module.define_function(id, &mut self.context)?));
250 self.module.clear_context(&mut self.context);
251 defined
252 }
253
254 pub fn function(
259 &mut self,
260 signature: Signature,
261 build: impl FnOnce(&mut FunctionBuilder<'_>, &mut M) -> Result<(), CodegenError>,
262 ) -> Result<FuncId, CodegenError> {
263 let id = self.declare_function(&signature)?;
264 self.define_function(id, signature, build)?;
265 Ok(id)
266 }
267
268 pub fn define_main(&mut self, program: DataId) -> Result<(), CodegenError> {
274 let pointer = self.pointer_type();
275 let run =
276 self.import_function(symbols::MAIN, &self.signature(&[pointer], &[types::I32]))?;
277 let signature = self.signature(&[types::I32, pointer], &[types::I32]);
278 let main = self
279 .module
280 .declare_function("main", Linkage::Export, &signature)?;
281 self.define_function(main, signature, |builder, module| {
282 let global = module.declare_data_in_func(program, builder.func);
283 let program = builder.ins().global_value(pointer, global);
284 let run = module.declare_func_in_func(run, builder.func);
285 let call = builder.ins().call(run, &[program]);
286 let status = builder.inst_results(call).to_vec();
287 builder.ins().return_(&status);
288 Ok(())
289 })
290 }
291}
292
293impl<M: Module> fmt::Debug for Emitter<M> {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 f.debug_struct("Emitter").finish_non_exhaustive()
296 }
297}