Emit a method for creating and inserting an instruction format. All instruction formats take an `opcode` argument and a `ctrl_typevar` argument for deducing the result types.
(format: &InstructionFormat, fmt: &mut Formatter)
| 1040 | /// All instruction formats take an `opcode` argument and a `ctrl_typevar` argument for deducing |
| 1041 | /// the result types. |
| 1042 | fn gen_format_constructor(format: &InstructionFormat, fmt: &mut Formatter) { |
| 1043 | // Construct method arguments. |
| 1044 | let mut args = vec![ |
| 1045 | "self".to_string(), |
| 1046 | "opcode: Opcode".into(), |
| 1047 | "ctrl_typevar: Type".into(), |
| 1048 | ]; |
| 1049 | |
| 1050 | // Raw block operands. |
| 1051 | args.extend((0..format.num_raw_block_operands).map(|i| format!("block{i}: ir::Block"))); |
| 1052 | |
| 1053 | // Normal operand arguments. Start with the immediate operands. |
| 1054 | for f in &format.imm_fields { |
| 1055 | args.push(format!("{}: {}", f.member, f.kind.rust_type)); |
| 1056 | } |
| 1057 | |
| 1058 | // Then the block operands. |
| 1059 | args.extend((0..format.num_block_operands).map(|i| format!("block{i}: ir::BlockCall"))); |
| 1060 | |
| 1061 | // Then the value operands. |
| 1062 | if format.has_value_list { |
| 1063 | // Take all value arguments as a finished value list. The value lists |
| 1064 | // are created by the individual instruction constructors. |
| 1065 | args.push("args: ir::ValueList".into()); |
| 1066 | } else { |
| 1067 | // Take a fixed number of value operands. |
| 1068 | for i in 0..format.num_value_operands { |
| 1069 | args.push(format!("arg{i}: Value")); |
| 1070 | } |
| 1071 | } |
| 1072 | |
| 1073 | let proto = format!( |
| 1074 | "{}({}) -> (Inst, &'f mut ir::DataFlowGraph)", |
| 1075 | format.name, |
| 1076 | args.join(", ") |
| 1077 | ); |
| 1078 | |
| 1079 | let imms_need_masking = format |
| 1080 | .imm_fields |
| 1081 | .iter() |
| 1082 | .any(|f| f.kind.rust_type == "ir::immediates::Imm64"); |
| 1083 | |
| 1084 | fmt.doc_comment(format.to_string()); |
| 1085 | fmt.line("#[allow(non_snake_case, reason = \"generated code\")]"); |
| 1086 | fmt.add_block(&format!("fn {proto}"), |fmt| { |
| 1087 | // Generate the instruction data. |
| 1088 | fmt.add_block(&format!( |
| 1089 | "let{} data = ir::InstructionData::{}", |
| 1090 | if imms_need_masking { " mut" } else { "" }, |
| 1091 | format.name |
| 1092 | ), |fmt| { |
| 1093 | fmt.line("opcode,"); |
| 1094 | gen_member_inits(format, fmt); |
| 1095 | }); |
| 1096 | fmtln!(fmt, ";"); |
| 1097 | |
| 1098 | if imms_need_masking { |
| 1099 | fmtln!(fmt, "data.mask_immediates(ctrl_typevar);"); |
no test coverage detected