Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom MIR: Support aggregate expressions #109390

Merged
merged 3 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Result<_, _>>()?
)
),
ExprKind::Array { fields } => {
let elem_ty = match expr.ty.kind() {
ty::Array(ty, ..) => ty,
_ => unreachable!("ty is array"),
};
cbeuw marked this conversation as resolved.
Show resolved Hide resolved
Ok(Rvalue::Aggregate(
Box::new(AggregateKind::Array(*elem_ty)),
fields.iter().map(|e| self.parse_operand(*e)).collect::<Result<_, _>>()?
))
},
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::<Result<_, _>>()?
))
},
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}
Expand Down
16 changes: 16 additions & 0 deletions tests/mir-opt/building/custom/aggregate_exprs.adt.built.after.mir
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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
}
}
71 changes: 71 additions & 0 deletions tests/mir-opt/building/custom/aggregate_exprs.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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
}
}