diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_1_case.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_1_case.hir index f2d45ac2d..69c0eb58b 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_1_case.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_1_case.hir @@ -1,13 +1,13 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } default { - ^block2: + ^block3: v4 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v4; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_2_cases.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_2_cases.hir index e08c6b981..679fa22ef 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_2_cases.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_2_cases.hir @@ -1,18 +1,18 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } case 1 { - ^block2: + ^block3: v4 = arith.constant 1 : u32; scf.yield v4; } default { - ^block3: + ^block4: v5 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v5; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_3_cases.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_3_cases.hir index 3d43af5b5..d4a214516 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_3_cases.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_3_cases.hir @@ -1,23 +1,23 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } case 1 { - ^block2: + ^block3: v4 = arith.constant 1 : u32; scf.yield v4; } case 2 { - ^block3: + ^block4: v5 = arith.constant 2 : u32; scf.yield v5; } default { - ^block4: + ^block5: v6 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v6; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_4_cases.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_4_cases.hir index 3dc46fe2c..0e5fed5ea 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_4_cases.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_4_cases.hir @@ -1,28 +1,28 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } case 1 { - ^block2: + ^block3: v4 = arith.constant 1 : u32; scf.yield v4; } case 2 { - ^block3: + ^block4: v5 = arith.constant 2 : u32; scf.yield v5; } case 3 { - ^block4: + ^block5: v6 = arith.constant 3 : u32; scf.yield v6; } default { - ^block5: + ^block6: v7 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v7; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_5_cases.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_5_cases.hir index 17a279636..014e7b023 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_5_cases.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_5_cases.hir @@ -1,33 +1,33 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } case 1 { - ^block2: + ^block3: v4 = arith.constant 1 : u32; scf.yield v4; } case 2 { - ^block3: + ^block4: v5 = arith.constant 2 : u32; scf.yield v5; } case 3 { - ^block4: + ^block5: v6 = arith.constant 3 : u32; scf.yield v6; } case 4 { - ^block5: + ^block6: v7 = arith.constant 4 : u32; scf.yield v7; } default { - ^block6: + ^block7: v8 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v8; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_binary_search_7_cases.hir b/codegen/masm/src/lower/expected/utils_emit_binary_search_7_cases.hir index a671639e2..9396b6f00 100644 --- a/codegen/masm/src/lower/expected/utils_emit_binary_search_7_cases.hir +++ b/codegen/masm/src/lower/expected/utils_emit_binary_search_7_cases.hir @@ -1,43 +1,43 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = scf.index_switch v0 : u32 case 0 { - ^block1: + ^block2: v3 = arith.constant 0 : u32; scf.yield v3; } case 1 { - ^block2: + ^block3: v4 = arith.constant 1 : u32; scf.yield v4; } case 2 { - ^block3: + ^block4: v5 = arith.constant 2 : u32; scf.yield v5; } case 3 { - ^block4: + ^block5: v6 = arith.constant 3 : u32; scf.yield v6; } case 4 { - ^block5: + ^block6: v7 = arith.constant 4 : u32; scf.yield v7; } case 5 { - ^block6: + ^block7: v8 = arith.constant 5 : u32; scf.yield v8; } case 6 { - ^block7: + ^block8: v9 = arith.constant 6 : u32; scf.yield v9; } default { - ^block8: + ^block9: v10 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v10; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_if.hir b/codegen/masm/src/lower/expected/utils_emit_if.hir index bf547b88f..19b72f4a2 100644 --- a/codegen/masm/src/lower/expected/utils_emit_if.hir +++ b/codegen/masm/src/lower/expected/utils_emit_if.hir @@ -1,13 +1,13 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = arith.constant 0 : u32; v3 = arith.eq v0, v1 : i1; v4 = scf.if v3 : u32 { - ^block1: + ^block2: v5 = arith.constant 1 : u32; scf.yield v5; } else { - ^block2: + ^block3: v6 = arith.mul v0, v2 : u32 #[overflow = checked]; scf.yield v6; }; diff --git a/codegen/masm/src/lower/expected/utils_emit_if_nested.hir b/codegen/masm/src/lower/expected/utils_emit_if_nested.hir index 12b4722bf..2ae841239 100644 --- a/codegen/masm/src/lower/expected/utils_emit_if_nested.hir +++ b/codegen/masm/src/lower/expected/utils_emit_if_nested.hir @@ -1,19 +1,19 @@ public builtin.function @test(v0: u32, v1: u32) -> u32 { -^block0(v0: u32, v1: u32): +^block1(v0: u32, v1: u32): v2 = arith.eq v0, v1 : i1; v3 = scf.if v2 : u32 { - ^block1: + ^block2: v4 = arith.constant 1 : u32; scf.yield v4; } else { - ^block2: + ^block3: v5 = arith.lt v0, v1 : i1; v6 = scf.if v5 : u32 { - ^block3: + ^block4: v7 = arith.constant 2 : u32; scf.yield v7; } else { - ^block4: + ^block5: v8 = arith.mul v0, v1 : u32 #[overflow = checked]; scf.yield v8; }; diff --git a/codegen/masm/src/lower/utils.rs b/codegen/masm/src/lower/utils.rs index 6cd932b4c..aecf54579 100644 --- a/codegen/masm/src/lower/utils.rs +++ b/codegen/masm/src/lower/utils.rs @@ -493,11 +493,11 @@ mod tests { use midenc_dialect_scf::StructuredControlFlowOpBuilder; use midenc_expect_test::expect_file; use midenc_hir::{ - dialects::builtin::{self, BuiltinOpBuilder, FunctionBuilder, FunctionRef}, + dialects::builtin::{self, BuiltinOpBuilder, FunctionBuilder, FunctionRef, WorldBuilder}, formatter::PrettyPrint, pass::AnalysisManager, version::Version, - AbiParam, Context, Ident, OpBuilder, Signature, Type, + AbiParam, BuilderExt, Context, Ident, OpBuilder, Signature, SymbolTable, Type, }; use midenc_hir_analysis::analyses::LivenessAnalysis; @@ -511,12 +511,18 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function_ref = builder.create_function( Ident::with_empty_span("test".into()), Signature::new( [AbiParam::new(Type::U32), AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)], ), + world, )?; let (a, b) = { @@ -597,12 +603,18 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function_ref = builder.create_function( Ident::with_empty_span("test".into()), Signature::new( [AbiParam::new(Type::U32), AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)], ), + world, )?; let (a, b) = { @@ -826,12 +838,18 @@ mod tests { ) -> Result<(FunctionRef, masm::Block), Report> { let mut builder = OpBuilder::new(context.clone()); + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function_ref = builder.create_function( Ident::with_empty_span("test".into()), Signature::new( [AbiParam::new(Type::U32), AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)], ), + world, )?; let (a, b) = { diff --git a/dialects/scf/src/transforms/cfg_to_scf.rs b/dialects/scf/src/transforms/cfg_to_scf.rs index 014200089..51bc43cf3 100644 --- a/dialects/scf/src/transforms/cfg_to_scf.rs +++ b/dialects/scf/src/transforms/cfg_to_scf.rs @@ -373,7 +373,7 @@ mod tests { use midenc_expect_test::expect_file; use midenc_hir::{ dialects::builtin, pass, AbiParam, BuilderExt, Context, Ident, OpBuilder, PointerType, - Report, Signature, SourceSpan, Type, + Report, Signature, SourceSpan, SymbolTable, Type, }; use super::*; @@ -384,11 +384,17 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); let span = SourceSpan::default(); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = builtin::WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(span); + let builder = builder.create::(span); let name = Ident::new("test".into(), span); let signature = Signature::new([AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)]); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body @@ -446,10 +452,15 @@ mod tests { let context = Rc::new(Context::default()); let mut builder = OpBuilder::new(context.clone()); - let span = SourceSpan::default(); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = builtin::WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(span); + let builder = builder.create::(span); let name = Ident::new("test".into(), span); let signature = Signature::new( [ @@ -460,7 +471,7 @@ mod tests { ], [AbiParam::new(Type::U32)], ); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body @@ -571,11 +582,17 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); let span = SourceSpan::default(); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = builtin::WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(span); + let builder = builder.create::(span); let name = Ident::new("test".into(), span); let signature = Signature::new([AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)]); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body @@ -630,8 +647,14 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); let span = SourceSpan::default(); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = builtin::WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(span); + let builder = builder.create::(span); let name = Ident::new("test".into(), span); let signature = Signature::new( [ @@ -641,7 +664,7 @@ mod tests { ], [AbiParam::new(Type::U32)], ); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body for the following pseudocode: @@ -743,8 +766,14 @@ mod tests { let mut builder = OpBuilder::new(context.clone()); let span = SourceSpan::default(); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = builtin::WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(span); + let builder = builder.create::(span); let name = Ident::new("test".into(), span); let signature = Signature::new( [ @@ -754,7 +783,7 @@ mod tests { ], [AbiParam::new(Type::U32)], ); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body for the following pseudocode: diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_after.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_after.hir index aee2ec449..945ea7a66 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_after.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_after.hir @@ -1,51 +1,51 @@ public builtin.function @test(v0: u32, v1: u32, v2: u32, v3: u32) -> u32 { -^block0(v0: u32, v1: u32, v2: u32, v3: u32): +^block1(v0: u32, v1: u32, v2: u32, v3: u32): v18 = arith.constant 1 : u32; v17 = ub.poison u32 : u32; v13 = arith.constant 0 : u32; v5 = arith.constant 0 : u32; v6 = arith.neq v1, v5 : i1; v22, v23, v24 = scf.if v6 : u32, u32, u32 { - ^block2: + ^block3: v9 = arith.incr v0 : u32; scf.yield v9, v17, v13; } else { - ^block3: + ^block4: v10 = arith.neq v3, v5 : i1; v33, v34, v35 = scf.if v10 : u32, u32, u32 { - ^block4: + ^block5: v11 = arith.incr v3 : u32; scf.yield v11, v17, v13; } else { - ^block5: + ^block6: scf.yield v17, v2, v18; }; scf.yield v33, v34, v35; }; v29, v30 = scf.index_switch v24 : u32, u32 case 0 { - ^block1: + ^block2: v7 = arith.eq v22, v5 : i1; v8 = arith.neq v7, v5 : i1; v31, v32 = scf.if v8 : u32, u32 { - ^block6: + ^block7: scf.yield v17, v18; } else { - ^block7: + ^block8: scf.yield v22, v13; }; scf.yield v31, v32; } default { - ^block13: + ^block14: scf.yield v23, v13; }; cf.switch v30 { - case 0 => ^block8(v29) - default => ^block9 + case 0 => ^block9(v29) + default => ^block10 }; -^block8(v12: u32): +^block9(v12: u32): builtin.ret v12; -^block9: +^block10: ub.unreachable ; }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_before.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_before.hir index 446f88e2e..b4dbe170e 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_before.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_conditional_early_exit_before.hir @@ -1,25 +1,25 @@ public builtin.function @test(v0: u32, v1: u32, v2: u32, v3: u32) -> u32 { -^block0(v0: u32, v1: u32, v2: u32, v3: u32): +^block1(v0: u32, v1: u32, v2: u32, v3: u32): v5 = arith.constant 0 : u32; v6 = arith.neq v1, v5 : i1; - cf.cond_br v6 ^block2, ^block3; -^block1(v4: u32): + cf.cond_br v6 ^block3, ^block4; +^block2(v4: u32): v7 = arith.eq v4, v5 : i1; v8 = arith.neq v7, v5 : i1; - cf.cond_br v8 ^block6, ^block7; -^block2: - v9 = arith.incr v0 : u32; - cf.br ^block1(v9); + cf.cond_br v8 ^block7, ^block8; ^block3: - v10 = arith.neq v3, v5 : i1; - cf.cond_br v10 ^block4, ^block5; + v9 = arith.incr v0 : u32; + cf.br ^block2(v9); ^block4: - v11 = arith.incr v3 : u32; - cf.br ^block1(v11); + v10 = arith.neq v3, v5 : i1; + cf.cond_br v10 ^block5, ^block6; ^block5: - builtin.ret v2; + v11 = arith.incr v3 : u32; + cf.br ^block2(v11); ^block6: - ub.unreachable ; + builtin.ret v2; ^block7: + ub.unreachable ; +^block8: builtin.ret v4; }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_after.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_after.hir index 3ed535312..7ce0a98a4 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_after.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_after.hir @@ -1,20 +1,20 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { -^block0(v0: ptr, v1: u32, v2: u32): +^block1(v0: ptr, v1: u32, v2: u32): v28 = arith.constant 2 : u32; v27 = ub.poison u32 : u32; v26 = arith.constant 1 : u32; v21 = arith.constant 0 : u32; v39, v40, v41, v42 = scf.while v21, v21, v27, v27 : u32, u32, u32, u32 { - ^block1(v3: u32, v4: u32, v32: u32, v34: u32): + ^block2(v3: u32, v4: u32, v32: u32, v34: u32): v8 = arith.lt v3, v1 : i1; v111, v112, v113, v114 = scf.if v8 : u32, u32, u32, u32 { - ^block3: + ^block4: v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; v82, v83, v84, v85, v86, v87, v88, v89 = scf.while v21, v4, v27, v27, v27, v27, v27, v27 : u32, u32, u32, u32, u32, u32, u32, u32 { - ^block2(v5: u32, v6: u32, v63: u32, v65: u32, v67: u32, v69: u32, v71: u32, v73: u32): + ^block3(v5: u32, v6: u32, v63: u32, v65: u32, v67: u32, v69: u32, v71: u32, v73: u32): v10 = arith.lt v5, v2 : i1; v127, v128, v129, v130, v131, v132, v133, v134 = scf.if v10 : u32, u32, u32, u32, u32, u32, u32, u32 { - ^block5: + ^block6: v12 = arith.add v9, v5 : u32 #[overflow = unchecked]; v13 = builtin.unrealized_conversion_cast v0 : u32; v14 = arith.add v13, v12 : u32 #[overflow = unchecked]; @@ -23,48 +23,48 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { v17 = arith.incr v5 : u32; v18, v19 = arith.add_overflowing v6, v16 : i1, u32; v135, v136, v137, v138, v139, v140, v141, v142 = scf.if v18 : u32, u32, u32, u32, u32, u32, u32, u32 { - ^block25: + ^block26: scf.yield v27, v27, v27, v27, v26, v21, v26, v21; } else { - ^block26: + ^block27: scf.yield v17, v19, v27, v27, v27, v27, v21, v26; }; scf.yield v135, v136, v137, v138, v139, v140, v141, v142; } else { - ^block24: + ^block25: scf.yield v27, v27, v27, v27, v27, v27, v28, v21; }; v106 = arith.trunc v134 : i1; scf.condition v106, v127, v128, v6, v129, v130, v131, v132, v133; } do { - ^block19(v98: u32, v99: u32, v100: u32, v101: u32, v102: u32, v103: u32, v104: u32, v105: u32): + ^block20(v98: u32, v99: u32, v100: u32, v101: u32, v102: u32, v103: u32, v104: u32, v105: u32): scf.yield v98, v99, v100, v101, v102, v103, v104, v105; }; v115, v116, v117, v118 = scf.index_switch v89 : u32, u32, u32, u32 case 1 { - ^block22: + ^block23: scf.yield v85, v86, v87, v88; } default { - ^block6: + ^block7: v11 = arith.incr v3 : u32; scf.yield v11, v84, v21, v26; }; scf.yield v115, v116, v117, v118; } else { - ^block21: + ^block22: scf.yield v27, v27, v28, v21; }; v51 = arith.trunc v114 : i1; scf.condition v51, v111, v112, v4, v113; } do { - ^block14(v47: u32, v48: u32, v49: u32, v50: u32): + ^block15(v47: u32, v48: u32, v49: u32, v50: u32): scf.yield v47, v48, v49, v50; }; v144 = arith.eq v42, v26 : i1; - cf.cond_br v144 ^block7, ^block4; -^block4: + cf.cond_br v144 ^block8, ^block5; +^block5: builtin.ret v41; -^block7: +^block8: builtin.ret_imm 4294967295; }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_before.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_before.hir index 7e4ed12b2..8b7445f3d 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_before.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_multiple_exit_nested_while_loop_before.hir @@ -1,19 +1,19 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { -^block0(v0: ptr, v1: u32, v2: u32): +^block1(v0: ptr, v1: u32, v2: u32): v7 = arith.constant 0 : u32; - cf.br ^block1(v7, v7); -^block1(v3: u32, v4: u32): + cf.br ^block2(v7, v7); +^block2(v3: u32, v4: u32): v8 = arith.lt v3, v1 : i1; - cf.cond_br v8 ^block3(v4), ^block4; -^block2(v5: u32, v6: u32): + cf.cond_br v8 ^block4(v4), ^block5; +^block3(v5: u32, v6: u32): v10 = arith.lt v5, v2 : i1; - cf.cond_br v10 ^block5(v6), ^block6; -^block3: - v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; - cf.br ^block2(v7, v4); + cf.cond_br v10 ^block6(v6), ^block7; ^block4: - builtin.ret v4; + v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; + cf.br ^block3(v7, v4); ^block5: + builtin.ret v4; +^block6: v12 = arith.add v9, v5 : u32 #[overflow = unchecked]; v13 = builtin.unrealized_conversion_cast v0 : u32; v14 = arith.add v13, v12 : u32 #[overflow = unchecked]; @@ -21,10 +21,10 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { v16 = builtin.unrealized_conversion_cast v15 : u32; v17 = arith.incr v5 : u32; v18, v19 = arith.add_overflowing v6, v16 : i1, u32; - cf.cond_br v18 ^block7, ^block2(v17, v19); -^block6: - v11 = arith.incr v3 : u32; - cf.br ^block1(v11, v6); + cf.cond_br v18 ^block8, ^block3(v17, v19); ^block7: + v11 = arith.incr v3 : u32; + cf.br ^block2(v11, v6); +^block8: builtin.ret_imm 4294967295; }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_after.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_after.hir index cfce15343..b69cf3656 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_after.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_after.hir @@ -1,26 +1,26 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { -^block0(v0: ptr, v1: u32, v2: u32): +^block1(v0: ptr, v1: u32, v2: u32): v26 = ub.poison u32 : u32; v25 = arith.constant 1 : u32; v20 = arith.constant 0 : u32; v7 = arith.constant 0 : u32; v34, v35, v36 = scf.while v7, v7, v26 : u32, u32, u32 { - ^block1(v3: u32, v4: u32, v30: u32): + ^block2(v3: u32, v4: u32, v30: u32): v8 = arith.lt v3, v1 : i1; v65, v66, v67, v68 = scf.if v8 : u32, u32, u32, u32 { - ^block18: + ^block19: scf.yield v26, v26, v25, v20; } else { - ^block3: + ^block4: v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; v55, v56, v57 = scf.while v7, v4, v26 : u32, u32, u32 { - ^block2(v5: u32, v6: u32, v51: u32): + ^block3(v5: u32, v6: u32, v51: u32): v10 = arith.lt v5, v2 : i1; v69, v70, v71, v72 = scf.if v10 : u32, u32, u32, u32 { - ^block19: + ^block20: scf.yield v26, v26, v25, v20; } else { - ^block5: + ^block6: v12 = arith.add v9, v5 : u32 #[overflow = unchecked]; v13 = builtin.unrealized_conversion_cast v0 : u32; v14 = arith.add v13, v12 : u32 #[overflow = unchecked]; @@ -33,7 +33,7 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { v64 = arith.trunc v72 : i1; scf.condition v64, v69, v70, v6; } do { - ^block17(v61: u32, v62: u32, v63: u32): + ^block18(v61: u32, v62: u32, v63: u32): scf.yield v61, v62, v63; }; v11 = arith.incr v3 : u32; @@ -42,7 +42,7 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { v43 = arith.trunc v68 : i1; scf.condition v43, v65, v66, v4; } do { - ^block12(v40: u32, v41: u32, v42: u32): + ^block13(v40: u32, v41: u32, v42: u32): scf.yield v40, v41, v42; }; builtin.ret v36; diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_before.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_before.hir index 5f5e41efa..fa746727f 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_before.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_nested_while_loop_before.hir @@ -1,19 +1,19 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { -^block0(v0: ptr, v1: u32, v2: u32): +^block1(v0: ptr, v1: u32, v2: u32): v7 = arith.constant 0 : u32; - cf.br ^block1(v7, v7); -^block1(v3: u32, v4: u32): + cf.br ^block2(v7, v7); +^block2(v3: u32, v4: u32): v8 = arith.lt v3, v1 : i1; - cf.cond_br v8 ^block4, ^block3(v4); -^block2(v5: u32, v6: u32): + cf.cond_br v8 ^block5, ^block4(v4); +^block3(v5: u32, v6: u32): v10 = arith.lt v5, v2 : i1; - cf.cond_br v10 ^block6, ^block5(v6); -^block3: - v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; - cf.br ^block2(v7, v4); + cf.cond_br v10 ^block7, ^block6(v6); ^block4: - builtin.ret v4; + v9 = arith.mul v3, v2 : u32 #[overflow = unchecked]; + cf.br ^block3(v7, v4); ^block5: + builtin.ret v4; +^block6: v12 = arith.add v9, v5 : u32 #[overflow = unchecked]; v13 = builtin.unrealized_conversion_cast v0 : u32; v14 = arith.add v13, v12 : u32 #[overflow = unchecked]; @@ -21,8 +21,8 @@ public builtin.function @test(v0: ptr, v1: u32, v2: u32) -> u32 { v16 = builtin.unrealized_conversion_cast v15 : u32; v17 = arith.incr v5 : u32; v18 = arith.add v6, v16 : u32 #[overflow = unchecked]; - cf.br ^block2(v17, v18); -^block6: + cf.br ^block3(v17, v18); +^block7: v11 = arith.incr v3 : u32; - cf.br ^block1(v11, v6); + cf.br ^block2(v11, v6); }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_after.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_after.hir index 6ee59e782..f5aec2ce4 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_after.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_after.hir @@ -1,13 +1,13 @@ public builtin.function @test(v0: u32) -> u32 { -^block0(v0: u32): +^block1(v0: u32): v2 = arith.constant 0 : u32; v3 = arith.eq v0, v2 : i1; v8 = scf.if v3 : u32 { - ^block1: + ^block2: v4 = arith.incr v0 : u32; scf.yield v4; } else { - ^block2: + ^block3: v5 = arith.mul v0, v0 : u32 #[overflow = checked]; scf.yield v5; }; diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_before.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_before.hir index 2ad7c035d..7c1114f89 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_before.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_conditional_before.hir @@ -1,14 +1,14 @@ public builtin.function @test(v0: u32) -> u32 { -^block0(v0: u32): +^block1(v0: u32): v2 = arith.constant 0 : u32; v3 = arith.eq v0, v2 : i1; - cf.cond_br v3 ^block1, ^block2; -^block1: - v4 = arith.incr v0 : u32; - cf.br ^block3(v4); + cf.cond_br v3 ^block2, ^block3; ^block2: + v4 = arith.incr v0 : u32; + cf.br ^block4(v4); +^block3: v5 = arith.mul v0, v0 : u32 #[overflow = checked]; - cf.br ^block3(v5); -^block3(v1: u32): + cf.br ^block4(v5); +^block4(v1: u32): builtin.ret v1; }; \ No newline at end of file diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_after.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_after.hir index ce156c761..799767b8a 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_after.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_after.hir @@ -1,18 +1,18 @@ public builtin.function @test(v0: u32) -> u32 { -^block0(v0: u32): +^block1(v0: u32): v15 = ub.poison u32 : u32; v14 = arith.constant 1 : u32; v9 = arith.constant 0 : u32; v3 = arith.constant 0 : u32; v4 = arith.constant 1 : u32; v23, v24, v25 = scf.while v0, v3, v15 : u32, u32, u32 { - ^block1(v1: u32, v2: u32, v19: u32): + ^block2(v1: u32, v2: u32, v19: u32): v5 = arith.eq v1, v3 : i1; v33, v34, v35, v36 = scf.if v5 : u32, u32, u32, u32 { - ^block10: + ^block11: scf.yield v15, v15, v14, v9; } else { - ^block3: + ^block4: v6 = arith.sub v1, v4 : u32 #[overflow = unchecked]; v7 = arith.incr v2 : u32; scf.yield v6, v7, v9, v14; @@ -20,7 +20,7 @@ public builtin.function @test(v0: u32) -> u32 { v32 = arith.trunc v36 : i1; scf.condition v32, v33, v34, v2; } do { - ^block9(v29: u32, v30: u32, v31: u32): + ^block10(v29: u32, v30: u32, v31: u32): scf.yield v29, v30, v31; }; builtin.ret v25; diff --git a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_before.hir b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_before.hir index c744417e2..031c7cb9f 100644 --- a/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_before.hir +++ b/dialects/scf/src/transforms/expected/cfg_to_scf_lift_simple_while_loop_before.hir @@ -1,15 +1,15 @@ public builtin.function @test(v0: u32) -> u32 { -^block0(v0: u32): +^block1(v0: u32): v3 = arith.constant 0 : u32; v4 = arith.constant 1 : u32; - cf.br ^block1(v0, v3); -^block1(v1: u32, v2: u32): + cf.br ^block2(v0, v3); +^block2(v1: u32, v2: u32): v5 = arith.eq v1, v3 : i1; - cf.cond_br v5 ^block2, ^block3; -^block2: - builtin.ret v2; + cf.cond_br v5 ^block3, ^block4; ^block3: + builtin.ret v2; +^block4: v6 = arith.sub v1, v4 : u32 #[overflow = unchecked]; v7 = arith.incr v2 : u32; - cf.br ^block1(v6, v7); + cf.br ^block2(v6, v7); }; \ No newline at end of file diff --git a/eval/src/tests.rs b/eval/src/tests.rs index 845e380fd..640505997 100644 --- a/eval/src/tests.rs +++ b/eval/src/tests.rs @@ -5,8 +5,8 @@ use midenc_dialect_cf::ControlFlowOpBuilder; use midenc_dialect_hir::HirOpBuilder; use midenc_dialect_scf::StructuredControlFlowOpBuilder; use midenc_hir::{ - dialects::builtin::{BuiltinOpBuilder, FunctionBuilder}, - AbiParam, Builder, Context, Ident, Op, OpBuilder, ProgramPoint, Report, Signature, SourceSpan, + dialects::builtin::{BuiltinOpBuilder, FunctionBuilder, World, WorldBuilder}, + AbiParam, Builder, BuilderExt, Context, Ident, Op, OpBuilder, Report, Signature, SourceSpan, SymbolTable, Type, ValueRef, }; @@ -72,9 +72,15 @@ fn eval_callable_test() -> Result<(), Report> { let mut builder = OpBuilder::new(test_context.context.clone()); + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = builder.create_function( Ident::with_empty_span("test".into()), Signature::new([AbiParam::new(Type::I1)], [AbiParam::new(Type::U32)]), + world, )?; { @@ -119,29 +125,32 @@ fn call_handling_test() -> Result<(), Report> { let mut builder = OpBuilder::new(test_context.context.clone()); - let mut module = builder.create_module(Ident::with_empty_span("test".into()))?; + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + + let mut module = builder.create_module(Ident::with_empty_span("test".into()), world)?; let module_body = module.borrow().body().as_region_ref(); builder.create_block(module_body, None, &[]); + let module_ref = &mut module.borrow_mut().as_symbol_table_ref(); + // Define entry let entry = builder.create_function( Ident::with_empty_span("entrypoint".into()), Signature::new([AbiParam::new(Type::I1)], [AbiParam::new(Type::U32)]), + module_ref, )?; - module - .borrow_mut() - .symbol_manager_mut() - .insert_new(entry, ProgramPoint::Invalid); // Define callee let callee_signature = Signature::new([AbiParam::new(Type::I1)], [AbiParam::new(Type::I1)]); - let callee = builder - .create_function(Ident::with_empty_span("callee".into()), callee_signature.clone())?; - module - .borrow_mut() - .symbol_manager_mut() - .insert_new(callee, ProgramPoint::Invalid); + let callee = builder.create_function( + Ident::with_empty_span("callee".into()), + callee_signature.clone(), + module_ref, + )?; { let mut builder = FunctionBuilder::new(entry, &mut builder); diff --git a/hir-macros/src/operation.rs b/hir-macros/src/operation.rs index 3f7928a1d..448d1b039 100644 --- a/hir-macros/src/operation.rs +++ b/hir-macros/src/operation.rs @@ -11,6 +11,8 @@ use syn::{parse_quote, spanned::Spanned, Ident, Token}; pub fn derive_operation(input: syn::DeriveInput) -> darling::Result { let op = OpDefinition::from_derive_input(&input)?; + // This method is implicitly implemented using `to_tokens`, and acts as a + // convenience method for consumers of the `ToTokens` trait. Ok(op.into_token_stream()) } @@ -51,6 +53,11 @@ pub struct OpDefinition { /// Keyed successor groups are handled a bit differently than "normal" successor groups in terms /// of the types expected by the op builder for this type. successors: Vec, + /// Indicates whether the current operation could belong to a [`SymbolTable`]. + /// + /// If true, this operation's builder will have an additional parameter of type + ///`parent_symbol_table: &mut SymbolTableRef`. + belongs_in_symbol_table: bool, /// The symbolic references held by this op symbols: Vec, /// The struct definition @@ -123,6 +130,7 @@ impl OpDefinition { operands: vec![], results: None, successors: vec![], + belongs_in_symbol_table: false, symbols: vec![], op, op_builder_impl, @@ -345,6 +353,35 @@ impl OpDefinition { } } + // If the operations has the "BelongsInSymbolTable" trait, then an additional parameter is + // added to the Operation::create and OpBuilder function of type: + // parent_symbol_table: &mut SymbolTableRef, + // This is a reference to the symbol table of the parent where this operation will be added. + if self + .traits + .iter() + .any(|tr| tr.get_ident().unwrap() == stringify!(BelongsInSymbolTable)) + { + let parent_symbol_table = + Ident::new("parent_symbol_table", proc_macro2::Span::call_site()); + + let parent_symbol_type = syn::Type::Reference(syn::TypeReference { + and_token: syn::token::And(proc_macro2::Span::call_site()), + lifetime: None, + mutability: Some(syn::token::Mut(proc_macro2::Span::call_site())), + elem: Box::new(make_type(stringify!(SymbolTableRef))), + }); + + create_params.push(OpCreateParam { + param_ty: OpCreateParamType::BuildOnlyParameter( + parent_symbol_table.clone(), + parent_symbol_type, + ), + r#default: false, + }); + self.belongs_in_symbol_table = true; + } + self.op_builder_impl.set_create_params(&self.op.generics, create_params); Ok(()) @@ -566,7 +603,7 @@ impl quote::ToTokens for BuildOp<'_> { match self.0.results.as_ref() { None => { tokens.extend(quote! { - op_builder.build() + let op = op_builder.build(); }); } Some(group) => { @@ -639,13 +676,43 @@ impl quote::ToTokens for BuildOp<'_> { #verify_result_constraints } - Ok(op) + // We save the operation in a variable in case it needs to be modified later on + let op = Ok(op); }) } } } } +struct ModifyOp<'a>(&'a OpDefinition); +impl quote::ToTokens for ModifyOp<'_> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + if self.0.belongs_in_symbol_table { + tokens.extend(quote! { + op.as_ref().map(|op| { + let is_new = parent_symbol_table.borrow_mut().symbol_manager_mut().insert_new(*op, crate::ProgramPoint::Invalid); + assert!( + is_new, + "{} already exists in {}", + op.borrow().name(), + parent_symbol_table.borrow().as_symbol_table_operation().name() + ); + }); + }); + }; + } +} + +#[allow(dead_code)] +struct ReturnOp<'a>(&'a OpDefinition); +impl quote::ToTokens for ReturnOp<'_> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.extend(quote! { + op + }); + } +} + impl quote::ToTokens for OpCreateFn<'_> { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { let dialect = &self.op.dialect; @@ -670,6 +737,8 @@ impl quote::ToTokens for OpCreateFn<'_> { }); let with_successors = WithSuccessors(self.op); let build_op = BuildOp(self.op); + let modify_op = ModifyOp(self.op); + let return_op = ReturnOp(self.op); tokens.extend(quote! { /// Manually construct a new [#op_ident] @@ -719,8 +788,14 @@ impl quote::ToTokens for OpCreateFn<'_> { #with_successors #with_results - // Finalize construction of this op, verifying it + /// Construct the op, verifying it #build_op + + /// Apply modifications to the op + #modify_op + + /// Return the op + #return_op } }); } @@ -2362,6 +2437,8 @@ pub enum OpCreateParamType { #[allow(dead_code)] OperandGroup(Ident, syn::Type), CustomField(Ident, syn::Type), + /// Parameters that are only used in the Operation::create and are not stored in the resulting Operation + BuildOnlyParameter(Ident, syn::Type), Successor(Ident), SuccessorGroupNamed(Ident), SuccessorGroupKeyed(Ident, syn::Type), @@ -2375,6 +2452,7 @@ impl OpCreateParam { | OpCreateParamType::CustomField(name, _) | OpCreateParamType::Operand(Operand { name, .. }) | OpCreateParamType::OperandGroup(name, _) + | OpCreateParamType::BuildOnlyParameter(name, _) | OpCreateParamType::SuccessorGroupNamed(name) | OpCreateParamType::SuccessorGroupKeyed(name, _) | OpCreateParamType::Symbol(Symbol { name, .. }) => vec![name.clone()], @@ -2400,6 +2478,7 @@ impl OpCreateParam { vec![ty.clone()] } OpCreateParamType::Operand(_) => vec![make_type("::midenc_hir::ValueRef")], + OpCreateParamType::BuildOnlyParameter(_, ty) => vec![ty.clone()], OpCreateParamType::OperandGroup(group_name, _) | OpCreateParamType::SuccessorGroupNamed(group_name) | OpCreateParamType::SuccessorGroupKeyed(group_name, _) => { diff --git a/hir/src/dialects/builtin/builders.rs b/hir/src/dialects/builtin/builders.rs index 5e0bbff28..2361ef00a 100644 --- a/hir/src/dialects/builtin/builders.rs +++ b/hir/src/dialects/builtin/builders.rs @@ -7,7 +7,7 @@ pub use self::{component::*, function::*, module::*, world::*}; use super::ops::*; use crate::{ constants::ConstantData, Builder, BuilderExt, Ident, Immediate, OpBuilder, Report, Signature, - SourceSpan, Spanned, Type, UnsafeIntrusiveEntityRef, ValueRef, Visibility, + SourceSpan, Spanned, SymbolTableRef, Type, UnsafeIntrusiveEntityRef, ValueRef, Visibility, }; pub trait BuiltinOpBuilder<'f, B: ?Sized + Builder> { @@ -16,18 +16,23 @@ pub trait BuiltinOpBuilder<'f, B: ?Sized + Builder> { op_builder(name) } - fn create_module(&mut self, name: Ident) -> Result { - let op_builder = self.builder_mut().create::(name.span()); - op_builder(name) + fn create_module( + &mut self, + name: Ident, + parent_symbol_table: &mut SymbolTableRef, + ) -> Result { + let op_builder = self.builder_mut().create::(name.span()); + op_builder(name, parent_symbol_table) } fn create_function( &mut self, name: Ident, signature: Signature, + parent_symbol_table: &mut SymbolTableRef, ) -> Result { - let op_builder = self.builder_mut().create::(name.span()); - op_builder(name, signature) + let op_builder = self.builder_mut().create::(name.span()); + op_builder(name, signature, parent_symbol_table) } fn create_global_variable( @@ -35,9 +40,10 @@ pub trait BuiltinOpBuilder<'f, B: ?Sized + Builder> { name: Ident, visibility: Visibility, ty: Type, + parent_symbol_table: &mut SymbolTableRef, ) -> Result { - let op_builder = self.builder_mut().create::(name.span()); - op_builder(name, visibility, ty) + let op_builder = self.builder_mut().create::(name.span()); + op_builder(name, visibility, ty, parent_symbol_table) } fn create_data_segment( diff --git a/hir/src/dialects/builtin/builders/component.rs b/hir/src/dialects/builtin/builders/component.rs index f6273a0d0..5ed154fca 100644 --- a/hir/src/dialects/builtin/builders/component.rs +++ b/hir/src/dialects/builtin/builders/component.rs @@ -31,17 +31,9 @@ impl ComponentBuilder { } pub fn define_module(&mut self, name: Ident) -> Result { - let module_ref = self.builder.create_module(name)?; - let is_new = self - .component - .borrow_mut() - .symbol_manager_mut() - .insert_new(module_ref, crate::ProgramPoint::Invalid); - assert!( - is_new, - "module with the name {name} already exists in component {}", - self.component.borrow().name() - ); + let symbol_table = &mut self.component.borrow_mut().as_symbol_table_ref(); + let module_ref = self.builder.create_module(name, symbol_table)?; + Ok(module_ref) } @@ -66,13 +58,9 @@ impl ComponentBuilder { name: Ident, signature: Signature, ) -> Result { - let function_ref = self.builder.create_function(name, signature)?; - let is_new = self - .component - .borrow_mut() - .symbol_manager_mut() - .insert_new(function_ref, crate::ProgramPoint::Invalid); - assert!(is_new, "function with the name {name} already exists"); + let symbol_table = &mut self.component.borrow_mut().as_symbol_table_ref(); + let function_ref = self.builder.create_function(name, signature, symbol_table)?; + Ok(function_ref) } } diff --git a/hir/src/dialects/builtin/builders/module.rs b/hir/src/dialects/builtin/builders/module.rs index f61fca08e..2ed37d2b0 100644 --- a/hir/src/dialects/builtin/builders/module.rs +++ b/hir/src/dialects/builtin/builders/module.rs @@ -51,13 +51,9 @@ impl ModuleBuilder { name: Ident, signature: Signature, ) -> Result { - let function_ref = self.builder.create_function(name, signature)?; - let is_new = self - .module - .borrow_mut() - .symbol_manager_mut() - .insert_new(function_ref, crate::ProgramPoint::Invalid); - assert!(is_new, "function with the name {name} already exists"); + let symbol_table = &mut self.module.borrow_mut().as_symbol_table_ref(); + let function_ref = self.builder.create_function(name, signature, symbol_table)?; + Ok(function_ref) } @@ -71,13 +67,10 @@ impl ModuleBuilder { visibility: Visibility, ty: Type, ) -> Result, Report> { - let global_var_ref = self.builder.create_global_variable(name, visibility, ty)?; - let is_new = self - .module - .borrow_mut() - .symbol_manager_mut() - .insert_new(global_var_ref, crate::ProgramPoint::Invalid); - assert!(is_new, "global variable with the name {name} already exists"); + let symbol_table = &mut self.module.borrow_mut().as_symbol_table_ref(); + let global_var_ref = + self.builder.create_global_variable(name, visibility, ty, symbol_table)?; + Ok(global_var_ref) } @@ -118,13 +111,9 @@ impl ModuleBuilder { /// Declare a new nested module `name` pub fn declare_module(&mut self, name: Ident) -> Result { let builder = PrimModuleBuilder::new(&mut self.builder, name.span()); - let module_ref = builder(name)?; - let is_new = self - .module - .borrow_mut() - .symbol_manager_mut() - .insert_new(module_ref, crate::ProgramPoint::Invalid); - assert!(is_new, "module with the name {name} already exists in world",); + let symbol_table = &mut self.module.borrow_mut().as_symbol_table_ref(); + let module_ref = builder(name, symbol_table)?; + Ok(module_ref) } diff --git a/hir/src/dialects/builtin/builders/world.rs b/hir/src/dialects/builtin/builders/world.rs index 38408b6b7..3f29632ed 100644 --- a/hir/src/dialects/builtin/builders/world.rs +++ b/hir/src/dialects/builtin/builders/world.rs @@ -42,21 +42,10 @@ impl WorldBuilder { ver: Version, ) -> Result { let builder = PrimComponentBuilder::new(&mut self.builder, name.span()); - let component_ref = builder(ns, name, ver.clone())?; - let is_new = self - .world - .borrow_mut() - .symbol_manager_mut() - .insert_new(component_ref, crate::ProgramPoint::Invalid); - assert!( - is_new, - "component {} already exists in world", - ComponentId { - namespace: ns.name, - name: name.name, - version: ver - } - ); + let symbol_table = &mut self.world.borrow_mut().as_symbol_table_ref(); + + let component_ref = builder(ns, name, ver.clone(), symbol_table)?; + Ok(component_ref) } @@ -72,13 +61,9 @@ impl WorldBuilder { /// Declare a new world-level module `name` pub fn declare_module(&mut self, name: Ident) -> Result { let builder = PrimModuleBuilder::new(&mut self.builder, name.span()); - let module_ref = builder(name)?; - let is_new = self - .world - .borrow_mut() - .symbol_manager_mut() - .insert_new(module_ref, crate::ProgramPoint::Invalid); - assert!(is_new, "module with the name {name} already exists in world",); + let symbol_table = &mut self.world.borrow_mut().as_symbol_table_ref(); + let module_ref = builder(name, symbol_table)?; + Ok(module_ref) } diff --git a/hir/src/dialects/builtin/ops/component.rs b/hir/src/dialects/builtin/ops/component.rs index 2f7d275d5..6ea6863e0 100644 --- a/hir/src/dialects/builtin/ops/component.rs +++ b/hir/src/dialects/builtin/ops/component.rs @@ -7,12 +7,12 @@ use crate::{ derive::operation, dialects::builtin::BuiltinDialect, traits::{ - GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, NoRegionArguments, - NoTerminator, SingleBlock, SingleRegion, + BelongsInSymbolTable, GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, + NoRegionArguments, NoTerminator, SingleBlock, SingleRegion, }, version::Version, Ident, OpPrinter, Operation, RegionKind, RegionKindInterface, Symbol, SymbolManager, - SymbolManagerMut, SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolUseList, + SymbolManagerMut, SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolTableRef, SymbolUseList, UnsafeIntrusiveEntityRef, Usable, Visibility, }; @@ -69,6 +69,7 @@ pub type ComponentRef = UnsafeIntrusiveEntityRef; HasOnlyGraphRegion, GraphRegionNoTerminator, IsolatedFromAbove, + BelongsInSymbolTable, ), implements(RegionKindInterface, SymbolTable, Symbol, OpPrinter) )] @@ -192,6 +193,11 @@ impl SymbolTable for Component { &self.op } + #[inline(always)] + fn as_symbol_table_ref(&self) -> SymbolTableRef { + unsafe { SymbolTableRef::from_raw(self) } + } + #[inline(always)] fn as_symbol_table_operation_mut(&mut self) -> &mut Operation { &mut self.op diff --git a/hir/src/dialects/builtin/ops/function.rs b/hir/src/dialects/builtin/ops/function.rs index 95004f693..24c890fc2 100644 --- a/hir/src/dialects/builtin/ops/function.rs +++ b/hir/src/dialects/builtin/ops/function.rs @@ -6,11 +6,13 @@ use crate::{ define_attr_type, derive::operation, dialects::builtin::BuiltinDialect, - traits::{AnyType, IsolatedFromAbove, ReturnLike, SingleRegion, Terminator}, + traits::{ + AnyType, BelongsInSymbolTable, IsolatedFromAbove, ReturnLike, SingleRegion, Terminator, + }, AttrPrinter, BlockRef, CallableOpInterface, Context, Ident, Immediate, Op, OpPrinter, OpPrintingFlags, Operation, RegionKind, RegionKindInterface, RegionRef, Signature, Symbol, - SymbolName, SymbolUse, SymbolUseList, Type, UnsafeIntrusiveEntityRef, Usable, ValueRef, - Visibility, + SymbolName, SymbolTableRef, SymbolUse, SymbolUseList, Type, UnsafeIntrusiveEntityRef, Usable, + ValueRef, Visibility, }; trait UsableSymbol = Usable; @@ -75,13 +77,13 @@ impl AttrPrinter for LocalVariable { #[operation( dialect = BuiltinDialect, - traits(SingleRegion, IsolatedFromAbove), + traits(SingleRegion, IsolatedFromAbove, BelongsInSymbolTable), implements( UsableSymbol, Symbol, CallableOpInterface, RegionKindInterface, - OpPrinter + OpPrinter, ) )] pub struct Function { diff --git a/hir/src/dialects/builtin/ops/global_variable.rs b/hir/src/dialects/builtin/ops/global_variable.rs index c46c0cf10..f53e7c71a 100644 --- a/hir/src/dialects/builtin/ops/global_variable.rs +++ b/hir/src/dialects/builtin/ops/global_variable.rs @@ -8,12 +8,12 @@ use crate::{ MemoryEffect, MemoryEffectOpInterface, Pure, }, traits::{ - InferTypeOpInterface, IsolatedFromAbove, NoRegionArguments, PointerOf, SingleBlock, - SingleRegion, UInt8, + BelongsInSymbolTable, InferTypeOpInterface, IsolatedFromAbove, NoRegionArguments, + PointerOf, SingleBlock, SingleRegion, UInt8, }, AsSymbolRef, Context, Ident, Op, OpPrinter, Operation, PointerType, Report, Spanned, Symbol, - SymbolName, SymbolRef, SymbolUseList, Type, UnsafeIntrusiveEntityRef, Usable, Value, - Visibility, + SymbolName, SymbolRef, SymbolTableRef, SymbolUseList, Type, UnsafeIntrusiveEntityRef, Usable, + Value, Visibility, }; pub type GlobalVariableRef = UnsafeIntrusiveEntityRef; @@ -34,6 +34,7 @@ pub type GlobalVariableRef = UnsafeIntrusiveEntityRef; SingleBlock, NoRegionArguments, IsolatedFromAbove, + BelongsInSymbolTable, ), implements(Symbol, OpPrinter) )] diff --git a/hir/src/dialects/builtin/ops/interface.rs b/hir/src/dialects/builtin/ops/interface.rs index 856b18a99..14a486f5b 100644 --- a/hir/src/dialects/builtin/ops/interface.rs +++ b/hir/src/dialects/builtin/ops/interface.rs @@ -8,8 +8,8 @@ use crate::{ NoTerminator, SingleBlock, SingleRegion, }, Ident, Op, Operation, RegionKind, RegionKindInterface, Symbol, SymbolManager, SymbolManagerMut, - SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolUseList, UnsafeIntrusiveEntityRef, Usable, - Visibility, + SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolTableRef, SymbolUseList, + UnsafeIntrusiveEntityRef, Usable, Visibility, }; pub type InterfaceRef = UnsafeIntrusiveEntityRef; @@ -119,6 +119,11 @@ impl SymbolTable for Interface { &self.op } + #[inline(always)] + fn as_symbol_table_ref(&self) -> SymbolTableRef { + unsafe { SymbolTableRef::from_raw(self) } + } + #[inline(always)] fn as_symbol_table_operation_mut(&mut self) -> &mut Operation { &mut self.op diff --git a/hir/src/dialects/builtin/ops/module.rs b/hir/src/dialects/builtin/ops/module.rs index 5fb6100fc..3867d54c9 100644 --- a/hir/src/dialects/builtin/ops/module.rs +++ b/hir/src/dialects/builtin/ops/module.rs @@ -2,11 +2,11 @@ use crate::{ derive::operation, dialects::builtin::BuiltinDialect, traits::{ - GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, NoRegionArguments, - NoTerminator, SingleBlock, SingleRegion, + BelongsInSymbolTable, GraphRegionNoTerminator, HasOnlyGraphRegion, IsolatedFromAbove, + NoRegionArguments, NoTerminator, SingleBlock, SingleRegion, }, Ident, OpPrinter, Operation, RegionKind, RegionKindInterface, Symbol, SymbolManager, - SymbolManagerMut, SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolUseList, + SymbolManagerMut, SymbolMap, SymbolName, SymbolRef, SymbolTable, SymbolTableRef, SymbolUseList, UnsafeIntrusiveEntityRef, Usable, Visibility, }; @@ -57,6 +57,7 @@ pub type ModuleRef = UnsafeIntrusiveEntityRef; HasOnlyGraphRegion, GraphRegionNoTerminator, IsolatedFromAbove, + BelongsInSymbolTable, ), implements(RegionKindInterface, SymbolTable, Symbol, OpPrinter) )] @@ -176,6 +177,11 @@ impl SymbolTable for Module { &self.op } + #[inline(always)] + fn as_symbol_table_ref(&self) -> SymbolTableRef { + unsafe { SymbolTableRef::from_raw(self) } + } + #[inline(always)] fn as_symbol_table_operation_mut(&mut self) -> &mut Operation { &mut self.op diff --git a/hir/src/dialects/builtin/ops/world.rs b/hir/src/dialects/builtin/ops/world.rs index 9a922b632..4dc93cf9e 100644 --- a/hir/src/dialects/builtin/ops/world.rs +++ b/hir/src/dialects/builtin/ops/world.rs @@ -6,7 +6,8 @@ use crate::{ NoTerminator, SingleBlock, SingleRegion, }, Operation, RegionKind, RegionKindInterface, SymbolManager, SymbolManagerMut, SymbolMap, - SymbolName, SymbolRef, SymbolTable, SymbolUseList, UnsafeIntrusiveEntityRef, Usable, + SymbolName, SymbolRef, SymbolTable, SymbolTableRef, SymbolUseList, UnsafeIntrusiveEntityRef, + Usable, }; pub type WorldRef = UnsafeIntrusiveEntityRef; @@ -68,6 +69,11 @@ impl SymbolTable for World { &self.op } + #[inline(always)] + fn as_symbol_table_ref(&self) -> SymbolTableRef { + unsafe { SymbolTableRef::from_raw(self) } + } + #[inline(always)] fn as_symbol_table_operation_mut(&mut self) -> &mut Operation { &mut self.op diff --git a/hir/src/ir/symbols/table.rs b/hir/src/ir/symbols/table.rs index 53caba022..ea4017c14 100644 --- a/hir/src/ir/symbols/table.rs +++ b/hir/src/ir/symbols/table.rs @@ -23,6 +23,9 @@ pub trait SymbolTable { /// Get a reference to the underlying [Operation] fn as_symbol_table_operation(&self) -> &Operation; + /// Get a reference to the underlying [Operation] as a SymbolTable + fn as_symbol_table_ref(&self) -> SymbolTableRef; + /// Get a mutable reference to the underlying [Operation] fn as_symbol_table_operation_mut(&mut self) -> &mut Operation; diff --git a/hir/src/ir/traits.rs b/hir/src/ir/traits.rs index d82c6603c..b315d0b85 100644 --- a/hir/src/ir/traits.rs +++ b/hir/src/ir/traits.rs @@ -40,6 +40,9 @@ pub trait Involution {} /// Marker trait for ops which are not permitted to access values defined above them pub trait IsolatedFromAbove {} +/// Marker trait for ops whose parent op needs to add them to their own symbol list. +pub trait BelongsInSymbolTable {} + /// Marker trait for ops which have only regions of [`RegionKind::Graph`] pub trait HasOnlyGraphRegion {} diff --git a/hir/src/matchers/matcher.rs b/hir/src/matchers/matcher.rs index ba04d4d9d..8491f1881 100644 --- a/hir/src/matchers/matcher.rs +++ b/hir/src/matchers/matcher.rs @@ -752,11 +752,16 @@ mod tests { fn setup(context: Rc) -> (ValueRef, ValueRef, ValueRef) { let mut builder = OpBuilder::new(Rc::clone(&context)); + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(SourceSpan::default()); + let builder = builder.create::(SourceSpan::default()); let name = Ident::new("test".into(), SourceSpan::default()); let signature = Signature::new([AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)]); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body diff --git a/hir/src/patterns/pattern.rs b/hir/src/patterns/pattern.rs index 277a93ae4..5c4b10cc9 100644 --- a/hir/src/patterns/pattern.rs +++ b/hir/src/patterns/pattern.rs @@ -327,11 +327,17 @@ mod tests { let pattern = ConvertShiftLeftBy1ToMultiply::new(Rc::clone(&context)); let mut builder = OpBuilder::new(Rc::clone(&context)); + + let world_ref = builder.create::(Default::default())() + .expect("Error unrelated to test: Failed to build world."); + let mut world_builder = WorldBuilder::new(world_ref); + let world = &mut world_builder.world.borrow_mut().as_symbol_table_ref(); + let function = { - let builder = builder.create::(SourceSpan::default()); + let builder = builder.create::(SourceSpan::default()); let name = Ident::new("test".into(), SourceSpan::default()); let signature = Signature::new([AbiParam::new(Type::U32)], [AbiParam::new(Type::U32)]); - builder(name, signature).unwrap() + builder(name, signature, world).unwrap() }; // Define function body @@ -363,7 +369,7 @@ mod tests { let output = func.as_operation().to_string(); let expected = "\ public builtin.function @test(v0: u32) -> u32 { -^block0(v0: u32): +^block1(v0: u32): v3 = test.constant 2 : u32; v4 = test.mul v0, v3 : u32 #[overflow = wrapping]; builtin.ret v4; diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index 332c4a177..3a7da5321 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -1,7 +1,7 @@ //! Compilation and semantic tests for the whole compiler pipeline #![feature(iter_array_chunks)] #![feature(debug_closure_helpers)] -//#![deny(warnings)] +#![deny(warnings)] #![deny(missing_docs)] mod cargo_proj;