Auto-generate InstructionData.
The meta description has all the information to generate the `InstructionData` enum, so generate it rather than having a manually-maintained copy.
This commit is contained in:
@@ -103,6 +103,38 @@ def gen_arguments_method(fmt, is_mut):
|
||||
.format(n, capture, arg))
|
||||
|
||||
|
||||
def gen_instruction_data(fmt):
|
||||
# type: (srcgen.Formatter) -> None
|
||||
"""
|
||||
Generate the InstructionData enum.
|
||||
|
||||
Every variant must contain `opcode` and `ty` fields. An instruction that
|
||||
doesn't produce a value should have its `ty` field set to `VOID`. The size
|
||||
of `InstructionData` should be kept at 16 bytes on 64-bit architectures. If
|
||||
more space is needed to represent an instruction, use a `Box<AuxData>` to
|
||||
store the additional information out of line.
|
||||
"""
|
||||
|
||||
fmt.line('#[derive(Clone, Debug, Hash, PartialEq, Eq)]')
|
||||
fmt.line('#[allow(missing_docs)]')
|
||||
with fmt.indented('pub enum InstructionData {', '}'):
|
||||
for f in InstructionFormat.all_formats:
|
||||
with fmt.indented('{} {{'.format(f.name), '},'):
|
||||
fmt.line('opcode: Opcode,')
|
||||
if f.typevar_operand is None:
|
||||
pass
|
||||
elif f.has_value_list:
|
||||
fmt.line('args: ValueList,')
|
||||
elif f.num_value_operands == 1:
|
||||
fmt.line('arg: Value,')
|
||||
else:
|
||||
fmt.line('args: [Value; {}],'.format(f.num_value_operands))
|
||||
for field in f.imm_fields:
|
||||
fmt.line(
|
||||
'{}: {},'
|
||||
.format(field.member, field.kind.rust_type))
|
||||
|
||||
|
||||
def gen_instruction_data_impl(fmt):
|
||||
# type: (srcgen.Formatter) -> None
|
||||
"""
|
||||
@@ -682,6 +714,8 @@ def generate(isas, out_dir):
|
||||
# opcodes.rs
|
||||
fmt = srcgen.Formatter()
|
||||
gen_formats(fmt)
|
||||
gen_instruction_data(fmt)
|
||||
fmt.line()
|
||||
gen_instruction_data_impl(fmt)
|
||||
fmt.line()
|
||||
instrs = gen_opcodes(groups, fmt)
|
||||
|
||||
@@ -11,11 +11,9 @@ use std::str::FromStr;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use ir;
|
||||
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags};
|
||||
use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32};
|
||||
use ir::condcodes::*;
|
||||
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef};
|
||||
use ir::types;
|
||||
use isa::RegUnit;
|
||||
use isa;
|
||||
|
||||
use entity;
|
||||
use bitset::BitSet;
|
||||
@@ -94,190 +92,6 @@ impl FromStr for Opcode {
|
||||
}
|
||||
}
|
||||
|
||||
/// Contents on an instruction.
|
||||
///
|
||||
/// Every variant must contain `opcode` and `ty` fields. An instruction that doesn't produce a
|
||||
/// value should have its `ty` field set to `VOID`. The size of `InstructionData` should be kept at
|
||||
/// 16 bytes on 64-bit architectures. If more space is needed to represent an instruction, use a
|
||||
/// `Box<AuxData>` to store the additional information out of line.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum InstructionData {
|
||||
Unary { opcode: Opcode, arg: Value },
|
||||
UnaryImm { opcode: Opcode, imm: Imm64 },
|
||||
UnaryIeee32 { opcode: Opcode, imm: Ieee32 },
|
||||
UnaryIeee64 { opcode: Opcode, imm: Ieee64 },
|
||||
UnaryBool { opcode: Opcode, imm: bool },
|
||||
UnaryGlobalVar {
|
||||
opcode: Opcode,
|
||||
global_var: ir::GlobalVar,
|
||||
},
|
||||
Binary { opcode: Opcode, args: [Value; 2] },
|
||||
BinaryImm {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
imm: Imm64,
|
||||
},
|
||||
Ternary { opcode: Opcode, args: [Value; 3] },
|
||||
MultiAry { opcode: Opcode, args: ValueList },
|
||||
NullAry { opcode: Opcode },
|
||||
InsertLane {
|
||||
opcode: Opcode,
|
||||
lane: Uimm8,
|
||||
args: [Value; 2],
|
||||
},
|
||||
ExtractLane {
|
||||
opcode: Opcode,
|
||||
lane: Uimm8,
|
||||
arg: Value,
|
||||
},
|
||||
IntCompare {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
args: [Value; 2],
|
||||
},
|
||||
IntCompareImm {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
arg: Value,
|
||||
imm: Imm64,
|
||||
},
|
||||
IntCond {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
arg: Value,
|
||||
},
|
||||
FloatCompare {
|
||||
opcode: Opcode,
|
||||
cond: FloatCC,
|
||||
args: [Value; 2],
|
||||
},
|
||||
FloatCond {
|
||||
opcode: Opcode,
|
||||
cond: FloatCC,
|
||||
arg: Value,
|
||||
},
|
||||
IntSelect {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
args: [Value; 3],
|
||||
},
|
||||
Jump {
|
||||
opcode: Opcode,
|
||||
destination: Ebb,
|
||||
args: ValueList,
|
||||
},
|
||||
Branch {
|
||||
opcode: Opcode,
|
||||
destination: Ebb,
|
||||
args: ValueList,
|
||||
},
|
||||
BranchIcmp {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
destination: Ebb,
|
||||
args: ValueList,
|
||||
},
|
||||
BranchInt {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
destination: Ebb,
|
||||
args: ValueList,
|
||||
},
|
||||
BranchFloat {
|
||||
opcode: Opcode,
|
||||
cond: FloatCC,
|
||||
destination: Ebb,
|
||||
args: ValueList,
|
||||
},
|
||||
BranchTable {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
table: JumpTable,
|
||||
},
|
||||
Call {
|
||||
opcode: Opcode,
|
||||
func_ref: FuncRef,
|
||||
args: ValueList,
|
||||
},
|
||||
IndirectCall {
|
||||
opcode: Opcode,
|
||||
sig_ref: SigRef,
|
||||
args: ValueList,
|
||||
},
|
||||
FuncAddr { opcode: Opcode, func_ref: FuncRef },
|
||||
StackLoad {
|
||||
opcode: Opcode,
|
||||
stack_slot: StackSlot,
|
||||
offset: Offset32,
|
||||
},
|
||||
StackStore {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
stack_slot: StackSlot,
|
||||
offset: Offset32,
|
||||
},
|
||||
HeapAddr {
|
||||
opcode: Opcode,
|
||||
heap: ir::Heap,
|
||||
arg: Value,
|
||||
imm: Uimm32,
|
||||
},
|
||||
Load {
|
||||
opcode: Opcode,
|
||||
flags: MemFlags,
|
||||
arg: Value,
|
||||
offset: Offset32,
|
||||
},
|
||||
Store {
|
||||
opcode: Opcode,
|
||||
flags: MemFlags,
|
||||
args: [Value; 2],
|
||||
offset: Offset32,
|
||||
},
|
||||
RegMove {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
src: RegUnit,
|
||||
dst: RegUnit,
|
||||
},
|
||||
CopySpecial {
|
||||
opcode: Opcode,
|
||||
src: RegUnit,
|
||||
dst: RegUnit,
|
||||
},
|
||||
RegSpill {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
src: RegUnit,
|
||||
dst: StackSlot,
|
||||
},
|
||||
RegFill {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
src: StackSlot,
|
||||
dst: RegUnit,
|
||||
},
|
||||
Trap { opcode: Opcode, code: ir::TrapCode },
|
||||
CondTrap {
|
||||
opcode: Opcode,
|
||||
arg: Value,
|
||||
code: ir::TrapCode,
|
||||
},
|
||||
IntCondTrap {
|
||||
opcode: Opcode,
|
||||
cond: IntCC,
|
||||
arg: Value,
|
||||
code: ir::TrapCode,
|
||||
},
|
||||
FloatCondTrap {
|
||||
opcode: Opcode,
|
||||
cond: FloatCC,
|
||||
arg: Value,
|
||||
code: ir::TrapCode,
|
||||
},
|
||||
}
|
||||
|
||||
/// A variable list of `Value` operands used for function call arguments and passing arguments to
|
||||
/// basic blocks.
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
Reference in New Issue
Block a user