Cranelift: Add heap_load and heap_store instructions (#5300)
* Cranelift: Define `heap_load` and `heap_store` instructions
* Cranelift: Implement interpreter support for `heap_load` and `heap_store`
* Cranelift: Add a suite runtests for `heap_{load,store}`
There are so many knobs we can twist for heaps and I wanted to exhaustively test
all of them, so I wrote a script to generate the tests. I've checked in the
script in case we want to make any changes in the future, but I don't think it
is worth adding this to CI to check that scripts are up to date or anything like
that.
* Review feedback
This commit is contained in:
@@ -11,7 +11,9 @@ use crate::testfile::{Comment, Details, Feature, TestFile};
|
||||
use cranelift_codegen::data_value::DataValue;
|
||||
use cranelift_codegen::entity::{EntityRef, PrimaryMap};
|
||||
use cranelift_codegen::ir::entities::{AnyEntity, DynamicType};
|
||||
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64};
|
||||
use cranelift_codegen::ir::immediates::{
|
||||
HeapImmData, Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64,
|
||||
};
|
||||
use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs};
|
||||
use cranelift_codegen::ir::types::INVALID;
|
||||
use cranelift_codegen::ir::types::*;
|
||||
@@ -876,6 +878,19 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Match and consume an optional uimm32 offset immediate.
|
||||
//
|
||||
// Note that this will match an empty string as an empty offset, and that if an offset is
|
||||
// present, it must contain a plus sign.
|
||||
fn optional_uimm32_offset(&mut self) -> ParseResult<Uimm32> {
|
||||
match self.token() {
|
||||
Some(Token::Integer(x)) if x.starts_with('+') => {
|
||||
self.match_uimm32("expected a uimm32 offset immediate")
|
||||
}
|
||||
_ => Ok(Uimm32::from(0)),
|
||||
}
|
||||
}
|
||||
|
||||
// Match and consume a u8 immediate.
|
||||
// This is used for lane numbers in SIMD vectors.
|
||||
fn match_uimm8(&mut self, err_msg: &str) -> ParseResult<u8> {
|
||||
@@ -2976,6 +2991,42 @@ impl<'a> Parser<'a> {
|
||||
size,
|
||||
}
|
||||
}
|
||||
InstructionFormat::HeapLoad => {
|
||||
let heap = self.match_heap("expected heap identifier")?;
|
||||
ctx.check_heap(heap, self.loc)?;
|
||||
let flags = self.optional_memflags();
|
||||
let arg = self.match_value("expected SSA value heap index")?;
|
||||
let offset = self.optional_uimm32_offset()?;
|
||||
let heap_imm = ctx.function.dfg.heap_imms.push(HeapImmData {
|
||||
flags,
|
||||
heap,
|
||||
offset,
|
||||
});
|
||||
InstructionData::HeapLoad {
|
||||
opcode,
|
||||
heap_imm,
|
||||
arg,
|
||||
}
|
||||
}
|
||||
InstructionFormat::HeapStore => {
|
||||
let heap = self.match_heap("expected heap identifier")?;
|
||||
ctx.check_heap(heap, self.loc)?;
|
||||
let flags = self.optional_memflags();
|
||||
let index = self.match_value("expected SSA value heap index")?;
|
||||
let offset = self.optional_uimm32_offset()?;
|
||||
self.match_token(Token::Comma, "expected ',' between operands")?;
|
||||
let value = self.match_value("expected SSA value to store")?;
|
||||
let heap_imm = ctx.function.dfg.heap_imms.push(HeapImmData {
|
||||
flags,
|
||||
heap,
|
||||
offset,
|
||||
});
|
||||
InstructionData::HeapStore {
|
||||
opcode,
|
||||
heap_imm,
|
||||
args: [index, value],
|
||||
}
|
||||
}
|
||||
InstructionFormat::TableAddr => {
|
||||
let table = self.match_table("expected table identifier")?;
|
||||
ctx.check_table(table, self.loc)?;
|
||||
|
||||
Reference in New Issue
Block a user