|
3 | 3 | use crate::cdsl::camel_case;
|
4 | 4 | use crate::cdsl::formats::InstructionFormat;
|
5 | 5 | use crate::cdsl::instructions::{AllInstructions, Instruction};
|
6 |
| -use crate::cdsl::operands::Operand; |
| 6 | +use crate::cdsl::operands::{Operand, OperandKindFields}; |
7 | 7 | use crate::cdsl::typevar::{TypeSet, TypeVar};
|
8 | 8 | use crate::unique_table::{UniqueSeqTable, UniqueTable};
|
9 | 9 | use cranelift_codegen_shared::constant_hash;
|
@@ -159,7 +159,7 @@ fn gen_arguments_method(formats: &[Rc<InstructionFormat>], fmt: &mut Formatter,
|
159 | 159 | /// - `pub fn eq(&self, &other: Self, &pool) -> bool`
|
160 | 160 | /// - `pub fn hash<H: Hasher>(&self, state: &mut H, &pool)`
|
161 | 161 | fn gen_instruction_data_impl(formats: &[Rc<InstructionFormat>], fmt: &mut Formatter) {
|
162 |
| - fmt.add_block("impl InstructionData",|fmt| { |
| 162 | + fmt.add_block("impl InstructionData", |fmt| { |
163 | 163 | fmt.doc_comment("Get the opcode of this instruction.");
|
164 | 164 | fmt.add_block("pub fn opcode(&self) -> Opcode",|fmt| {
|
165 | 165 | let mut m = Match::new("*self");
|
@@ -413,8 +413,98 @@ fn gen_instruction_data_impl(formats: &[Rc<InstructionFormat>], fmt: &mut Format
|
413 | 413 | });
|
414 | 414 | }
|
415 | 415 | });
|
| 416 | + }); |
| 417 | + fmt.doc_comment(r#" |
| 418 | + Map some functions, described by the given `InstructionMapper`, over each of the |
| 419 | + entities within this instruction, producing a new `InstructionData`. |
| 420 | + "#); |
| 421 | + fmt.add_block("pub fn map(&self, mut mapper: impl crate::ir::instructions::InstructionMapper) -> Self", |fmt| { |
| 422 | + fmt.add_block("match *self",|fmt| { |
| 423 | + for format in formats { |
| 424 | + let name = format!("Self::{}", format.name); |
| 425 | + let mut members = vec!["opcode"]; |
| 426 | + |
| 427 | + if format.has_value_list { |
| 428 | + members.push("args"); |
| 429 | + } else if format.num_value_operands == 1 { |
| 430 | + members.push("arg"); |
| 431 | + } else if format.num_value_operands > 0 { |
| 432 | + members.push("args"); |
| 433 | + } |
| 434 | + |
| 435 | + match format.num_block_operands { |
| 436 | + 0 => {} |
| 437 | + 1 => { |
| 438 | + members.push("destination"); |
| 439 | + } |
| 440 | + _ => { |
| 441 | + members.push("blocks"); |
| 442 | + } |
| 443 | + }; |
| 444 | + |
| 445 | + for field in &format.imm_fields { |
| 446 | + members.push(field.member); |
| 447 | + } |
| 448 | + let members = members.join(", "); |
| 449 | + |
| 450 | + fmt.add_block(&format!("{name}{{{members}}} => "), |fmt| { |
| 451 | + fmt.add_block(&format!("Self::{}", format.name), |fmt| { |
| 452 | + fmtln!(fmt, "opcode,"); |
| 453 | + |
| 454 | + if format.has_value_list { |
| 455 | + fmtln!(fmt, "args: mapper.map_value_list(args),"); |
| 456 | + } else if format.num_value_operands == 1 { |
| 457 | + fmtln!(fmt, "arg: mapper.map_value(arg),"); |
| 458 | + } else if format.num_value_operands > 0 { |
| 459 | + let maps = (0..format.num_value_operands) |
| 460 | + .map(|i| format!("mapper.map_value(args[{i}])")) |
| 461 | + .collect::<Box<[_]>>() |
| 462 | + .join(", "); |
| 463 | + fmtln!(fmt, "args: [{maps}],"); |
| 464 | + } |
| 465 | + |
| 466 | + match format.num_block_operands { |
| 467 | + 0 => {} |
| 468 | + 1 => { |
| 469 | + fmtln!(fmt, "destination: mapper.map_block_call(destination),"); |
| 470 | + } |
| 471 | + 2 => { |
| 472 | + fmtln!(fmt, "blocks: [mapper.map_block_call(blocks[0]), mapper.map_block_call(blocks[1])],"); |
| 473 | + } |
| 474 | + _ => panic!("Too many block targets in instruction"), |
| 475 | + } |
| 476 | + |
| 477 | + for field in &format.imm_fields { |
| 478 | + let member = field.member; |
| 479 | + match &field.kind.fields { |
| 480 | + OperandKindFields::EntityRef => { |
| 481 | + let mut kind = heck::ToSnakeCase::to_snake_case( |
| 482 | + field |
| 483 | + .kind |
| 484 | + .rust_type |
| 485 | + .split("::") |
| 486 | + .last() |
| 487 | + .unwrap_or(field.kind.rust_type), |
| 488 | + ); |
| 489 | + if kind == "block" { |
| 490 | + kind.push_str("_call"); |
| 491 | + } |
| 492 | + fmtln!(fmt, "{member}: mapper.map_{kind}({member}),"); |
| 493 | + } |
| 494 | + OperandKindFields::VariableArgs => { |
| 495 | + fmtln!(fmt, "{member}: mapper.map_value_list({member}),"); |
| 496 | + } |
| 497 | + OperandKindFields::ImmValue | |
| 498 | + OperandKindFields::ImmEnum(_) | |
| 499 | + OperandKindFields::TypeVar(_) => fmtln!(fmt, "{member},"), |
| 500 | + } |
| 501 | + } |
| 502 | + }); |
416 | 503 | });
|
| 504 | + } |
417 | 505 | });
|
| 506 | + }); |
| 507 | + }); |
418 | 508 | }
|
419 | 509 |
|
420 | 510 | fn gen_bool_accessor<T: Fn(&Instruction) -> bool>(
|
|
0 commit comments