Parse an instruction, append it to `block`. instruction ::= [inst-results "="] Opcode(opc) ["." Type] ...
(
&mut self,
results: &[Value],
srcloc: ir::SourceLoc,
debug_tags: Vec<DebugTag>,
ctx: &mut Context,
block: Block,
)
| 2228 | // instruction ::= [inst-results "="] Opcode(opc) ["." Type] ... |
| 2229 | // |
| 2230 | fn parse_instruction( |
| 2231 | &mut self, |
| 2232 | results: &[Value], |
| 2233 | srcloc: ir::SourceLoc, |
| 2234 | debug_tags: Vec<DebugTag>, |
| 2235 | ctx: &mut Context, |
| 2236 | block: Block, |
| 2237 | ) -> ParseResult<()> { |
| 2238 | // Define the result values. |
| 2239 | for val in results { |
| 2240 | ctx.map.def_value(*val, self.loc)?; |
| 2241 | } |
| 2242 | |
| 2243 | // Collect comments for the next instruction. |
| 2244 | self.start_gathering_comments(); |
| 2245 | |
| 2246 | // instruction ::= [inst-results "="] * Opcode(opc) ["." Type] ... |
| 2247 | let opcode = if let Some(Token::Identifier(text)) = self.token() { |
| 2248 | match text.parse() { |
| 2249 | Ok(opc) => opc, |
| 2250 | Err(msg) => return err!(self.loc, "{}: '{}'", msg, text), |
| 2251 | } |
| 2252 | } else { |
| 2253 | return err!(self.loc, "expected instruction opcode"); |
| 2254 | }; |
| 2255 | let opcode_loc = self.loc; |
| 2256 | self.consume(); |
| 2257 | |
| 2258 | // Look for a controlling type variable annotation. |
| 2259 | // instruction ::= [inst-results "="] Opcode(opc) * ["." Type] ... |
| 2260 | let explicit_ctrl_type = if self.optional(Token::Dot) { |
| 2261 | if let Some(Token::Type(_t)) = self.token() { |
| 2262 | Some(self.match_type("expected type after 'opcode.'")?) |
| 2263 | } else { |
| 2264 | let dt = self.match_dt("expected dynamic type")?; |
| 2265 | self.concrete_from_dt(dt, ctx) |
| 2266 | } |
| 2267 | } else { |
| 2268 | None |
| 2269 | }; |
| 2270 | |
| 2271 | // instruction ::= [inst-results "="] Opcode(opc) ["." Type] * ... |
| 2272 | let inst_data = self.parse_inst_operands(ctx, opcode, explicit_ctrl_type)?; |
| 2273 | |
| 2274 | let ctrl_typevar = self.infer_typevar(ctx, opcode, explicit_ctrl_type, &inst_data)?; |
| 2275 | let inst = ctx.function.dfg.make_inst(inst_data); |
| 2276 | |
| 2277 | // Attach stack map, if present. |
| 2278 | if self.optional(Token::Comma) { |
| 2279 | self.match_token( |
| 2280 | Token::Identifier("stack_map"), |
| 2281 | "expected `stack_map = [...]`", |
| 2282 | )?; |
| 2283 | if !opcode.is_call() || opcode.is_return() { |
| 2284 | return err!( |
| 2285 | self.loc, |
| 2286 | "stack map can only be attached to a (non-tail) call" |
| 2287 | ); |
no test coverage detected