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:
Dan Gohman
2018-03-13 10:06:45 -07:00
parent 9128290fb4
commit 3afe85ff17
2 changed files with 36 additions and 188 deletions

View File

@@ -103,6 +103,38 @@ def gen_arguments_method(fmt, is_mut):
.format(n, capture, arg)) .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): def gen_instruction_data_impl(fmt):
# type: (srcgen.Formatter) -> None # type: (srcgen.Formatter) -> None
""" """
@@ -682,6 +714,8 @@ def generate(isas, out_dir):
# opcodes.rs # opcodes.rs
fmt = srcgen.Formatter() fmt = srcgen.Formatter()
gen_formats(fmt) gen_formats(fmt)
gen_instruction_data(fmt)
fmt.line()
gen_instruction_data_impl(fmt) gen_instruction_data_impl(fmt)
fmt.line() fmt.line()
instrs = gen_opcodes(groups, fmt) instrs = gen_opcodes(groups, fmt)

View File

@@ -11,11 +11,9 @@ use std::str::FromStr;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use ir; use ir;
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags}; use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef};
use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32};
use ir::condcodes::*;
use ir::types; use ir::types;
use isa::RegUnit; use isa;
use entity; use entity;
use bitset::BitSet; 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 /// A variable list of `Value` operands used for function call arguments and passing arguments to
/// basic blocks. /// basic blocks.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]