Remove the HeapLoad/HeapStore instruction formats.
These formats are not used any longer after the heap_load and heap_store instructions were replaced by heap_addr. Also drop the Uoffset32 immediate operand type which isn't used either.
This commit is contained in:
@@ -8,8 +8,7 @@ in this module.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from cdsl.formats import InstructionFormat
|
from cdsl.formats import InstructionFormat
|
||||||
from cdsl.operands import VALUE, VARIABLE_ARGS
|
from cdsl.operands import VALUE, VARIABLE_ARGS
|
||||||
from .immediates import imm64, uimm8, uimm32, ieee32, ieee64
|
from .immediates import imm64, uimm8, uimm32, ieee32, ieee64, offset32
|
||||||
from .immediates import offset32, uoffset32
|
|
||||||
from .immediates import boolean, intcc, floatcc, memflags, regunit
|
from .immediates import boolean, intcc, floatcc, memflags, regunit
|
||||||
from . import entities
|
from . import entities
|
||||||
from .entities import ebb, sig_ref, func_ref, stack_slot, heap
|
from .entities import ebb, sig_ref, func_ref, stack_slot, heap
|
||||||
@@ -58,9 +57,6 @@ StackLoad = InstructionFormat(stack_slot, offset32)
|
|||||||
StackStore = InstructionFormat(VALUE, stack_slot, offset32)
|
StackStore = InstructionFormat(VALUE, stack_slot, offset32)
|
||||||
|
|
||||||
# Accessing a WebAssembly heap.
|
# Accessing a WebAssembly heap.
|
||||||
# TODO: Add a reference to a `heap` declared in the preamble.
|
|
||||||
HeapLoad = InstructionFormat(VALUE, uoffset32)
|
|
||||||
HeapStore = InstructionFormat(VALUE, VALUE, uoffset32)
|
|
||||||
HeapAddr = InstructionFormat(heap, VALUE, uimm32)
|
HeapAddr = InstructionFormat(heap, VALUE, uimm32)
|
||||||
|
|
||||||
RegMove = InstructionFormat(VALUE, ('src', regunit), ('dst', regunit))
|
RegMove = InstructionFormat(VALUE, ('src', regunit), ('dst', regunit))
|
||||||
|
|||||||
@@ -29,15 +29,6 @@ offset32 = ImmediateKind(
|
|||||||
'A 32-bit immediate signed offset.',
|
'A 32-bit immediate signed offset.',
|
||||||
default_member='offset')
|
default_member='offset')
|
||||||
|
|
||||||
#: A 32-bit immediate unsigned offset.
|
|
||||||
#:
|
|
||||||
#: This is used to represent an immediate address offset in WebAssembly memory
|
|
||||||
#: instructions.
|
|
||||||
uoffset32 = ImmediateKind(
|
|
||||||
'uoffset32',
|
|
||||||
'A 32-bit immediate unsigned offset.',
|
|
||||||
default_member='offset')
|
|
||||||
|
|
||||||
#: A 32-bit immediate floating point operand.
|
#: A 32-bit immediate floating point operand.
|
||||||
#:
|
#:
|
||||||
#: IEEE 754-2008 binary32 interchange format.
|
#: IEEE 754-2008 binary32 interchange format.
|
||||||
|
|||||||
@@ -269,71 +269,6 @@ impl FromStr for Offset32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 32-bit unsigned immediate offset.
|
|
||||||
///
|
|
||||||
/// This is used to encode an immediate offset for WebAssembly heap_load/heap_store instructions.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
|
||||||
pub struct Uoffset32(u32);
|
|
||||||
|
|
||||||
impl Uoffset32 {
|
|
||||||
/// Create a new `Uoffset32` representing the number `x`.
|
|
||||||
pub fn new(x: u32) -> Uoffset32 {
|
|
||||||
Uoffset32(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<u32> for Uoffset32 {
|
|
||||||
fn into(self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<i64> for Uoffset32 {
|
|
||||||
fn into(self) -> i64 {
|
|
||||||
i64::from(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<u32> for Uoffset32 {
|
|
||||||
fn from(x: u32) -> Self {
|
|
||||||
Uoffset32(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Uoffset32 {
|
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
// 0 displays as an empty offset.
|
|
||||||
if self.0 == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always include a sign.
|
|
||||||
if self.0 < 10_000 {
|
|
||||||
write!(f, "+{}", self.0)
|
|
||||||
} else {
|
|
||||||
write!(f, "+")?;
|
|
||||||
write_hex(i64::from(self.0), f)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Uoffset32 {
|
|
||||||
type Err = &'static str;
|
|
||||||
|
|
||||||
// Parse a decimal or hexadecimal `Uoffset32`, formatted as above.
|
|
||||||
fn from_str(s: &str) -> Result<Uoffset32, &'static str> {
|
|
||||||
if !s.starts_with('+') {
|
|
||||||
return Err("Unsigned offset must begin with '+' sign");
|
|
||||||
}
|
|
||||||
parse_i64(s).and_then(|x| if 0 <= x && x <= i64::from(u32::MAX) {
|
|
||||||
Ok(Uoffset32::new(x as u32))
|
|
||||||
} else {
|
|
||||||
Err("Offset out of range")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An IEEE binary32 immediate floating point value, represented as a u32
|
/// An IEEE binary32 immediate floating point value, represented as a u32
|
||||||
/// containing the bit pattern.
|
/// containing the bit pattern.
|
||||||
///
|
///
|
||||||
@@ -772,28 +707,6 @@ mod tests {
|
|||||||
parse_err::<Offset32>("+0x8000_0000", "Offset out of range");
|
parse_err::<Offset32>("+0x8000_0000", "Offset out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn format_uoffset32() {
|
|
||||||
assert_eq!(Uoffset32(0).to_string(), "");
|
|
||||||
assert_eq!(Uoffset32(1).to_string(), "+1");
|
|
||||||
assert_eq!(Uoffset32(9999).to_string(), "+9999");
|
|
||||||
assert_eq!(Uoffset32(10000).to_string(), "+0x2710");
|
|
||||||
assert_eq!(Uoffset32(0xffff).to_string(), "+0xffff");
|
|
||||||
assert_eq!(Uoffset32(0x10000).to_string(), "+0x0001_0000");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_uoffset32() {
|
|
||||||
parse_ok::<Uoffset32>("+0", "");
|
|
||||||
parse_ok::<Uoffset32>("+1", "+1");
|
|
||||||
parse_ok::<Uoffset32>("+0x0", "");
|
|
||||||
parse_ok::<Uoffset32>("+0xf", "+15");
|
|
||||||
parse_ok::<Uoffset32>("+0x8000_0000", "+0x8000_0000");
|
|
||||||
parse_ok::<Uoffset32>("+0xffff_ffff", "+0xffff_ffff");
|
|
||||||
|
|
||||||
parse_err::<Uoffset32>("+0x1_0000_0000", "Offset out of range");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_ieee32() {
|
fn format_ieee32() {
|
||||||
assert_eq!(Ieee32::with_float(0.0).to_string(), "0.0");
|
assert_eq!(Ieee32::with_float(0.0).to_string(), "0.0");
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ 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, StackSlot, MemFlags};
|
||||||
use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32, Uoffset32};
|
use ir::immediates::{Imm64, Uimm8, Uimm32, Ieee32, Ieee64, Offset32};
|
||||||
use ir::condcodes::*;
|
use ir::condcodes::*;
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::RegUnit;
|
use isa::RegUnit;
|
||||||
@@ -190,16 +190,6 @@ pub enum InstructionData {
|
|||||||
stack_slot: StackSlot,
|
stack_slot: StackSlot,
|
||||||
offset: Offset32,
|
offset: Offset32,
|
||||||
},
|
},
|
||||||
HeapLoad {
|
|
||||||
opcode: Opcode,
|
|
||||||
arg: Value,
|
|
||||||
offset: Uoffset32,
|
|
||||||
},
|
|
||||||
HeapStore {
|
|
||||||
opcode: Opcode,
|
|
||||||
args: [Value; 2],
|
|
||||||
offset: Uoffset32,
|
|
||||||
},
|
|
||||||
HeapAddr {
|
HeapAddr {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
heap: ir::Heap,
|
heap: ir::Heap,
|
||||||
|
|||||||
@@ -335,8 +335,6 @@ impl<'a> Verifier<'a> {
|
|||||||
IntCompare { .. } |
|
IntCompare { .. } |
|
||||||
IntCompareImm { .. } |
|
IntCompareImm { .. } |
|
||||||
FloatCompare { .. } |
|
FloatCompare { .. } |
|
||||||
HeapLoad { .. } |
|
|
||||||
HeapStore { .. } |
|
|
||||||
Load { .. } |
|
Load { .. } |
|
||||||
Store { .. } |
|
Store { .. } |
|
||||||
RegMove { .. } => {}
|
RegMove { .. } => {}
|
||||||
|
|||||||
@@ -354,8 +354,6 @@ pub fn write_operands(
|
|||||||
offset,
|
offset,
|
||||||
..
|
..
|
||||||
} => write!(w, " {}, {}{}", arg, stack_slot, offset),
|
} => write!(w, " {}, {}{}", arg, stack_slot, offset),
|
||||||
HeapLoad { arg, offset, .. } => write!(w, " {}{}", arg, offset),
|
|
||||||
HeapStore { args, offset, .. } => write!(w, " {}, {}{}", args[0], args[1], offset),
|
|
||||||
HeapAddr { heap, arg, imm, .. } => write!(w, " {}, {}, {}", heap, arg, imm),
|
HeapAddr { heap, arg, imm, .. } => write!(w, " {}, {}, {}", heap, arg, imm),
|
||||||
Load { flags, arg, offset, .. } => write!(w, "{} {}{}", flags, arg, offset),
|
Load { flags, arg, offset, .. } => write!(w, "{} {}{}", flags, arg, offset),
|
||||||
Store {
|
Store {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, CallConv, S
|
|||||||
ExtFuncData, SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags,
|
ExtFuncData, SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags,
|
||||||
GlobalVar, GlobalVarData, Heap, HeapData, HeapStyle, HeapBase};
|
GlobalVar, GlobalVarData, Heap, HeapData, HeapStyle, HeapBase};
|
||||||
use cretonne::ir::types::VOID;
|
use cretonne::ir::types::VOID;
|
||||||
use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Uoffset32, Ieee32, Ieee64};
|
use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Ieee32, Ieee64};
|
||||||
use cretonne::ir::entities::AnyEntity;
|
use cretonne::ir::entities::AnyEntity;
|
||||||
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs};
|
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs};
|
||||||
use cretonne::isa::{self, TargetIsa, Encoding, RegUnit};
|
use cretonne::isa::{self, TargetIsa, Encoding, RegUnit};
|
||||||
@@ -585,22 +585,6 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match and consume an optional uoffset32 immediate.
|
|
||||||
//
|
|
||||||
// Note that this will match an empty string as an empty offset, and that if an offset is
|
|
||||||
// present, it must contain a `+` sign.
|
|
||||||
fn optional_uoffset32(&mut self) -> Result<Uoffset32> {
|
|
||||||
if let Some(Token::Integer(text)) = self.token() {
|
|
||||||
self.consume();
|
|
||||||
// Lexer just gives us raw text that looks like an integer.
|
|
||||||
// Parse it as a `Uoffset32` to check for overflow and other issues.
|
|
||||||
text.parse().map_err(|e| self.error(e))
|
|
||||||
} else {
|
|
||||||
// A uoffset32 operand can be absent.
|
|
||||||
Ok(Uoffset32::new(0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Match and consume an Ieee32 immediate.
|
// Match and consume an Ieee32 immediate.
|
||||||
fn match_ieee32(&mut self, err_msg: &str) -> Result<Ieee32> {
|
fn match_ieee32(&mut self, err_msg: &str) -> Result<Ieee32> {
|
||||||
if let Some(Token::Float(text)) = self.token() {
|
if let Some(Token::Float(text)) = self.token() {
|
||||||
@@ -2141,29 +2125,6 @@ impl<'a> Parser<'a> {
|
|||||||
offset,
|
offset,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstructionFormat::HeapLoad => {
|
|
||||||
let addr = self.match_value("expected SSA value address")?;
|
|
||||||
let offset = self.optional_uoffset32()?;
|
|
||||||
InstructionData::HeapLoad {
|
|
||||||
opcode,
|
|
||||||
arg: addr,
|
|
||||||
offset,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InstructionFormat::HeapStore => {
|
|
||||||
let arg = self.match_value("expected SSA value operand")?;
|
|
||||||
self.match_token(
|
|
||||||
Token::Comma,
|
|
||||||
"expected ',' between operands",
|
|
||||||
)?;
|
|
||||||
let addr = self.match_value("expected SSA value address")?;
|
|
||||||
let offset = self.optional_uoffset32()?;
|
|
||||||
InstructionData::HeapStore {
|
|
||||||
opcode,
|
|
||||||
args: [arg, addr],
|
|
||||||
offset,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InstructionFormat::HeapAddr => {
|
InstructionFormat::HeapAddr => {
|
||||||
let heap = self.match_heap("expected heap identifier").and_then(|h| {
|
let heap = self.match_heap("expected heap identifier").and_then(|h| {
|
||||||
ctx.get_heap(h, &self.loc)
|
ctx.get_heap(h, &self.loc)
|
||||||
|
|||||||
Reference in New Issue
Block a user