Coverage Report

Created: 2021-03-22 08:29

/src/regalloc.rs/bin/parser.rs
Line
Count
Source (jump to first uncovered line)
1
#![allow(unused_imports)]
2
3
use std::collections::HashMap;
4
use std::fs::File;
5
use std::io;
6
use std::io::prelude::*;
7
use std::iter::Peekable;
8
use std::path::{Path, PathBuf};
9
use std::str;
10
use std::str::CharIndices;
11
12
use regalloc::{Reg, RegClass};
13
14
use crate::test_framework::*;
15
16
pub(crate) const REFTYPE_START: &'static str = "reftype_start";
17
18
#[derive(Debug)]
19
pub enum ParseError {
20
    IoError(io::Error),
21
    Parse(String),
22
}
23
24
impl From<io::Error> for ParseError {
25
    fn from(err: io::Error) -> ParseError {
26
        ParseError::IoError(err)
27
    }
28
}
29
30
pub type ParseResult<T> = Result<T, ParseError>;
31
32
0
pub fn parse_file(path: PathBuf) -> ParseResult<Func> {
33
0
    let basename = path.file_stem().unwrap().to_str().unwrap().to_string();
34
0
    let mut file = File::open(path)?;
35
0
    let mut content = String::new();
36
0
    file.read_to_string(&mut content)?;
37
0
    parse_content(&basename, &content)
38
0
}
39
40
struct Parser<'f, 'str> {
41
    func: &'f mut Func,
42
    vars: HashMap<String, Reg>,
43
44
    source: &'str str,
45
    iter: Peekable<CharIndices<'str>>,
46
    line: usize,
47
    start: usize,
48
    current: usize,
49
}
50
51
impl<'f, 'str> Parser<'f, 'str> {
52
    fn new(func: &'f mut Func, source: &'str str) -> Self {
53
        let iter = source.char_indices().peekable();
54
        Self {
55
            func,
56
            start: 0,
57
            current: 0,
58
            line: 1,
59
            vars: HashMap::new(),
60
            iter,
61
            source,
62
        }
63
    }
64
65
    // Environment.
66
0
    fn define_virtual_var(&mut self, name: &str, reg_class: RegClass) -> ParseResult<()> {
67
0
        if let Some(_) = self
68
0
            .vars
69
0
            .insert(name.into(), self.func.new_virtual_reg(reg_class))
70
        {
71
0
            self.error("duplicate variable declaration")
72
        } else {
73
0
            Ok(())
74
        }
75
0
    }
76
77
0
    fn define_real_var(&mut self, name: &str, reg_class: RegClass, index: u8) -> ParseResult<()> {
78
0
        if let Some(_) = self
79
0
            .vars
80
0
            .insert(name.into(), Reg::new_real(reg_class, 0x0, index))
81
        {
82
0
            self.error("duplicate variable declaration")
83
        } else {
84
0
            Ok(())
85
        }
86
0
    }
87
88
    fn var(&mut self, name: &str) -> Option<Reg> {
89
        self.vars.get(name).cloned()
90
    }
91
92
    fn define_block(&mut self, block_name: String, insts: Vec<Inst>) {
93
        self.func.block(&block_name, insts);
94
    }
95
96
    // Parsing.
97
    fn peek(&mut self) -> Option<char> {
98
0
        if let Some((_, c)) = self.iter.peek() {
99
0
            Some(*c)
100
        } else {
101
0
            None
102
        }
103
0
    }
104
105
0
    fn peek_next(&self) -> Option<char> {
106
0
        let mut clone = self.iter.clone();
107
0
        if let Some(_) = clone.next() {
108
0
            if let Some((_, c)) = clone.peek() {
109
0
                return Some(*c);
110
0
            }
111
0
        }
112
0
        None
113
0
    }
114
115
    fn advance(&mut self) -> Option<char> {
116
0
        if let Some((i, ch)) = self.iter.next() {
117
0
            self.current = i;
118
0
            Some(ch)
119
        } else {
120
0
            None
121
        }
122
0
    }
123
124
    // Higher level parsing.
125
    fn skip_whitespace_and_comments(&mut self) {
126
0
        while let Some(c) = self.peek() {
127
0
            if c == ' ' || c == '\t' || c == '\r' || c == '\n' {
128
                // Skip whitespace.
129
0
                self.advance().unwrap();
130
0
                if c == '\n' {
131
0
                    self.line += 1;
132
0
                }
133
0
            } else if c == ';' {
134
                // It's a comment! skip until the end of line.
135
0
                self.advance().unwrap();
136
0
                while let Some(c) = self.advance() {
137
0
                    if c == '\n' {
138
0
                        self.line += 1;
139
0
                        break;
140
0
                    }
141
                }
142
            } else {
143
0
                break;
144
            }
145
        }
146
0
    }
147
148
0
    fn read_char(&mut self) -> ParseResult<char> {
149
0
        self.skip_whitespace_and_comments();
150
0
        if let Some(c) = self.advance() {
151
0
            Ok(c)
152
        } else {
153
0
            self.error("expected char")
154
        }
155
0
    }
156
157
0
    fn try_read_char(&mut self, expected: char) -> Option<char> {
158
0
        self.skip_whitespace_and_comments();
159
0
        if let Some(c) = self.peek() {
160
0
            if c == expected {
161
0
                self.advance().unwrap();
162
0
                return Some(c);
163
0
            }
164
0
        }
165
0
        None
166
0
    }
167
168
0
    fn try_read_ident_sameline(&mut self) -> Option<String> {
169
        // Only ignore simple spaces.
170
0
        while let Some(c) = self.peek() {
171
0
            if c == ' ' {
172
0
                self.advance().unwrap();
173
0
            } else {
174
0
                break;
175
            }
176
        }
177
178
0
        if let Some(c) = self.peek() {
179
0
            if !is_alpha(c) {
180
0
                return None;
181
0
            }
182
0
            self.advance().unwrap();
183
        } else {
184
0
            return None;
185
        }
186
187
0
        self.start = self.current;
188
0
        while let Some(c) = self.peek() {
189
0
            if !is_alpha_numeric(c) {
190
0
                break;
191
0
            }
192
0
            self.advance().unwrap();
193
        }
194
195
0
        let substr = str::from_utf8(&self.source.as_bytes()[self.start..self.current + 1]).unwrap();
196
0
        Some(substr.to_string())
197
0
    }
198
199
    fn try_read_ident(&mut self) -> Option<String> {
200
        self.skip_whitespace_and_comments();
201
        self.try_read_ident_sameline()
202
    }
203
204
    fn read_ident(&mut self) -> ParseResult<String> {
205
0
        if let Some(string) = self.try_read_ident() {
206
0
            Ok(string)
207
        } else {
208
0
            self.error("expected identifier or keyword")
209
        }
210
0
    }
211
212
0
    fn read_block(&mut self) -> ParseResult<String> {
213
0
        let block_name = self.read_ident()?;
214
0
        if let Some(':') = self.peek() {
215
0
            self.advance().unwrap();
216
            // Ignore the block's name.
217
0
            self.read_ident()?;
218
0
        }
219
0
        Ok(block_name)
220
0
    }
221
222
0
    fn read_string(&mut self) -> ParseResult<&str> {
223
0
        self.skip_whitespace_and_comments();
224
0
        if let Some('"') = self.advance() {
225
0
            // All good!
226
0
        } else {
227
0
            return self.error("expected opening \"");
228
        }
229
0
        self.start = self.current;
230
0
        while let Some(c) = self.peek() {
231
0
            if c == '\n' {
232
0
                self.line += 1;
233
0
            }
234
0
            self.advance().unwrap();
235
0
            if c == '"' {
236
0
                let substr =
237
0
                    str::from_utf8(&self.source.as_bytes()[self.start + 1..self.current]).unwrap();
238
0
                return Ok(substr);
239
0
            }
240
        }
241
0
        self.error("unterminated string")
242
0
    }
243
244
0
    fn try_read_number(&mut self) -> ParseResult<Option<f64>> {
245
0
        self.skip_whitespace_and_comments();
246
0
247
0
        let mut is_negative = false;
248
0
        if let Some('-') = self.peek() {
249
0
            // Consume the minus sign.
250
0
            self.advance().unwrap();
251
0
            is_negative = true;
252
0
        }
253
254
0
        let first_digit = if let Some(c) = self.peek() {
255
            // A regular number.
256
0
            if is_digit(c) {
257
0
                self.advance().unwrap();
258
0
                c
259
0
            } else if c == 'i' {
260
0
                self.advance().unwrap();
261
                // This must be inf.
262
0
                self.expect_char('n')?;
263
0
                self.expect_char('f')?;
264
0
                let mut result = std::f64::INFINITY;
265
0
                if is_negative {
266
0
                    result = -result;
267
0
                }
268
0
                return Ok(Some(result));
269
0
            } else if c == 'N' {
270
                // This must be NaN.
271
0
                self.advance().unwrap();
272
0
                self.expect_char('a')?;
273
0
                self.expect_char('N')?;
274
0
                let mut result = std::f64::NAN;
275
0
                if is_negative {
276
0
                    result = -result;
277
0
                }
278
0
                return Ok(Some(result));
279
0
            } else if is_negative {
280
                // We saw a minus sign, we should have had something after it.
281
0
                return self.error("expected a valid number after minus sign");
282
            } else {
283
0
                return Ok(None);
284
            }
285
0
        } else if is_negative {
286
            // We saw a minus sign, we should have had something after it.
287
0
            return self.error("expected something after minus sign");
288
        } else {
289
0
            return Ok(None);
290
        };
291
292
0
        let mut number = first_digit.to_digit(10).unwrap() as f64;
293
0
        let mut fractional_power_of_ten: Option<f64> = None;
294
0
        while let Some(c) = self.peek() {
295
0
            if is_digit(c) {
296
0
                self.advance().unwrap();
297
0
                let c_num = c.to_digit(10).unwrap() as f64;
298
0
                if let Some(decimal) = fractional_power_of_ten.as_mut() {
299
0
                    number += c_num * *decimal;
300
0
                    *decimal /= 10.0;
301
0
                } else {
302
0
                    number *= 10.0;
303
0
                    number += c_num;
304
0
                }
305
0
            } else if c == '.' {
306
0
                if let Some(d) = self.peek_next() {
307
0
                    if is_digit(d) {
308
0
                        self.advance().unwrap();
309
0
                        if fractional_power_of_ten.is_some() {
310
0
                            return self.error("unexpected dot in number")?;
311
0
                        }
312
0
                        fractional_power_of_ten = Some(0.1);
313
                        continue;
314
0
                    }
315
0
                }
316
0
                break;
317
            } else {
318
0
                break;
319
            }
320
        }
321
322
0
        if is_negative {
323
0
            number = -number;
324
0
        }
325
326
0
        Ok(Some(number))
327
0
    }
328
0
    fn read_number(&mut self) -> ParseResult<f64> {
329
0
        Ok(self.try_read_number()?.expect("expected number"))
330
0
    }
331
332
0
    fn try_read_int(&mut self) -> ParseResult<Option<u32>> {
333
0
        if let Some(value) = self.try_read_number()? {
334
0
            let as_int = value as u32;
335
0
            let as_float_back = as_int as f64;
336
0
            if as_float_back != value {
337
0
                self.error("expected an integer, got a double")
338
            } else {
339
0
                Ok(Some(as_int))
340
            }
341
        } else {
342
0
            Ok(None)
343
        }
344
0
    }
345
0
    fn read_int(&mut self) -> ParseResult<u32> {
346
0
        Ok(self.try_read_int()?.expect("expected integer"))
347
0
    }
348
349
    fn try_read_var(&mut self) -> ParseResult<Option<Reg>> {
350
0
        if let Some(ident) = self.try_read_ident() {
351
0
            if let Some(reg) = self.vars.get(&ident) {
352
0
                Ok(Some(*reg))
353
            } else {
354
0
                self.error("expected variable")
355
            }
356
        } else {
357
0
            Ok(None)
358
        }
359
0
    }
360
0
    fn read_var(&mut self) -> ParseResult<Reg> {
361
0
        Ok(self.try_read_var()?.expect("expected var"))
362
0
    }
363
364
0
    fn to_reg_class(&self, ident: &str) -> ParseResult<RegClass> {
365
0
        if ident == "i32" || ident == "I32" {
366
0
            Ok(RegClass::I32)
367
0
        } else if ident == "f32" || ident == "F32" {
368
0
            Ok(RegClass::F32)
369
        } else {
370
0
            self.error("unknown register class")
371
        }
372
0
    }
373
374
0
    fn read_ri(&mut self) -> ParseResult<RI> {
375
0
        if let Some(reg) = self.try_read_var()? {
376
0
            Ok(RI_R(reg))
377
        } else {
378
0
            let int = self.read_int()?;
379
0
            Ok(RI_I(int))
380
        }
381
0
    }
382
383
    fn read_am(&mut self) -> ParseResult<AM> {
384
        // Either RR or RI. As a shortcut, allow R, meaning RI with 0 offset.
385
0
        self.expect_char('[')?;
386
0
        let base = self.read_var()?;
387
0
        let am = if let Some(_) = self.try_read_char(',') {
388
0
            if let Some(disp) = self.try_read_var()? {
389
0
                AM_RR(base, disp)
390
            } else {
391
0
                let offset = self.read_int()?;
392
0
                AM_RI(base, offset)
393
            }
394
        } else {
395
0
            AM_R(base)
396
        };
397
0
        self.expect_char(']')?;
398
0
        Ok(am)
399
0
    }
400
401
0
    fn expect_char(&mut self, expected: char) -> ParseResult<()> {
402
0
        let c = self.read_char()?;
403
0
        if c != expected {
404
0
            self.error(&format!("expected char '{}'", expected))
405
        } else {
406
0
            Ok(())
407
        }
408
0
    }
409
410
    fn is_done(&mut self) -> bool {
411
        self.skip_whitespace_and_comments();
412
        self.peek().is_none()
413
    }
414
415
    fn error<T>(&self, msg: &str) -> ParseResult<T> {
416
        Err(ParseError::Parse(format!(
417
            "error at line {}: {}",
418
            self.line, msg
419
        )))
420
    }
421
}
422
423
0
pub fn parse_content(func_name: &str, content: &str) -> ParseResult<Func> {
424
0
    let mut func = Func::new(func_name);
425
0
426
0
    let mut parser = Parser::new(&mut func, content);
427
428
    // Look for variable declarations.
429
    let mut name;
430
    loop {
431
0
        name = parser.read_ident()?;
432
0
        let c = parser.read_char()?;
433
0
        if &name == REFTYPE_START && c == '=' {
434
0
            let index = parser.read_int()?;
435
0
            parser.func.reftype_reg_start = Some(index);
436
0
        } else if c == '=' {
437
            // variable declaration.
438
0
            let real_or_class = parser.read_ident()?;
439
0
            if real_or_class == "real" {
440
0
                let class = parser.read_ident()?;
441
0
                let reg_class = parser.to_reg_class(&class)?;
442
0
                let index = parser.read_int()?;
443
0
                if index > 255 {
444
0
                    return parser.error("expected u8");
445
0
                }
446
0
                parser.define_real_var(&name, reg_class, index as u8)?;
447
            } else {
448
0
                let reg_class = parser.to_reg_class(&real_or_class)?;
449
0
                parser.define_virtual_var(&name, reg_class)?;
450
            }
451
0
        } else if c == ':' {
452
            // first block declaration!
453
0
            break;
454
        } else {
455
0
            return parser.error("expected = or :");
456
        }
457
    }
458
459
0
    parser.func.set_entry(&name);
460
0
    let mut next_block_name = Some(name);
461
462
    // Look for blocks (name already contains the name of the first block).
463
0
    loop {
464
0
        let mut insts = Vec::new();
465
0
        let block_name = next_block_name;
466
467
        // Look for instructions.
468
0
        loop {
469
0
            // Either:
470
0
            // - nothing (empty block, no more blocks thereafter).
471
0
            // - instruction (name, maybe operands).
472
0
            // - next block.
473
0
            if parser.is_done() {
474
0
                next_block_name = None;
475
0
                break;
476
0
            }
477
478
0
            let inst_or_block_name = parser.read_ident()?;
479
0
            match inst_or_block_name.as_str() {
480
0
                "add" => {
481
0
                    let dst = parser.read_var()?;
482
0
                    parser.expect_char(',')?;
483
0
                    let src = parser.read_var()?;
484
0
                    parser.expect_char(',')?;
485
0
                    let op = parser.read_ri()?;
486
0
                    insts.push(i_add(dst, src, op));
487
                }
488
489
0
                "addm" => {
490
0
                    let dst = parser.read_var()?;
491
0
                    parser.expect_char(',')?;
492
0
                    let src = parser.read_ri()?;
493
0
                    insts.push(i_addm(dst, src));
494
                }
495
496
0
                "and" => {
497
0
                    let dst = parser.read_var()?;
498
0
                    parser.expect_char(',')?;
499
0
                    let src = parser.read_var()?;
500
0
                    parser.expect_char(',')?;
501
0
                    let op = parser.read_ri()?;
502
0
                    insts.push(i_and(dst, src, op));
503
                }
504
505
0
                "andm" => {
506
0
                    let dst = parser.read_var()?;
507
0
                    parser.expect_char(',')?;
508
0
                    let src = parser.read_ri()?;
509
0
                    insts.push(i_andm(dst, src));
510
                }
511
512
0
                "copy" => {
513
0
                    let dst = parser.read_var()?;
514
0
                    parser.expect_char(',')?;
515
0
                    let src = parser.read_var()?;
516
0
                    insts.push(i_copy(dst, src));
517
                }
518
519
0
                "copyf" => {
520
0
                    let dst = parser.read_var()?;
521
0
                    parser.expect_char(',')?;
522
0
                    let src = parser.read_var()?;
523
0
                    insts.push(i_copyf(dst, src));
524
                }
525
526
0
                "cmp_eq" => {
527
0
                    let dst = parser.read_var()?;
528
0
                    parser.expect_char(',')?;
529
0
                    let src = parser.read_var()?;
530
0
                    parser.expect_char(',')?;
531
0
                    let ri = parser.read_ri()?;
532
0
                    insts.push(i_cmp_eq(dst, src, ri));
533
                }
534
535
0
                "cmp_eqm" => {
536
0
                    let dst = parser.read_var()?;
537
0
                    parser.expect_char(',')?;
538
0
                    let ri = parser.read_ri()?;
539
0
                    insts.push(i_cmp_eqm(dst, ri));
540
                }
541
542
0
                "cmp_gem" => {
543
0
                    let dst = parser.read_var()?;
544
0
                    parser.expect_char(',')?;
545
0
                    let ri = parser.read_ri()?;
546
0
                    insts.push(i_cmp_gem(dst, ri));
547
                }
548
549
0
                "cmp_gtm" => {
550
0
                    let dst = parser.read_var()?;
551
0
                    parser.expect_char(',')?;
552
0
                    let ri = parser.read_ri()?;
553
0
                    insts.push(i_cmp_gtm(dst, ri));
554
                }
555
556
0
                "cmp_ge" => {
557
0
                    let dst = parser.read_var()?;
558
0
                    parser.expect_char(',')?;
559
0
                    let src = parser.read_var()?;
560
0
                    parser.expect_char(',')?;
561
0
                    let ri = parser.read_ri()?;
562
0
                    insts.push(i_cmp_ge(dst, src, ri));
563
                }
564
565
0
                "cmp_gt" => {
566
0
                    let dst = parser.read_var()?;
567
0
                    parser.expect_char(',')?;
568
0
                    let src = parser.read_var()?;
569
0
                    parser.expect_char(',')?;
570
0
                    let ri = parser.read_ri()?;
571
0
                    insts.push(i_cmp_gt(dst, src, ri));
572
                }
573
574
0
                "cmp_lem" => {
575
0
                    let dst = parser.read_var()?;
576
0
                    parser.expect_char(',')?;
577
0
                    let ri = parser.read_ri()?;
578
0
                    insts.push(i_cmp_lem(dst, ri));
579
                }
580
581
0
                "cmp_ltm" => {
582
0
                    let dst = parser.read_var()?;
583
0
                    parser.expect_char(',')?;
584
0
                    let ri = parser.read_ri()?;
585
0
                    insts.push(i_cmp_ltm(dst, ri));
586
                }
587
588
0
                "cmp_le" => {
589
0
                    let dst = parser.read_var()?;
590
0
                    parser.expect_char(',')?;
591
0
                    let src = parser.read_var()?;
592
0
                    parser.expect_char(',')?;
593
0
                    let ri = parser.read_ri()?;
594
0
                    insts.push(i_cmp_le(dst, src, ri));
595
                }
596
597
0
                "cmp_lt" => {
598
0
                    let dst = parser.read_var()?;
599
0
                    parser.expect_char(',')?;
600
0
                    let src = parser.read_var()?;
601
0
                    parser.expect_char(',')?;
602
0
                    let ri = parser.read_ri()?;
603
0
                    insts.push(i_cmp_lt(dst, src, ri));
604
                }
605
606
0
                "fadd" => {
607
0
                    let dst = parser.read_var()?;
608
0
                    parser.expect_char(',')?;
609
0
                    let src_left = parser.read_var()?;
610
0
                    parser.expect_char(',')?;
611
0
                    let src_right = parser.read_var()?;
612
0
                    insts.push(i_fadd(dst, src_left, src_right));
613
                }
614
615
0
                "fdiv" => {
616
0
                    let dst = parser.read_var()?;
617
0
                    parser.expect_char(',')?;
618
0
                    let src_left = parser.read_var()?;
619
0
                    parser.expect_char(',')?;
620
0
                    let src_right = parser.read_var()?;
621
0
                    insts.push(i_fdiv(dst, src_left, src_right));
622
                }
623
624
0
                "fmul" => {
625
0
                    let dst = parser.read_var()?;
626
0
                    parser.expect_char(',')?;
627
0
                    let src_left = parser.read_var()?;
628
0
                    parser.expect_char(',')?;
629
0
                    let src_right = parser.read_var()?;
630
0
                    insts.push(i_fmul(dst, src_left, src_right));
631
                }
632
633
0
                "fsub" => {
634
0
                    let dst = parser.read_var()?;
635
0
                    parser.expect_char(',')?;
636
0
                    let src_left = parser.read_var()?;
637
0
                    parser.expect_char(',')?;
638
0
                    let src_right = parser.read_var()?;
639
0
                    insts.push(i_fsub(dst, src_left, src_right));
640
                }
641
642
0
                "finish" => {
643
0
                    let return_val = parser
644
0
                        .try_read_ident_sameline()
645
0
                        .and_then(|var_name| parser.var(&var_name));
646
0
                    insts.push(i_finish(return_val));
647
0
                }
648
649
0
                "goto" => {
650
0
                    let target = parser.read_block()?;
651
0
                    insts.push(i_goto(&target));
652
                }
653
654
0
                "if_then_else" => {
655
0
                    let test_var = parser.read_var()?;
656
0
                    parser.expect_char(',')?;
657
0
                    let then_block = parser.read_block()?;
658
0
                    parser.expect_char(',')?;
659
0
                    let else_block = parser.read_block()?;
660
0
                    insts.push(i_goto_ctf(test_var, &then_block, &else_block));
661
                }
662
663
0
                "imm" => {
664
0
                    let dst = parser.read_var()?;
665
0
                    parser.expect_char(',')?;
666
0
                    let value = parser.read_int()?;
667
0
                    insts.push(i_imm(dst, value));
668
                }
669
670
0
                "immf" => {
671
0
                    let dst = parser.read_var()?;
672
0
                    parser.expect_char(',')?;
673
0
                    let value = parser.read_number()?;
674
0
                    insts.push(i_immf(dst, value as f32));
675
                }
676
677
0
                "load" => {
678
0
                    let dst = parser.read_var()?;
679
0
                    parser.expect_char(',')?;
680
0
                    let addr = parser.read_am()?;
681
0
                    insts.push(i_load(dst, addr));
682
                }
683
684
0
                "loadf" => {
685
0
                    let dst = parser.read_var()?;
686
0
                    parser.expect_char(',')?;
687
0
                    let addr = parser.read_am()?;
688
0
                    insts.push(i_loadf(dst, addr));
689
                }
690
691
0
                "mod" => {
692
0
                    let dst = parser.read_var()?;
693
0
                    parser.expect_char(',')?;
694
0
                    let src_left = parser.read_var()?;
695
0
                    parser.expect_char(',')?;
696
0
                    let src_right = parser.read_ri()?;
697
0
                    insts.push(i_mod(dst, src_left, src_right));
698
                }
699
700
0
                "modm" => {
701
0
                    let dst = parser.read_var()?;
702
0
                    parser.expect_char(',')?;
703
0
                    let src_right = parser.read_ri()?;
704
0
                    insts.push(i_modm(dst, src_right));
705
                }
706
707
0
                "mul" => {
708
0
                    let dst = parser.read_var()?;
709
0
                    parser.expect_char(',')?;
710
0
                    let src_left = parser.read_var()?;
711
0
                    parser.expect_char(',')?;
712
0
                    let src_right = parser.read_ri()?;
713
0
                    insts.push(i_mul(dst, src_left, src_right));
714
                }
715
716
0
                "mulm" => {
717
0
                    let dst = parser.read_var()?;
718
0
                    parser.expect_char(',')?;
719
0
                    let src_right = parser.read_ri()?;
720
0
                    insts.push(i_mulm(dst, src_right));
721
                }
722
723
0
                "shr" => {
724
0
                    let dst = parser.read_var()?;
725
0
                    parser.expect_char(',')?;
726
0
                    let src_left = parser.read_var()?;
727
0
                    parser.expect_char(',')?;
728
0
                    let src_right = parser.read_ri()?;
729
0
                    insts.push(i_shr(dst, src_left, src_right));
730
                }
731
732
0
                "shrm" => {
733
0
                    let dst = parser.read_var()?;
734
0
                    parser.expect_char(',')?;
735
0
                    let src_right = parser.read_ri()?;
736
0
                    insts.push(i_shrm(dst, src_right));
737
                }
738
739
0
                "store" => {
740
0
                    let addr = parser.read_am()?;
741
0
                    parser.expect_char(',')?;
742
0
                    let src = parser.read_var()?;
743
0
                    insts.push(i_store(addr, src));
744
                }
745
746
0
                "storef" => {
747
0
                    let addr = parser.read_am()?;
748
0
                    parser.expect_char(',')?;
749
0
                    let src = parser.read_var()?;
750
0
                    insts.push(i_storef(addr, src));
751
                }
752
753
0
                "makeref" => {
754
0
                    let dst = parser.read_var()?;
755
0
                    parser.expect_char(',')?;
756
0
                    let src = parser.read_var()?;
757
0
                    insts.push(Inst::MakeRef { dst, src });
758
                }
759
760
0
                "useref" => {
761
0
                    let dst = parser.read_var()?;
762
0
                    parser.expect_char(',')?;
763
0
                    let src = parser.read_var()?;
764
0
                    insts.push(Inst::UseRef { dst, src });
765
                }
766
767
0
                "safepoint" => {
768
0
                    insts.push(Inst::Safepoint);
769
0
                }
770
771
0
                "sub" => {
772
0
                    let dst = parser.read_var()?;
773
0
                    parser.expect_char(',')?;
774
0
                    let src_left = parser.read_var()?;
775
0
                    parser.expect_char(',')?;
776
0
                    let src_right = parser.read_ri()?;
777
0
                    insts.push(i_sub(dst, src_left, src_right));
778
                }
779
780
0
                "subm" => {
781
0
                    let dst = parser.read_var()?;
782
0
                    parser.expect_char(',')?;
783
0
                    let src_right = parser.read_ri()?;
784
0
                    insts.push(i_subm(dst, src_right));
785
                }
786
787
0
                "printi" => {
788
0
                    let reg = parser.read_var()?;
789
0
                    insts.push(i_print_i(reg));
790
                }
791
792
0
                "prints" => {
793
0
                    let string = parser.read_string()?;
794
0
                    insts.push(i_print_s(string));
795
                }
796
797
0
                "println" => {
798
0
                    let string = parser.read_string()?;
799
0
                    insts.push(i_print_s(&format!("{}\n", string)));
800
                }
801
802
                _ => {
803
0
                    next_block_name = Some(inst_or_block_name);
804
0
                    break;
805
                }
806
            }
807
        }
808
809
0
        if let Some(block_name) = block_name {
810
0
            parser.define_block(block_name, insts);
811
0
        }
812
813
0
        if parser.is_done() {
814
0
            break;
815
0
        }
816
817
0
        if parser.read_char()? != ':' {
818
0
            return parser
819
0
                .error("expected : after possible block name, or unexpected instruction name");
820
0
        }
821
    }
822
823
0
    func.finish();
824
0
    Ok(func)
825
0
}
826
827
fn is_digit(c: char) -> bool {
828
    c >= '0' && c <= '9'
829
}
830
831
fn is_alpha(c: char) -> bool {
832
    c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' || c == '-'
833
}
834
835
fn is_alpha_numeric(c: char) -> bool {
836
    is_digit(c) || is_alpha(c)
837
}