From 407d24c0132dcb9d050990bb225ee3cf39c7a1b1 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Tue, 23 Jul 2019 11:02:52 -0700 Subject: [PATCH] Add operand kind and format for unsigned 128-bit immediates --- cranelift/codegen/meta/src/shared/formats.rs | 2 ++ .../codegen/meta/src/shared/immediates.rs | 10 +++++++ .../codegen/meta/src/shared/instructions.rs | 17 ++++++++++++ cranelift/codegen/src/verifier/mod.rs | 1 + cranelift/codegen/src/write.rs | 6 +++++ cranelift/reader/src/parser.rs | 27 ++++++++++++++++++- cranelift/serde/src/serde_clif_json.rs | 9 +++++++ 7 files changed, 71 insertions(+), 1 deletion(-) diff --git a/cranelift/codegen/meta/src/shared/formats.rs b/cranelift/codegen/meta/src/shared/formats.rs index e6e7c92df7..394eb6d58f 100644 --- a/cranelift/codegen/meta/src/shared/formats.rs +++ b/cranelift/codegen/meta/src/shared/formats.rs @@ -5,6 +5,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis // Shorthands for immediates. let uimm8 = immediates.by_name("uimm8"); let uimm32 = immediates.by_name("uimm32"); + let uimm128 = immediates.by_name("uimm128"); let imm64 = immediates.by_name("imm64"); let ieee32 = immediates.by_name("ieee32"); let ieee64 = immediates.by_name("ieee64"); @@ -30,6 +31,7 @@ pub fn define(immediates: &OperandKinds, entities: &OperandKinds) -> FormatRegis registry.insert(Builder::new("Unary").value()); registry.insert(Builder::new("UnaryImm").imm(imm64)); + registry.insert(Builder::new("UnaryImm128").imm(uimm128)); registry.insert(Builder::new("UnaryIeee32").imm(ieee32)); registry.insert(Builder::new("UnaryIeee64").imm(ieee64)); registry.insert(Builder::new("UnaryBool").imm(boolean)); diff --git a/cranelift/codegen/meta/src/shared/immediates.rs b/cranelift/codegen/meta/src/shared/immediates.rs index bee762a9e5..5b8baca898 100644 --- a/cranelift/codegen/meta/src/shared/immediates.rs +++ b/cranelift/codegen/meta/src/shared/immediates.rs @@ -29,6 +29,16 @@ pub fn define() -> Vec { .build(); kinds.push(uimm32); + // An unsigned 128-bit immediate integer operand. + // + // This operand is used to pass entire 128-bit vectors as immediates to + // instructions like const. + let uimm128 = Builder::new_imm("uimm128") + .doc("A 128-bit immediate unsigned integer.") + .rust_type("ir::Constant") + .build(); + kinds.push(uimm128); + // A 32-bit immediate signed offset. // // This is used to represent an immediate address offset in load/store diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 3d3fda49b9..c11016c64d 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -30,6 +30,7 @@ pub fn define( let uimm8 = immediates.by_name("uimm8"); let uimm32 = immediates.by_name("uimm32"); let imm64 = immediates.by_name("imm64"); + let uimm128 = immediates.by_name("uimm128"); let offset32 = immediates.by_name("offset32"); let memflags = immediates.by_name("memflags"); let ieee32 = immediates.by_name("ieee32"); @@ -1088,6 +1089,22 @@ pub fn define( .operands_out(vec![a]), ); + let N = &operand_doc("N", uimm128, "The 16 immediate bytes of a 128-bit vector"); + let a = &operand_doc("a", TxN, "A constant vector value"); + + ig.push( + Inst::new( + "vconst", + r#" + SIMD vector constant. + + Construct a vector with the given immediate bytes. + "#, + ) + .operands_in(vec![N]) + .operands_out(vec![a]), + ); + let a = &operand_doc("a", Ref, "A constant reference null value"); ig.push( diff --git a/cranelift/codegen/src/verifier/mod.rs b/cranelift/codegen/src/verifier/mod.rs index 84acd0bd09..72fa1f7e17 100644 --- a/cranelift/codegen/src/verifier/mod.rs +++ b/cranelift/codegen/src/verifier/mod.rs @@ -679,6 +679,7 @@ impl<'a> Verifier<'a> { // Exhaustive list so we can't forget to add new formats Unary { .. } | UnaryImm { .. } + | UnaryImm128 { .. } | UnaryIeee32 { .. } | UnaryIeee64 { .. } | UnaryBool { .. } diff --git a/cranelift/codegen/src/write.rs b/cranelift/codegen/src/write.rs index 4fe2b67f3c..4b616cab2e 100644 --- a/cranelift/codegen/src/write.rs +++ b/cranelift/codegen/src/write.rs @@ -5,6 +5,7 @@ use crate::entity::SecondaryMap; use crate::ir::entities::AnyEntity; +use crate::ir::immediates::Uimm128; use crate::ir::{ DataFlowGraph, DisplayFunctionAnnotations, Ebb, Function, Inst, SigRef, Type, Value, ValueDef, ValueLoc, @@ -487,6 +488,11 @@ pub fn write_operands( match dfg[inst] { Unary { arg, .. } => write!(w, " {}", arg), UnaryImm { imm, .. } => write!(w, " {}", imm), + UnaryImm128 { imm, .. } => { + let data = dfg.constants.get(imm); + let uimm128 = Uimm128::from(&data[..]); + write!(w, " {}", uimm128) + } UnaryIeee32 { imm, .. } => write!(w, " {}", imm), UnaryIeee64 { imm, .. } => write!(w, " {}", imm), UnaryBool { imm, .. } => write!(w, " {}", imm), diff --git a/cranelift/reader/src/parser.rs b/cranelift/reader/src/parser.rs index 5bcc87de0c..d503151701 100644 --- a/cranelift/reader/src/parser.rs +++ b/cranelift/reader/src/parser.rs @@ -9,7 +9,7 @@ use crate::testfile::{Comment, Details, TestFile}; use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir; use cranelift_codegen::ir::entities::AnyEntity; -use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64}; +use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm128, Uimm32, Uimm64}; use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; use cranelift_codegen::ir::types::INVALID; use cranelift_codegen::ir::{ @@ -546,6 +546,23 @@ impl<'a> Parser<'a> { } } + // Match and consume a Uimm128 immediate; due to size restrictions on InstructionData, Uimm128 is boxed in cranelift-codegen/meta/src/shared/immediates.rs + fn match_uimm128(&mut self, err_msg: &str) -> ParseResult { + if let Some(Token::Integer(text)) = self.token() { + self.consume(); + // Lexer just gives us raw text that looks like hex code. + // Parse it as an Uimm128 to check for overflow and other issues. + text.parse().map_err(|e| { + self.error(&format!( + "expected u128 hexadecimal immediate, failed to parse: {}", + e + )) + }) + } else { + err!(self.loc, err_msg) + } + } + // Match and consume a Uimm64 immediate. fn match_uimm64(&mut self, err_msg: &str) -> ParseResult { if let Some(Token::Integer(text)) = self.token() { @@ -2109,6 +2126,14 @@ impl<'a> Parser<'a> { opcode, imm: self.match_imm64("expected immediate integer operand")?, }, + InstructionFormat::UnaryImm128 => { + let uimm128 = self.match_uimm128("expected immediate hexadecimal operand")?; + let constant_handle = ctx.function.dfg.constants.insert(uimm128.0.to_vec()); + InstructionData::UnaryImm128 { + opcode, + imm: constant_handle, + } + } InstructionFormat::UnaryIeee32 => InstructionData::UnaryIeee32 { opcode, imm: self.match_ieee32("expected immediate 32-bit float operand")?, diff --git a/cranelift/serde/src/serde_clif_json.rs b/cranelift/serde/src/serde_clif_json.rs index 0a66cd710c..90935e9234 100644 --- a/cranelift/serde/src/serde_clif_json.rs +++ b/cranelift/serde/src/serde_clif_json.rs @@ -1,3 +1,4 @@ +use cranelift_codegen::ir::immediates::Uimm128; use cranelift_codegen::ir::{Ebb, Function, Inst, InstructionData, Signature}; use serde_derive::{Deserialize, Serialize}; @@ -261,6 +262,14 @@ pub fn get_inst_data(inst_index: Inst, func: &Function) -> SerInstData { opcode: opcode.to_string(), imm: imm.to_string(), }, + InstructionData::UnaryImm128 { opcode, imm } => { + let data = func.dfg.constants.get(imm); + let uimm128 = Uimm128::from(&data[..]); + SerInstData::UnaryImm { + opcode: opcode.to_string(), + imm: uimm128.to_string(), + } + } InstructionData::UnaryIeee32 { opcode, imm } => SerInstData::UnaryIeee32 { opcode: opcode.to_string(), imm: imm.to_string(),