Skip to content

Commit 334098a

Browse files
committed
Add fwrite in libcc2rs to allow taking its address
1 parent 7e9a423 commit 334098a

8 files changed

Lines changed: 468 additions & 418 deletions

File tree

libcc2rs/src/io.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,104 @@ pub fn fread_refcount(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) ->
121121
(read_bytes / a1 as usize) as u64
122122
}
123123

124+
pub fn fwrite_refcount(a0: AnyPtr, a1: u64, a2: u64, a3: Ptr<::std::fs::File>) -> u64 {
125+
let total = a1.saturating_mul(a2) as usize;
126+
let mut src = a0
127+
.cast::<u8>()
128+
.expect("fwrite: only supporting u8 pointers")
129+
.clone();
130+
131+
let f = (*a3.upgrade().deref())
132+
.try_clone()
133+
.expect("try_clone failed");
134+
let mut writer = std::io::BufWriter::with_capacity(64 * 1024, f);
135+
136+
let mut written_bytes: usize = 0;
137+
let mut buffer: [u8; 8192] = [0; 8192];
138+
139+
while written_bytes < total {
140+
let remaining = total - written_bytes;
141+
let to_fill = std::cmp::min(buffer.len(), remaining);
142+
143+
for b in buffer.iter_mut().take(to_fill) {
144+
*b = src.read();
145+
src = src.offset(1);
146+
}
147+
148+
let mut off = 0;
149+
while off < to_fill {
150+
match std::io::Write::write(&mut writer, &buffer[off..to_fill]) {
151+
Ok(0) => break,
152+
Ok(n) => off += n,
153+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
154+
Err(e) => panic!("Unhandled error in fwrite: {e}"),
155+
}
156+
}
157+
158+
if off == 0 {
159+
break;
160+
}
161+
162+
written_bytes += off;
163+
}
164+
165+
std::io::Write::flush(&mut writer).expect("flush failed");
166+
167+
(written_bytes / a1 as usize) as u64
168+
}
169+
170+
/// # Safety
171+
///
172+
/// `a0` must point to a readable buffer of at least `a1 * a2` bytes, and `a3`
173+
/// must point to a valid, open `std::fs::File`.
174+
pub unsafe fn fwrite_unsafe(
175+
a0: *const ::std::ffi::c_void,
176+
a1: u64,
177+
a2: u64,
178+
a3: *mut ::std::fs::File,
179+
) -> u64 {
180+
let total = a1.saturating_mul(a2) as usize;
181+
let mut src = a0 as *const u8;
182+
183+
let f = unsafe { (*a3).try_clone().expect("try_clone failed") };
184+
let mut writer = std::io::BufWriter::with_capacity(64 * 1024, f);
185+
186+
let mut written_bytes: usize = 0;
187+
let mut buffer: [u8; 8192] = [0; 8192];
188+
189+
while written_bytes < total {
190+
let remaining = total - written_bytes;
191+
let to_fill = std::cmp::min(buffer.len(), remaining);
192+
193+
for b in buffer.iter_mut().take(to_fill) {
194+
unsafe {
195+
*b = *src;
196+
src = src.offset(1);
197+
}
198+
}
199+
200+
let mut off = 0;
201+
while off < to_fill {
202+
match std::io::Write::write(&mut writer, &buffer[off..to_fill]) {
203+
Ok(0) => break,
204+
Ok(n) => off += n,
205+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
206+
Err(e) => panic!("Unhandled error in fwrite: {e}"),
207+
}
208+
}
209+
210+
if off == 0 {
211+
break;
212+
}
213+
214+
written_bytes += off;
215+
}
216+
217+
std::io::Write::flush(&mut writer).expect("flush failed");
218+
219+
(written_bytes / a1 as usize) as u64
220+
}
221+
124222
/// # Safety
125223
///
126224
/// `a0` must point to a writable buffer of at least `a1 * a2` bytes, and `a3`

rules/stdio/ir_refcount.json

