From 15fe9c7c933d18ceed25d9843af5f995cb0d05eb Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Thu, 9 Feb 2023 14:24:04 -0800 Subject: [PATCH] Inline jump tables in parsed br_table instructions (#5755) As jump tables are used by at most one br_table instruction, inline their definition in those instructions instead of requiring them to be declared as function-level metadata. --- cranelift/codegen/src/ir/jumptable.rs | 6 +- cranelift/codegen/src/verifier/mod.rs | 13 +-- cranelift/codegen/src/write.rs | 8 +- .../filetests/egraph/issue-5437.clif | 3 +- .../filetests/egraph/issue-5716.clif | 3 +- .../filetests/filetests/isa/aarch64/bti.clif | 8 +- .../filetests/isa/aarch64/jumptable.clif | 4 +- .../filetests/isa/s390x/jumptable.clif | 4 +- .../filetests/isa/x64/atomic-cas-bug.clif | 3 +- .../filetests/filetests/isa/x64/branches.clif | 4 +- .../isa/x64/unused_jt_unreachable_block.clif | 22 ----- .../filetests/filetests/licm/br-table.clif | 3 +- .../filetests/licm/rewrite-jump-table.clif | 4 +- .../filetests/filetests/parser/branch.clif | 9 +- .../filetests/runtests/br_table.clif | 10 +- .../filetests/verifier/jump_table.clif | 8 +- .../filetests/verifier/type_check.clif | 3 +- .../filetests/filetests/wasm/control.clif | 4 +- cranelift/frontend/src/ssa.rs | 3 +- cranelift/frontend/src/switch.rs | 33 +++---- cranelift/reader/src/lexer.rs | 2 - cranelift/reader/src/parser.rs | 95 +++---------------- cranelift/reader/src/sourcemap.rs | 2 - 23 files changed, 54 insertions(+), 200 deletions(-) delete mode 100644 cranelift/filetests/filetests/isa/x64/unused_jt_unreachable_block.clif diff --git a/cranelift/codegen/src/ir/jumptable.rs b/cranelift/codegen/src/ir/jumptable.rs index 3f2cdb8fb1..f92ae1162c 100644 --- a/cranelift/codegen/src/ir/jumptable.rs +++ b/cranelift/codegen/src/ir/jumptable.rs @@ -81,7 +81,7 @@ impl JumpTableData { impl Display for JumpTableData { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - write!(fmt, "jump_table [")?; + write!(fmt, "[")?; match self.table.first() { None => (), Some(first) => write!(fmt, "{}", first)?, @@ -107,7 +107,7 @@ mod tests { assert_eq!(jt.as_slice().get(0), None); assert_eq!(jt.as_slice().get(10), None); - assert_eq!(jt.to_string(), "jump_table []"); + assert_eq!(jt.to_string(), "[]"); let v = jt.as_slice(); assert_eq!(v, []); @@ -124,7 +124,7 @@ mod tests { jt.push_entry(e2); jt.push_entry(e1); - assert_eq!(jt.to_string(), "jump_table [block1, block2, block1]"); + assert_eq!(jt.to_string(), "[block1, block2, block1]"); let v = jt.as_slice(); assert_eq!(v, [e1, e2, e1]); diff --git a/cranelift/codegen/src/verifier/mod.rs b/cranelift/codegen/src/verifier/mod.rs index f17f8cb621..e9fff15ff4 100644 --- a/cranelift/codegen/src/verifier/mod.rs +++ b/cranelift/codegen/src/verifier/mod.rs @@ -446,15 +446,6 @@ impl<'a> Verifier<'a> { Ok(()) } - fn verify_jump_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { - for (jt, jt_data) in &self.func.stencil.dfg.jump_tables { - for &block in jt_data.iter() { - self.verify_block(jt, block, errors)?; - } - } - Ok(()) - } - /// Check that the given block can be encoded as a BB, by checking that only /// branching instructions are ending the block. fn encodable_as_bb(&self, block: Block, errors: &mut VerifierErrors) -> VerifierStepResult<()> { @@ -861,6 +852,9 @@ impl<'a> Verifier<'a> { format!("invalid jump table reference {}", j), )) } else { + for &block in self.func.stencil.dfg.jump_tables[j].as_slice() { + self.verify_block(inst, block, errors)?; + } Ok(()) } } @@ -1792,7 +1786,6 @@ impl<'a> Verifier<'a> { pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { self.verify_global_values(errors)?; self.verify_tables(errors)?; - self.verify_jump_tables(errors)?; self.typecheck_entry_block_params(errors)?; self.check_entry_not_cold(errors)?; self.typecheck_function_signature(errors)?; diff --git a/cranelift/codegen/src/write.rs b/cranelift/codegen/src/write.rs index 90d8e14d87..0b4c1d9da4 100644 --- a/cranelift/codegen/src/write.rs +++ b/cranelift/codegen/src/write.rs @@ -82,11 +82,6 @@ pub trait FuncWriter { } } - for (jt, jt_data) in &func.stencil.dfg.jump_tables { - any = true; - self.write_entity_definition(w, func, jt.into(), jt_data)?; - } - for (&cref, cval) in func.dfg.constants.iter() { any = true; self.write_entity_definition(w, func, cref.into(), cval)?; @@ -377,6 +372,7 @@ fn write_instruction( /// Write the operands of `inst` to `w` with a prepended space. pub fn write_operands(w: &mut dyn Write, dfg: &DataFlowGraph, inst: Inst) -> fmt::Result { let pool = &dfg.value_lists; + let jump_tables = &dfg.jump_tables; use crate::ir::instructions::InstructionData::*; match dfg.insts[inst] { AtomicRmw { op, args, .. } => write!(w, " {} {}, {}", op, args[0], args[1]), @@ -430,7 +426,7 @@ pub fn write_operands(w: &mut dyn Write, dfg: &DataFlowGraph, inst: Inst) -> fmt destination, table, .. - } => write!(w, " {}, {}, {}", arg, destination, table), + } => write!(w, " {}, {}, {}", arg, destination, jump_tables[table]), Call { func_ref, ref args, .. } => write!(w, " {}({})", func_ref, DisplayValues(args.as_slice(pool))), diff --git a/cranelift/filetests/filetests/egraph/issue-5437.clif b/cranelift/filetests/filetests/egraph/issue-5437.clif index c3c40af43a..d20d8d2072 100644 --- a/cranelift/filetests/filetests/egraph/issue-5437.clif +++ b/cranelift/filetests/filetests/egraph/issue-5437.clif @@ -11,7 +11,6 @@ function u0:0(i64 vmctx, i64) fast { gv2 = load.i64 notrap aligned gv1 sig0 = (i64 vmctx, i64) fast fn0 = colocated u0:2 sig0 - jt0 = jump_table [block1] stack_limit = gv2 block0(v0: i64, v1: i64): @@ -33,7 +32,7 @@ function u0:0(i64 vmctx, i64) fast { block4: @002e call fn0(v0, v0) -@0030 br_table v8, block1, jt0 +@0030 br_table v8, block1, [block1] block1: @0036 return diff --git a/cranelift/filetests/filetests/egraph/issue-5716.clif b/cranelift/filetests/filetests/egraph/issue-5716.clif index 7763d3eac8..35d2aaa960 100644 --- a/cranelift/filetests/filetests/egraph/issue-5716.clif +++ b/cranelift/filetests/filetests/egraph/issue-5716.clif @@ -17,7 +17,6 @@ function u0:33() system_v { ss0 = explicit_slot 32 sig0 = (i64, i64, i64, i64, i64) -> i64, i64 system_v fn0 = colocated u0:0 sig0 -jt0 = jump_table [block36, block38] block0: v80 = iconst.i32 0 v91 = iconst.i64 0 @@ -28,7 +27,7 @@ block0: v237 = iconst.i64 0 v238, v239 = call fn0(v236, v237, v91, v92, v235) ; v236 = 0, v237 = 0, v91 = 0, v92 = 0, v235 = 0 v97 = iadd v238, v96 ; v96 = 0 - br_table v80, block37, jt0 ; v80 = 0 + br_table v80, block37, [block36, block38] ; v80 = 0 block36: trap user0 block37: diff --git a/cranelift/filetests/filetests/isa/aarch64/bti.clif b/cranelift/filetests/filetests/isa/aarch64/bti.clif index 531593a1da..3163de489f 100644 --- a/cranelift/filetests/filetests/isa/aarch64/bti.clif +++ b/cranelift/filetests/filetests/isa/aarch64/bti.clif @@ -3,10 +3,8 @@ set unwind_info=false target aarch64 use_bti function %f1(i32) -> i32 { - jt0 = jump_table [block1, block2, block3] - block0(v0: i32): - br_table v0, block4, jt0 + br_table v0, block4, [block1, block2, block3] block1: v1 = iconst.i32 1 @@ -62,12 +60,10 @@ block5(v5: i32): ; ret function %f2(i64) -> i64 { - jt0 = jump_table [block2] - block0(v0: i64): v1 = ireduce.i32 v0 v2 = load.i64 notrap aligned table v0 - br_table v1, block1, jt0 + br_table v1, block1, [block2] block1: return v2 diff --git a/cranelift/filetests/filetests/isa/aarch64/jumptable.clif b/cranelift/filetests/filetests/isa/aarch64/jumptable.clif index c4ab852848..1b2b2fd09b 100644 --- a/cranelift/filetests/filetests/isa/aarch64/jumptable.clif +++ b/cranelift/filetests/filetests/isa/aarch64/jumptable.clif @@ -3,10 +3,8 @@ set unwind_info=false target aarch64 function %f(i32) -> i32 { - jt0 = jump_table [block1, block2, block3] - block0(v0: i32): - br_table v0, block4, jt0 + br_table v0, block4, [block1, block2, block3] block1: v1 = iconst.i32 1 diff --git a/cranelift/filetests/filetests/isa/s390x/jumptable.clif b/cranelift/filetests/filetests/isa/s390x/jumptable.clif index 3a2cbdef83..e40aa747f3 100644 --- a/cranelift/filetests/filetests/isa/s390x/jumptable.clif +++ b/cranelift/filetests/filetests/isa/s390x/jumptable.clif @@ -2,10 +2,8 @@ test compile precise-output target s390x function %f(i32) -> i32 { - jt0 = jump_table [block1, block2, block3] - block0(v0: i32): - br_table v0, block4, jt0 + br_table v0, block4, [block1, block2, block3] block1: v1 = iconst.i32 1 diff --git a/cranelift/filetests/filetests/isa/x64/atomic-cas-bug.clif b/cranelift/filetests/filetests/isa/x64/atomic-cas-bug.clif index 7164a356e1..822cd10e8c 100644 --- a/cranelift/filetests/filetests/isa/x64/atomic-cas-bug.clif +++ b/cranelift/filetests/filetests/isa/x64/atomic-cas-bug.clif @@ -34,7 +34,6 @@ function u0:31(i64, i32, i32, i8, i8) -> i32, i32 system_v { fn3 = colocated u0:11 sig3 fn4 = u0:110 sig4 fn5 = u0:110 sig5 - jt0 = jump_table [block2, block4, block5, block6, block7] block0(v0: i64, v1: i32, v2: i32, v3: i8, v4: i8): v34 -> v0 @@ -82,7 +81,7 @@ function u0:31(i64, i32, i32, i8, i8) -> i32, i32 system_v { @0005 jump block37 block37: -@0005 br_table v10, block36, jt0 +@0005 br_table v10, block36, [block2, block4, block5, block6, block7] block2: @0001 v11 = stack_load.i8 ss3+1 diff --git a/cranelift/filetests/filetests/isa/x64/branches.clif b/cranelift/filetests/filetests/isa/x64/branches.clif index ed05b5325a..d2dc7d9698 100644 --- a/cranelift/filetests/filetests/isa/x64/branches.clif +++ b/cranelift/filetests/filetests/isa/x64/branches.clif @@ -181,10 +181,8 @@ block2: ; ret function %f5(i32) -> i8 { - jt0 = jump_table [block1, block2] - block0(v0: i32): - br_table v0, block1, jt0 + br_table v0, block1, [block1, block2] block1: v1 = iconst.i8 1 diff --git a/cranelift/filetests/filetests/isa/x64/unused_jt_unreachable_block.clif b/cranelift/filetests/filetests/isa/x64/unused_jt_unreachable_block.clif deleted file mode 100644 index 7160805ddb..0000000000 --- a/cranelift/filetests/filetests/isa/x64/unused_jt_unreachable_block.clif +++ /dev/null @@ -1,22 +0,0 @@ -test compile precise-output -target x86_64 - -;; From: https://github.com/bytecodealliance/wasmtime/issues/2670 - -function %f() system_v { - jt0 = jump_table [block1] - -block0: - return - -block1: - trap unreachable -} - -; pushq %rbp -; movq %rsp, %rbp -; block0: -; movq %rbp, %rsp -; popq %rbp -; ret - diff --git a/cranelift/filetests/filetests/licm/br-table.clif b/cranelift/filetests/filetests/licm/br-table.clif index 8e2f042558..3710f74210 100644 --- a/cranelift/filetests/filetests/licm/br-table.clif +++ b/cranelift/filetests/filetests/licm/br-table.clif @@ -4,11 +4,10 @@ target aarch64 target x86_64 function %br_table_opt() { - jt0 = jump_table [block1, block2] block0: v0 = iconst.i32 1 - br_table v0, block2, jt0 + br_table v0, block2, [block1, block2] block1: return diff --git a/cranelift/filetests/filetests/licm/rewrite-jump-table.clif b/cranelift/filetests/filetests/licm/rewrite-jump-table.clif index 7899f89752..a4a00c62c5 100644 --- a/cranelift/filetests/filetests/licm/rewrite-jump-table.clif +++ b/cranelift/filetests/filetests/licm/rewrite-jump-table.clif @@ -2,11 +2,10 @@ test licm target aarch64 function %rewrite_jump_table() { - jt0 = jump_table [block1, block2] block0: v0 = iconst.i32 1 - br_table v0, block1, jt0 + br_table v0, block1, [block1, block2] block1: return @@ -17,7 +16,6 @@ function %rewrite_jump_table() { } ; sameln: function -; nextln: jt0 = jump_table [block1, block3] ; check: block3: ; nextln: v4 = iconst.i8 0 ; nextln: jump block2 diff --git a/cranelift/filetests/filetests/parser/branch.clif b/cranelift/filetests/filetests/parser/branch.clif index 708f7cdcb3..305b3328f5 100644 --- a/cranelift/filetests/filetests/parser/branch.clif +++ b/cranelift/filetests/filetests/parser/branch.clif @@ -81,11 +81,8 @@ block1(v92: i32, v93: f32): ; nextln: } function %jumptable(i32) { - jt200 = jump_table [] - jt2 = jump_table [block10, block40, block20, block30] - block10(v3: i32): - br_table v3, block50, jt2 + br_table v3, block50, [block10, block40, block20, block30] block20: trap user2 @@ -97,10 +94,8 @@ block50: trap user1 } ; sameln: function %jumptable(i32) fast { -; check: jt2 = jump_table [block10, block40, block20, block30] -; check: jt200 = jump_table [] ; check: block10(v3: i32): -; nextln: br_table v3, block50, jt2 +; nextln: br_table v3, block50, [block10, block40, block20, block30] ; nextln: ; nextln: block20: ; nextln: trap user2 diff --git a/cranelift/filetests/filetests/runtests/br_table.clif b/cranelift/filetests/filetests/runtests/br_table.clif index 8d08bf355b..bc1635b5eb 100644 --- a/cranelift/filetests/filetests/runtests/br_table.clif +++ b/cranelift/filetests/filetests/runtests/br_table.clif @@ -7,10 +7,8 @@ target s390x target riscv64 function %br_table_i32(i32) -> i32 { - jt0 = jump_table [block1, block2, block2, block3] - block0(v0: i32): - br_table v0, block4, jt0 + br_table v0, block4, [block1, block2, block2, block3] block1: v1 = iconst.i32 1 @@ -46,17 +44,15 @@ block5(v5: i32): ; RISC-V had a bug where having a br_table on a cold block would cause a segfault ; See #5496 for more details. function %br_table_cold_block(i32) -> i32 system_v { - jt0 = jump_table [] - block0(v0: i32): jump block1 block1 cold: - br_table v0, block2, jt0 + br_table v0, block2, [] block2: v1 = iconst.i32 0 return v1 } ; run: %br_table_cold_block(0) == 0 -; run: %br_table_cold_block(1) == 0 \ No newline at end of file +; run: %br_table_cold_block(1) == 0 diff --git a/cranelift/filetests/filetests/verifier/jump_table.clif b/cranelift/filetests/filetests/verifier/jump_table.clif index 8302a636c5..2238d9f004 100644 --- a/cranelift/filetests/filetests/verifier/jump_table.clif +++ b/cranelift/filetests/filetests/verifier/jump_table.clif @@ -1,19 +1,15 @@ test verifier function %br_invalid_default(i32) { - jt0 = jump_table [block1, block1] - block0(v0: i32): - br_table v0, block2, jt0 ; error: invalid block reference block2 + br_table v0, block2, [block1, block1] ; error: invalid block reference block2 block1: return } function %br(i32) { - jt0 = jump_table [block1, block2] ; error: invalid block reference block2 - block0(v0: i32): - br_table v0, block1, jt0 + br_table v0, block1, [block1, block3] ; error: invalid block reference block3 block1: return } diff --git a/cranelift/filetests/filetests/verifier/type_check.clif b/cranelift/filetests/filetests/verifier/type_check.clif index ff3e8fcf91..1b3fb5c7b0 100644 --- a/cranelift/filetests/filetests/verifier/type_check.clif +++ b/cranelift/filetests/filetests/verifier/type_check.clif @@ -66,10 +66,9 @@ function %fn_call_incorrect_arg_type(i64) { ; TODO: Should we instead just verify that jump tables contain no blocks that take arguments? This ; error doesn't occur if no instruction uses the jump table. function %jump_table_args() { - jt1 = jump_table [block1] block0: v0 = iconst.i32 0 - br_table v0, block2, jt1 ; error: takes no arguments, but had target block1 with 1 arguments + br_table v0, block2, [block1] ; error: takes no arguments, but had target block1 with 1 arguments block1(v5: i32): return diff --git a/cranelift/filetests/filetests/wasm/control.clif b/cranelift/filetests/filetests/wasm/control.clif index e5f355371d..4916d2b0f8 100644 --- a/cranelift/filetests/filetests/wasm/control.clif +++ b/cranelift/filetests/filetests/wasm/control.clif @@ -45,10 +45,8 @@ block0: } function %br_table(i32) { -jt0 = jump_table [block3, block1, block2] - block0(v0: i32): - br_table v0, block4, jt0 + br_table v0, block4, [block3, block1, block2] block4: trap heap_oob diff --git a/cranelift/frontend/src/ssa.rs b/cranelift/frontend/src/ssa.rs index cfcf292a40..d6c852e2f6 100644 --- a/cranelift/frontend/src/ssa.rs +++ b/cranelift/frontend/src/ssa.rs @@ -985,10 +985,9 @@ mod tests { // Here is the pseudo-program we want to translate: // // function %f { - // jt = jump_table [block2, block1] // block0: // x = 1; - // br_table x, block2, jt + // br_table x, block2, [block2, block1] // block1: // x = 2 // jump block2 diff --git a/cranelift/frontend/src/switch.rs b/cranelift/frontend/src/switch.rs index 1e6c3d930a..f7ff7f8743 100644 --- a/cranelift/frontend/src/switch.rs +++ b/cranelift/frontend/src/switch.rs @@ -416,12 +416,10 @@ mod tests { let func = setup!(0, [0, 1,]); assert_eq_output!( func, - " jt0 = jump_table [block1, block2] - -block0: + "block0: v0 = iconst.i8 0 v1 = uextend.i32 v0 ; v0 = 0 - br_table v1, block0, jt0" + br_table v1, block0, [block1, block2]" ); } @@ -445,10 +443,7 @@ block3: let func = setup!(0, [0, 1, 5, 7, 10, 11, 12,]); assert_eq_output!( func, - " jt0 = jump_table [block5, block6, block7] - jt1 = jump_table [block1, block2] - -block0: + "block0: v0 = iconst.i8 0 v1 = icmp_imm uge v0, 7 ; v0 = 0 brif v1, block9, block8 @@ -460,7 +455,7 @@ block9: block11: v3 = iadd_imm.i8 v0, -10 ; v0 = 0 v4 = uextend.i32 v3 - br_table v4, block0, jt0 + br_table v4, block0, [block5, block6, block7] block10: v5 = icmp_imm.i8 eq v0, 7 ; v0 = 0 @@ -472,7 +467,7 @@ block8: block12: v7 = uextend.i32 v0 ; v0 = 0 - br_table v7, block0, jt1" + br_table v7, block0, [block1, block2]" ); } @@ -513,16 +508,14 @@ block3: let func = setup!(0, [-1i8 as u8 as u128, 0, 1,]); assert_eq_output!( func, - " jt0 = jump_table [block2, block3] - -block0: + "block0: v0 = iconst.i8 0 v1 = icmp_imm eq v0, 255 ; v0 = 0 brif v1, block1, block4 block4: v2 = uextend.i32 v0 ; v0 = 0 - br_table v2, block0, jt0" + br_table v2, block0, [block2, block3]" ); } @@ -607,16 +600,14 @@ block4: .to_string(); assert_eq_output!( func, - " jt0 = jump_table [block2, block1] - -block0: + "block0: v0 = iconst.i64 0 v1 = icmp_imm ugt v0, 0xffff_ffff ; v0 = 0 brif v1, block3, block4 block4: v2 = ireduce.i32 v0 ; v0 = 0 - br_table v2, block3, jt0" + br_table v2, block3, [block2, block1]" ); } @@ -645,9 +636,7 @@ block4: .to_string(); assert_eq_output!( func, - " jt0 = jump_table [block2, block1] - -block0: + "block0: v0 = iconst.i64 0 v1 = uextend.i128 v0 ; v0 = 0 v2 = icmp_imm ugt v1, 0xffff_ffff @@ -655,7 +644,7 @@ block0: block4: v3 = ireduce.i32 v1 - br_table v3, block3, jt0" + br_table v3, block3, [block2, block1]" ); } } diff --git a/cranelift/reader/src/lexer.rs b/cranelift/reader/src/lexer.rs index 6622c52549..2fd1037c3c 100644 --- a/cranelift/reader/src/lexer.rs +++ b/cranelift/reader/src/lexer.rs @@ -41,7 +41,6 @@ pub enum Token<'a> { DynamicStackSlot(u32), // dss4 GlobalValue(u32), // gv3 Table(u32), // table2 - JumpTable(u32), // jt2 Constant(u32), // const2 FuncRef(u32), // fn2 SigRef(u32), // sig2 @@ -346,7 +345,6 @@ impl<'a> Lexer<'a> { "dt" => Some(Token::DynamicType(number)), "gv" => Some(Token::GlobalValue(number)), "table" => Some(Token::Table(number)), - "jt" => Some(Token::JumpTable(number)), "const" => Some(Token::Constant(number)), "fn" => Some(Token::FuncRef(number)), "sig" => Some(Token::SigRef(number)), diff --git a/cranelift/reader/src/parser.rs b/cranelift/reader/src/parser.rs index 94be7b13f7..2154219bb4 100644 --- a/cranelift/reader/src/parser.rs +++ b/cranelift/reader/src/parser.rs @@ -18,8 +18,8 @@ use cranelift_codegen::ir::{self, UserExternalNameRef}; use cranelift_codegen::ir::{ AbiParam, ArgumentExtension, ArgumentPurpose, Block, Constant, ConstantData, DynamicStackSlot, DynamicStackSlotData, DynamicTypeData, ExtFuncData, ExternalName, FuncRef, Function, - GlobalValue, GlobalValueData, JumpTable, JumpTableData, MemFlags, Opcode, SigRef, Signature, - StackSlot, StackSlotData, StackSlotKind, Table, TableData, Type, UserFuncName, Value, + GlobalValue, GlobalValueData, JumpTableData, MemFlags, Opcode, SigRef, Signature, StackSlot, + StackSlotData, StackSlotKind, Table, TableData, Type, UserFuncName, Value, }; use cranelift_codegen::isa::{self, CallConv}; use cranelift_codegen::packed_option::ReservedValue; @@ -390,25 +390,6 @@ impl Context { } } - // Allocate a new jump table. - fn add_jt(&mut self, jt: JumpTable, data: JumpTableData, loc: Location) -> ParseResult<()> { - self.map.def_jt(jt, loc)?; - while self.function.stencil.dfg.jump_tables.next_key().index() <= jt.index() { - self.function.create_jump_table(JumpTableData::new()); - } - self.function.stencil.dfg.jump_tables[jt] = data; - Ok(()) - } - - // Resolve a reference to a jump table. - fn check_jt(&self, jt: JumpTable, loc: Location) -> ParseResult<()> { - if !self.map.contains_jt(jt) { - err!(loc, "undefined jump table {}", jt) - } else { - Ok(()) - } - } - // Allocate a new constant. fn add_constant( &mut self, @@ -670,17 +651,6 @@ impl<'a> Parser<'a> { err!(self.loc, err_msg) } - // Match and consume a jump table reference. - fn match_jt(&mut self) -> ParseResult { - if let Some(Token::JumpTable(jt)) = self.token() { - self.consume(); - if let Some(jt) = JumpTable::with_number(jt) { - return Ok(jt); - } - } - err!(self.loc, "expected jump table number: jt«n»") - } - // Match and consume a constant reference. fn match_constant(&mut self) -> ParseResult { if let Some(Token::Constant(c)) = self.token() { @@ -1484,11 +1454,6 @@ impl<'a> Parser<'a> { self.parse_function_decl(ctx) .and_then(|(fn_, dat)| ctx.add_fn(fn_, dat, self.loc)) } - Some(Token::JumpTable(..)) => { - self.start_gathering_comments(); - self.parse_jump_table_decl() - .and_then(|(jt, dat)| ctx.add_jt(jt, dat, self.loc)) - } Some(Token::Constant(..)) => { self.start_gathering_comments(); self.parse_constant_decl() @@ -1798,18 +1763,15 @@ impl<'a> Parser<'a> { Ok((fn_, data)) } - // Parse a jump table decl. + // Parse a jump table literal. // - // jump-table-decl ::= * JumpTable(jt) "=" "jump_table" "[" jt-entry {"," jt-entry} "]" - fn parse_jump_table_decl(&mut self) -> ParseResult<(JumpTable, JumpTableData)> { - let jt = self.match_jt()?; - self.match_token(Token::Equal, "expected '=' in jump_table decl")?; - self.match_identifier("jump_table", "expected 'jump_table'")?; + // jump-table-lit ::= "[" block {"," block } "]" + // | "[]" + fn parse_jump_table(&mut self) -> ParseResult { self.match_token(Token::LBracket, "expected '[' before jump table contents")?; let mut data = JumpTableData::new(); - // jump-table-decl ::= JumpTable(jt) "=" "jump_table" "[" * Block(dest) {"," Block(dest)} "]" match self.token() { Some(Token::Block(dest)) => { self.consume(); @@ -1837,11 +1799,7 @@ impl<'a> Parser<'a> { self.consume(); - // Collect any trailing comments. - self.token(); - self.claim_gathered_comments(jt); - - Ok((jt, data)) + Ok(data) } // Parse a constant decl. @@ -2613,8 +2571,8 @@ impl<'a> Parser<'a> { self.match_token(Token::Comma, "expected ',' between operands")?; let block_num = self.match_block("expected branch destination block")?; self.match_token(Token::Comma, "expected ',' between operands")?; - let table = self.match_jt()?; - ctx.check_jt(table, self.loc)?; + let table_data = self.parse_jump_table()?; + let table = ctx.function.dfg.jump_tables.push(table_data); InstructionData::BranchTable { opcode, arg, @@ -3079,25 +3037,6 @@ mod tests { assert!(!is_warning); } - #[test] - fn duplicate_jt() { - let ParseError { - location, - message, - is_warning, - } = Parser::new( - "function %blocks() system_v { - jt0 = jump_table [] - jt0 = jump_table []", - ) - .parse_function() - .unwrap_err(); - - assert_eq!(location.line_number, 3); - assert_eq!(message, "duplicate entity: jt0"); - assert!(!is_warning); - } - #[test] fn duplicate_ss() { let ParseError { @@ -3182,8 +3121,6 @@ mod tests { function %comment() system_v { ; decl ss10 = explicit_slot 13 ; stackslot. ; Still stackslot. - jt10 = jump_table [block0] - ; Jumptable block0: ; Basic block trap user42; Instruction } ; Trailing. @@ -3192,7 +3129,7 @@ mod tests { .parse_function() .unwrap(); assert_eq!(func.name.to_string(), "%comment"); - assert_eq!(comments.len(), 8); // no 'before' comment. + assert_eq!(comments.len(), 7); // no 'before' comment. assert_eq!( comments[0], Comment { @@ -3203,16 +3140,14 @@ mod tests { assert_eq!(comments[1].entity.to_string(), "ss10"); assert_eq!(comments[2].entity.to_string(), "ss10"); assert_eq!(comments[2].text, "; Still stackslot."); - assert_eq!(comments[3].entity.to_string(), "jt10"); - assert_eq!(comments[3].text, "; Jumptable"); - assert_eq!(comments[4].entity.to_string(), "block0"); - assert_eq!(comments[4].text, "; Basic block"); + assert_eq!(comments[3].entity.to_string(), "block0"); + assert_eq!(comments[3].text, "; Basic block"); - assert_eq!(comments[5].entity.to_string(), "inst0"); - assert_eq!(comments[5].text, "; Instruction"); + assert_eq!(comments[4].entity.to_string(), "inst0"); + assert_eq!(comments[4].text, "; Instruction"); + assert_eq!(comments[5].entity, AnyEntity::Function); assert_eq!(comments[6].entity, AnyEntity::Function); - assert_eq!(comments[7].entity, AnyEntity::Function); } #[test] diff --git a/cranelift/reader/src/sourcemap.rs b/cranelift/reader/src/sourcemap.rs index 57be4d55ee..d8c21ebb10 100644 --- a/cranelift/reader/src/sourcemap.rs +++ b/cranelift/reader/src/sourcemap.rs @@ -227,7 +227,6 @@ mod tests { let tf = parse_test( "function %detail() { ss10 = explicit_slot 13 - jt10 = jump_table [block0] block0(v4: i32, v7: i32): v10 = iadd v4, v7 }", @@ -239,7 +238,6 @@ mod tests { assert_eq!(map.lookup_str("v0"), None); assert_eq!(map.lookup_str("ss1"), None); assert_eq!(map.lookup_str("ss10").unwrap().to_string(), "ss10"); - assert_eq!(map.lookup_str("jt10").unwrap().to_string(), "jt10"); assert_eq!(map.lookup_str("block0").unwrap().to_string(), "block0"); assert_eq!(map.lookup_str("v4").unwrap().to_string(), "v4"); assert_eq!(map.lookup_str("v7").unwrap().to_string(), "v7");