1*61046927SAndroid Build Coastguard Worker // Copyright © 2024 Igalia S.L.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker
4*61046927SAndroid Build Coastguard Worker use crate::parser::*;
5*61046927SAndroid Build Coastguard Worker use crate::util::EtnaAsmResultExt;
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker use isa_bindings::*;
8*61046927SAndroid Build Coastguard Worker use std::ffi::CStr;
9*61046927SAndroid Build Coastguard Worker use std::os::raw::c_char;
10*61046927SAndroid Build Coastguard Worker
11*61046927SAndroid Build Coastguard Worker /// Shared implementation to interact with the asm parser
12*61046927SAndroid Build Coastguard Worker ///
13*61046927SAndroid Build Coastguard Worker /// # Safety
14*61046927SAndroid Build Coastguard Worker ///
15*61046927SAndroid Build Coastguard Worker /// `c_str` must point to a valid nul-termintated string not longer than `isize::MAX` bytes.
16*61046927SAndroid Build Coastguard Worker /// See https://doc.rust-lang.org/std/ffi/struct.CStr.html#safety for further details.
isa_parse( c_str: *const c_char, dual_16_mode: bool, func: impl FnOnce(&str, bool, &mut etna_asm_result), ) -> *mut etna_asm_result17*61046927SAndroid Build Coastguard Worker unsafe fn isa_parse(
18*61046927SAndroid Build Coastguard Worker c_str: *const c_char,
19*61046927SAndroid Build Coastguard Worker dual_16_mode: bool,
20*61046927SAndroid Build Coastguard Worker func: impl FnOnce(&str, bool, &mut etna_asm_result),
21*61046927SAndroid Build Coastguard Worker ) -> *mut etna_asm_result {
22*61046927SAndroid Build Coastguard Worker let mut result = Box::new(etna_asm_result::default());
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker if c_str.is_null() {
25*61046927SAndroid Build Coastguard Worker result.set_error("str pointer is NULL");
26*61046927SAndroid Build Coastguard Worker return Box::into_raw(result);
27*61046927SAndroid Build Coastguard Worker }
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker // SAFETY: As per the safety section, the caller has to uphold these requirements
30*61046927SAndroid Build Coastguard Worker let c_str_safe = unsafe { CStr::from_ptr(c_str) };
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker if let Ok(str) = c_str_safe.to_str() {
33*61046927SAndroid Build Coastguard Worker func(str, dual_16_mode, &mut result);
34*61046927SAndroid Build Coastguard Worker } else {
35*61046927SAndroid Build Coastguard Worker result.set_error("Failed to convert CStr to &str");
36*61046927SAndroid Build Coastguard Worker result.success = false;
37*61046927SAndroid Build Coastguard Worker }
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker Box::into_raw(result)
40*61046927SAndroid Build Coastguard Worker }
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker /// # Safety
43*61046927SAndroid Build Coastguard Worker ///
44*61046927SAndroid Build Coastguard Worker /// `c_str` must point to a valid nul-termintated string not longer than `isize::MAX` bytes.
45*61046927SAndroid Build Coastguard Worker /// See https://doc.rust-lang.org/std/ffi/struct.CStr.html#safety for further details.
46*61046927SAndroid Build Coastguard Worker #[no_mangle]
isa_parse_str( c_str: *const c_char, dual_16_mode: bool, ) -> *mut etna_asm_result47*61046927SAndroid Build Coastguard Worker pub unsafe extern "C" fn isa_parse_str(
48*61046927SAndroid Build Coastguard Worker c_str: *const c_char,
49*61046927SAndroid Build Coastguard Worker dual_16_mode: bool,
50*61046927SAndroid Build Coastguard Worker ) -> *mut etna_asm_result {
51*61046927SAndroid Build Coastguard Worker // SAFETY: As per the safety section, the caller has to uphold these requirements
52*61046927SAndroid Build Coastguard Worker unsafe { isa_parse(c_str, dual_16_mode, asm_process_str) }
53*61046927SAndroid Build Coastguard Worker }
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker /// # Safety
56*61046927SAndroid Build Coastguard Worker ///
57*61046927SAndroid Build Coastguard Worker /// `c_filepath` must point to a valid nul-termintated string not longer than `isize::MAX` bytes.
58*61046927SAndroid Build Coastguard Worker /// See https://doc.rust-lang.org/std/ffi/struct.CStr.html#safety for further details.
59*61046927SAndroid Build Coastguard Worker #[no_mangle]
isa_parse_file( c_filepath: *const c_char, dual_16_mode: bool, ) -> *mut etna_asm_result60*61046927SAndroid Build Coastguard Worker pub unsafe extern "C" fn isa_parse_file(
61*61046927SAndroid Build Coastguard Worker c_filepath: *const c_char,
62*61046927SAndroid Build Coastguard Worker dual_16_mode: bool,
63*61046927SAndroid Build Coastguard Worker ) -> *mut etna_asm_result {
64*61046927SAndroid Build Coastguard Worker // SAFETY: As per the safety section, the caller has to uphold these requirements
65*61046927SAndroid Build Coastguard Worker unsafe { isa_parse(c_filepath, dual_16_mode, asm_process_file) }
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker /// # Safety
69*61046927SAndroid Build Coastguard Worker ///
70*61046927SAndroid Build Coastguard Worker /// `result` must have previously been obtained from `isa_parse_str` or `isa_parse_file`.
71*61046927SAndroid Build Coastguard Worker #[no_mangle]
isa_asm_result_destroy(result: *mut etna_asm_result)72*61046927SAndroid Build Coastguard Worker pub unsafe extern "C" fn isa_asm_result_destroy(result: *mut etna_asm_result) {
73*61046927SAndroid Build Coastguard Worker // SAFETY: As per the safety section, the caller has to uphold these requirements
74*61046927SAndroid Build Coastguard Worker let mut r = unsafe { Box::from_raw(result) };
75*61046927SAndroid Build Coastguard Worker r.dealloc_instructions();
76*61046927SAndroid Build Coastguard Worker r.dealloc_error();
77*61046927SAndroid Build Coastguard Worker }
78