Parse a stack slot decl. stack-slot-decl ::= * StackSlot(ss) "=" stack-slot-kind Bytes {"," stack-slot-flag} stack-slot-kind ::= "explicit_slot" | "spill_slot" | "incoming_arg" | "outgoing_arg" stack-slot-flag ::= "align" "=" Bytes | "key" "=" uimm64
(&mut self)
| 1534 | // | "outgoing_arg" |
| 1535 | // stack-slot-flag ::= "align" "=" Bytes | "key" "=" uimm64 |
| 1536 | fn parse_stack_slot_decl(&mut self) -> ParseResult<(StackSlot, StackSlotData)> { |
| 1537 | let ss = self.match_ss("expected stack slot number: ss«n»")?; |
| 1538 | self.match_token(Token::Equal, "expected '=' in stack slot declaration")?; |
| 1539 | let kind = self.match_enum("expected stack slot kind")?; |
| 1540 | |
| 1541 | // stack-slot-decl ::= StackSlot(ss) "=" stack-slot-kind * Bytes {"," stack-slot-flag} |
| 1542 | let bytes: i64 = self |
| 1543 | .match_imm64("expected byte-size in stack_slot decl")? |
| 1544 | .into(); |
| 1545 | if bytes < 0 { |
| 1546 | return err!(self.loc, "negative stack slot size"); |
| 1547 | } |
| 1548 | if bytes > i64::from(u32::MAX) { |
| 1549 | return err!(self.loc, "stack slot too large"); |
| 1550 | } |
| 1551 | |
| 1552 | let mut align = 1; |
| 1553 | let mut key = None; |
| 1554 | |
| 1555 | while self.token() == Some(Token::Comma) { |
| 1556 | self.consume(); |
| 1557 | match self.token() { |
| 1558 | Some(Token::Identifier("align")) => { |
| 1559 | self.consume(); |
| 1560 | self.match_token(Token::Equal, "expected `=` after flag")?; |
| 1561 | let align64: i64 = self |
| 1562 | .match_imm64("expected alignment-size after `align` flag")? |
| 1563 | .into(); |
| 1564 | align = u32::try_from(align64) |
| 1565 | .map_err(|_| self.error("alignment must be a 32-bit unsigned integer"))?; |
| 1566 | } |
| 1567 | Some(Token::Identifier("key")) => { |
| 1568 | self.consume(); |
| 1569 | self.match_token(Token::Equal, "expected `=` after flag")?; |
| 1570 | let value = self.match_uimm64("expected `u64` value for `key` flag")?; |
| 1571 | key = Some(StackSlotKey::new(value.into())); |
| 1572 | } |
| 1573 | _ => { |
| 1574 | return Err(self.error("invalid flag for stack slot")); |
| 1575 | } |
| 1576 | } |
| 1577 | } |
| 1578 | |
| 1579 | if !align.is_power_of_two() { |
| 1580 | return err!(self.loc, "stack slot alignment is not a power of two"); |
| 1581 | } |
| 1582 | let align_shift = u8::try_from(align.ilog2()).unwrap(); // Always succeeds: range 0..=31. |
| 1583 | |
| 1584 | let data = match key { |
| 1585 | Some(key) => StackSlotData::new_with_key(kind, bytes as u32, align_shift, key), |
| 1586 | None => StackSlotData::new(kind, bytes as u32, align_shift), |
| 1587 | }; |
| 1588 | |
| 1589 | // Collect any trailing comments. |
| 1590 | self.token(); |
| 1591 | self.claim_gathered_comments(ss); |
| 1592 | |
| 1593 | // TBD: stack-slot-decl ::= StackSlot(ss) "=" stack-slot-kind Bytes * {"," stack-slot-flag} |
no test coverage detected