Skip to content

Commit 74a4261

Browse files
authored
92 extract type layouts (#94)
Includes layout information for all type metadata (except primitive and function types). The original Stable MIR data structures are dumped, probably containing some redundancy. Fixes #92
1 parent 18f452d commit 74a4261

31 files changed

+17632
-445
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ jobs:
6262
run: | # Warning check should be redundant since code-quality runs first
6363
RUSTFLAGS='--deny warnings' cargo build -vv
6464
65+
- name: 'Install a good-enough jq version'
66+
uses: dcarbone/install-jq-action@v3
67+
with:
68+
version: 1.7.1
69+
force: true
70+
6571
- name: 'Run smir integration tests'
6672
run: |
6773
which jq

src/printer.rs

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use rustc_span::{
3232
};
3333
use serde::{Serialize, Serializer};
3434
use stable_mir::{
35+
abi::LayoutShape,
3536
mir::mono::{Instance, InstanceKind, MonoItem},
3637
mir::{alloc::AllocId, visit::MirVisitor, Body, LocalDecl, Rvalue, Terminator, TerminatorKind},
3738
ty::{AdtDef, Allocation, ConstDef, ForeignItemKind, IndexedVal, RigidTy, TyKind},
@@ -566,19 +567,14 @@ impl Visitor for TyCollector<'_> {
566567
.map(rustc_internal::stable)
567568
.collect();
568569

569-
let mut control = ty.super_visit(self);
570+
let control = ty.super_visit(self);
570571
if matches!(control, ControlFlow::Continue(_)) {
571572
let maybe_layout_shape = ty.layout().ok().map(|layout| layout.shape());
572573
self.types.insert(*ty, (ty.kind(), maybe_layout_shape));
574+
fields.super_visit(self)
575+
} else {
576+
control
573577
}
574-
575-
for f_ty in fields {
576-
control = self.visit_ty(&f_ty);
577-
if matches!(control, ControlFlow::Break(())) {
578-
break;
579-
}
580-
}
581-
control
582578
}
583579
_ => {
584580
let control = ty.super_visit(self);
@@ -1005,21 +1001,35 @@ pub enum TypeMetadata {
10051001
adt_def: AdtDef,
10061002
discriminants: Vec<u128>,
10071003
fields: Vec<Vec<stable_mir::ty::Ty>>,
1004+
layout: Option<LayoutShape>,
10081005
},
10091006
StructType {
10101007
name: String,
10111008
adt_def: AdtDef,
10121009
fields: Vec<stable_mir::ty::Ty>,
1010+
layout: Option<LayoutShape>,
10131011
},
10141012
UnionType {
10151013
name: String,
10161014
adt_def: AdtDef,
1015+
layout: Option<LayoutShape>,
1016+
},
1017+
ArrayType {
1018+
elem_type: stable_mir::ty::Ty,
1019+
size: Option<stable_mir::ty::TyConst>,
1020+
layout: Option<LayoutShape>,
1021+
},
1022+
PtrType {
1023+
pointee_type: stable_mir::ty::Ty,
1024+
layout: Option<LayoutShape>,
1025+
},
1026+
RefType {
1027+
pointee_type: stable_mir::ty::Ty,
1028+
layout: Option<LayoutShape>,
10171029
},
1018-
ArrayType(stable_mir::ty::Ty, Option<stable_mir::ty::TyConst>),
1019-
PtrType(stable_mir::ty::Ty),
1020-
RefType(stable_mir::ty::Ty),
10211030
TupleType {
10221031
types: Vec<stable_mir::ty::Ty>,
1032+
layout: Option<LayoutShape>,
10231033
},
10241034
FunType(String),
10251035
VoidType,
@@ -1029,10 +1039,12 @@ fn mk_type_metadata(
10291039
tcx: TyCtxt<'_>,
10301040
k: stable_mir::ty::Ty,
10311041
t: TyKind,
1042+
layout: Option<LayoutShape>,
10321043
) -> Option<(stable_mir::ty::Ty, TypeMetadata)> {
10331044
use stable_mir::ty::RigidTy::*;
10341045
use TyKind::RigidTy as T;
10351046
use TypeMetadata::*;
1047+
let name = format!("{k}"); // prints name with type parameters
10361048
match t {
10371049
T(prim_type) if t.is_primitive() => Some((k, PrimitiveType(prim_type))),
10381050
// for enums, we need a mapping of variantIdx to discriminant
@@ -1054,20 +1066,18 @@ fn mk_type_metadata(
10541066
.collect::<Vec<stable_mir::ty::Ty>>()
10551067
})
10561068
.collect();
1057-
let name = adt_def.name();
10581069
Some((
10591070
k,
10601071
EnumType {
10611072
name,
10621073
adt_def,
10631074
discriminants,
10641075
fields,
1076+
layout,
10651077
},
10661078
))
10671079
}
1068-
// for structs, we record the name for information purposes and the field types
10691080
T(Adt(adt_def, args)) if t.is_struct() => {
1070-
let name = adt_def.name();
10711081
let fields = rustc_internal::internal(tcx, adt_def)
10721082
.all_fields() // is_struct, so only one variant
10731083
.map(move |f| f.ty(tcx, rustc_internal::internal(tcx, &args)))
@@ -1079,26 +1089,56 @@ fn mk_type_metadata(
10791089
name,
10801090
adt_def,
10811091
fields,
1092+
layout,
10821093
},
10831094
))
10841095
}
1085-
// for unions, we only record the name
1086-
T(Adt(adt_def, _)) if t.is_union() => {
1087-
let name = adt_def.name();
1088-
Some((k, UnionType { name, adt_def }))
1089-
}
1096+
T(Adt(adt_def, _)) if t.is_union() => Some((
1097+
k,
1098+
UnionType {
1099+
name,
1100+
adt_def,
1101+
layout,
1102+
},
1103+
)),
10901104
// encode str together with primitive types
10911105
T(Str) => Some((k, PrimitiveType(Str))),
10921106
// for arrays and slices, record element type and optional size
1093-
T(Array(ty, ty_const)) => Some((k, ArrayType(ty, Some(ty_const)))),
1094-
T(Slice(ty)) => Some((k, ArrayType(ty, None))),
1107+
T(Array(elem_type, ty_const)) => Some((
1108+
k,
1109+
ArrayType {
1110+
elem_type,
1111+
size: Some(ty_const),
1112+
layout,
1113+
},
1114+
)),
1115+
T(Slice(elem_type)) => Some((
1116+
k,
1117+
ArrayType {
1118+
elem_type,
1119+
size: None,
1120+
layout,
1121+
},
1122+
)),
10951123
// for raw pointers and references store the pointee type
1096-
T(RawPtr(ty, _)) => Some((k, PtrType(ty))),
1097-
T(Ref(_, ty, _)) => Some((k, RefType(ty))),
1124+
T(RawPtr(pointee_type, _)) => Some((
1125+
k,
1126+
PtrType {
1127+
pointee_type,
1128+
layout,
1129+
},
1130+
)),
1131+
T(Ref(_, pointee_type, _)) => Some((
1132+
k,
1133+
RefType {
1134+
pointee_type,
1135+
layout,
1136+
},
1137+
)),
10981138
// for tuples the element types are provided
1099-
T(Tuple(tys)) => Some((k, TupleType { types: tys })),
1139+
T(Tuple(types)) => Some((k, TupleType { types, layout })),
11001140
// opaque function types (fun ptrs, closures, FnDef) are only provided to avoid dangling ty references
1101-
T(FnDef(_, _)) | T(FnPtr(_)) | T(Closure(_, _)) => Some((k, FunType(format!("{}", k)))),
1141+
T(FnDef(_, _)) | T(FnPtr(_)) | T(Closure(_, _)) => Some((k, FunType(name))),
11021142
// other types are not provided either
11031143
T(Foreign(_))
11041144
| T(Pat(_, _))
@@ -1203,8 +1243,7 @@ pub fn collect_smir(tcx: TyCtxt<'_>) -> SmirJson {
12031243

12041244
let mut types = visited_tys
12051245
.into_iter()
1206-
.map(|(k, (v, _))| (k, v))
1207-
.filter_map(|(k, t)| mk_type_metadata(tcx, k, t))
1246+
.filter_map(|(k, (t, l))| mk_type_metadata(tcx, k, t, l))
12081247
// .filter(|(_, v)| v.is_primitive())
12091248
.collect::<Vec<_>>();
12101249

tests/integration/normalise-filter.jq

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@
1616
# sort by constructors and remove unstable IDs within each
1717
( .types | map(select(.[0].PrimitiveType)) | sort ),
1818
# delete unstable adt_ref IDs and struct field Ty IDs
19-
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def) | .[0].EnumType.fields = "elided") | sort ),
20-
( .types | map(select(.[0].StructType) | del(.[0].StructType.adt_def) | .[0].StructType.fields = "elided" ) | sort ),
21-
( .types | map(select(.[0].UnionType) | del(.[0].UnionType.adt_def)) | sort ),
19+
( .types | map(select(.[0].EnumType) | del(.[0].EnumType.adt_def) | .[0].EnumType.fields = "elided") | sort_by(.[0].EnumType.name) ),
20+
( .types | map(select(.[0].StructType) | del(.[0].StructType.adt_def) | .[0].StructType.fields = "elided" ) | sort_by(.[0].StructType.name) ),
21+
( .types | map(select(.[0].UnionType) | del(.[0].UnionType.adt_def)) | sort_by(.[0].UnionType.name) ),
2222
# delete unstable Ty IDs for arrays and tuples
23-
( .types | map(select(.[0].ArrayType) | del(.[0].ArrayType[0]) | del(.[0].ArrayType[0].id)) | sort ),
23+
( .types | map(select(.[0].ArrayType) | del(.[0].ArrayType.elem_type) | del(.[0].ArrayType.size.id)) | sort ),
2424
( .types | map(select(.[0].TupleType) | .[0].TupleType.types = "elided") ),
2525
# replace unstable Ty IDs for references by zero
26-
( .types | map(select(.[0].PtrType) | .[0].PtrType = "elided") ),
27-
( .types | map(select(.[0].RefType) | .[0].RefType = "elided") ),
26+
( .types | map(select(.[0].PtrType) | .[0].PtrType.pointee_type = "elided") | sort ),
27+
( .types | map(select(.[0].RefType) | .[0].RefType.pointee_type = "elided") | sort ),
2828
# keep function type strings
29-
( .types | map(select(.[0].FunType) | .[0].FunType = "elided") )
29+
( .types | map(select(.[0].FunType) | sort) )
3030
] | flatten(1) )
3131
}

0 commit comments

Comments
 (0)