Return a function pointer from TargetIsa::encode().

Replace the isa::Legalize enumeration with a function pointer. This
allows an ISA to define its own specific legalization actions instead of
relying on the default two.

Generate a LEGALIZE_ACTIONS table for each ISA which contains
legalization function pointers indexed by the legalization codes that
are already in the encoding tables. Include this table in
isa/*/enc_tables.rs.

Give the `Encodings` iterator a reference to the action table and change
its `legalize()` method to return a function pointer instead of an
ISA-specific code.

The Result<> returned from TargetIsa::encode() no longer implements
Debug, so eliminate uses of unwrap and expect on that type.
This commit is contained in:
Jakob Stoklund Olesen
2017-07-27 14:46:56 -07:00
parent d1353bba05
commit 2aca35a9aa
19 changed files with 140 additions and 102 deletions

View File

@@ -2,7 +2,7 @@
use ir::condcodes::IntCC;
use ir::{self, types, Opcode};
use isa::EncInfo;
use isa;
use isa::constraints::*;
use isa::enc_tables::*;
use isa::encoding::RecipeSizing;
@@ -16,3 +16,4 @@ use super::registers::*;
// - `ENCLIST`
// - `INFO`
include!(concat!(env!("OUT_DIR"), "/encoding-riscv.rs"));
include!(concat!(env!("OUT_DIR"), "/legalize-riscv.rs"));

View File

@@ -72,6 +72,7 @@ impl TargetIsa for Isa {
self.cpumode,
&enc_tables::LEVEL2[..],
&enc_tables::ENCLISTS[..],
&enc_tables::LEGALIZE_ACTIONS[..],
&enc_tables::RECIPE_PREDICATES[..],
&enc_tables::INST_PREDICATES[..],
self.isa_flags.predicate_view())
@@ -113,8 +114,11 @@ mod tests {
use ir::{DataFlowGraph, InstructionData, Opcode};
use ir::{types, immediates};
fn encstr(isa: &isa::TargetIsa, enc: isa::Encoding) -> String {
isa.encoding_info().display(enc).to_string()
fn encstr(isa: &isa::TargetIsa, enc: Result<isa::Encoding, isa::Legalize>) -> String {
match enc {
Ok(e) => isa.encoding_info().display(e).to_string(),
Err(_) => "no encoding".to_string(),
}
}
#[test]
@@ -137,8 +141,7 @@ mod tests {
};
// ADDI is I/0b00100
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst64, types::I64).unwrap()),
"I#04");
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst64, types::I64)), "I#04");
// Try to encode iadd_imm.i64 v1, -10000.
let inst64_large = InstructionData::BinaryImm {
@@ -148,8 +151,7 @@ mod tests {
};
// Immediate is out of range for ADDI.
assert_eq!(isa.encode(&dfg, &inst64_large, types::I64),
Err(isa::Legalize::Expand));
assert!(isa.encode(&dfg, &inst64_large, types::I64).is_err());
// Create an iadd_imm.i32 which is encodable in RV64.
let inst32 = InstructionData::BinaryImm {
@@ -159,8 +161,7 @@ mod tests {
};
// ADDIW is I/0b00110
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst32, types::I32).unwrap()),
"I#06");
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst32, types::I32)), "I#06");
}
// Same as above, but for RV32.
@@ -184,8 +185,7 @@ mod tests {
};
// In 32-bit mode, an i64 bit add should be narrowed.
assert_eq!(isa.encode(&dfg, &inst64, types::I64),
Err(isa::Legalize::Narrow));
assert!(isa.encode(&dfg, &inst64, types::I64).is_err());
// Try to encode iadd_imm.i64 v1, -10000.
let inst64_large = InstructionData::BinaryImm {
@@ -195,8 +195,7 @@ mod tests {
};
// In 32-bit mode, an i64 bit add should be narrowed.
assert_eq!(isa.encode(&dfg, &inst64_large, types::I64),
Err(isa::Legalize::Narrow));
assert!(isa.encode(&dfg, &inst64_large, types::I64).is_err());
// Create an iadd_imm.i32 which is encodable in RV32.
let inst32 = InstructionData::BinaryImm {
@@ -206,8 +205,7 @@ mod tests {
};
// ADDI is I/0b00100
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst32, types::I32).unwrap()),
"I#04");
assert_eq!(encstr(&*isa, isa.encode(&dfg, &inst32, types::I32)), "I#04");
// Create an imul.i32 which is encodable in RV32, but only when use_m is true.
let mul32 = InstructionData::Binary {
@@ -215,8 +213,7 @@ mod tests {
args: [arg32, arg32],
};
assert_eq!(isa.encode(&dfg, &mul32, types::I32),
Err(isa::Legalize::Expand));
assert!(isa.encode(&dfg, &mul32, types::I32).is_err());
}
#[test]
@@ -241,7 +238,6 @@ mod tests {
opcode: Opcode::Imul,
args: [arg32, arg32],
};
assert_eq!(encstr(&*isa, isa.encode(&dfg, &mul32, types::I32).unwrap()),
"R#10c");
assert_eq!(encstr(&*isa, isa.encode(&dfg, &mul32, types::I32)), "R#10c");
}
}