From 8e4e55e5246492e7add98ccf24f2f483163cdbf2 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Mon, 20 Mar 2023 12:32:38 +0100 Subject: [PATCH 1/3] Support aggregate expressions --- .../src/build/custom/parse/instruction.rs | 25 +++++++ .../aggregate_exprs.adt.built.after.mir | 16 +++++ .../aggregate_exprs.array.built.after.mir | 15 ++++ .../building/custom/aggregate_exprs.rs | 71 +++++++++++++++++++ .../aggregate_exprs.tuple.built.after.mir | 10 +++ 5 files changed, 137 insertions(+) create mode 100644 tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir create mode 100644 tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir create mode 100644 tests/mir-opt/building/custom/aggregate_exprs.rs create mode 100644 tests/mir-opt/building/custom/aggregate_exprs.tuple.built.after.mir diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 5e77f2dc1268d..e60e1a4c81507 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -166,6 +166,31 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { let cast_kind = mir_cast_kind(source_ty, expr.ty); Ok(Rvalue::Cast(cast_kind, source, expr.ty)) }, + ExprKind::Tuple { fields } => Ok( + Rvalue::Aggregate( + Box::new(AggregateKind::Tuple), + fields.iter().map(|e| self.parse_operand(*e)).collect::>()? + ) + ), + ExprKind::Array { fields } => { + let elem_ty = match expr.ty.kind() { + ty::Array(ty, ..) => ty, + _ => unreachable!("ty is array"), + }; + Ok(Rvalue::Aggregate( + Box::new(AggregateKind::Array(*elem_ty)), + fields.iter().map(|e| self.parse_operand(*e)).collect::>()? + )) + }, + ExprKind::Adt(box AdtExpr{ adt_def, variant_index, substs, fields, .. }) => { + let is_union = adt_def.is_union(); + let active_field_index = is_union.then(|| fields[0].name.index()); + + Ok(Rvalue::Aggregate( + Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, substs, None, active_field_index)), + fields.iter().map(|f| self.parse_operand(f.expr)).collect::>()? + )) + }, _ => self.parse_operand(expr_id).map(Rvalue::Use), ) } diff --git a/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir b/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir new file mode 100644 index 0000000000000..49e8c812c197a --- /dev/null +++ b/tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir @@ -0,0 +1,16 @@ +// MIR for `adt` after built + +fn adt() -> Onion { + let mut _0: Onion; // return place in scope 0 at $DIR/aggregate_exprs.rs:+0:13: +0:18 + let mut _1: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _2: Foo; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _3: Bar; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _1 = const 1_i32; // scope 0 at $DIR/aggregate_exprs.rs:+6:13: +6:20 + _2 = Foo { a: const 1_i32, b: const 2_i32 }; // scope 0 at $DIR/aggregate_exprs.rs:+7:13: +10:14 + _3 = Bar::Foo(move _2, _1); // scope 0 at $DIR/aggregate_exprs.rs:+11:13: +11:39 + _0 = Onion { neon: ((_3 as variant#0).1: i32) }; // scope 0 at $DIR/aggregate_exprs.rs:+12:13: +12:58 + return; // scope 0 at $DIR/aggregate_exprs.rs:+13:13: +13:21 + } +} diff --git a/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir b/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir new file mode 100644 index 0000000000000..30d12897331ce --- /dev/null +++ b/tests/mir-opt/building/custom/aggregate_exprs.array.built.after.mir @@ -0,0 +1,15 @@ +// MIR for `array` after built + +fn array() -> [i32; 2] { + let mut _0: [i32; 2]; // return place in scope 0 at $DIR/aggregate_exprs.rs:+0:15: +0:23 + let mut _1: [i32; 2]; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL + + bb0: { + _1 = [const 42_i32, const 43_i32]; // scope 0 at $DIR/aggregate_exprs.rs:+5:13: +5:25 + _2 = const 1_i32; // scope 0 at $DIR/aggregate_exprs.rs:+6:13: +6:20 + _1 = [_2, const 2_i32]; // scope 0 at $DIR/aggregate_exprs.rs:+7:13: +7:25 + _0 = move _1; // scope 0 at $DIR/aggregate_exprs.rs:+8:13: +8:26 + return; // scope 0 at $DIR/aggregate_exprs.rs:+9:13: +9:21 + } +} diff --git a/tests/mir-opt/building/custom/aggregate_exprs.rs b/tests/mir-opt/building/custom/aggregate_exprs.rs new file mode 100644 index 0000000000000..554c9c03ba4a0 --- /dev/null +++ b/tests/mir-opt/building/custom/aggregate_exprs.rs @@ -0,0 +1,71 @@ +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR aggregate_exprs.tuple.built.after.mir +#[custom_mir(dialect = "built")] +fn tuple() -> (i32, bool) { + mir!( + { + RET = (1, true); + Return() + } + ) +} + +// EMIT_MIR aggregate_exprs.array.built.after.mir +#[custom_mir(dialect = "built")] +fn array() -> [i32; 2] { + mir!( + let x: [i32; 2]; + let one: i32; + { + x = [42, 43]; + one = 1; + x = [one, 2]; + RET = Move(x); + Return() + } + ) +} + +struct Foo { + a: i32, + b: i32, +} + +enum Bar { + Foo(Foo, i32), +} + +union Onion { + neon: i32, + noun: f32, +} + +// EMIT_MIR aggregate_exprs.adt.built.after.mir +#[custom_mir(dialect = "built")] +fn adt() -> Onion { + mir!( + let one: i32; + let x: Foo; + let y: Bar; + { + one = 1; + x = Foo { + a: 1, + b: 2, + }; + y = Bar::Foo(Move(x), one); + RET = Onion { neon: Field(Variant(y, 0), 1) }; + Return() + } + ) +} + +fn main() { + assert_eq!(tuple(), (1, true)); + assert_eq!(array(), [1, 2]); + assert_eq!(unsafe { adt().neon }, 1); +} diff --git a/tests/mir-opt/building/custom/aggregate_exprs.tuple.built.after.mir b/tests/mir-opt/building/custom/aggregate_exprs.tuple.built.after.mir new file mode 100644 index 0000000000000..5fe45ccc90ca6 --- /dev/null +++ b/tests/mir-opt/building/custom/aggregate_exprs.tuple.built.after.mir @@ -0,0 +1,10 @@ +// MIR for `tuple` after built + +fn tuple() -> (i32, bool) { + let mut _0: (i32, bool); // return place in scope 0 at $DIR/aggregate_exprs.rs:+0:15: +0:26 + + bb0: { + _0 = (const 1_i32, const true); // scope 0 at $DIR/aggregate_exprs.rs:+3:13: +3:28 + return; // scope 0 at $DIR/aggregate_exprs.rs:+4:13: +4:21 + } +} From e24f5ac56b001d205618590b0519137abbc65580 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Mon, 20 Mar 2023 15:27:40 +0100 Subject: [PATCH 2/3] Fix off-by-one in mir syntax doc --- compiler/rustc_middle/src/mir/syntax.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b16b6616415aa..a702a6b9ee1b6 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1165,7 +1165,7 @@ pub enum AggregateKind<'tcx> { Tuple, /// The second field is the variant index. It's equal to 0 for struct - /// and union expressions. The fourth field is + /// and union expressions. The last field is the /// active field number and is present only for union expressions /// -- e.g., for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` From f404f33c2197c534cf2468ea7b929e73c9b5d4b7 Mon Sep 17 00:00:00 2001 From: Andy Wang Date: Mon, 20 Mar 2023 16:21:43 +0100 Subject: [PATCH 3/3] Use builtin_index instead of match Co-authored-by: Oli Scherer --- .../rustc_mir_build/src/build/custom/parse/instruction.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index e60e1a4c81507..adbd37a7cd950 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -173,12 +173,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) ), ExprKind::Array { fields } => { - let elem_ty = match expr.ty.kind() { - ty::Array(ty, ..) => ty, - _ => unreachable!("ty is array"), - }; + let elem_ty = expr.ty.builtin_index().expect("ty must be an array"); Ok(Rvalue::Aggregate( - Box::new(AggregateKind::Array(*elem_ty)), + Box::new(AggregateKind::Array(elem_ty)), fields.iter().map(|e| self.parse_operand(*e)).collect::>()? )) },