Add instructions using CPU flags.
Add integer and floating comparison instructions that return CPU flags: ifcmp, ifcmp_imm, and ffcmp. Add conditional branch instructions that check CPU flags: brif, brff Add instructions that check a condition in the CPU flags and return a b1: trueif, trueff.
This commit is contained in:
@@ -329,6 +329,8 @@ instruction in the EBB.
|
|||||||
.. autoinst:: brz
|
.. autoinst:: brz
|
||||||
.. autoinst:: brnz
|
.. autoinst:: brnz
|
||||||
.. autoinst:: br_icmp
|
.. autoinst:: br_icmp
|
||||||
|
.. autoinst:: brif
|
||||||
|
.. autoinst:: brff
|
||||||
.. autoinst:: br_table
|
.. autoinst:: br_table
|
||||||
|
|
||||||
.. inst:: JT = jump_table EBB0, EBB1, ..., EBBn
|
.. inst:: JT = jump_table EBB0, EBB1, ..., EBBn
|
||||||
@@ -722,6 +724,8 @@ Integer operations
|
|||||||
|
|
||||||
.. autoinst:: icmp
|
.. autoinst:: icmp
|
||||||
.. autoinst:: icmp_imm
|
.. autoinst:: icmp_imm
|
||||||
|
.. autoinst:: ifcmp
|
||||||
|
.. autoinst:: ifcmp_imm
|
||||||
.. autoinst:: iadd
|
.. autoinst:: iadd
|
||||||
.. autoinst:: iadd_imm
|
.. autoinst:: iadd_imm
|
||||||
.. autoinst:: iadd_cin
|
.. autoinst:: iadd_cin
|
||||||
@@ -814,6 +818,7 @@ Floating point operations
|
|||||||
These operations generally follow IEEE 754-2008 semantics.
|
These operations generally follow IEEE 754-2008 semantics.
|
||||||
|
|
||||||
.. autoinst:: fcmp
|
.. autoinst:: fcmp
|
||||||
|
.. autoinst:: ffcmp
|
||||||
.. autoinst:: fadd
|
.. autoinst:: fadd
|
||||||
.. autoinst:: fsub
|
.. autoinst:: fsub
|
||||||
.. autoinst:: fmul
|
.. autoinst:: fmul
|
||||||
@@ -857,6 +862,12 @@ represented as a floating point number.
|
|||||||
.. autoinst:: trunc
|
.. autoinst:: trunc
|
||||||
.. autoinst:: nearest
|
.. autoinst:: nearest
|
||||||
|
|
||||||
|
CPU flag operations
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. autoinst:: trueif
|
||||||
|
.. autoinst:: trueff
|
||||||
|
|
||||||
Conversion operations
|
Conversion operations
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|||||||
46
cranelift/filetests/parser/flags.cton
Normal file
46
cranelift/filetests/parser/flags.cton
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
test cat
|
||||||
|
test verifier
|
||||||
|
|
||||||
|
function %iflags(i32) {
|
||||||
|
ebb0(v0: i32):
|
||||||
|
v1 = ifcmp_imm v0, 17
|
||||||
|
brif eq v1, ebb1
|
||||||
|
brif ugt v1, ebb2
|
||||||
|
v2 = iconst.i32 34
|
||||||
|
v3 = ifcmp v0, v2
|
||||||
|
v4 = trueif eq v3
|
||||||
|
brnz v4, ebb2
|
||||||
|
return
|
||||||
|
|
||||||
|
ebb1:
|
||||||
|
return
|
||||||
|
|
||||||
|
ebb2:
|
||||||
|
trap oob
|
||||||
|
}
|
||||||
|
; check: $v1 = ifcmp_imm $v0, 17
|
||||||
|
; check: brif eq $v1, $ebb1
|
||||||
|
; check: brif ugt $v1, $ebb2
|
||||||
|
; check: $v3 = ifcmp $v0, $v2
|
||||||
|
; check: $v4 = trueif eq $v3
|
||||||
|
|
||||||
|
function %fflags(f32) {
|
||||||
|
ebb0(v0: f32):
|
||||||
|
v1 = f32const 0x34.0p0
|
||||||
|
v2 = ffcmp v0, v1
|
||||||
|
brff eq v2, ebb1
|
||||||
|
brff ord v2, ebb2
|
||||||
|
v3 = trueff gt v2
|
||||||
|
brnz v3, ebb2
|
||||||
|
return
|
||||||
|
|
||||||
|
ebb1:
|
||||||
|
return
|
||||||
|
|
||||||
|
ebb2:
|
||||||
|
trap oob
|
||||||
|
}
|
||||||
|
; check: $v2 = ffcmp $v0, $v1
|
||||||
|
; check: brff eq $v2, $ebb1
|
||||||
|
; check: brff ord $v2, $ebb2
|
||||||
|
; check: $v3 = trueff gt $v2
|
||||||
@@ -37,10 +37,14 @@ ExtractLane = InstructionFormat(VALUE, ('lane', uimm8))
|
|||||||
|
|
||||||
IntCompare = InstructionFormat(intcc, VALUE, VALUE)
|
IntCompare = InstructionFormat(intcc, VALUE, VALUE)
|
||||||
IntCompareImm = InstructionFormat(intcc, VALUE, imm64)
|
IntCompareImm = InstructionFormat(intcc, VALUE, imm64)
|
||||||
|
IntCond = InstructionFormat(intcc, VALUE)
|
||||||
FloatCompare = InstructionFormat(floatcc, VALUE, VALUE)
|
FloatCompare = InstructionFormat(floatcc, VALUE, VALUE)
|
||||||
|
FloatCond = InstructionFormat(floatcc, VALUE)
|
||||||
|
|
||||||
Jump = InstructionFormat(ebb, VARIABLE_ARGS)
|
Jump = InstructionFormat(ebb, VARIABLE_ARGS)
|
||||||
Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
|
Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
|
||||||
|
BranchInt = InstructionFormat(intcc, VALUE, ebb, VARIABLE_ARGS)
|
||||||
|
BranchFloat = InstructionFormat(floatcc, VALUE, ebb, VARIABLE_ARGS)
|
||||||
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
||||||
BranchTable = InstructionFormat(VALUE, entities.jump_table)
|
BranchTable = InstructionFormat(VALUE, entities.jump_table)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from __future__ import absolute_import
|
|||||||
from cdsl.operands import Operand, VARIABLE_ARGS
|
from cdsl.operands import Operand, VARIABLE_ARGS
|
||||||
from cdsl.typevar import TypeVar
|
from cdsl.typevar import TypeVar
|
||||||
from cdsl.instructions import Instruction, InstructionGroup
|
from cdsl.instructions import Instruction, InstructionGroup
|
||||||
from base.types import f32, f64, b1
|
from base.types import f32, f64, b1, iflags, fflags
|
||||||
from base.immediates import imm64, uimm8, uimm32, ieee32, ieee64, offset32
|
from base.immediates import imm64, uimm8, uimm32, ieee32, ieee64, offset32
|
||||||
from base.immediates import boolean, intcc, floatcc, memflags, regunit
|
from base.immediates import boolean, intcc, floatcc, memflags, regunit
|
||||||
from base.immediates import trapcode
|
from base.immediates import trapcode
|
||||||
@@ -112,6 +112,23 @@ br_icmp = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=(Cond, x, y, EBB, args), is_branch=True)
|
ins=(Cond, x, y, EBB, args), is_branch=True)
|
||||||
|
|
||||||
|
f = Operand('f', iflags)
|
||||||
|
|
||||||
|
brif = Instruction(
|
||||||
|
'brif', r"""
|
||||||
|
Branch when condition is true in integer CPU flags.
|
||||||
|
""",
|
||||||
|
ins=(Cond, f, EBB, args), is_branch=True)
|
||||||
|
|
||||||
|
Cond = Operand('Cond', floatcc)
|
||||||
|
f = Operand('f', fflags)
|
||||||
|
|
||||||
|
brff = Instruction(
|
||||||
|
'brff', r"""
|
||||||
|
Branch when condition is true in floating point CPU flags.
|
||||||
|
""",
|
||||||
|
ins=(Cond, f, EBB, args), is_branch=True)
|
||||||
|
|
||||||
x = Operand('x', iB, doc='index into jump table')
|
x = Operand('x', iB, doc='index into jump table')
|
||||||
JT = Operand('JT', entities.jump_table)
|
JT = Operand('JT', entities.jump_table)
|
||||||
br_table = Instruction(
|
br_table = Instruction(
|
||||||
@@ -677,6 +694,28 @@ icmp_imm = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=(Cond, x, Y), outs=a)
|
ins=(Cond, x, Y), outs=a)
|
||||||
|
|
||||||
|
f = Operand('f', iflags)
|
||||||
|
x = Operand('x', iB)
|
||||||
|
y = Operand('y', iB)
|
||||||
|
|
||||||
|
ifcmp = Instruction(
|
||||||
|
'ifcmp', r"""
|
||||||
|
Compare scalar integers and return flags.
|
||||||
|
|
||||||
|
Compare two scalar integer values and return integer CPU flags
|
||||||
|
representing the result.
|
||||||
|
""",
|
||||||
|
ins=(x, y), outs=f)
|
||||||
|
|
||||||
|
ifcmp_imm = Instruction(
|
||||||
|
'ifcmp_imm', r"""
|
||||||
|
Compare scalar integer to a constant and return flags.
|
||||||
|
|
||||||
|
Like :inst:`icmp_imm`, but returns integer CPU flags instead of testing
|
||||||
|
a specific condition code.
|
||||||
|
""",
|
||||||
|
ins=(x, Y), outs=f)
|
||||||
|
|
||||||
a = Operand('a', Int)
|
a = Operand('a', Int)
|
||||||
x = Operand('x', Int)
|
x = Operand('x', Int)
|
||||||
y = Operand('y', Int)
|
y = Operand('y', Int)
|
||||||
@@ -1176,6 +1215,7 @@ popcnt = Instruction(
|
|||||||
Float = TypeVar(
|
Float = TypeVar(
|
||||||
'Float', 'A scalar or vector floating point number',
|
'Float', 'A scalar or vector floating point number',
|
||||||
floats=True, simd=True)
|
floats=True, simd=True)
|
||||||
|
fB = TypeVar('fB', 'A scalar floating point number', floats=True)
|
||||||
|
|
||||||
Cond = Operand('Cond', floatcc)
|
Cond = Operand('Cond', floatcc)
|
||||||
x = Operand('x', Float)
|
x = Operand('x', Float)
|
||||||
@@ -1246,6 +1286,17 @@ fcmp = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=(Cond, x, y), outs=a)
|
ins=(Cond, x, y), outs=a)
|
||||||
|
|
||||||
|
f = Operand('f', fflags)
|
||||||
|
|
||||||
|
ffcmp = Instruction(
|
||||||
|
'ffcmp', r"""
|
||||||
|
Floating point comparison returning flags.
|
||||||
|
|
||||||
|
Compares two numbers like :inst:`fcmp`, but returns floating point CPU
|
||||||
|
flags instead of testing a specific condition.
|
||||||
|
""",
|
||||||
|
ins=(x, y), outs=f)
|
||||||
|
|
||||||
x = Operand('x', Float)
|
x = Operand('x', Float)
|
||||||
y = Operand('y', Float)
|
y = Operand('y', Float)
|
||||||
z = Operand('z', Float)
|
z = Operand('z', Float)
|
||||||
@@ -1387,6 +1438,35 @@ nearest = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=x, outs=a)
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
#
|
||||||
|
# CPU flag operations
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
Cond = Operand('Cond', intcc)
|
||||||
|
f = Operand('f', iflags)
|
||||||
|
a = Operand('a', b1)
|
||||||
|
|
||||||
|
trueif = Instruction(
|
||||||
|
'trueif', r"""
|
||||||
|
Test integer CPU flags for a specific condition.
|
||||||
|
|
||||||
|
Check the CPU flags in ``f`` against the ``Cond`` condition code and
|
||||||
|
return true when the condition code is satisfied.
|
||||||
|
""",
|
||||||
|
ins=(Cond, f), outs=a)
|
||||||
|
|
||||||
|
Cond = Operand('Cond', floatcc)
|
||||||
|
f = Operand('f', fflags)
|
||||||
|
|
||||||
|
trueff = Instruction(
|
||||||
|
'trueff', r"""
|
||||||
|
Test floating point CPU flags for a specific condition.
|
||||||
|
|
||||||
|
Check the CPU flags in ``f`` against the ``Cond`` condition code and
|
||||||
|
return true when the condition code is satisfied.
|
||||||
|
""",
|
||||||
|
ins=(Cond, f), outs=a)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Conversions
|
# Conversions
|
||||||
|
|||||||
@@ -141,11 +141,21 @@ pub enum InstructionData {
|
|||||||
arg: Value,
|
arg: Value,
|
||||||
imm: Imm64,
|
imm: Imm64,
|
||||||
},
|
},
|
||||||
|
IntCond {
|
||||||
|
opcode: Opcode,
|
||||||
|
cond: IntCC,
|
||||||
|
arg: Value,
|
||||||
|
},
|
||||||
FloatCompare {
|
FloatCompare {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
cond: FloatCC,
|
cond: FloatCC,
|
||||||
args: [Value; 2],
|
args: [Value; 2],
|
||||||
},
|
},
|
||||||
|
FloatCond {
|
||||||
|
opcode: Opcode,
|
||||||
|
cond: FloatCC,
|
||||||
|
arg: Value,
|
||||||
|
},
|
||||||
Jump {
|
Jump {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
destination: Ebb,
|
destination: Ebb,
|
||||||
@@ -162,6 +172,18 @@ pub enum InstructionData {
|
|||||||
destination: Ebb,
|
destination: Ebb,
|
||||||
args: ValueList,
|
args: ValueList,
|
||||||
},
|
},
|
||||||
|
BranchInt {
|
||||||
|
opcode: Opcode,
|
||||||
|
cond: IntCC,
|
||||||
|
destination: Ebb,
|
||||||
|
args: ValueList,
|
||||||
|
},
|
||||||
|
BranchFloat {
|
||||||
|
opcode: Opcode,
|
||||||
|
cond: FloatCC,
|
||||||
|
destination: Ebb,
|
||||||
|
args: ValueList,
|
||||||
|
},
|
||||||
BranchTable {
|
BranchTable {
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
arg: Value,
|
arg: Value,
|
||||||
|
|||||||
@@ -288,6 +288,16 @@ impl<'a> Verifier<'a> {
|
|||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} |
|
} |
|
||||||
|
BranchInt {
|
||||||
|
destination,
|
||||||
|
ref args,
|
||||||
|
..
|
||||||
|
} |
|
||||||
|
BranchFloat {
|
||||||
|
destination,
|
||||||
|
ref args,
|
||||||
|
..
|
||||||
|
} |
|
||||||
BranchIcmp {
|
BranchIcmp {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
@@ -340,7 +350,9 @@ impl<'a> Verifier<'a> {
|
|||||||
ExtractLane { .. } |
|
ExtractLane { .. } |
|
||||||
IntCompare { .. } |
|
IntCompare { .. } |
|
||||||
IntCompareImm { .. } |
|
IntCompareImm { .. } |
|
||||||
|
IntCond { .. } |
|
||||||
FloatCompare { .. } |
|
FloatCompare { .. } |
|
||||||
|
FloatCond { .. } |
|
||||||
Load { .. } |
|
Load { .. } |
|
||||||
Store { .. } |
|
Store { .. } |
|
||||||
RegMove { .. } |
|
RegMove { .. } |
|
||||||
|
|||||||
@@ -299,22 +299,16 @@ pub fn write_operands(
|
|||||||
ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane),
|
ExtractLane { lane, arg, .. } => write!(w, " {}, {}", arg, lane),
|
||||||
IntCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
|
IntCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
|
||||||
IntCompareImm { cond, arg, imm, .. } => write!(w, " {} {}, {}", cond, arg, imm),
|
IntCompareImm { cond, arg, imm, .. } => write!(w, " {} {}, {}", cond, arg, imm),
|
||||||
|
IntCond { cond, arg, .. } => write!(w, " {} {}", cond, arg),
|
||||||
FloatCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
|
FloatCompare { cond, args, .. } => write!(w, " {} {}, {}", cond, args[0], args[1]),
|
||||||
|
FloatCond { cond, arg, .. } => write!(w, " {} {}", cond, arg),
|
||||||
Jump {
|
Jump {
|
||||||
destination,
|
destination,
|
||||||
ref args,
|
ref args,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if args.is_empty() {
|
write!(w, " {}", destination)?;
|
||||||
write!(w, " {}", destination)
|
write_ebb_args(w, args.as_slice(pool))
|
||||||
} else {
|
|
||||||
write!(
|
|
||||||
w,
|
|
||||||
" {}({})",
|
|
||||||
destination,
|
|
||||||
DisplayValues(args.as_slice(pool))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Branch {
|
Branch {
|
||||||
destination,
|
destination,
|
||||||
@@ -323,10 +317,27 @@ pub fn write_operands(
|
|||||||
} => {
|
} => {
|
||||||
let args = args.as_slice(pool);
|
let args = args.as_slice(pool);
|
||||||
write!(w, " {}, {}", args[0], destination)?;
|
write!(w, " {}, {}", args[0], destination)?;
|
||||||
if args.len() > 1 {
|
write_ebb_args(w, &args[1..])
|
||||||
write!(w, "({})", DisplayValues(&args[1..]))?;
|
}
|
||||||
}
|
BranchInt {
|
||||||
Ok(())
|
cond,
|
||||||
|
destination,
|
||||||
|
ref args,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let args = args.as_slice(pool);
|
||||||
|
write!(w, " {} {}, {}", cond, args[0], destination)?;
|
||||||
|
write_ebb_args(w, &args[1..])
|
||||||
|
}
|
||||||
|
BranchFloat {
|
||||||
|
cond,
|
||||||
|
destination,
|
||||||
|
ref args,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let args = args.as_slice(pool);
|
||||||
|
write!(w, " {} {}, {}", cond, args[0], destination)?;
|
||||||
|
write_ebb_args(w, &args[1..])
|
||||||
}
|
}
|
||||||
BranchIcmp {
|
BranchIcmp {
|
||||||
cond,
|
cond,
|
||||||
@@ -336,10 +347,7 @@ pub fn write_operands(
|
|||||||
} => {
|
} => {
|
||||||
let args = args.as_slice(pool);
|
let args = args.as_slice(pool);
|
||||||
write!(w, " {} {}, {}, {}", cond, args[0], args[1], destination)?;
|
write!(w, " {} {}, {}, {}", cond, args[0], args[1], destination)?;
|
||||||
if args.len() > 2 {
|
write_ebb_args(w, &args[2..])
|
||||||
write!(w, "({})", DisplayValues(&args[2..]))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
BranchTable { arg, table, .. } => write!(w, " {}, {}", arg, table),
|
BranchTable { arg, table, .. } => write!(w, " {}, {}", arg, table),
|
||||||
Call { func_ref, ref args, .. } => {
|
Call { func_ref, ref args, .. } => {
|
||||||
@@ -406,6 +414,15 @@ pub fn write_operands(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write EBB args using optional parantheses.
|
||||||
|
fn write_ebb_args(w: &mut Write, args: &[Value]) -> Result {
|
||||||
|
if args.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
write!(w, "({})", DisplayValues(args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Displayable slice of values.
|
/// Displayable slice of values.
|
||||||
struct DisplayValues<'a>(&'a [Value]);
|
struct DisplayValues<'a>(&'a [Value]);
|
||||||
|
|
||||||
|
|||||||
@@ -1975,6 +1975,38 @@ impl<'a> Parser<'a> {
|
|||||||
args: args.into_value_list(&[ctrl_arg], &mut ctx.function.dfg.value_lists),
|
args: args.into_value_list(&[ctrl_arg], &mut ctx.function.dfg.value_lists),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InstructionFormat::BranchInt => {
|
||||||
|
let cond = self.match_enum("expected intcc condition code")?;
|
||||||
|
let arg = self.match_value("expected SSA value first operand")?;
|
||||||
|
self.match_token(
|
||||||
|
Token::Comma,
|
||||||
|
"expected ',' between operands",
|
||||||
|
)?;
|
||||||
|
let ebb_num = self.match_ebb("expected branch destination EBB")?;
|
||||||
|
let args = self.parse_opt_value_list()?;
|
||||||
|
InstructionData::BranchInt {
|
||||||
|
opcode,
|
||||||
|
cond,
|
||||||
|
destination: ebb_num,
|
||||||
|
args: args.into_value_list(&[arg], &mut ctx.function.dfg.value_lists),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InstructionFormat::BranchFloat => {
|
||||||
|
let cond = self.match_enum("expected floatcc condition code")?;
|
||||||
|
let arg = self.match_value("expected SSA value first operand")?;
|
||||||
|
self.match_token(
|
||||||
|
Token::Comma,
|
||||||
|
"expected ',' between operands",
|
||||||
|
)?;
|
||||||
|
let ebb_num = self.match_ebb("expected branch destination EBB")?;
|
||||||
|
let args = self.parse_opt_value_list()?;
|
||||||
|
InstructionData::BranchFloat {
|
||||||
|
opcode,
|
||||||
|
cond,
|
||||||
|
destination: ebb_num,
|
||||||
|
args: args.into_value_list(&[arg], &mut ctx.function.dfg.value_lists),
|
||||||
|
}
|
||||||
|
}
|
||||||
InstructionFormat::BranchIcmp => {
|
InstructionFormat::BranchIcmp => {
|
||||||
let cond = self.match_enum("expected intcc condition code")?;
|
let cond = self.match_enum("expected intcc condition code")?;
|
||||||
let lhs = self.match_value("expected SSA value first operand")?;
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
@@ -1996,6 +2028,15 @@ impl<'a> Parser<'a> {
|
|||||||
args: args.into_value_list(&[lhs, rhs], &mut ctx.function.dfg.value_lists),
|
args: args.into_value_list(&[lhs, rhs], &mut ctx.function.dfg.value_lists),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InstructionFormat::BranchTable => {
|
||||||
|
let arg = self.match_value("expected SSA value operand")?;
|
||||||
|
self.match_token(
|
||||||
|
Token::Comma,
|
||||||
|
"expected ',' between operands",
|
||||||
|
)?;
|
||||||
|
let table = self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))?;
|
||||||
|
InstructionData::BranchTable { opcode, arg, table }
|
||||||
|
}
|
||||||
InstructionFormat::InsertLane => {
|
InstructionFormat::InsertLane => {
|
||||||
let lhs = self.match_value("expected SSA value first operand")?;
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
self.match_token(
|
self.match_token(
|
||||||
@@ -2052,6 +2093,11 @@ impl<'a> Parser<'a> {
|
|||||||
imm: rhs,
|
imm: rhs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InstructionFormat::IntCond => {
|
||||||
|
let cond = self.match_enum("expected intcc condition code")?;
|
||||||
|
let arg = self.match_value("expected SSA value")?;
|
||||||
|
InstructionData::IntCond { opcode, cond, arg }
|
||||||
|
}
|
||||||
InstructionFormat::FloatCompare => {
|
InstructionFormat::FloatCompare => {
|
||||||
let cond = self.match_enum("expected floatcc condition code")?;
|
let cond = self.match_enum("expected floatcc condition code")?;
|
||||||
let lhs = self.match_value("expected SSA value first operand")?;
|
let lhs = self.match_value("expected SSA value first operand")?;
|
||||||
@@ -2066,6 +2112,11 @@ impl<'a> Parser<'a> {
|
|||||||
args: [lhs, rhs],
|
args: [lhs, rhs],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InstructionFormat::FloatCond => {
|
||||||
|
let cond = self.match_enum("expected floatcc condition code")?;
|
||||||
|
let arg = self.match_value("expected SSA value")?;
|
||||||
|
InstructionData::FloatCond { opcode, cond, arg }
|
||||||
|
}
|
||||||
InstructionFormat::Call => {
|
InstructionFormat::Call => {
|
||||||
let func_ref = self.match_fn("expected function reference").and_then(
|
let func_ref = self.match_fn("expected function reference").and_then(
|
||||||
|num| {
|
|num| {
|
||||||
@@ -2121,15 +2172,6 @@ impl<'a> Parser<'a> {
|
|||||||
)?;
|
)?;
|
||||||
InstructionData::FuncAddr { opcode, func_ref }
|
InstructionData::FuncAddr { opcode, func_ref }
|
||||||
}
|
}
|
||||||
InstructionFormat::BranchTable => {
|
|
||||||
let arg = self.match_value("expected SSA value operand")?;
|
|
||||||
self.match_token(
|
|
||||||
Token::Comma,
|
|
||||||
"expected ',' between operands",
|
|
||||||
)?;
|
|
||||||
let table = self.match_jt().and_then(|num| ctx.get_jt(num, &self.loc))?;
|
|
||||||
InstructionData::BranchTable { opcode, arg, table }
|
|
||||||
}
|
|
||||||
InstructionFormat::StackLoad => {
|
InstructionFormat::StackLoad => {
|
||||||
let ss = self.match_ss("expected stack slot number: ss«n»")
|
let ss = self.match_ss("expected stack slot number: ss«n»")
|
||||||
.and_then(|num| ctx.get_ss(num, &self.loc))?;
|
.and_then(|num| ctx.get_ss(num, &self.loc))?;
|
||||||
|
|||||||
Reference in New Issue
Block a user