Add load and store instructions.

Define a MemFlags class, currently holding a notrap and aligned flag.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-11 09:54:55 -07:00
parent 0c3771bccb
commit aad6ebebb5
12 changed files with 227 additions and 45 deletions

View File

@@ -5,7 +5,8 @@
use ir::types;
use ir::{InstructionData, DataFlowGraph, Cursor};
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, SigRef, FuncRef, StackSlot, ValueList};
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, SigRef, FuncRef, StackSlot, ValueList,
MemFlags};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, Offset32, Uoffset32};
use ir::condcodes::{IntCC, FloatCC};

View File

@@ -10,7 +10,7 @@ use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use std::ops::{Deref, DerefMut};
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot};
use ir::{Value, Type, Ebb, JumpTable, SigRef, FuncRef, StackSlot, MemFlags};
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, Offset32, Uoffset32};
use ir::condcodes::*;
use ir::types;
@@ -252,6 +252,20 @@ pub enum InstructionData {
args: [Value; 2],
offset: Uoffset32,
},
Load {
opcode: Opcode,
ty: Type,
flags: MemFlags,
arg: Value,
offset: Offset32,
},
Store {
opcode: Opcode,
ty: Type,
flags: MemFlags,
args: [Value; 2],
offset: Offset32,
},
}
/// A variable list of `Value` operands used for function call arguments and passing arguments to

View File

@@ -0,0 +1,92 @@
//! Memory operation flags.
use std::fmt;
enum FlagBit {
Notrap,
Aligned,
}
const NAMES: [&'static str; 2] = ["notrap", "aligned"];
/// Flags for memory operations like load/store.
///
/// Each of these flags introduce a limited form of undefined behavior. The flags each enable
/// certain optimizations that need to make additional assumptions. Generally, the semantics of a
/// program does not change when a flag is removed, but adding a flag will.
#[derive(Clone, Copy, Debug)]
pub struct MemFlags {
bits: u8,
}
impl MemFlags {
/// Create a new empty set of flags.
pub fn new() -> MemFlags {
MemFlags { bits: 0 }
}
/// Read a flag bit.
fn read(self, bit: FlagBit) -> bool {
self.bits & (1 << bit as usize) != 0
}
/// Set a flag bit.
fn set(&mut self, bit: FlagBit) {
self.bits |= 1 << bit as usize
}
/// Set a flag bit by name.
///
/// Returns true if the flag was found and set, false for an unknown flag name.
pub fn set_by_name(&mut self, name: &str) -> bool {
match NAMES.iter().position(|&s| s == name) {
Some(bit) => {
self.bits |= 1 << bit;
true
}
None => false,
}
}
/// Test if the `notrap` flag is set.
///
/// Normally, trapping is part of the semantics of a load/store operation. If the platform
/// would cause a trap when accessing the effective address, the Cretonne memory operation is
/// also required to trap.
///
/// The `notrap` flag gives a Cretonne operation permission to not trap. This makes it possible
/// to delete an unused load or a dead store instruction.
pub fn notrap(self) -> bool {
self.read(FlagBit::Notrap)
}
/// Set the `notrap` flag.
pub fn set_notrap(&mut self) {
self.set(FlagBit::Notrap)
}
/// Test if the `aligned` flag is set.
///
/// By default, Cretonne memory instructions work with any unaligned effective address. If the
/// `aligned` flag is set, the instruction is permitted to trap or return a wrong result if the
/// effective address is misaligned.
pub fn aligned(self) -> bool {
self.read(FlagBit::Aligned)
}
/// Set the `aligned` flag.
pub fn set_aligned(&mut self) {
self.set(FlagBit::Aligned)
}
}
impl fmt::Display for MemFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, n) in NAMES.iter().enumerate() {
if self.bits & (1 << i) != 0 {
write!(f, " {}", n)?;
}
}
Ok(())
}
}

View File

@@ -10,11 +10,12 @@ pub mod jumptable;
pub mod dfg;
pub mod layout;
pub mod function;
mod funcname;
mod extfunc;
mod builder;
mod valueloc;
mod extfunc;
mod funcname;
mod memflags;
mod progpoint;
mod valueloc;
pub use ir::funcname::FunctionName;
pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension, ExtFuncData};
@@ -29,3 +30,4 @@ pub use ir::layout::{Layout, Cursor};
pub use ir::function::Function;
pub use ir::builder::InstBuilder;
pub use ir::progpoint::{ProgramPoint, ProgramOrder, ExpandedProgramPoint};
pub use ir::memflags::MemFlags;

View File

@@ -271,7 +271,9 @@ impl<'a> Verifier<'a> {
&IntCompareImm { .. } |
&FloatCompare { .. } |
&HeapLoad { .. } |
&HeapStore { .. } => {}
&HeapStore { .. } |
&Load { .. } |
&Store { .. } => {}
}
Ok(())

View File

@@ -322,6 +322,13 @@ pub fn write_operands(w: &mut Write, dfg: &DataFlowGraph, inst: Inst) -> Result
} => write!(w, " {}, {}{}", arg, stack_slot, offset),
HeapLoad { arg, offset, .. } => write!(w, " {}{}", arg, offset),
HeapStore { args, offset, .. } => write!(w, " {}, {}{}", args[0], args[1], offset),
Load { flags, arg, offset, .. } => write!(w, "{} {}{}", flags, arg, offset),
Store {
flags,
args,
offset,
..
} => write!(w, "{} {}, {}{}", flags, args[0], args[1], offset),
}
}