1 // Copyright © 2024 Igalia S.L. 2 // SPDX-License-Identifier: MIT 3 4 use isa_bindings::*; 5 use std::ffi::CString; 6 use std::mem::ManuallyDrop; 7 use std::ptr; 8 9 pub trait EtnaAsmResultExt { set_error(&mut self, error_message: &str)10 fn set_error(&mut self, error_message: &str); dealloc_error(&mut self)11 fn dealloc_error(&mut self); 12 append_instruction(&mut self, new_inst: etna_inst)13 fn append_instruction(&mut self, new_inst: etna_inst); dealloc_instructions(&mut self)14 fn dealloc_instructions(&mut self); 15 } 16 17 impl EtnaAsmResultExt for etna_asm_result { set_error(&mut self, error_message: &str)18 fn set_error(&mut self, error_message: &str) { 19 self.dealloc_error(); 20 21 self.error = CString::new(error_message) 22 .expect("CString::new failed") 23 .into_raw(); 24 } 25 dealloc_error(&mut self)26 fn dealloc_error(&mut self) { 27 if !self.error.is_null() { 28 // SAFETY: Previously obtained from CString::into_raw in set_error 29 let _ = unsafe { CString::from_raw(self.error) }; 30 self.error = ptr::null_mut(); 31 } 32 } 33 append_instruction(&mut self, new_inst: etna_inst)34 fn append_instruction(&mut self, new_inst: etna_inst) { 35 let mut instrs = if self.instr.is_null() { 36 Vec::new() 37 } else { 38 // SAFETY: These values come from a previous call to `append_instruction` where we turned a Vec into raw parts 39 unsafe { Vec::from_raw_parts(self.instr, self.num_instr, self.capacity_instr) } 40 }; 41 42 instrs.push(new_inst); 43 44 // This is Vec::into_raw_parts, which is still unstable 45 let mut md_vec = ManuallyDrop::new(instrs); 46 self.num_instr = md_vec.len(); 47 self.capacity_instr = md_vec.capacity(); 48 self.instr = md_vec.as_mut_ptr(); 49 } 50 dealloc_instructions(&mut self)51 fn dealloc_instructions(&mut self) { 52 if !self.instr.is_null() { 53 // SAFETY: These values come from a previous call to `append_instruction` where we turned a Vec into raw parts 54 let _ = unsafe { Vec::from_raw_parts(self.instr, self.num_instr, self.capacity_instr) }; 55 (self.instr, self.num_instr, self.capacity_instr) = (ptr::null_mut(), 0, 0); 56 } 57 } 58 } 59