1#![allow(clippy::arc_with_non_send_sync)]
9
10use std::{
11 ffi::{CStr, CString},
12 sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
13};
14
15use xlsynth_sys::{
16 CIrAnalysis, CIrBValue, CIrBits, CIrFunction, CIrFunctionJit, CIrFunctionType, CIrIntervalSet,
17 CIrPackage, CIrType, CIrValue, CScheduleAndCodegenResult, CTraceMessage, XlsFormatPreference,
18};
19
20use crate::{
21 ir_package::{IrPackagePtr, IrType, ScheduleAndCodegenResult},
22 IrBits, IrFunction, IrValue, XlsynthError,
23};
24
25pub(crate) struct IrFnBuilderPtr {
28 pub(crate) ptr: *mut xlsynth_sys::CIrFunctionBuilder,
29}
30
31impl Drop for IrFnBuilderPtr {
32 fn drop(&mut self) {
33 if !self.ptr.is_null() {
34 unsafe {
35 xlsynth_sys::xls_function_builder_free(self.ptr);
36 }
37 }
38 }
39}
40
41pub(crate) struct BValuePtr {
44 pub(crate) ptr: *mut CIrBValue,
45}
46
47impl Drop for BValuePtr {
48 fn drop(&mut self) {
49 unsafe {
50 xlsynth_sys::xls_bvalue_free(self.ptr);
51 }
52 }
53}
54
55macro_rules! xls_ffi_call {
70 ($func:path $(, $arg:expr )* ; $out:ident) => {{
71 unsafe {
72 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
73 let success = $func($($arg,)* &mut error_out, &mut $out);
74 if success {
75 Ok(())
76 } else {
77 Err(XlsynthError(c_str_to_rust(error_out)))
78 }
79 }
80 }};
81}
82
83macro_rules! xls_ffi_call_noreturn {
85 ($func:path $(, $arg:expr )*) => {{
86 unsafe {
87 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
88 let success = $func($($arg,)* &mut error_out);
89 if success {
90 Ok(())
91 } else {
92 Err(XlsynthError(c_str_to_rust(error_out)))
93 }
94 }
95 }};
96}
97
98pub(crate) fn xls_package_to_string(p: *const CIrPackage) -> Result<String, XlsynthError> {
99 unsafe {
100 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
101 let success = xlsynth_sys::xls_package_to_string(p, &mut c_str_out);
102 if success {
103 Ok(c_str_to_rust(c_str_out))
104 } else {
105 Err(XlsynthError(
106 "Failed to convert XLS package to string via C API".to_string(),
107 ))
108 }
109 }
110}
111
112pub(crate) fn xls_function_to_string(f: *const CIrFunction) -> Result<String, XlsynthError> {
113 unsafe {
114 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
115 let success = xlsynth_sys::xls_function_to_string(f, &mut c_str_out);
116 if success {
117 Ok(c_str_to_rust(c_str_out))
118 } else {
119 Err(XlsynthError(
120 "Failed to convert XLS function to string via C API".to_string(),
121 ))
122 }
123 }
124}
125
126pub(crate) unsafe fn c_str_to_rust_no_dealloc(xls_c_str: *mut std::os::raw::c_char) -> String {
127 if xls_c_str.is_null() {
128 String::new()
129 } else {
130 let c_str: &CStr = CStr::from_ptr(xls_c_str);
131 String::from_utf8_lossy(c_str.to_bytes()).to_string()
132 }
133}
134
135pub(crate) unsafe fn c_str_to_rust(xls_c_str: *mut std::os::raw::c_char) -> String {
138 let result = c_str_to_rust_no_dealloc(xls_c_str);
139
140 xlsynth_sys::xls_c_str_free(xls_c_str);
145 result
146}
147
148fn cstring_and_ptr(name: &str) -> (CString, *const std::os::raw::c_char) {
151 let cstr = CString::new(name).unwrap();
152 let ptr = cstr.as_ptr();
153 (cstr, ptr)
154}
155
156fn optional_cstring_and_ptr(name: Option<&str>) -> (Option<CString>, *const std::os::raw::c_char) {
159 if let Some(s) = name {
160 let cstr = CString::new(s).unwrap();
161 let ptr = cstr.as_ptr();
162 (Some(cstr), ptr)
163 } else {
164 (None, std::ptr::null())
165 }
166}
167
168pub(crate) fn xls_value_free(p: *mut CIrValue) {
169 unsafe { xlsynth_sys::xls_value_free(p) }
170}
171
172pub(crate) fn xls_package_free(p: *mut CIrPackage) {
173 unsafe { xlsynth_sys::xls_package_free(p) }
174}
175
176pub(crate) fn xls_value_to_string(p: *mut CIrValue) -> Result<String, XlsynthError> {
177 unsafe {
178 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
179 let success = xlsynth_sys::xls_value_to_string(p, &mut c_str_out);
180 if success {
181 Ok(c_str_to_rust(c_str_out))
182 } else {
183 Err(XlsynthError(
184 "Failed to convert XLS value to string via C API".to_string(),
185 ))
186 }
187 }
188}
189
190pub(crate) fn xls_value_get_element(
191 p: *mut CIrValue,
192 index: usize,
193) -> Result<IrValue, XlsynthError> {
194 let mut element_out: *mut CIrValue = std::ptr::null_mut();
195 xls_ffi_call!(xlsynth_sys::xls_value_get_element, p, index; element_out)?;
196 Ok(IrValue { ptr: element_out })
197}
198
199pub(crate) fn xls_value_get_element_count(p: *const CIrValue) -> Result<usize, XlsynthError> {
200 let mut count: i64 = 0;
201 xls_ffi_call!(xlsynth_sys::xls_value_get_element_count, p; count)?;
202 Ok(count as usize)
203}
204
205pub(crate) fn xls_value_make_ubits(value: u64, bit_count: usize) -> Result<IrValue, XlsynthError> {
206 let mut result: *mut CIrValue = std::ptr::null_mut();
207 xls_ffi_call!(xlsynth_sys::xls_value_make_ubits, bit_count as i64, value; result)?;
208 Ok(IrValue { ptr: result })
209}
210
211pub(crate) fn xls_value_make_sbits(value: i64, bit_count: usize) -> Result<IrValue, XlsynthError> {
212 let mut result: *mut CIrValue = std::ptr::null_mut();
213 xls_ffi_call!(xlsynth_sys::xls_value_make_sbits, bit_count as i64, value; result)?;
214 Ok(IrValue { ptr: result })
215}
216
217pub(crate) fn xls_value_make_token() -> IrValue {
218 let result = unsafe { xlsynth_sys::xls_value_make_token() };
219 assert!(!result.is_null());
220 IrValue { ptr: result }
221}
222
223pub(crate) fn xls_value_make_tuple(elements: &[IrValue]) -> IrValue {
224 unsafe {
225 let elements_ptrs: Vec<*const CIrValue> =
226 elements.iter().map(|v| v.ptr as *const CIrValue).collect();
227 let result = xlsynth_sys::xls_value_make_tuple(elements_ptrs.len(), elements_ptrs.as_ptr());
228 assert!(!result.is_null());
229 IrValue { ptr: result }
230 }
231}
232
233pub(crate) fn xls_value_make_array(elements: &[IrValue]) -> Result<IrValue, XlsynthError> {
234 let elements_ptrs: Vec<*const CIrValue> =
235 elements.iter().map(|v| v.ptr as *const CIrValue).collect();
236 let mut result: *mut CIrValue = std::ptr::null_mut();
237 xls_ffi_call!(xlsynth_sys::xls_value_make_array, elements_ptrs.len(), elements_ptrs.as_ptr(); result)?;
238 Ok(IrValue { ptr: result })
239}
240
241pub(crate) fn xls_bits_to_debug_str(p: *const CIrBits) -> String {
242 unsafe {
243 let c_str_out = xlsynth_sys::xls_bits_to_debug_string(p);
244 c_str_to_rust(c_str_out)
245 }
246}
247
248pub(crate) fn xls_bits_make_ubits(bit_count: usize, value: u64) -> Result<IrBits, XlsynthError> {
249 let mut result: *mut CIrBits = std::ptr::null_mut();
250 xls_ffi_call!(xlsynth_sys::xls_bits_make_ubits, bit_count as i64, value; result)?;
251 Ok(IrBits { ptr: result })
252}
253
254pub(crate) fn xls_bits_make_sbits(bit_count: usize, value: i64) -> Result<IrBits, XlsynthError> {
255 let mut result: *mut CIrBits = std::ptr::null_mut();
256 xls_ffi_call!(xlsynth_sys::xls_bits_make_sbits, bit_count as i64, value; result)?;
257 Ok(IrBits { ptr: result })
258}
259
260pub(crate) fn xls_value_get_bits(p: *const CIrValue) -> Result<IrBits, XlsynthError> {
261 let mut result: *mut CIrBits = std::ptr::null_mut();
262 xls_ffi_call!(xlsynth_sys::xls_value_get_bits, p; result)?;
263 Ok(IrBits { ptr: result })
264}
265
266pub(crate) fn xls_format_preference_from_string(
267 s: &str,
268) -> Result<XlsFormatPreference, XlsynthError> {
269 let c_str = CString::new(s).unwrap();
270 let mut result_out: XlsFormatPreference = -1;
271 xls_ffi_call!(xlsynth_sys::xls_format_preference_from_string, c_str.as_ptr(); result_out)?;
272 Ok(result_out)
273}
274
275pub(crate) fn xls_value_to_string_format_preference(
276 p: *mut CIrValue,
277 fmt: XlsFormatPreference,
278) -> Result<String, XlsynthError> {
279 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
280 xls_ffi_call!(xlsynth_sys::xls_value_to_string_format_preference, p, fmt; c_str_out)?;
281 Ok(unsafe { c_str_to_rust(c_str_out) })
282}
283
284pub(crate) fn xls_bits_to_string(
285 p: *const CIrBits,
286 fmt: XlsFormatPreference,
287 include_bit_count: bool,
288) -> Result<String, XlsynthError> {
289 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
290 xls_ffi_call!(xlsynth_sys::xls_bits_to_string, p, fmt, include_bit_count; c_str_out)?;
291 Ok(unsafe { c_str_to_rust(c_str_out) })
292}
293
294pub(crate) fn xls_bits_to_bytes(p: *const CIrBits) -> Result<Vec<u8>, XlsynthError> {
295 unsafe {
296 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
297 let mut bytes_out: *mut u8 = std::ptr::null_mut();
298 let mut byte_count_out: usize = 0;
299 let success =
300 xlsynth_sys::xls_bits_to_bytes(p, &mut error_out, &mut bytes_out, &mut byte_count_out);
301 if !success {
302 return Err(XlsynthError(c_str_to_rust(error_out)));
303 }
304 let slice = std::slice::from_raw_parts(bytes_out, byte_count_out);
305 let vec = slice.to_vec();
306 xlsynth_sys::xls_bytes_free(bytes_out);
307 Ok(vec)
308 }
309}
310
311pub(crate) fn xls_bits_to_uint64(p: *const CIrBits) -> Result<u64, XlsynthError> {
312 let mut value_out: u64 = 0;
313 xls_ffi_call!(xlsynth_sys::xls_bits_to_uint64, p; value_out)?;
314 Ok(value_out)
315}
316
317pub(crate) fn xls_bits_to_int64(p: *const CIrBits) -> Result<i64, XlsynthError> {
318 let mut value_out: i64 = 0;
319 xls_ffi_call!(xlsynth_sys::xls_bits_to_int64, p; value_out)?;
320 Ok(value_out)
321}
322
323pub(crate) fn xls_value_eq(
324 lhs: *const CIrValue,
325 rhs: *const CIrValue,
326) -> Result<bool, XlsynthError> {
327 unsafe { Ok(xlsynth_sys::xls_value_eq(lhs, rhs)) }
328}
329
330pub(crate) fn xls_parse_ir_package(
331 ir: &str,
332 filename: Option<&str>,
333) -> Result<crate::ir_package::IrPackage, XlsynthError> {
334 let ir_cstring = CString::new(ir).unwrap();
335 let (_filename_cstr, filename_ptr) = optional_cstring_and_ptr(filename);
336 let mut xls_package_out: *mut CIrPackage = std::ptr::null_mut();
337 xls_ffi_call!(xlsynth_sys::xls_parse_ir_package, ir_cstring.as_ptr(), filename_ptr; xls_package_out)?;
338 let package = crate::ir_package::IrPackage {
339 ptr: Arc::new(RwLock::new(IrPackagePtr(xls_package_out))),
340 filename: filename.map(|s| s.to_string()),
341 };
342 Ok(package)
343}
344
345pub(crate) fn xls_ir_analysis_create_from_package_with_options(
346 p: *mut CIrPackage,
347 options: Option<&xlsynth_sys::XlsIrAnalysisOptions>,
348) -> Result<*mut CIrAnalysis, XlsynthError> {
349 let mut out: *mut CIrAnalysis = std::ptr::null_mut();
350 let options_ptr: *const xlsynth_sys::XlsIrAnalysisOptions = options
351 .map_or(std::ptr::null(), |o| {
352 o as *const xlsynth_sys::XlsIrAnalysisOptions
353 });
354 xls_ffi_call!(
355 xlsynth_sys::xls_ir_analysis_create_from_package_with_options,
356 p,
357 options_ptr;
358 out
359 )?;
360 Ok(out)
361}
362
363pub(crate) fn xls_ir_analysis_get_known_bits_for_node_id(
364 a: *const CIrAnalysis,
365 node_id: i64,
366) -> Result<(IrBits, IrBits), XlsynthError> {
367 unsafe {
368 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
369 let mut known_mask_out: *mut CIrBits = std::ptr::null_mut();
370 let mut known_value_out: *mut CIrBits = std::ptr::null_mut();
371 let success = xlsynth_sys::xls_ir_analysis_get_known_bits_for_node_id(
372 a,
373 node_id,
374 &mut error_out,
375 &mut known_mask_out,
376 &mut known_value_out,
377 );
378 if success {
379 Ok((
380 IrBits {
381 ptr: known_mask_out,
382 },
383 IrBits {
384 ptr: known_value_out,
385 },
386 ))
387 } else {
388 Err(XlsynthError(c_str_to_rust(error_out)))
389 }
390 }
391}
392
393pub(crate) fn xls_ir_analysis_get_intervals_for_node_id(
394 a: *const CIrAnalysis,
395 node_id: i64,
396) -> Result<*mut CIrIntervalSet, XlsynthError> {
397 let mut intervals_out: *mut CIrIntervalSet = std::ptr::null_mut();
398 xls_ffi_call!(
399 xlsynth_sys::xls_ir_analysis_get_intervals_for_node_id,
400 a,
401 node_id;
402 intervals_out
403 )?;
404 Ok(intervals_out)
405}
406
407pub(crate) fn xls_interval_set_get_interval_bounds(
408 s: *const CIrIntervalSet,
409 i: i64,
410) -> Result<(IrBits, IrBits), XlsynthError> {
411 unsafe {
412 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
413 let mut lo_out: *mut CIrBits = std::ptr::null_mut();
414 let mut hi_out: *mut CIrBits = std::ptr::null_mut();
415 let success = xlsynth_sys::xls_interval_set_get_interval_bounds(
416 s,
417 i,
418 &mut error_out,
419 &mut lo_out,
420 &mut hi_out,
421 );
422 if success {
423 Ok((IrBits { ptr: lo_out }, IrBits { ptr: hi_out }))
424 } else {
425 Err(XlsynthError(c_str_to_rust(error_out)))
426 }
427 }
428}
429
430pub(crate) fn xls_package_new(name: &str) -> Result<crate::ir_package::IrPackage, XlsynthError> {
431 let (_name_cstr, name_ptr) = cstring_and_ptr(name);
432 let xls_package_out: *mut CIrPackage = unsafe { xlsynth_sys::xls_package_create(name_ptr) };
433 Ok(crate::ir_package::IrPackage {
434 ptr: Arc::new(RwLock::new(IrPackagePtr(xls_package_out))),
435 filename: None,
436 })
437}
438
439pub(crate) fn xls_function_builder_new(
440 package: *mut CIrPackage,
441 name: &str,
442 should_verify: bool,
443) -> Arc<RwLock<IrFnBuilderPtr>> {
444 let (_name_cstr, name_ptr) = cstring_and_ptr(name);
445 let fn_builder =
446 unsafe { xlsynth_sys::xls_function_builder_create(name_ptr, package, should_verify) };
447 assert!(!fn_builder.is_null());
448 Arc::new(RwLock::new(IrFnBuilderPtr { ptr: fn_builder }))
449}
450
451pub(crate) fn xls_function_builder_add_parameter(
452 builder: RwLockWriteGuard<IrFnBuilderPtr>,
453 name: &str,
454 type_: &IrType,
455) -> Arc<RwLock<BValuePtr>> {
456 let (_name_cstr, name_ptr) = cstring_and_ptr(name);
457 let type_raw = type_.ptr;
458 let bvalue_raw =
459 unsafe { xlsynth_sys::xls_function_builder_add_parameter(builder.ptr, name_ptr, type_raw) };
460 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
461}
462
463pub(crate) fn xls_function_builder_add_dynamic_bit_slice(
464 builder: RwLockWriteGuard<IrFnBuilderPtr>,
465 value: RwLockReadGuard<BValuePtr>,
466 start: RwLockReadGuard<BValuePtr>,
467 width: u64,
468 name: Option<&str>,
469) -> Arc<RwLock<BValuePtr>> {
470 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
471 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
472 let width_i64 = width as i64;
473 let bvalue_raw = unsafe {
474 xlsynth_sys::xls_builder_base_add_dynamic_bit_slice(
475 builder_base,
476 value.ptr,
477 start.ptr,
478 width_i64,
479 name_ptr,
480 )
481 };
482 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
483}
484
485pub(crate) fn xls_function_builder_add_bit_slice(
486 builder: RwLockWriteGuard<IrFnBuilderPtr>,
487 value: RwLockReadGuard<BValuePtr>,
488 start: u64,
489 width: u64,
490 name: Option<&str>,
491) -> Arc<RwLock<BValuePtr>> {
492 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
493 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
494 let bvalue_raw = unsafe {
495 xlsynth_sys::xls_builder_base_add_bit_slice(
496 builder_base,
497 value.ptr,
498 start as i64,
499 width as i64,
500 name_ptr,
501 )
502 };
503 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
504}
505
506pub(crate) fn xls_function_builder_add_concat(
507 builder: RwLockWriteGuard<IrFnBuilderPtr>,
508 values: &[RwLockReadGuard<BValuePtr>],
509 name: Option<&str>,
510) -> Arc<RwLock<BValuePtr>> {
511 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
512 let values_ptrs: Vec<*mut CIrBValue> = values.iter().map(|v| v.ptr).collect();
513 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
514 let bvalue_raw = unsafe {
515 xlsynth_sys::xls_builder_base_add_concat(
516 builder_base,
517 values_ptrs.as_ptr(),
518 values.len() as i64,
519 name_ptr,
520 )
521 };
522 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
523}
524
525pub(crate) fn xls_function_builder_add_literal(
526 builder: RwLockWriteGuard<IrFnBuilderPtr>,
527 value: &IrValue,
528 name: Option<&str>,
529) -> Arc<RwLock<BValuePtr>> {
530 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
531 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
532 let bvalue_raw =
533 unsafe { xlsynth_sys::xls_builder_base_add_literal(builder_base, value.ptr, name_ptr) };
534 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
535}
536
537pub(crate) fn xls_function_builder_add_tuple(
538 builder: RwLockWriteGuard<IrFnBuilderPtr>,
539 elements: &[RwLockReadGuard<BValuePtr>],
540 name: Option<&str>,
541) -> Arc<RwLock<BValuePtr>> {
542 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
543 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
544 let mut elements_ptrs: Vec<*mut CIrBValue> = elements.iter().map(|v| v.ptr).collect();
545 let bvalue_raw = unsafe {
546 xlsynth_sys::xls_builder_base_add_tuple(
547 builder_base,
548 elements_ptrs.as_mut_ptr(),
549 elements.len() as i64,
550 name_ptr,
551 )
552 };
553 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
554}
555
556pub(crate) fn xls_function_builder_add_tuple_index(
557 builder: RwLockWriteGuard<IrFnBuilderPtr>,
558 tuple: RwLockReadGuard<BValuePtr>,
559 index: u64,
560 name: Option<&str>,
561) -> Arc<RwLock<BValuePtr>> {
562 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
563 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
564 let bvalue_raw = unsafe {
565 xlsynth_sys::xls_builder_base_add_tuple_index(
566 builder_base,
567 tuple.ptr,
568 index as i64,
569 name_ptr,
570 )
571 };
572 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
573}
574
575pub(crate) fn xls_function_builder_build_with_return_value(
576 package: &Arc<RwLock<IrPackagePtr>>,
577 _package_guard: RwLockWriteGuard<IrPackagePtr>,
578 builder: RwLockWriteGuard<IrFnBuilderPtr>,
579 return_value: RwLockReadGuard<BValuePtr>,
580) -> Result<IrFunction, XlsynthError> {
581 let return_value_ptr = return_value.ptr;
582 let mut result_out: *mut CIrFunction = std::ptr::null_mut();
583 xls_ffi_call!(xlsynth_sys::xls_function_builder_build_with_return_value, builder.ptr, return_value_ptr; result_out)?;
584 Ok(IrFunction {
585 parent: package.clone(),
586 ptr: result_out,
587 })
588}
589
590pub(crate) fn xls_type_to_string(t: *const CIrType) -> Result<String, XlsynthError> {
591 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
592 xls_ffi_call!(xlsynth_sys::xls_type_to_string, t; c_str_out)?;
593 Ok(unsafe { c_str_to_rust(c_str_out) })
594}
595
596pub(crate) fn xls_type_get_flat_bit_count(t: *const CIrType) -> u64 {
597 let bit_count = unsafe { xlsynth_sys::xls_type_get_flat_bit_count(t) };
598 assert!(bit_count >= 0, "bit count must be non-negative");
599 bit_count as u64
600}
601
602pub(crate) fn xls_package_set_top_by_name(
603 package: *mut CIrPackage,
604 name: &str,
605) -> Result<(), XlsynthError> {
606 let (_name_cstr, name_ptr) = cstring_and_ptr(name);
607 xls_ffi_call_noreturn!(xlsynth_sys::xls_package_set_top_by_name, package, name_ptr)?;
608 Ok(())
609}
610
611pub(crate) fn xls_verify_package(package: *mut CIrPackage) -> Result<(), XlsynthError> {
612 xls_ffi_call_noreturn!(xlsynth_sys::xls_verify_package, package)?;
613 Ok(())
614}
615
616pub(crate) fn xls_package_get_bits_type(package: *mut CIrPackage, bit_count: u64) -> *mut CIrType {
617 unsafe { xlsynth_sys::xls_package_get_bits_type(package, bit_count as i64) }
618}
619
620pub(crate) fn xls_package_get_tuple_type(
621 package: *mut CIrPackage,
622 members: &[IrType],
623) -> *mut CIrType {
624 let mut members_ptrs: Vec<*mut CIrType> = members.iter().map(|v| v.ptr).collect();
625 let members_ptr = members_ptrs.as_mut_ptr();
626 let member_count = members_ptrs.len() as i64;
627 unsafe { xlsynth_sys::xls_package_get_tuple_type(package, members_ptr, member_count) }
628}
629
630pub(crate) fn xls_package_get_array_type(
631 package: *mut CIrPackage,
632 element_type: *mut CIrType,
633 size: i64,
634) -> *mut CIrType {
635 unsafe { xlsynth_sys::xls_package_get_array_type(package, element_type, size) }
636}
637
638pub(crate) fn xls_package_get_token_type(package: *mut CIrPackage) -> *mut CIrType {
639 unsafe { xlsynth_sys::xls_package_get_token_type(package) }
640}
641
642pub(crate) fn xls_package_get_type_for_value(
643 package: *mut CIrPackage,
644 value: *mut CIrValue,
645) -> Result<*mut CIrType, XlsynthError> {
646 let mut result_out: *mut CIrType = std::ptr::null_mut();
647 xls_ffi_call!(xlsynth_sys::xls_package_get_type_for_value, package, value; result_out)?;
648 Ok(result_out)
649}
650
651pub(crate) fn xls_package_get_function(
652 package: &Arc<RwLock<IrPackagePtr>>,
653 guard: RwLockReadGuard<IrPackagePtr>,
654 function_name: &str,
655) -> Result<crate::ir_package::IrFunction, XlsynthError> {
656 let function_name = CString::new(function_name).unwrap();
657 let mut result_out: *mut CIrFunction = std::ptr::null_mut();
658 xls_ffi_call!(xlsynth_sys::xls_package_get_function, guard.const_c_ptr(), function_name.as_ptr(); result_out)?;
659 Ok(crate::ir_package::IrFunction {
660 parent: package.clone(),
661 ptr: result_out,
662 })
663}
664
665pub(crate) fn xls_package_get_functions(
666 package: &Arc<RwLock<IrPackagePtr>>,
667 guard: RwLockWriteGuard<IrPackagePtr>,
668) -> Result<Vec<crate::ir_package::IrFunction>, XlsynthError> {
669 unsafe {
670 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
671 let mut result_out: *mut *mut CIrFunction = std::ptr::null_mut();
672 let mut count_out: libc::size_t = 0;
673 let success = xlsynth_sys::xls_package_get_functions(
674 guard.mut_c_ptr(),
675 &mut error_out,
676 &mut result_out,
677 &mut count_out,
678 );
679 if !success {
680 return Err(XlsynthError(c_str_to_rust(error_out)));
681 }
682
683 let functions = if result_out.is_null() || count_out == 0 {
684 Vec::new()
685 } else {
686 let raw_slice = std::slice::from_raw_parts(result_out, count_out);
687 raw_slice
688 .iter()
689 .map(|&ptr| crate::ir_package::IrFunction {
690 parent: package.clone(),
691 ptr,
692 })
693 .collect()
694 };
695
696 if !result_out.is_null() {
697 xlsynth_sys::xls_function_ptr_array_free(result_out);
698 }
699
700 Ok(functions)
701 }
702}
703
704pub(crate) fn xls_function_get_type(
705 _package_write_guard: &RwLockWriteGuard<IrPackagePtr>,
706 function: *const CIrFunction,
707) -> Result<*mut CIrFunctionType, XlsynthError> {
708 let mut xls_fn_type_out: *mut CIrFunctionType = std::ptr::null_mut();
709 xls_ffi_call!(xlsynth_sys::xls_function_get_type, function; xls_fn_type_out)?;
710 Ok(xls_fn_type_out)
711}
712
713pub(crate) fn xls_function_type_to_string(
714 t: *const CIrFunctionType,
715) -> Result<String, XlsynthError> {
716 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
717 xls_ffi_call!(xlsynth_sys::xls_function_type_to_string, t; c_str_out)?;
718 Ok(unsafe { c_str_to_rust(c_str_out) })
719}
720
721pub(crate) fn xls_function_get_name(function: *const CIrFunction) -> Result<String, XlsynthError> {
722 let mut c_str_out: *mut std::os::raw::c_char = std::ptr::null_mut();
723 xls_ffi_call!(xlsynth_sys::xls_function_get_name, function; c_str_out)?;
724 Ok(unsafe { c_str_to_rust(c_str_out) })
725}
726
727pub(crate) fn xls_interpret_function(
728 _package_guard: &RwLockReadGuard<IrPackagePtr>,
729 function: *const CIrFunction,
730 args: &[IrValue],
731) -> Result<IrValue, XlsynthError> {
732 let args_ptrs: Vec<*const CIrValue> =
733 args.iter().map(|v| -> *const CIrValue { v.ptr }).collect();
734 let argc = args_ptrs.len();
735 let mut result_out: *mut CIrValue = std::ptr::null_mut();
736 xls_ffi_call!(xlsynth_sys::xls_interpret_function, function, argc, args_ptrs.as_ptr(); result_out)?;
737 Ok(IrValue { ptr: result_out })
738}
739
740pub(crate) fn xls_optimize_ir(ir: &str, top: &str) -> Result<String, XlsynthError> {
741 let ir = CString::new(ir).unwrap();
742 let top = CString::new(top).unwrap();
743 let mut ir_out: *mut std::os::raw::c_char = std::ptr::null_mut();
744 xls_ffi_call!(xlsynth_sys::xls_optimize_ir, ir.as_ptr(), top.as_ptr(); ir_out)?;
745 let ir_str = unsafe { c_str_to_rust(ir_out) };
746 Ok(ir_str)
747}
748
749#[derive(Debug, Clone, PartialEq, Eq)]
750pub struct TraceMessage {
751 pub message: String,
752 pub verbosity: i64,
753}
754
755#[derive(Debug, Clone, PartialEq, Eq)]
756pub struct RunResult {
757 pub value: IrValue,
758 pub trace_messages: Vec<TraceMessage>,
759 pub assert_messages: Vec<String>,
760}
761
762unsafe fn trace_messages_to_rust(
765 c_trace_messages: *mut CTraceMessage,
766 count: usize,
767) -> Vec<TraceMessage> {
768 if c_trace_messages.is_null() {
769 return Vec::new();
770 }
771 let mut trace_messages: Vec<TraceMessage> = Vec::new();
772 for i in 0..count {
773 let trace_message: &CTraceMessage = unsafe { &*c_trace_messages.wrapping_add(i) };
774 trace_messages.push(TraceMessage {
775 message: unsafe { c_str_to_rust_no_dealloc(trace_message.message) },
776 verbosity: trace_message.verbosity,
777 });
778 }
779 xlsynth_sys::xls_trace_messages_free(c_trace_messages, count);
780 trace_messages
781}
782
783pub(crate) unsafe fn c_strs_to_rust(
784 c_strs: *mut *mut std::os::raw::c_char,
785 count: usize,
786) -> Vec<String> {
787 let mut result: Vec<String> = Vec::new();
788 for i in 0..count {
789 let xls_c_str: *mut std::os::raw::c_char = unsafe { *c_strs.wrapping_add(i) };
790 result.push(c_str_to_rust_no_dealloc(xls_c_str));
791 }
792 if !c_strs.is_null() && count > 0 {
793 unsafe {
794 xlsynth_sys::xls_c_strs_free(c_strs, count);
795 }
796 }
797 result
798}
799
800pub(crate) fn xls_make_function_jit(
801 _package_guard: &RwLockReadGuard<IrPackagePtr>,
802 function: *const CIrFunction,
803) -> Result<*mut CIrFunctionJit, XlsynthError> {
804 let mut ptr: *mut CIrFunctionJit = std::ptr::null_mut();
805 xls_ffi_call!(xlsynth_sys::xls_make_function_jit, function; ptr)?;
806 Ok(ptr)
807}
808
809pub(crate) fn xls_function_jit_run(
810 _package_guard: &RwLockReadGuard<IrPackagePtr>,
811 jit: *const CIrFunctionJit,
812 args: &[IrValue],
813) -> Result<RunResult, XlsynthError> {
814 let mut result_out: *mut CIrValue = std::ptr::null_mut();
815 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
816 let argc = args.len();
817 let args_ptrs: Vec<*const CIrValue> =
818 args.iter().map(|v| -> *const CIrValue { v.ptr }).collect();
819 let mut trace_messages_out: *mut CTraceMessage = std::ptr::null_mut();
820 let mut trace_messages_count: usize = 0;
821 let mut assert_messages_out: *mut *mut std::os::raw::c_char = std::ptr::null_mut();
822 let mut assert_messages_count: usize = 0;
823 let success = unsafe {
824 xlsynth_sys::xls_function_jit_run(
825 jit,
826 argc,
827 args_ptrs.as_ptr(),
828 &mut error_out,
829 &mut trace_messages_out,
830 &mut trace_messages_count,
831 &mut assert_messages_out,
832 &mut assert_messages_count,
833 &mut result_out,
834 )
835 };
836 if !success {
837 let error_message = unsafe { c_str_to_rust(error_out) };
838 return Err(XlsynthError(format!(
839 "Failed to run JIT function: {error_message}"
840 )));
841 }
842 let trace_messages =
843 unsafe { trace_messages_to_rust(trace_messages_out, trace_messages_count) };
844 let assert_messages = unsafe { c_strs_to_rust(assert_messages_out, assert_messages_count) };
845 Ok(RunResult {
846 value: IrValue { ptr: result_out },
847 trace_messages,
848 assert_messages,
849 })
850}
851
852pub(crate) fn xls_mangle_dslx_name(
853 module_name: &str,
854 function_name: &str,
855) -> Result<String, XlsynthError> {
856 let module_name = CString::new(module_name).unwrap();
857 let function_name = CString::new(function_name).unwrap();
858 let mut mangled_out: *mut std::os::raw::c_char = std::ptr::null_mut();
859 xls_ffi_call!(xlsynth_sys::xls_mangle_dslx_name, module_name.as_ptr(), function_name.as_ptr(); mangled_out)?;
860 Ok(unsafe { c_str_to_rust(mangled_out) })
861}
862
863pub(crate) fn xls_mangle_dslx_name_full(
864 module_name: &str,
865 function_name: &str,
866 convention: crate::DslxCallingConvention,
867 free_keys: &[&str],
868 param_env: Option<&crate::dslx::ParametricEnv>,
869 scope: Option<&str>,
870) -> Result<String, XlsynthError> {
871 let module_c = std::ffi::CString::new(module_name).unwrap();
872 let function_c = std::ffi::CString::new(function_name).unwrap();
873
874 let free_key_cstrs: Vec<std::ffi::CString> = free_keys
875 .iter()
876 .map(|s| std::ffi::CString::new((*s).as_bytes()).unwrap())
877 .collect();
878 let free_key_ptrs: Vec<*const std::os::raw::c_char> =
879 free_key_cstrs.iter().map(|s| s.as_ptr()).collect();
880 let free_keys_ptr = if free_key_ptrs.is_empty() {
881 std::ptr::null()
882 } else {
883 free_key_ptrs.as_ptr()
884 };
885
886 let (_scope_cstr_opt, scope_ptr) = optional_cstring_and_ptr(scope);
887 let cc: xlsynth_sys::XlsCallingConvention = convention.into();
888
889 let mut mangled_out: *mut std::os::raw::c_char = std::ptr::null_mut();
890 xls_ffi_call!(
891 xlsynth_sys::xls_mangle_dslx_name_full,
892 module_c.as_ptr(),
893 function_c.as_ptr(),
894 cc,
895 free_keys_ptr,
896 free_key_ptrs.len(),
897 param_env.map(|e| e.ptr as *const _).unwrap_or(std::ptr::null()),
898 scope_ptr;
899 mangled_out
900 )?;
901 Ok(unsafe { c_str_to_rust(mangled_out) })
902}
903
904pub(crate) fn xls_schedule_and_codegen_package(
905 _package: &Arc<RwLock<IrPackagePtr>>,
906 guard: RwLockWriteGuard<IrPackagePtr>,
907 scheduling_options_flags_proto_str: &str,
908 codegen_flags_proto_str: &str,
909 with_delay_model: bool,
910) -> Result<ScheduleAndCodegenResult, XlsynthError> {
911 let scheduling_options_flags_proto = CString::new(scheduling_options_flags_proto_str).unwrap();
912 let codegen_flags_proto = CString::new(codegen_flags_proto_str).unwrap();
913 let mut result_out: *mut CScheduleAndCodegenResult = std::ptr::null_mut();
914 xls_ffi_call!(xlsynth_sys::xls_schedule_and_codegen_package,
915 guard.mut_c_ptr(),
916 scheduling_options_flags_proto.as_ptr(),
917 codegen_flags_proto.as_ptr(),
918 with_delay_model;
919 result_out
920 )?;
921 assert!(!result_out.is_null());
922 Ok(ScheduleAndCodegenResult { ptr: result_out })
923}
924
925pub(crate) fn xls_function_builder_add_array(
926 builder: RwLockWriteGuard<IrFnBuilderPtr>,
927 element_type: &IrType,
928 elements: &[RwLockReadGuard<BValuePtr>],
929 name: Option<&str>,
930) -> Arc<RwLock<BValuePtr>> {
931 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
932 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
933 let elements_ptrs: Vec<*mut CIrBValue> = elements.iter().map(|v| v.ptr).collect();
934 let bvalue_raw = unsafe {
935 xlsynth_sys::xls_builder_base_add_array(
936 builder_base,
937 element_type.ptr,
938 elements_ptrs.as_ptr(),
939 elements_ptrs.len() as i64,
940 name_ptr,
941 )
942 };
943 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
944}
945
946pub(crate) fn xls_function_builder_add_array_index_multi(
947 builder: RwLockWriteGuard<IrFnBuilderPtr>,
948 array: RwLockReadGuard<BValuePtr>,
949 index: &[RwLockReadGuard<BValuePtr>],
950 assumed_in_bounds: bool,
951 name: Option<&str>,
952) -> Arc<RwLock<BValuePtr>> {
953 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
954 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
955 let index_ptrs: Vec<*mut CIrBValue> = index.iter().map(|v| v.ptr).collect();
956 let bvalue_raw = unsafe {
957 xlsynth_sys::xls_builder_base_add_array_index(
958 builder_base,
959 array.ptr,
960 index_ptrs.as_ptr(),
961 index_ptrs.len() as i64,
962 assumed_in_bounds,
963 name_ptr,
964 )
965 };
966 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
967}
968
969pub(crate) fn xls_function_builder_add_bit_slice_update(
970 builder: RwLockWriteGuard<IrFnBuilderPtr>,
971 value: RwLockReadGuard<BValuePtr>,
972 start: RwLockReadGuard<BValuePtr>,
973 update: RwLockReadGuard<BValuePtr>,
974 name: Option<&str>,
975) -> Arc<RwLock<BValuePtr>> {
976 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
977 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
978 let bvalue_raw = unsafe {
979 xlsynth_sys::xls_builder_base_add_bit_slice_update(
980 builder_base,
981 value.ptr,
982 start.ptr,
983 update.ptr,
984 name_ptr,
985 )
986 };
987 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
988}
989
990pub(crate) fn xls_function_builder_add_select(
991 builder: RwLockWriteGuard<IrFnBuilderPtr>,
992 selector: RwLockReadGuard<BValuePtr>,
993 cases: &[RwLockReadGuard<BValuePtr>],
994 default_value: RwLockReadGuard<BValuePtr>,
995 name: Option<&str>,
996) -> Arc<RwLock<BValuePtr>> {
997 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
998 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
999 let cases_ptrs: Vec<*mut CIrBValue> = cases.iter().map(|v| v.ptr).collect();
1000 let bvalue_raw = unsafe {
1001 xlsynth_sys::xls_builder_base_add_select(
1002 builder_base,
1003 selector.ptr,
1004 cases_ptrs.as_ptr(),
1005 cases_ptrs.len() as i64,
1006 default_value.ptr,
1007 name_ptr,
1008 )
1009 };
1010 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1011}
1012
1013pub(crate) fn xls_function_builder_add_array_concat(
1014 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1015 arrays: &[RwLockReadGuard<BValuePtr>],
1016 name: Option<&str>,
1017) -> Arc<RwLock<BValuePtr>> {
1018 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
1019 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1020 let arrays_ptrs: Vec<*mut CIrBValue> = arrays.iter().map(|v| v.ptr).collect();
1021 let bvalue_raw = unsafe {
1022 xlsynth_sys::xls_builder_base_add_array_concat(
1023 builder_base,
1024 arrays_ptrs.as_ptr(),
1025 arrays_ptrs.len() as i64,
1026 name_ptr,
1027 )
1028 };
1029 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1030}
1031
1032pub(crate) fn xls_function_builder_add_array_slice(
1033 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1034 array: RwLockReadGuard<BValuePtr>,
1035 start: RwLockReadGuard<BValuePtr>,
1036 width: i64,
1037 name: Option<&str>,
1038) -> Arc<RwLock<BValuePtr>> {
1039 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
1040 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1041 let bvalue_raw = unsafe {
1042 xlsynth_sys::xls_builder_base_add_array_slice(
1043 builder_base,
1044 array.ptr,
1045 start.ptr,
1046 width,
1047 name_ptr,
1048 )
1049 };
1050 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1051}
1052
1053pub(crate) fn xls_function_builder_add_array_update(
1054 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1055 array: RwLockReadGuard<BValuePtr>,
1056 update_value: RwLockReadGuard<BValuePtr>,
1057 indices: &[RwLockReadGuard<BValuePtr>],
1058 assumed_in_bounds: bool,
1059 name: Option<&str>,
1060) -> Arc<RwLock<BValuePtr>> {
1061 let (_name_cstr, name_ptr) = optional_cstring_and_ptr(name);
1062 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1063 let indices_ptrs: Vec<*mut CIrBValue> = indices.iter().map(|v| v.ptr).collect();
1064 let bvalue_raw = unsafe {
1065 xlsynth_sys::xls_builder_base_add_array_update(
1066 builder_base,
1067 array.ptr,
1068 update_value.ptr,
1069 indices_ptrs.as_ptr(),
1070 indices_ptrs.len() as i64,
1071 assumed_in_bounds,
1072 name_ptr,
1073 )
1074 };
1075 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1076}
1077
1078pub(crate) fn xls_function_builder_add_sign_extend(
1079 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1080 value: RwLockReadGuard<BValuePtr>,
1081 new_bit_count: i64,
1082 name: Option<&str>,
1083) -> Arc<RwLock<BValuePtr>> {
1084 let name_cstr = name.map(|s| CString::new(s).unwrap());
1085 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1086 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1087 let bvalue_raw = unsafe {
1088 xlsynth_sys::xls_builder_base_add_sign_extend(
1089 builder_base,
1090 value.ptr,
1091 new_bit_count,
1092 name_ptr,
1093 )
1094 };
1095 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1096}
1097
1098pub(crate) fn xls_function_builder_add_zero_extend(
1099 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1100 value: RwLockReadGuard<BValuePtr>,
1101 new_bit_count: i64,
1102 name: Option<&str>,
1103) -> Arc<RwLock<BValuePtr>> {
1104 let name_cstr = name.map(|s| CString::new(s).unwrap());
1105 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1106 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1107 let bvalue_raw = unsafe {
1108 xlsynth_sys::xls_builder_base_add_zero_extend(
1109 builder_base,
1110 value.ptr,
1111 new_bit_count,
1112 name_ptr,
1113 )
1114 };
1115 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1116}
1117
1118pub(crate) fn xls_function_builder_add_one_hot(
1119 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1120 input: RwLockReadGuard<BValuePtr>,
1121 lsb_is_priority: bool,
1122 name: Option<&str>,
1123) -> Arc<RwLock<BValuePtr>> {
1124 let name_cstr = name.map(|s| CString::new(s).unwrap());
1125 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1126 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1127 let bvalue_raw = unsafe {
1128 xlsynth_sys::xls_builder_base_add_one_hot(
1129 builder_base,
1130 input.ptr,
1131 lsb_is_priority,
1132 name_ptr,
1133 )
1134 };
1135 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1136}
1137
1138pub(crate) fn xls_function_builder_add_priority_select(
1139 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1140 selector: RwLockReadGuard<BValuePtr>,
1141 cases: &[RwLockReadGuard<BValuePtr>],
1142 default_value: RwLockReadGuard<BValuePtr>,
1143 name: Option<&str>,
1144) -> Arc<RwLock<BValuePtr>> {
1145 let name_cstr = name.map(|s| CString::new(s).unwrap());
1146 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1147 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1148 let cases_ptrs: Vec<*mut CIrBValue> = cases.iter().map(|v| v.ptr).collect();
1149 let bvalue_raw = unsafe {
1150 xlsynth_sys::xls_builder_base_add_priority_select(
1151 builder_base,
1152 selector.ptr,
1153 cases_ptrs.as_ptr(),
1154 cases_ptrs.len() as i64,
1155 default_value.ptr,
1156 name_ptr,
1157 )
1158 };
1159 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1160}
1161
1162pub(crate) fn xls_function_builder_add_one_hot_select(
1163 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1164 selector: RwLockReadGuard<BValuePtr>,
1165 cases: &[RwLockReadGuard<BValuePtr>],
1166 name: Option<&str>,
1167) -> Arc<RwLock<BValuePtr>> {
1168 let name_cstr = name.map(|s| CString::new(s).unwrap());
1169 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1170 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1171 let cases_ptrs: Vec<*mut CIrBValue> = cases.iter().map(|v| v.ptr).collect();
1172 let bvalue_raw = unsafe {
1173 xlsynth_sys::xls_builder_base_add_one_hot_select(
1174 builder_base,
1175 selector.ptr,
1176 cases_ptrs.as_ptr(),
1177 cases_ptrs.len() as i64,
1178 name_ptr,
1179 )
1180 };
1181 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1182}
1183
1184pub(crate) fn xls_function_builder_add_decode(
1185 builder: RwLockWriteGuard<IrFnBuilderPtr>,
1186 value: RwLockReadGuard<BValuePtr>,
1187 width: Option<u64>,
1188 name: Option<&str>,
1189) -> Arc<RwLock<BValuePtr>> {
1190 let name_cstr = name.map(|s| CString::new(s).unwrap());
1191 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1192 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1193
1194 let mut width_value = width.unwrap_or(0);
1195 let width_ptr: *mut i64 = if width.is_some() {
1196 &mut width_value as *mut u64 as *mut i64
1197 } else {
1198 std::ptr::null_mut()
1199 };
1200 let bvalue_raw = unsafe {
1201 xlsynth_sys::xls_builder_base_add_decode(builder_base, value.ptr, width_ptr, name_ptr)
1202 };
1203 Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw }))
1204}
1205
1206pub(crate) fn xls_function_builder_last_value(
1207 builder: RwLockReadGuard<IrFnBuilderPtr>,
1208) -> Result<Arc<RwLock<BValuePtr>>, XlsynthError> {
1209 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1210 let mut bvalue_raw: *mut CIrBValue = std::ptr::null_mut();
1211 xls_ffi_call!(xlsynth_sys::xls_builder_base_get_last_value, builder_base; bvalue_raw)?;
1212 assert!(!bvalue_raw.is_null());
1213 Ok(Arc::new(RwLock::new(BValuePtr { ptr: bvalue_raw })))
1214}
1215
1216pub(crate) fn xls_function_builder_get_type(
1217 builder: RwLockReadGuard<IrFnBuilderPtr>,
1218 value: RwLockReadGuard<BValuePtr>,
1219) -> Option<*mut CIrType> {
1220 let builder_base = unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1221 let type_raw = unsafe { xlsynth_sys::xls_builder_base_get_type(builder_base, value.ptr) };
1222 if type_raw.is_null() {
1223 None
1224 } else {
1225 Some(type_raw)
1226 }
1227}
1228
1229macro_rules! impl_binary_ir_builder {
1230 ($fn_name:ident, $ffi_func:ident) => {
1231 pub(crate) fn $fn_name(
1232 builder: std::sync::RwLockWriteGuard<IrFnBuilderPtr>,
1233 a: std::sync::RwLockReadGuard<BValuePtr>,
1234 b: std::sync::RwLockReadGuard<BValuePtr>,
1235 name: Option<&str>,
1236 ) -> std::sync::Arc<std::sync::RwLock<BValuePtr>> {
1237 let builder_base =
1238 unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1239 let name_cstr = name.map(|s| std::ffi::CString::new(s).unwrap());
1240 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1241 let builder_base =
1242 unsafe { xlsynth_sys::$ffi_func(builder_base, a.ptr, b.ptr, name_ptr) };
1243 std::sync::Arc::new(std::sync::RwLock::new(BValuePtr { ptr: builder_base }))
1244 }
1245 };
1246}
1247
1248impl_binary_ir_builder!(xls_function_builder_add_add, xls_builder_base_add_add);
1249impl_binary_ir_builder!(xls_function_builder_add_sub, xls_builder_base_add_sub);
1250impl_binary_ir_builder!(xls_function_builder_add_shra, xls_builder_base_add_shra);
1251impl_binary_ir_builder!(xls_function_builder_add_shrl, xls_builder_base_add_shrl);
1252impl_binary_ir_builder!(xls_function_builder_add_shll, xls_builder_base_add_shll);
1253impl_binary_ir_builder!(xls_function_builder_add_nor, xls_builder_base_add_nor);
1254impl_binary_ir_builder!(xls_function_builder_add_and, xls_builder_base_add_and);
1255impl_binary_ir_builder!(xls_function_builder_add_nand, xls_builder_base_add_nand);
1256impl_binary_ir_builder!(xls_function_builder_add_or, xls_builder_base_add_or);
1257impl_binary_ir_builder!(xls_function_builder_add_xor, xls_builder_base_add_xor);
1258impl_binary_ir_builder!(xls_function_builder_add_eq, xls_builder_base_add_eq);
1259impl_binary_ir_builder!(xls_function_builder_add_ne, xls_builder_base_add_ne);
1260impl_binary_ir_builder!(xls_function_builder_add_ule, xls_builder_base_add_ule);
1261impl_binary_ir_builder!(xls_function_builder_add_ult, xls_builder_base_add_ult);
1262impl_binary_ir_builder!(xls_function_builder_add_uge, xls_builder_base_add_uge);
1263impl_binary_ir_builder!(xls_function_builder_add_ugt, xls_builder_base_add_ugt);
1264impl_binary_ir_builder!(xls_function_builder_add_sle, xls_builder_base_add_sle);
1265impl_binary_ir_builder!(xls_function_builder_add_slt, xls_builder_base_add_slt);
1266impl_binary_ir_builder!(xls_function_builder_add_sgt, xls_builder_base_add_sgt);
1267impl_binary_ir_builder!(xls_function_builder_add_sge, xls_builder_base_add_sge);
1268impl_binary_ir_builder!(xls_function_builder_add_umul, xls_builder_base_add_umul);
1269impl_binary_ir_builder!(xls_function_builder_add_smul, xls_builder_base_add_smul);
1270impl_binary_ir_builder!(xls_function_builder_add_udiv, xls_builder_base_add_udiv);
1271impl_binary_ir_builder!(xls_function_builder_add_sdiv, xls_builder_base_add_sdiv);
1272impl_binary_ir_builder!(xls_function_builder_add_umod, xls_builder_base_add_umod);
1273impl_binary_ir_builder!(xls_function_builder_add_smod, xls_builder_base_add_smod);
1274
1275macro_rules! impl_unary_ir_builder {
1276 ($fn_name:ident, $ffi_func:ident) => {
1277 pub(crate) fn $fn_name(
1278 builder: std::sync::RwLockWriteGuard<IrFnBuilderPtr>,
1279 a: std::sync::RwLockReadGuard<BValuePtr>,
1280 name: Option<&str>,
1281 ) -> std::sync::Arc<std::sync::RwLock<BValuePtr>> {
1282 let builder_base =
1283 unsafe { xlsynth_sys::xls_function_builder_as_builder_base(builder.ptr) };
1284 let name_cstr = name.map(|s| std::ffi::CString::new(s).unwrap());
1285 let name_ptr = name_cstr.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
1286 let builder_base = unsafe { xlsynth_sys::$ffi_func(builder_base, a.ptr, name_ptr) };
1287 std::sync::Arc::new(std::sync::RwLock::new(BValuePtr { ptr: builder_base }))
1288 }
1289 };
1290}
1291
1292impl_unary_ir_builder!(xls_function_builder_add_not, xls_builder_base_add_not);
1293impl_unary_ir_builder!(xls_function_builder_add_negate, xls_builder_base_add_negate);
1294impl_unary_ir_builder!(
1295 xls_function_builder_add_reverse,
1296 xls_builder_base_add_reverse
1297);
1298impl_unary_ir_builder!(
1299 xls_function_builder_add_or_reduce,
1300 xls_builder_base_add_or_reduce
1301);
1302impl_unary_ir_builder!(
1303 xls_function_builder_add_and_reduce,
1304 xls_builder_base_add_and_reduce
1305);
1306impl_unary_ir_builder!(
1307 xls_function_builder_add_xor_reduce,
1308 xls_builder_base_add_xor_reduce
1309);
1310impl_unary_ir_builder!(xls_function_builder_add_ctz, xls_builder_base_add_ctz);
1311impl_unary_ir_builder!(xls_function_builder_add_clz, xls_builder_base_add_clz);
1312impl_unary_ir_builder!(xls_function_builder_add_encode, xls_builder_base_add_encode);
1313impl_unary_ir_builder!(
1314 xls_function_builder_add_identity,
1315 xls_builder_base_add_identity
1316);
1317
1318pub(crate) fn xls_function_type_param_count(t: *mut xlsynth_sys::CIrFunctionType) -> i64 {
1319 unsafe { xlsynth_sys::xls_function_type_get_param_count(t) }
1320}
1321
1322pub(crate) fn xls_function_type_get_param_type(
1323 t: *mut xlsynth_sys::CIrFunctionType,
1324 index: usize,
1325) -> Result<*mut xlsynth_sys::CIrType, XlsynthError> {
1326 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
1327 let mut type_out: *mut xlsynth_sys::CIrType = std::ptr::null_mut();
1328 let success = unsafe {
1329 xlsynth_sys::xls_function_type_get_param_type(t, index, &mut error_out, &mut type_out)
1330 };
1331 if success {
1332 Ok(type_out)
1333 } else {
1334 Err(XlsynthError(unsafe { c_str_to_rust(error_out) }))
1335 }
1336}
1337
1338pub(crate) fn xls_function_type_get_return_type(
1339 t: *mut xlsynth_sys::CIrFunctionType,
1340) -> *mut xlsynth_sys::CIrType {
1341 unsafe { xlsynth_sys::xls_function_type_get_return_type(t) }
1342}
1343
1344pub(crate) fn xls_function_get_param_name(
1345 f: *mut xlsynth_sys::CIrFunction,
1346 index: usize,
1347) -> Result<String, XlsynthError> {
1348 let mut error_out: *mut std::os::raw::c_char = std::ptr::null_mut();
1349 let mut name_out: *mut std::os::raw::c_char = std::ptr::null_mut();
1350 let success = unsafe {
1351 xlsynth_sys::xls_function_get_param_name(f, index, &mut error_out, &mut name_out)
1352 };
1353 if success {
1354 Ok(unsafe { c_str_to_rust(name_out) })
1355 } else {
1356 Err(XlsynthError(unsafe { c_str_to_rust(error_out) }))
1357 }
1358}