Lines changed: 19 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -503,234 +503,56 @@
503503
"f6": {
504504
"body": [
505505
{
506-
"text": "let total = "
506+
"text": "libcc2rs::fwrite_refcount("
507507
},
508508
{
509-
"method_call": {
510-
"receiver": [
511-
{
512-
"placeholder": {
513-
"arg": 1,
514-
"access": "read"
515-
}
516-
}
517-
],
518-
"body": [
519-
{
520-
"text": ".saturating_mul("
521-
},
522-
{
523-
"placeholder": {
524-
"arg": 2,
525-
"access": "read"
526-
}
527-
},
528-
{
529-
"text": ")"
530-
}
531-
]
532-
}
533-
},
534-
{
535-
"text": " as usize;\n let mut src = "
536-
},
537-
{
538-
"method_call": {
539-
"receiver": [
540-
{
541-
"method_call": {
542-
"receiver": [
543-
{
544-
"method_call": {
545-
"receiver": [
546-
{
547-
"placeholder": {
548-
"arg": 0,
549-
"access": "read"
550-
}
551-
}
552-
],
553-
"body": [
554-
{
555-
"text": ".cast::<u8>()"
556-
}
557-
]
558-
}
559-
}
560-
],
561-
"body": [
562-
{
563-
"text": ".expect(\"fwrite: only supporting u8 pointers\")"
564-
}
565-
]
566-
}
567-
}
568-
],
569-
"body": [
570-
{
571-
"text": ".clone()"
572-
}
573-
]
574-
}
575-
},
576-
{
577-
"text": ";\n\n let mut f = "
578-
},
579-
{
580-
"method_call": {
581-
"receiver": [
582-
{
583-
"method_call": {
584-
"receiver": [
585-
{
586-
"text": "(*"
587-
},
588-
{
589-
"method_call": {
590-
"receiver": [
591-
{
592-
"method_call": {
593-
"receiver": [
594-
{
595-
"placeholder": {
596-
"arg": 3,
597-
"access": "read"
598-
}
599-
}
600-
],
601-
"body": [
602-
{
603-
"text": ".upgrade()"
604-
}
605-
]
606-
}
607-
}
608-
],
609-
"body": [
610-
{
611-
"text": ".deref()"
612-
}
613-
]
614-
}
615-
},
616-
{
617-
"text": ")"
618-
}
619-
],
620-
"body": [
621-
{
622-
"text": ".try_clone()"
623-
}
624-
]
625-
}
626-
}
627-
],
628-
"body": [
629-
{
630-
"text": ".expect(\"try_clone failed\")"
631-
}
632-
]
633-
}
634-
},
635-
{
636-
"text": ";\n let mut writer = std::io::BufWriter::with_capacity(64 * 1024, f);\n\n let mut written_bytes: usize = 0;\n let mut buffer: [u8; 8192] = [0; 8192];\n\n while written_bytes < total {\n let remaining = total - written_bytes;\n let to_fill = std::cmp::min("
637-
},
638-
{
639-
"method_call": {
640-
"receiver": [
641-
{
642-
"text": "buffer"
643-
}
644-
],
645-
"body": [
646-
{
647-
"text": ".len()"
648-
}
649-
]
650-
}
651-
},
652-
{
653-
"text": ", remaining);\n\n for i in 0..to_fill {\n buffer[i] = "
654-
},
655-
{
656-
"method_call": {
657-
"receiver": [
658-
{
659-
"text": "src"
660-
}
661-
],
662-
"body": [
663-
{
664-
"text": ".read()"
665-
}
666-
]
509+
"placeholder": {
510+
"arg": 0,
511+
"access": "read"
667512
}
668513
},
669514
{
670-
"text": ";\n src = "
515+
"text": ", "
671516
},
672517
{
673-
"method_call": {
674-
"receiver": [
675-
{
676-
"text": "src"
677-
}
678-
],
679-
"body": [
680-
{
681-
"text": ".offset(1)"
682-
}
683-
]
518+
"placeholder": {
519+
"arg": 1,
520+
"access": "read"
684521
}
685522
},
686523
{
687-
"text": ";\n }\n\n let mut off = 0;\n while off < to_fill {\n match std::io::Write::write(&mut writer, &buffer[off..to_fill]) {\n Ok(0) => break,\n Ok(n) => off += n,\n Err(ref e) if "
524+
"text": ", "
688525
},
689526
{
690-
"method_call": {
691-
"receiver": [
692-
{
693-
"text": "e"
694-
}
695-
],
696-
"body": [
697-
{
698-
"text": ".kind()"
699-
}
700-
]
527+
"placeholder": {
528+
"arg": 2,
529+
"access": "read"
701530
}
702531
},
703532
{
704-
"text": " == std::io::ErrorKind::Interrupted => continue,\n Err(e) => panic!(\"Unhandled error in fwrite: {e}\"),\n }\n }\n\n if off == 0 {\n break;\n }\n\n written_bytes += off;\n }\n\n "
533+
"text": ", "
705534
},
706535
{
707536
"method_call": {
708537
"receiver": [
709538
{
710-
"text": "std::io::Write::flush(&mut writer)"
539+
"placeholder": {
540+
"arg": 3,
541+
"access": "read"
542+
}
711543
}
712544
],
713545
"body": [
714546
{
715-
"text": ".expect(\"flush failed\")"
547+
"text": ".clone()"
716548
}
717549
]
718550
}
719551
},
720552
{
721-
"text": ";\n\n (written_bytes / "
722-
},
723-
{
724-
"placeholder": {
725-
"arg": 1,
726-
"access": "read"
727-
}
728-
},
729-
{
730-
"text": " as usize) as u64"
553+
"text": ")"
731554
}
732555
],
733-
"multi_statement": true,
734556
"params": {
735557
"a0": {
736558
"type": "AnyPtr"

0 commit comments

Comments
 (0)